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