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