TelecomSystem.java revision eaaf074d6b8b0b16fb922d8d511d6e8b979bfe0d
1/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.telecom;
18
19import com.android.internal.annotations.VisibleForTesting;
20import com.android.server.telecom.components.UserCallIntentProcessor;
21import com.android.server.telecom.components.UserCallIntentProcessorFactory;
22import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
23import com.android.server.telecom.BluetoothPhoneServiceImpl.BluetoothPhoneServiceImplFactory;
24import com.android.server.telecom.CallAudioManager.AudioServiceFactory;
25import com.android.server.telecom.TelecomServiceImpl.DefaultDialerManagerAdapter;
26
27import android.Manifest;
28import android.content.BroadcastReceiver;
29import android.content.Context;
30import android.content.Intent;
31import android.content.IntentFilter;
32import android.net.Uri;
33import android.os.UserHandle;
34
35import java.io.FileNotFoundException;
36import java.io.InputStream;
37
38/**
39 * Top-level Application class for Telecom.
40 */
41public final class TelecomSystem {
42
43    /**
44     * This interface is implemented by system-instantiated components (e.g., Services and
45     * Activity-s) that wish to use the TelecomSystem but would like to be testable. Such a
46     * component should implement the getTelecomSystem() method to return the global singleton,
47     * and use its own method. Tests can subclass the component to return a non-singleton.
48     *
49     * A refactoring goal for Telecom is to limit use of the TelecomSystem singleton to those
50     * system-instantiated components, and have all other parts of the system just take all their
51     * dependencies as explicit arguments to their constructor or other methods.
52     */
53    public interface Component {
54        TelecomSystem getTelecomSystem();
55    }
56
57
58    /**
59     * Tagging interface for the object used for synchronizing multi-threaded operations in
60     * the Telecom system.
61     */
62    public interface SyncRoot {
63    }
64
65    private static final IntentFilter USER_SWITCHED_FILTER =
66            new IntentFilter(Intent.ACTION_USER_SWITCHED);
67
68    private static final IntentFilter USER_STARTING_FILTER =
69            new IntentFilter(Intent.ACTION_USER_STARTING);
70
71    /** Intent filter for dialer secret codes. */
72    private static final IntentFilter DIALER_SECRET_CODE_FILTER;
73
74    /**
75     * Initializes the dialer secret code intent filter.  Setup to handle the various secret codes
76     * which can be dialed (e.g. in format *#*#code#*#*) to trigger various behavior in Telecom.
77     */
78    static {
79        DIALER_SECRET_CODE_FILTER = new IntentFilter(
80                "android.provider.Telephony.SECRET_CODE");
81        DIALER_SECRET_CODE_FILTER.addDataScheme("android_secret_code");
82        DIALER_SECRET_CODE_FILTER
83                .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_DEBUG_ON, null);
84        DIALER_SECRET_CODE_FILTER
85                .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_DEBUG_OFF, null);
86        DIALER_SECRET_CODE_FILTER
87                .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_MARK, null);
88    }
89
90    private static TelecomSystem INSTANCE = null;
91
92    private final SyncRoot mLock = new SyncRoot() { };
93    private final MissedCallNotifier mMissedCallNotifier;
94    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
95    private final CallsManager mCallsManager;
96    private final RespondViaSmsManager mRespondViaSmsManager;
97    private final Context mContext;
98    private final BluetoothPhoneServiceImpl mBluetoothPhoneServiceImpl;
99    private final CallIntentProcessor mCallIntentProcessor;
100    private final TelecomBroadcastIntentProcessor mTelecomBroadcastIntentProcessor;
101    private final TelecomServiceImpl mTelecomServiceImpl;
102    private final ContactsAsyncHelper mContactsAsyncHelper;
103    private final DialerCodeReceiver mDialerCodeReceiver;
104
105    private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
106        @Override
107        public void onReceive(Context context, Intent intent) {
108            Log.startSession("TSSwR.oR");
109            try {
110                int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
111                UserHandle currentUserHandle = new UserHandle(userHandleId);
112                mPhoneAccountRegistrar.setCurrentUserHandle(currentUserHandle);
113                mCallsManager.onUserSwitch(currentUserHandle);
114            } finally {
115                Log.endSession();
116            }
117        }
118    };
119
120    private final BroadcastReceiver mUserStartingReceiver = new BroadcastReceiver() {
121        @Override
122        public void onReceive(Context context, Intent intent) {
123            Log.startSession("TSStR.oR");
124            try {
125                int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
126                UserHandle addingUserHandle = new UserHandle(userHandleId);
127                mCallsManager.onUserStarting(addingUserHandle);
128            } finally {
129                Log.endSession();
130            }
131        }
132    };
133
134    public static TelecomSystem getInstance() {
135        return INSTANCE;
136    }
137
138    public static void setInstance(TelecomSystem instance) {
139        if (INSTANCE != null) {
140            throw new RuntimeException("Attempt to set TelecomSystem.INSTANCE twice");
141        }
142        Log.i(TelecomSystem.class, "TelecomSystem.INSTANCE being set");
143        INSTANCE = instance;
144    }
145
146    public TelecomSystem(
147            Context context,
148            MissedCallNotifierImplFactory missedCallNotifierImplFactory,
149            CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory,
150            HeadsetMediaButtonFactory headsetMediaButtonFactory,
151            ProximitySensorManagerFactory proximitySensorManagerFactory,
152            InCallWakeLockControllerFactory inCallWakeLockControllerFactory,
153            AudioServiceFactory audioServiceFactory,
154            BluetoothPhoneServiceImplFactory
155                    bluetoothPhoneServiceImplFactory,
156            Timeouts.Adapter timeoutsAdapter,
157            AsyncRingtonePlayer asyncRingtonePlayer,
158            PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
159            InterruptionFilterProxy interruptionFilterProxy) {
160        mContext = context.getApplicationContext();
161        Log.setContext(mContext);
162        Log.initMd5Sum();
163
164        Log.startSession("TS.init");
165        mPhoneAccountRegistrar = new PhoneAccountRegistrar(mContext);
166        mContactsAsyncHelper = new ContactsAsyncHelper(
167                new ContactsAsyncHelper.ContentResolverAdapter() {
168                    @Override
169                    public InputStream openInputStream(Context context, Uri uri)
170                            throws FileNotFoundException {
171                        return context.getContentResolver().openInputStream(uri);
172                    }
173                });
174        BluetoothManager bluetoothManager = new BluetoothManager(mContext,
175                new BluetoothAdapterProxy());
176        WiredHeadsetManager wiredHeadsetManager = new WiredHeadsetManager(mContext);
177        SystemStateProvider systemStateProvider = new SystemStateProvider(mContext);
178
179        mMissedCallNotifier = missedCallNotifierImplFactory
180                .makeMissedCallNotifierImpl(mContext, mPhoneAccountRegistrar,
181                        phoneNumberUtilsAdapter);
182
183        DefaultDialerManagerAdapter defaultDialerAdapter =
184                new TelecomServiceImpl.DefaultDialerManagerAdapterImpl();
185
186        mCallsManager = new CallsManager(
187                mContext,
188                mLock,
189                mContactsAsyncHelper,
190                callerInfoAsyncQueryFactory,
191                mMissedCallNotifier,
192                mPhoneAccountRegistrar,
193                headsetMediaButtonFactory,
194                proximitySensorManagerFactory,
195                inCallWakeLockControllerFactory,
196                audioServiceFactory,
197                bluetoothManager,
198                wiredHeadsetManager,
199                systemStateProvider,
200                defaultDialerAdapter,
201                timeoutsAdapter,
202                asyncRingtonePlayer,
203                phoneNumberUtilsAdapter,
204                interruptionFilterProxy);
205
206        mRespondViaSmsManager = new RespondViaSmsManager(mCallsManager, mLock);
207        mCallsManager.setRespondViaSmsManager(mRespondViaSmsManager);
208
209        mContext.registerReceiver(mUserSwitchedReceiver, USER_SWITCHED_FILTER);
210        mContext.registerReceiver(mUserStartingReceiver, USER_STARTING_FILTER);
211
212        mBluetoothPhoneServiceImpl = bluetoothPhoneServiceImplFactory.makeBluetoothPhoneServiceImpl(
213                mContext, mLock, mCallsManager, mPhoneAccountRegistrar);
214        mCallIntentProcessor = new CallIntentProcessor(mContext, mCallsManager);
215        mTelecomBroadcastIntentProcessor = new TelecomBroadcastIntentProcessor(
216                mContext, mCallsManager);
217
218        // Register the receiver for the dialer secret codes, used to enable extended logging.
219        mDialerCodeReceiver = new DialerCodeReceiver(mCallsManager);
220        mContext.registerReceiver(mDialerCodeReceiver, DIALER_SECRET_CODE_FILTER,
221                Manifest.permission.CONTROL_INCALL_EXPERIENCE, null);
222
223        mTelecomServiceImpl = new TelecomServiceImpl(
224                mContext, mCallsManager, mPhoneAccountRegistrar,
225                new CallIntentProcessor.AdapterImpl(),
226                new UserCallIntentProcessorFactory() {
227                    @Override
228                    public UserCallIntentProcessor create(Context context, UserHandle userHandle) {
229                        return new UserCallIntentProcessor(context, userHandle);
230                    }
231                },
232                defaultDialerAdapter,
233                new TelecomServiceImpl.SubscriptionManagerAdapterImpl(),
234                mLock);
235        Log.endSession();
236    }
237
238    @VisibleForTesting
239    public PhoneAccountRegistrar getPhoneAccountRegistrar() {
240        return mPhoneAccountRegistrar;
241    }
242
243    @VisibleForTesting
244    public CallsManager getCallsManager() {
245        return mCallsManager;
246    }
247
248    public BluetoothPhoneServiceImpl getBluetoothPhoneServiceImpl() {
249        return mBluetoothPhoneServiceImpl;
250    }
251
252    public CallIntentProcessor getCallIntentProcessor() {
253        return mCallIntentProcessor;
254    }
255
256    public TelecomBroadcastIntentProcessor getTelecomBroadcastIntentProcessor() {
257        return mTelecomBroadcastIntentProcessor;
258    }
259
260    public TelecomServiceImpl getTelecomServiceImpl() {
261        return mTelecomServiceImpl;
262    }
263
264    public Object getLock() {
265        return mLock;
266    }
267}
268