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