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