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