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