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