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