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