TelecomSystem.java revision fc9c8ffcac8fb7c6796d0fe74152bb1fb14d74d9
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.bluetooth.BluetoothDeviceManager;
21import com.android.server.telecom.bluetooth.BluetoothRouteManager;
22import com.android.server.telecom.components.UserCallIntentProcessor;
23import com.android.server.telecom.components.UserCallIntentProcessorFactory;
24import com.android.server.telecom.ui.IncomingCallNotifier;
25import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
26import com.android.server.telecom.BluetoothPhoneServiceImpl.BluetoothPhoneServiceImplFactory;
27import com.android.server.telecom.CallAudioManager.AudioServiceFactory;
28import com.android.server.telecom.DefaultDialerCache.DefaultDialerManagerAdapter;
29
30import android.Manifest;
31import android.content.BroadcastReceiver;
32import android.content.Context;
33import android.content.Intent;
34import android.content.IntentFilter;
35import android.content.pm.ApplicationInfo;
36import android.content.pm.PackageManager;
37import android.net.Uri;
38import android.os.UserHandle;
39import android.telecom.Log;
40import android.telecom.PhoneAccountHandle;
41
42import java.io.FileNotFoundException;
43import java.io.InputStream;
44
45/**
46 * Top-level Application class for Telecom.
47 */
48public class TelecomSystem {
49
50    /**
51     * This interface is implemented by system-instantiated components (e.g., Services and
52     * Activity-s) that wish to use the TelecomSystem but would like to be testable. Such a
53     * component should implement the getTelecomSystem() method to return the global singleton,
54     * and use its own method. Tests can subclass the component to return a non-singleton.
55     *
56     * A refactoring goal for Telecom is to limit use of the TelecomSystem singleton to those
57     * system-instantiated components, and have all other parts of the system just take all their
58     * dependencies as explicit arguments to their constructor or other methods.
59     */
60    public interface Component {
61        TelecomSystem getTelecomSystem();
62    }
63
64
65    /**
66     * Tagging interface for the object used for synchronizing multi-threaded operations in
67     * the Telecom system.
68     */
69    public interface SyncRoot {
70    }
71
72    private static final IntentFilter USER_SWITCHED_FILTER =
73            new IntentFilter(Intent.ACTION_USER_SWITCHED);
74
75    private static final IntentFilter USER_STARTING_FILTER =
76            new IntentFilter(Intent.ACTION_USER_STARTING);
77
78    private static final IntentFilter BOOT_COMPLETE_FILTER =
79            new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
80
81    /** Intent filter for dialer secret codes. */
82    private static final IntentFilter DIALER_SECRET_CODE_FILTER;
83
84    /**
85     * Initializes the dialer secret code intent filter.  Setup to handle the various secret codes
86     * which can be dialed (e.g. in format *#*#code#*#*) to trigger various behavior in Telecom.
87     */
88    static {
89        DIALER_SECRET_CODE_FILTER = new IntentFilter(
90                "android.provider.Telephony.SECRET_CODE");
91        DIALER_SECRET_CODE_FILTER.addDataScheme("android_secret_code");
92        DIALER_SECRET_CODE_FILTER
93                .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_DEBUG_ON, null);
94        DIALER_SECRET_CODE_FILTER
95                .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_DEBUG_OFF, null);
96        DIALER_SECRET_CODE_FILTER
97                .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_MARK, null);
98    }
99
100    private static TelecomSystem INSTANCE = null;
101
102    private final SyncRoot mLock = new SyncRoot() { };
103    private final MissedCallNotifier mMissedCallNotifier;
104    private final IncomingCallNotifier mIncomingCallNotifier;
105    private final PhoneAccountRegistrar mPhoneAccountRegistrar;
106    private final CallsManager mCallsManager;
107    private final RespondViaSmsManager mRespondViaSmsManager;
108    private final Context mContext;
109    private final BluetoothPhoneServiceImpl mBluetoothPhoneServiceImpl;
110    private final CallIntentProcessor mCallIntentProcessor;
111    private final TelecomBroadcastIntentProcessor mTelecomBroadcastIntentProcessor;
112    private final TelecomServiceImpl mTelecomServiceImpl;
113    private final ContactsAsyncHelper mContactsAsyncHelper;
114    private final DialerCodeReceiver mDialerCodeReceiver;
115
116    private boolean mIsBootComplete = false;
117
118    private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
119        @Override
120        public void onReceive(Context context, Intent intent) {
121            Log.startSession("TSSwR.oR");
122            try {
123                synchronized (mLock) {
124                    int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
125                    UserHandle currentUserHandle = new UserHandle(userHandleId);
126                    mPhoneAccountRegistrar.setCurrentUserHandle(currentUserHandle);
127                    mCallsManager.onUserSwitch(currentUserHandle);
128                }
129            } finally {
130                Log.endSession();
131            }
132        }
133    };
134
135    private final BroadcastReceiver mUserStartingReceiver = new BroadcastReceiver() {
136        @Override
137        public void onReceive(Context context, Intent intent) {
138            Log.startSession("TSStR.oR");
139            try {
140                synchronized (mLock) {
141                    int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
142                    UserHandle addingUserHandle = new UserHandle(userHandleId);
143                    mCallsManager.onUserStarting(addingUserHandle);
144                }
145            } finally {
146                Log.endSession();
147            }
148        }
149    };
150
151    private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
152        @Override
153        public void onReceive(Context context, Intent intent) {
154            Log.startSession("TSBCR.oR");
155            try {
156                synchronized (mLock) {
157                    mIsBootComplete = true;
158                    mCallsManager.onBootCompleted();
159                }
160            } finally {
161                Log.endSession();
162            }
163        }
164    };
165
166    public static TelecomSystem getInstance() {
167        return INSTANCE;
168    }
169
170    public static void setInstance(TelecomSystem instance) {
171        if (INSTANCE != null) {
172            Log.w("TelecomSystem", "Attempt to set TelecomSystem.INSTANCE twice");
173        }
174        Log.i(TelecomSystem.class, "TelecomSystem.INSTANCE being set");
175        INSTANCE = instance;
176    }
177
178    public TelecomSystem(
179            Context context,
180            MissedCallNotifierImplFactory missedCallNotifierImplFactory,
181            CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory,
182            HeadsetMediaButtonFactory headsetMediaButtonFactory,
183            ProximitySensorManagerFactory proximitySensorManagerFactory,
184            InCallWakeLockControllerFactory inCallWakeLockControllerFactory,
185            AudioServiceFactory audioServiceFactory,
186            BluetoothPhoneServiceImplFactory
187                    bluetoothPhoneServiceImplFactory,
188            Timeouts.Adapter timeoutsAdapter,
189            AsyncRingtonePlayer asyncRingtonePlayer,
190            PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
191            IncomingCallNotifier incomingCallNotifier,
192            InCallTonePlayer.ToneGeneratorFactory toneGeneratorFactory,
193            ClockProxy clockProxy) {
194        mContext = context.getApplicationContext();
195        LogUtils.initLogging(mContext);
196        DefaultDialerManagerAdapter defaultDialerAdapter =
197                new DefaultDialerCache.DefaultDialerManagerAdapterImpl();
198
199        DefaultDialerCache defaultDialerCache = new DefaultDialerCache(mContext,
200                defaultDialerAdapter, mLock);
201
202        Log.startSession("TS.init");
203        mPhoneAccountRegistrar = new PhoneAccountRegistrar(mContext, defaultDialerCache,
204                new PhoneAccountRegistrar.AppLabelProxy() {
205                    @Override
206                    public CharSequence getAppLabel(String packageName) {
207                        PackageManager pm = mContext.getPackageManager();
208                        try {
209                            ApplicationInfo info = pm.getApplicationInfo(packageName, 0);
210                            return pm.getApplicationLabel(info);
211                        } catch (PackageManager.NameNotFoundException nnfe) {
212                            Log.w(this, "Could not determine package name.");
213                        }
214
215                        return null;
216                    }
217                });
218        mContactsAsyncHelper = new ContactsAsyncHelper(
219                new ContactsAsyncHelper.ContentResolverAdapter() {
220                    @Override
221                    public InputStream openInputStream(Context context, Uri uri)
222                            throws FileNotFoundException {
223                        return context.getContentResolver().openInputStream(uri);
224                    }
225                });
226        BluetoothDeviceManager bluetoothDeviceManager = new BluetoothDeviceManager(mContext,
227                new BluetoothAdapterProxy(), mLock);
228        BluetoothRouteManager bluetoothRouteManager = new BluetoothRouteManager(mContext, mLock,
229                bluetoothDeviceManager, new Timeouts.Adapter());
230        WiredHeadsetManager wiredHeadsetManager = new WiredHeadsetManager(mContext);
231        SystemStateProvider systemStateProvider = new SystemStateProvider(mContext);
232
233        mMissedCallNotifier = missedCallNotifierImplFactory
234                .makeMissedCallNotifierImpl(mContext, mPhoneAccountRegistrar, defaultDialerCache);
235
236        EmergencyCallHelper emergencyCallHelper = new EmergencyCallHelper(mContext,
237                mContext.getResources().getString(R.string.ui_default_package), timeoutsAdapter);
238
239        InCallControllerFactory inCallControllerFactory = new InCallControllerFactory() {
240            @Override
241            public InCallController create(Context context, SyncRoot lock,
242                    CallsManager callsManager, SystemStateProvider systemStateProvider,
243                    DefaultDialerCache defaultDialerCache, Timeouts.Adapter timeoutsAdapter,
244                    EmergencyCallHelper emergencyCallHelper) {
245                return new InCallController(context, lock, callsManager, systemStateProvider,
246                        defaultDialerCache, timeoutsAdapter, emergencyCallHelper);
247            }
248        };
249
250        mCallsManager = new CallsManager(
251                mContext,
252                mLock,
253                mContactsAsyncHelper,
254                callerInfoAsyncQueryFactory,
255                mMissedCallNotifier,
256                mPhoneAccountRegistrar,
257                headsetMediaButtonFactory,
258                proximitySensorManagerFactory,
259                inCallWakeLockControllerFactory,
260                audioServiceFactory,
261                bluetoothRouteManager,
262                wiredHeadsetManager,
263                systemStateProvider,
264                defaultDialerCache,
265                timeoutsAdapter,
266                asyncRingtonePlayer,
267                phoneNumberUtilsAdapter,
268                emergencyCallHelper,
269                toneGeneratorFactory,
270                clockProxy,
271                inCallControllerFactory);
272
273        mIncomingCallNotifier = incomingCallNotifier;
274        incomingCallNotifier.setCallsManagerProxy(new IncomingCallNotifier.CallsManagerProxy() {
275            @Override
276            public boolean hasCallsForOtherPhoneAccount(PhoneAccountHandle phoneAccountHandle) {
277                return mCallsManager.hasCallsForOtherPhoneAccount(phoneAccountHandle);
278            }
279
280            @Override
281            public int getNumCallsForOtherPhoneAccount(PhoneAccountHandle phoneAccountHandle) {
282                return mCallsManager.getNumCallsForOtherPhoneAccount(phoneAccountHandle);
283            }
284
285            @Override
286            public Call getActiveCall() {
287                return mCallsManager.getActiveCall();
288            }
289        });
290        mCallsManager.setIncomingCallNotifier(mIncomingCallNotifier);
291
292        mRespondViaSmsManager = new RespondViaSmsManager(mCallsManager, mLock);
293        mCallsManager.setRespondViaSmsManager(mRespondViaSmsManager);
294
295        mContext.registerReceiver(mUserSwitchedReceiver, USER_SWITCHED_FILTER);
296        mContext.registerReceiver(mUserStartingReceiver, USER_STARTING_FILTER);
297        mContext.registerReceiver(mBootCompletedReceiver, BOOT_COMPLETE_FILTER);
298
299        mBluetoothPhoneServiceImpl = bluetoothPhoneServiceImplFactory.makeBluetoothPhoneServiceImpl(
300                mContext, mLock, mCallsManager, mPhoneAccountRegistrar);
301        mCallIntentProcessor = new CallIntentProcessor(mContext, mCallsManager);
302        mTelecomBroadcastIntentProcessor = new TelecomBroadcastIntentProcessor(
303                mContext, mCallsManager);
304
305        // Register the receiver for the dialer secret codes, used to enable extended logging.
306        mDialerCodeReceiver = new DialerCodeReceiver(mCallsManager);
307        mContext.registerReceiver(mDialerCodeReceiver, DIALER_SECRET_CODE_FILTER,
308                Manifest.permission.CONTROL_INCALL_EXPERIENCE, null);
309
310        mTelecomServiceImpl = new TelecomServiceImpl(
311                mContext, mCallsManager, mPhoneAccountRegistrar,
312                new CallIntentProcessor.AdapterImpl(),
313                new UserCallIntentProcessorFactory() {
314                    @Override
315                    public UserCallIntentProcessor create(Context context, UserHandle userHandle) {
316                        return new UserCallIntentProcessor(context, userHandle);
317                    }
318                },
319                defaultDialerCache,
320                new TelecomServiceImpl.SubscriptionManagerAdapterImpl(),
321                mLock);
322        Log.endSession();
323    }
324
325    @VisibleForTesting
326    public PhoneAccountRegistrar getPhoneAccountRegistrar() {
327        return mPhoneAccountRegistrar;
328    }
329
330    @VisibleForTesting
331    public CallsManager getCallsManager() {
332        return mCallsManager;
333    }
334
335    public BluetoothPhoneServiceImpl getBluetoothPhoneServiceImpl() {
336        return mBluetoothPhoneServiceImpl;
337    }
338
339    public CallIntentProcessor getCallIntentProcessor() {
340        return mCallIntentProcessor;
341    }
342
343    public TelecomBroadcastIntentProcessor getTelecomBroadcastIntentProcessor() {
344        return mTelecomBroadcastIntentProcessor;
345    }
346
347    public TelecomServiceImpl getTelecomServiceImpl() {
348        return mTelecomServiceImpl;
349    }
350
351    public Object getLock() {
352        return mLock;
353    }
354
355    public boolean isBootComplete() {
356        return mIsBootComplete;
357    }
358}
359