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