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