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