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