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                             || IccCardConstants.INTENT_VALUE_ICC_NOT_READY.equals(bag.mIccStatus)
271                             || IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(bag.mIccStatus)) {
272                         // when the right event is triggered and there
273                         // are UI objects in the foreground, we close
274                         // them to display the lock panel.
275                         if (mPUKEntryActivity != null) {
276                             Log.i(LOG_TAG, "Dismiss puk entry activity");
277                             mPUKEntryActivity.finish();
278                             mPUKEntryActivity = null;
279                         }
280                         if (mPUKEntryProgressDialog != null) {
281                             Log.i(LOG_TAG, "Dismiss puk progress dialog");
282                             mPUKEntryProgressDialog.dismiss();
283                             mPUKEntryProgressDialog = null;
284                         }
285                         Log.i(LOG_TAG, "Dismissing depersonal panel" + (bag.mIccStatus));
286                         IccNetworkDepersonalizationPanel.dialogDismiss(bag.mPhoneId);
287                     }
288                     break;
289 
290                 case EVENT_UNSOL_CDMA_INFO_RECORD:
291                     //TODO: handle message here;
292                     break;
293                 case EVENT_RESTART_SIP:
294                     // This should only run if the Phone process crashed and was restarted. We do
295                     // not want this running if the device is still in the FBE encrypted state.
296                     // This is the same procedure that is triggered in the SipIncomingCallReceiver
297                     // upon BOOT_COMPLETED.
298                     UserManager userManager =
299                             (UserManager) sMe.getSystemService(Context.USER_SERVICE);
300                     if (userManager != null && userManager.isUserUnlocked()) {
301                         SipUtil.startSipService();
302                     }
303                     break;
304                 case EVENT_DATA_ROAMING_SETTINGS_CHANGED:
305                 case EVENT_MOBILE_DATA_SETTINGS_CHANGED:
306                     updateDataRoamingStatus();
307                     break;
308             }
309         }
310     };
311 
PhoneGlobals(Context context)312     public PhoneGlobals(Context context) {
313         super(context);
314         sMe = this;
315         mSettingsObserver = new SettingsObserver(context, mHandler);
316     }
317 
onCreate()318     public void onCreate() {
319         if (VDBG) Log.v(LOG_TAG, "onCreate()...");
320 
321         ContentResolver resolver = getContentResolver();
322 
323         // Cache the "voice capable" flag.
324         // This flag currently comes from a resource (which is
325         // overrideable on a per-product basis):
326         sVoiceCapable = ((TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE))
327                 .isVoiceCapable();
328         // ...but this might eventually become a PackageManager "system
329         // feature" instead, in which case we'd do something like:
330         // sVoiceCapable =
331         //   getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_VOICE_CALLS);
332 
333         if (mCM == null) {
334             // Initialize AnomalyReporter early so that it can be used
335             AnomalyReporter.initialize(this);
336 
337             // Inject telephony component factory if configured using other jars.
338             XmlResourceParser parser = getResources().getXml(R.xml.telephony_injection);
339             TelephonyComponentFactory.getInstance().injectTheComponentFactory(parser);
340             // Initialize the telephony framework
341             PhoneFactory.makeDefaultPhones(this);
342 
343             // Only bring up ImsResolver if the device supports having an IMS stack.
344             if (getPackageManager().hasSystemFeature(
345                     PackageManager.FEATURE_TELEPHONY_IMS)) {
346                 // Get the package name of the default IMS implementation.
347                 String defaultImsMmtelPackage = getResources().getString(
348                         R.string.config_ims_mmtel_package);
349                 String defaultImsRcsPackage = getResources().getString(
350                         R.string.config_ims_rcs_package);
351                 mImsResolver = new ImsResolver(this, defaultImsMmtelPackage,
352                         defaultImsRcsPackage, PhoneFactory.getPhones().length);
353                 mImsResolver.initialize();
354             }
355 
356             // Start TelephonyDebugService After the default phone is created.
357             Intent intent = new Intent(this, TelephonyDebugService.class);
358             startService(intent);
359 
360             mCM = CallManager.getInstance();
361             for (Phone phone : PhoneFactory.getPhones()) {
362                 mCM.registerPhone(phone);
363             }
364 
365             // Create the NotificationMgr singleton, which is used to display
366             // status bar icons and control other status bar behavior.
367             notificationMgr = NotificationMgr.init(this);
368 
369             // If PhoneGlobals has crashed and is being restarted, then restart.
370             mHandler.sendEmptyMessage(EVENT_RESTART_SIP);
371 
372             // Create an instance of CdmaPhoneCallState and initialize it to IDLE
373             cdmaPhoneCallState = new CdmaPhoneCallState();
374             cdmaPhoneCallState.CdmaPhoneCallStateInit();
375 
376             // before registering for phone state changes
377             mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
378             mWakeLock = mPowerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, LOG_TAG);
379             // lock used to keep the processor awake, when we don't care for the display.
380             mPartialWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK
381                     | PowerManager.ON_AFTER_RELEASE, LOG_TAG);
382 
383             mKeyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
384 
385             // Create the CallerInfoCache singleton, which remembers custom ring tone and
386             // send-to-voicemail settings.
387             //
388             // The asynchronous caching will start just after this call.
389             callerInfoCache = CallerInfoCache.init(this);
390 
391             phoneMgr = PhoneInterfaceManager.init(this);
392 
393             imsRcsController = ImsRcsController.init(this);
394 
395             if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY_IMS)) {
396                 mTelephonyRcsService = new TelephonyRcsService(this,
397                         PhoneFactory.getPhones().length);
398                 mTelephonyRcsService.initialize();
399                 imsRcsController.setRcsService(mTelephonyRcsService);
400             }
401 
402             configLoader = CarrierConfigLoader.init(this);
403 
404             // Create the CallNotifier singleton, which handles
405             // asynchronous events from the telephony layer (like
406             // launching the incoming-call UI when an incoming call comes
407             // in.)
408             notifier = CallNotifier.init(this);
409 
410             PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED);
411 
412             // register for MMI/USSD
413             mCM.registerForMmiComplete(mHandler, MMI_COMPLETE, null);
414 
415             // Initialize cell status using current airplane mode.
416             handleAirplaneModeChange(this, Settings.Global.getInt(getContentResolver(),
417                     Settings.Global.AIRPLANE_MODE_ON, AIRPLANE_OFF));
418 
419             // Register for misc other intent broadcasts.
420             IntentFilter intentFilter =
421                     new IntentFilter(Intent.ACTION_AIRPLANE_MODE_CHANGED);
422             intentFilter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
423             intentFilter.addAction(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
424             intentFilter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
425             intentFilter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
426             intentFilter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
427             intentFilter.addAction(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
428             registerReceiver(mReceiver, intentFilter);
429 
430             IntentFilter sipIntentFilter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
431             sipIntentFilter.addAction(SipManager.ACTION_SIP_SERVICE_UP);
432             sipIntentFilter.addAction(SipManager.ACTION_SIP_CALL_OPTION_CHANGED);
433             sipIntentFilter.addAction(SipManager.ACTION_SIP_REMOVE_PROFILE);
434             registerReceiver(mSipReceiver, sipIntentFilter);
435 
436             mCarrierVvmPackageInstalledReceiver.register(this);
437 
438             //set the default values for the preferences in the phone.
439             PreferenceManager.setDefaultValues(this, R.xml.call_feature_setting, false);
440         }
441 
442         // XXX pre-load the SimProvider so that it's ready
443         resolver.getType(Uri.parse("content://icc/adn"));
444 
445         // TODO: Register for Cdma Information Records
446         // phone.registerCdmaInformationRecord(mHandler, EVENT_UNSOL_CDMA_INFO_RECORD, null);
447 
448         // Read HAC settings and configure audio hardware
449         if (getResources().getBoolean(R.bool.hac_enabled)) {
450             int hac = android.provider.Settings.System.getInt(
451                     getContentResolver(),
452                     android.provider.Settings.System.HEARING_AID,
453                     0);
454             AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
455             audioManager.setParameters(
456                     SettingsConstants.HAC_KEY + "=" + (hac == SettingsConstants.HAC_ENABLED
457                             ? SettingsConstants.HAC_VAL_ON : SettingsConstants.HAC_VAL_OFF));
458         }
459     }
460 
461     /**
462      * Returns the singleton instance of the PhoneApp.
463      */
getInstance()464     public static PhoneGlobals getInstance() {
465         if (sMe == null) {
466             throw new IllegalStateException("No PhoneGlobals here!");
467         }
468         return sMe;
469     }
470 
471     /**
472      * Returns the default phone.
473      *
474      * WARNING: This method should be used carefully, now that there may be multiple phones.
475      */
getPhone()476     public static Phone getPhone() {
477         return PhoneFactory.getDefaultPhone();
478     }
479 
getPhone(int subId)480     public static Phone getPhone(int subId) {
481         return PhoneFactory.getPhone(SubscriptionManager.getPhoneId(subId));
482     }
483 
getImsResolver()484     public ImsResolver getImsResolver() {
485         return mImsResolver;
486     }
487 
getCallManager()488     /* package */ CallManager getCallManager() {
489         return mCM;
490     }
491 
getCarrierConfig()492     public PersistableBundle getCarrierConfig() {
493         return getCarrierConfigForSubId(SubscriptionManager.getDefaultSubscriptionId());
494     }
495 
getCarrierConfigForSubId(int subId)496     public PersistableBundle getCarrierConfigForSubId(int subId) {
497         return configLoader.getConfigForSubIdWithFeature(subId, getOpPackageName(), null);
498     }
499 
registerSettingsObserver()500     private void registerSettingsObserver() {
501         mSettingsObserver.unobserve();
502         String dataRoamingSetting = Settings.Global.DATA_ROAMING;
503         String mobileDataSetting = Settings.Global.MOBILE_DATA;
504         if (TelephonyManager.getDefault().getSimCount() > 1) {
505             int subId = mDefaultDataSubId;
506             if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
507                 dataRoamingSetting += subId;
508                 mobileDataSetting += subId;
509             }
510         }
511 
512         // Listen for user data roaming setting changed event
513         mSettingsObserver.observe(Settings.Global.getUriFor(dataRoamingSetting),
514                 EVENT_DATA_ROAMING_SETTINGS_CHANGED);
515 
516         // Listen for mobile data setting changed event
517         mSettingsObserver.observe(Settings.Global.getUriFor(mobileDataSetting),
518                 EVENT_MOBILE_DATA_SETTINGS_CHANGED);
519     }
520 
521     /**
522      * Sets the activity responsible for un-PUK-blocking the device
523      * so that we may close it when we receive a positive result.
524      * mPUKEntryActivity is also used to indicate to the device that
525      * we are trying to un-PUK-lock the phone. In other words, iff
526      * it is NOT null, then we are trying to unlock and waiting for
527      * the SIM to move to READY state.
528      *
529      * @param activity is the activity to close when PUK has
530      * finished unlocking. Can be set to null to indicate the unlock
531      * or SIM READYing process is over.
532      */
setPukEntryActivity(Activity activity)533     void setPukEntryActivity(Activity activity) {
534         Log.i(LOG_TAG, "setPukEntryActivity - set to " + (activity == null ? "null" : "activity"));
535         mPUKEntryActivity = activity;
536     }
537 
getPUKEntryActivity()538     Activity getPUKEntryActivity() {
539         return mPUKEntryActivity;
540     }
541 
542     /**
543      * Sets the dialog responsible for notifying the user of un-PUK-
544      * blocking - SIM READYing progress, so that we may dismiss it
545      * when we receive a positive result.
546      *
547      * @param dialog indicates the progress dialog informing the user
548      * of the state of the device.  Dismissed upon completion of
549      * READYing process
550      */
setPukEntryProgressDialog(ProgressDialog dialog)551     void setPukEntryProgressDialog(ProgressDialog dialog) {
552         Log.i(LOG_TAG, "setPukEntryProgressDialog - set to "
553                 + (dialog == null ? "null" : "activity"));
554         mPUKEntryProgressDialog = dialog;
555     }
556 
getKeyguardManager()557     KeyguardManager getKeyguardManager() {
558         return mKeyguardManager;
559     }
560 
onMMIComplete(AsyncResult r)561     private void onMMIComplete(AsyncResult r) {
562         if (VDBG) Log.d(LOG_TAG, "onMMIComplete()...");
563         MmiCode mmiCode = (MmiCode) r.result;
564         PhoneUtils.displayMMIComplete(mmiCode.getPhone(), getInstance(), mmiCode, null, null);
565     }
566 
initForNewRadioTechnology()567     private void initForNewRadioTechnology() {
568         if (DBG) Log.d(LOG_TAG, "initForNewRadioTechnology...");
569         notifier.updateCallNotifierRegistrationsAfterRadioTechnologyChange();
570     }
571 
handleAirplaneModeChange(Context context, int newMode)572     private void handleAirplaneModeChange(Context context, int newMode) {
573         int cellState = Settings.Global.getInt(context.getContentResolver(),
574                 Settings.Global.CELL_ON, PhoneConstants.CELL_ON_FLAG);
575         boolean isAirplaneNewlyOn = (newMode == 1);
576         switch (cellState) {
577             case PhoneConstants.CELL_OFF_FLAG:
578                 // Airplane mode does not affect the cell radio if user
579                 // has turned it off.
580                 break;
581             case PhoneConstants.CELL_ON_FLAG:
582                 maybeTurnCellOff(context, isAirplaneNewlyOn);
583                 break;
584             case PhoneConstants.CELL_OFF_DUE_TO_AIRPLANE_MODE_FLAG:
585                 maybeTurnCellOn(context, isAirplaneNewlyOn);
586                 break;
587         }
588         for (Phone phone : PhoneFactory.getPhones()) {
589             phone.getServiceStateTracker().onAirplaneModeChanged(isAirplaneNewlyOn);
590         }
591     }
592 
593     /*
594      * Returns true if the radio must be turned off when entering airplane mode.
595      */
isCellOffInAirplaneMode(Context context)596     private boolean isCellOffInAirplaneMode(Context context) {
597         String airplaneModeRadios = Settings.Global.getString(context.getContentResolver(),
598                 Settings.Global.AIRPLANE_MODE_RADIOS);
599         return airplaneModeRadios == null
600                 || airplaneModeRadios.contains(Settings.Global.RADIO_CELL);
601     }
602 
setRadioPowerOff(Context context)603     private void setRadioPowerOff(Context context) {
604         Log.i(LOG_TAG, "Turning radio off - airplane");
605         Settings.Global.putInt(context.getContentResolver(), Settings.Global.CELL_ON,
606                  PhoneConstants.CELL_OFF_DUE_TO_AIRPLANE_MODE_FLAG);
607         TelephonyProperties.airplane_mode_on(true); // true means int value 1
608         Settings.Global.putInt(getContentResolver(), Settings.Global.ENABLE_CELLULAR_ON_BOOT, 0);
609         PhoneUtils.setRadioPower(false);
610     }
611 
setRadioPowerOn(Context context)612     private void setRadioPowerOn(Context context) {
613         Log.i(LOG_TAG, "Turning radio on - airplane");
614         Settings.Global.putInt(context.getContentResolver(), Settings.Global.CELL_ON,
615                 PhoneConstants.CELL_ON_FLAG);
616         Settings.Global.putInt(getContentResolver(), Settings.Global.ENABLE_CELLULAR_ON_BOOT,
617                 1);
618         TelephonyProperties.airplane_mode_on(false); // false means int value 0
619         PhoneUtils.setRadioPower(true);
620     }
621 
maybeTurnCellOff(Context context, boolean isAirplaneNewlyOn)622     private void maybeTurnCellOff(Context context, boolean isAirplaneNewlyOn) {
623         if (isAirplaneNewlyOn) {
624             // If we are trying to turn off the radio, make sure there are no active
625             // emergency calls.  If there are, switch airplane mode back to off.
626             TelecomManager tm = (TelecomManager) context.getSystemService(TELECOM_SERVICE);
627 
628             if (tm != null && tm.isInEmergencyCall()) {
629                 // Switch airplane mode back to off.
630                 ConnectivityManager cm =
631                         (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);
632                 cm.setAirplaneMode(false);
633                 Toast.makeText(this, R.string.radio_off_during_emergency_call, Toast.LENGTH_LONG)
634                         .show();
635                 Log.i(LOG_TAG, "Ignoring airplane mode: emergency call. Turning airplane off");
636             } else if (isCellOffInAirplaneMode(context)) {
637                 setRadioPowerOff(context);
638             } else {
639                 Log.i(LOG_TAG, "Ignoring airplane mode: settings prevent cell radio power off");
640             }
641         }
642     }
643 
maybeTurnCellOn(Context context, boolean isAirplaneNewlyOn)644     private void maybeTurnCellOn(Context context, boolean isAirplaneNewlyOn) {
645         if (!isAirplaneNewlyOn) {
646             setRadioPowerOn(context);
647         }
648     }
649 
650     /**
651      * Receiver for misc intent broadcasts the Phone app cares about.
652      */
653     private class PhoneAppBroadcastReceiver extends BroadcastReceiver {
654         @Override
onReceive(Context context, Intent intent)655         public void onReceive(Context context, Intent intent) {
656             String action = intent.getAction();
657             if (action.equals(Intent.ACTION_AIRPLANE_MODE_CHANGED)) {
658                 int airplaneMode = Settings.Global.getInt(getContentResolver(),
659                         Settings.Global.AIRPLANE_MODE_ON, AIRPLANE_OFF);
660                 // Treat any non-OFF values as ON.
661                 if (airplaneMode != AIRPLANE_OFF) {
662                     airplaneMode = AIRPLANE_ON;
663                 }
664                 handleAirplaneModeChange(context, airplaneMode);
665             } else if (action.equals(TelephonyIntents.ACTION_SIM_STATE_CHANGED)) {
666                 // re-register as it may be a new IccCard
667                 int phoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY,
668                         SubscriptionManager.INVALID_PHONE_INDEX);
669                 if (SubscriptionManager.isValidPhoneId(phoneId)) {
670                     PhoneUtils.unregisterIccStatus(mHandler, phoneId);
671                     PhoneUtils.registerIccStatus(mHandler, EVENT_SIM_NETWORK_LOCKED, phoneId);
672                 }
673                 String iccStatus = intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
674                 mHandler.sendMessage(mHandler.obtainMessage(EVENT_SIM_STATE_CHANGED,
675                         new EventSimStateChangedBag(phoneId, iccStatus)));
676             } else if (action.equals(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED)) {
677                 String newPhone = intent.getStringExtra(PhoneConstants.PHONE_NAME_KEY);
678                 Log.d(LOG_TAG, "Radio technology switched. Now " + newPhone + " is active.");
679                 initForNewRadioTechnology();
680             } else if (action.equals(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED)) {
681                 handleServiceStateChanged(intent);
682             } else if (action.equals(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED)) {
683                 int phoneId = intent.getIntExtra(PhoneConstants.PHONE_KEY, 0);
684                 phoneInEcm = PhoneFactory.getPhone(phoneId);
685                 Log.d(LOG_TAG, "Emergency Callback Mode. phoneId:" + phoneId);
686                 if (phoneInEcm != null) {
687                     if (TelephonyCapabilities.supportsEcm(phoneInEcm)) {
688                         Log.d(LOG_TAG, "Emergency Callback Mode arrived in PhoneApp.");
689                         // Start Emergency Callback Mode service
690                         if (intent.getBooleanExtra(
691                                 TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, false)) {
692                             context.startService(new Intent(context,
693                                     EmergencyCallbackModeService.class));
694                         } else {
695                             phoneInEcm = null;
696                         }
697                     } else {
698                         // It doesn't make sense to get ACTION_EMERGENCY_CALLBACK_MODE_CHANGED
699                         // on a device that doesn't support ECM in the first place.
700                         Log.e(LOG_TAG, "Got ACTION_EMERGENCY_CALLBACK_MODE_CHANGED, but "
701                                 + "ECM isn't supported for phone: " + phoneInEcm.getPhoneName());
702                         phoneInEcm = null;
703                     }
704                 } else {
705                     Log.w(LOG_TAG, "phoneInEcm is null.");
706                 }
707             } else if (action.equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
708                 // Roaming status could be overridden by carrier config, so we need to update it.
709                 if (VDBG) Log.v(LOG_TAG, "carrier config changed.");
710                 updateDataRoamingStatus();
711                 updateLimitedSimFunctionForDualSim();
712             } else if (action.equals(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED)) {
713                 // We also need to pay attention when default data subscription changes.
714                 if (VDBG) Log.v(LOG_TAG, "default data sub changed.");
715                 mDefaultDataSubId = SubscriptionManager.getDefaultDataSubscriptionId();
716                 registerSettingsObserver();
717                 Phone phone = getPhone(mDefaultDataSubId);
718                 if (phone != null) {
719                     updateDataRoamingStatus();
720                 }
721             }
722         }
723     }
724 
725     private class SipReceiver extends BroadcastReceiver {
726 
727         @Override
onReceive(Context context, Intent intent)728         public void onReceive(Context context, Intent intent) {
729             String action = intent.getAction();
730 
731             SipAccountRegistry sipAccountRegistry = SipAccountRegistry.getInstance();
732             if (action.equals(Intent.ACTION_BOOT_COMPLETED)) {
733                 SipUtil.startSipService();
734             } else if (action.equals(SipManager.ACTION_SIP_SERVICE_UP)
735                     || action.equals(SipManager.ACTION_SIP_CALL_OPTION_CHANGED)) {
736                 sipAccountRegistry.setup(context);
737             } else if (action.equals(SipManager.ACTION_SIP_REMOVE_PROFILE)) {
738                 if (DBG) {
739                     Log.d(LOG_TAG, "SIP_REMOVE_PHONE "
740                             + intent.getStringExtra(SipManager.EXTRA_LOCAL_URI));
741                 }
742                 sipAccountRegistry.removeSipProfile(intent.getStringExtra(
743                         SipManager.EXTRA_LOCAL_URI));
744             } else {
745                 if (DBG) Log.d(LOG_TAG, "onReceive, action not processed: " + action);
746             }
747         }
748     }
749 
handleServiceStateChanged(Intent intent)750     private void handleServiceStateChanged(Intent intent) {
751         /**
752          * This used to handle updating EriTextWidgetProvider this routine
753          * and and listening for ACTION_SERVICE_STATE_CHANGED intents could
754          * be removed. But leaving just in case it might be needed in the near
755          * future.
756          */
757 
758         if (VDBG) Log.v(LOG_TAG, "handleServiceStateChanged");
759         // If service just returned, start sending out the queued messages
760         Bundle extras = intent.getExtras();
761         if (extras != null) {
762             ServiceState ss = ServiceState.newFromBundle(extras);
763             if (ss != null) {
764                 int state = ss.getState();
765                 int subId = intent.getIntExtra(PhoneConstants.SUBSCRIPTION_KEY,
766                         SubscriptionManager.INVALID_SUBSCRIPTION_ID);
767                 notificationMgr.updateNetworkSelection(state, subId);
768 
769                 if (VDBG) {
770                     Log.v(LOG_TAG, "subId=" + subId + ",mDefaultDataSubId="
771                             + mDefaultDataSubId + ",ss roaming=" + ss.getDataRoaming());
772                 }
773                 if (subId == mDefaultDataSubId) {
774                     updateDataRoamingStatus();
775                 }
776             }
777         }
778     }
779 
780     /**
781      * @return whether or not we should show a notification when connecting to data roaming if the
782      * user has data roaming enabled
783      */
shouldShowDataConnectedRoaming(int subId)784     private boolean shouldShowDataConnectedRoaming(int subId) {
785         PersistableBundle config = getCarrierConfigForSubId(subId);
786         return config.getBoolean(CarrierConfigManager
787                 .KEY_SHOW_DATA_CONNECTED_ROAMING_NOTIFICATION_BOOL);
788     }
789 
790     /**
791      * When roaming, if mobile data cannot be established due to data roaming not enabled, we need
792      * to notify the user so they can enable it through settings. Vise versa if the condition
793      * changes, we need to dismiss the notification.
794      */
updateDataRoamingStatus()795     private void updateDataRoamingStatus() {
796         if (VDBG) Log.v(LOG_TAG, "updateDataRoamingStatus");
797         Phone phone = getPhone(mDefaultDataSubId);
798         if (phone == null) {
799             Log.w(LOG_TAG, "Can't get phone with sub id = " + mDefaultDataSubId);
800             return;
801         }
802 
803         DataConnectionReasons reasons = new DataConnectionReasons();
804         boolean dataAllowed = phone.isDataAllowed(ApnSetting.TYPE_DEFAULT, reasons);
805         mDataRoamingNotifLog.log("dataAllowed=" + dataAllowed + ", reasons=" + reasons);
806         if (VDBG) Log.v(LOG_TAG, "dataAllowed=" + dataAllowed + ", reasons=" + reasons);
807         if (!dataAllowed && reasons.containsOnly(DataDisallowedReasonType.ROAMING_DISABLED)) {
808             // No need to show it again if we never cancelled it explicitly.
809             if (mPrevRoamingNotification == ROAMING_NOTIFICATION_DISCONNECTED) return;
810             // If the only reason of no data is data roaming disabled, then we notify the user
811             // so the user can turn on data roaming.
812             mPrevRoamingNotification = ROAMING_NOTIFICATION_DISCONNECTED;
813             Log.d(LOG_TAG, "Show roaming disconnected notification");
814             mDataRoamingNotifLog.log("Show roaming off.");
815             Message msg = mHandler.obtainMessage(EVENT_DATA_ROAMING_DISCONNECTED);
816             msg.arg1 = mDefaultDataSubId;
817             msg.sendToTarget();
818         } else if (dataAllowed && dataIsNowRoaming(mDefaultDataSubId)
819                 && shouldShowDataConnectedRoaming(mDefaultDataSubId)) {
820             // No need to show it again if we never cancelled it explicitly, or carrier config
821             // indicates this is not needed.
822             if (mPrevRoamingNotification == ROAMING_NOTIFICATION_CONNECTED) return;
823             mPrevRoamingNotification = ROAMING_NOTIFICATION_CONNECTED;
824             Log.d(LOG_TAG, "Show roaming connected notification");
825             mDataRoamingNotifLog.log("Show roaming on.");
826             Message msg = mHandler.obtainMessage(EVENT_DATA_ROAMING_CONNECTED);
827             msg.arg1 = mDefaultDataSubId;
828             msg.sendToTarget();
829         } else if (mPrevRoamingNotification != ROAMING_NOTIFICATION_NO_NOTIFICATION) {
830             // Otherwise we either 1) we are not roaming or 2) roaming is off but ROAMING_DISABLED
831             // is not the only data disable reason. In this case we dismiss the notification we
832             // showed earlier.
833             mPrevRoamingNotification = ROAMING_NOTIFICATION_NO_NOTIFICATION;
834             Log.d(LOG_TAG, "Dismiss roaming notification");
835             mDataRoamingNotifLog.log("Hide. data allowed=" + dataAllowed + ", reasons=" + reasons);
836             mHandler.sendEmptyMessage(EVENT_DATA_ROAMING_OK);
837         }
838     }
839 
840     /**
841      *
842      * @param subId to check roaming on
843      * @return whether we have transitioned to dataRoaming
844      */
dataIsNowRoaming(int subId)845     private boolean dataIsNowRoaming(int subId) {
846         return getPhone(subId).getServiceState().getDataRoaming();
847     }
848 
updateLimitedSimFunctionForDualSim()849     private void updateLimitedSimFunctionForDualSim() {
850         if (DBG) Log.d(LOG_TAG, "updateLimitedSimFunctionForDualSim");
851         // check conditions to display limited SIM function notification under dual SIM
852         SubscriptionManager subMgr = (SubscriptionManager) getSystemService(
853                 Context.TELEPHONY_SUBSCRIPTION_SERVICE);
854         List<SubscriptionInfo> subList = subMgr.getActiveSubscriptionInfoList(false);
855         if (subList != null && subList.size() > 1) {
856             CarrierConfigManager configMgr = (CarrierConfigManager)
857                     getSystemService(Context.CARRIER_CONFIG_SERVICE);
858             for (SubscriptionInfo info : subList) {
859                 PersistableBundle b = configMgr.getConfigForSubId(info.getSubscriptionId());
860                 if (b != null) {
861                     if (b.getBoolean(CarrierConfigManager
862                             .KEY_LIMITED_SIM_FUNCTION_NOTIFICATION_FOR_DSDS_BOOL)) {
863                         notificationMgr.showLimitedSimFunctionWarningNotification(
864                                 info.getSubscriptionId(),
865                                 info.getDisplayName().toString());
866                     } else {
867                         notificationMgr.dismissLimitedSimFunctionWarningNotification(
868                                 info.getSubscriptionId());
869                     }
870                 }
871             }
872         } else {
873             // cancel notifications for all subs
874             notificationMgr.dismissLimitedSimFunctionWarningNotification(
875                     SubscriptionManager.INVALID_SUBSCRIPTION_ID);
876         }
877         notificationMgr.dismissLimitedSimFunctionWarningNotificationForInactiveSubs();
878 
879     }
880 
getPhoneInEcm()881     public Phone getPhoneInEcm() {
882         return phoneInEcm;
883     }
884 
885     /**
886      * Triggers a refresh of the message waiting (voicemail) indicator.
887      *
888      * @param subId the subscription id we should refresh the notification for.
889      */
refreshMwiIndicator(int subId)890     public void refreshMwiIndicator(int subId) {
891         notificationMgr.refreshMwi(subId);
892     }
893 
894     /**
895      * Called when the network selection on the subscription {@code subId} is changed by the user.
896      *
897      * @param subId the subscription id.
898      */
onNetworkSelectionChanged(int subId)899     public void onNetworkSelectionChanged(int subId) {
900         Phone phone = getPhone(subId);
901         if (phone != null) {
902             notificationMgr.updateNetworkSelection(phone.getServiceState().getState(), subId);
903         } else {
904             Log.w(LOG_TAG, "onNetworkSelectionChanged on null phone, subId: " + subId);
905         }
906     }
907 
908     /**
909      * Dump the state of the object, add calls to other objects as desired.
910      *
911      * @param fd File descriptor
912      * @param printWriter Print writer
913      * @param args Arguments
914      */
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)915     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
916         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
917         pw.println("------- PhoneGlobals -------");
918         pw.increaseIndent();
919         pw.println("mPrevRoamingNotification=" + mPrevRoamingNotification);
920         pw.println("mDefaultDataSubId=" + mDefaultDataSubId);
921         pw.println("mDataRoamingNotifLog:");
922         pw.println("isSmsCapable=" + TelephonyManager.from(this).isSmsCapable());
923         pw.increaseIndent();
924         mDataRoamingNotifLog.dump(fd, pw, args);
925         pw.decreaseIndent();
926         pw.println("ImsResolver:");
927         pw.increaseIndent();
928         try {
929             if (mImsResolver != null) mImsResolver.dump(fd, pw, args);
930         } catch (Exception e) {
931             e.printStackTrace();
932         }
933         pw.decreaseIndent();
934         pw.println("RcsService:");
935         try {
936             if (mTelephonyRcsService != null) mTelephonyRcsService.dump(fd, pw, args);
937         } catch (Exception e) {
938             e.printStackTrace();
939         }
940         pw.decreaseIndent();
941         pw.println("------- End PhoneGlobals -------");
942     }
943 }
944