1 /* 2 * Copyright (C) 2006 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.phone; 18 19 import android.app.Activity; 20 import android.app.KeyguardManager; 21 import android.app.PendingIntent; 22 import android.app.ProgressDialog; 23 import android.app.TaskStackBuilder; 24 import android.bluetooth.BluetoothAdapter; 25 import android.bluetooth.IBluetoothHeadsetPhone; 26 import android.content.BroadcastReceiver; 27 import android.content.ComponentName; 28 import android.content.ContentResolver; 29 import android.content.Context; 30 import android.content.ContextWrapper; 31 import android.content.Intent; 32 import android.content.IntentFilter; 33 import android.content.ServiceConnection; 34 import android.media.AudioManager; 35 import android.net.Uri; 36 import android.os.AsyncResult; 37 import android.os.Bundle; 38 import android.os.Handler; 39 import android.os.IBinder; 40 import android.os.IPowerManager; 41 import android.os.Message; 42 import android.os.PersistableBundle; 43 import android.os.PowerManager; 44 import android.os.RemoteException; 45 import android.os.ServiceManager; 46 import android.os.SystemClock; 47 import android.os.SystemProperties; 48 import android.os.UpdateLock; 49 import android.os.UserHandle; 50 import android.preference.PreferenceManager; 51 import android.provider.Settings.System; 52 import android.telephony.CarrierConfigManager; 53 import android.telephony.ServiceState; 54 import android.telephony.SubscriptionInfo; 55 import android.telephony.SubscriptionManager; 56 import android.util.Log; 57 58 import com.android.internal.telephony.Call; 59 import com.android.internal.telephony.CallManager; 60 import com.android.internal.telephony.IccCard; 61 import com.android.internal.telephony.IccCardConstants; 62 import com.android.internal.telephony.MmiCode; 63 import com.android.internal.telephony.Phone; 64 import com.android.internal.telephony.PhoneConstants; 65 import com.android.internal.telephony.PhoneFactory; 66 import com.android.internal.telephony.SubscriptionController; 67 import com.android.internal.telephony.TelephonyCapabilities; 68 import com.android.internal.telephony.TelephonyIntents; 69 import com.android.phone.common.CallLogAsync; 70 import com.android.phone.settings.SettingsConstants; 71 import com.android.server.sip.SipService; 72 import com.android.services.telephony.activation.SimActivationManager; 73 74 import java.util.ArrayList; 75 import java.util.List; 76 77 /** 78 * Global state for the telephony subsystem when running in the primary 79 * phone process. 80 */ 81 public class PhoneGlobals extends ContextWrapper { 82 public static final String LOG_TAG = "PhoneApp"; 83 84 /** 85 * Phone app-wide debug level: 86 * 0 - no debug logging 87 * 1 - normal debug logging if ro.debuggable is set (which is true in 88 * "eng" and "userdebug" builds but not "user" builds) 89 * 2 - ultra-verbose debug logging 90 * 91 * Most individual classes in the phone app have a local DBG constant, 92 * typically set to 93 * (PhoneApp.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1) 94 * or else 95 * (PhoneApp.DBG_LEVEL >= 2) 96 * depending on the desired verbosity. 97 * 98 * ***** DO NOT SUBMIT WITH DBG_LEVEL > 0 ************* 99 */ 100 public static final int DBG_LEVEL = 0; 101 102 private static final boolean DBG = 103 (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1); 104 private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2); 105 106 // Message codes; see mHandler below. 107 private static final int EVENT_SIM_NETWORK_LOCKED = 3; 108 private static final int EVENT_SIM_STATE_CHANGED = 8; 109 private static final int EVENT_DATA_ROAMING_DISCONNECTED = 10; 110 private static final int EVENT_DATA_ROAMING_OK = 11; 111 private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 12; 112 private static final int EVENT_DOCK_STATE_CHANGED = 13; 113 private static final int EVENT_START_SIP_SERVICE = 14; 114 115 // The MMI codes are also used by the InCallScreen. 116 public static final int MMI_INITIATE = 51; 117 public static final int MMI_COMPLETE = 52; 118 public static final int MMI_CANCEL = 53; 119 // Don't use message codes larger than 99 here; those are reserved for 120 // the individual Activities of the Phone UI. 121 122 /** 123 * Allowable values for the wake lock code. 124 * SLEEP means the device can be put to sleep. 125 * PARTIAL means wake the processor, but we display can be kept off. 126 * FULL means wake both the processor and the display. 127 */ 128 public enum WakeState { 129 SLEEP, 130 PARTIAL, 131 FULL 132 } 133 134 /** 135 * Intent Action used for hanging up the current call from Notification bar. This will 136 * choose first ringing call, first active call, or first background call (typically in 137 * HOLDING state). 138 */ 139 public static final String ACTION_HANG_UP_ONGOING_CALL = 140 "com.android.phone.ACTION_HANG_UP_ONGOING_CALL"; 141 142 private static PhoneGlobals sMe; 143 144 // A few important fields we expose to the rest of the package 145 // directly (rather than thru set/get methods) for efficiency. 146 CallController callController; 147 CallManager mCM; 148 CallNotifier notifier; 149 CallerInfoCache callerInfoCache; 150 NotificationMgr notificationMgr; 151 public PhoneInterfaceManager phoneMgr; 152 public SimActivationManager simActivationManager; 153 CarrierConfigLoader configLoader; 154 155 private BluetoothManager bluetoothManager; 156 private CallGatewayManager callGatewayManager; 157 private CallStateMonitor callStateMonitor; 158 159 static int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; 160 static boolean sVoiceCapable = true; 161 162 // TODO: Remove, no longer used. 163 CdmaPhoneCallState cdmaPhoneCallState; 164 165 // The currently-active PUK entry activity and progress dialog. 166 // Normally, these are the Emergency Dialer and the subsequent 167 // progress dialog. null if there is are no such objects in 168 // the foreground. 169 private Activity mPUKEntryActivity; 170 private ProgressDialog mPUKEntryProgressDialog; 171 172 private boolean mIsSimPinEnabled; 173 private String mCachedSimPin; 174 175 // True if we are beginning a call, but the phone state has not changed yet 176 private boolean mBeginningCall; 177 private boolean mDataDisconnectedDueToRoaming = false; 178 179 // Last phone state seen by updatePhoneState() 180 private PhoneConstants.State mLastPhoneState = PhoneConstants.State.IDLE; 181 182 private WakeState mWakeState = WakeState.SLEEP; 183 184 private PowerManager mPowerManager; 185 private IPowerManager mPowerManagerService; 186 private PowerManager.WakeLock mWakeLock; 187 private PowerManager.WakeLock mPartialWakeLock; 188 private KeyguardManager mKeyguardManager; 189 190 private UpdateLock mUpdateLock; 191 192 // Broadcast receiver for various intent broadcasts (see onCreate()) 193 private final BroadcastReceiver mReceiver = new PhoneAppBroadcastReceiver(); 194 195 /** boolean indicating restoring mute state on InCallScreen.onResume() */ 196 private boolean mShouldRestoreMuteOnInCallResume; 197 198 /** 199 * The singleton OtaUtils instance used for OTASP calls. 200 * 201 * The OtaUtils instance is created lazily the first time we need to 202 * make an OTASP call, regardless of whether it's an interactive or 203 * non-interactive OTASP call. 204 */ 205 public OtaUtils otaUtils; 206 207 // Following are the CDMA OTA information Objects used during OTA Call. 208 // cdmaOtaProvisionData object store static OTA information that needs 209 // to be maintained even during Slider open/close scenarios. 210 // cdmaOtaConfigData object stores configuration info to control visiblity 211 // of each OTA Screens. 212 // cdmaOtaScreenState object store OTA Screen State information. 213 public OtaUtils.CdmaOtaProvisionData cdmaOtaProvisionData; 214 public OtaUtils.CdmaOtaConfigData cdmaOtaConfigData; 215 public OtaUtils.CdmaOtaScreenState cdmaOtaScreenState; 216 public OtaUtils.CdmaOtaInCallScreenUiState cdmaOtaInCallScreenUiState; 217 218 /** 219 * Set the restore mute state flag. Used when we are setting the mute state 220 * OUTSIDE of user interaction {@link PhoneUtils#startNewCall(Phone)} 221 */ setRestoreMuteOnInCallResume(boolean mode)222 /*package*/void setRestoreMuteOnInCallResume (boolean mode) { 223 mShouldRestoreMuteOnInCallResume = mode; 224 } 225 226 Handler mHandler = new Handler() { 227 @Override 228 public void handleMessage(Message msg) { 229 PhoneConstants.State phoneState; 230 switch (msg.what) { 231 // Starts the SIP service. It's a no-op if SIP API is not supported 232 // on the deivce. 233 // TODO: Having the phone process host the SIP service is only 234 // temporary. Will move it to a persistent communication process 235 // later. 236 case EVENT_START_SIP_SERVICE: 237 SipService.start(getApplicationContext()); 238 break; 239 240 // TODO: This event should be handled by the lock screen, just 241 // like the "SIM missing" and "Sim locked" cases (bug 1804111). 242 case EVENT_SIM_NETWORK_LOCKED: 243 if (getCarrierConfig().getBoolean( 244 CarrierConfigManager.KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL)) { 245 // Some products don't have the concept of a "SIM network lock" 246 Log.i(LOG_TAG, "Ignoring EVENT_SIM_NETWORK_LOCKED event; " 247 + "not showing 'SIM network unlock' PIN entry screen"); 248 } else { 249 // Normal case: show the "SIM network unlock" PIN entry screen. 250 // The user won't be able to do anything else until 251 // they enter a valid SIM network PIN. 252 Log.i(LOG_TAG, "show sim depersonal panel"); 253 IccNetworkDepersonalizationPanel.showDialog(); 254 } 255 break; 256 257 case EVENT_DATA_ROAMING_DISCONNECTED: 258 notificationMgr.showDataDisconnectedRoaming(); 259 break; 260 261 case EVENT_DATA_ROAMING_OK: 262 notificationMgr.hideDataDisconnectedRoaming(); 263 break; 264 265 case MMI_COMPLETE: 266 onMMIComplete((AsyncResult) msg.obj); 267 break; 268 269 case MMI_CANCEL: 270 PhoneUtils.cancelMmiCode(mCM.getFgPhone()); 271 break; 272 273 case EVENT_SIM_STATE_CHANGED: 274 // Marks the event where the SIM goes into ready state. 275 // Right now, this is only used for the PUK-unlocking 276 // process. 277 if (msg.obj.equals(IccCardConstants.INTENT_VALUE_ICC_READY)) { 278 // when the right event is triggered and there 279 // are UI objects in the foreground, we close 280 // them to display the lock panel. 281 if (mPUKEntryActivity != null) { 282 mPUKEntryActivity.finish(); 283 mPUKEntryActivity = null; 284 } 285 if (mPUKEntryProgressDialog != null) { 286 mPUKEntryProgressDialog.dismiss(); 287 mPUKEntryProgressDialog = null; 288 } 289 } 290 break; 291 292 case EVENT_UNSOL_CDMA_INFO_RECORD: 293 //TODO: handle message here; 294 break; 295 296 case EVENT_DOCK_STATE_CHANGED: 297 // If the phone is docked/undocked during a call, and no wired or BT headset 298 // is connected: turn on/off the speaker accordingly. 299 boolean inDockMode = false; 300 if (mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) { 301 inDockMode = true; 302 } 303 if (VDBG) Log.d(LOG_TAG, "received EVENT_DOCK_STATE_CHANGED. Phone inDock = " 304 + inDockMode); 305 306 phoneState = mCM.getState(); 307 if (phoneState == PhoneConstants.State.OFFHOOK && 308 !bluetoothManager.isBluetoothHeadsetAudioOn()) { 309 PhoneUtils.turnOnSpeaker(getApplicationContext(), inDockMode, true); 310 } 311 break; 312 } 313 } 314 }; 315 PhoneGlobals(Context context)316 public PhoneGlobals(Context context) { 317 super(context); 318 sMe = this; 319 } 320 onCreate()321 public void onCreate() { 322 if (VDBG) Log.v(LOG_TAG, "onCreate()..."); 323 324 ContentResolver resolver = getContentResolver(); 325 326 // Cache the "voice capable" flag. 327 // This flag currently comes from a resource (which is 328 // overrideable on a per-product basis): 329 sVoiceCapable = 330 getResources().getBoolean(com.android.internal.R.bool.config_voice_capable); 331 // ...but this might eventually become a PackageManager "system 332 // feature" instead, in which case we'd do something like: 333 // sVoiceCapable = 334 // getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS); 335 336 if (mCM == null) { 337 // Initialize the telephony framework 338 PhoneFactory.makeDefaultPhones(this); 339 340 // Start TelephonyDebugService After the default phone is created. 341 Intent intent = new Intent(this, TelephonyDebugService.class); 342 startService(intent); 343 344 mCM = CallManager.getInstance(); 345 for (Phone phone : PhoneFactory.getPhones()) { 346 mCM.registerPhone(phone); 347 } 348 349 // Create the NotificationMgr singleton, which is used to display 350 // status bar icons and control other status bar behavior. 351 notificationMgr = NotificationMgr.init(this); 352 353 mHandler.sendEmptyMessage(EVENT_START_SIP_SERVICE); 354 355 // Create an instance of CdmaPhoneCallState and initialize it to IDLE 356 cdmaPhoneCallState = new CdmaPhoneCallState(); 357 cdmaPhoneCallState.CdmaPhoneCallStateInit(); 358 359 // before registering for phone state changes 360 mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 361 mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG); 362 // lock used to keep the processor awake, when we don't care for the display. 363 mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK 364 | PowerManager.ON_AFTER_RELEASE, LOG_TAG); 365 366 mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); 367 368 // get a handle to the service so that we can use it later when we 369 // want to set the poke lock. 370 mPowerManagerService = IPowerManager.Stub.asInterface( 371 ServiceManager.getService("power")); 372 373 // Get UpdateLock to suppress system-update related events (e.g. dialog show-up) 374 // during phone calls. 375 mUpdateLock = new UpdateLock("phone"); 376 377 if (DBG) Log.d(LOG_TAG, "onCreate: mUpdateLock: " + mUpdateLock); 378 379 CallLogger callLogger = new CallLogger(this, new CallLogAsync()); 380 381 callGatewayManager = CallGatewayManager.getInstance(); 382 383 // Create the CallController singleton, which is the interface 384 // to the telephony layer for user-initiated telephony functionality 385 // (like making outgoing calls.) 386 callController = CallController.init(this, callLogger, callGatewayManager); 387 388 // Create the CallerInfoCache singleton, which remembers custom ring tone and 389 // send-to-voicemail settings. 390 // 391 // The asynchronous caching will start just after this call. 392 callerInfoCache = CallerInfoCache.init(this); 393 394 // Monitors call activity from the telephony layer 395 callStateMonitor = new CallStateMonitor(mCM); 396 397 // Bluetooth manager 398 bluetoothManager = new BluetoothManager(); 399 400 phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone()); 401 402 configLoader = CarrierConfigLoader.init(this); 403 404 // Create the CallNotifer singleton, which handles 405 // asynchronous events from the telephony layer (like 406 // launching the incoming-call UI when an incoming call comes 407 // in.) 408 notifier = CallNotifier.init(this, callLogger, callStateMonitor, bluetoothManager); 409 410 PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED); 411 412 // register for MMI/USSD 413 mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null); 414 415 // register connection tracking to PhoneUtils 416 PhoneUtils.initializeConnectionHandler(mCM); 417 418 // Register for misc other intent broadcasts. 419 IntentFilter intentFilter = 420 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED); 421 intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED); 422 intentFilter.addAction(Intent.ACTION_DOCK_EVENT); 423 intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 424 intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED); 425 intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); 426 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 427 registerReceiver(mReceiver, intentFilter); 428 429 //set the default values for the preferences in the phone. 430 PreferenceManager.setDefaultValues(this, R.xml.network_setting, false); 431 432 PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false); 433 434 // Make sure the audio mode (along with some 435 // audio-mode-related state of our own) is initialized 436 // correctly, given the current state of the phone. 437 PhoneUtils.setAudioMode(mCM); 438 } 439 440 cdmaOtaProvisionData = new OtaUtils.CdmaOtaProvisionData(); 441 cdmaOtaConfigData = new OtaUtils.CdmaOtaConfigData(); 442 cdmaOtaScreenState = new OtaUtils.CdmaOtaScreenState(); 443 cdmaOtaInCallScreenUiState = new OtaUtils.CdmaOtaInCallScreenUiState(); 444 445 simActivationManager = new SimActivationManager(); 446 447 // XXX pre-load the SimProvider so that it's ready 448 resolver.getType(Uri.parse("content://icc/adn")); 449 450 // start with the default value to set the mute state. 451 mShouldRestoreMuteOnInCallResume = false; 452 453 // TODO: Register for Cdma Information Records 454 // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null); 455 456 // Read HAC settings and configure audio hardware 457 if (getResources().getBoolean(R.bool.hac_enabled)) { 458 int hac = android.provider.Settings.System.getInt( 459 getContentResolver(), 460 android.provider.Settings.System.HEARING_AID, 461 0); 462 AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 463 audioManager.setParameter(SettingsConstants.HAC_KEY, 464 hac == SettingsConstants.HAC_ENABLED 465 ? SettingsConstants.HAC_VAL_ON : SettingsConstants.HAC_VAL_OFF); 466 } 467 } 468 469 /** 470 * Returns the singleton instance of the PhoneApp. 471 */ getInstance()472 public static PhoneGlobals getInstance() { 473 if (sMe == null) { 474 throw new IllegalStateException("No PhoneGlobals here!"); 475 } 476 return sMe; 477 } 478 479 /** 480 * Returns the singleton instance of the PhoneApp if running as the 481 * primary user, otherwise null. 482 */ getInstanceIfPrimary()483 static PhoneGlobals getInstanceIfPrimary() { 484 return sMe; 485 } 486 487 /** 488 * Returns the default phone. 489 * 490 * WARNING: This method should be used carefully, now that there may be multiple phones. 491 */ getPhone()492 public static Phone getPhone() { 493 return PhoneFactory.getDefaultPhone(); 494 } 495 getPhone(int subId)496 public static Phone getPhone(int subId) { 497 return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId)); 498 } 499 getBluetoothManager()500 /* package */ BluetoothManager getBluetoothManager() { 501 return bluetoothManager; 502 } 503 getCallManager()504 /* package */ CallManager getCallManager() { 505 return mCM; 506 } 507 getCarrierConfig()508 public PersistableBundle getCarrierConfig() { 509 return getCarrierConfigForSubId(SubscriptionManager.getDefaultSubId()); 510 } 511 getCarrierConfigForSubId(int subId)512 public PersistableBundle getCarrierConfigForSubId(int subId) { 513 return configLoader.getConfigForSubId(subId); 514 } 515 516 /** 517 * Returns PendingIntent for hanging up ongoing phone call. This will typically be used from 518 * Notification context. 519 */ createHangUpOngoingCallPendingIntent(Context context)520 /* package */ static PendingIntent createHangUpOngoingCallPendingIntent(Context context) { 521 Intent intent = new Intent(PhoneGlobals.ACTION_HANG_UP_ONGOING_CALL, null, 522 context, NotificationBroadcastReceiver.class); 523 return PendingIntent.getBroadcast(context, 0, intent, 0); 524 } 525 isSimPinEnabled()526 boolean isSimPinEnabled() { 527 return mIsSimPinEnabled; 528 } 529 authenticateAgainstCachedSimPin(String pin)530 boolean authenticateAgainstCachedSimPin(String pin) { 531 return (mCachedSimPin != null && mCachedSimPin.equals(pin)); 532 } 533 setCachedSimPin(String pin)534 void setCachedSimPin(String pin) { 535 mCachedSimPin = pin; 536 } 537 538 /** 539 * Handles OTASP-related events from the telephony layer. 540 * 541 * While an OTASP call is active, the CallNotifier forwards 542 * OTASP-related telephony events to this method. 543 */ handleOtaspEvent(Message msg)544 void handleOtaspEvent(Message msg) { 545 if (DBG) Log.d(LOG_TAG, "handleOtaspEvent(message " + msg + ")..."); 546 547 if (otaUtils == null) { 548 // We shouldn't be getting OTASP events without ever 549 // having started the OTASP call in the first place! 550 Log.w(LOG_TAG, "handleOtaEvents: got an event but otaUtils is null! " 551 + "message = " + msg); 552 return; 553 } 554 555 otaUtils.onOtaProvisionStatusChanged((AsyncResult) msg.obj); 556 } 557 558 /** 559 * Similarly, handle the disconnect event of an OTASP call 560 * by forwarding it to the OtaUtils instance. 561 */ handleOtaspDisconnect()562 /* package */ void handleOtaspDisconnect() { 563 if (DBG) Log.d(LOG_TAG, "handleOtaspDisconnect()..."); 564 565 if (otaUtils == null) { 566 // We shouldn't be getting OTASP events without ever 567 // having started the OTASP call in the first place! 568 Log.w(LOG_TAG, "handleOtaspDisconnect: otaUtils is null!"); 569 return; 570 } 571 572 otaUtils.onOtaspDisconnect(); 573 } 574 575 /** 576 * Sets the activity responsible for un-PUK-blocking the device 577 * so that we may close it when we receive a positive result. 578 * mPUKEntryActivity is also used to indicate to the device that 579 * we are trying to un-PUK-lock the phone. In other words, iff 580 * it is NOT null, then we are trying to unlock and waiting for 581 * the SIM to move to READY state. 582 * 583 * @param activity is the activity to close when PUK has 584 * finished unlocking. Can be set to null to indicate the unlock 585 * or SIM READYing process is over. 586 */ setPukEntryActivity(Activity activity)587 void setPukEntryActivity(Activity activity) { 588 mPUKEntryActivity = activity; 589 } 590 getPUKEntryActivity()591 Activity getPUKEntryActivity() { 592 return mPUKEntryActivity; 593 } 594 595 /** 596 * Sets the dialog responsible for notifying the user of un-PUK- 597 * blocking - SIM READYing progress, so that we may dismiss it 598 * when we receive a positive result. 599 * 600 * @param dialog indicates the progress dialog informing the user 601 * of the state of the device. Dismissed upon completion of 602 * READYing process 603 */ setPukEntryProgressDialog(ProgressDialog dialog)604 void setPukEntryProgressDialog(ProgressDialog dialog) { 605 mPUKEntryProgressDialog = dialog; 606 } 607 getPUKEntryProgressDialog()608 ProgressDialog getPUKEntryProgressDialog() { 609 return mPUKEntryProgressDialog; 610 } 611 612 /** 613 * Controls whether or not the screen is allowed to sleep. 614 * 615 * Once sleep is allowed (WakeState is SLEEP), it will rely on the 616 * settings for the poke lock to determine when to timeout and let 617 * the device sleep {@link PhoneGlobals#setScreenTimeout}. 618 * 619 * @param ws tells the device to how to wake. 620 */ requestWakeState(WakeState ws)621 /* package */ void requestWakeState(WakeState ws) { 622 if (VDBG) Log.d(LOG_TAG, "requestWakeState(" + ws + ")..."); 623 synchronized (this) { 624 if (mWakeState != ws) { 625 switch (ws) { 626 case PARTIAL: 627 // acquire the processor wake lock, and release the FULL 628 // lock if it is being held. 629 mPartialWakeLock.acquire(); 630 if (mWakeLock.isHeld()) { 631 mWakeLock.release(); 632 } 633 break; 634 case FULL: 635 // acquire the full wake lock, and release the PARTIAL 636 // lock if it is being held. 637 mWakeLock.acquire(); 638 if (mPartialWakeLock.isHeld()) { 639 mPartialWakeLock.release(); 640 } 641 break; 642 case SLEEP: 643 default: 644 // release both the PARTIAL and FULL locks. 645 if (mWakeLock.isHeld()) { 646 mWakeLock.release(); 647 } 648 if (mPartialWakeLock.isHeld()) { 649 mPartialWakeLock.release(); 650 } 651 break; 652 } 653 mWakeState = ws; 654 } 655 } 656 } 657 658 /** 659 * If we are not currently keeping the screen on, then poke the power 660 * manager to wake up the screen for the user activity timeout duration. 661 */ wakeUpScreen()662 /* package */ void wakeUpScreen() { 663 synchronized (this) { 664 if (mWakeState == WakeState.SLEEP) { 665 if (DBG) Log.d(LOG_TAG, "pulse screen lock"); 666 mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.phone:WAKE"); 667 } 668 } 669 } 670 671 /** 672 * Sets the wake state and screen timeout based on the current state 673 * of the phone, and the current state of the in-call UI. 674 * 675 * This method is a "UI Policy" wrapper around 676 * {@link PhoneGlobals#requestWakeState} and {@link PhoneGlobals#setScreenTimeout}. 677 * 678 * It's safe to call this method regardless of the state of the Phone 679 * (e.g. whether or not it's idle), and regardless of the state of the 680 * Phone UI (e.g. whether or not the InCallScreen is active.) 681 */ updateWakeState()682 /* package */ void updateWakeState() { 683 PhoneConstants.State state = mCM.getState(); 684 685 // True if the speakerphone is in use. (If so, we *always* use 686 // the default timeout. Since the user is obviously not holding 687 // the phone up to his/her face, we don't need to worry about 688 // false touches, and thus don't need to turn the screen off so 689 // aggressively.) 690 // Note that we need to make a fresh call to this method any 691 // time the speaker state changes. (That happens in 692 // PhoneUtils.turnOnSpeaker().) 693 boolean isSpeakerInUse = (state == PhoneConstants.State.OFFHOOK) && PhoneUtils.isSpeakerOn(this); 694 695 // TODO (bug 1440854): The screen timeout *might* also need to 696 // depend on the bluetooth state, but this isn't as clear-cut as 697 // the speaker state (since while using BT it's common for the 698 // user to put the phone straight into a pocket, in which case the 699 // timeout should probably still be short.) 700 701 // Decide whether to force the screen on or not. 702 // 703 // Force the screen to be on if the phone is ringing or dialing, 704 // or if we're displaying the "Call ended" UI for a connection in 705 // the "disconnected" state. 706 // However, if the phone is disconnected while the user is in the 707 // middle of selecting a quick response message, we should not force 708 // the screen to be on. 709 // 710 boolean isRinging = (state == PhoneConstants.State.RINGING); 711 boolean isDialing = (mCM.getFgPhone().getForegroundCall().getState() == Call.State.DIALING); 712 boolean keepScreenOn = isRinging || isDialing; 713 // keepScreenOn == true means we'll hold a full wake lock: 714 requestWakeState(keepScreenOn ? WakeState.FULL : WakeState.SLEEP); 715 } 716 717 /** 718 * Manually pokes the PowerManager's userActivity method. Since we 719 * set the {@link WindowManager.LayoutParams#INPUT_FEATURE_DISABLE_USER_ACTIVITY} 720 * flag while the InCallScreen is active when there is no proximity sensor, 721 * we need to do this for touch events that really do count as user activity 722 * (like pressing any onscreen UI elements.) 723 */ pokeUserActivity()724 /* package */ void pokeUserActivity() { 725 if (VDBG) Log.d(LOG_TAG, "pokeUserActivity()..."); 726 mPowerManager.userActivity(SystemClock.uptimeMillis(), false); 727 } 728 729 /** 730 * Notifies the phone app when the phone state changes. 731 * 732 * This method will updates various states inside Phone app (e.g. update-lock state, etc.) 733 */ updatePhoneState(PhoneConstants.State state)734 /* package */ void updatePhoneState(PhoneConstants.State state) { 735 if (state != mLastPhoneState) { 736 mLastPhoneState = state; 737 738 // Try to acquire or release UpdateLock. 739 // 740 // Watch out: we don't release the lock here when the screen is still in foreground. 741 // At that time InCallScreen will release it on onPause(). 742 if (state != PhoneConstants.State.IDLE) { 743 // UpdateLock is a recursive lock, while we may get "acquire" request twice and 744 // "release" request once for a single call (RINGING + OFFHOOK and IDLE). 745 // We need to manually ensure the lock is just acquired once for each (and this 746 // will prevent other possible buggy situations too). 747 if (!mUpdateLock.isHeld()) { 748 mUpdateLock.acquire(); 749 } 750 } else { 751 if (mUpdateLock.isHeld()) { 752 mUpdateLock.release(); 753 } 754 } 755 } 756 } 757 getPhoneState()758 /* package */ PhoneConstants.State getPhoneState() { 759 return mLastPhoneState; 760 } 761 getKeyguardManager()762 KeyguardManager getKeyguardManager() { 763 return mKeyguardManager; 764 } 765 onMMIComplete(AsyncResult r)766 private void onMMIComplete(AsyncResult r) { 767 if (VDBG) Log.d(LOG_TAG, "onMMIComplete()..."); 768 MmiCode mmiCode = (MmiCode) r.result; 769 PhoneUtils.displayMMIComplete(mmiCode.getPhone(), getInstance(), mmiCode, null, null); 770 } 771 initForNewRadioTechnology(int phoneId)772 private void initForNewRadioTechnology(int phoneId) { 773 if (DBG) Log.d(LOG_TAG, "initForNewRadioTechnology..."); 774 775 final Phone phone = PhoneFactory.getPhone(phoneId); 776 if (phone == null || !TelephonyCapabilities.supportsOtasp(phone)) { 777 // Clean up OTA for non-CDMA since it is only valid for CDMA. 778 clearOtaState(); 779 } 780 781 notifier.updateCallNotifierRegistrationsAfterRadioTechnologyChange(); 782 callStateMonitor.updateAfterRadioTechnologyChange(); 783 784 // Update registration for ICC status after radio technology change 785 IccCard sim = phone == null ? null : phone.getIccCard(); 786 if (sim != null) { 787 if (DBG) Log.d(LOG_TAG, "Update registration for ICC status..."); 788 789 //Register all events new to the new active phone 790 sim.registerForNetworkLocked(mHandler, EVENT_SIM_NETWORK_LOCKED, null); 791 } 792 } 793 794 /** 795 * Receiver for misc intent broadcasts the Phone app cares about. 796 */ 797 private class PhoneAppBroadcastReceiver extends BroadcastReceiver { 798 @Override onReceive(Context context, Intent intent)799 public void onReceive(Context context, Intent intent) { 800 String action = intent.getAction(); 801 if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 802 boolean enabled = System.getInt(getContentResolver(), 803 System.AIRPLANE_MODE_ON, 0) == 0; 804 PhoneUtils.setRadioPower(enabled); 805 } else if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) { 806 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, 807 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 808 int phoneId = SubscriptionManager.getPhoneId(subId); 809 String state = intent.getStringExtra(PhoneConstants.STATE_KEY); 810 if (VDBG) { 811 Log.d(LOG_TAG, "mReceiver: ACTION_ANY_DATA_CONNECTION_STATE_CHANGED"); 812 Log.d(LOG_TAG, "- state: " + state); 813 Log.d(LOG_TAG, "- reason: " 814 + intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY)); 815 Log.d(LOG_TAG, "- subId: " + subId); 816 Log.d(LOG_TAG, "- phoneId: " + phoneId); 817 } 818 Phone phone = SubscriptionManager.isValidPhoneId(phoneId) ? 819 PhoneFactory.getPhone(phoneId) : PhoneFactory.getDefaultPhone(); 820 821 // The "data disconnected due to roaming" notification is shown 822 // if (a) you have the "data roaming" feature turned off, and 823 // (b) you just lost data connectivity because you're roaming. 824 boolean disconnectedDueToRoaming = 825 !phone.getDataRoamingEnabled() 826 && PhoneConstants.DataState.DISCONNECTED.equals(state) 827 && Phone.REASON_ROAMING_ON.equals( 828 intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY)); 829 if (mDataDisconnectedDueToRoaming != disconnectedDueToRoaming) { 830 mDataDisconnectedDueToRoaming = disconnectedDueToRoaming; 831 mHandler.sendEmptyMessage(disconnectedDueToRoaming 832 ? EVENT_DATA_ROAMING_DISCONNECTED : EVENT_DATA_ROAMING_OK); 833 } 834 } else if ((action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) && 835 (mPUKEntryActivity != null)) { 836 // if an attempt to un-PUK-lock the device was made, while we're 837 // receiving this state change notification, notify the handler. 838 // NOTE: This is ONLY triggered if an attempt to un-PUK-lock has 839 // been attempted. 840 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SIM_STATE_CHANGED, 841 intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE))); 842 } else if (action.equals(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED)) { 843 String newPhone = intent.getStringExtra(PhoneConstants.PHONE_NAME_KEY); 844 int phoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY, 845 SubscriptionManager.INVALID_PHONE_INDEX); 846 Log.d(LOG_TAG, "Radio technology switched. Now " + newPhone + " (" + phoneId 847 + ") is active."); 848 initForNewRadioTechnology(phoneId); 849 } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) { 850 handleServiceStateChanged(intent); 851 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) { 852 if (TelephonyCapabilities.supportsEcm(mCM.getFgPhone())) { 853 Log.d(LOG_TAG, "Emergency Callback Mode arrived in PhoneApp."); 854 // Start Emergency Callback Mode service 855 if (intent.getBooleanExtra("phoneinECMState", false)) { 856 context.startService(new Intent(context, 857 EmergencyCallbackModeService.class)); 858 } 859 } else { 860 // It doesn't make sense to get ACTION_EMERGENCY_CALLBACK_MODE_CHANGED 861 // on a device that doesn't support ECM in the first place. 862 Log.e(LOG_TAG, "Got ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, " 863 + "but ECM isn't supported for phone: " 864 + mCM.getFgPhone().getPhoneName()); 865 } 866 } else if (action.equals(Intent.ACTION_DOCK_EVENT)) { 867 mDockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE, 868 Intent.EXTRA_DOCK_STATE_UNDOCKED); 869 if (VDBG) Log.d(LOG_TAG, "ACTION_DOCK_EVENT -> mDockState = " + mDockState); 870 mHandler.sendMessage(mHandler.obtainMessage(EVENT_DOCK_STATE_CHANGED, 0)); 871 } 872 } 873 } 874 875 /** 876 * Accepts broadcast Intents which will be prepared by {@link NotificationMgr} and thus 877 * sent from framework's notification mechanism (which is outside Phone context). 878 * This should be visible from outside, but shouldn't be in "exported" state. 879 * 880 * TODO: If possible merge this into PhoneAppBroadcastReceiver. 881 */ 882 public static class NotificationBroadcastReceiver extends BroadcastReceiver { 883 @Override onReceive(Context context, Intent intent)884 public void onReceive(Context context, Intent intent) { 885 String action = intent.getAction(); 886 // TODO: use "if (VDBG)" here. 887 Log.d(LOG_TAG, "Broadcast from Notification: " + action); 888 889 if (action.equals(ACTION_HANG_UP_ONGOING_CALL)) { 890 PhoneUtils.hangup(PhoneGlobals.getInstance().mCM); 891 } else { 892 Log.w(LOG_TAG, "Received hang-up request from notification," 893 + " but there's no call the system can hang up."); 894 } 895 } 896 } 897 handleServiceStateChanged(Intent intent)898 private void handleServiceStateChanged(Intent intent) { 899 /** 900 * This used to handle updating EriTextWidgetProvider this routine 901 * and and listening for ACTION_SERVICE_STATE_CHANGED intents could 902 * be removed. But leaving just in case it might be needed in the near 903 * future. 904 */ 905 906 // If service just returned, start sending out the queued messages 907 Bundle extras = intent.getExtras(); 908 if (extras != null) { 909 ServiceState ss = ServiceState.newFromBundle(extras); 910 if (ss != null) { 911 int state = ss.getState(); 912 notificationMgr.updateNetworkSelection(state); 913 } 914 } 915 } 916 isOtaCallInActiveState()917 public boolean isOtaCallInActiveState() { 918 boolean otaCallActive = false; 919 if (VDBG) Log.d(LOG_TAG, "- isOtaCallInActiveState " + otaCallActive); 920 return otaCallActive; 921 } 922 isOtaCallInEndState()923 public boolean isOtaCallInEndState() { 924 boolean otaCallEnded = false; 925 if (VDBG) Log.d(LOG_TAG, "- isOtaCallInEndState " + otaCallEnded); 926 return otaCallEnded; 927 } 928 929 // it is safe to call clearOtaState() even if the InCallScreen isn't active clearOtaState()930 public void clearOtaState() { 931 if (DBG) Log.d(LOG_TAG, "- clearOtaState ..."); 932 if (otaUtils != null) { 933 otaUtils.cleanOtaScreen(true); 934 if (DBG) Log.d(LOG_TAG, " - clearOtaState clears OTA screen"); 935 } 936 } 937 938 // it is safe to call dismissOtaDialogs() even if the InCallScreen isn't active dismissOtaDialogs()939 public void dismissOtaDialogs() { 940 if (DBG) Log.d(LOG_TAG, "- dismissOtaDialogs ..."); 941 if (otaUtils != null) { 942 otaUtils.dismissAllOtaDialogs(); 943 if (DBG) Log.d(LOG_TAG, " - dismissOtaDialogs clears OTA dialogs"); 944 } 945 } 946 947 /** 948 * Triggers a refresh of the message waiting (voicemail) indicator. 949 * 950 * @param subId the subscription id we should refresh the notification for. 951 */ refreshMwiIndicator(int subId)952 public void refreshMwiIndicator(int subId) { 953 notificationMgr.refreshMwi(subId); 954 } 955 956 /** 957 * Dismisses the message waiting (voicemail) indicator. 958 * 959 * @param subId the subscription id we should dismiss the notification for. 960 */ clearMwiIndicator(int subId)961 public void clearMwiIndicator(int subId) { 962 notificationMgr.updateMwi(subId, false); 963 } 964 965 /** 966 * "Call origin" may be used by Contacts app to specify where the phone call comes from. 967 * Currently, the only permitted value for this extra is {@link #ALLOWED_EXTRA_CALL_ORIGIN}. 968 * Any other value will be ignored, to make sure that malicious apps can't trick the in-call 969 * UI into launching some random other app after a call ends. 970 * 971 * TODO: make this more generic. Note that we should let the "origin" specify its package 972 * while we are now assuming it is "com.android.contacts" 973 */ 974 public static final String EXTRA_CALL_ORIGIN = "com.android.phone.CALL_ORIGIN"; 975 private static final String DEFAULT_CALL_ORIGIN_PACKAGE = "com.android.dialer"; 976 private static final String ALLOWED_EXTRA_CALL_ORIGIN = 977 "com.android.dialer.DialtactsActivity"; 978 /** 979 * Used to determine if the preserved call origin is fresh enough. 980 */ 981 private static final long CALL_ORIGIN_EXPIRATION_MILLIS = 30 * 1000; 982 } 983