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