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.app.ActivityManagerNative;
     20 import android.app.IActivityManager;
     21 import android.content.Context;
     22 import android.content.res.Configuration;
     23 import android.content.SharedPreferences;
     24 import android.net.wifi.WifiManager;
     25 import android.os.AsyncResult;
     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.ServiceState;
     34 import android.text.TextUtils;
     35 import android.util.Log;
     36 
     37 import com.android.internal.R;
     38 import com.android.internal.telephony.gsm.GsmDataConnection;
     39 import com.android.internal.telephony.test.SimulatedRadioControl;
     40 
     41 import java.util.List;
     42 import java.util.Locale;
     43 
     44 
     45 /**
     46  * (<em>Not for SDK use</em>)
     47  * A base implementation for the com.android.internal.telephony.Phone interface.
     48  *
     49  * Note that implementations of Phone.java are expected to be used
     50  * from a single application thread. This should be the same thread that
     51  * originally called PhoneFactory to obtain the interface.
     52  *
     53  *  {@hide}
     54  *
     55  */
     56 
     57 public abstract class PhoneBase extends Handler implements Phone {
     58     private static final String LOG_TAG = "PHONE";
     59     private static final boolean LOCAL_DEBUG = true;
     60 
     61     // Key used to read and write the saved network selection numeric value
     62     public static final String NETWORK_SELECTION_KEY = "network_selection_key";
     63     // Key used to read and write the saved network selection operator name
     64     public static final String NETWORK_SELECTION_NAME_KEY = "network_selection_name_key";
     65 
     66 
     67     // Key used to read/write "disable data connection on boot" pref (used for testing)
     68     public static final String DATA_DISABLED_ON_BOOT_KEY = "disabled_on_boot_key";
     69 
     70     /* Event Constants */
     71     protected static final int EVENT_RADIO_AVAILABLE             = 1;
     72     /** Supplementary Service Notification received. */
     73     protected static final int EVENT_SSN                         = 2;
     74     protected static final int EVENT_SIM_RECORDS_LOADED          = 3;
     75     protected static final int EVENT_MMI_DONE                    = 4;
     76     protected static final int EVENT_RADIO_ON                    = 5;
     77     protected static final int EVENT_GET_BASEBAND_VERSION_DONE   = 6;
     78     protected static final int EVENT_USSD                        = 7;
     79     protected static final int EVENT_RADIO_OFF_OR_NOT_AVAILABLE  = 8;
     80     protected static final int EVENT_GET_IMEI_DONE               = 9;
     81     protected static final int EVENT_GET_IMEISV_DONE             = 10;
     82     protected static final int EVENT_GET_SIM_STATUS_DONE         = 11;
     83     protected static final int EVENT_SET_CALL_FORWARD_DONE       = 12;
     84     protected static final int EVENT_GET_CALL_FORWARD_DONE       = 13;
     85     protected static final int EVENT_CALL_RING                   = 14;
     86     protected static final int EVENT_CALL_RING_CONTINUE          = 15;
     87 
     88     // Used to intercept the carrier selection calls so that
     89     // we can save the values.
     90     protected static final int EVENT_SET_NETWORK_MANUAL_COMPLETE    = 16;
     91     protected static final int EVENT_SET_NETWORK_AUTOMATIC_COMPLETE = 17;
     92     protected static final int EVENT_SET_CLIR_COMPLETE              = 18;
     93     protected static final int EVENT_REGISTERED_TO_NETWORK          = 19;
     94     protected static final int EVENT_SET_VM_NUMBER_DONE             = 20;
     95     // Events for CDMA support
     96     protected static final int EVENT_GET_DEVICE_IDENTITY_DONE       = 21;
     97     protected static final int EVENT_RUIM_RECORDS_LOADED            = 22;
     98     protected static final int EVENT_NV_READY                       = 23;
     99     protected static final int EVENT_SET_ENHANCED_VP                = 24;
    100     protected static final int EVENT_EMERGENCY_CALLBACK_MODE_ENTER  = 25;
    101     protected static final int EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE = 26;
    102 
    103     // Key used to read/write current CLIR setting
    104     public static final String CLIR_KEY = "clir_key";
    105 
    106     // Key used to read/write "disable DNS server check" pref (used for testing)
    107     public static final String DNS_SERVER_CHECK_DISABLED_KEY = "dns_server_check_disabled_key";
    108 
    109     /* Instance Variables */
    110     public CommandsInterface mCM;
    111     protected IccFileHandler mIccFileHandler;
    112     boolean mDnsCheckDisabled = false;
    113     public DataConnectionTracker mDataConnection;
    114     boolean mDoesRilSendMultipleCallRing;
    115     int mCallRingContinueToken = 0;
    116     int mCallRingDelay;
    117     public boolean mIsTheCurrentActivePhone = true;
    118 
    119     /**
    120      * Set a system property, unless we're in unit test mode
    121      */
    122     public void
    123     setSystemProperty(String property, String value) {
    124         if(getUnitTestMode()) {
    125             return;
    126         }
    127         SystemProperties.set(property, value);
    128     }
    129 
    130 
    131     protected final RegistrantList mPreciseCallStateRegistrants
    132             = new RegistrantList();
    133 
    134     protected final RegistrantList mNewRingingConnectionRegistrants
    135             = new RegistrantList();
    136 
    137     protected final RegistrantList mIncomingRingRegistrants
    138             = new RegistrantList();
    139 
    140     protected final RegistrantList mDisconnectRegistrants
    141             = new RegistrantList();
    142 
    143     protected final RegistrantList mServiceStateRegistrants
    144             = new RegistrantList();
    145 
    146     protected final RegistrantList mMmiCompleteRegistrants
    147             = new RegistrantList();
    148 
    149     protected final RegistrantList mMmiRegistrants
    150             = new RegistrantList();
    151 
    152     protected final RegistrantList mUnknownConnectionRegistrants
    153             = new RegistrantList();
    154 
    155     protected final RegistrantList mSuppServiceFailedRegistrants
    156             = new RegistrantList();
    157 
    158     protected Looper mLooper; /* to insure registrants are in correct thread*/
    159 
    160     protected Context mContext;
    161 
    162     /**
    163      * PhoneNotifier is an abstraction for all system-wide
    164      * state change notification. DefaultPhoneNotifier is
    165      * used here unless running we're inside a unit test.
    166      */
    167     protected PhoneNotifier mNotifier;
    168 
    169     protected SimulatedRadioControl mSimulatedRadioControl;
    170 
    171     boolean mUnitTestMode;
    172 
    173     /**
    174      * Constructs a PhoneBase in normal (non-unit test) mode.
    175      *
    176      * @param context Context object from hosting application
    177      * @param notifier An instance of DefaultPhoneNotifier,
    178      * unless unit testing.
    179      */
    180     protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci) {
    181         this(notifier, context, ci, false);
    182     }
    183 
    184     /**
    185      * Constructs a PhoneBase in normal (non-unit test) mode.
    186      *
    187      * @param context Context object from hosting application
    188      * @param notifier An instance of DefaultPhoneNotifier,
    189      * unless unit testing.
    190      * @param unitTestMode when true, prevents notifications
    191      * of state change events
    192      */
    193     protected PhoneBase(PhoneNotifier notifier, Context context, CommandsInterface ci,
    194             boolean unitTestMode) {
    195         this.mNotifier = notifier;
    196         this.mContext = context;
    197         mLooper = Looper.myLooper();
    198         mCM = ci;
    199 
    200         setPropertiesByCarrier();
    201 
    202         setUnitTestMode(unitTestMode);
    203 
    204         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
    205         mDnsCheckDisabled = sp.getBoolean(DNS_SERVER_CHECK_DISABLED_KEY, false);
    206         mCM.setOnCallRing(this, EVENT_CALL_RING, null);
    207 
    208         /**
    209          *  Some RIL's don't always send RIL_UNSOL_CALL_RING so it needs
    210          *  to be generated locally. Ideally all ring tones should be loops
    211          * and this wouldn't be necessary. But to minimize changes to upper
    212          * layers it is requested that it be generated by lower layers.
    213          *
    214          * By default old phones won't have the property set but do generate
    215          * the RIL_UNSOL_CALL_RING so the default if there is no property is
    216          * true.
    217          */
    218         mDoesRilSendMultipleCallRing = SystemProperties.getBoolean(
    219                 TelephonyProperties.PROPERTY_RIL_SENDS_MULTIPLE_CALL_RING, true);
    220         Log.d(LOG_TAG, "mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing);
    221 
    222         mCallRingDelay = SystemProperties.getInt(
    223                 TelephonyProperties.PROPERTY_CALL_RING_DELAY, 3000);
    224         Log.d(LOG_TAG, "mCallRingDelay=" + mCallRingDelay);
    225     }
    226 
    227     public void dispose() {
    228         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
    229             mCM.unSetOnCallRing(this);
    230             mDataConnection.onCleanUpConnection(false, REASON_RADIO_TURNED_OFF);
    231             mIsTheCurrentActivePhone = false;
    232         }
    233     }
    234 
    235     /**
    236      * When overridden the derived class needs to call
    237      * super.handleMessage(msg) so this method has a
    238      * a chance to process the message.
    239      *
    240      * @param msg
    241      */
    242     @Override
    243     public void handleMessage(Message msg) {
    244         AsyncResult ar;
    245 
    246         switch(msg.what) {
    247             case EVENT_CALL_RING:
    248                 Log.d(LOG_TAG, "Event EVENT_CALL_RING Received state=" + getState());
    249                 ar = (AsyncResult)msg.obj;
    250                 if (ar.exception == null) {
    251                     Phone.State state = getState();
    252                     if ((!mDoesRilSendMultipleCallRing)
    253                             && ((state == Phone.State.RINGING) || (state == Phone.State.IDLE))) {
    254                         mCallRingContinueToken += 1;
    255                         sendIncomingCallRingNotification(mCallRingContinueToken);
    256                     } else {
    257                         notifyIncomingRing();
    258                     }
    259                 }
    260                 break;
    261 
    262             case EVENT_CALL_RING_CONTINUE:
    263                 Log.d(LOG_TAG, "Event EVENT_CALL_RING_CONTINUE Received stat=" + getState());
    264                 if (getState() == Phone.State.RINGING) {
    265                     sendIncomingCallRingNotification(msg.arg1);
    266                 }
    267                 break;
    268 
    269             default:
    270                 throw new RuntimeException("unexpected event not handled");
    271         }
    272     }
    273 
    274     // Inherited documentation suffices.
    275     public Context getContext() {
    276         return mContext;
    277     }
    278 
    279     /**
    280      * Disables the DNS check (i.e., allows "0.0.0.0").
    281      * Useful for lab testing environment.
    282      * @param b true disables the check, false enables.
    283      */
    284     public void disableDnsCheck(boolean b) {
    285         mDnsCheckDisabled = b;
    286         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
    287         SharedPreferences.Editor editor = sp.edit();
    288         editor.putBoolean(DNS_SERVER_CHECK_DISABLED_KEY, b);
    289         editor.apply();
    290     }
    291 
    292     /**
    293      * Returns true if the DNS check is currently disabled.
    294      */
    295     public boolean isDnsCheckDisabled() {
    296         return mDnsCheckDisabled;
    297     }
    298 
    299     // Inherited documentation suffices.
    300     public void registerForPreciseCallStateChanged(Handler h, int what, Object obj) {
    301         checkCorrectThread(h);
    302 
    303         mPreciseCallStateRegistrants.addUnique(h, what, obj);
    304     }
    305 
    306     // Inherited documentation suffices.
    307     public void unregisterForPreciseCallStateChanged(Handler h) {
    308         mPreciseCallStateRegistrants.remove(h);
    309     }
    310 
    311     /**
    312      * Subclasses of Phone probably want to replace this with a
    313      * version scoped to their packages
    314      */
    315     protected void notifyPreciseCallStateChangedP() {
    316         AsyncResult ar = new AsyncResult(null, this, null);
    317         mPreciseCallStateRegistrants.notifyRegistrants(ar);
    318     }
    319 
    320     // Inherited documentation suffices.
    321     public void registerForUnknownConnection(Handler h, int what, Object obj) {
    322         checkCorrectThread(h);
    323 
    324         mUnknownConnectionRegistrants.addUnique(h, what, obj);
    325     }
    326 
    327     // Inherited documentation suffices.
    328     public void unregisterForUnknownConnection(Handler h) {
    329         mUnknownConnectionRegistrants.remove(h);
    330     }
    331 
    332     // Inherited documentation suffices.
    333     public void registerForNewRingingConnection(
    334             Handler h, int what, Object obj) {
    335         checkCorrectThread(h);
    336 
    337         mNewRingingConnectionRegistrants.addUnique(h, what, obj);
    338     }
    339 
    340     // Inherited documentation suffices.
    341     public void unregisterForNewRingingConnection(Handler h) {
    342         mNewRingingConnectionRegistrants.remove(h);
    343     }
    344 
    345     // Inherited documentation suffices.
    346     public void registerForInCallVoicePrivacyOn(Handler h, int what, Object obj){
    347         mCM.registerForInCallVoicePrivacyOn(h,what,obj);
    348     }
    349 
    350     // Inherited documentation suffices.
    351     public void unregisterForInCallVoicePrivacyOn(Handler h){
    352         mCM.unregisterForInCallVoicePrivacyOn(h);
    353     }
    354 
    355     // Inherited documentation suffices.
    356     public void registerForInCallVoicePrivacyOff(Handler h, int what, Object obj){
    357         mCM.registerForInCallVoicePrivacyOff(h,what,obj);
    358     }
    359 
    360     // Inherited documentation suffices.
    361     public void unregisterForInCallVoicePrivacyOff(Handler h){
    362         mCM.unregisterForInCallVoicePrivacyOff(h);
    363     }
    364 
    365     // Inherited documentation suffices.
    366     public void registerForIncomingRing(
    367             Handler h, int what, Object obj) {
    368         checkCorrectThread(h);
    369 
    370         mIncomingRingRegistrants.addUnique(h, what, obj);
    371     }
    372 
    373     // Inherited documentation suffices.
    374     public void unregisterForIncomingRing(Handler h) {
    375         mIncomingRingRegistrants.remove(h);
    376     }
    377 
    378     // Inherited documentation suffices.
    379     public void registerForDisconnect(Handler h, int what, Object obj) {
    380         checkCorrectThread(h);
    381 
    382         mDisconnectRegistrants.addUnique(h, what, obj);
    383     }
    384 
    385     // Inherited documentation suffices.
    386     public void unregisterForDisconnect(Handler h) {
    387         mDisconnectRegistrants.remove(h);
    388     }
    389 
    390     // Inherited documentation suffices.
    391     public void registerForSuppServiceFailed(Handler h, int what, Object obj) {
    392         checkCorrectThread(h);
    393 
    394         mSuppServiceFailedRegistrants.addUnique(h, what, obj);
    395     }
    396 
    397     // Inherited documentation suffices.
    398     public void unregisterForSuppServiceFailed(Handler h) {
    399         mSuppServiceFailedRegistrants.remove(h);
    400     }
    401 
    402     // Inherited documentation suffices.
    403     public void registerForMmiInitiate(Handler h, int what, Object obj) {
    404         checkCorrectThread(h);
    405 
    406         mMmiRegistrants.addUnique(h, what, obj);
    407     }
    408 
    409     // Inherited documentation suffices.
    410     public void unregisterForMmiInitiate(Handler h) {
    411         mMmiRegistrants.remove(h);
    412     }
    413 
    414     // Inherited documentation suffices.
    415     public void registerForMmiComplete(Handler h, int what, Object obj) {
    416         checkCorrectThread(h);
    417 
    418         mMmiCompleteRegistrants.addUnique(h, what, obj);
    419     }
    420 
    421     // Inherited documentation suffices.
    422     public void unregisterForMmiComplete(Handler h) {
    423         checkCorrectThread(h);
    424 
    425         mMmiCompleteRegistrants.remove(h);
    426     }
    427 
    428     /**
    429      * Method to retrieve the saved operator id from the Shared Preferences
    430      */
    431     private String getSavedNetworkSelection() {
    432         // open the shared preferences and search with our key.
    433         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
    434         return sp.getString(NETWORK_SELECTION_KEY, "");
    435     }
    436 
    437     /**
    438      * Method to restore the previously saved operator id, or reset to
    439      * automatic selection, all depending upon the value in the shared
    440      * preferences.
    441      */
    442     public void restoreSavedNetworkSelection(Message response) {
    443         // retrieve the operator id
    444         String networkSelection = getSavedNetworkSelection();
    445 
    446         // set to auto if the id is empty, otherwise select the network.
    447         if (TextUtils.isEmpty(networkSelection)) {
    448             mCM.setNetworkSelectionModeAutomatic(response);
    449         } else {
    450             mCM.setNetworkSelectionModeManual(networkSelection, response);
    451         }
    452     }
    453 
    454     // Inherited documentation suffices.
    455     public void setUnitTestMode(boolean f) {
    456         mUnitTestMode = f;
    457     }
    458 
    459     // Inherited documentation suffices.
    460     public boolean getUnitTestMode() {
    461         return mUnitTestMode;
    462     }
    463 
    464     /**
    465      * To be invoked when a voice call Connection disconnects.
    466      *
    467      * Subclasses of Phone probably want to replace this with a
    468      * version scoped to their packages
    469      */
    470     protected void notifyDisconnectP(Connection cn) {
    471         AsyncResult ar = new AsyncResult(null, cn, null);
    472         mDisconnectRegistrants.notifyRegistrants(ar);
    473     }
    474 
    475     // Inherited documentation suffices.
    476     public void registerForServiceStateChanged(
    477             Handler h, int what, Object obj) {
    478         checkCorrectThread(h);
    479 
    480         mServiceStateRegistrants.add(h, what, obj);
    481     }
    482 
    483     // Inherited documentation suffices.
    484     public void unregisterForServiceStateChanged(Handler h) {
    485         mServiceStateRegistrants.remove(h);
    486     }
    487 
    488     // Inherited documentation suffices.
    489     public void registerForRingbackTone(Handler h, int what, Object obj) {
    490         mCM.registerForRingbackTone(h,what,obj);
    491     }
    492 
    493     // Inherited documentation suffices.
    494     public void unregisterForRingbackTone(Handler h) {
    495         mCM.unregisterForRingbackTone(h);
    496     }
    497 
    498     // Inherited documentation suffices.
    499     public void registerForResendIncallMute(Handler h, int what, Object obj) {
    500         mCM.registerForResendIncallMute(h,what,obj);
    501     }
    502 
    503     // Inherited documentation suffices.
    504     public void unregisterForResendIncallMute(Handler h) {
    505         mCM.unregisterForResendIncallMute(h);
    506     }
    507 
    508     public void setEchoSuppressionEnabled(boolean enabled) {
    509         // no need for regular phone
    510     }
    511 
    512     /**
    513      * Subclasses of Phone probably want to replace this with a
    514      * version scoped to their packages
    515      */
    516     protected void notifyServiceStateChangedP(ServiceState ss) {
    517         AsyncResult ar = new AsyncResult(null, ss, null);
    518         mServiceStateRegistrants.notifyRegistrants(ar);
    519 
    520         mNotifier.notifyServiceState(this);
    521     }
    522 
    523     // Inherited documentation suffices.
    524     public SimulatedRadioControl getSimulatedRadioControl() {
    525         return mSimulatedRadioControl;
    526     }
    527 
    528     /**
    529      * Verifies the current thread is the same as the thread originally
    530      * used in the initialization of this instance. Throws RuntimeException
    531      * if not.
    532      *
    533      * @exception RuntimeException if the current thread is not
    534      * the thread that originally obtained this PhoneBase instance.
    535      */
    536     private void checkCorrectThread(Handler h) {
    537         if (h.getLooper() != mLooper) {
    538             throw new RuntimeException(
    539                     "com.android.internal.telephony.Phone must be used from within one thread");
    540         }
    541     }
    542 
    543     /**
    544      * Set the properties by matching the carrier string in
    545      * a string-array resource
    546      */
    547     private void setPropertiesByCarrier() {
    548         String carrier = SystemProperties.get("ro.carrier");
    549 
    550         if (null == carrier || 0 == carrier.length() || "unknown".equals(carrier)) {
    551             return;
    552         }
    553 
    554         CharSequence[] carrierLocales = mContext.
    555                 getResources().getTextArray(R.array.carrier_properties);
    556 
    557         for (int i = 0; i < carrierLocales.length; i+=3) {
    558             String c = carrierLocales[i].toString();
    559             if (carrier.equals(c)) {
    560                 String l = carrierLocales[i+1].toString();
    561                 int wifiChannels = 0;
    562                 try {
    563                     wifiChannels = Integer.parseInt(
    564                             carrierLocales[i+2].toString());
    565                 } catch (NumberFormatException e) { }
    566 
    567                 String language = l.substring(0, 2);
    568                 String country = "";
    569                 if (l.length() >=5) {
    570                     country = l.substring(3, 5);
    571                 }
    572                 setSystemLocale(language, country);
    573 
    574                 if (wifiChannels != 0) {
    575                     try {
    576                         Settings.Secure.getInt(mContext.getContentResolver(),
    577                                 Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS);
    578                     } catch (Settings.SettingNotFoundException e) {
    579                         // note this is not persisting
    580                         WifiManager wM = (WifiManager)
    581                                 mContext.getSystemService(Context.WIFI_SERVICE);
    582                         wM.setNumAllowedChannels(wifiChannels, false);
    583                     }
    584                 }
    585                 return;
    586             }
    587         }
    588     }
    589 
    590     /**
    591      * Utility code to set the system locale if it's not set already
    592      * @param language Two character language code desired
    593      * @param country Two character country code desired
    594      *
    595      *  {@hide}
    596      */
    597     public void setSystemLocale(String language, String country) {
    598         String l = SystemProperties.get("persist.sys.language");
    599         String c = SystemProperties.get("persist.sys.country");
    600 
    601         if (null == language) {
    602             return; // no match possible
    603         }
    604         language = language.toLowerCase();
    605         if (null == country) {
    606             country = "";
    607         }
    608         country = country.toUpperCase();
    609 
    610         if((null == l || 0 == l.length()) && (null == c || 0 == c.length())) {
    611             try {
    612                 // try to find a good match
    613                 String[] locales = mContext.getAssets().getLocales();
    614                 final int N = locales.length;
    615                 String bestMatch = null;
    616                 for(int i = 0; i < N; i++) {
    617                     // only match full (lang + country) locales
    618                     if (locales[i]!=null && locales[i].length() >= 5 &&
    619                             locales[i].substring(0,2).equals(language)) {
    620                         if (locales[i].substring(3,5).equals(country)) {
    621                             bestMatch = locales[i];
    622                             break;
    623                         } else if (null == bestMatch) {
    624                             bestMatch = locales[i];
    625                         }
    626                     }
    627                 }
    628                 if (null != bestMatch) {
    629                     IActivityManager am = ActivityManagerNative.getDefault();
    630                     Configuration config = am.getConfiguration();
    631                     config.locale = new Locale(bestMatch.substring(0,2),
    632                                                bestMatch.substring(3,5));
    633                     config.userSetLocale = true;
    634                     am.updateConfiguration(config);
    635                 }
    636             } catch (Exception e) {
    637                 // Intentionally left blank
    638             }
    639         }
    640     }
    641 
    642     /**
    643      * Get state
    644      */
    645     public abstract Phone.State getState();
    646 
    647     /**
    648      * Retrieves the IccFileHandler of the Phone instance
    649      */
    650     public abstract IccFileHandler getIccFileHandler();
    651 
    652     /*
    653      * Retrieves the Handler of the Phone instance
    654      */
    655     public Handler getHandler() {
    656         return this;
    657     }
    658 
    659     /**
    660      *  Query the status of the CDMA roaming preference
    661      */
    662     public void queryCdmaRoamingPreference(Message response) {
    663         mCM.queryCdmaRoamingPreference(response);
    664     }
    665 
    666     /**
    667      *  Set the status of the CDMA roaming preference
    668      */
    669     public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
    670         mCM.setCdmaRoamingPreference(cdmaRoamingType, response);
    671     }
    672 
    673     /**
    674      *  Set the status of the CDMA subscription mode
    675      */
    676     public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
    677         mCM.setCdmaSubscription(cdmaSubscriptionType, response);
    678     }
    679 
    680     /**
    681      *  Set the preferred Network Type: Global, CDMA only or GSM/UMTS only
    682      */
    683     public void setPreferredNetworkType(int networkType, Message response) {
    684         mCM.setPreferredNetworkType(networkType, response);
    685     }
    686 
    687     public void getPreferredNetworkType(Message response) {
    688         mCM.getPreferredNetworkType(response);
    689     }
    690 
    691     public void getSmscAddress(Message result) {
    692         mCM.getSmscAddress(result);
    693     }
    694 
    695     public void setSmscAddress(String address, Message result) {
    696         mCM.setSmscAddress(address, result);
    697     }
    698 
    699     public void setTTYMode(int ttyMode, Message onComplete) {
    700         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    701         logUnexpectedCdmaMethodCall("setTTYMode");
    702     }
    703 
    704     public void queryTTYMode(Message onComplete) {
    705         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    706         logUnexpectedCdmaMethodCall("queryTTYMode");
    707     }
    708 
    709     public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
    710         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    711         logUnexpectedCdmaMethodCall("enableEnhancedVoicePrivacy");
    712     }
    713 
    714     public void getEnhancedVoicePrivacy(Message onComplete) {
    715         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    716         logUnexpectedCdmaMethodCall("getEnhancedVoicePrivacy");
    717     }
    718 
    719     public void setBandMode(int bandMode, Message response) {
    720         mCM.setBandMode(bandMode, response);
    721     }
    722 
    723     public void queryAvailableBandMode(Message response) {
    724         mCM.queryAvailableBandMode(response);
    725     }
    726 
    727     public void invokeOemRilRequestRaw(byte[] data, Message response) {
    728         mCM.invokeOemRilRequestRaw(data, response);
    729     }
    730 
    731     public void invokeOemRilRequestStrings(String[] strings, Message response) {
    732         mCM.invokeOemRilRequestStrings(strings, response);
    733     }
    734 
    735     public void notifyDataActivity() {
    736         mNotifier.notifyDataActivity(this);
    737     }
    738 
    739     public void notifyMessageWaitingIndicator() {
    740         // This function is added to send the notification to DefaultPhoneNotifier.
    741         mNotifier.notifyMessageWaitingChanged(this);
    742     }
    743 
    744     public void notifyDataConnection(String reason) {
    745         mNotifier.notifyDataConnection(this, reason);
    746     }
    747 
    748     public abstract String getPhoneName();
    749 
    750     public abstract int getPhoneType();
    751 
    752     /** @hide */
    753     public int getVoiceMessageCount(){
    754         return 0;
    755     }
    756 
    757     /**
    758      * Returns the CDMA ERI icon index to display
    759      */
    760     public int getCdmaEriIconIndex() {
    761         logUnexpectedCdmaMethodCall("getCdmaEriIconIndex");
    762         return -1;
    763     }
    764 
    765     /**
    766      * Returns the CDMA ERI icon mode,
    767      * 0 - ON
    768      * 1 - FLASHING
    769      */
    770     public int getCdmaEriIconMode() {
    771         logUnexpectedCdmaMethodCall("getCdmaEriIconMode");
    772         return -1;
    773     }
    774 
    775     /**
    776      * Returns the CDMA ERI text,
    777      */
    778     public String getCdmaEriText() {
    779         logUnexpectedCdmaMethodCall("getCdmaEriText");
    780         return "GSM nw, no ERI";
    781     }
    782 
    783     public String getCdmaMin() {
    784         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    785         logUnexpectedCdmaMethodCall("getCdmaMin");
    786         return null;
    787     }
    788 
    789     public boolean isMinInfoReady() {
    790         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    791         logUnexpectedCdmaMethodCall("isMinInfoReady");
    792         return false;
    793     }
    794 
    795     public String getCdmaPrlVersion(){
    796         //  This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    797         logUnexpectedCdmaMethodCall("getCdmaPrlVersion");
    798         return null;
    799     }
    800 
    801     public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
    802         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    803         logUnexpectedCdmaMethodCall("sendBurstDtmf");
    804     }
    805 
    806     public void exitEmergencyCallbackMode() {
    807         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    808         logUnexpectedCdmaMethodCall("exitEmergencyCallbackMode");
    809     }
    810 
    811     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
    812         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    813         logUnexpectedCdmaMethodCall("registerForCdmaOtaStatusChange");
    814     }
    815 
    816     public void unregisterForCdmaOtaStatusChange(Handler h) {
    817         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    818         logUnexpectedCdmaMethodCall("unregisterForCdmaOtaStatusChange");
    819     }
    820 
    821     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
    822         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    823         logUnexpectedCdmaMethodCall("registerForSubscriptionInfoReady");
    824     }
    825 
    826     public void unregisterForSubscriptionInfoReady(Handler h) {
    827         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    828         logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady");
    829     }
    830 
    831     public  boolean isOtaSpNumber(String dialStr) {
    832         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    833         logUnexpectedCdmaMethodCall("isOtaSpNumber");
    834         return false;
    835     }
    836 
    837     public void registerForCallWaiting(Handler h, int what, Object obj){
    838         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    839         logUnexpectedCdmaMethodCall("registerForCallWaiting");
    840     }
    841 
    842     public void unregisterForCallWaiting(Handler h){
    843         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    844         logUnexpectedCdmaMethodCall("unregisterForCallWaiting");
    845     }
    846 
    847     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
    848         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    849         logUnexpectedCdmaMethodCall("registerForEcmTimerReset");
    850     }
    851 
    852     public void unregisterForEcmTimerReset(Handler h) {
    853         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    854         logUnexpectedCdmaMethodCall("unregisterForEcmTimerReset");
    855     }
    856 
    857     public void registerForSignalInfo(Handler h, int what, Object obj) {
    858         mCM.registerForSignalInfo(h, what, obj);
    859     }
    860 
    861     public void unregisterForSignalInfo(Handler h) {
    862         mCM.unregisterForSignalInfo(h);
    863     }
    864 
    865     public void registerForDisplayInfo(Handler h, int what, Object obj) {
    866         mCM.registerForDisplayInfo(h, what, obj);
    867     }
    868 
    869      public void unregisterForDisplayInfo(Handler h) {
    870          mCM.unregisterForDisplayInfo(h);
    871      }
    872 
    873     public void registerForNumberInfo(Handler h, int what, Object obj) {
    874         mCM.registerForNumberInfo(h, what, obj);
    875     }
    876 
    877     public void unregisterForNumberInfo(Handler h) {
    878         mCM.unregisterForNumberInfo(h);
    879     }
    880 
    881     public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
    882         mCM.registerForRedirectedNumberInfo(h, what, obj);
    883     }
    884 
    885     public void unregisterForRedirectedNumberInfo(Handler h) {
    886         mCM.unregisterForRedirectedNumberInfo(h);
    887     }
    888 
    889     public void registerForLineControlInfo(Handler h, int what, Object obj) {
    890         mCM.registerForLineControlInfo( h, what, obj);
    891     }
    892 
    893     public void unregisterForLineControlInfo(Handler h) {
    894         mCM.unregisterForLineControlInfo(h);
    895     }
    896 
    897     public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
    898         mCM.registerFoT53ClirlInfo(h, what, obj);
    899     }
    900 
    901     public void unregisterForT53ClirInfo(Handler h) {
    902         mCM.unregisterForT53ClirInfo(h);
    903     }
    904 
    905     public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
    906         mCM.registerForT53AudioControlInfo( h, what, obj);
    907     }
    908 
    909     public void unregisterForT53AudioControlInfo(Handler h) {
    910         mCM.unregisterForT53AudioControlInfo(h);
    911     }
    912 
    913      public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
    914          // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    915          logUnexpectedCdmaMethodCall("setOnEcbModeExitResponse");
    916      }
    917 
    918      public void unsetOnEcbModeExitResponse(Handler h){
    919         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    920          logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse");
    921      }
    922 
    923     public String getInterfaceName(String apnType) {
    924         return mDataConnection.getInterfaceName(apnType);
    925     }
    926 
    927     public String getIpAddress(String apnType) {
    928         return mDataConnection.getIpAddress(apnType);
    929     }
    930 
    931     public boolean isDataConnectivityEnabled() {
    932         return mDataConnection.getDataEnabled();
    933     }
    934 
    935     public String getGateway(String apnType) {
    936         return mDataConnection.getGateway(apnType);
    937     }
    938 
    939     public String[] getDnsServers(String apnType) {
    940         return mDataConnection.getDnsServers(apnType);
    941     }
    942 
    943     public String[] getActiveApnTypes() {
    944         return mDataConnection.getActiveApnTypes();
    945     }
    946 
    947     public String getActiveApn() {
    948         return mDataConnection.getActiveApnString();
    949     }
    950 
    951     public int enableApnType(String type) {
    952         return mDataConnection.enableApnType(type);
    953     }
    954 
    955     public int disableApnType(String type) {
    956         return mDataConnection.disableApnType(type);
    957     }
    958 
    959     /**
    960      * simulateDataConnection
    961      *
    962      * simulates various data connection states. This messes with
    963      * DataConnectionTracker's internal states, but doesn't actually change
    964      * the underlying radio connection states.
    965      *
    966      * @param state Phone.DataState enum.
    967      */
    968     public void simulateDataConnection(Phone.DataState state) {
    969         DataConnectionTracker.State dcState;
    970 
    971         switch (state) {
    972             case CONNECTED:
    973                 dcState = DataConnectionTracker.State.CONNECTED;
    974                 break;
    975             case SUSPENDED:
    976                 dcState = DataConnectionTracker.State.CONNECTED;
    977                 break;
    978             case DISCONNECTED:
    979                 dcState = DataConnectionTracker.State.FAILED;
    980                 break;
    981             default:
    982                 dcState = DataConnectionTracker.State.CONNECTING;
    983                 break;
    984         }
    985 
    986         mDataConnection.setState(dcState);
    987         notifyDataConnection(null);
    988     }
    989 
    990     /**
    991      * Notify registrants of a new ringing Connection.
    992      * Subclasses of Phone probably want to replace this with a
    993      * version scoped to their packages
    994      */
    995     protected void notifyNewRingingConnectionP(Connection cn) {
    996         AsyncResult ar = new AsyncResult(null, cn, null);
    997         mNewRingingConnectionRegistrants.notifyRegistrants(ar);
    998     }
    999 
   1000     /**
   1001      * Notify registrants of a RING event.
   1002      */
   1003     private void notifyIncomingRing() {
   1004         AsyncResult ar = new AsyncResult(null, this, null);
   1005         mIncomingRingRegistrants.notifyRegistrants(ar);
   1006     }
   1007 
   1008     /**
   1009      * Send the incoming call Ring notification if conditions are right.
   1010      */
   1011     private void sendIncomingCallRingNotification(int token) {
   1012         if (!mDoesRilSendMultipleCallRing && (token == mCallRingContinueToken)) {
   1013             Log.d(LOG_TAG, "Sending notifyIncomingRing");
   1014             notifyIncomingRing();
   1015             sendMessageDelayed(
   1016                     obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
   1017         } else {
   1018             Log.d(LOG_TAG, "Ignoring ring notification request,"
   1019                     + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
   1020                     + " token=" + token
   1021                     + " mCallRingContinueToken=" + mCallRingContinueToken);
   1022         }
   1023     }
   1024 
   1025     /**
   1026      * Common error logger method for unexpected calls to CDMA-only methods.
   1027      */
   1028     private void logUnexpectedCdmaMethodCall(String name)
   1029     {
   1030         Log.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
   1031                 "called, CDMAPhone inactive.");
   1032     }
   1033 }
   1034