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