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