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