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