PhoneBase.java revision cbaa45bbf2cab852b6c9c3a887e9f803d4e857ea
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.Context;
20import android.content.SharedPreferences;
21import android.net.LinkCapabilities;
22import android.net.LinkProperties;
23import android.net.wifi.WifiManager;
24import android.os.AsyncResult;
25import android.os.Handler;
26import android.os.Looper;
27import android.os.Message;
28import android.os.RegistrantList;
29import android.os.SystemProperties;
30import android.preference.PreferenceManager;
31import android.provider.Settings;
32import android.telephony.CellInfo;
33import android.telephony.ServiceState;
34import android.telephony.SignalStrength;
35import android.text.TextUtils;
36import android.telephony.Rlog;
37
38import com.android.internal.R;
39import com.android.internal.telephony.dataconnection.DataConnectionTrackerBase;
40import com.android.internal.telephony.test.SimulatedRadioControl;
41import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
42import com.android.internal.telephony.uicc.IccFileHandler;
43import com.android.internal.telephony.uicc.IccRecords;
44import com.android.internal.telephony.uicc.IsimRecords;
45import com.android.internal.telephony.uicc.UiccCardApplication;
46import com.android.internal.telephony.uicc.UiccController;
47import com.android.internal.telephony.uicc.UsimServiceTable;
48import java.io.FileDescriptor;
49import java.io.PrintWriter;
50import java.util.List;
51import java.util.concurrent.atomic.AtomicReference;
52
53
54/**
55 * (<em>Not for SDK use</em>)
56 * A base implementation for the com.android.internal.telephony.Phone interface.
57 *
58 * Note that implementations of Phone.java are expected to be used
59 * from a single application thread. This should be the same thread that
60 * originally called PhoneFactory to obtain the interface.
61 *
62 *  {@hide}
63 *
64 */
65
66public abstract class PhoneBase extends Handler implements Phone {
67    private static final String LOG_TAG = "PhoneBase";
68    // Key used to read and write the saved network selection numeric value
69    public static final String NETWORK_SELECTION_KEY = "network_selection_key";
70    // Key used to read and write the saved network selection operator name
71    public static final String NETWORK_SELECTION_NAME_KEY = "network_selection_name_key";
72
73
74    // Key used to read/write "disable data connection on boot" pref (used for testing)
75    public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
76
77    /* Event Constants */
78    protected static final int EVENT_RADIO_AVAILABLE             = 1;
79    /** Supplementary Service Notification received. */
80    protected static final int EVENT_SSN                         = 2;
81    protected static final int EVENT_SIM_RECORDS_LOADED          = 3;
82    protected static final int EVENT_MMI_DONE                    = 4;
83    protected static final int EVENT_RADIO_ON                    = 5;
84    protected static final int EVENT_GET_BASEBAND_VERSION_DONE   = 6;
85    protected static final int EVENT_USSD                        = 7;
86    protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE  = 8;
87    protected static final int EVENT_GET_IMEI_DONE               = 9;
88    protected static final int EVENT_GET_IMEISV_DONE             = 10;
89    protected static final int EVENT_GET_SIM_STATUS_DONE         = 11;
90    protected static final int EVENT_SET_CALL_FORWARD_DONE       = 12;
91    protected static final int EVENT_GET_CALL_FORWARD_DONE       = 13;
92    protected static final int EVENT_CALL_RING                   = 14;
93    protected static final int EVENT_CALL_RING_CONTINUE          = 15;
94
95    // Used to intercept the carrier selection calls so that
96    // we can save the values.
97    protected static final int EVENT_SET_NETWORK_MANUAL_COMPLETE    = 16;
98    protected static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 17;
99    protected static final int EVENT_SET_CLIR_COMPLETE              = 18;
100    protected static final int EVENT_REGISTERED_TO_NETWORK          = 19;
101    protected static final int EVENT_SET_VM_NUMBER_DONE             = 20;
102    // Events for CDMA support
103    protected static final int EVENT_GET_DEVICE_IDENTITY_DONE       = 21;
104    protected static final int EVENT_RUIM_RECORDS_LOADED            = 22;
105    protected static final int EVENT_NV_READY                       = 23;
106    protected static final int EVENT_SET_ENHANCED_VP                = 24;
107    protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER  = 25;
108    protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 26;
109    protected static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 27;
110    // other
111    protected static final int EVENT_SET_NETWORK_AUTOMATIC          = 28;
112    protected static final int EVENT_NEW_ICC_SMS                    = 29;
113    protected static final int EVENT_ICC_RECORD_EVENTS              = 30;
114    protected static final int EVENT_ICC_CHANGED                    = 31;
115
116    // Key used to read/write current CLIR setting
117    public static final String CLIR_KEY = "clir_key";
118
119    // Key used to read/write "disable DNS server check" pref (used for testing)
120    public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
121
122    /* Instance Variables */
123    public CommandsInterface mCM;
124    boolean mDnsCheckDisabled;
125    public DataConnectionTrackerBase mDataConnectionTracker;
126    boolean mDoesRilSendMultipleCallRing;
127    int mCallRingContinueToken;
128    int mCallRingDelay;
129    public boolean mIsTheCurrentActivePhone = true;
130    boolean mIsVoiceCapable = true;
131    protected UiccController mUiccController = null;
132    public AtomicReference<IccRecords> mIccRecords = new AtomicReference<IccRecords>();
133    public SmsStorageMonitor mSmsStorageMonitor;
134    public SmsUsageMonitor mSmsUsageMonitor;
135    protected AtomicReference<UiccCardApplication> mUiccApplication =
136            new AtomicReference<UiccCardApplication>();
137    public SMSDispatcher mSMS;
138
139    /**
140     * Set a system property, unless we're in unit test mode
141     */
142    public void
143    setSystemProperty(String property, String value) {
144        if(getUnitTestMode()) {
145            return;
146        }
147        SystemProperties.set(property, value);
148    }
149
150
151    protected final RegistrantList mPreciseCallStateRegistrants
152            = new RegistrantList();
153
154    protected final RegistrantList mNewRingingConnectionRegistrants
155            = new RegistrantList();
156
157    protected final RegistrantList mIncomingRingRegistrants
158            = new RegistrantList();
159
160    protected final RegistrantList mDisconnectRegistrants
161            = new RegistrantList();
162
163    protected final RegistrantList mServiceStateRegistrants
164            = new RegistrantList();
165
166    protected final RegistrantList mMmiCompleteRegistrants
167            = new RegistrantList();
168
169    protected final RegistrantList mMmiRegistrants
170            = new RegistrantList();
171
172    protected final RegistrantList mUnknownConnectionRegistrants
173            = new RegistrantList();
174
175    protected final RegistrantList mSuppServiceFailedRegistrants
176            = new RegistrantList();
177
178    protected Looper mLooper; /* to insure registrants are in correct thread*/
179
180    protected final Context mContext;
181
182    /**
183     * PhoneNotifier is an abstraction for all system-wide
184     * state change notification. DefaultPhoneNotifier is
185     * used here unless running we're inside a unit test.
186     */
187    protected PhoneNotifier mNotifier;
188
189    protected SimulatedRadioControl mSimulatedRadioControl;
190
191    boolean mUnitTestMode;
192
193    /**
194     * Constructs a PhoneBase in normal (non-unit test) mode.
195     *
196     * @param notifier An instance of DefaultPhoneNotifier,
197     * @param context Context object from hosting application
198     * unless unit testing.
199     * @param ci the CommandsInterface
200     */
201    protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci) {
202        this(notifier, context, ci, false);
203    }
204
205    /**
206     * Constructs a PhoneBase in normal (non-unit test) mode.
207     *
208     * @param notifier An instance of DefaultPhoneNotifier,
209     * @param context Context object from hosting application
210     * unless unit testing.
211     * @param ci is CommandsInterface
212     * @param unitTestMode when true, prevents notifications
213     * of state change events
214     */
215    protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci,
216            boolean unitTestMode) {
217        this.mNotifier = notifier;
218        this.mContext = context;
219        mLooper = Looper.myLooper();
220        mCM = ci;
221
222        setPropertiesByCarrier();
223
224        setUnitTestMode(unitTestMode);
225
226        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
227        mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
228        mCM.setOnCallRing(this, EVENT_CALL_RING, null);
229
230        /* "Voice capable" means that this device supports circuit-switched
231        * (i.e. voice) phone calls over the telephony network, and is allowed
232        * to display the in-call UI while a cellular voice call is active.
233        * This will be false on "data only" devices which can't make voice
234        * calls and don't support any in-call UI.
235        */
236        mIsVoiceCapable = mContext.getResources().getBoolean(
237                com.android.internal.R.bool.config_voice_capable);
238
239        /**
240         *  Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs
241         *  to be generated locally. Ideally all ring tones should be loops
242         * and this wouldn't be necessary. But to minimize changes to upper
243         * layers it is requested that it be generated by lower layers.
244         *
245         * By default old phones won't have the property set but do generate
246         * the RIL_UNSOL_CALL_RING so the default if there is no property is
247         * true.
248         */
249        mDoesRilSendMultipleCallRing = SystemProperties.getBoolean(
250                TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true);
251        Rlog.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
252
253        mCallRingDelay = SystemProperties.getInt(
254                TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000);
255        Rlog.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
256
257        // Initialize device storage and outgoing SMS usage monitors for SMSDispatchers.
258        mSmsStorageMonitor = new SmsStorageMonitor(this);
259        mSmsUsageMonitor = new SmsUsageMonitor(context);
260        mUiccController = UiccController.getInstance();
261        mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null);
262    }
263
264    @Override
265    public void dispose() {
266        synchronized(PhoneProxy.lockForRadioTechnologyChange) {
267            mCM.unSetOnCallRing(this);
268            // Must cleanup all connectionS and needs to use sendMessage!
269            mDataConnectionTracker.cleanUpAllConnections(null);
270            mIsTheCurrentActivePhone = false;
271            // Dispose the SMS usage and storage monitors
272            mSmsStorageMonitor.dispose();
273            mSmsUsageMonitor.dispose();
274            mUiccController.unregisterForIccChanged(this);
275        }
276    }
277
278    @Override
279    public void removeReferences() {
280        mSmsStorageMonitor = null;
281        mSmsUsageMonitor = null;
282        mSMS = null;
283        mIccRecords.set(null);
284        mUiccApplication.set(null);
285        mDataConnectionTracker = null;
286        mUiccController = null;
287    }
288
289    /**
290     * When overridden the derived class needs to call
291     * super.handleMessage(msg) so this method has a
292     * a chance to process the message.
293     *
294     * @param msg
295     */
296    @Override
297    public void handleMessage(Message msg) {
298        AsyncResult ar;
299
300        switch(msg.what) {
301            case EVENT_CALL_RING:
302                Rlog.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState());
303                ar = (AsyncResult)msg.obj;
304                if (ar.exception == null) {
305                    PhoneConstants.State state = getState();
306                    if ((!mDoesRilSendMultipleCallRing)
307                            && ((state == PhoneConstants.State.RINGING) ||
308                                    (state == PhoneConstants.State.IDLE))) {
309                        mCallRingContinueToken += 1;
310                        sendIncomingCallRingNotification(mCallRingContinueToken);
311                    } else {
312                        notifyIncomingRing();
313                    }
314                }
315                break;
316
317            case EVENT_CALL_RING_CONTINUE:
318                Rlog.d(LOG_TAG, "Event EVENT_CALL_RING_CONTINUE Received stat=" + getState());
319                if (getState() == PhoneConstants.State.RINGING) {
320                    sendIncomingCallRingNotification(msg.arg1);
321                }
322                break;
323
324            case EVENT_ICC_CHANGED:
325                onUpdateIccAvailability();
326                break;
327
328            default:
329                throw new RuntimeException("unexpected event not handled");
330        }
331    }
332
333    // Inherited documentation suffices.
334    @Override
335    public Context getContext() {
336        return mContext;
337    }
338
339    // Will be called when icc changed
340    protected abstract void onUpdateIccAvailability();
341
342    /**
343     * Disables the DNS check (i.e., allows "0.0.0.0").
344     * Useful for lab testing environment.
345     * @param b true disables the check, false enables.
346     */
347    @Override
348    public void disableDnsCheck(boolean b) {
349        mDnsCheckDisabled = b;
350        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
351        SharedPreferences.Editor editor = sp.edit();
352        editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);
353        editor.apply();
354    }
355
356    /**
357     * Returns true if the DNS check is currently disabled.
358     */
359    @Override
360    public boolean isDnsCheckDisabled() {
361        return mDnsCheckDisabled;
362    }
363
364    // Inherited documentation suffices.
365    @Override
366    public void registerForPreciseCallStateChanged(Handler h, int what, Object obj) {
367        checkCorrectThread(h);
368
369        mPreciseCallStateRegistrants.addUnique(h, what, obj);
370    }
371
372    // Inherited documentation suffices.
373    @Override
374    public void unregisterForPreciseCallStateChanged(Handler h) {
375        mPreciseCallStateRegistrants.remove(h);
376    }
377
378    /**
379     * Subclasses of Phone probably want to replace this with a
380     * version scoped to their packages
381     */
382    protected void notifyPreciseCallStateChangedP() {
383        AsyncResult ar = new AsyncResult(null, this, null);
384        mPreciseCallStateRegistrants.notifyRegistrants(ar);
385    }
386
387    // Inherited documentation suffices.
388    @Override
389    public void registerForUnknownConnection(Handler h, int what, Object obj) {
390        checkCorrectThread(h);
391
392        mUnknownConnectionRegistrants.addUnique(h, what, obj);
393    }
394
395    // Inherited documentation suffices.
396    @Override
397    public void unregisterForUnknownConnection(Handler h) {
398        mUnknownConnectionRegistrants.remove(h);
399    }
400
401    // Inherited documentation suffices.
402    @Override
403    public void registerForNewRingingConnection(
404            Handler h, int what, Object obj) {
405        checkCorrectThread(h);
406
407        mNewRingingConnectionRegistrants.addUnique(h, what, obj);
408    }
409
410    // Inherited documentation suffices.
411    @Override
412    public void unregisterForNewRingingConnection(Handler h) {
413        mNewRingingConnectionRegistrants.remove(h);
414    }
415
416    // Inherited documentation suffices.
417    @Override
418    public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
419        mCM.registerForInCallVoicePrivacyOn(h,what,obj);
420    }
421
422    // Inherited documentation suffices.
423    @Override
424    public void unregisterForInCallVoicePrivacyOn(Handler h){
425        mCM.unregisterForInCallVoicePrivacyOn(h);
426    }
427
428    // Inherited documentation suffices.
429    @Override
430    public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
431        mCM.registerForInCallVoicePrivacyOff(h,what,obj);
432    }
433
434    // Inherited documentation suffices.
435    @Override
436    public void unregisterForInCallVoicePrivacyOff(Handler h){
437        mCM.unregisterForInCallVoicePrivacyOff(h);
438    }
439
440    // Inherited documentation suffices.
441    @Override
442    public void registerForIncomingRing(
443            Handler h, int what, Object obj) {
444        checkCorrectThread(h);
445
446        mIncomingRingRegistrants.addUnique(h, what, obj);
447    }
448
449    // Inherited documentation suffices.
450    @Override
451    public void unregisterForIncomingRing(Handler h) {
452        mIncomingRingRegistrants.remove(h);
453    }
454
455    // Inherited documentation suffices.
456    @Override
457    public void registerForDisconnect(Handler h, int what, Object obj) {
458        checkCorrectThread(h);
459
460        mDisconnectRegistrants.addUnique(h, what, obj);
461    }
462
463    // Inherited documentation suffices.
464    @Override
465    public void unregisterForDisconnect(Handler h) {
466        mDisconnectRegistrants.remove(h);
467    }
468
469    // Inherited documentation suffices.
470    @Override
471    public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
472        checkCorrectThread(h);
473
474        mSuppServiceFailedRegistrants.addUnique(h, what, obj);
475    }
476
477    // Inherited documentation suffices.
478    @Override
479    public void unregisterForSuppServiceFailed(Handler h) {
480        mSuppServiceFailedRegistrants.remove(h);
481    }
482
483    // Inherited documentation suffices.
484    @Override
485    public void registerForMmiInitiate(Handler h, int what, Object obj) {
486        checkCorrectThread(h);
487
488        mMmiRegistrants.addUnique(h, what, obj);
489    }
490
491    // Inherited documentation suffices.
492    @Override
493    public void unregisterForMmiInitiate(Handler h) {
494        mMmiRegistrants.remove(h);
495    }
496
497    // Inherited documentation suffices.
498    @Override
499    public void registerForMmiComplete(Handler h, int what, Object obj) {
500        checkCorrectThread(h);
501
502        mMmiCompleteRegistrants.addUnique(h, what, obj);
503    }
504
505    // Inherited documentation suffices.
506    @Override
507    public void unregisterForMmiComplete(Handler h) {
508        checkCorrectThread(h);
509
510        mMmiCompleteRegistrants.remove(h);
511    }
512
513    /**
514     * Method to retrieve the saved operator id from the Shared Preferences
515     */
516    private String getSavedNetworkSelection() {
517        // open the shared preferences and search with our key.
518        SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
519        return sp.getString(NETWORK_SELECTION_KEY, "");
520    }
521
522    /**
523     * Method to restore the previously saved operator id, or reset to
524     * automatic selection, all depending upon the value in the shared
525     * preferences.
526     */
527    public void restoreSavedNetworkSelection(Message response) {
528        // retrieve the operator id
529        String networkSelection = getSavedNetworkSelection();
530
531        // set to auto if the id is empty, otherwise select the network.
532        if (TextUtils.isEmpty(networkSelection)) {
533            mCM.setNetworkSelectionModeAutomatic(response);
534        } else {
535            mCM.setNetworkSelectionModeManual(networkSelection, response);
536        }
537    }
538
539    // Inherited documentation suffices.
540    @Override
541    public void setUnitTestMode(boolean f) {
542        mUnitTestMode = f;
543    }
544
545    // Inherited documentation suffices.
546    @Override
547    public boolean getUnitTestMode() {
548        return mUnitTestMode;
549    }
550
551    /**
552     * To be invoked when a voice call Connection disconnects.
553     *
554     * Subclasses of Phone probably want to replace this with a
555     * version scoped to their packages
556     */
557    protected void notifyDisconnectP(Connection cn) {
558        AsyncResult ar = new AsyncResult(null, cn, null);
559        mDisconnectRegistrants.notifyRegistrants(ar);
560    }
561
562    // Inherited documentation suffices.
563    @Override
564    public void registerForServiceStateChanged(
565            Handler h, int what, Object obj) {
566        checkCorrectThread(h);
567
568        mServiceStateRegistrants.add(h, what, obj);
569    }
570
571    // Inherited documentation suffices.
572    @Override
573    public void unregisterForServiceStateChanged(Handler h) {
574        mServiceStateRegistrants.remove(h);
575    }
576
577    // Inherited documentation suffices.
578    @Override
579    public void registerForRingbackTone(Handler h, int what, Object obj) {
580        mCM.registerForRingbackTone(h,what,obj);
581    }
582
583    // Inherited documentation suffices.
584    @Override
585    public void unregisterForRingbackTone(Handler h) {
586        mCM.unregisterForRingbackTone(h);
587    }
588
589    // Inherited documentation suffices.
590    @Override
591    public void registerForResendIncallMute(Handler h, int what, Object obj) {
592        mCM.registerForResendIncallMute(h,what,obj);
593    }
594
595    // Inherited documentation suffices.
596    @Override
597    public void unregisterForResendIncallMute(Handler h) {
598        mCM.unregisterForResendIncallMute(h);
599    }
600
601    @Override
602    public void setEchoSuppressionEnabled(boolean enabled) {
603        // no need for regular phone
604    }
605
606    /**
607     * Subclasses of Phone probably want to replace this with a
608     * version scoped to their packages
609     */
610    protected void notifyServiceStateChangedP(ServiceState ss) {
611        AsyncResult ar = new AsyncResult(null, ss, null);
612        mServiceStateRegistrants.notifyRegistrants(ar);
613
614        mNotifier.notifyServiceState(this);
615    }
616
617    // Inherited documentation suffices.
618    @Override
619    public SimulatedRadioControl getSimulatedRadioControl() {
620        return mSimulatedRadioControl;
621    }
622
623    /**
624     * Verifies the current thread is the same as the thread originally
625     * used in the initialization of this instance. Throws RuntimeException
626     * if not.
627     *
628     * @exception RuntimeException if the current thread is not
629     * the thread that originally obtained this PhoneBase instance.
630     */
631    private void checkCorrectThread(Handler h) {
632        if (h.getLooper() != mLooper) {
633            throw new RuntimeException(
634                    "com.android.internal.telephony.Phone must be used from within one thread");
635        }
636    }
637
638    /**
639     * Set the properties by matching the carrier string in
640     * a string-array resource
641     */
642    private void setPropertiesByCarrier() {
643        String carrier = SystemProperties.get("ro.carrier");
644
645        if (null == carrier || 0 == carrier.length() || "unknown".equals(carrier)) {
646            return;
647        }
648
649        CharSequence[] carrierLocales = mContext.
650                getResources().getTextArray(R.array.carrier_properties);
651
652        for (int i = 0; i < carrierLocales.length; i+=3) {
653            String c = carrierLocales[i].toString();
654            if (carrier.equals(c)) {
655                String l = carrierLocales[i+1].toString();
656
657                String language = l.substring(0, 2);
658                String country = "";
659                if (l.length() >=5) {
660                    country = l.substring(3, 5);
661                }
662                MccTable.setSystemLocale(mContext, language, country);
663
664                if (!country.isEmpty()) {
665                    try {
666                        Settings.Global.getInt(mContext.getContentResolver(),
667                                Settings.Global.WIFI_COUNTRY_CODE);
668                    } catch (Settings.SettingNotFoundException e) {
669                        // note this is not persisting
670                        WifiManager wM = (WifiManager)
671                                mContext.getSystemService(Context.WIFI_SERVICE);
672                        wM.setCountryCode(country, false);
673                    }
674                }
675                return;
676            }
677        }
678    }
679
680    /**
681     * Get state
682     */
683    @Override
684    public abstract PhoneConstants.State getState();
685
686    /**
687     * Retrieves the IccFileHandler of the Phone instance
688     */
689    public IccFileHandler getIccFileHandler(){
690        UiccCardApplication uiccApplication = mUiccApplication.get();
691        if (uiccApplication == null) return null;
692        return uiccApplication.getIccFileHandler();
693    }
694
695    /*
696     * Retrieves the Handler of the Phone instance
697     */
698    public Handler getHandler() {
699        return this;
700    }
701
702    /**
703    * Retrieves the ServiceStateTracker of the phone instance.
704    */
705    public ServiceStateTracker getServiceStateTracker() {
706        return null;
707    }
708
709    /**
710    * Get call tracker
711    */
712    public CallTracker getCallTracker() {
713        return null;
714    }
715
716    public AppType getCurrentUiccAppType() {
717        UiccCardApplication currentApp = mUiccApplication.get();
718        if (currentApp != null) {
719            return currentApp.getType();
720        }
721        return AppType.APPTYPE_UNKNOWN;
722    }
723
724    @Override
725    public IccCard getIccCard() {
726        return null;
727        //throw new Exception("getIccCard Shouldn't be called from PhoneBase");
728    }
729
730    @Override
731    public String getIccSerialNumber() {
732        IccRecords r = mIccRecords.get();
733        return (r != null) ? r.iccid : "";
734    }
735
736    @Override
737    public boolean getIccRecordsLoaded() {
738        IccRecords r = mIccRecords.get();
739        return (r != null) ? r.getRecordsLoaded() : false;
740    }
741
742    /**
743     * @return all available cell information or null if none.
744     */
745    @Override
746    public List<CellInfo> getAllCellInfo() {
747        return getServiceStateTracker().getAllCellInfo();
748    }
749
750    @Override
751    public boolean getMessageWaitingIndicator() {
752        IccRecords r = mIccRecords.get();
753        return (r != null) ? r.getVoiceMessageWaiting() : false;
754    }
755
756    @Override
757    public boolean getCallForwardingIndicator() {
758        IccRecords r = mIccRecords.get();
759        return (r != null) ? r.getVoiceCallForwardingFlag() : false;
760    }
761
762    /**
763     *  Query the status of the CDMA roaming preference
764     */
765    @Override
766    public void queryCdmaRoamingPreference(Message response) {
767        mCM.queryCdmaRoamingPreference(response);
768    }
769
770    /**
771     * Get the signal strength
772     */
773    @Override
774    public SignalStrength getSignalStrength() {
775        ServiceStateTracker sst = getServiceStateTracker();
776        if (sst == null) {
777            return new SignalStrength();
778        } else {
779            return sst.getSignalStrength();
780        }
781    }
782
783    /**
784     *  Set the status of the CDMA roaming preference
785     */
786    @Override
787    public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
788        mCM.setCdmaRoamingPreference(cdmaRoamingType, response);
789    }
790
791    /**
792     *  Set the status of the CDMA subscription mode
793     */
794    @Override
795    public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
796        mCM.setCdmaSubscriptionSource(cdmaSubscriptionType, response);
797    }
798
799    /**
800     *  Set the preferred Network Type: Global, CDMA only or GSM/UMTS only
801     */
802    @Override
803    public void setPreferredNetworkType(int networkType, Message response) {
804        mCM.setPreferredNetworkType(networkType, response);
805    }
806
807    @Override
808    public void getPreferredNetworkType(Message response) {
809        mCM.getPreferredNetworkType(response);
810    }
811
812    @Override
813    public void getSmscAddress(Message result) {
814        mCM.getSmscAddress(result);
815    }
816
817    @Override
818    public void setSmscAddress(String address, Message result) {
819        mCM.setSmscAddress(address, result);
820    }
821
822    @Override
823    public void setTTYMode(int ttyMode, Message onComplete) {
824        mCM.setTTYMode(ttyMode, onComplete);
825    }
826
827    @Override
828    public void queryTTYMode(Message onComplete) {
829        mCM.queryTTYMode(onComplete);
830    }
831
832    @Override
833    public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
834        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
835        logUnexpectedCdmaMethodCall("enableEnhancedVoicePrivacy");
836    }
837
838    @Override
839    public void getEnhancedVoicePrivacy(Message onComplete) {
840        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
841        logUnexpectedCdmaMethodCall("getEnhancedVoicePrivacy");
842    }
843
844    @Override
845    public void setBandMode(int bandMode, Message response) {
846        mCM.setBandMode(bandMode, response);
847    }
848
849    @Override
850    public void queryAvailableBandMode(Message response) {
851        mCM.queryAvailableBandMode(response);
852    }
853
854    @Override
855    public void invokeOemRilRequestRaw(byte[] data, Message response) {
856        mCM.invokeOemRilRequestRaw(data, response);
857    }
858
859    @Override
860    public void invokeOemRilRequestStrings(String[] strings, Message response) {
861        mCM.invokeOemRilRequestStrings(strings, response);
862    }
863
864    @Override
865    public void notifyDataActivity() {
866        mNotifier.notifyDataActivity(this);
867    }
868
869    public void notifyMessageWaitingIndicator() {
870        // Do not notify voice mail waiting if device doesn't support voice
871        if (!mIsVoiceCapable)
872            return;
873
874        // This function is added to send the notification to DefaultPhoneNotifier.
875        mNotifier.notifyMessageWaitingChanged(this);
876    }
877
878    public void notifyDataConnection(String reason, String apnType,
879            PhoneConstants.DataState state) {
880        mNotifier.notifyDataConnection(this, reason, apnType, state);
881    }
882
883    public void notifyDataConnection(String reason, String apnType) {
884        mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
885    }
886
887    public void notifyDataConnection(String reason) {
888        String types[] = getActiveApnTypes();
889        for (String apnType : types) {
890            mNotifier.notifyDataConnection(this, reason, apnType, getDataConnectionState(apnType));
891        }
892    }
893
894    public void notifyOtaspChanged(int otaspMode) {
895        mNotifier.notifyOtaspChanged(this, otaspMode);
896    }
897
898    public void notifySignalStrength() {
899        mNotifier.notifySignalStrength(this);
900    }
901
902    public void notifyCellInfo(List<CellInfo> cellInfo) {
903        mNotifier.notifyCellInfo(this, cellInfo);
904    }
905
906    /**
907     * @return true if a mobile originating emergency call is active
908     */
909    public boolean isInEmergencyCall() {
910        return false;
911    }
912
913    /**
914     * @return true if we are in the emergency call back mode. This is a period where
915     * the phone should be using as little power as possible and be ready to receive an
916     * incoming call from the emergency operator.
917     */
918    public boolean isInEcm() {
919        return false;
920    }
921
922    @Override
923    public abstract String getPhoneName();
924
925    @Override
926    public abstract int getPhoneType();
927
928    /** @hide */
929    @Override
930    public int getVoiceMessageCount(){
931        return 0;
932    }
933
934    /**
935     * Returns the CDMA ERI icon index to display
936     */
937    @Override
938    public int getCdmaEriIconIndex() {
939        logUnexpectedCdmaMethodCall("getCdmaEriIconIndex");
940        return -1;
941    }
942
943    /**
944     * Returns the CDMA ERI icon mode,
945     * 0 - ON
946     * 1 - FLASHING
947     */
948    @Override
949    public int getCdmaEriIconMode() {
950        logUnexpectedCdmaMethodCall("getCdmaEriIconMode");
951        return -1;
952    }
953
954    /**
955     * Returns the CDMA ERI text,
956     */
957    @Override
958    public String getCdmaEriText() {
959        logUnexpectedCdmaMethodCall("getCdmaEriText");
960        return "GSM nw, no ERI";
961    }
962
963    @Override
964    public String getCdmaMin() {
965        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
966        logUnexpectedCdmaMethodCall("getCdmaMin");
967        return null;
968    }
969
970    @Override
971    public boolean isMinInfoReady() {
972        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
973        logUnexpectedCdmaMethodCall("isMinInfoReady");
974        return false;
975    }
976
977    @Override
978    public String getCdmaPrlVersion(){
979        //  This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
980        logUnexpectedCdmaMethodCall("getCdmaPrlVersion");
981        return null;
982    }
983
984    @Override
985    public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
986        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
987        logUnexpectedCdmaMethodCall("sendBurstDtmf");
988    }
989
990    @Override
991    public void exitEmergencyCallbackMode() {
992        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
993        logUnexpectedCdmaMethodCall("exitEmergencyCallbackMode");
994    }
995
996    @Override
997    public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
998        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
999        logUnexpectedCdmaMethodCall("registerForCdmaOtaStatusChange");
1000    }
1001
1002    @Override
1003    public void unregisterForCdmaOtaStatusChange(Handler h) {
1004        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1005        logUnexpectedCdmaMethodCall("unregisterForCdmaOtaStatusChange");
1006    }
1007
1008    @Override
1009    public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
1010        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1011        logUnexpectedCdmaMethodCall("registerForSubscriptionInfoReady");
1012    }
1013
1014    @Override
1015    public void unregisterForSubscriptionInfoReady(Handler h) {
1016        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1017        logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady");
1018    }
1019
1020    /**
1021     * Returns true if OTA Service Provisioning needs to be performed.
1022     * If not overridden return false.
1023     */
1024    @Override
1025    public boolean needsOtaServiceProvisioning() {
1026        return false;
1027    }
1028
1029    /**
1030     * Return true if number is an OTASP number.
1031     * If not overridden return false.
1032     */
1033    @Override
1034    public  boolean isOtaSpNumber(String dialStr) {
1035        return false;
1036    }
1037
1038    @Override
1039    public void registerForCallWaiting(Handler h, int what, Object obj){
1040        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1041        logUnexpectedCdmaMethodCall("registerForCallWaiting");
1042    }
1043
1044    @Override
1045    public void unregisterForCallWaiting(Handler h){
1046        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1047        logUnexpectedCdmaMethodCall("unregisterForCallWaiting");
1048    }
1049
1050    @Override
1051    public void registerForEcmTimerReset(Handler h, int what, Object obj) {
1052        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1053        logUnexpectedCdmaMethodCall("registerForEcmTimerReset");
1054    }
1055
1056    @Override
1057    public void unregisterForEcmTimerReset(Handler h) {
1058        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1059        logUnexpectedCdmaMethodCall("unregisterForEcmTimerReset");
1060    }
1061
1062    @Override
1063    public void registerForSignalInfo(Handler h, int what, Object obj) {
1064        mCM.registerForSignalInfo(h, what, obj);
1065    }
1066
1067    @Override
1068    public void unregisterForSignalInfo(Handler h) {
1069        mCM.unregisterForSignalInfo(h);
1070    }
1071
1072    @Override
1073    public void registerForDisplayInfo(Handler h, int what, Object obj) {
1074        mCM.registerForDisplayInfo(h, what, obj);
1075    }
1076
1077     @Override
1078    public void unregisterForDisplayInfo(Handler h) {
1079         mCM.unregisterForDisplayInfo(h);
1080     }
1081
1082    @Override
1083    public void registerForNumberInfo(Handler h, int what, Object obj) {
1084        mCM.registerForNumberInfo(h, what, obj);
1085    }
1086
1087    @Override
1088    public void unregisterForNumberInfo(Handler h) {
1089        mCM.unregisterForNumberInfo(h);
1090    }
1091
1092    @Override
1093    public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
1094        mCM.registerForRedirectedNumberInfo(h, what, obj);
1095    }
1096
1097    @Override
1098    public void unregisterForRedirectedNumberInfo(Handler h) {
1099        mCM.unregisterForRedirectedNumberInfo(h);
1100    }
1101
1102    @Override
1103    public void registerForLineControlInfo(Handler h, int what, Object obj) {
1104        mCM.registerForLineControlInfo( h, what, obj);
1105    }
1106
1107    @Override
1108    public void unregisterForLineControlInfo(Handler h) {
1109        mCM.unregisterForLineControlInfo(h);
1110    }
1111
1112    @Override
1113    public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
1114        mCM.registerFoT53ClirlInfo(h, what, obj);
1115    }
1116
1117    @Override
1118    public void unregisterForT53ClirInfo(Handler h) {
1119        mCM.unregisterForT53ClirInfo(h);
1120    }
1121
1122    @Override
1123    public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
1124        mCM.registerForT53AudioControlInfo( h, what, obj);
1125    }
1126
1127    @Override
1128    public void unregisterForT53AudioControlInfo(Handler h) {
1129        mCM.unregisterForT53AudioControlInfo(h);
1130    }
1131
1132     @Override
1133    public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
1134         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1135         logUnexpectedCdmaMethodCall("setOnEcbModeExitResponse");
1136     }
1137
1138     @Override
1139    public void unsetOnEcbModeExitResponse(Handler h){
1140        // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
1141         logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse");
1142     }
1143
1144    @Override
1145    public String[] getActiveApnTypes() {
1146        return mDataConnectionTracker.getActiveApnTypes();
1147    }
1148
1149    @Override
1150    public String getActiveApnHost(String apnType) {
1151        return mDataConnectionTracker.getActiveApnString(apnType);
1152    }
1153
1154    @Override
1155    public LinkProperties getLinkProperties(String apnType) {
1156        return mDataConnectionTracker.getLinkProperties(apnType);
1157    }
1158
1159    @Override
1160    public LinkCapabilities getLinkCapabilities(String apnType) {
1161        return mDataConnectionTracker.getLinkCapabilities(apnType);
1162    }
1163
1164    @Override
1165    public int enableApnType(String type) {
1166        return mDataConnectionTracker.enableApnType(type);
1167    }
1168
1169    @Override
1170    public int disableApnType(String type) {
1171        return mDataConnectionTracker.disableApnType(type);
1172    }
1173
1174    @Override
1175    public boolean isDataConnectivityPossible() {
1176        return isDataConnectivityPossible(PhoneConstants.APN_TYPE_DEFAULT);
1177    }
1178
1179    @Override
1180    public boolean isDataConnectivityPossible(String apnType) {
1181        return ((mDataConnectionTracker != null) &&
1182                (mDataConnectionTracker.isDataPossible(apnType)));
1183    }
1184
1185    /**
1186     * Notify registrants of a new ringing Connection.
1187     * Subclasses of Phone probably want to replace this with a
1188     * version scoped to their packages
1189     */
1190    protected void notifyNewRingingConnectionP(Connection cn) {
1191        if (!mIsVoiceCapable)
1192            return;
1193        AsyncResult ar = new AsyncResult(null, cn, null);
1194        mNewRingingConnectionRegistrants.notifyRegistrants(ar);
1195    }
1196
1197    /**
1198     * Notify registrants of a RING event.
1199     */
1200    private void notifyIncomingRing() {
1201        if (!mIsVoiceCapable)
1202            return;
1203        AsyncResult ar = new AsyncResult(null, this, null);
1204        mIncomingRingRegistrants.notifyRegistrants(ar);
1205    }
1206
1207    /**
1208     * Send the incoming call Ring notification if conditions are right.
1209     */
1210    private void sendIncomingCallRingNotification(int token) {
1211        if (mIsVoiceCapable && !mDoesRilSendMultipleCallRing &&
1212                (token == mCallRingContinueToken)) {
1213            Rlog.d(LOG_TAG, "Sending notifyIncomingRing");
1214            notifyIncomingRing();
1215            sendMessageDelayed(
1216                    obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
1217        } else {
1218            Rlog.d(LOG_TAG, "Ignoring ring notification request,"
1219                    + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
1220                    + " token=" + token
1221                    + " mCallRingContinueToken=" + mCallRingContinueToken
1222                    + " mIsVoiceCapable=" + mIsVoiceCapable);
1223        }
1224    }
1225
1226    @Override
1227    public boolean isCspPlmnEnabled() {
1228        // This function should be overridden by the class GSMPhone.
1229        // Not implemented in CDMAPhone.
1230        logUnexpectedGsmMethodCall("isCspPlmnEnabled");
1231        return false;
1232    }
1233
1234    @Override
1235    public IsimRecords getIsimRecords() {
1236        Rlog.e(LOG_TAG, "getIsimRecords() is only supported on LTE devices");
1237        return null;
1238    }
1239
1240    @Override
1241    public void requestIsimAuthentication(String nonce, Message result) {
1242        Rlog.e(LOG_TAG, "requestIsimAuthentication() is only supported on LTE devices");
1243    }
1244
1245    @Override
1246    public String getMsisdn() {
1247        logUnexpectedGsmMethodCall("getMsisdn");
1248        return null;
1249    }
1250
1251    /**
1252     * Common error logger method for unexpected calls to CDMA-only methods.
1253     */
1254    private static void logUnexpectedCdmaMethodCall(String name)
1255    {
1256        Rlog.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
1257                "called, CDMAPhone inactive.");
1258    }
1259
1260    @Override
1261    public PhoneConstants.DataState getDataConnectionState() {
1262        return getDataConnectionState(PhoneConstants.APN_TYPE_DEFAULT);
1263    }
1264
1265    /**
1266     * Common error logger method for unexpected calls to GSM/WCDMA-only methods.
1267     */
1268    private static void logUnexpectedGsmMethodCall(String name) {
1269        Rlog.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
1270                "called, GSMPhone inactive.");
1271    }
1272
1273    // Called by SimRecords which is constructed with a PhoneBase instead of a GSMPhone.
1274    public void notifyCallForwardingIndicator() {
1275        // This function should be overridden by the class GSMPhone. Not implemented in CDMAPhone.
1276        Rlog.e(LOG_TAG, "Error! This function should never be executed, inactive CDMAPhone.");
1277    }
1278
1279    public void notifyDataConnectionFailed(String reason, String apnType) {
1280        mNotifier.notifyDataConnectionFailed(this, reason, apnType);
1281    }
1282
1283    /**
1284     * {@inheritDoc}
1285     */
1286    @Override
1287    public int getLteOnCdmaMode() {
1288        return mCM.getLteOnCdmaMode();
1289    }
1290
1291    /**
1292     * Sets the SIM voice message waiting indicator records.
1293     * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
1294     * @param countWaiting The number of messages waiting, if known. Use
1295     *                     -1 to indicate that an unknown number of
1296     *                      messages are waiting
1297     */
1298    @Override
1299    public void setVoiceMessageWaiting(int line, int countWaiting) {
1300        IccRecords r = mIccRecords.get();
1301        if (r != null) {
1302            r.setVoiceMessageWaiting(line, countWaiting);
1303        }
1304    }
1305
1306    /**
1307     * Gets the USIM service table from the UICC, if present and available.
1308     * @return an interface to the UsimServiceTable record, or null if not available
1309     */
1310    @Override
1311    public UsimServiceTable getUsimServiceTable() {
1312        IccRecords r = mIccRecords.get();
1313        return (r != null) ? r.getUsimServiceTable() : null;
1314    }
1315
1316    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1317        pw.println("PhoneBase:");
1318        pw.println(" mCM=" + mCM);
1319        pw.println(" mDnsCheckDisabled=" + mDnsCheckDisabled);
1320        pw.println(" mDataConnectionTracker=" + mDataConnectionTracker);
1321        pw.println(" mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
1322        pw.println(" mCallRingContinueToken=" + mCallRingContinueToken);
1323        pw.println(" mCallRingDelay=" + mCallRingDelay);
1324        pw.println(" mIsTheCurrentActivePhone=" + mIsTheCurrentActivePhone);
1325        pw.println(" mIsVoiceCapable=" + mIsVoiceCapable);
1326        pw.println(" mIccRecords=" + mIccRecords.get());
1327        pw.println(" mUiccApplication=" + mUiccApplication.get());
1328        pw.println(" mSmsStorageMonitor=" + mSmsStorageMonitor);
1329        pw.println(" mSmsUsageMonitor=" + mSmsUsageMonitor);
1330        pw.println(" mSMS=" + mSMS);
1331        pw.flush();
1332        pw.println(" mLooper=" + mLooper);
1333        pw.println(" mContext=" + mContext);
1334        pw.println(" mNotifier=" + mNotifier);
1335        pw.println(" mSimulatedRadioControl=" + mSimulatedRadioControl);
1336        pw.println(" mUnitTestMode=" + mUnitTestMode);
1337        pw.println(" isDnsCheckDisabled()=" + isDnsCheckDisabled());
1338        pw.println(" getUnitTestMode()=" + getUnitTestMode());
1339        pw.println(" getState()=" + getState());
1340        pw.println(" getIccSerialNumber()=" + getIccSerialNumber());
1341        pw.println(" getIccRecordsLoaded()=" + getIccRecordsLoaded());
1342        pw.println(" getMessageWaitingIndicator()=" + getMessageWaitingIndicator());
1343        pw.println(" getCallForwardingIndicator()=" + getCallForwardingIndicator());
1344        pw.println(" isInEmergencyCall()=" + isInEmergencyCall());
1345        pw.flush();
1346        pw.println(" isInEcm()=" + isInEcm());
1347        pw.println(" getPhoneName()=" + getPhoneName());
1348        pw.println(" getPhoneType()=" + getPhoneType());
1349        pw.println(" getVoiceMessageCount()=" + getVoiceMessageCount());
1350        pw.println(" getActiveApnTypes()=" + getActiveApnTypes());
1351        pw.println(" isDataConnectivityPossible()=" + isDataConnectivityPossible());
1352        pw.println(" needsOtaServiceProvisioning=" + needsOtaServiceProvisioning());
1353    }
1354}
1355