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.ProgressDialog; 22 import android.content.BroadcastReceiver; 23 import android.content.ContentResolver; 24 import android.content.Context; 25 import android.content.ContextWrapper; 26 import android.content.Intent; 27 import android.content.IntentFilter; 28 import android.media.AudioManager; 29 import android.net.ConnectivityManager; 30 import android.net.Uri; 31 import android.net.sip.SipManager; 32 import android.os.AsyncResult; 33 import android.os.Bundle; 34 import android.os.Handler; 35 import android.os.Message; 36 import android.os.PersistableBundle; 37 import android.os.PowerManager; 38 import android.os.SystemClock; 39 import android.os.SystemProperties; 40 import android.os.UpdateLock; 41 import android.os.UserManager; 42 import android.preference.PreferenceManager; 43 import android.provider.Settings; 44 import android.telephony.CarrierConfigManager; 45 import android.telephony.ServiceState; 46 import android.telephony.SubscriptionManager; 47 import android.telephony.TelephonyManager; 48 import android.util.LocalLog; 49 import android.util.Log; 50 import android.widget.Toast; 51 52 import com.android.internal.telephony.Call; 53 import com.android.internal.telephony.CallManager; 54 import com.android.internal.telephony.IccCardConstants; 55 import com.android.internal.telephony.MmiCode; 56 import com.android.internal.telephony.Phone; 57 import com.android.internal.telephony.PhoneConstants; 58 import com.android.internal.telephony.PhoneFactory; 59 import com.android.internal.telephony.SettingsObserver; 60 import com.android.internal.telephony.TelephonyCapabilities; 61 import com.android.internal.telephony.TelephonyIntents; 62 import com.android.internal.telephony.dataconnection.DataConnectionReasons; 63 import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataDisallowedReasonType; 64 import com.android.internal.util.IndentingPrintWriter; 65 import com.android.phone.common.CallLogAsync; 66 import com.android.phone.settings.SettingsConstants; 67 import com.android.phone.vvm.CarrierVvmPackageInstalledReceiver; 68 import com.android.services.telephony.sip.SipAccountRegistry; 69 import com.android.services.telephony.sip.SipUtil; 70 71 import java.io.FileDescriptor; 72 import java.io.PrintWriter; 73 74 /** 75 * Global state for the telephony subsystem when running in the primary 76 * phone process. 77 */ 78 public class PhoneGlobals extends ContextWrapper { 79 public static final String LOG_TAG = "PhoneGlobals"; 80 81 /** 82 * Phone app-wide debug level: 83 * 0 - no debug logging 84 * 1 - normal debug logging if ro.debuggable is set (which is true in 85 * "eng" and "userdebug" builds but not "user" builds) 86 * 2 - ultra-verbose debug logging 87 * 88 * Most individual classes in the phone app have a local DBG constant, 89 * typically set to 90 * (PhoneApp.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1) 91 * or else 92 * (PhoneApp.DBG_LEVEL >= 2) 93 * depending on the desired verbosity. 94 * 95 * ***** DO NOT SUBMIT WITH DBG_LEVEL > 0 ************* 96 */ 97 public static final int DBG_LEVEL = 0; 98 99 private static final boolean DBG = 100 (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1); 101 private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2); 102 103 // Message codes; see mHandler below. 104 private static final int EVENT_SIM_NETWORK_LOCKED = 3; 105 private static final int EVENT_SIM_STATE_CHANGED = 8; 106 private static final int EVENT_DATA_ROAMING_DISCONNECTED = 10; 107 private static final int EVENT_DATA_ROAMING_OK = 11; 108 private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 12; 109 private static final int EVENT_RESTART_SIP = 13; 110 private static final int EVENT_DATA_ROAMING_SETTINGS_CHANGED = 14; 111 private static final int EVENT_MOBILE_DATA_SETTINGS_CHANGED = 15; 112 113 // The MMI codes are also used by the InCallScreen. 114 public static final int MMI_INITIATE = 51; 115 public static final int MMI_COMPLETE = 52; 116 public static final int MMI_CANCEL = 53; 117 // Don't use message codes larger than 99 here; those are reserved for 118 // the individual Activities of the Phone UI. 119 120 public static final int AIRPLANE_ON = 1; 121 public static final int AIRPLANE_OFF = 0; 122 123 /** 124 * Allowable values for the wake lock code. 125 * SLEEP means the device can be put to sleep. 126 * PARTIAL means wake the processor, but we display can be kept off. 127 * FULL means wake both the processor and the display. 128 */ 129 public enum WakeState { 130 SLEEP, 131 PARTIAL, 132 FULL 133 } 134 135 private static PhoneGlobals sMe; 136 137 // A few important fields we expose to the rest of the package 138 // directly (rather than thru set/get methods) for efficiency. 139 CallController callController; 140 CallManager mCM; 141 CallNotifier notifier; 142 CallerInfoCache callerInfoCache; 143 NotificationMgr notificationMgr; 144 public PhoneInterfaceManager phoneMgr; 145 CarrierConfigLoader configLoader; 146 147 private CallGatewayManager callGatewayManager; 148 private Phone phoneInEcm; 149 150 static boolean sVoiceCapable = true; 151 152 // TODO: Remove, no longer used. 153 CdmaPhoneCallState cdmaPhoneCallState; 154 155 // The currently-active PUK entry activity and progress dialog. 156 // Normally, these are the Emergency Dialer and the subsequent 157 // progress dialog. null if there is are no such objects in 158 // the foreground. 159 private Activity mPUKEntryActivity; 160 private ProgressDialog mPUKEntryProgressDialog; 161 162 private boolean mNoDataDueToRoaming = false; 163 164 private WakeState mWakeState = WakeState.SLEEP; 165 166 private PowerManager mPowerManager; 167 private PowerManager.WakeLock mWakeLock; 168 private PowerManager.WakeLock mPartialWakeLock; 169 private KeyguardManager mKeyguardManager; 170 171 private UpdateLock mUpdateLock; 172 173 private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 174 private final LocalLog mDataRoamingNotifLog = new LocalLog(50); 175 176 // Broadcast receiver for various intent broadcasts (see onCreate()) 177 private final BroadcastReceiver mReceiver = new PhoneAppBroadcastReceiver(); 178 // Broadcast receiver for SIP based intents (see onCreate()) 179 private final SipReceiver mSipReceiver = new SipReceiver(); 180 181 private final CarrierVvmPackageInstalledReceiver mCarrierVvmPackageInstalledReceiver = 182 new CarrierVvmPackageInstalledReceiver(); 183 184 private final SettingsObserver mSettingsObserver; 185 186 Handler mHandler = new Handler() { 187 @Override 188 public void handleMessage(Message msg) { 189 PhoneConstants.State phoneState; 190 if (VDBG) Log.v(LOG_TAG, "event=" + msg.what); 191 switch (msg.what) { 192 // TODO: This event should be handled by the lock screen, just 193 // like the "SIM missing" and "Sim locked" cases (bug 1804111). 194 case EVENT_SIM_NETWORK_LOCKED: 195 if (getCarrierConfig().getBoolean( 196 CarrierConfigManager.KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL)) { 197 // Some products don't have the concept of a "SIM network lock" 198 Log.i(LOG_TAG, "Ignoring EVENT_SIM_NETWORK_LOCKED event; " 199 + "not showing 'SIM network unlock' PIN entry screen"); 200 } else { 201 // Normal case: show the "SIM network unlock" PIN entry screen. 202 // The user won't be able to do anything else until 203 // they enter a valid SIM network PIN. 204 Log.i(LOG_TAG, "show sim depersonal panel"); 205 IccNetworkDepersonalizationPanel.showDialog(); 206 } 207 break; 208 209 case EVENT_DATA_ROAMING_DISCONNECTED: 210 notificationMgr.showDataDisconnectedRoaming(); 211 break; 212 213 case EVENT_DATA_ROAMING_OK: 214 notificationMgr.hideDataDisconnectedRoaming(); 215 break; 216 217 case MMI_COMPLETE: 218 onMMIComplete((AsyncResult) msg.obj); 219 break; 220 221 case MMI_CANCEL: 222 PhoneUtils.cancelMmiCode(mCM.getFgPhone()); 223 break; 224 225 case EVENT_SIM_STATE_CHANGED: 226 // Marks the event where the SIM goes into ready state. 227 // Right now, this is only used for the PUK-unlocking 228 // process. 229 if (msg.obj.equals(IccCardConstants.INTENT_VALUE_ICC_READY)) { 230 // when the right event is triggered and there 231 // are UI objects in the foreground, we close 232 // them to display the lock panel. 233 if (mPUKEntryActivity != null) { 234 mPUKEntryActivity.finish(); 235 mPUKEntryActivity = null; 236 } 237 if (mPUKEntryProgressDialog != null) { 238 mPUKEntryProgressDialog.dismiss(); 239 mPUKEntryProgressDialog = null; 240 } 241 } 242 break; 243 244 case EVENT_UNSOL_CDMA_INFO_RECORD: 245 //TODO: handle message here; 246 break; 247 case EVENT_RESTART_SIP: 248 // This should only run if the Phone process crashed and was restarted. We do 249 // not want this running if the device is still in the FBE encrypted state. 250 // This is the same procedure that is triggered in the SipIncomingCallReceiver 251 // upon BOOT_COMPLETED. 252 UserManager userManager = UserManager.get(sMe); 253 if (userManager != null && userManager.isUserUnlocked()) { 254 SipUtil.startSipService(); 255 } 256 break; 257 case EVENT_DATA_ROAMING_SETTINGS_CHANGED: 258 case EVENT_MOBILE_DATA_SETTINGS_CHANGED: 259 updateDataRoamingStatus(); 260 break; 261 } 262 } 263 }; 264 PhoneGlobals(Context context)265 public PhoneGlobals(Context context) { 266 super(context); 267 sMe = this; 268 mSettingsObserver = new SettingsObserver(context, mHandler); 269 } 270 onCreate()271 public void onCreate() { 272 if (VDBG) Log.v(LOG_TAG, "onCreate()..."); 273 274 ContentResolver resolver = getContentResolver(); 275 276 // Cache the "voice capable" flag. 277 // This flag currently comes from a resource (which is 278 // overrideable on a per-product basis): 279 sVoiceCapable = 280 getResources().getBoolean(com.android.internal.R.bool.config_voice_capable); 281 // ...but this might eventually become a PackageManager "system 282 // feature" instead, in which case we'd do something like: 283 // sVoiceCapable = 284 // getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS); 285 286 if (mCM == null) { 287 // Initialize the telephony framework 288 PhoneFactory.makeDefaultPhones(this); 289 290 // Start TelephonyDebugService After the default phone is created. 291 Intent intent = new Intent(this, TelephonyDebugService.class); 292 startService(intent); 293 294 mCM = CallManager.getInstance(); 295 for (Phone phone : PhoneFactory.getPhones()) { 296 mCM.registerPhone(phone); 297 } 298 299 // Create the NotificationMgr singleton, which is used to display 300 // status bar icons and control other status bar behavior. 301 notificationMgr = NotificationMgr.init(this); 302 303 // If PhoneGlobals has crashed and is being restarted, then restart. 304 mHandler.sendEmptyMessage(EVENT_RESTART_SIP); 305 306 // Create an instance of CdmaPhoneCallState and initialize it to IDLE 307 cdmaPhoneCallState = new CdmaPhoneCallState(); 308 cdmaPhoneCallState.CdmaPhoneCallStateInit(); 309 310 // before registering for phone state changes 311 mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 312 mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG); 313 // lock used to keep the processor awake, when we don't care for the display. 314 mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK 315 | PowerManager.ON_AFTER_RELEASE, LOG_TAG); 316 317 mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); 318 319 // Get UpdateLock to suppress system-update related events (e.g. dialog show-up) 320 // during phone calls. 321 mUpdateLock = new UpdateLock("phone"); 322 323 if (DBG) Log.d(LOG_TAG, "onCreate: mUpdateLock: " + mUpdateLock); 324 325 CallLogger callLogger = new CallLogger(this, new CallLogAsync()); 326 327 callGatewayManager = CallGatewayManager.getInstance(); 328 329 // Create the CallController singleton, which is the interface 330 // to the telephony layer for user-initiated telephony functionality 331 // (like making outgoing calls.) 332 callController = CallController.init(this, callLogger, callGatewayManager); 333 334 // Create the CallerInfoCache singleton, which remembers custom ring tone and 335 // send-to-voicemail settings. 336 // 337 // The asynchronous caching will start just after this call. 338 callerInfoCache = CallerInfoCache.init(this); 339 340 phoneMgr = PhoneInterfaceManager.init(this, PhoneFactory.getDefaultPhone()); 341 342 configLoader = CarrierConfigLoader.init(this); 343 344 // Create the CallNotifier singleton, which handles 345 // asynchronous events from the telephony layer (like 346 // launching the incoming-call UI when an incoming call comes 347 // in.) 348 notifier = CallNotifier.init(this); 349 350 PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED); 351 352 // register for MMI/USSD 353 mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null); 354 355 // register connection tracking to PhoneUtils 356 PhoneUtils.initializeConnectionHandler(mCM); 357 358 // Register for misc other intent broadcasts. 359 IntentFilter intentFilter = 360 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED); 361 intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 362 intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED); 363 intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); 364 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 365 intentFilter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); 366 intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 367 registerReceiver(mReceiver, intentFilter); 368 369 IntentFilter sipIntentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); 370 sipIntentFilter.addAction(SipManager.ACTION_SIP_SERVICE_UP); 371 sipIntentFilter.addAction(SipManager.ACTION_SIP_CALL_OPTION_CHANGED); 372 sipIntentFilter.addAction(SipManager.ACTION_SIP_REMOVE_PHONE); 373 registerReceiver(mSipReceiver, sipIntentFilter); 374 375 mCarrierVvmPackageInstalledReceiver.register(this); 376 377 //set the default values for the preferences in the phone. 378 PreferenceManager.setDefaultValues(this, R.xml.network_setting_fragment, false); 379 380 PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false); 381 382 // Make sure the audio mode (along with some 383 // audio-mode-related state of our own) is initialized 384 // correctly, given the current state of the phone. 385 PhoneUtils.setAudioMode(mCM); 386 } 387 388 // XXX pre-load the SimProvider so that it's ready 389 resolver.getType(Uri.parse("content://icc/adn")); 390 391 // TODO: Register for Cdma Information Records 392 // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null); 393 394 // Read HAC settings and configure audio hardware 395 if (getResources().getBoolean(R.bool.hac_enabled)) { 396 int hac = android.provider.Settings.System.getInt( 397 getContentResolver(), 398 android.provider.Settings.System.HEARING_AID, 399 0); 400 AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 401 audioManager.setParameter(SettingsConstants.HAC_KEY, 402 hac == SettingsConstants.HAC_ENABLED 403 ? SettingsConstants.HAC_VAL_ON : SettingsConstants.HAC_VAL_OFF); 404 } 405 } 406 407 /** 408 * Returns the singleton instance of the PhoneApp. 409 */ getInstance()410 public static PhoneGlobals getInstance() { 411 if (sMe == null) { 412 throw new IllegalStateException("No PhoneGlobals here!"); 413 } 414 return sMe; 415 } 416 417 /** 418 * Returns the singleton instance of the PhoneApp if running as the 419 * primary user, otherwise null. 420 */ getInstanceIfPrimary()421 static PhoneGlobals getInstanceIfPrimary() { 422 return sMe; 423 } 424 425 /** 426 * Returns the default phone. 427 * 428 * WARNING: This method should be used carefully, now that there may be multiple phones. 429 */ getPhone()430 public static Phone getPhone() { 431 return PhoneFactory.getDefaultPhone(); 432 } 433 getPhone(int subId)434 public static Phone getPhone(int subId) { 435 return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId)); 436 } 437 getCallManager()438 /* package */ CallManager getCallManager() { 439 return mCM; 440 } 441 getCarrierConfig()442 public PersistableBundle getCarrierConfig() { 443 return getCarrierConfigForSubId(SubscriptionManager.getDefaultSubscriptionId()); 444 } 445 getCarrierConfigForSubId(int subId)446 public PersistableBundle getCarrierConfigForSubId(int subId) { 447 return configLoader.getConfigForSubId(subId); 448 } 449 registerSettingsObserver()450 private void registerSettingsObserver() { 451 mSettingsObserver.unobserve(); 452 String dataRoamingSetting = Settings.Global.DATA_ROAMING; 453 String mobileDataSetting = Settings.Global.MOBILE_DATA; 454 if (TelephonyManager.getDefault().getSimCount() > 1) { 455 int subId = mDefaultDataSubId; 456 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 457 dataRoamingSetting += subId; 458 mobileDataSetting += subId; 459 } 460 } 461 462 // Listen for user data roaming setting changed event 463 mSettingsObserver.observe(Settings.Global.getUriFor(dataRoamingSetting), 464 EVENT_DATA_ROAMING_SETTINGS_CHANGED); 465 466 // Listen for mobile data setting changed event 467 mSettingsObserver.observe(Settings.Global.getUriFor(mobileDataSetting), 468 EVENT_MOBILE_DATA_SETTINGS_CHANGED); 469 } 470 471 /** 472 * Sets the activity responsible for un-PUK-blocking the device 473 * so that we may close it when we receive a positive result. 474 * mPUKEntryActivity is also used to indicate to the device that 475 * we are trying to un-PUK-lock the phone. In other words, iff 476 * it is NOT null, then we are trying to unlock and waiting for 477 * the SIM to move to READY state. 478 * 479 * @param activity is the activity to close when PUK has 480 * finished unlocking. Can be set to null to indicate the unlock 481 * or SIM READYing process is over. 482 */ setPukEntryActivity(Activity activity)483 void setPukEntryActivity(Activity activity) { 484 mPUKEntryActivity = activity; 485 } 486 getPUKEntryActivity()487 Activity getPUKEntryActivity() { 488 return mPUKEntryActivity; 489 } 490 491 /** 492 * Sets the dialog responsible for notifying the user of un-PUK- 493 * blocking - SIM READYing progress, so that we may dismiss it 494 * when we receive a positive result. 495 * 496 * @param dialog indicates the progress dialog informing the user 497 * of the state of the device. Dismissed upon completion of 498 * READYing process 499 */ setPukEntryProgressDialog(ProgressDialog dialog)500 void setPukEntryProgressDialog(ProgressDialog dialog) { 501 mPUKEntryProgressDialog = dialog; 502 } 503 504 /** 505 * Controls whether or not the screen is allowed to sleep. 506 * 507 * Once sleep is allowed (WakeState is SLEEP), it will rely on the 508 * settings for the poke lock to determine when to timeout and let 509 * the device sleep {@link PhoneGlobals#setScreenTimeout}. 510 * 511 * @param ws tells the device to how to wake. 512 */ requestWakeState(WakeState ws)513 /* package */ void requestWakeState(WakeState ws) { 514 if (VDBG) Log.d(LOG_TAG, "requestWakeState(" + ws + ")..."); 515 synchronized (this) { 516 if (mWakeState != ws) { 517 switch (ws) { 518 case PARTIAL: 519 // acquire the processor wake lock, and release the FULL 520 // lock if it is being held. 521 mPartialWakeLock.acquire(); 522 if (mWakeLock.isHeld()) { 523 mWakeLock.release(); 524 } 525 break; 526 case FULL: 527 // acquire the full wake lock, and release the PARTIAL 528 // lock if it is being held. 529 mWakeLock.acquire(); 530 if (mPartialWakeLock.isHeld()) { 531 mPartialWakeLock.release(); 532 } 533 break; 534 case SLEEP: 535 default: 536 // release both the PARTIAL and FULL locks. 537 if (mWakeLock.isHeld()) { 538 mWakeLock.release(); 539 } 540 if (mPartialWakeLock.isHeld()) { 541 mPartialWakeLock.release(); 542 } 543 break; 544 } 545 mWakeState = ws; 546 } 547 } 548 } 549 550 /** 551 * If we are not currently keeping the screen on, then poke the power 552 * manager to wake up the screen for the user activity timeout duration. 553 */ wakeUpScreen()554 /* package */ void wakeUpScreen() { 555 synchronized (this) { 556 if (mWakeState == WakeState.SLEEP) { 557 if (DBG) Log.d(LOG_TAG, "pulse screen lock"); 558 mPowerManager.wakeUp(SystemClock.uptimeMillis(), "android.phone:WAKE"); 559 } 560 } 561 } 562 563 /** 564 * Sets the wake state and screen timeout based on the current state 565 * of the phone, and the current state of the in-call UI. 566 * 567 * This method is a "UI Policy" wrapper around 568 * {@link PhoneGlobals#requestWakeState} and {@link PhoneGlobals#setScreenTimeout}. 569 * 570 * It's safe to call this method regardless of the state of the Phone 571 * (e.g. whether or not it's idle), and regardless of the state of the 572 * Phone UI (e.g. whether or not the InCallScreen is active.) 573 */ updateWakeState()574 /* package */ void updateWakeState() { 575 PhoneConstants.State state = mCM.getState(); 576 577 // True if the speakerphone is in use. (If so, we *always* use 578 // the default timeout. Since the user is obviously not holding 579 // the phone up to his/her face, we don't need to worry about 580 // false touches, and thus don't need to turn the screen off so 581 // aggressively.) 582 // Note that we need to make a fresh call to this method any 583 // time the speaker state changes. (That happens in 584 // PhoneUtils.turnOnSpeaker().) 585 boolean isSpeakerInUse = (state == PhoneConstants.State.OFFHOOK) && PhoneUtils.isSpeakerOn(this); 586 587 // TODO (bug 1440854): The screen timeout *might* also need to 588 // depend on the bluetooth state, but this isn't as clear-cut as 589 // the speaker state (since while using BT it's common for the 590 // user to put the phone straight into a pocket, in which case the 591 // timeout should probably still be short.) 592 593 // Decide whether to force the screen on or not. 594 // 595 // Force the screen to be on if the phone is ringing or dialing, 596 // or if we're displaying the "Call ended" UI for a connection in 597 // the "disconnected" state. 598 // However, if the phone is disconnected while the user is in the 599 // middle of selecting a quick response message, we should not force 600 // the screen to be on. 601 // 602 boolean isRinging = (state == PhoneConstants.State.RINGING); 603 boolean isDialing = (mCM.getFgPhone().getForegroundCall().getState() == Call.State.DIALING); 604 boolean keepScreenOn = isRinging || isDialing; 605 // keepScreenOn == true means we'll hold a full wake lock: 606 requestWakeState(keepScreenOn ? WakeState.FULL : WakeState.SLEEP); 607 } 608 getKeyguardManager()609 KeyguardManager getKeyguardManager() { 610 return mKeyguardManager; 611 } 612 onMMIComplete(AsyncResult r)613 private void onMMIComplete(AsyncResult r) { 614 if (VDBG) Log.d(LOG_TAG, "onMMIComplete()..."); 615 MmiCode mmiCode = (MmiCode) r.result; 616 PhoneUtils.displayMMIComplete(mmiCode.getPhone(), getInstance(), mmiCode, null, null); 617 } 618 initForNewRadioTechnology()619 private void initForNewRadioTechnology() { 620 if (DBG) Log.d(LOG_TAG, "initForNewRadioTechnology..."); 621 notifier.updateCallNotifierRegistrationsAfterRadioTechnologyChange(); 622 } 623 handleAirplaneModeChange(Context context, int newMode)624 private void handleAirplaneModeChange(Context context, int newMode) { 625 int cellState = Settings.Global.getInt(context.getContentResolver(), 626 Settings.Global.CELL_ON, PhoneConstants.CELL_ON_FLAG); 627 boolean isAirplaneNewlyOn = (newMode == 1); 628 switch (cellState) { 629 case PhoneConstants.CELL_OFF_FLAG: 630 // Airplane mode does not affect the cell radio if user 631 // has turned it off. 632 break; 633 case PhoneConstants.CELL_ON_FLAG: 634 maybeTurnCellOff(context, isAirplaneNewlyOn); 635 break; 636 case PhoneConstants.CELL_OFF_DUE_TO_AIRPLANE_MODE_FLAG: 637 maybeTurnCellOn(context, isAirplaneNewlyOn); 638 break; 639 } 640 } 641 642 /* 643 * Returns true if the radio must be turned off when entering airplane mode. 644 */ isCellOffInAirplaneMode(Context context)645 private boolean isCellOffInAirplaneMode(Context context) { 646 String airplaneModeRadios = Settings.Global.getString(context.getContentResolver(), 647 Settings.Global.AIRPLANE_MODE_RADIOS); 648 return airplaneModeRadios == null 649 || airplaneModeRadios.contains(Settings.Global.RADIO_CELL); 650 } 651 setRadioPowerOff(Context context)652 private void setRadioPowerOff(Context context) { 653 Log.i(LOG_TAG, "Turning radio off - airplane"); 654 Settings.Global.putInt(context.getContentResolver(), Settings.Global.CELL_ON, 655 PhoneConstants.CELL_OFF_DUE_TO_AIRPLANE_MODE_FLAG); 656 SystemProperties.set("persist.radio.airplane_mode_on", "1"); 657 Settings.Global.putInt(getContentResolver(), Settings.Global.ENABLE_CELLULAR_ON_BOOT, 0); 658 PhoneUtils.setRadioPower(false); 659 } 660 setRadioPowerOn(Context context)661 private void setRadioPowerOn(Context context) { 662 Log.i(LOG_TAG, "Turning radio on - airplane"); 663 Settings.Global.putInt(context.getContentResolver(), Settings.Global.CELL_ON, 664 PhoneConstants.CELL_ON_FLAG); 665 Settings.Global.putInt(getContentResolver(), Settings.Global.ENABLE_CELLULAR_ON_BOOT, 666 1); 667 SystemProperties.set("persist.radio.airplane_mode_on", "0"); 668 PhoneUtils.setRadioPower(true); 669 } 670 maybeTurnCellOff(Context context, boolean isAirplaneNewlyOn)671 private void maybeTurnCellOff(Context context, boolean isAirplaneNewlyOn) { 672 if (isAirplaneNewlyOn) { 673 // If we are trying to turn off the radio, make sure there are no active 674 // emergency calls. If there are, switch airplane mode back to off. 675 if (PhoneUtils.isInEmergencyCall(mCM)) { 676 // Switch airplane mode back to off. 677 ConnectivityManager.from(this).setAirplaneMode(false); 678 Toast.makeText(this, R.string.radio_off_during_emergency_call, Toast.LENGTH_LONG) 679 .show(); 680 Log.i(LOG_TAG, "Ignoring airplane mode: emergency call. Turning airplane off"); 681 } else if (isCellOffInAirplaneMode(context)) { 682 setRadioPowerOff(context); 683 } else { 684 Log.i(LOG_TAG, "Ignoring airplane mode: settings prevent cell radio power off"); 685 } 686 } 687 } 688 maybeTurnCellOn(Context context, boolean isAirplaneNewlyOn)689 private void maybeTurnCellOn(Context context, boolean isAirplaneNewlyOn) { 690 if (!isAirplaneNewlyOn) { 691 setRadioPowerOn(context); 692 } 693 } 694 695 /** 696 * Receiver for misc intent broadcasts the Phone app cares about. 697 */ 698 private class PhoneAppBroadcastReceiver extends BroadcastReceiver { 699 @Override onReceive(Context context, Intent intent)700 public void onReceive(Context context, Intent intent) { 701 String action = intent.getAction(); 702 if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 703 int airplaneMode = Settings.Global.getInt(getContentResolver(), 704 Settings.Global.AIRPLANE_MODE_ON, AIRPLANE_OFF); 705 // Treat any non-OFF values as ON. 706 if (airplaneMode != AIRPLANE_OFF) { 707 airplaneMode = AIRPLANE_ON; 708 } 709 handleAirplaneModeChange(context, airplaneMode); 710 } else if ((action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) && 711 (mPUKEntryActivity != null)) { 712 // if an attempt to un-PUK-lock the device was made, while we're 713 // receiving this state change notification, notify the handler. 714 // NOTE: This is ONLY triggered if an attempt to un-PUK-lock has 715 // been attempted. 716 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SIM_STATE_CHANGED, 717 intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE))); 718 } else if (action.equals(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED)) { 719 String newPhone = intent.getStringExtra(PhoneConstants.PHONE_NAME_KEY); 720 Log.d(LOG_TAG, "Radio technology switched. Now " + newPhone + " is active."); 721 initForNewRadioTechnology(); 722 } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) { 723 handleServiceStateChanged(intent); 724 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) { 725 int phoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY, 0); 726 phoneInEcm = PhoneFactory.getPhone(phoneId); 727 Log.d(LOG_TAG, "Emergency Callback Mode. phoneId:" + phoneId); 728 if (phoneInEcm != null) { 729 if (TelephonyCapabilities.supportsEcm(phoneInEcm)) { 730 Log.d(LOG_TAG, "Emergency Callback Mode arrived in PhoneApp."); 731 // Start Emergency Callback Mode service 732 if (intent.getBooleanExtra("phoneinECMState", false)) { 733 context.startService(new Intent(context, 734 EmergencyCallbackModeService.class)); 735 } else { 736 phoneInEcm = null; 737 } 738 } else { 739 // It doesn't make sense to get ACTION_EMERGENCY_CALLBACK_MODE_CHANGED 740 // on a device that doesn't support ECM in the first place. 741 Log.e(LOG_TAG, "Got ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, but " 742 + "ECM isn't supported for phone: " + phoneInEcm.getPhoneName()); 743 phoneInEcm = null; 744 } 745 } else { 746 Log.w(LOG_TAG, "phoneInEcm is null."); 747 } 748 } else if (action.equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) { 749 // Roaming status could be overridden by carrier config, so we need to update it. 750 if (VDBG) Log.v(LOG_TAG, "carrier config changed."); 751 updateDataRoamingStatus(); 752 } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) { 753 // We also need to pay attention when default data subscription changes. 754 if (VDBG) Log.v(LOG_TAG, "default data sub changed."); 755 mDefaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); 756 registerSettingsObserver(); 757 Phone phone = getPhone(mDefaultDataSubId); 758 if (phone != null) { 759 updateDataRoamingStatus(); 760 } 761 } 762 } 763 } 764 765 private class SipReceiver extends BroadcastReceiver { 766 767 @Override onReceive(Context context, Intent intent)768 public void onReceive(Context context, Intent intent) { 769 String action = intent.getAction(); 770 771 SipAccountRegistry sipAccountRegistry = SipAccountRegistry.getInstance(); 772 if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { 773 SipUtil.startSipService(); 774 } else if (action.equals(SipManager.ACTION_SIP_SERVICE_UP) 775 || action.equals(SipManager.ACTION_SIP_CALL_OPTION_CHANGED)) { 776 sipAccountRegistry.setup(context); 777 } else if (action.equals(SipManager.ACTION_SIP_REMOVE_PHONE)) { 778 if (DBG) { 779 Log.d(LOG_TAG, "SIP_REMOVE_PHONE " 780 + intent.getStringExtra(SipManager.EXTRA_LOCAL_URI)); 781 } 782 sipAccountRegistry.removeSipProfile(intent.getStringExtra( 783 SipManager.EXTRA_LOCAL_URI)); 784 } else { 785 if (DBG) Log.d(LOG_TAG, "onReceive, action not processed: " + action); 786 } 787 } 788 } 789 handleServiceStateChanged(Intent intent)790 private void handleServiceStateChanged(Intent intent) { 791 /** 792 * This used to handle updating EriTextWidgetProvider this routine 793 * and and listening for ACTION_SERVICE_STATE_CHANGED intents could 794 * be removed. But leaving just in case it might be needed in the near 795 * future. 796 */ 797 798 if (VDBG) Log.v(LOG_TAG, "handleServiceStateChanged"); 799 // If service just returned, start sending out the queued messages 800 Bundle extras = intent.getExtras(); 801 if (extras != null) { 802 ServiceState ss = ServiceState.newFromBundle(extras); 803 if (ss != null) { 804 int state = ss.getState(); 805 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, 806 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 807 notificationMgr.updateNetworkSelection(state, subId); 808 809 if (VDBG) { 810 Log.v(LOG_TAG, "subId=" + subId + ",mDefaultDataSubId=" 811 + mDefaultDataSubId + ",ss roaming=" + ss.getDataRoaming()); 812 } 813 if (subId == mDefaultDataSubId) { 814 updateDataRoamingStatus(); 815 } 816 } 817 } 818 } 819 820 /** 821 * When roaming, if mobile data cannot be established due to data roaming not enabled, we need 822 * to notify the user so they can enable it through settings. Vise versa if the condition 823 * changes, we need to dismiss the notification. 824 */ updateDataRoamingStatus()825 private void updateDataRoamingStatus() { 826 if (VDBG) Log.v(LOG_TAG, "updateDataRoamingStatus"); 827 Phone phone = getPhone(mDefaultDataSubId); 828 if (phone == null) { 829 Log.w(LOG_TAG, "Can't get phone with sub id = " + mDefaultDataSubId); 830 return; 831 } 832 833 DataConnectionReasons reasons = new DataConnectionReasons(); 834 boolean dataAllowed = phone.isDataAllowed(reasons); 835 mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons); 836 if (VDBG) Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons); 837 if (!mNoDataDueToRoaming 838 && !dataAllowed 839 && reasons.containsOnly(DataDisallowedReasonType.ROAMING_DISABLED)) { 840 // If the only reason of no data is data roaming disabled, then we notify the user 841 // so the user can turn on data roaming. 842 mNoDataDueToRoaming = true; 843 Log.d(LOG_TAG, "Show roaming disconnected notification"); 844 mDataRoamingNotifLog.log("Show"); 845 mHandler.sendEmptyMessage(EVENT_DATA_ROAMING_DISCONNECTED); 846 } else if (mNoDataDueToRoaming && (dataAllowed 847 || !reasons.containsOnly(DataDisallowedReasonType.ROAMING_DISABLED))) { 848 // Otherwise dismiss the notification we showed earlier. 849 mNoDataDueToRoaming = false; 850 Log.d(LOG_TAG, "Dismiss roaming disconnected notification"); 851 mDataRoamingNotifLog.log("Hide. data allowed=" + dataAllowed + ", reasons=" + reasons); 852 mHandler.sendEmptyMessage(EVENT_DATA_ROAMING_OK); 853 } 854 } 855 getPhoneInEcm()856 public Phone getPhoneInEcm() { 857 return phoneInEcm; 858 } 859 860 /** 861 * Triggers a refresh of the message waiting (voicemail) indicator. 862 * 863 * @param subId the subscription id we should refresh the notification for. 864 */ refreshMwiIndicator(int subId)865 public void refreshMwiIndicator(int subId) { 866 notificationMgr.refreshMwi(subId); 867 } 868 869 /** 870 * Dismisses the message waiting (voicemail) indicator. 871 * 872 * @param subId the subscription id we should dismiss the notification for. 873 */ clearMwiIndicator(int subId)874 public void clearMwiIndicator(int subId) { 875 // Setting voiceMessageCount to 0 will remove the current notification and clear the system 876 // cached value. 877 Phone phone = getPhone(subId); 878 if (phone == null) { 879 Log.w(LOG_TAG, "clearMwiIndicator on null phone, subId:" + subId); 880 } else { 881 phone.setVoiceMessageCount(0); 882 } 883 } 884 885 /** 886 * Enables or disables the visual voicemail check for message waiting indicator. Default value 887 * is true. MWI is the traditional voicemail notification which should be suppressed if visual 888 * voicemail is active. {@link NotificationMgr#updateMwi(int, boolean, boolean)} currently 889 * checks the {@link android.provider.VoicemailContract.Status#CONFIGURATION_STATE} to suppress 890 * the MWI, but there are several issues. b/31229016 is a bug that when the device boots the 891 * configuration state will be cleared and the MWI for voicemail that arrives when the device 892 * is offline will be cleared, even if the account cannot be activated. A full solution will be 893 * adding a setMwiEnabled() method and stop checking the configuration state, but that is too 894 * risky at this moment. This is a temporary workaround to shut down the configuration state 895 * check if visual voicemail cannot be activated. 896 * <p>TODO(twyen): implement the setMwiEnabled() mentioned above. 897 * 898 * @param subId the account to set the enabled state 899 */ setShouldCheckVisualVoicemailConfigurationForMwi(int subId, boolean enabled)900 public void setShouldCheckVisualVoicemailConfigurationForMwi(int subId, boolean enabled) { 901 notificationMgr.setShouldCheckVisualVoicemailConfigurationForMwi(subId, enabled); 902 } 903 904 /** 905 * Dump the state of the object, add calls to other objects as desired. 906 * 907 * @param fd File descriptor 908 * @param printWriter Print writer 909 * @param args Arguments 910 */ dump(FileDescriptor fd, PrintWriter printWriter, String[] args)911 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 912 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 913 pw.println("------- PhoneGlobals -------"); 914 pw.increaseIndent(); 915 pw.println("mNoDataDueToRoaming=" + mNoDataDueToRoaming); 916 pw.println("mDefaultDataSubId=" + mDefaultDataSubId); 917 pw.println("mDataRoamingNotifLog:"); 918 pw.increaseIndent(); 919 mDataRoamingNotifLog.dump(fd, pw, args); 920 pw.decreaseIndent(); 921 pw.decreaseIndent(); 922 pw.println("------- End PhoneGlobals -------"); 923 } 924 } 925