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