• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 package com.android.server.telecom;
18 
19 import com.android.internal.annotations.VisibleForTesting;
20 import com.android.server.telecom.bluetooth.BluetoothDeviceManager;
21 import com.android.server.telecom.bluetooth.BluetoothRouteManager;
22 import com.android.server.telecom.bluetooth.BluetoothStateReceiver;
23 import com.android.server.telecom.components.UserCallIntentProcessor;
24 import com.android.server.telecom.components.UserCallIntentProcessorFactory;
25 import com.android.server.telecom.ui.AudioProcessingNotification;
26 import com.android.server.telecom.ui.DisconnectedCallNotifier;
27 import com.android.server.telecom.ui.IncomingCallNotifier;
28 import com.android.server.telecom.ui.MissedCallNotifierImpl.MissedCallNotifierImplFactory;
29 import com.android.server.telecom.CallAudioManager.AudioServiceFactory;
30 import com.android.server.telecom.DefaultDialerCache.DefaultDialerManagerAdapter;
31 import com.android.server.telecom.ui.ToastFactory;
32 
33 import android.app.ActivityManager;
34 import android.bluetooth.BluetoothManager;
35 import android.Manifest;
36 import android.content.BroadcastReceiver;
37 import android.content.Context;
38 import android.content.Intent;
39 import android.content.IntentFilter;
40 import android.content.ServiceConnection;
41 import android.content.pm.ApplicationInfo;
42 import android.content.pm.PackageManager;
43 import android.content.pm.ResolveInfo;
44 import android.net.Uri;
45 import android.os.UserHandle;
46 import android.os.UserManager;
47 import android.telecom.Log;
48 import android.telecom.PhoneAccountHandle;
49 import android.widget.Toast;
50 
51 import androidx.annotation.NonNull;
52 
53 import java.io.FileNotFoundException;
54 import java.io.InputStream;
55 import java.util.List;
56 
57 /**
58  * Top-level Application class for Telecom.
59  */
60 public class TelecomSystem {
61 
62     /**
63      * This interface is implemented by system-instantiated components (e.g., Services and
64      * Activity-s) that wish to use the TelecomSystem but would like to be testable. Such a
65      * component should implement the getTelecomSystem() method to return the global singleton,
66      * and use its own method. Tests can subclass the component to return a non-singleton.
67      *
68      * A refactoring goal for Telecom is to limit use of the TelecomSystem singleton to those
69      * system-instantiated components, and have all other parts of the system just take all their
70      * dependencies as explicit arguments to their constructor or other methods.
71      */
72     public interface Component {
getTelecomSystem()73         TelecomSystem getTelecomSystem();
74     }
75 
76 
77     /**
78      * Tagging interface for the object used for synchronizing multi-threaded operations in
79      * the Telecom system.
80      */
81     public interface SyncRoot {
82     }
83 
84     private static final IntentFilter USER_SWITCHED_FILTER =
85             new IntentFilter(Intent.ACTION_USER_SWITCHED);
86 
87     private static final IntentFilter USER_STARTING_FILTER =
88             new IntentFilter(Intent.ACTION_USER_STARTING);
89 
90     private static final IntentFilter BOOT_COMPLETE_FILTER =
91             new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
92 
93     /** Intent filter for dialer secret codes. */
94     private static final IntentFilter DIALER_SECRET_CODE_FILTER;
95 
96     /**
97      * Initializes the dialer secret code intent filter.  Setup to handle the various secret codes
98      * which can be dialed (e.g. in format *#*#code#*#*) to trigger various behavior in Telecom.
99      */
100     static {
101         DIALER_SECRET_CODE_FILTER = new IntentFilter(
102                 "android.provider.Telephony.SECRET_CODE");
103         DIALER_SECRET_CODE_FILTER.addDataScheme("android_secret_code");
104         DIALER_SECRET_CODE_FILTER
addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_DEBUG_ON, null)105                 .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_DEBUG_ON, null);
106         DIALER_SECRET_CODE_FILTER
addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_DEBUG_OFF, null)107                 .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_DEBUG_OFF, null);
108         DIALER_SECRET_CODE_FILTER
addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_MARK, null)109                 .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_MARK, null);
110         DIALER_SECRET_CODE_FILTER
addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_MENU, null)111                 .addDataAuthority(DialerCodeReceiver.TELECOM_SECRET_CODE_MENU, null);
112     }
113 
114     private static TelecomSystem INSTANCE = null;
115 
116     private final SyncRoot mLock = new SyncRoot() { };
117     private final MissedCallNotifier mMissedCallNotifier;
118     private final IncomingCallNotifier mIncomingCallNotifier;
119     private final PhoneAccountRegistrar mPhoneAccountRegistrar;
120     private final CallsManager mCallsManager;
121     private final RespondViaSmsManager mRespondViaSmsManager;
122     private final Context mContext;
123     private final CallIntentProcessor mCallIntentProcessor;
124     private final TelecomBroadcastIntentProcessor mTelecomBroadcastIntentProcessor;
125     private final TelecomServiceImpl mTelecomServiceImpl;
126     private final ContactsAsyncHelper mContactsAsyncHelper;
127     private final DialerCodeReceiver mDialerCodeReceiver;
128 
129     private boolean mIsBootComplete = false;
130 
131     private final BroadcastReceiver mUserSwitchedReceiver = new BroadcastReceiver() {
132         @Override
133         public void onReceive(Context context, Intent intent) {
134             Log.startSession("TSSwR.oR");
135             try {
136                 synchronized (mLock) {
137                     int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
138                     UserHandle currentUserHandle = new UserHandle(userHandleId);
139                     mPhoneAccountRegistrar.setCurrentUserHandle(currentUserHandle);
140                     mCallsManager.onUserSwitch(currentUserHandle);
141                 }
142             } finally {
143                 Log.endSession();
144             }
145         }
146     };
147 
148     private final BroadcastReceiver mUserStartingReceiver = new BroadcastReceiver() {
149         @Override
150         public void onReceive(Context context, Intent intent) {
151             Log.startSession("TSStR.oR");
152             try {
153                 synchronized (mLock) {
154                     int userHandleId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, 0);
155                     UserHandle addingUserHandle = new UserHandle(userHandleId);
156                     mCallsManager.onUserStarting(addingUserHandle);
157                 }
158             } finally {
159                 Log.endSession();
160             }
161         }
162     };
163 
164     private final BroadcastReceiver mBootCompletedReceiver = new BroadcastReceiver() {
165         @Override
166         public void onReceive(Context context, Intent intent) {
167             Log.startSession("TSBCR.oR");
168             try {
169                 synchronized (mLock) {
170                     mIsBootComplete = true;
171                     mCallsManager.onBootCompleted();
172                 }
173             } finally {
174                 Log.endSession();
175             }
176         }
177     };
178 
getInstance()179     public static TelecomSystem getInstance() {
180         return INSTANCE;
181     }
182 
setInstance(TelecomSystem instance)183     public static void setInstance(TelecomSystem instance) {
184         if (INSTANCE != null) {
185             Log.w("TelecomSystem", "Attempt to set TelecomSystem.INSTANCE twice");
186         }
187         Log.i(TelecomSystem.class, "TelecomSystem.INSTANCE being set");
188         INSTANCE = instance;
189     }
190 
TelecomSystem( Context context, MissedCallNotifierImplFactory missedCallNotifierImplFactory, CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory, HeadsetMediaButtonFactory headsetMediaButtonFactory, ProximitySensorManagerFactory proximitySensorManagerFactory, InCallWakeLockControllerFactory inCallWakeLockControllerFactory, AudioServiceFactory audioServiceFactory, ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory connectionServiceFocusManagerFactory, Timeouts.Adapter timeoutsAdapter, AsyncRingtonePlayer asyncRingtonePlayer, PhoneNumberUtilsAdapter phoneNumberUtilsAdapter, IncomingCallNotifier incomingCallNotifier, InCallTonePlayer.ToneGeneratorFactory toneGeneratorFactory, CallAudioRouteStateMachine.Factory callAudioRouteStateMachineFactory, CallAudioModeStateMachine.Factory callAudioModeStateMachineFactory, ClockProxy clockProxy, RoleManagerAdapter roleManagerAdapter, ContactsAsyncHelper.Factory contactsAsyncHelperFactory, DeviceIdleControllerAdapter deviceIdleControllerAdapter)191     public TelecomSystem(
192             Context context,
193             MissedCallNotifierImplFactory missedCallNotifierImplFactory,
194             CallerInfoAsyncQueryFactory callerInfoAsyncQueryFactory,
195             HeadsetMediaButtonFactory headsetMediaButtonFactory,
196             ProximitySensorManagerFactory proximitySensorManagerFactory,
197             InCallWakeLockControllerFactory inCallWakeLockControllerFactory,
198             AudioServiceFactory audioServiceFactory,
199             ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory
200                     connectionServiceFocusManagerFactory,
201             Timeouts.Adapter timeoutsAdapter,
202             AsyncRingtonePlayer asyncRingtonePlayer,
203             PhoneNumberUtilsAdapter phoneNumberUtilsAdapter,
204             IncomingCallNotifier incomingCallNotifier,
205             InCallTonePlayer.ToneGeneratorFactory toneGeneratorFactory,
206             CallAudioRouteStateMachine.Factory callAudioRouteStateMachineFactory,
207             CallAudioModeStateMachine.Factory callAudioModeStateMachineFactory,
208             ClockProxy clockProxy,
209             RoleManagerAdapter roleManagerAdapter,
210             ContactsAsyncHelper.Factory contactsAsyncHelperFactory,
211             DeviceIdleControllerAdapter deviceIdleControllerAdapter) {
212         mContext = context.getApplicationContext();
213         LogUtils.initLogging(mContext);
214         DefaultDialerManagerAdapter defaultDialerAdapter =
215                 new DefaultDialerCache.DefaultDialerManagerAdapterImpl();
216 
217         DefaultDialerCache defaultDialerCache = new DefaultDialerCache(mContext,
218                 defaultDialerAdapter, roleManagerAdapter, mLock);
219 
220         Log.startSession("TS.init");
221         // Wrap this in a try block to ensure session cleanup occurs in the case of error.
222         try {
223             mPhoneAccountRegistrar = new PhoneAccountRegistrar(mContext, mLock, defaultDialerCache,
224                     packageName -> AppLabelProxy.Util.getAppLabel(
225                             mContext.getPackageManager(), packageName));
226 
227             mContactsAsyncHelper = contactsAsyncHelperFactory.create(
228                     new ContactsAsyncHelper.ContentResolverAdapter() {
229                         @Override
230                         public InputStream openInputStream(Context context, Uri uri)
231                                 throws FileNotFoundException {
232                             return context.getContentResolver().openInputStream(uri);
233                         }
234                     });
235             BluetoothDeviceManager bluetoothDeviceManager = new BluetoothDeviceManager(mContext,
236                     mContext.getSystemService(BluetoothManager.class).getAdapter());
237             BluetoothRouteManager bluetoothRouteManager = new BluetoothRouteManager(mContext, mLock,
238                     bluetoothDeviceManager, new Timeouts.Adapter());
239             BluetoothStateReceiver bluetoothStateReceiver = new BluetoothStateReceiver(
240                     bluetoothDeviceManager, bluetoothRouteManager);
241             mContext.registerReceiver(bluetoothStateReceiver, BluetoothStateReceiver.INTENT_FILTER);
242 
243             WiredHeadsetManager wiredHeadsetManager = new WiredHeadsetManager(mContext);
244             SystemStateHelper systemStateHelper = new SystemStateHelper(mContext, mLock);
245 
246             mMissedCallNotifier = missedCallNotifierImplFactory
247                     .makeMissedCallNotifierImpl(mContext, mPhoneAccountRegistrar,
248                             defaultDialerCache,
249                             deviceIdleControllerAdapter);
250             DisconnectedCallNotifier.Factory disconnectedCallNotifierFactory =
251                     new DisconnectedCallNotifier.Default();
252 
253             CallerInfoLookupHelper callerInfoLookupHelper =
254                     new CallerInfoLookupHelper(context, callerInfoAsyncQueryFactory,
255                             mContactsAsyncHelper, mLock);
256 
257             EmergencyCallHelper emergencyCallHelper = new EmergencyCallHelper(mContext,
258                     defaultDialerCache, timeoutsAdapter);
259 
260             InCallControllerFactory inCallControllerFactory = new InCallControllerFactory() {
261                 @Override
262                 public InCallController create(Context context, SyncRoot lock,
263                         CallsManager callsManager, SystemStateHelper systemStateProvider,
264                         DefaultDialerCache defaultDialerCache, Timeouts.Adapter timeoutsAdapter,
265                         EmergencyCallHelper emergencyCallHelper) {
266                     return new InCallController(context, lock, callsManager, systemStateProvider,
267                             defaultDialerCache, timeoutsAdapter, emergencyCallHelper,
268                             new CarModeTracker(), clockProxy);
269                 }
270             };
271 
272             CallDiagnosticServiceController callDiagnosticServiceController =
273                     new CallDiagnosticServiceController(
274                             new CallDiagnosticServiceController.ContextProxy() {
275                                 @Override
276                                 public List<ResolveInfo> queryIntentServicesAsUser(
277                                         @NonNull Intent intent, int flags, int userId) {
278                                     return mContext.getPackageManager().queryIntentServicesAsUser(
279                                             intent, flags, userId);
280                                 }
281 
282                                 @Override
283                                 public boolean bindServiceAsUser(@NonNull Intent service,
284                                         @NonNull ServiceConnection conn, int flags,
285                                         @NonNull UserHandle user) {
286                                     return mContext.bindServiceAsUser(service, conn, flags, user);
287                                 }
288 
289                                 @Override
290                                 public void unbindService(@NonNull ServiceConnection conn) {
291                                     mContext.unbindService(conn);
292                                 }
293 
294                                 @Override
295                                 public UserHandle getCurrentUserHandle() {
296                                     return mCallsManager.getCurrentUserHandle();
297                                 }
298                             },
299                             mContext.getResources().getString(
300                                     com.android.server.telecom.R.string
301                                             .call_diagnostic_service_package_name),
302                             mLock
303                     );
304 
305             AudioProcessingNotification audioProcessingNotification =
306                     new AudioProcessingNotification(mContext);
307 
308             ToastFactory toastFactory = new ToastFactory() {
309                 @Override
310                 public Toast makeText(Context context, int resId, int duration) {
311                     return Toast.makeText(context, context.getMainLooper(),
312                             context.getString(resId),
313                             duration);
314                 }
315 
316                 @Override
317                 public Toast makeText(Context context, CharSequence text, int duration) {
318                     return Toast.makeText(context, context.getMainLooper(), text, duration);
319                 }
320             };
321 
322             mCallsManager = new CallsManager(
323                     mContext,
324                     mLock,
325                     callerInfoLookupHelper,
326                     mMissedCallNotifier,
327                     disconnectedCallNotifierFactory,
328                     mPhoneAccountRegistrar,
329                     headsetMediaButtonFactory,
330                     proximitySensorManagerFactory,
331                     inCallWakeLockControllerFactory,
332                     connectionServiceFocusManagerFactory,
333                     audioServiceFactory,
334                     bluetoothRouteManager,
335                     wiredHeadsetManager,
336                     systemStateHelper,
337                     defaultDialerCache,
338                     timeoutsAdapter,
339                     asyncRingtonePlayer,
340                     phoneNumberUtilsAdapter,
341                     emergencyCallHelper,
342                     toneGeneratorFactory,
343                     clockProxy,
344                     audioProcessingNotification,
345                     bluetoothStateReceiver,
346                     callAudioRouteStateMachineFactory,
347                     callAudioModeStateMachineFactory,
348                     inCallControllerFactory,
349                     callDiagnosticServiceController,
350                     roleManagerAdapter,
351                     toastFactory);
352 
353             mIncomingCallNotifier = incomingCallNotifier;
354             incomingCallNotifier.setCallsManagerProxy(new IncomingCallNotifier.CallsManagerProxy() {
355                 @Override
356                 public boolean hasUnholdableCallsForOtherConnectionService(
357                         PhoneAccountHandle phoneAccountHandle) {
358                     return mCallsManager.hasUnholdableCallsForOtherConnectionService(
359                             phoneAccountHandle);
360                 }
361 
362                 @Override
363                 public int getNumUnholdableCallsForOtherConnectionService(
364                         PhoneAccountHandle phoneAccountHandle) {
365                     return mCallsManager.getNumUnholdableCallsForOtherConnectionService(
366                             phoneAccountHandle);
367                 }
368 
369                 @Override
370                 public Call getActiveCall() {
371                     return mCallsManager.getActiveCall();
372                 }
373             });
374             mCallsManager.setIncomingCallNotifier(mIncomingCallNotifier);
375 
376             mRespondViaSmsManager = new RespondViaSmsManager(mCallsManager, mLock);
377             mCallsManager.setRespondViaSmsManager(mRespondViaSmsManager);
378 
379             mContext.registerReceiverAsUser(mUserSwitchedReceiver, UserHandle.ALL,
380                     USER_SWITCHED_FILTER, null, null);
381             mContext.registerReceiverAsUser(mUserStartingReceiver, UserHandle.ALL,
382                     USER_STARTING_FILTER, null, null);
383             mContext.registerReceiverAsUser(mBootCompletedReceiver, UserHandle.ALL,
384                     BOOT_COMPLETE_FILTER, null, null);
385 
386             // Set current user explicitly since USER_SWITCHED_FILTER intent can be missed at
387             // startup
388             synchronized (mLock) {
389                 UserHandle currentUserHandle = UserHandle.of(ActivityManager.getCurrentUser());
390                 mPhoneAccountRegistrar.setCurrentUserHandle(currentUserHandle);
391                 mCallsManager.onUserSwitch(currentUserHandle);
392             }
393 
394             mCallIntentProcessor = new CallIntentProcessor(mContext, mCallsManager,
395                     defaultDialerCache);
396             mTelecomBroadcastIntentProcessor = new TelecomBroadcastIntentProcessor(
397                     mContext, mCallsManager);
398 
399             // Register the receiver for the dialer secret codes, used to enable extended logging.
400             mDialerCodeReceiver = new DialerCodeReceiver(mCallsManager);
401             mContext.registerReceiver(mDialerCodeReceiver, DIALER_SECRET_CODE_FILTER,
402                     Manifest.permission.CONTROL_INCALL_EXPERIENCE, null);
403 
404             // There is no USER_SWITCHED broadcast for user 0, handle it here explicitly.
405             final UserManager userManager = UserManager.get(mContext);
406             mTelecomServiceImpl = new TelecomServiceImpl(
407                     mContext, mCallsManager, mPhoneAccountRegistrar,
408                     new CallIntentProcessor.AdapterImpl(defaultDialerCache),
409                     new UserCallIntentProcessorFactory() {
410                         @Override
411                         public UserCallIntentProcessor create(Context context,
412                                 UserHandle userHandle) {
413                             return new UserCallIntentProcessor(context, userHandle);
414                         }
415                     },
416                     defaultDialerCache,
417                     new TelecomServiceImpl.SubscriptionManagerAdapterImpl(),
418                     new TelecomServiceImpl.SettingsSecureAdapterImpl(),
419                     mLock);
420         } finally {
421             Log.endSession();
422         }
423     }
424 
425     @VisibleForTesting
getPhoneAccountRegistrar()426     public PhoneAccountRegistrar getPhoneAccountRegistrar() {
427         return mPhoneAccountRegistrar;
428     }
429 
430     @VisibleForTesting
getCallsManager()431     public CallsManager getCallsManager() {
432         return mCallsManager;
433     }
434 
getCallIntentProcessor()435     public CallIntentProcessor getCallIntentProcessor() {
436         return mCallIntentProcessor;
437     }
438 
getTelecomBroadcastIntentProcessor()439     public TelecomBroadcastIntentProcessor getTelecomBroadcastIntentProcessor() {
440         return mTelecomBroadcastIntentProcessor;
441     }
442 
getTelecomServiceImpl()443     public TelecomServiceImpl getTelecomServiceImpl() {
444         return mTelecomServiceImpl;
445     }
446 
getLock()447     public Object getLock() {
448         return mLock;
449     }
450 
isBootComplete()451     public boolean isBootComplete() {
452         return mIsBootComplete;
453     }
454 }
455