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