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