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.annotation.IntDef; 20 import android.app.Activity; 21 import android.app.KeyguardManager; 22 import android.app.ProgressDialog; 23 import android.content.BroadcastReceiver; 24 import android.content.ContentResolver; 25 import android.content.Context; 26 import android.content.ContextWrapper; 27 import android.content.Intent; 28 import android.content.IntentFilter; 29 import android.content.pm.PackageManager; 30 import android.content.res.XmlResourceParser; 31 import android.media.AudioManager; 32 import android.net.ConnectivityManager; 33 import android.net.Uri; 34 import android.net.sip.SipManager; 35 import android.os.AsyncResult; 36 import android.os.Bundle; 37 import android.os.Handler; 38 import android.os.Message; 39 import android.os.PersistableBundle; 40 import android.os.PowerManager; 41 import android.os.SystemProperties; 42 import android.os.UserManager; 43 import android.preference.PreferenceManager; 44 import android.provider.Settings; 45 import android.sysprop.TelephonyProperties; 46 import android.telecom.TelecomManager; 47 import android.telephony.AnomalyReporter; 48 import android.telephony.CarrierConfigManager; 49 import android.telephony.ServiceState; 50 import android.telephony.SubscriptionInfo; 51 import android.telephony.SubscriptionManager; 52 import android.telephony.TelephonyLocalConnection; 53 import android.telephony.TelephonyManager; 54 import android.telephony.data.ApnSetting; 55 import android.util.LocalLog; 56 import android.util.Log; 57 import android.widget.Toast; 58 59 import com.android.ims.ImsFeatureBinderRepository; 60 import com.android.internal.os.BinderCallsStats; 61 import com.android.internal.telephony.CallManager; 62 import com.android.internal.telephony.IccCardConstants; 63 import com.android.internal.telephony.MmiCode; 64 import com.android.internal.telephony.Phone; 65 import com.android.internal.telephony.PhoneConstants; 66 import com.android.internal.telephony.PhoneFactory; 67 import com.android.internal.telephony.SettingsObserver; 68 import com.android.internal.telephony.TelephonyCapabilities; 69 import com.android.internal.telephony.TelephonyComponentFactory; 70 import com.android.internal.telephony.TelephonyIntents; 71 import com.android.internal.telephony.dataconnection.DataConnectionReasons; 72 import com.android.internal.telephony.dataconnection.DataConnectionReasons.DataDisallowedReasonType; 73 import com.android.internal.telephony.ims.ImsResolver; 74 import com.android.internal.telephony.imsphone.ImsPhone; 75 import com.android.internal.telephony.imsphone.ImsPhoneCallTracker; 76 import com.android.internal.telephony.uicc.UiccCard; 77 import com.android.internal.telephony.uicc.UiccProfile; 78 import com.android.internal.util.IndentingPrintWriter; 79 import com.android.phone.settings.SettingsConstants; 80 import com.android.phone.vvm.CarrierVvmPackageInstalledReceiver; 81 import com.android.services.telephony.rcs.TelephonyRcsService; 82 import com.android.services.telephony.sip.SipAccountRegistry; 83 import com.android.services.telephony.sip.SipUtil; 84 85 import java.io.FileDescriptor; 86 import java.io.PrintWriter; 87 import java.lang.annotation.Retention; 88 import java.lang.annotation.RetentionPolicy; 89 import java.util.List; 90 91 /** 92 * Global state for the telephony subsystem when running in the primary 93 * phone process. 94 */ 95 public class PhoneGlobals extends ContextWrapper { 96 public static final String LOG_TAG = "PhoneGlobals"; 97 98 /** 99 * Phone app-wide debug level: 100 * 0 - no debug logging 101 * 1 - normal debug logging if ro.debuggable is set (which is true in 102 * "eng" and "userdebug" builds but not "user" builds) 103 * 2 - ultra-verbose debug logging 104 * 105 * Most individual classes in the phone app have a local DBG constant, 106 * typically set to 107 * (PhoneApp.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1) 108 * or else 109 * (PhoneApp.DBG_LEVEL >= 2) 110 * depending on the desired verbosity. 111 * 112 * ***** DO NOT SUBMIT WITH DBG_LEVEL > 0 ************* 113 */ 114 public static final int DBG_LEVEL = 0; 115 116 private static final boolean DBG = 117 (PhoneGlobals.DBG_LEVEL >= 1) && (SystemProperties.getInt("ro.debuggable", 0) == 1); 118 private static final boolean VDBG = (PhoneGlobals.DBG_LEVEL >= 2); 119 120 // Message codes; see mHandler below. 121 private static final int EVENT_SIM_NETWORK_LOCKED = 3; 122 private static final int EVENT_SIM_STATE_CHANGED = 8; 123 private static final int EVENT_DATA_ROAMING_DISCONNECTED = 10; 124 private static final int EVENT_DATA_ROAMING_CONNECTED = 11; 125 private static final int EVENT_DATA_ROAMING_OK = 12; 126 private static final int EVENT_UNSOL_CDMA_INFO_RECORD = 13; 127 private static final int EVENT_RESTART_SIP = 14; 128 private static final int EVENT_DATA_ROAMING_SETTINGS_CHANGED = 15; 129 private static final int EVENT_MOBILE_DATA_SETTINGS_CHANGED = 16; 130 private static final int EVENT_CARRIER_CONFIG_CHANGED = 17; 131 132 // The MMI codes are also used by the InCallScreen. 133 public static final int MMI_INITIATE = 51; 134 public static final int MMI_COMPLETE = 52; 135 public static final int MMI_CANCEL = 53; 136 // Don't use message codes larger than 99 here; those are reserved for 137 // the individual Activities of the Phone UI. 138 139 public static final int AIRPLANE_ON = 1; 140 public static final int AIRPLANE_OFF = 0; 141 142 /** 143 * Allowable values for the wake lock code. 144 * SLEEP means the device can be put to sleep. 145 * PARTIAL means wake the processor, but we display can be kept off. 146 * FULL means wake both the processor and the display. 147 */ 148 public enum WakeState { 149 SLEEP, 150 PARTIAL, 151 FULL 152 } 153 154 private static PhoneGlobals sMe; 155 156 CallManager mCM; 157 CallNotifier notifier; 158 CallerInfoCache callerInfoCache; 159 NotificationMgr notificationMgr; 160 TelephonyRcsService mTelephonyRcsService; 161 public PhoneInterfaceManager phoneMgr; 162 public ImsRcsController imsRcsController; 163 CarrierConfigLoader configLoader; 164 165 private Phone phoneInEcm; 166 167 static boolean sVoiceCapable = true; 168 169 // TODO: Remove, no longer used. 170 CdmaPhoneCallState cdmaPhoneCallState; 171 172 // The currently-active PUK entry activity and progress dialog. 173 // Normally, these are the Emergency Dialer and the subsequent 174 // progress dialog. null if there is are no such objects in 175 // the foreground. 176 private Activity mPUKEntryActivity; 177 private ProgressDialog mPUKEntryProgressDialog; 178 179 /** @hide */ 180 @Retention(RetentionPolicy.SOURCE) 181 @IntDef(prefix = {"ROAMING_NOTIFICATION_"}, 182 value = { 183 ROAMING_NOTIFICATION_NO_NOTIFICATION, 184 ROAMING_NOTIFICATION_CONNECTED, 185 ROAMING_NOTIFICATION_DISCONNECTED}) 186 public @interface RoamingNotification {} 187 188 private static final int ROAMING_NOTIFICATION_NO_NOTIFICATION = 0; 189 private static final int ROAMING_NOTIFICATION_CONNECTED = 1; 190 private static final int ROAMING_NOTIFICATION_DISCONNECTED = 2; 191 192 @RoamingNotification 193 private int mPrevRoamingNotification = ROAMING_NOTIFICATION_NO_NOTIFICATION; 194 195 private WakeState mWakeState = WakeState.SLEEP; 196 197 private PowerManager mPowerManager; 198 private PowerManager.WakeLock mWakeLock; 199 private PowerManager.WakeLock mPartialWakeLock; 200 private KeyguardManager mKeyguardManager; 201 202 private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 203 private final LocalLog mDataRoamingNotifLog = new LocalLog(50); 204 205 // Broadcast receiver for various intent broadcasts (see onCreate()) 206 private final BroadcastReceiver mReceiver = new PhoneAppBroadcastReceiver(); 207 // Broadcast receiver for SIP based intents (see onCreate()) 208 private final SipReceiver mSipReceiver = new SipReceiver(); 209 210 private final CarrierVvmPackageInstalledReceiver mCarrierVvmPackageInstalledReceiver = 211 new CarrierVvmPackageInstalledReceiver(); 212 213 private final SettingsObserver mSettingsObserver; 214 private BinderCallsStats.SettingsObserver mBinderCallsSettingsObserver; 215 216 private static class EventSimStateChangedBag { 217 final int mPhoneId; 218 final String mIccStatus; 219 EventSimStateChangedBag(int phoneId, String iccStatus)220 EventSimStateChangedBag(int phoneId, String iccStatus) { 221 mPhoneId = phoneId; 222 mIccStatus = iccStatus; 223 } 224 } 225 226 // Some carrier config settings disable the network lock screen, so we call handleSimLock 227 // when either SIM_LOCK or CARRIER_CONFIG changes so that no matter which one happens first, 228 // we still do the right thing handleSimLock(int subType, Phone phone)229 private void handleSimLock(int subType, Phone phone) { 230 PersistableBundle cc = getCarrierConfigForSubId(phone.getSubId()); 231 if (!CarrierConfigManager.isConfigForIdentifiedCarrier(cc)) { 232 // If we only have the default carrier config just return, to avoid popping up the 233 // the SIM lock screen when it's disabled by the carrier. 234 Log.i(LOG_TAG, "Not showing 'SIM network unlock' screen. Carrier config not loaded"); 235 return; 236 } 237 if (cc.getBoolean(CarrierConfigManager.KEY_IGNORE_SIM_NETWORK_LOCKED_EVENTS_BOOL)) { 238 // Some products don't have the concept of a "SIM network lock" 239 Log.i(LOG_TAG, "Not showing 'SIM network unlock' screen. Disabled by carrier config"); 240 return; 241 } 242 243 // if passed in subType is unknown, retrieve it here. 244 if (subType == -1) { 245 final UiccCard uiccCard = phone.getUiccCard(); 246 if (uiccCard == null) { 247 Log.e(LOG_TAG, 248 "handleSimLock: uiccCard for phone " + phone.getPhoneId() + " is null"); 249 return; 250 } 251 final UiccProfile uiccProfile = uiccCard.getUiccProfile(); 252 if (uiccProfile == null) { 253 Log.e(LOG_TAG, 254 "handleSimLock: uiccProfile for phone " + phone.getPhoneId() + " is null"); 255 return; 256 } 257 subType = uiccProfile.getApplication( 258 uiccProfile.mCurrentAppType).getPersoSubState().ordinal(); 259 } 260 // Normal case: show the "SIM network unlock" PIN entry screen. 261 // The user won't be able to do anything else until 262 // they enter a valid SIM network PIN. 263 Log.i(LOG_TAG, "show sim depersonal panel"); 264 IccNetworkDepersonalizationPanel.showDialog(phone, subType); 265 } 266 isSimLocked(Phone phone)267 private boolean isSimLocked(Phone phone) { 268 TelephonyManager tm = getSystemService(TelephonyManager.class); 269 return tm.createForSubscriptionId(phone.getSubId()).getSimState() 270 == TelephonyManager.SIM_STATE_NETWORK_LOCKED; 271 } 272 273 Handler mHandler = new Handler() { 274 @Override 275 public void handleMessage(Message msg) { 276 PhoneConstants.State phoneState; 277 if (VDBG) Log.v(LOG_TAG, "event=" + msg.what); 278 switch (msg.what) { 279 // TODO: This event should be handled by the lock screen, just 280 // like the "SIM missing" and "Sim locked" cases (bug 1804111). 281 case EVENT_SIM_NETWORK_LOCKED: 282 int subType = (Integer) ((AsyncResult) msg.obj).result; 283 Phone phone = (Phone) ((AsyncResult) msg.obj).userObj; 284 handleSimLock(subType, phone); 285 break; 286 287 case EVENT_DATA_ROAMING_DISCONNECTED: 288 notificationMgr.showDataRoamingNotification(msg.arg1, false); 289 break; 290 291 case EVENT_DATA_ROAMING_CONNECTED: 292 notificationMgr.showDataRoamingNotification(msg.arg1, true); 293 break; 294 295 case EVENT_DATA_ROAMING_OK: 296 notificationMgr.hideDataRoamingNotification(); 297 break; 298 299 case MMI_COMPLETE: 300 onMMIComplete((AsyncResult) msg.obj); 301 break; 302 303 case MMI_CANCEL: 304 PhoneUtils.cancelMmiCode(mCM.getFgPhone()); 305 break; 306 307 case EVENT_SIM_STATE_CHANGED: 308 // Marks the event where the SIM goes into ready state. 309 // Right now, this is only used for the PUK-unlocking 310 // process. 311 EventSimStateChangedBag bag = (EventSimStateChangedBag)msg.obj; 312 if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(bag.mIccStatus) 313 || IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(bag.mIccStatus) 314 || IccCardConstants.INTENT_VALUE_ICC_NOT_READY.equals(bag.mIccStatus) 315 || IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(bag.mIccStatus)) { 316 // when the right event is triggered and there 317 // are UI objects in the foreground, we close 318 // them to display the lock panel. 319 if (mPUKEntryActivity != null) { 320 Log.i(LOG_TAG, "Dismiss puk entry activity"); 321 mPUKEntryActivity.finish(); 322 mPUKEntryActivity = null; 323 } 324 if (mPUKEntryProgressDialog != null) { 325 Log.i(LOG_TAG, "Dismiss puk progress dialog"); 326 mPUKEntryProgressDialog.dismiss(); 327 mPUKEntryProgressDialog = null; 328 } 329 Log.i(LOG_TAG, "Dismissing depersonal panel" + (bag.mIccStatus)); 330 IccNetworkDepersonalizationPanel.dialogDismiss(bag.mPhoneId); 331 } 332 break; 333 334 case EVENT_UNSOL_CDMA_INFO_RECORD: 335 //TODO: handle message here; 336 break; 337 case EVENT_RESTART_SIP: 338 // This should only run if the Phone process crashed and was restarted. We do 339 // not want this running if the device is still in the FBE encrypted state. 340 // This is the same procedure that is triggered in the SipIncomingCallReceiver 341 // upon BOOT_COMPLETED. 342 UserManager userManager = 343 (UserManager) sMe.getSystemService(Context.USER_SERVICE); 344 if (userManager != null && userManager.isUserUnlocked()) { 345 SipUtil.startSipService(); 346 } 347 break; 348 case EVENT_DATA_ROAMING_SETTINGS_CHANGED: 349 case EVENT_MOBILE_DATA_SETTINGS_CHANGED: 350 updateDataRoamingStatus(); 351 break; 352 case EVENT_CARRIER_CONFIG_CHANGED: 353 int subId = (Integer) msg.obj; 354 // The voicemail number could be overridden by carrier config, so need to 355 // refresh the message waiting (voicemail) indicator. 356 refreshMwiIndicator(subId); 357 phone = getPhone(subId); 358 if (phone != null && isSimLocked(phone)) { 359 // pass in subType=-1 so handleSimLock can find the actual subType if 360 // needed. This is safe as valid values for subType are >= 0 361 handleSimLock(-1, phone); 362 } 363 break; 364 } 365 } 366 }; 367 PhoneGlobals(Context context)368 public PhoneGlobals(Context context) { 369 super(context); 370 sMe = this; 371 mSettingsObserver = new SettingsObserver(context, mHandler); 372 } 373 onCreate()374 public void onCreate() { 375 if (VDBG) Log.v(LOG_TAG, "onCreate()..."); 376 377 ContentResolver resolver = getContentResolver(); 378 379 // Initialize the shim from frameworks/opt/telephony into packages/services/Telephony. 380 TelephonyLocalConnection.setInstance(new LocalConnectionImpl(this)); 381 382 // Cache the "voice capable" flag. 383 // This flag currently comes from a resource (which is 384 // overrideable on a per-product basis): 385 sVoiceCapable = ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE)) 386 .isVoiceCapable(); 387 // ...but this might eventually become a PackageManager "system 388 // feature" instead, in which case we'd do something like: 389 // sVoiceCapable = 390 // getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS); 391 392 if (mCM == null) { 393 // Initialize AnomalyReporter early so that it can be used 394 AnomalyReporter.initialize(this); 395 396 // Inject telephony component factory if configured using other jars. 397 XmlResourceParser parser = getResources().getXml(R.xml.telephony_injection); 398 TelephonyComponentFactory.getInstance().injectTheComponentFactory(parser); 399 // Initialize the telephony framework 400 PhoneFactory.makeDefaultPhones(this); 401 402 // Only bring up ImsResolver if the device supports having an IMS stack. 403 if (getPackageManager().hasSystemFeature( 404 PackageManager.FEATURE_TELEPHONY_IMS)) { 405 // Get the package name of the default IMS implementation. 406 String defaultImsMmtelPackage = getResources().getString( 407 R.string.config_ims_mmtel_package); 408 String defaultImsRcsPackage = getResources().getString( 409 R.string.config_ims_rcs_package); 410 ImsResolver.make(this, defaultImsMmtelPackage, 411 defaultImsRcsPackage, PhoneFactory.getPhones().length, 412 new ImsFeatureBinderRepository()); 413 ImsResolver.getInstance().initialize(); 414 415 // With the IMS phone created, load static config.xml values from the phone process 416 // so that it can be provided to the ImsPhoneCallTracker. 417 for (Phone p : PhoneFactory.getPhones()) { 418 Phone imsPhone = p.getImsPhone(); 419 if (imsPhone != null && imsPhone instanceof ImsPhone) { 420 ImsPhone theImsPhone = (ImsPhone) imsPhone; 421 if (theImsPhone.getCallTracker() instanceof ImsPhoneCallTracker) { 422 ImsPhoneCallTracker ict = (ImsPhoneCallTracker) 423 theImsPhone.getCallTracker(); 424 425 ImsPhoneCallTracker.Config config = new ImsPhoneCallTracker.Config(); 426 config.isD2DCommunicationSupported = getResources().getBoolean( 427 R.bool.config_use_device_to_device_communication); 428 ict.setConfig(config); 429 } 430 } 431 } 432 RcsProvisioningMonitor.make(this); 433 } 434 435 // Start TelephonyDebugService After the default phone is created. 436 Intent intent = new Intent(this, TelephonyDebugService.class); 437 startService(intent); 438 439 mCM = CallManager.getInstance(); 440 441 // Create the NotificationMgr singleton, which is used to display 442 // status bar icons and control other status bar behavior. 443 notificationMgr = NotificationMgr.init(this); 444 445 // If PhoneGlobals has crashed and is being restarted, then restart. 446 mHandler.sendEmptyMessage(EVENT_RESTART_SIP); 447 448 // Create an instance of CdmaPhoneCallState and initialize it to IDLE 449 cdmaPhoneCallState = new CdmaPhoneCallState(); 450 cdmaPhoneCallState.CdmaPhoneCallStateInit(); 451 452 // before registering for phone state changes 453 mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE); 454 mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG); 455 // lock used to keep the processor awake, when we don't care for the display. 456 mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK 457 | PowerManager.ON_AFTER_RELEASE, LOG_TAG); 458 459 mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE); 460 461 // Create the CallerInfoCache singleton, which remembers custom ring tone and 462 // send-to-voicemail settings. 463 // 464 // The asynchronous caching will start just after this call. 465 callerInfoCache = CallerInfoCache.init(this); 466 467 phoneMgr = PhoneInterfaceManager.init(this); 468 469 imsRcsController = ImsRcsController.init(this); 470 471 if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS)) { 472 mTelephonyRcsService = new TelephonyRcsService(this, 473 PhoneFactory.getPhones().length); 474 mTelephonyRcsService.initialize(); 475 imsRcsController.setRcsService(mTelephonyRcsService); 476 } 477 478 configLoader = CarrierConfigLoader.init(this); 479 480 // Create the CallNotifier singleton, which handles 481 // asynchronous events from the telephony layer (like 482 // launching the incoming-call UI when an incoming call comes 483 // in.) 484 notifier = CallNotifier.init(this); 485 486 PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED); 487 488 // register for MMI/USSD 489 mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null); 490 491 // Initialize cell status using current airplane mode. 492 handleAirplaneModeChange(this, Settings.Global.getInt(getContentResolver(), 493 Settings.Global.AIRPLANE_MODE_ON, AIRPLANE_OFF)); 494 495 // Register for misc other intent broadcasts. 496 IntentFilter intentFilter = 497 new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED); 498 intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 499 intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED); 500 intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED); 501 intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 502 intentFilter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED); 503 intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 504 registerReceiver(mReceiver, intentFilter); 505 506 IntentFilter sipIntentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED); 507 sipIntentFilter.addAction(SipManager.ACTION_SIP_SERVICE_UP); 508 sipIntentFilter.addAction(SipManager.ACTION_SIP_CALL_OPTION_CHANGED); 509 sipIntentFilter.addAction(SipManager.ACTION_SIP_REMOVE_PROFILE); 510 registerReceiver(mSipReceiver, sipIntentFilter); 511 512 mCarrierVvmPackageInstalledReceiver.register(this); 513 514 //set the default values for the preferences in the phone. 515 PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false); 516 } 517 518 // XXX pre-load the SimProvider so that it's ready 519 resolver.getType(Uri.parse("content://icc/adn")); 520 521 // TODO: Register for Cdma Information Records 522 // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null); 523 524 // Read HAC settings and configure audio hardware 525 if (getResources().getBoolean(R.bool.hac_enabled)) { 526 int hac = android.provider.Settings.System.getInt( 527 getContentResolver(), 528 android.provider.Settings.System.HEARING_AID, 529 0); 530 AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 531 audioManager.setParameters( 532 SettingsConstants.HAC_KEY + "=" + (hac == SettingsConstants.HAC_ENABLED 533 ? SettingsConstants.HAC_VAL_ON : SettingsConstants.HAC_VAL_OFF)); 534 } 535 536 // Start tracking Binder latency for the phone process. 537 mBinderCallsSettingsObserver = new BinderCallsStats.SettingsObserver( 538 getApplicationContext(), 539 new BinderCallsStats( 540 new BinderCallsStats.Injector(), 541 com.android.internal.os.BinderLatencyProto.Dims.TELEPHONY)); 542 } 543 544 /** 545 * Returns the singleton instance of the PhoneApp. 546 */ getInstance()547 public static PhoneGlobals getInstance() { 548 if (sMe == null) { 549 throw new IllegalStateException("No PhoneGlobals here!"); 550 } 551 return sMe; 552 } 553 554 /** 555 * Returns the default phone. 556 * 557 * WARNING: This method should be used carefully, now that there may be multiple phones. 558 */ getPhone()559 public static Phone getPhone() { 560 return PhoneFactory.getDefaultPhone(); 561 } 562 getPhone(int subId)563 public static Phone getPhone(int subId) { 564 return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId)); 565 } 566 getCallManager()567 /* package */ CallManager getCallManager() { 568 return mCM; 569 } 570 getCarrierConfig()571 public PersistableBundle getCarrierConfig() { 572 return getCarrierConfigForSubId(SubscriptionManager.getDefaultSubscriptionId()); 573 } 574 getCarrierConfigForSubId(int subId)575 public PersistableBundle getCarrierConfigForSubId(int subId) { 576 return configLoader.getConfigForSubIdWithFeature(subId, getOpPackageName(), 577 getAttributionTag()); 578 } 579 registerSettingsObserver()580 private void registerSettingsObserver() { 581 mSettingsObserver.unobserve(); 582 String dataRoamingSetting = Settings.Global.DATA_ROAMING; 583 String mobileDataSetting = Settings.Global.MOBILE_DATA; 584 if (TelephonyManager.getDefault().getSimCount() > 1) { 585 int subId = mDefaultDataSubId; 586 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 587 dataRoamingSetting += subId; 588 mobileDataSetting += subId; 589 } 590 } 591 592 // Listen for user data roaming setting changed event 593 mSettingsObserver.observe(Settings.Global.getUriFor(dataRoamingSetting), 594 EVENT_DATA_ROAMING_SETTINGS_CHANGED); 595 596 // Listen for mobile data setting changed event 597 mSettingsObserver.observe(Settings.Global.getUriFor(mobileDataSetting), 598 EVENT_MOBILE_DATA_SETTINGS_CHANGED); 599 } 600 601 /** 602 * Sets the activity responsible for un-PUK-blocking the device 603 * so that we may close it when we receive a positive result. 604 * mPUKEntryActivity is also used to indicate to the device that 605 * we are trying to un-PUK-lock the phone. In other words, iff 606 * it is NOT null, then we are trying to unlock and waiting for 607 * the SIM to move to READY state. 608 * 609 * @param activity is the activity to close when PUK has 610 * finished unlocking. Can be set to null to indicate the unlock 611 * or SIM READYing process is over. 612 */ setPukEntryActivity(Activity activity)613 void setPukEntryActivity(Activity activity) { 614 Log.i(LOG_TAG, "setPukEntryActivity - set to " + (activity == null ? "null" : "activity")); 615 mPUKEntryActivity = activity; 616 } 617 getPUKEntryActivity()618 Activity getPUKEntryActivity() { 619 return mPUKEntryActivity; 620 } 621 622 /** 623 * Sets the dialog responsible for notifying the user of un-PUK- 624 * blocking - SIM READYing progress, so that we may dismiss it 625 * when we receive a positive result. 626 * 627 * @param dialog indicates the progress dialog informing the user 628 * of the state of the device. Dismissed upon completion of 629 * READYing process 630 */ setPukEntryProgressDialog(ProgressDialog dialog)631 void setPukEntryProgressDialog(ProgressDialog dialog) { 632 Log.i(LOG_TAG, "setPukEntryProgressDialog - set to " 633 + (dialog == null ? "null" : "activity")); 634 mPUKEntryProgressDialog = dialog; 635 } 636 getKeyguardManager()637 KeyguardManager getKeyguardManager() { 638 return mKeyguardManager; 639 } 640 onMMIComplete(AsyncResult r)641 private void onMMIComplete(AsyncResult r) { 642 if (VDBG) Log.d(LOG_TAG, "onMMIComplete()..."); 643 MmiCode mmiCode = (MmiCode) r.result; 644 PhoneUtils.displayMMIComplete(mmiCode.getPhone(), getInstance(), mmiCode, null, null); 645 } 646 initForNewRadioTechnology()647 private void initForNewRadioTechnology() { 648 if (DBG) Log.d(LOG_TAG, "initForNewRadioTechnology..."); 649 notifier.updateCallNotifierRegistrationsAfterRadioTechnologyChange(); 650 } 651 handleAirplaneModeChange(Context context, int newMode)652 private void handleAirplaneModeChange(Context context, int newMode) { 653 int cellState = Settings.Global.getInt(context.getContentResolver(), 654 Settings.Global.CELL_ON, PhoneConstants.CELL_ON_FLAG); 655 boolean isAirplaneNewlyOn = (newMode == 1); 656 switch (cellState) { 657 case PhoneConstants.CELL_OFF_FLAG: 658 // Airplane mode does not affect the cell radio if user 659 // has turned it off. 660 break; 661 case PhoneConstants.CELL_ON_FLAG: 662 maybeTurnCellOff(context, isAirplaneNewlyOn); 663 break; 664 case PhoneConstants.CELL_OFF_DUE_TO_AIRPLANE_MODE_FLAG: 665 maybeTurnCellOn(context, isAirplaneNewlyOn); 666 break; 667 } 668 for (Phone phone : PhoneFactory.getPhones()) { 669 phone.getServiceStateTracker().onAirplaneModeChanged(isAirplaneNewlyOn); 670 } 671 } 672 673 /* 674 * Returns true if the radio must be turned off when entering airplane mode. 675 */ isCellOffInAirplaneMode(Context context)676 private boolean isCellOffInAirplaneMode(Context context) { 677 String airplaneModeRadios = Settings.Global.getString(context.getContentResolver(), 678 Settings.Global.AIRPLANE_MODE_RADIOS); 679 return airplaneModeRadios == null 680 || airplaneModeRadios.contains(Settings.Global.RADIO_CELL); 681 } 682 setRadioPowerOff(Context context)683 private void setRadioPowerOff(Context context) { 684 Log.i(LOG_TAG, "Turning radio off - airplane"); 685 Settings.Global.putInt(context.getContentResolver(), Settings.Global.CELL_ON, 686 PhoneConstants.CELL_OFF_DUE_TO_AIRPLANE_MODE_FLAG); 687 TelephonyProperties.airplane_mode_on(true); // true means int value 1 688 Settings.Global.putInt(getContentResolver(), Settings.Global.ENABLE_CELLULAR_ON_BOOT, 0); 689 PhoneUtils.setRadioPower(false); 690 } 691 setRadioPowerOn(Context context)692 private void setRadioPowerOn(Context context) { 693 Log.i(LOG_TAG, "Turning radio on - airplane"); 694 Settings.Global.putInt(context.getContentResolver(), Settings.Global.CELL_ON, 695 PhoneConstants.CELL_ON_FLAG); 696 Settings.Global.putInt(getContentResolver(), Settings.Global.ENABLE_CELLULAR_ON_BOOT, 697 1); 698 TelephonyProperties.airplane_mode_on(false); // false means int value 0 699 PhoneUtils.setRadioPower(true); 700 } 701 maybeTurnCellOff(Context context, boolean isAirplaneNewlyOn)702 private void maybeTurnCellOff(Context context, boolean isAirplaneNewlyOn) { 703 if (isAirplaneNewlyOn) { 704 // If we are trying to turn off the radio, make sure there are no active 705 // emergency calls. If there are, switch airplane mode back to off. 706 TelecomManager tm = (TelecomManager) context.getSystemService(TELECOM_SERVICE); 707 708 if (tm != null && tm.isInEmergencyCall()) { 709 // Switch airplane mode back to off. 710 ConnectivityManager cm = 711 (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE); 712 cm.setAirplaneMode(false); 713 Toast.makeText(this, R.string.radio_off_during_emergency_call, Toast.LENGTH_LONG) 714 .show(); 715 Log.i(LOG_TAG, "Ignoring airplane mode: emergency call. Turning airplane off"); 716 } else if (isCellOffInAirplaneMode(context)) { 717 setRadioPowerOff(context); 718 } else { 719 Log.i(LOG_TAG, "Ignoring airplane mode: settings prevent cell radio power off"); 720 } 721 } 722 } 723 maybeTurnCellOn(Context context, boolean isAirplaneNewlyOn)724 private void maybeTurnCellOn(Context context, boolean isAirplaneNewlyOn) { 725 if (!isAirplaneNewlyOn) { 726 setRadioPowerOn(context); 727 } 728 } 729 730 /** 731 * Receiver for misc intent broadcasts the Phone app cares about. 732 */ 733 private class PhoneAppBroadcastReceiver extends BroadcastReceiver { 734 @Override onReceive(Context context, Intent intent)735 public void onReceive(Context context, Intent intent) { 736 String action = intent.getAction(); 737 if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) { 738 int airplaneMode = Settings.Global.getInt(getContentResolver(), 739 Settings.Global.AIRPLANE_MODE_ON, AIRPLANE_OFF); 740 // Treat any non-OFF values as ON. 741 if (airplaneMode != AIRPLANE_OFF) { 742 airplaneMode = AIRPLANE_ON; 743 } 744 handleAirplaneModeChange(context, airplaneMode); 745 } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) { 746 // re-register as it may be a new IccCard 747 int phoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY, 748 SubscriptionManager.INVALID_PHONE_INDEX); 749 if (SubscriptionManager.isValidPhoneId(phoneId)) { 750 PhoneUtils.unregisterIccStatus(mHandler, phoneId); 751 PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED, phoneId); 752 } 753 String iccStatus = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE); 754 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SIM_STATE_CHANGED, 755 new EventSimStateChangedBag(phoneId, iccStatus))); 756 } else if (action.equals(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED)) { 757 String newPhone = intent.getStringExtra(PhoneConstants.PHONE_NAME_KEY); 758 Log.d(LOG_TAG, "Radio technology switched. Now " + newPhone + " is active."); 759 initForNewRadioTechnology(); 760 } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) { 761 handleServiceStateChanged(intent); 762 } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) { 763 int phoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY, 0); 764 phoneInEcm = PhoneFactory.getPhone(phoneId); 765 Log.d(LOG_TAG, "Emergency Callback Mode. phoneId:" + phoneId); 766 if (phoneInEcm != null) { 767 if (TelephonyCapabilities.supportsEcm(phoneInEcm)) { 768 Log.d(LOG_TAG, "Emergency Callback Mode arrived in PhoneApp."); 769 // Start Emergency Callback Mode service 770 if (intent.getBooleanExtra( 771 TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, false)) { 772 context.startService(new Intent(context, 773 EmergencyCallbackModeService.class)); 774 } else { 775 phoneInEcm = null; 776 } 777 } else { 778 // It doesn't make sense to get ACTION_EMERGENCY_CALLBACK_MODE_CHANGED 779 // on a device that doesn't support ECM in the first place. 780 Log.e(LOG_TAG, "Got ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, but " 781 + "ECM isn't supported for phone: " + phoneInEcm.getPhoneName()); 782 phoneInEcm = null; 783 } 784 } else { 785 Log.w(LOG_TAG, "phoneInEcm is null."); 786 } 787 } else if (action.equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) { 788 // Roaming status could be overridden by carrier config, so we need to update it. 789 if (VDBG) Log.v(LOG_TAG, "carrier config changed."); 790 updateDataRoamingStatus(); 791 updateLimitedSimFunctionForDualSim(); 792 int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, 793 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 794 if (SubscriptionManager.isValidSubscriptionId(subId)) { 795 mHandler.sendMessage(mHandler.obtainMessage(EVENT_CARRIER_CONFIG_CHANGED, 796 new Integer(subId))); 797 } 798 } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) { 799 // We also need to pay attention when default data subscription changes. 800 if (VDBG) Log.v(LOG_TAG, "default data sub changed."); 801 mDefaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId(); 802 registerSettingsObserver(); 803 Phone phone = getPhone(mDefaultDataSubId); 804 if (phone != null) { 805 updateDataRoamingStatus(); 806 } 807 } 808 } 809 } 810 811 private class SipReceiver extends BroadcastReceiver { 812 813 @Override onReceive(Context context, Intent intent)814 public void onReceive(Context context, Intent intent) { 815 String action = intent.getAction(); 816 817 SipAccountRegistry sipAccountRegistry = SipAccountRegistry.getInstance(); 818 if (action.equals(Intent.ACTION_BOOT_COMPLETED)) { 819 SipUtil.startSipService(); 820 } else if (action.equals(SipManager.ACTION_SIP_SERVICE_UP) 821 || action.equals(SipManager.ACTION_SIP_CALL_OPTION_CHANGED)) { 822 sipAccountRegistry.setup(context); 823 } else if (action.equals(SipManager.ACTION_SIP_REMOVE_PROFILE)) { 824 if (DBG) { 825 Log.d(LOG_TAG, "SIP_REMOVE_PHONE " 826 + intent.getStringExtra(SipManager.EXTRA_LOCAL_URI)); 827 } 828 sipAccountRegistry.removeSipProfile(intent.getStringExtra( 829 SipManager.EXTRA_LOCAL_URI)); 830 } else { 831 if (DBG) Log.d(LOG_TAG, "onReceive, action not processed: " + action); 832 } 833 } 834 } 835 handleServiceStateChanged(Intent intent)836 private void handleServiceStateChanged(Intent intent) { 837 /** 838 * This used to handle updating EriTextWidgetProvider this routine 839 * and and listening for ACTION_SERVICE_STATE_CHANGED intents could 840 * be removed. But leaving just in case it might be needed in the near 841 * future. 842 */ 843 844 if (VDBG) Log.v(LOG_TAG, "handleServiceStateChanged"); 845 // If service just returned, start sending out the queued messages 846 Bundle extras = intent.getExtras(); 847 if (extras != null) { 848 ServiceState ss = ServiceState.newFromBundle(extras); 849 if (ss != null) { 850 int state = ss.getState(); 851 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY, 852 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 853 notificationMgr.updateNetworkSelection(state, subId); 854 855 if (VDBG) { 856 Log.v(LOG_TAG, "subId=" + subId + ",mDefaultDataSubId=" 857 + mDefaultDataSubId + ",ss roaming=" + ss.getDataRoaming()); 858 } 859 if (subId == mDefaultDataSubId) { 860 updateDataRoamingStatus(); 861 } 862 } 863 } 864 } 865 866 /** 867 * @return whether or not we should show a notification when connecting to data roaming if the 868 * user has data roaming enabled 869 */ shouldShowDataConnectedRoaming(int subId)870 private boolean shouldShowDataConnectedRoaming(int subId) { 871 PersistableBundle config = getCarrierConfigForSubId(subId); 872 return config.getBoolean(CarrierConfigManager 873 .KEY_SHOW_DATA_CONNECTED_ROAMING_NOTIFICATION_BOOL); 874 } 875 876 /** 877 * When roaming, if mobile data cannot be established due to data roaming not enabled, we need 878 * to notify the user so they can enable it through settings. Vise versa if the condition 879 * changes, we need to dismiss the notification. 880 */ updateDataRoamingStatus()881 private void updateDataRoamingStatus() { 882 if (VDBG) Log.v(LOG_TAG, "updateDataRoamingStatus"); 883 Phone phone = getPhone(mDefaultDataSubId); 884 if (phone == null) { 885 Log.w(LOG_TAG, "Can't get phone with sub id = " + mDefaultDataSubId); 886 return; 887 } 888 889 DataConnectionReasons reasons = new DataConnectionReasons(); 890 boolean dataAllowed = phone.isDataAllowed(ApnSetting.TYPE_DEFAULT, reasons); 891 mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons); 892 if (VDBG) Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons); 893 if (!dataAllowed && reasons.containsOnly(DataDisallowedReasonType.ROAMING_DISABLED)) { 894 // No need to show it again if we never cancelled it explicitly. 895 if (mPrevRoamingNotification == ROAMING_NOTIFICATION_DISCONNECTED) return; 896 // If the only reason of no data is data roaming disabled, then we notify the user 897 // so the user can turn on data roaming. 898 mPrevRoamingNotification = ROAMING_NOTIFICATION_DISCONNECTED; 899 Log.d(LOG_TAG, "Show roaming disconnected notification"); 900 mDataRoamingNotifLog.log("Show roaming off."); 901 Message msg = mHandler.obtainMessage(EVENT_DATA_ROAMING_DISCONNECTED); 902 msg.arg1 = mDefaultDataSubId; 903 msg.sendToTarget(); 904 } else if (dataAllowed && dataIsNowRoaming(mDefaultDataSubId) 905 && shouldShowDataConnectedRoaming(mDefaultDataSubId)) { 906 // No need to show it again if we never cancelled it explicitly, or carrier config 907 // indicates this is not needed. 908 if (mPrevRoamingNotification == ROAMING_NOTIFICATION_CONNECTED) return; 909 mPrevRoamingNotification = ROAMING_NOTIFICATION_CONNECTED; 910 Log.d(LOG_TAG, "Show roaming connected notification"); 911 mDataRoamingNotifLog.log("Show roaming on."); 912 Message msg = mHandler.obtainMessage(EVENT_DATA_ROAMING_CONNECTED); 913 msg.arg1 = mDefaultDataSubId; 914 msg.sendToTarget(); 915 } else if (mPrevRoamingNotification != ROAMING_NOTIFICATION_NO_NOTIFICATION) { 916 // Otherwise we either 1) we are not roaming or 2) roaming is off but ROAMING_DISABLED 917 // is not the only data disable reason. In this case we dismiss the notification we 918 // showed earlier. 919 mPrevRoamingNotification = ROAMING_NOTIFICATION_NO_NOTIFICATION; 920 Log.d(LOG_TAG, "Dismiss roaming notification"); 921 mDataRoamingNotifLog.log("Hide. data allowed=" + dataAllowed + ", reasons=" + reasons); 922 mHandler.sendEmptyMessage(EVENT_DATA_ROAMING_OK); 923 } 924 } 925 926 /** 927 * 928 * @param subId to check roaming on 929 * @return whether we have transitioned to dataRoaming 930 */ dataIsNowRoaming(int subId)931 private boolean dataIsNowRoaming(int subId) { 932 return getPhone(subId).getServiceState().getDataRoaming(); 933 } 934 updateLimitedSimFunctionForDualSim()935 private void updateLimitedSimFunctionForDualSim() { 936 if (DBG) Log.d(LOG_TAG, "updateLimitedSimFunctionForDualSim"); 937 // check conditions to display limited SIM function notification under dual SIM 938 SubscriptionManager subMgr = (SubscriptionManager) getSystemService( 939 Context.TELEPHONY_SUBSCRIPTION_SERVICE); 940 List<SubscriptionInfo> subList = subMgr.getActiveSubscriptionInfoList(false); 941 if (subList != null && subList.size() > 1) { 942 CarrierConfigManager configMgr = (CarrierConfigManager) 943 getSystemService(Context.CARRIER_CONFIG_SERVICE); 944 for (SubscriptionInfo info : subList) { 945 PersistableBundle b = configMgr.getConfigForSubId(info.getSubscriptionId()); 946 if (b != null) { 947 if (b.getBoolean(CarrierConfigManager 948 .KEY_LIMITED_SIM_FUNCTION_NOTIFICATION_FOR_DSDS_BOOL)) { 949 notificationMgr.showLimitedSimFunctionWarningNotification( 950 info.getSubscriptionId(), 951 info.getDisplayName().toString()); 952 } else { 953 notificationMgr.dismissLimitedSimFunctionWarningNotification( 954 info.getSubscriptionId()); 955 } 956 } 957 } 958 } else { 959 // cancel notifications for all subs 960 notificationMgr.dismissLimitedSimFunctionWarningNotification( 961 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 962 } 963 notificationMgr.dismissLimitedSimFunctionWarningNotificationForInactiveSubs(); 964 965 } 966 getPhoneInEcm()967 public Phone getPhoneInEcm() { 968 return phoneInEcm; 969 } 970 971 /** 972 * Triggers a refresh of the message waiting (voicemail) indicator. 973 * 974 * @param subId the subscription id we should refresh the notification for. 975 */ refreshMwiIndicator(int subId)976 public void refreshMwiIndicator(int subId) { 977 notificationMgr.refreshMwi(subId); 978 } 979 980 /** 981 * Called when the network selection on the subscription {@code subId} is changed by the user. 982 * 983 * @param subId the subscription id. 984 */ onNetworkSelectionChanged(int subId)985 public void onNetworkSelectionChanged(int subId) { 986 Phone phone = getPhone(subId); 987 if (phone != null) { 988 notificationMgr.updateNetworkSelection(phone.getServiceState().getState(), subId); 989 } else { 990 Log.w(LOG_TAG, "onNetworkSelectionChanged on null phone, subId: " + subId); 991 } 992 } 993 994 /** 995 * @return whether the device supports RCS User Capability Exchange or not. 996 */ getDeviceUceEnabled()997 public boolean getDeviceUceEnabled() { 998 return (mTelephonyRcsService == null) ? false : mTelephonyRcsService.isDeviceUceEnabled(); 999 } 1000 1001 /** 1002 * Set the device supports RCS User Capability Exchange. 1003 * @param isEnabled true if the device supports UCE. 1004 */ setDeviceUceEnabled(boolean isEnabled)1005 public void setDeviceUceEnabled(boolean isEnabled) { 1006 if (mTelephonyRcsService != null) { 1007 mTelephonyRcsService.setDeviceUceEnabled(isEnabled); 1008 } 1009 } 1010 1011 /** 1012 * Dump the state of the object, add calls to other objects as desired. 1013 * 1014 * @param fd File descriptor 1015 * @param printWriter Print writer 1016 * @param args Arguments 1017 */ dump(FileDescriptor fd, PrintWriter printWriter, String[] args)1018 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 1019 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 1020 pw.println("------- PhoneGlobals -------"); 1021 pw.increaseIndent(); 1022 pw.println("mPrevRoamingNotification=" + mPrevRoamingNotification); 1023 pw.println("mDefaultDataSubId=" + mDefaultDataSubId); 1024 pw.println("mDataRoamingNotifLog:"); 1025 pw.println("isSmsCapable=" + TelephonyManager.from(this).isSmsCapable()); 1026 pw.increaseIndent(); 1027 mDataRoamingNotifLog.dump(fd, pw, args); 1028 pw.decreaseIndent(); 1029 pw.println("ImsResolver:"); 1030 pw.increaseIndent(); 1031 try { 1032 if (ImsResolver.getInstance() != null) ImsResolver.getInstance().dump(fd, pw, args); 1033 } catch (Exception e) { 1034 e.printStackTrace(); 1035 } 1036 pw.decreaseIndent(); 1037 pw.println("RcsService:"); 1038 try { 1039 if (mTelephonyRcsService != null) mTelephonyRcsService.dump(fd, pw, args); 1040 } catch (Exception e) { 1041 e.printStackTrace(); 1042 } 1043 pw.decreaseIndent(); 1044 pw.println("------- End PhoneGlobals -------"); 1045 } 1046 } 1047