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