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