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