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