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