1 /*
2  * Copyright (C) 2007 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.internal.telephony;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.content.SharedPreferences;
24 import android.net.LinkProperties;
25 import android.net.NetworkCapabilities;
26 import android.net.wifi.WifiManager;
27 import android.os.AsyncResult;
28 import android.os.Build;
29 import android.os.Bundle;
30 import android.os.Handler;
31 import android.os.Looper;
32 import android.os.Message;
33 import android.os.Registrant;
34 import android.os.RegistrantList;
35 import android.os.SystemProperties;
36 import android.preference.PreferenceManager;
37 import android.provider.Settings;
38 import android.telecom.VideoProfile;
39 import android.telephony.CellIdentityCdma;
40 import android.telephony.CellInfo;
41 import android.telephony.CellInfoCdma;
42 import android.telephony.DataConnectionRealTimeInfo;
43 import android.telephony.RadioAccessFamily;
44 import android.telephony.Rlog;
45 import android.telephony.ServiceState;
46 import android.telephony.SignalStrength;
47 import android.telephony.SubscriptionManager;
48 import android.telephony.VoLteServiceState;
49 import android.telephony.ModemActivityInfo;
50 import android.text.TextUtils;
51 
52 import com.android.ims.ImsManager;
53 import com.android.internal.R;
54 import com.android.internal.telephony.dataconnection.DcTrackerBase;
55 import com.android.internal.telephony.imsphone.ImsPhone;
56 import com.android.internal.telephony.imsphone.ImsPhoneConnection;
57 import com.android.internal.telephony.test.SimulatedRadioControl;
58 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
59 import com.android.internal.telephony.uicc.IccFileHandler;
60 import com.android.internal.telephony.uicc.IccRecords;
61 import com.android.internal.telephony.uicc.IsimRecords;
62 import com.android.internal.telephony.uicc.UiccCard;
63 import com.android.internal.telephony.uicc.UiccCardApplication;
64 import com.android.internal.telephony.uicc.UiccController;
65 import com.android.internal.telephony.uicc.UsimServiceTable;
66 
67 import java.io.FileDescriptor;
68 import java.io.PrintWriter;
69 import java.util.ArrayList;
70 import java.util.HashSet;
71 import java.util.List;
72 import java.util.Locale;
73 import java.util.Set;
74 import java.util.concurrent.atomic.AtomicReference;
75 
76 /**
77  * (<em>Not for SDK use</em>)
78  * A base implementation for the com.android.internal.telephony.Phone interface.
79  *
80  * Note that implementations of Phone.java are expected to be used
81  * from a single application thread. This should be the same thread that
82  * originally called PhoneFactory to obtain the interface.
83  *
84  *  {@hide}
85  *
86  */
87 
88 public abstract class PhoneBase extends Handler implements Phone {
89     private static final String LOG_TAG = "PhoneBase";
90 
91     private boolean mImsIntentReceiverRegistered = false;
92     private BroadcastReceiver mImsIntentReceiver = new BroadcastReceiver() {
93         @Override
94         public void onReceive(Context context, Intent intent) {
95             Rlog.d(LOG_TAG, "mImsIntentReceiver: action " + intent.getAction());
96             if (intent.hasExtra(ImsManager.EXTRA_PHONE_ID)) {
97                 int extraPhoneId = intent.getIntExtra(ImsManager.EXTRA_PHONE_ID,
98                         SubscriptionManager.INVALID_PHONE_INDEX);
99                 Rlog.d(LOG_TAG, "mImsIntentReceiver: extraPhoneId = " + extraPhoneId);
100                 if (extraPhoneId == SubscriptionManager.INVALID_PHONE_INDEX ||
101                         extraPhoneId != getPhoneId()) {
102                     return;
103                 }
104             }
105 
106             synchronized (PhoneProxy.lockForRadioTechnologyChange) {
107                 if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_UP)) {
108                     mImsServiceReady = true;
109                     updateImsPhone();
110                 } else if (intent.getAction().equals(ImsManager.ACTION_IMS_SERVICE_DOWN)) {
111                     mImsServiceReady = false;
112                     updateImsPhone();
113                 }
114             }
115         }
116     };
117 
118     // Key used to read and write the saved network selection numeric value
119     public static final String NETWORK_SELECTION_KEY = "network_selection_key";
120     // Key used to read and write the saved network selection operator name
121     public static final String NETWORK_SELECTION_NAME_KEY = "network_selection_name_key";
122     // Key used to read and write the saved network selection operator short name
123     public static final String NETWORK_SELECTION_SHORT_KEY = "network_selection_short_key";
124 
125 
126     // Key used to read/write "disable data connection on boot" pref (used for testing)
127     public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
128 
129     /* Event Constants */
130     protected static final int EVENT_RADIO_AVAILABLE             = 1;
131     /** Supplementary Service Notification received. */
132     protected static final int EVENT_SSN                         = 2;
133     protected static final int EVENT_SIM_RECORDS_LOADED          = 3;
134     protected static final int EVENT_MMI_DONE                    = 4;
135     protected static final int EVENT_RADIO_ON                    = 5;
136     protected static final int EVENT_GET_BASEBAND_VERSION_DONE   = 6;
137     protected static final int EVENT_USSD                        = 7;
138     protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE  = 8;
139     protected static final int EVENT_GET_IMEI_DONE               = 9;
140     protected static final int EVENT_GET_IMEISV_DONE             = 10;
141     protected static final int EVENT_GET_SIM_STATUS_DONE         = 11;
142     protected static final int EVENT_SET_CALL_FORWARD_DONE       = 12;
143     protected static final int EVENT_GET_CALL_FORWARD_DONE       = 13;
144     protected static final int EVENT_CALL_RING                   = 14;
145     protected static final int EVENT_CALL_RING_CONTINUE          = 15;
146 
147     // Used to intercept the carrier selection calls so that
148     // we can save the values.
149     protected static final int EVENT_SET_NETWORK_MANUAL_COMPLETE    = 16;
150     protected static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 17;
151     protected static final int EVENT_SET_CLIR_COMPLETE              = 18;
152     protected static final int EVENT_REGISTERED_TO_NETWORK          = 19;
153     protected static final int EVENT_SET_VM_NUMBER_DONE             = 20;
154     // Events for CDMA support
155     protected static final int EVENT_GET_DEVICE_IDENTITY_DONE       = 21;
156     protected static final int EVENT_RUIM_RECORDS_LOADED            = 22;
157     protected static final int EVENT_NV_READY                       = 23;
158     protected static final int EVENT_SET_ENHANCED_VP                = 24;
159     protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER  = 25;
160     protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 26;
161     protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 27;
162     // other
163     protected static final int EVENT_SET_NETWORK_AUTOMATIC          = 28;
164     protected static final int EVENT_ICC_RECORD_EVENTS              = 29;
165     protected static final int EVENT_ICC_CHANGED                    = 30;
166     // Single Radio Voice Call Continuity
167     protected static final int EVENT_SRVCC_STATE_CHANGED            = 31;
168     protected static final int EVENT_INITIATE_SILENT_REDIAL         = 32;
169     protected static final int EVENT_RADIO_NOT_AVAILABLE            = 33;
170     protected static final int EVENT_UNSOL_OEM_HOOK_RAW             = 34;
171     protected static final int EVENT_GET_RADIO_CAPABILITY           = 35;
172     protected static final int EVENT_SS                             = 36;
173     protected static final int EVENT_CONFIG_LCE                     = 37;
174     private static final int EVENT_CHECK_FOR_NETWORK_AUTOMATIC      = 38;
175     protected static final int EVENT_LAST                           =
176             EVENT_CHECK_FOR_NETWORK_AUTOMATIC;
177 
178     // For shared prefs.
179     private static final String GSM_ROAMING_LIST_OVERRIDE_PREFIX = "gsm_roaming_list_";
180     private static final String GSM_NON_ROAMING_LIST_OVERRIDE_PREFIX = "gsm_non_roaming_list_";
181     private static final String CDMA_ROAMING_LIST_OVERRIDE_PREFIX = "cdma_roaming_list_";
182     private static final String CDMA_NON_ROAMING_LIST_OVERRIDE_PREFIX = "cdma_non_roaming_list_";
183 
184     // Key used to read/write current CLIR setting
185     public static final String CLIR_KEY = "clir_key";
186 
187     // Key used for storing voice mail count
188     public static final String VM_COUNT = "vm_count_key";
189     // Key used to read/write the ID for storing the voice mail
190     public static final String VM_ID = "vm_id_key";
191 
192     // Key used to read/write "disable DNS server check" pref (used for testing)
193     public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
194 
195     /**
196      * Small container class used to hold information relevant to
197      * the carrier selection process. operatorNumeric can be ""
198      * if we are looking for automatic selection. operatorAlphaLong is the
199      * corresponding operator name.
200      */
201     protected static class NetworkSelectMessage {
202         public Message message;
203         public String operatorNumeric;
204         public String operatorAlphaLong;
205         public String operatorAlphaShort;
206     }
207 
208     /* Instance Variables */
209     public CommandsInterface mCi;
210     private int mVmCount = 0;
211     boolean mDnsCheckDisabled;
212     public DcTrackerBase mDcTracker;
213     boolean mDoesRilSendMultipleCallRing;
214     int mCallRingContinueToken;
215     int mCallRingDelay;
216     public boolean mIsTheCurrentActivePhone = true;
217     boolean mIsVoiceCapable = true;
218 
219     // Variable to cache the video capability. When RAT changes, we lose this info and are unable
220     // to recover from the state. We cache it and notify listeners when they register.
221     protected boolean mIsVideoCapable = false;
222     protected UiccController mUiccController = null;
223     public final AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
224     public SmsStorageMonitor mSmsStorageMonitor;
225     public SmsUsageMonitor mSmsUsageMonitor;
226     protected AtomicReference<UiccCardApplication> mUiccApplication =
227             new AtomicReference<UiccCardApplication>();
228 
229     private TelephonyTester mTelephonyTester;
230     private final String mName;
231     private final String mActionDetached;
232     private final String mActionAttached;
233 
234     protected int mPhoneId;
235 
236     private boolean mImsServiceReady = false;
237     protected ImsPhone mImsPhone = null;
238 
239     private final AtomicReference<RadioCapability> mRadioCapability =
240             new AtomicReference<RadioCapability>();
241 
242     protected static final int DEFAULT_REPORT_INTERVAL_MS = 200;
243     protected static final boolean LCE_PULL_MODE = true;
244     protected int mReportInterval = 0;  // ms
245     protected int mLceStatus = RILConstants.LCE_NOT_AVAILABLE;
246 
247     @Override
getPhoneName()248     public String getPhoneName() {
249         return mName;
250     }
251 
getNai()252     public String getNai(){
253          return null;
254     }
255 
256     /**
257      * Return the ActionDetached string. When this action is received by components
258      * they are to simulate detaching from the network.
259      *
260      * @return com.android.internal.telephony.{mName}.action_detached
261      *          {mName} is GSM, CDMA ...
262      */
getActionDetached()263     public String getActionDetached() {
264         return mActionDetached;
265     }
266 
267     /**
268      * Return the ActionAttached string. When this action is received by components
269      * they are to simulate attaching to the network.
270      *
271      * @return com.android.internal.telephony.{mName}.action_detached
272      *          {mName} is GSM, CDMA ...
273      */
getActionAttached()274     public String getActionAttached() {
275         return mActionAttached;
276     }
277 
278     /**
279      * Set a system property, unless we're in unit test mode
280      */
281     // CAF_MSIM TODO this need to be replated with TelephonyManager API ?
setSystemProperty(String property, String value)282     public void setSystemProperty(String property, String value) {
283         if(getUnitTestMode()) {
284             return;
285         }
286         SystemProperties.set(property, value);
287     }
288 
289     /**
290      * Set a system property, unless we're in unit test mode
291      */
292     // CAF_MSIM TODO this need to be replated with TelephonyManager API ?
getSystemProperty(String property, String defValue)293     public String getSystemProperty(String property, String defValue) {
294         if(getUnitTestMode()) {
295             return null;
296         }
297         return SystemProperties.get(property, defValue);
298     }
299 
300 
301     protected final RegistrantList mPreciseCallStateRegistrants
302             = new RegistrantList();
303 
304     protected final RegistrantList mHandoverRegistrants
305              = new RegistrantList();
306 
307     protected final RegistrantList mNewRingingConnectionRegistrants
308             = new RegistrantList();
309 
310     protected final RegistrantList mIncomingRingRegistrants
311             = new RegistrantList();
312 
313     protected final RegistrantList mDisconnectRegistrants
314             = new RegistrantList();
315 
316     protected final RegistrantList mServiceStateRegistrants
317             = new RegistrantList();
318 
319     protected final RegistrantList mMmiCompleteRegistrants
320             = new RegistrantList();
321 
322     protected final RegistrantList mMmiRegistrants
323             = new RegistrantList();
324 
325     protected final RegistrantList mUnknownConnectionRegistrants
326             = new RegistrantList();
327 
328     protected final RegistrantList mSuppServiceFailedRegistrants
329             = new RegistrantList();
330 
331     protected final RegistrantList mRadioOffOrNotAvailableRegistrants
332             = new RegistrantList();
333 
334     protected final RegistrantList mSimRecordsLoadedRegistrants
335             = new RegistrantList();
336 
337     protected final RegistrantList mVideoCapabilityChangedRegistrants
338             = new RegistrantList();
339 
340     protected final RegistrantList mEmergencyCallToggledRegistrants
341             = new RegistrantList();
342 
343 
344     protected Looper mLooper; /* to insure registrants are in correct thread*/
345 
346     protected final Context mContext;
347 
348     /**
349      * PhoneNotifier is an abstraction for all system-wide
350      * state change notification. DefaultPhoneNotifier is
351      * used here unless running we're inside a unit test.
352      */
353     protected PhoneNotifier mNotifier;
354 
355     protected SimulatedRadioControl mSimulatedRadioControl;
356 
357     boolean mUnitTestMode;
358 
359     /**
360      * Constructs a PhoneBase in normal (non-unit test) mode.
361      *
362      * @param notifier An instance of DefaultPhoneNotifier,
363      * @param context Context object from hosting application
364      * unless unit testing.
365      * @param ci the CommandsInterface
366      */
PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci)367     protected PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci) {
368         this(name, notifier, context, ci, false);
369     }
370 
371     /**
372      * Constructs a PhoneBase in normal (non-unit test) mode.
373      *
374      * @param notifier An instance of DefaultPhoneNotifier,
375      * @param context Context object from hosting application
376      * unless unit testing.
377      * @param ci is CommandsInterface
378      * @param unitTestMode when true, prevents notifications
379      * of state change events
380      */
PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci, boolean unitTestMode)381     protected PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci,
382             boolean unitTestMode) {
383         this(name, notifier, context, ci, unitTestMode, SubscriptionManager.DEFAULT_PHONE_INDEX);
384     }
385 
386     /**
387      * Constructs a PhoneBase in normal (non-unit test) mode.
388      *
389      * @param notifier An instance of DefaultPhoneNotifier,
390      * @param context Context object from hosting application
391      * unless unit testing.
392      * @param ci is CommandsInterface
393      * @param unitTestMode when true, prevents notifications
394      * of state change events
395      * @param phoneId the phone-id of this phone.
396      */
PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci, boolean unitTestMode, int phoneId)397     protected PhoneBase(String name, PhoneNotifier notifier, Context context, CommandsInterface ci,
398             boolean unitTestMode, int phoneId) {
399         mPhoneId = phoneId;
400         mName = name;
401         mNotifier = notifier;
402         mContext = context;
403         mLooper = Looper.myLooper();
404         mCi = ci;
405         mActionDetached = this.getClass().getPackage().getName() + ".action_detached";
406         mActionAttached = this.getClass().getPackage().getName() + ".action_attached";
407 
408         if (Build.IS_DEBUGGABLE) {
409             mTelephonyTester = new TelephonyTester(this);
410         }
411 
412         setUnitTestMode(unitTestMode);
413 
414         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
415         mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
416         mCi.setOnCallRing(this, EVENT_CALL_RING, null);
417 
418         /* "Voice capable" means that this device supports circuit-switched
419         * (i.e. voice) phone calls over the telephony network, and is allowed
420         * to display the in-call UI while a cellular voice call is active.
421         * This will be false on "data only" devices which can't make voice
422         * calls and don't support any in-call UI.
423         */
424         mIsVoiceCapable = mContext.getResources().getBoolean(
425                 com.android.internal.R.bool.config_voice_capable);
426 
427         /**
428          *  Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs
429          *  to be generated locally. Ideally all ring tones should be loops
430          * and this wouldn't be necessary. But to minimize changes to upper
431          * layers it is requested that it be generated by lower layers.
432          *
433          * By default old phones won't have the property set but do generate
434          * the RIL_UNSOL_CALL_RING so the default if there is no property is
435          * true.
436          */
437         mDoesRilSendMultipleCallRing = SystemProperties.getBoolean(
438                 TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true);
439         Rlog.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
440 
441         mCallRingDelay = SystemProperties.getInt(
442                 TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000);
443         Rlog.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
444 
445         if (getPhoneType() == PhoneConstants.PHONE_TYPE_IMS) {
446             return;
447         }
448 
449         // The locale from the "ro.carrier" system property or R.array.carrier_properties.
450         // This will be overwritten by the Locale from the SIM language settings (EF-PL, EF-LI)
451         // if applicable.
452         final Locale carrierLocale = getLocaleFromCarrierProperties(mContext);
453         if (carrierLocale != null && !TextUtils.isEmpty(carrierLocale.getCountry())) {
454             final String country = carrierLocale.getCountry();
455             try {
456                 Settings.Global.getInt(mContext.getContentResolver(),
457                         Settings.Global.WIFI_COUNTRY_CODE);
458             } catch (Settings.SettingNotFoundException e) {
459                 // note this is not persisting
460                 WifiManager wM = (WifiManager)
461                         mContext.getSystemService(Context.WIFI_SERVICE);
462                 wM.setCountryCode(country, false);
463             }
464         }
465 
466         // Initialize device storage and outgoing SMS usage monitors for SMSDispatchers.
467         mSmsStorageMonitor = new SmsStorageMonitor(this);
468         mSmsUsageMonitor = new SmsUsageMonitor(context);
469         mUiccController = UiccController.getInstance();
470         mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
471         if (getPhoneType() != PhoneConstants.PHONE_TYPE_SIP) {
472             mCi.registerForSrvccStateChanged(this, EVENT_SRVCC_STATE_CHANGED, null);
473         }
474         mCi.setOnUnsolOemHookRaw(this, EVENT_UNSOL_OEM_HOOK_RAW, null);
475         mCi.startLceService(DEFAULT_REPORT_INTERVAL_MS, LCE_PULL_MODE,
476                 obtainMessage(EVENT_CONFIG_LCE));
477     }
478 
479     @Override
startMonitoringImsService()480     public void startMonitoringImsService() {
481         if (getPhoneType() == PhoneConstants.PHONE_TYPE_SIP) {
482             return;
483         }
484 
485         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
486             IntentFilter filter = new IntentFilter();
487             filter.addAction(ImsManager.ACTION_IMS_SERVICE_UP);
488             filter.addAction(ImsManager.ACTION_IMS_SERVICE_DOWN);
489             mContext.registerReceiver(mImsIntentReceiver, filter);
490             mImsIntentReceiverRegistered = true;
491 
492             // Monitor IMS service - but first poll to see if already up (could miss
493             // intent)
494             ImsManager imsManager = ImsManager.getInstance(mContext, getPhoneId());
495             if (imsManager != null && imsManager.isServiceAvailable()) {
496                 mImsServiceReady = true;
497                 updateImsPhone();
498             }
499         }
500     }
501 
502     @Override
dispose()503     public void dispose() {
504         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
505             if (mImsIntentReceiverRegistered) {
506                 mContext.unregisterReceiver(mImsIntentReceiver);
507                 mImsIntentReceiverRegistered = false;
508             }
509             mCi.unSetOnCallRing(this);
510             // Must cleanup all connectionS and needs to use sendMessage!
511             mDcTracker.cleanUpAllConnections(null);
512             mIsTheCurrentActivePhone = false;
513             // Dispose the SMS usage and storage monitors
514             mSmsStorageMonitor.dispose();
515             mSmsUsageMonitor.dispose();
516             mUiccController.unregisterForIccChanged(this);
517             mCi.unregisterForSrvccStateChanged(this);
518             mCi.unSetOnUnsolOemHookRaw(this);
519             mCi.stopLceService(obtainMessage(EVENT_CONFIG_LCE));
520 
521             if (mTelephonyTester != null) {
522                 mTelephonyTester.dispose();
523             }
524 
525             ImsPhone imsPhone = mImsPhone;
526             if (imsPhone != null) {
527                 imsPhone.unregisterForSilentRedial(this);
528                 imsPhone.dispose();
529             }
530         }
531     }
532 
533     @Override
removeReferences()534     public void removeReferences() {
535         mSmsStorageMonitor = null;
536         mSmsUsageMonitor = null;
537         mIccRecords.set(null);
538         mUiccApplication.set(null);
539         mDcTracker = null;
540         mUiccController = null;
541 
542         ImsPhone imsPhone = mImsPhone;
543         if (imsPhone != null) {
544             imsPhone.removeReferences();
545             mImsPhone = null;
546         }
547     }
548 
549     /**
550      * When overridden the derived class needs to call
551      * super.handleMessage(msg) so this method has a
552      * a chance to process the message.
553      *
554      * @param msg
555      */
556     @Override
handleMessage(Message msg)557     public void handleMessage(Message msg) {
558         AsyncResult ar;
559 
560         // messages to be handled whether or not the phone is being destroyed
561         // should only include messages which are being re-directed and do not use
562         // resources of the phone being destroyed
563         // Note: make sure to add code in GSMPhone/CDMAPhone to re-direct here before
564         // they check if phone destroyed.
565         switch (msg.what) {
566             // handle the select network completion callbacks.
567             case EVENT_SET_NETWORK_MANUAL_COMPLETE:
568             case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE:
569                 handleSetSelectNetwork((AsyncResult) msg.obj);
570                 return;
571         }
572 
573         if (!mIsTheCurrentActivePhone) {
574             Rlog.e(LOG_TAG, "Received message " + msg +
575                     "[" + msg.what + "] while being destroyed. Ignoring.");
576             return;
577         }
578         switch(msg.what) {
579             case EVENT_CALL_RING:
580                 Rlog.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState());
581                 ar = (AsyncResult)msg.obj;
582                 if (ar.exception == null) {
583                     PhoneConstants.State state = getState();
584                     if ((!mDoesRilSendMultipleCallRing)
585                             && ((state == PhoneConstants.State.RINGING) ||
586                                     (state == PhoneConstants.State.IDLE))) {
587                         mCallRingContinueToken += 1;
588                         sendIncomingCallRingNotification(mCallRingContinueToken);
589                     } else {
590                         notifyIncomingRing();
591                     }
592                 }
593                 break;
594 
595             case EVENT_CALL_RING_CONTINUE:
596                 Rlog.d(LOG_TAG, "Event EVENT_CALL_RING_CONTINUE Received stat=" + getState());
597                 if (getState() == PhoneConstants.State.RINGING) {
598                     sendIncomingCallRingNotification(msg.arg1);
599                 }
600                 break;
601 
602             case EVENT_ICC_CHANGED:
603                 onUpdateIccAvailability();
604                 break;
605 
606             case EVENT_INITIATE_SILENT_REDIAL:
607                 Rlog.d(LOG_TAG, "Event EVENT_INITIATE_SILENT_REDIAL Received");
608                 ar = (AsyncResult) msg.obj;
609                 if ((ar.exception == null) && (ar.result != null)) {
610                     String dialString = (String) ar.result;
611                     if (TextUtils.isEmpty(dialString)) return;
612                     try {
613                         dialInternal(dialString, null, VideoProfile.STATE_AUDIO_ONLY, null);
614                     } catch (CallStateException e) {
615                         Rlog.e(LOG_TAG, "silent redial failed: " + e);
616                     }
617                 }
618                 break;
619 
620             case EVENT_SRVCC_STATE_CHANGED:
621                 ar = (AsyncResult)msg.obj;
622                 if (ar.exception == null) {
623                     handleSrvccStateChanged((int[]) ar.result);
624                 } else {
625                     Rlog.e(LOG_TAG, "Srvcc exception: " + ar.exception);
626                 }
627                 break;
628 
629             case EVENT_UNSOL_OEM_HOOK_RAW:
630                 ar = (AsyncResult)msg.obj;
631                 if (ar.exception == null) {
632                     byte[] data = (byte[])ar.result;
633                     Rlog.d(LOG_TAG, "EVENT_UNSOL_OEM_HOOK_RAW data="
634                             + IccUtils.bytesToHexString(data));
635                     mNotifier.notifyOemHookRawEventForSubscriber(getSubId(), data);
636                 } else {
637                     Rlog.e(LOG_TAG, "OEM hook raw exception: " + ar.exception);
638                 }
639                 break;
640 
641             case EVENT_GET_RADIO_CAPABILITY:
642                 ar = (AsyncResult) msg.obj;
643                 RadioCapability rc = (RadioCapability) ar.result;
644                 if (ar.exception != null) {
645                     Rlog.d(LOG_TAG, "get phone radio capability fail,"
646                             + "no need to change mRadioCapability");
647                 } else {
648                     radioCapabilityUpdated(rc);
649                 }
650                 Rlog.d(LOG_TAG, "EVENT_GET_RADIO_CAPABILITY :"
651                         + "phone rc : " + rc);
652                 break;
653 
654             case EVENT_CONFIG_LCE:
655                 ar = (AsyncResult) msg.obj;
656                 if (ar.exception != null) {
657                     Rlog.d(LOG_TAG, "config LCE service failed: " + ar.exception);
658                 } else {
659                     final ArrayList<Integer> statusInfo = (ArrayList<Integer>)ar.result;
660                     mLceStatus = statusInfo.get(0);
661                     mReportInterval = statusInfo.get(1);
662                 }
663                 break;
664 
665             case EVENT_CHECK_FOR_NETWORK_AUTOMATIC: {
666                 onCheckForNetworkSelectionModeAutomatic(msg);
667                 break;
668             }
669             default:
670                 throw new RuntimeException("unexpected event not handled");
671         }
672     }
673 
handleSrvccStateChanged(int[] ret)674     private void handleSrvccStateChanged(int[] ret) {
675         Rlog.d(LOG_TAG, "handleSrvccStateChanged");
676 
677         ArrayList<Connection> conn = null;
678         ImsPhone imsPhone = mImsPhone;
679         Call.SrvccState srvccState = Call.SrvccState.NONE;
680         if (ret != null && ret.length != 0) {
681             int state = ret[0];
682             switch(state) {
683                 case VoLteServiceState.HANDOVER_STARTED:
684                     srvccState = Call.SrvccState.STARTED;
685                     if (imsPhone != null) {
686                         conn = imsPhone.getHandoverConnection();
687                         migrateFrom(imsPhone);
688                     } else {
689                         Rlog.d(LOG_TAG, "HANDOVER_STARTED: mImsPhone null");
690                     }
691                     break;
692                 case VoLteServiceState.HANDOVER_COMPLETED:
693                     srvccState = Call.SrvccState.COMPLETED;
694                     if (imsPhone != null) {
695                         imsPhone.notifySrvccState(srvccState);
696                     } else {
697                         Rlog.d(LOG_TAG, "HANDOVER_COMPLETED: mImsPhone null");
698                     }
699                     break;
700                 case VoLteServiceState.HANDOVER_FAILED:
701                 case VoLteServiceState.HANDOVER_CANCELED:
702                     srvccState = Call.SrvccState.FAILED;
703                     break;
704 
705                 default:
706                     //ignore invalid state
707                     return;
708             }
709 
710             getCallTracker().notifySrvccState(srvccState, conn);
711 
712             VoLteServiceState lteState = new VoLteServiceState(state);
713             notifyVoLteServiceStateChanged(lteState);
714         }
715     }
716 
717     // Inherited documentation suffices.
718     @Override
getContext()719     public Context getContext() {
720         return mContext;
721     }
722 
723     // Will be called when icc changed
onUpdateIccAvailability()724     protected abstract void onUpdateIccAvailability();
725 
726     /**
727      * Disables the DNS check (i.e., allows "0.0.0.0").
728      * Useful for lab testing environment.
729      * @param b true disables the check, false enables.
730      */
731     @Override
disableDnsCheck(boolean b)732     public void disableDnsCheck(boolean b) {
733         mDnsCheckDisabled = b;
734         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
735         SharedPreferences.Editor editor = sp.edit();
736         editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);
737         editor.apply();
738     }
739 
740     /**
741      * Returns true if the DNS check is currently disabled.
742      */
743     @Override
isDnsCheckDisabled()744     public boolean isDnsCheckDisabled() {
745         return mDnsCheckDisabled;
746     }
747 
748     // Inherited documentation suffices.
749     @Override
registerForPreciseCallStateChanged(Handler h, int what, Object obj)750     public void registerForPreciseCallStateChanged(Handler h, int what, Object obj) {
751         checkCorrectThread(h);
752 
753         mPreciseCallStateRegistrants.addUnique(h, what, obj);
754     }
755 
756     // Inherited documentation suffices.
757     @Override
unregisterForPreciseCallStateChanged(Handler h)758     public void unregisterForPreciseCallStateChanged(Handler h) {
759         mPreciseCallStateRegistrants.remove(h);
760     }
761 
762     /**
763      * Subclasses of Phone probably want to replace this with a
764      * version scoped to their packages
765      */
notifyPreciseCallStateChangedP()766     protected void notifyPreciseCallStateChangedP() {
767         AsyncResult ar = new AsyncResult(null, this, null);
768         mPreciseCallStateRegistrants.notifyRegistrants(ar);
769 
770         mNotifier.notifyPreciseCallState(this);
771     }
772 
773     @Override
registerForHandoverStateChanged(Handler h, int what, Object obj)774     public void registerForHandoverStateChanged(Handler h, int what, Object obj) {
775         checkCorrectThread(h);
776         mHandoverRegistrants.addUnique(h, what, obj);
777     }
778 
779     @Override
unregisterForHandoverStateChanged(Handler h)780     public void unregisterForHandoverStateChanged(Handler h) {
781         mHandoverRegistrants.remove(h);
782     }
783 
784     /**
785      * Subclasses of Phone probably want to replace this with a
786      * version scoped to their packages
787      */
notifyHandoverStateChanged(Connection cn)788     public void notifyHandoverStateChanged(Connection cn) {
789        AsyncResult ar = new AsyncResult(null, cn, null);
790        mHandoverRegistrants.notifyRegistrants(ar);
791     }
792 
migrateFrom(PhoneBase from)793     public void migrateFrom(PhoneBase from) {
794         migrate(mHandoverRegistrants, from.mHandoverRegistrants);
795         migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants);
796         migrate(mNewRingingConnectionRegistrants, from.mNewRingingConnectionRegistrants);
797         migrate(mIncomingRingRegistrants, from.mIncomingRingRegistrants);
798         migrate(mDisconnectRegistrants, from.mDisconnectRegistrants);
799         migrate(mServiceStateRegistrants, from.mServiceStateRegistrants);
800         migrate(mMmiCompleteRegistrants, from.mMmiCompleteRegistrants);
801         migrate(mMmiRegistrants, from.mMmiRegistrants);
802         migrate(mUnknownConnectionRegistrants, from.mUnknownConnectionRegistrants);
803         migrate(mSuppServiceFailedRegistrants, from.mSuppServiceFailedRegistrants);
804     }
805 
migrate(RegistrantList to, RegistrantList from)806     public void migrate(RegistrantList to, RegistrantList from) {
807         from.removeCleared();
808         for (int i = 0, n = from.size(); i < n; i++) {
809             to.add((Registrant) from.get(i));
810         }
811     }
812 
813     // Inherited documentation suffices.
814     @Override
registerForUnknownConnection(Handler h, int what, Object obj)815     public void registerForUnknownConnection(Handler h, int what, Object obj) {
816         checkCorrectThread(h);
817 
818         mUnknownConnectionRegistrants.addUnique(h, what, obj);
819     }
820 
821     // Inherited documentation suffices.
822     @Override
unregisterForUnknownConnection(Handler h)823     public void unregisterForUnknownConnection(Handler h) {
824         mUnknownConnectionRegistrants.remove(h);
825     }
826 
827     // Inherited documentation suffices.
828     @Override
registerForNewRingingConnection( Handler h, int what, Object obj)829     public void registerForNewRingingConnection(
830             Handler h, int what, Object obj) {
831         checkCorrectThread(h);
832 
833         mNewRingingConnectionRegistrants.addUnique(h, what, obj);
834     }
835 
836     // Inherited documentation suffices.
837     @Override
unregisterForNewRingingConnection(Handler h)838     public void unregisterForNewRingingConnection(Handler h) {
839         mNewRingingConnectionRegistrants.remove(h);
840     }
841 
842     // Inherited documentation suffices.
843     @Override
registerForVideoCapabilityChanged( Handler h, int what, Object obj)844     public void registerForVideoCapabilityChanged(
845             Handler h, int what, Object obj) {
846         checkCorrectThread(h);
847 
848         mVideoCapabilityChangedRegistrants.addUnique(h, what, obj);
849 
850         // Notify any registrants of the cached video capability as soon as they register.
851         notifyForVideoCapabilityChanged(mIsVideoCapable);
852     }
853 
854     // Inherited documentation suffices.
855     @Override
unregisterForVideoCapabilityChanged(Handler h)856     public void unregisterForVideoCapabilityChanged(Handler h) {
857         mVideoCapabilityChangedRegistrants.remove(h);
858     }
859 
860     // Inherited documentation suffices.
861     @Override
registerForInCallVoicePrivacyOn(Handler h, int what, Object obj)862     public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
863         mCi.registerForInCallVoicePrivacyOn(h, what, obj);
864     }
865 
866     // Inherited documentation suffices.
867     @Override
unregisterForInCallVoicePrivacyOn(Handler h)868     public void unregisterForInCallVoicePrivacyOn(Handler h){
869         mCi.unregisterForInCallVoicePrivacyOn(h);
870     }
871 
872     // Inherited documentation suffices.
873     @Override
registerForInCallVoicePrivacyOff(Handler h, int what, Object obj)874     public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
875         mCi.registerForInCallVoicePrivacyOff(h, what, obj);
876     }
877 
878     // Inherited documentation suffices.
879     @Override
unregisterForInCallVoicePrivacyOff(Handler h)880     public void unregisterForInCallVoicePrivacyOff(Handler h){
881         mCi.unregisterForInCallVoicePrivacyOff(h);
882     }
883 
884     // Inherited documentation suffices.
885     @Override
registerForIncomingRing( Handler h, int what, Object obj)886     public void registerForIncomingRing(
887             Handler h, int what, Object obj) {
888         checkCorrectThread(h);
889 
890         mIncomingRingRegistrants.addUnique(h, what, obj);
891     }
892 
893     // Inherited documentation suffices.
894     @Override
unregisterForIncomingRing(Handler h)895     public void unregisterForIncomingRing(Handler h) {
896         mIncomingRingRegistrants.remove(h);
897     }
898 
899     // Inherited documentation suffices.
900     @Override
registerForDisconnect(Handler h, int what, Object obj)901     public void registerForDisconnect(Handler h, int what, Object obj) {
902         checkCorrectThread(h);
903 
904         mDisconnectRegistrants.addUnique(h, what, obj);
905     }
906 
907     // Inherited documentation suffices.
908     @Override
unregisterForDisconnect(Handler h)909     public void unregisterForDisconnect(Handler h) {
910         mDisconnectRegistrants.remove(h);
911     }
912 
913     // Inherited documentation suffices.
914     @Override
registerForSuppServiceFailed(Handler h, int what, Object obj)915     public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
916         checkCorrectThread(h);
917 
918         mSuppServiceFailedRegistrants.addUnique(h, what, obj);
919     }
920 
921     // Inherited documentation suffices.
922     @Override
unregisterForSuppServiceFailed(Handler h)923     public void unregisterForSuppServiceFailed(Handler h) {
924         mSuppServiceFailedRegistrants.remove(h);
925     }
926 
927     // Inherited documentation suffices.
928     @Override
registerForMmiInitiate(Handler h, int what, Object obj)929     public void registerForMmiInitiate(Handler h, int what, Object obj) {
930         checkCorrectThread(h);
931 
932         mMmiRegistrants.addUnique(h, what, obj);
933     }
934 
935     // Inherited documentation suffices.
936     @Override
unregisterForMmiInitiate(Handler h)937     public void unregisterForMmiInitiate(Handler h) {
938         mMmiRegistrants.remove(h);
939     }
940 
941     // Inherited documentation suffices.
942     @Override
registerForMmiComplete(Handler h, int what, Object obj)943     public void registerForMmiComplete(Handler h, int what, Object obj) {
944         checkCorrectThread(h);
945 
946         mMmiCompleteRegistrants.addUnique(h, what, obj);
947     }
948 
949     // Inherited documentation suffices.
950     @Override
unregisterForMmiComplete(Handler h)951     public void unregisterForMmiComplete(Handler h) {
952         checkCorrectThread(h);
953 
954         mMmiCompleteRegistrants.remove(h);
955     }
956 
registerForSimRecordsLoaded(Handler h, int what, Object obj)957     public void registerForSimRecordsLoaded(Handler h, int what, Object obj) {
958         logUnexpectedCdmaMethodCall("registerForSimRecordsLoaded");
959     }
960 
unregisterForSimRecordsLoaded(Handler h)961     public void unregisterForSimRecordsLoaded(Handler h) {
962         logUnexpectedCdmaMethodCall("unregisterForSimRecordsLoaded");
963     }
964 
965     @Override
registerForTtyModeReceived(Handler h, int what, Object obj)966     public void registerForTtyModeReceived(Handler h, int what, Object obj) {
967     }
968 
969     @Override
unregisterForTtyModeReceived(Handler h)970     public void unregisterForTtyModeReceived(Handler h) {
971     }
972 
973     @Override
setNetworkSelectionModeAutomatic(Message response)974     public void setNetworkSelectionModeAutomatic(Message response) {
975         Rlog.d(LOG_TAG, "setNetworkSelectionModeAutomatic, querying current mode");
976         // we don't want to do this unecesarily - it acutally causes
977         // the radio to repeate network selection and is costly
978         // first check if we're already in automatic mode
979         Message msg = obtainMessage(EVENT_CHECK_FOR_NETWORK_AUTOMATIC);
980         msg.obj = response;
981         mCi.getNetworkSelectionMode(msg);
982     }
983 
onCheckForNetworkSelectionModeAutomatic(Message fromRil)984     private void onCheckForNetworkSelectionModeAutomatic(Message fromRil) {
985         AsyncResult ar = (AsyncResult)fromRil.obj;
986         Message response = (Message)ar.userObj;
987         boolean doAutomatic = true;
988         if (ar.exception == null && ar.result != null) {
989             try {
990                 int[] modes = (int[])ar.result;
991                 if (modes[0] == 0) {
992                     // already confirmed to be in automatic mode - don't resend
993                     doAutomatic = false;
994                 }
995             } catch (Exception e) {
996                 // send the setting on error
997             }
998         }
999         if (doAutomatic) {
1000             // wrap the response message in our own message along with
1001             // an empty string (to indicate automatic selection) for the
1002             // operator's id.
1003             NetworkSelectMessage nsm = new NetworkSelectMessage();
1004             nsm.message = response;
1005             nsm.operatorNumeric = "";
1006             nsm.operatorAlphaLong = "";
1007             nsm.operatorAlphaShort = "";
1008 
1009             Message msg = obtainMessage(EVENT_SET_NETWORK_AUTOMATIC_COMPLETE, nsm);
1010             mCi.setNetworkSelectionModeAutomatic(msg);
1011 
1012             updateSavedNetworkOperator(nsm);
1013         } else {
1014             Rlog.d(LOG_TAG, "setNetworkSelectionModeAutomatic - already auto, ignoring");
1015         }
1016     }
1017 
1018     @Override
getNetworkSelectionMode(Message message)1019     public void getNetworkSelectionMode(Message message) {
1020         mCi.getNetworkSelectionMode(message);
1021     }
1022 
1023     @Override
selectNetworkManually(OperatorInfo network, Message response)1024     public void selectNetworkManually(OperatorInfo network, Message response) {
1025         // wrap the response message in our own message along with
1026         // the operator's id.
1027         NetworkSelectMessage nsm = new NetworkSelectMessage();
1028         nsm.message = response;
1029         nsm.operatorNumeric = network.getOperatorNumeric();
1030         nsm.operatorAlphaLong = network.getOperatorAlphaLong();
1031         nsm.operatorAlphaShort = network.getOperatorAlphaShort();
1032 
1033         Message msg = obtainMessage(EVENT_SET_NETWORK_MANUAL_COMPLETE, nsm);
1034         mCi.setNetworkSelectionModeManual(network.getOperatorNumeric(), msg);
1035 
1036         updateSavedNetworkOperator(nsm);
1037     }
1038 
1039     /**
1040      * Registration point for emergency call/callback mode start. Message.obj is AsyncResult and
1041      * Message.obj.result will be Integer indicating start of call by value 1 or end of call by
1042      * value 0
1043      * @param h handler to notify
1044      * @param what what code of message when delivered
1045      * @param obj placed in Message.obj.userObj
1046      */
registerForEmergencyCallToggle(Handler h, int what, Object obj)1047     public void registerForEmergencyCallToggle(Handler h, int what, Object obj) {
1048         Registrant r = new Registrant(h, what, obj);
1049         mEmergencyCallToggledRegistrants.add(r);
1050     }
1051 
unregisterForEmergencyCallToggle(Handler h)1052     public void unregisterForEmergencyCallToggle(Handler h) {
1053         mEmergencyCallToggledRegistrants.remove(h);
1054     }
1055 
updateSavedNetworkOperator(NetworkSelectMessage nsm)1056     private void updateSavedNetworkOperator(NetworkSelectMessage nsm) {
1057         int subId = getSubId();
1058         if (SubscriptionManager.isValidSubscriptionId(subId)) {
1059             // open the shared preferences editor, and write the value.
1060             // nsm.operatorNumeric is "" if we're in automatic.selection.
1061             SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1062             SharedPreferences.Editor editor = sp.edit();
1063             editor.putString(NETWORK_SELECTION_KEY + subId, nsm.operatorNumeric);
1064             editor.putString(NETWORK_SELECTION_NAME_KEY + subId, nsm.operatorAlphaLong);
1065             editor.putString(NETWORK_SELECTION_SHORT_KEY + subId, nsm.operatorAlphaShort);
1066 
1067             // commit and log the result.
1068             if (!editor.commit()) {
1069                 Rlog.e(LOG_TAG, "failed to commit network selection preference");
1070             }
1071         } else {
1072             Rlog.e(LOG_TAG, "Cannot update network selection preference due to invalid subId " +
1073                     subId);
1074         }
1075     }
1076 
1077     /**
1078      * Used to track the settings upon completion of the network change.
1079      */
handleSetSelectNetwork(AsyncResult ar)1080     private void handleSetSelectNetwork(AsyncResult ar) {
1081         // look for our wrapper within the asyncresult, skip the rest if it
1082         // is null.
1083         if (!(ar.userObj instanceof NetworkSelectMessage)) {
1084             Rlog.e(LOG_TAG, "unexpected result from user object.");
1085             return;
1086         }
1087 
1088         NetworkSelectMessage nsm = (NetworkSelectMessage) ar.userObj;
1089 
1090         // found the object, now we send off the message we had originally
1091         // attached to the request.
1092         if (nsm.message != null) {
1093             AsyncResult.forMessage(nsm.message, ar.result, ar.exception);
1094             nsm.message.sendToTarget();
1095         }
1096     }
1097 
1098     /**
1099      * Method to retrieve the saved operator from the Shared Preferences
1100      */
getSavedNetworkSelection()1101     private OperatorInfo getSavedNetworkSelection() {
1102         // open the shared preferences and search with our key.
1103         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1104         String numeric = sp.getString(NETWORK_SELECTION_KEY + getSubId(), "");
1105         String name = sp.getString(NETWORK_SELECTION_NAME_KEY + getSubId(), "");
1106         String shrt = sp.getString(NETWORK_SELECTION_SHORT_KEY + getSubId(), "");
1107         return new OperatorInfo(numeric, name, shrt);
1108     }
1109 
1110     /**
1111      * Method to restore the previously saved operator id, or reset to
1112      * automatic selection, all depending upon the value in the shared
1113      * preferences.
1114      */
restoreSavedNetworkSelection(Message response)1115     public void restoreSavedNetworkSelection(Message response) {
1116         // retrieve the operator
1117         OperatorInfo networkSelection = getSavedNetworkSelection();
1118 
1119         // set to auto if the id is empty, otherwise select the network.
1120         if (networkSelection == null || TextUtils.isEmpty(networkSelection.getOperatorNumeric())) {
1121             setNetworkSelectionModeAutomatic(response);
1122         } else {
1123             selectNetworkManually(networkSelection, response);
1124         }
1125     }
1126 
1127     // Inherited documentation suffices.
1128     @Override
setUnitTestMode(boolean f)1129     public void setUnitTestMode(boolean f) {
1130         mUnitTestMode = f;
1131     }
1132 
1133     // Inherited documentation suffices.
1134     @Override
getUnitTestMode()1135     public boolean getUnitTestMode() {
1136         return mUnitTestMode;
1137     }
1138 
1139     /**
1140      * To be invoked when a voice call Connection disconnects.
1141      *
1142      * Subclasses of Phone probably want to replace this with a
1143      * version scoped to their packages
1144      */
notifyDisconnectP(Connection cn)1145     protected void notifyDisconnectP(Connection cn) {
1146         AsyncResult ar = new AsyncResult(null, cn, null);
1147         mDisconnectRegistrants.notifyRegistrants(ar);
1148     }
1149 
1150     // Inherited documentation suffices.
1151     @Override
registerForServiceStateChanged( Handler h, int what, Object obj)1152     public void registerForServiceStateChanged(
1153             Handler h, int what, Object obj) {
1154         checkCorrectThread(h);
1155 
1156         mServiceStateRegistrants.add(h, what, obj);
1157     }
1158 
1159     // Inherited documentation suffices.
1160     @Override
unregisterForServiceStateChanged(Handler h)1161     public void unregisterForServiceStateChanged(Handler h) {
1162         mServiceStateRegistrants.remove(h);
1163     }
1164 
1165     // Inherited documentation suffices.
1166     @Override
registerForRingbackTone(Handler h, int what, Object obj)1167     public void registerForRingbackTone(Handler h, int what, Object obj) {
1168         mCi.registerForRingbackTone(h, what, obj);
1169     }
1170 
1171     // Inherited documentation suffices.
1172     @Override
unregisterForRingbackTone(Handler h)1173     public void unregisterForRingbackTone(Handler h) {
1174         mCi.unregisterForRingbackTone(h);
1175     }
1176 
1177     // Inherited documentation suffices.
1178     @Override
registerForOnHoldTone(Handler h, int what, Object obj)1179     public void registerForOnHoldTone(Handler h, int what, Object obj) {
1180     }
1181 
1182     // Inherited documentation suffices.
1183     @Override
unregisterForOnHoldTone(Handler h)1184     public void unregisterForOnHoldTone(Handler h) {
1185     }
1186 
1187     // Inherited documentation suffices.
1188     @Override
registerForResendIncallMute(Handler h, int what, Object obj)1189     public void registerForResendIncallMute(Handler h, int what, Object obj) {
1190         mCi.registerForResendIncallMute(h, what, obj);
1191     }
1192 
1193     // Inherited documentation suffices.
1194     @Override
unregisterForResendIncallMute(Handler h)1195     public void unregisterForResendIncallMute(Handler h) {
1196         mCi.unregisterForResendIncallMute(h);
1197     }
1198 
1199     @Override
setEchoSuppressionEnabled()1200     public void setEchoSuppressionEnabled() {
1201         // no need for regular phone
1202     }
1203 
1204     /**
1205      * Subclasses of Phone probably want to replace this with a
1206      * version scoped to their packages
1207      */
notifyServiceStateChangedP(ServiceState ss)1208     protected void notifyServiceStateChangedP(ServiceState ss) {
1209         AsyncResult ar = new AsyncResult(null, ss, null);
1210         mServiceStateRegistrants.notifyRegistrants(ar);
1211 
1212         mNotifier.notifyServiceState(this);
1213     }
1214 
1215     // Inherited documentation suffices.
1216     @Override
getSimulatedRadioControl()1217     public SimulatedRadioControl getSimulatedRadioControl() {
1218         return mSimulatedRadioControl;
1219     }
1220 
1221     /**
1222      * Verifies the current thread is the same as the thread originally
1223      * used in the initialization of this instance. Throws RuntimeException
1224      * if not.
1225      *
1226      * @exception RuntimeException if the current thread is not
1227      * the thread that originally obtained this PhoneBase instance.
1228      */
checkCorrectThread(Handler h)1229     private void checkCorrectThread(Handler h) {
1230         if (h.getLooper() != mLooper) {
1231             throw new RuntimeException(
1232                     "com.android.internal.telephony.Phone must be used from within one thread");
1233         }
1234     }
1235 
1236     /**
1237      * Set the properties by matching the carrier string in
1238      * a string-array resource
1239      */
getLocaleFromCarrierProperties(Context ctx)1240     private static Locale getLocaleFromCarrierProperties(Context ctx) {
1241         String carrier = SystemProperties.get("ro.carrier");
1242 
1243         if (null == carrier || 0 == carrier.length() || "unknown".equals(carrier)) {
1244             return null;
1245         }
1246 
1247         CharSequence[] carrierLocales = ctx.getResources().getTextArray(R.array.carrier_properties);
1248 
1249         for (int i = 0; i < carrierLocales.length; i+=3) {
1250             String c = carrierLocales[i].toString();
1251             if (carrier.equals(c)) {
1252                 return Locale.forLanguageTag(carrierLocales[i + 1].toString().replace('_', '-'));
1253             }
1254         }
1255 
1256         return null;
1257     }
1258 
1259     /**
1260      * Get state
1261      */
1262     @Override
getState()1263     public abstract PhoneConstants.State getState();
1264 
1265     /**
1266      * Retrieves the IccFileHandler of the Phone instance
1267      */
getIccFileHandler()1268     public IccFileHandler getIccFileHandler(){
1269         UiccCardApplication uiccApplication = mUiccApplication.get();
1270         IccFileHandler fh;
1271 
1272         if (uiccApplication == null) {
1273             Rlog.d(LOG_TAG, "getIccFileHandler: uiccApplication == null, return null");
1274             fh = null;
1275         } else {
1276             fh = uiccApplication.getIccFileHandler();
1277         }
1278 
1279         Rlog.d(LOG_TAG, "getIccFileHandler: fh=" + fh);
1280         return fh;
1281     }
1282 
1283     /*
1284      * Retrieves the Handler of the Phone instance
1285      */
getHandler()1286     public Handler getHandler() {
1287         return this;
1288     }
1289 
1290     @Override
updatePhoneObject(int voiceRadioTech)1291     public void updatePhoneObject(int voiceRadioTech) {
1292         // Only the PhoneProxy can update the phone object.
1293         PhoneFactory.getDefaultPhone().updatePhoneObject(voiceRadioTech);
1294     }
1295 
1296     /**
1297     * Retrieves the ServiceStateTracker of the phone instance.
1298     */
getServiceStateTracker()1299     public ServiceStateTracker getServiceStateTracker() {
1300         return null;
1301     }
1302 
1303     /**
1304     * Get call tracker
1305     */
getCallTracker()1306     public CallTracker getCallTracker() {
1307         return null;
1308     }
1309 
getCurrentUiccAppType()1310     public AppType getCurrentUiccAppType() {
1311         UiccCardApplication currentApp = mUiccApplication.get();
1312         if (currentApp != null) {
1313             return currentApp.getType();
1314         }
1315         return AppType.APPTYPE_UNKNOWN;
1316     }
1317 
1318     @Override
getIccCard()1319     public IccCard getIccCard() {
1320         return null;
1321         //throw new Exception("getIccCard Shouldn't be called from PhoneBase");
1322     }
1323 
1324     @Override
getIccSerialNumber()1325     public String getIccSerialNumber() {
1326         IccRecords r = mIccRecords.get();
1327         return (r != null) ? r.getIccId() : null;
1328     }
1329 
1330     @Override
getIccRecordsLoaded()1331     public boolean getIccRecordsLoaded() {
1332         IccRecords r = mIccRecords.get();
1333         return (r != null) ? r.getRecordsLoaded() : false;
1334     }
1335 
1336     /**
1337      * @return all available cell information or null if none.
1338      */
1339     @Override
getAllCellInfo()1340     public List<CellInfo> getAllCellInfo() {
1341         List<CellInfo> cellInfoList = getServiceStateTracker().getAllCellInfo();
1342         return privatizeCellInfoList(cellInfoList);
1343     }
1344 
1345     /**
1346      * Clear CDMA base station lat/long values if location setting is disabled.
1347      * @param cellInfoList the original cell info list from the RIL
1348      * @return the original list with CDMA lat/long cleared if necessary
1349      */
privatizeCellInfoList(List<CellInfo> cellInfoList)1350     private List<CellInfo> privatizeCellInfoList(List<CellInfo> cellInfoList) {
1351         if (cellInfoList == null) return null;
1352         int mode = Settings.Secure.getInt(getContext().getContentResolver(),
1353                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
1354         if (mode == Settings.Secure.LOCATION_MODE_OFF) {
1355             ArrayList<CellInfo> privateCellInfoList = new ArrayList<CellInfo>(cellInfoList.size());
1356             // clear lat/lon values for location privacy
1357             for (CellInfo c : cellInfoList) {
1358                 if (c instanceof CellInfoCdma) {
1359                     CellInfoCdma cellInfoCdma = (CellInfoCdma) c;
1360                     CellIdentityCdma cellIdentity = cellInfoCdma.getCellIdentity();
1361                     CellIdentityCdma maskedCellIdentity = new CellIdentityCdma(
1362                             cellIdentity.getNetworkId(),
1363                             cellIdentity.getSystemId(),
1364                             cellIdentity.getBasestationId(),
1365                             Integer.MAX_VALUE, Integer.MAX_VALUE);
1366                     CellInfoCdma privateCellInfoCdma = new CellInfoCdma(cellInfoCdma);
1367                     privateCellInfoCdma.setCellIdentity(maskedCellIdentity);
1368                     privateCellInfoList.add(privateCellInfoCdma);
1369                 } else {
1370                     privateCellInfoList.add(c);
1371                 }
1372             }
1373             cellInfoList = privateCellInfoList;
1374         }
1375         return cellInfoList;
1376     }
1377 
1378     /**
1379      * {@inheritDoc}
1380      */
1381     @Override
setCellInfoListRate(int rateInMillis)1382     public void setCellInfoListRate(int rateInMillis) {
1383         mCi.setCellInfoListRate(rateInMillis, null);
1384     }
1385 
1386     @Override
1387     /** @return true if there are messages waiting, false otherwise. */
getMessageWaitingIndicator()1388     public boolean getMessageWaitingIndicator() {
1389         return mVmCount != 0;
1390     }
1391 
1392     @Override
getCallForwardingIndicator()1393     public boolean getCallForwardingIndicator() {
1394         IccRecords r = mIccRecords.get();
1395         return (r != null) ? r.getVoiceCallForwardingFlag() : false;
1396     }
1397 
1398     /**
1399      *  Query the status of the CDMA roaming preference
1400      */
1401     @Override
queryCdmaRoamingPreference(Message response)1402     public void queryCdmaRoamingPreference(Message response) {
1403         mCi.queryCdmaRoamingPreference(response);
1404     }
1405 
1406     /**
1407      * Get the signal strength
1408      */
1409     @Override
getSignalStrength()1410     public SignalStrength getSignalStrength() {
1411         ServiceStateTracker sst = getServiceStateTracker();
1412         if (sst == null) {
1413             return new SignalStrength();
1414         } else {
1415             return sst.getSignalStrength();
1416         }
1417     }
1418 
1419     /**
1420      *  Set the status of the CDMA roaming preference
1421      */
1422     @Override
setCdmaRoamingPreference(int cdmaRoamingType, Message response)1423     public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
1424         mCi.setCdmaRoamingPreference(cdmaRoamingType, response);
1425     }
1426 
1427     /**
1428      *  Set the status of the CDMA subscription mode
1429      */
1430     @Override
setCdmaSubscription(int cdmaSubscriptionType, Message response)1431     public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
1432         mCi.setCdmaSubscriptionSource(cdmaSubscriptionType, response);
1433     }
1434 
1435     /**
1436      *  Set the preferred Network Type: Global, CDMA only or GSM/UMTS only
1437      */
1438     @Override
setPreferredNetworkType(int networkType, Message response)1439     public void setPreferredNetworkType(int networkType, Message response) {
1440         // Only set preferred network types to that which the modem supports
1441         int modemRaf = getRadioAccessFamily();
1442         int rafFromType = RadioAccessFamily.getRafFromNetworkType(networkType);
1443 
1444         if (modemRaf == RadioAccessFamily.RAF_UNKNOWN
1445                 || rafFromType == RadioAccessFamily.RAF_UNKNOWN) {
1446             Rlog.d(LOG_TAG, "setPreferredNetworkType: Abort, unknown RAF: "
1447                     + modemRaf + " " + rafFromType);
1448             if (response != null) {
1449                 CommandException ex;
1450 
1451                 ex = new CommandException(CommandException.Error.GENERIC_FAILURE);
1452                 AsyncResult.forMessage(response, null, ex);
1453                 response.sendToTarget();
1454             }
1455             return;
1456         }
1457 
1458         int filteredRaf = (rafFromType & modemRaf);
1459         int filteredType = RadioAccessFamily.getNetworkTypeFromRaf(filteredRaf);
1460 
1461         Rlog.d(LOG_TAG, "setPreferredNetworkType: networkType = " + networkType
1462                 + " modemRaf = " + modemRaf
1463                 + " rafFromType = " + rafFromType
1464                 + " filteredType = " + filteredType);
1465 
1466         mCi.setPreferredNetworkType(filteredType, response);
1467     }
1468 
1469     @Override
getPreferredNetworkType(Message response)1470     public void getPreferredNetworkType(Message response) {
1471         mCi.getPreferredNetworkType(response);
1472     }
1473 
1474     @Override
getSmscAddress(Message result)1475     public void getSmscAddress(Message result) {
1476         mCi.getSmscAddress(result);
1477     }
1478 
1479     @Override
setSmscAddress(String address, Message result)1480     public void setSmscAddress(String address, Message result) {
1481         mCi.setSmscAddress(address, result);
1482     }
1483 
1484     @Override
setTTYMode(int ttyMode, Message onComplete)1485     public void setTTYMode(int ttyMode, Message onComplete) {
1486         mCi.setTTYMode(ttyMode, onComplete);
1487     }
1488 
1489     @Override
setUiTTYMode(int uiTtyMode, Message onComplete)1490     public void setUiTTYMode(int uiTtyMode, Message onComplete) {
1491         Rlog.d(LOG_TAG, "unexpected setUiTTYMode method call");
1492     }
1493 
1494     @Override
queryTTYMode(Message onComplete)1495     public void queryTTYMode(Message onComplete) {
1496         mCi.queryTTYMode(onComplete);
1497     }
1498 
1499     @Override
enableEnhancedVoicePrivacy(boolean enable, Message onComplete)1500     public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
1501         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1502         logUnexpectedCdmaMethodCall("enableEnhancedVoicePrivacy");
1503     }
1504 
1505     @Override
getEnhancedVoicePrivacy(Message onComplete)1506     public void getEnhancedVoicePrivacy(Message onComplete) {
1507         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1508         logUnexpectedCdmaMethodCall("getEnhancedVoicePrivacy");
1509     }
1510 
1511     @Override
setBandMode(int bandMode, Message response)1512     public void setBandMode(int bandMode, Message response) {
1513         mCi.setBandMode(bandMode, response);
1514     }
1515 
1516     @Override
queryAvailableBandMode(Message response)1517     public void queryAvailableBandMode(Message response) {
1518         mCi.queryAvailableBandMode(response);
1519     }
1520 
1521     @Override
invokeOemRilRequestRaw(byte[] data, Message response)1522     public void invokeOemRilRequestRaw(byte[] data, Message response) {
1523         mCi.invokeOemRilRequestRaw(data, response);
1524     }
1525 
1526     @Override
invokeOemRilRequestStrings(String[] strings, Message response)1527     public void invokeOemRilRequestStrings(String[] strings, Message response) {
1528         mCi.invokeOemRilRequestStrings(strings, response);
1529     }
1530 
1531     @Override
nvReadItem(int itemID, Message response)1532     public void nvReadItem(int itemID, Message response) {
1533         mCi.nvReadItem(itemID, response);
1534     }
1535 
1536     @Override
nvWriteItem(int itemID, String itemValue, Message response)1537     public void nvWriteItem(int itemID, String itemValue, Message response) {
1538         mCi.nvWriteItem(itemID, itemValue, response);
1539     }
1540 
1541     @Override
nvWriteCdmaPrl(byte[] preferredRoamingList, Message response)1542     public void nvWriteCdmaPrl(byte[] preferredRoamingList, Message response) {
1543         mCi.nvWriteCdmaPrl(preferredRoamingList, response);
1544     }
1545 
1546     @Override
nvResetConfig(int resetType, Message response)1547     public void nvResetConfig(int resetType, Message response) {
1548         mCi.nvResetConfig(resetType, response);
1549     }
1550 
1551     @Override
notifyDataActivity()1552     public void notifyDataActivity() {
1553         mNotifier.notifyDataActivity(this);
1554     }
1555 
notifyMessageWaitingIndicator()1556     public void notifyMessageWaitingIndicator() {
1557         // Do not notify voice mail waiting if device doesn't support voice
1558         if (!mIsVoiceCapable)
1559             return;
1560 
1561         // This function is added to send the notification to DefaultPhoneNotifier.
1562         mNotifier.notifyMessageWaitingChanged(this);
1563     }
1564 
notifyDataConnection(String reason, String apnType, PhoneConstants.DataState state)1565     public void notifyDataConnection(String reason, String apnType,
1566             PhoneConstants.DataState state) {
1567         mNotifier.notifyDataConnection(this, reason, apnType, state);
1568     }
1569 
notifyDataConnection(String reason, String apnType)1570     public void notifyDataConnection(String reason, String apnType) {
1571         mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
1572     }
1573 
notifyDataConnection(String reason)1574     public void notifyDataConnection(String reason) {
1575         String types[] = getActiveApnTypes();
1576         for (String apnType : types) {
1577             mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
1578         }
1579     }
1580 
notifyOtaspChanged(int otaspMode)1581     public void notifyOtaspChanged(int otaspMode) {
1582         mNotifier.notifyOtaspChanged(this, otaspMode);
1583     }
1584 
notifySignalStrength()1585     public void notifySignalStrength() {
1586         mNotifier.notifySignalStrength(this);
1587     }
1588 
notifyCellInfo(List<CellInfo> cellInfo)1589     public void notifyCellInfo(List<CellInfo> cellInfo) {
1590         mNotifier.notifyCellInfo(this, privatizeCellInfoList(cellInfo));
1591     }
1592 
notifyDataConnectionRealTimeInfo(DataConnectionRealTimeInfo dcRtInfo)1593     public void notifyDataConnectionRealTimeInfo(DataConnectionRealTimeInfo dcRtInfo) {
1594         mNotifier.notifyDataConnectionRealTimeInfo(this, dcRtInfo);
1595     }
1596 
notifyVoLteServiceStateChanged(VoLteServiceState lteState)1597     public void notifyVoLteServiceStateChanged(VoLteServiceState lteState) {
1598         mNotifier.notifyVoLteServiceStateChanged(this, lteState);
1599     }
1600 
1601     /**
1602      * @return true if a mobile originating emergency call is active
1603      */
isInEmergencyCall()1604     public boolean isInEmergencyCall() {
1605         return false;
1606     }
1607 
1608     /**
1609      * @return {@code true} if we are in emergency call back mode. This is a period where the phone
1610      * should be using as little power as possible and be ready to receive an incoming call from the
1611      * emergency operator.
1612      */
isInEcm()1613     public boolean isInEcm() {
1614         return false;
1615     }
1616 
getVideoState(Call call)1617     private static int getVideoState(Call call) {
1618         int videoState = VideoProfile.STATE_AUDIO_ONLY;
1619         ImsPhoneConnection conn = (ImsPhoneConnection) call.getEarliestConnection();
1620         if (conn != null) {
1621             videoState = conn.getVideoState();
1622         }
1623         return videoState;
1624     }
1625 
isVideoCall(Call call)1626     private boolean isVideoCall(Call call) {
1627         int videoState = getVideoState(call);
1628         return (VideoProfile.isVideo(videoState));
1629     }
1630 
1631     @Override
isVideoCallPresent()1632     public boolean isVideoCallPresent() {
1633         boolean isVideoCallActive = false;
1634         if (mImsPhone != null) {
1635             isVideoCallActive = isVideoCall(mImsPhone.getForegroundCall()) ||
1636                     isVideoCall(mImsPhone.getBackgroundCall()) ||
1637                     isVideoCall(mImsPhone.getRingingCall());
1638         }
1639         Rlog.d(LOG_TAG, "isVideoCallActive: " + isVideoCallActive);
1640         return isVideoCallActive;
1641     }
1642 
1643     @Override
getPhoneType()1644     public abstract int getPhoneType();
1645 
1646     /** @hide */
1647     /** @return number of voicemails */
1648     @Override
getVoiceMessageCount()1649     public int getVoiceMessageCount(){
1650         return mVmCount;
1651     }
1652 
1653     /** sets the voice mail count of the phone and notifies listeners. */
setVoiceMessageCount(int countWaiting)1654     public void setVoiceMessageCount(int countWaiting) {
1655         mVmCount = countWaiting;
1656         // notify listeners of voice mail
1657         notifyMessageWaitingIndicator();
1658     }
1659 
1660     /** gets the voice mail count from preferences */
getStoredVoiceMessageCount()1661     protected int getStoredVoiceMessageCount() {
1662         int countVoiceMessages = 0;
1663         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
1664         String subscriberId = sp.getString(VM_ID, null);
1665         String currentSubscriberId = getSubscriberId();
1666 
1667         if ((subscriberId != null) && (currentSubscriberId != null)
1668                 && (currentSubscriberId.equals(subscriberId))) {
1669             // get voice mail count from preferences
1670             countVoiceMessages = sp.getInt(VM_COUNT, 0);
1671             Rlog.d(LOG_TAG, "Voice Mail Count from preference = " + countVoiceMessages);
1672         } else {
1673             Rlog.d(LOG_TAG, "Voicemail count retrieval returning 0 as count for matching " +
1674                     "subscriberId not found");
1675 
1676         }
1677         return countVoiceMessages;
1678     }
1679 
1680     /**
1681      * Returns the CDMA ERI icon index to display
1682      */
1683     @Override
getCdmaEriIconIndex()1684     public int getCdmaEriIconIndex() {
1685         logUnexpectedCdmaMethodCall("getCdmaEriIconIndex");
1686         return -1;
1687     }
1688 
1689     /**
1690      * Returns the CDMA ERI icon mode,
1691      * 0 - ON
1692      * 1 - FLASHING
1693      */
1694     @Override
getCdmaEriIconMode()1695     public int getCdmaEriIconMode() {
1696         logUnexpectedCdmaMethodCall("getCdmaEriIconMode");
1697         return -1;
1698     }
1699 
1700     /**
1701      * Returns the CDMA ERI text,
1702      */
1703     @Override
getCdmaEriText()1704     public String getCdmaEriText() {
1705         logUnexpectedCdmaMethodCall("getCdmaEriText");
1706         return "GSM nw, no ERI";
1707     }
1708 
1709     @Override
getCdmaMin()1710     public String getCdmaMin() {
1711         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1712         logUnexpectedCdmaMethodCall("getCdmaMin");
1713         return null;
1714     }
1715 
1716     @Override
isMinInfoReady()1717     public boolean isMinInfoReady() {
1718         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1719         logUnexpectedCdmaMethodCall("isMinInfoReady");
1720         return false;
1721     }
1722 
1723     @Override
getCdmaPrlVersion()1724     public String getCdmaPrlVersion(){
1725         //  This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1726         logUnexpectedCdmaMethodCall("getCdmaPrlVersion");
1727         return null;
1728     }
1729 
1730     @Override
sendBurstDtmf(String dtmfString, int on, int off, Message onComplete)1731     public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
1732         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1733         logUnexpectedCdmaMethodCall("sendBurstDtmf");
1734     }
1735 
1736     @Override
exitEmergencyCallbackMode()1737     public void exitEmergencyCallbackMode() {
1738         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1739         logUnexpectedCdmaMethodCall("exitEmergencyCallbackMode");
1740     }
1741 
1742     @Override
registerForCdmaOtaStatusChange(Handler h, int what, Object obj)1743     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
1744         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1745         logUnexpectedCdmaMethodCall("registerForCdmaOtaStatusChange");
1746     }
1747 
1748     @Override
unregisterForCdmaOtaStatusChange(Handler h)1749     public void unregisterForCdmaOtaStatusChange(Handler h) {
1750         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1751         logUnexpectedCdmaMethodCall("unregisterForCdmaOtaStatusChange");
1752     }
1753 
1754     @Override
registerForSubscriptionInfoReady(Handler h, int what, Object obj)1755     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
1756         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1757         logUnexpectedCdmaMethodCall("registerForSubscriptionInfoReady");
1758     }
1759 
1760     @Override
unregisterForSubscriptionInfoReady(Handler h)1761     public void unregisterForSubscriptionInfoReady(Handler h) {
1762         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1763         logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady");
1764     }
1765 
1766     /**
1767      * Returns true if OTA Service Provisioning needs to be performed.
1768      * If not overridden return false.
1769      */
1770     @Override
needsOtaServiceProvisioning()1771     public boolean needsOtaServiceProvisioning() {
1772         return false;
1773     }
1774 
1775     /**
1776      * Return true if number is an OTASP number.
1777      * If not overridden return false.
1778      */
1779     @Override
isOtaSpNumber(String dialStr)1780     public  boolean isOtaSpNumber(String dialStr) {
1781         return false;
1782     }
1783 
1784     @Override
registerForCallWaiting(Handler h, int what, Object obj)1785     public void registerForCallWaiting(Handler h, int what, Object obj){
1786         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1787         logUnexpectedCdmaMethodCall("registerForCallWaiting");
1788     }
1789 
1790     @Override
unregisterForCallWaiting(Handler h)1791     public void unregisterForCallWaiting(Handler h){
1792         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1793         logUnexpectedCdmaMethodCall("unregisterForCallWaiting");
1794     }
1795 
1796     @Override
registerForEcmTimerReset(Handler h, int what, Object obj)1797     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
1798         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1799         logUnexpectedCdmaMethodCall("registerForEcmTimerReset");
1800     }
1801 
1802     @Override
unregisterForEcmTimerReset(Handler h)1803     public void unregisterForEcmTimerReset(Handler h) {
1804         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1805         logUnexpectedCdmaMethodCall("unregisterForEcmTimerReset");
1806     }
1807 
1808     @Override
registerForSignalInfo(Handler h, int what, Object obj)1809     public void registerForSignalInfo(Handler h, int what, Object obj) {
1810         mCi.registerForSignalInfo(h, what, obj);
1811     }
1812 
1813     @Override
unregisterForSignalInfo(Handler h)1814     public void unregisterForSignalInfo(Handler h) {
1815         mCi.unregisterForSignalInfo(h);
1816     }
1817 
1818     @Override
registerForDisplayInfo(Handler h, int what, Object obj)1819     public void registerForDisplayInfo(Handler h, int what, Object obj) {
1820         mCi.registerForDisplayInfo(h, what, obj);
1821     }
1822 
1823      @Override
unregisterForDisplayInfo(Handler h)1824     public void unregisterForDisplayInfo(Handler h) {
1825          mCi.unregisterForDisplayInfo(h);
1826      }
1827 
1828     @Override
registerForNumberInfo(Handler h, int what, Object obj)1829     public void registerForNumberInfo(Handler h, int what, Object obj) {
1830         mCi.registerForNumberInfo(h, what, obj);
1831     }
1832 
1833     @Override
unregisterForNumberInfo(Handler h)1834     public void unregisterForNumberInfo(Handler h) {
1835         mCi.unregisterForNumberInfo(h);
1836     }
1837 
1838     @Override
registerForRedirectedNumberInfo(Handler h, int what, Object obj)1839     public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
1840         mCi.registerForRedirectedNumberInfo(h, what, obj);
1841     }
1842 
1843     @Override
unregisterForRedirectedNumberInfo(Handler h)1844     public void unregisterForRedirectedNumberInfo(Handler h) {
1845         mCi.unregisterForRedirectedNumberInfo(h);
1846     }
1847 
1848     @Override
registerForLineControlInfo(Handler h, int what, Object obj)1849     public void registerForLineControlInfo(Handler h, int what, Object obj) {
1850         mCi.registerForLineControlInfo( h, what, obj);
1851     }
1852 
1853     @Override
unregisterForLineControlInfo(Handler h)1854     public void unregisterForLineControlInfo(Handler h) {
1855         mCi.unregisterForLineControlInfo(h);
1856     }
1857 
1858     @Override
registerFoT53ClirlInfo(Handler h, int what, Object obj)1859     public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
1860         mCi.registerFoT53ClirlInfo(h, what, obj);
1861     }
1862 
1863     @Override
unregisterForT53ClirInfo(Handler h)1864     public void unregisterForT53ClirInfo(Handler h) {
1865         mCi.unregisterForT53ClirInfo(h);
1866     }
1867 
1868     @Override
registerForT53AudioControlInfo(Handler h, int what, Object obj)1869     public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
1870         mCi.registerForT53AudioControlInfo( h, what, obj);
1871     }
1872 
1873     @Override
unregisterForT53AudioControlInfo(Handler h)1874     public void unregisterForT53AudioControlInfo(Handler h) {
1875         mCi.unregisterForT53AudioControlInfo(h);
1876     }
1877 
1878      @Override
setOnEcbModeExitResponse(Handler h, int what, Object obj)1879     public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
1880          // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1881          logUnexpectedCdmaMethodCall("setOnEcbModeExitResponse");
1882      }
1883 
1884      @Override
unsetOnEcbModeExitResponse(Handler h)1885     public void unsetOnEcbModeExitResponse(Handler h){
1886         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1887          logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse");
1888      }
1889 
1890     @Override
registerForRadioOffOrNotAvailable(Handler h, int what, Object obj)1891     public void registerForRadioOffOrNotAvailable(Handler h, int what, Object obj) {
1892         mRadioOffOrNotAvailableRegistrants.addUnique(h, what, obj);
1893     }
1894 
1895     @Override
unregisterForRadioOffOrNotAvailable(Handler h)1896     public void unregisterForRadioOffOrNotAvailable(Handler h) {
1897         mRadioOffOrNotAvailableRegistrants.remove(h);
1898     }
1899 
1900     @Override
getActiveApnTypes()1901     public String[] getActiveApnTypes() {
1902         return mDcTracker.getActiveApnTypes();
1903     }
1904 
1905     @Override
hasMatchedTetherApnSetting()1906     public boolean hasMatchedTetherApnSetting() {
1907         return mDcTracker.hasMatchedTetherApnSetting();
1908     }
1909 
1910     @Override
getActiveApnHost(String apnType)1911     public String getActiveApnHost(String apnType) {
1912         return mDcTracker.getActiveApnString(apnType);
1913     }
1914 
1915     @Override
getLinkProperties(String apnType)1916     public LinkProperties getLinkProperties(String apnType) {
1917         return mDcTracker.getLinkProperties(apnType);
1918     }
1919 
1920     @Override
getNetworkCapabilities(String apnType)1921     public NetworkCapabilities getNetworkCapabilities(String apnType) {
1922         return mDcTracker.getNetworkCapabilities(apnType);
1923     }
1924 
1925     @Override
isDataConnectivityPossible()1926     public boolean isDataConnectivityPossible() {
1927         return isDataConnectivityPossible(PhoneConstants.APN_TYPE_DEFAULT);
1928     }
1929 
1930     @Override
isDataConnectivityPossible(String apnType)1931     public boolean isDataConnectivityPossible(String apnType) {
1932         return ((mDcTracker != null) &&
1933                 (mDcTracker.isDataPossible(apnType)));
1934     }
1935 
1936     /**
1937      * Notify registrants of a new ringing Connection.
1938      * Subclasses of Phone probably want to replace this with a
1939      * version scoped to their packages
1940      */
notifyNewRingingConnectionP(Connection cn)1941     public void notifyNewRingingConnectionP(Connection cn) {
1942         if (!mIsVoiceCapable)
1943             return;
1944         AsyncResult ar = new AsyncResult(null, cn, null);
1945         mNewRingingConnectionRegistrants.notifyRegistrants(ar);
1946     }
1947 
1948 
1949     /**
1950      * Notify registrants if phone is video capable.
1951      */
notifyForVideoCapabilityChanged(boolean isVideoCallCapable)1952     public void notifyForVideoCapabilityChanged(boolean isVideoCallCapable) {
1953         // Cache the current video capability so that we don't lose the information.
1954         mIsVideoCapable = isVideoCallCapable;
1955 
1956         AsyncResult ar = new AsyncResult(null, isVideoCallCapable, null);
1957         mVideoCapabilityChangedRegistrants.notifyRegistrants(ar);
1958     }
1959 
1960     /**
1961      * Notify registrants of a RING event.
1962      */
notifyIncomingRing()1963     private void notifyIncomingRing() {
1964         if (!mIsVoiceCapable)
1965             return;
1966         AsyncResult ar = new AsyncResult(null, this, null);
1967         mIncomingRingRegistrants.notifyRegistrants(ar);
1968     }
1969 
1970     /**
1971      * Send the incoming call Ring notification if conditions are right.
1972      */
sendIncomingCallRingNotification(int token)1973     private void sendIncomingCallRingNotification(int token) {
1974         if (mIsVoiceCapable && !mDoesRilSendMultipleCallRing &&
1975                 (token == mCallRingContinueToken)) {
1976             Rlog.d(LOG_TAG, "Sending notifyIncomingRing");
1977             notifyIncomingRing();
1978             sendMessageDelayed(
1979                     obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
1980         } else {
1981             Rlog.d(LOG_TAG, "Ignoring ring notification request,"
1982                     + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
1983                     + " token=" + token
1984                     + " mCallRingContinueToken=" + mCallRingContinueToken
1985                     + " mIsVoiceCapable=" + mIsVoiceCapable);
1986         }
1987     }
1988 
1989     @Override
isCspPlmnEnabled()1990     public boolean isCspPlmnEnabled() {
1991         // This function should be overridden by the class GSMPhone.
1992         // Not implemented in CDMAPhone.
1993         logUnexpectedGsmMethodCall("isCspPlmnEnabled");
1994         return false;
1995     }
1996 
1997     @Override
getIsimRecords()1998     public IsimRecords getIsimRecords() {
1999         Rlog.e(LOG_TAG, "getIsimRecords() is only supported on LTE devices");
2000         return null;
2001     }
2002 
2003     @Override
getMsisdn()2004     public String getMsisdn() {
2005         logUnexpectedGsmMethodCall("getMsisdn");
2006         return null;
2007     }
2008 
2009     /**
2010      * Common error logger method for unexpected calls to CDMA-only methods.
2011      */
logUnexpectedCdmaMethodCall(String name)2012     private static void logUnexpectedCdmaMethodCall(String name)
2013     {
2014         Rlog.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
2015                 "called, CDMAPhone inactive.");
2016     }
2017 
2018     @Override
getDataConnectionState()2019     public PhoneConstants.DataState getDataConnectionState() {
2020         return getDataConnectionState(PhoneConstants.APN_TYPE_DEFAULT);
2021     }
2022 
2023     /**
2024      * Common error logger method for unexpected calls to GSM/WCDMA-only methods.
2025      */
logUnexpectedGsmMethodCall(String name)2026     private static void logUnexpectedGsmMethodCall(String name) {
2027         Rlog.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
2028                 "called, GSMPhone inactive.");
2029     }
2030 
2031     // Called by SimRecords which is constructed with a PhoneBase instead of a GSMPhone.
notifyCallForwardingIndicator()2032     public void notifyCallForwardingIndicator() {
2033         // This function should be overridden by the class GSMPhone. Not implemented in CDMAPhone.
2034         Rlog.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
2035     }
2036 
notifyDataConnectionFailed(String reason, String apnType)2037     public void notifyDataConnectionFailed(String reason, String apnType) {
2038         mNotifier.notifyDataConnectionFailed(this, reason, apnType);
2039     }
2040 
notifyPreciseDataConnectionFailed(String reason, String apnType, String apn, String failCause)2041     public void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn,
2042             String failCause) {
2043         mNotifier.notifyPreciseDataConnectionFailed(this, reason, apnType, apn, failCause);
2044     }
2045 
2046     /**
2047      * {@inheritDoc}
2048      */
2049     @Override
getLteOnCdmaMode()2050     public int getLteOnCdmaMode() {
2051         return mCi.getLteOnCdmaMode();
2052     }
2053 
setVoiceMessageWaiting(int line, int countWaiting)2054     public void setVoiceMessageWaiting(int line, int countWaiting) {
2055         // This function should be overridden by class GSMPhone and CDMAPhone.
2056         Rlog.e(LOG_TAG, "Error! This function should never be executed, inactive Phone.");
2057     }
2058 
2059     /**
2060      * Gets the USIM service table from the UICC, if present and available.
2061      * @return an interface to the UsimServiceTable record, or null if not available
2062      */
2063     @Override
getUsimServiceTable()2064     public UsimServiceTable getUsimServiceTable() {
2065         IccRecords r = mIccRecords.get();
2066         return (r != null) ? r.getUsimServiceTable() : null;
2067     }
2068 
2069     /**
2070      * Gets the Uicc card corresponding to this phone.
2071      * @return the UiccCard object corresponding to the phone ID.
2072      */
2073     @Override
getUiccCard()2074     public UiccCard getUiccCard() {
2075         return mUiccController.getUiccCard(mPhoneId);
2076     }
2077 
2078     /**
2079      * Get P-CSCF address from PCO after data connection is established or modified.
2080      * @param apnType the apnType, "ims" for IMS APN, "emergency" for EMERGENCY APN
2081      */
2082     @Override
getPcscfAddress(String apnType)2083     public String[] getPcscfAddress(String apnType) {
2084         return mDcTracker.getPcscfAddress(apnType);
2085     }
2086 
2087     /**
2088      * Set IMS registration state
2089      */
2090     @Override
setImsRegistrationState(boolean registered)2091     public void setImsRegistrationState(boolean registered) {
2092         mDcTracker.setImsRegistrationState(registered);
2093     }
2094 
2095     /**
2096      * Return an instance of a IMS phone
2097      */
2098     @Override
getImsPhone()2099     public Phone getImsPhone() {
2100         return mImsPhone;
2101     }
2102 
2103     @Override
relinquishOwnershipOfImsPhone()2104     public ImsPhone relinquishOwnershipOfImsPhone() {
2105         synchronized (PhoneProxy.lockForRadioTechnologyChange) {
2106             if (mImsPhone == null)
2107                 return null;
2108 
2109             if (mImsIntentReceiverRegistered) {
2110                 mContext.unregisterReceiver(mImsIntentReceiver);
2111                 mImsIntentReceiverRegistered = false;
2112             }
2113 
2114             ImsPhone imsPhone = mImsPhone;
2115             mImsPhone = null;
2116 
2117             CallManager.getInstance().unregisterPhone(imsPhone);
2118             imsPhone.unregisterForSilentRedial(this);
2119 
2120             return imsPhone;
2121         }
2122     }
2123 
2124     @Override
acquireOwnershipOfImsPhone(ImsPhone imsPhone)2125     public void acquireOwnershipOfImsPhone(ImsPhone imsPhone) {
2126         synchronized (PhoneProxy.lockForRadioTechnologyChange) {
2127             if (imsPhone == null)
2128                 return;
2129 
2130             if (mImsPhone != null) {
2131                 Rlog.e(LOG_TAG, "acquireOwnershipOfImsPhone: non-null mImsPhone." +
2132                         " Shouldn't happen - but disposing");
2133                 mImsPhone.dispose();
2134                 // Potential GC issue if someone keeps a reference to ImsPhone.
2135                 // However: this change will make sure that such a reference does
2136                 // not access functions through NULL pointer.
2137                 //mImsPhone.removeReferences();
2138             }
2139 
2140             mImsPhone = imsPhone;
2141 
2142             mImsServiceReady = true;
2143             mImsPhone.updateParentPhone(this);
2144             CallManager.getInstance().registerPhone(mImsPhone);
2145             mImsPhone.registerForSilentRedial(
2146                     this, EVENT_INITIATE_SILENT_REDIAL, null);
2147         }
2148     }
2149 
updateImsPhone()2150     protected void updateImsPhone() {
2151         Rlog.d(LOG_TAG, "updateImsPhone"
2152                 + " mImsServiceReady=" + mImsServiceReady);
2153 
2154         if (mImsServiceReady && (mImsPhone == null)) {
2155             mImsPhone = PhoneFactory.makeImsPhone(mNotifier, this);
2156             CallManager.getInstance().registerPhone(mImsPhone);
2157             mImsPhone.registerForSilentRedial(
2158                     this, EVENT_INITIATE_SILENT_REDIAL, null);
2159         } else if (!mImsServiceReady && (mImsPhone != null)) {
2160             CallManager.getInstance().unregisterPhone(mImsPhone);
2161             mImsPhone.unregisterForSilentRedial(this);
2162 
2163             mImsPhone.dispose();
2164             // Potential GC issue if someone keeps a reference to ImsPhone.
2165             // However: this change will make sure that such a reference does
2166             // not access functions through NULL pointer.
2167             //mImsPhone.removeReferences();
2168             mImsPhone = null;
2169         }
2170     }
2171 
2172     /**
2173      * Dials a number.
2174      *
2175      * @param dialString The number to dial.
2176      * @param uusInfo The UUSInfo.
2177      * @param videoState The video state for the call.
2178      * @param intentExtras Extras from the original CALL intent.
2179      * @return The Connection.
2180      * @throws CallStateException
2181      */
dialInternal( String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)2182     protected Connection dialInternal(
2183             String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)
2184             throws CallStateException {
2185         // dialInternal shall be overriden by GSMPhone and CDMAPhone
2186         return null;
2187     }
2188 
2189     /**
2190      * Returns the subscription id.
2191      */
getSubId()2192     public int getSubId() {
2193         return SubscriptionController.getInstance().getSubIdUsingPhoneId(mPhoneId);
2194     }
2195 
2196     /**
2197      * Returns the phone id.
2198      */
getPhoneId()2199     public int getPhoneId() {
2200         return mPhoneId;
2201     }
2202 
2203     /**
2204      * Return the service state of mImsPhone if it is STATE_IN_SERVICE
2205      * otherwise return the current voice service state
2206      */
2207     @Override
getVoicePhoneServiceState()2208     public int getVoicePhoneServiceState() {
2209         ImsPhone imsPhone = mImsPhone;
2210         if (imsPhone != null
2211                 && imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE) {
2212             return ServiceState.STATE_IN_SERVICE;
2213         }
2214         return getServiceState().getState();
2215     }
2216 
2217     @Override
setOperatorBrandOverride(String brand)2218     public boolean setOperatorBrandOverride(String brand) {
2219         return false;
2220     }
2221 
2222     @Override
setRoamingOverride(List<String> gsmRoamingList, List<String> gsmNonRoamingList, List<String> cdmaRoamingList, List<String> cdmaNonRoamingList)2223     public boolean setRoamingOverride(List<String> gsmRoamingList,
2224             List<String> gsmNonRoamingList, List<String> cdmaRoamingList,
2225             List<String> cdmaNonRoamingList) {
2226         String iccId = getIccSerialNumber();
2227         if (TextUtils.isEmpty(iccId)) {
2228             return false;
2229         }
2230 
2231         setRoamingOverrideHelper(gsmRoamingList, GSM_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
2232         setRoamingOverrideHelper(gsmNonRoamingList, GSM_NON_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
2233         setRoamingOverrideHelper(cdmaRoamingList, CDMA_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
2234         setRoamingOverrideHelper(cdmaNonRoamingList, CDMA_NON_ROAMING_LIST_OVERRIDE_PREFIX, iccId);
2235 
2236         // Refresh.
2237         ServiceStateTracker tracker = getServiceStateTracker();
2238         if (tracker != null) {
2239             tracker.pollState();
2240         }
2241         return true;
2242     }
2243 
setRoamingOverrideHelper(List<String> list, String prefix, String iccId)2244     private void setRoamingOverrideHelper(List<String> list, String prefix, String iccId) {
2245         SharedPreferences.Editor spEditor =
2246                 PreferenceManager.getDefaultSharedPreferences(mContext).edit();
2247         String key = prefix + iccId;
2248         if (list == null || list.isEmpty()) {
2249             spEditor.remove(key).commit();
2250         } else {
2251             spEditor.putStringSet(key, new HashSet<String>(list)).commit();
2252         }
2253     }
2254 
isMccMncMarkedAsRoaming(String mccMnc)2255     public boolean isMccMncMarkedAsRoaming(String mccMnc) {
2256         return getRoamingOverrideHelper(GSM_ROAMING_LIST_OVERRIDE_PREFIX, mccMnc);
2257     }
2258 
isMccMncMarkedAsNonRoaming(String mccMnc)2259     public boolean isMccMncMarkedAsNonRoaming(String mccMnc) {
2260         return getRoamingOverrideHelper(GSM_NON_ROAMING_LIST_OVERRIDE_PREFIX, mccMnc);
2261     }
2262 
isSidMarkedAsRoaming(int SID)2263     public boolean isSidMarkedAsRoaming(int SID) {
2264         return getRoamingOverrideHelper(CDMA_ROAMING_LIST_OVERRIDE_PREFIX,
2265                 Integer.toString(SID));
2266     }
2267 
isSidMarkedAsNonRoaming(int SID)2268     public boolean isSidMarkedAsNonRoaming(int SID) {
2269         return getRoamingOverrideHelper(CDMA_NON_ROAMING_LIST_OVERRIDE_PREFIX,
2270                 Integer.toString(SID));
2271     }
2272 
2273     /**
2274      * Get IMS Registration Status
2275      */
2276     @Override
isImsRegistered()2277     public boolean isImsRegistered() {
2278         ImsPhone imsPhone = mImsPhone;
2279         boolean isImsRegistered = false;
2280         if (imsPhone != null) {
2281             isImsRegistered = imsPhone.isImsRegistered();
2282         } else {
2283             ServiceStateTracker sst = getServiceStateTracker();
2284             if (sst != null) {
2285                 isImsRegistered = sst.isImsRegistered();
2286             }
2287         }
2288         Rlog.d(LOG_TAG, "isImsRegistered =" + isImsRegistered);
2289         return isImsRegistered;
2290     }
2291 
2292     /**
2293      * Get Wifi Calling Feature Availability
2294      */
2295     @Override
isWifiCallingEnabled()2296     public boolean isWifiCallingEnabled() {
2297         ImsPhone imsPhone = mImsPhone;
2298         boolean isWifiCallingEnabled = false;
2299         if (imsPhone != null) {
2300             isWifiCallingEnabled = imsPhone.isVowifiEnabled();
2301         }
2302         Rlog.d(LOG_TAG, "isWifiCallingEnabled =" + isWifiCallingEnabled);
2303         return isWifiCallingEnabled;
2304     }
2305 
2306     /**
2307      * Get Volte Feature Availability
2308      */
2309     @Override
isVolteEnabled()2310     public boolean isVolteEnabled() {
2311         ImsPhone imsPhone = mImsPhone;
2312         boolean isVolteEnabled = false;
2313         if (imsPhone != null) {
2314             isVolteEnabled = imsPhone.isVolteEnabled();
2315         }
2316         Rlog.d(LOG_TAG, "isImsRegistered =" + isVolteEnabled);
2317         return isVolteEnabled;
2318     }
2319 
getRoamingOverrideHelper(String prefix, String key)2320     private boolean getRoamingOverrideHelper(String prefix, String key) {
2321         String iccId = getIccSerialNumber();
2322         if (TextUtils.isEmpty(iccId) || TextUtils.isEmpty(key)) {
2323             return false;
2324         }
2325 
2326         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(mContext);
2327         Set<String> value = sp.getStringSet(prefix + iccId, null);
2328         if (value == null) {
2329             return false;
2330         }
2331         return value.contains(key);
2332     }
2333 
2334     @Override
isRadioAvailable()2335     public boolean isRadioAvailable() {
2336         return mCi.getRadioState().isAvailable();
2337     }
2338 
2339     @Override
isRadioOn()2340     public boolean isRadioOn() {
2341         return mCi.getRadioState().isOn();
2342     }
2343 
2344     @Override
shutdownRadio()2345     public void shutdownRadio() {
2346         getServiceStateTracker().requestShutdown();
2347     }
2348 
2349     @Override
setRadioCapability(RadioCapability rc, Message response)2350     public void setRadioCapability(RadioCapability rc, Message response) {
2351         mCi.setRadioCapability(rc, response);
2352     }
2353 
2354     @Override
getRadioAccessFamily()2355     public int getRadioAccessFamily() {
2356         final RadioCapability rc = getRadioCapability();
2357         return (rc == null ? RadioAccessFamily.RAF_UNKNOWN : rc.getRadioAccessFamily());
2358     }
2359 
2360     @Override
getModemUuId()2361     public String getModemUuId() {
2362         final RadioCapability rc = getRadioCapability();
2363         return (rc == null ? "" : rc.getLogicalModemUuid());
2364     }
2365 
2366     @Override
getRadioCapability()2367     public RadioCapability getRadioCapability() {
2368         return mRadioCapability.get();
2369     }
2370 
2371     @Override
radioCapabilityUpdated(RadioCapability rc)2372     public void radioCapabilityUpdated(RadioCapability rc) {
2373         // Called when radios first become available or after a capability switch
2374         // Update the cached value
2375         mRadioCapability.set(rc);
2376 
2377         if (SubscriptionManager.isValidSubscriptionId(getSubId())) {
2378             sendSubscriptionSettings(true);
2379         }
2380     }
2381 
sendSubscriptionSettings(boolean restoreNetworkSelection)2382     public void sendSubscriptionSettings(boolean restoreNetworkSelection) {
2383         // Send settings down
2384         int type = PhoneFactory.calculatePreferredNetworkType(mContext, getSubId());
2385         setPreferredNetworkType(type, null);
2386 
2387         if (restoreNetworkSelection) {
2388             restoreSavedNetworkSelection(null);
2389         }
2390         mDcTracker.setDataEnabled(getDataEnabled());
2391     }
2392 
setPreferredNetworkTypeIfSimLoaded()2393     protected void setPreferredNetworkTypeIfSimLoaded() {
2394         int subId = getSubId();
2395         if (SubscriptionManager.isValidSubscriptionId(subId)) {
2396             int type = PhoneFactory.calculatePreferredNetworkType(mContext, getSubId());
2397             setPreferredNetworkType(type, null);
2398         }
2399     }
2400 
2401     @Override
registerForRadioCapabilityChanged(Handler h, int what, Object obj)2402     public void registerForRadioCapabilityChanged(Handler h, int what, Object obj) {
2403         mCi.registerForRadioCapabilityChanged(h, what, obj);
2404     }
2405 
2406     @Override
unregisterForRadioCapabilityChanged(Handler h)2407     public void unregisterForRadioCapabilityChanged(Handler h) {
2408         mCi.unregisterForRadioCapabilityChanged(this);
2409     }
2410 
2411     /**
2412      * Determines if  IMS is enabled for call.
2413      *
2414      * @return {@code true} if IMS calling is enabled.
2415      */
isImsUseEnabled()2416     public boolean isImsUseEnabled() {
2417         boolean imsUseEnabled =
2418                 ((ImsManager.isVolteEnabledByPlatform(mContext) &&
2419                 ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mContext)) ||
2420                 (ImsManager.isWfcEnabledByPlatform(mContext) &&
2421                 ImsManager.isWfcEnabledByUser(mContext)) &&
2422                 ImsManager.isNonTtyOrTtyOnVolteEnabled(mContext));
2423         return imsUseEnabled;
2424     }
2425 
2426     /**
2427      * Determines if video calling is enabled for the IMS phone.
2428      *
2429      * @return {@code true} if video calling is enabled.
2430      */
2431     @Override
isVideoEnabled()2432     public boolean isVideoEnabled() {
2433         ImsPhone imsPhone = mImsPhone;
2434         if ((imsPhone != null)
2435                 && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)) {
2436             return imsPhone.isVideoEnabled();
2437         }
2438         return false;
2439     }
2440 
2441     @Override
getLceStatus()2442     public int getLceStatus() {
2443         return mLceStatus;
2444     }
2445 
2446     @Override
getModemActivityInfo(Message response)2447     public void getModemActivityInfo(Message response)  {
2448         mCi.getModemActivityInfo(response);
2449     }
2450 
2451     /**
2452      * Starts LCE service after radio becomes available.
2453      * LCE service state may get destroyed on the modem when radio becomes unavailable.
2454      */
startLceAfterRadioIsAvailable()2455     public void startLceAfterRadioIsAvailable() {
2456         if (mIsTheCurrentActivePhone) {
2457             mCi.startLceService(DEFAULT_REPORT_INTERVAL_MS, LCE_PULL_MODE,
2458                 obtainMessage(EVENT_CONFIG_LCE));
2459         }
2460     }
2461 
2462     @Override
getLocaleFromSimAndCarrierPrefs()2463     public Locale getLocaleFromSimAndCarrierPrefs() {
2464         final IccRecords records = mIccRecords.get();
2465         if (records != null && records.getSimLanguage() != null) {
2466             return new Locale(records.getSimLanguage());
2467         }
2468 
2469         return getLocaleFromCarrierProperties(mContext);
2470     }
2471 
dump(FileDescriptor fd, PrintWriter pw, String[] args)2472     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
2473         pw.println("PhoneBase: subId=" + getSubId());
2474         pw.println(" mPhoneId=" + mPhoneId);
2475         pw.println(" mCi=" + mCi);
2476         pw.println(" mDnsCheckDisabled=" + mDnsCheckDisabled);
2477         pw.println(" mDcTracker=" + mDcTracker);
2478         pw.println(" mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
2479         pw.println(" mCallRingContinueToken=" + mCallRingContinueToken);
2480         pw.println(" mCallRingDelay=" + mCallRingDelay);
2481         pw.println(" mIsTheCurrentActivePhone=" + mIsTheCurrentActivePhone);
2482         pw.println(" mIsVoiceCapable=" + mIsVoiceCapable);
2483         pw.println(" mIccRecords=" + mIccRecords.get());
2484         pw.println(" mUiccApplication=" + mUiccApplication.get());
2485         pw.println(" mSmsStorageMonitor=" + mSmsStorageMonitor);
2486         pw.println(" mSmsUsageMonitor=" + mSmsUsageMonitor);
2487         pw.flush();
2488         pw.println(" mLooper=" + mLooper);
2489         pw.println(" mContext=" + mContext);
2490         pw.println(" mNotifier=" + mNotifier);
2491         pw.println(" mSimulatedRadioControl=" + mSimulatedRadioControl);
2492         pw.println(" mUnitTestMode=" + mUnitTestMode);
2493         pw.println(" isDnsCheckDisabled()=" + isDnsCheckDisabled());
2494         pw.println(" getUnitTestMode()=" + getUnitTestMode());
2495         pw.println(" getState()=" + getState());
2496         pw.println(" getIccSerialNumber()=" + getIccSerialNumber());
2497         pw.println(" getIccRecordsLoaded()=" + getIccRecordsLoaded());
2498         pw.println(" getMessageWaitingIndicator()=" + getMessageWaitingIndicator());
2499         pw.println(" getCallForwardingIndicator()=" + getCallForwardingIndicator());
2500         pw.println(" isInEmergencyCall()=" + isInEmergencyCall());
2501         pw.flush();
2502         pw.println(" isInEcm()=" + isInEcm());
2503         pw.println(" getPhoneName()=" + getPhoneName());
2504         pw.println(" getPhoneType()=" + getPhoneType());
2505         pw.println(" getVoiceMessageCount()=" + getVoiceMessageCount());
2506         pw.println(" getActiveApnTypes()=" + getActiveApnTypes());
2507         pw.println(" isDataConnectivityPossible()=" + isDataConnectivityPossible());
2508         pw.println(" needsOtaServiceProvisioning=" + needsOtaServiceProvisioning());
2509         pw.flush();
2510         pw.println("++++++++++++++++++++++++++++++++");
2511 
2512         try {
2513             mDcTracker.dump(fd, pw, args);
2514         } catch (Exception e) {
2515             e.printStackTrace();
2516         }
2517         pw.flush();
2518         pw.println("++++++++++++++++++++++++++++++++");
2519 
2520         try {
2521             getServiceStateTracker().dump(fd, pw, args);
2522         } catch (Exception e) {
2523             e.printStackTrace();
2524         }
2525         pw.flush();
2526         pw.println("++++++++++++++++++++++++++++++++");
2527 
2528         try {
2529             getCallTracker().dump(fd, pw, args);
2530         } catch (Exception e) {
2531             e.printStackTrace();
2532         }
2533         pw.flush();
2534         pw.println("++++++++++++++++++++++++++++++++");
2535 
2536         try {
2537             ((RIL)mCi).dump(fd, pw, args);
2538         } catch (Exception e) {
2539             e.printStackTrace();
2540         }
2541         pw.flush();
2542         pw.println("++++++++++++++++++++++++++++++++");
2543     }
2544 }
2545