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         mCM.setTTYMode(ttyMode, onComplete);
    701     }
    702 
    703     public void queryTTYMode(Message onComplete) {
    704         mCM.queryTTYMode(onComplete);
    705     }
    706 
    707     public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
    708         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    709         logUnexpectedCdmaMethodCall("enableEnhancedVoicePrivacy");
    710     }
    711 
    712     public void getEnhancedVoicePrivacy(Message onComplete) {
    713         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    714         logUnexpectedCdmaMethodCall("getEnhancedVoicePrivacy");
    715     }
    716 
    717     public void setBandMode(int bandMode, Message response) {
    718         mCM.setBandMode(bandMode, response);
    719     }
    720 
    721     public void queryAvailableBandMode(Message response) {
    722         mCM.queryAvailableBandMode(response);
    723     }
    724 
    725     public void invokeOemRilRequestRaw(byte[] data, Message response) {
    726         mCM.invokeOemRilRequestRaw(data, response);
    727     }
    728 
    729     public void invokeOemRilRequestStrings(String[] strings, Message response) {
    730         mCM.invokeOemRilRequestStrings(strings, response);
    731     }
    732 
    733     public void notifyDataActivity() {
    734         mNotifier.notifyDataActivity(this);
    735     }
    736 
    737     public void notifyMessageWaitingIndicator() {
    738         // This function is added to send the notification to DefaultPhoneNotifier.
    739         mNotifier.notifyMessageWaitingChanged(this);
    740     }
    741 
    742     public void notifyDataConnection(String reason) {
    743         mNotifier.notifyDataConnection(this, reason);
    744     }
    745 
    746     public abstract String getPhoneName();
    747 
    748     public abstract int getPhoneType();
    749 
    750     /** @hide */
    751     public int getVoiceMessageCount(){
    752         return 0;
    753     }
    754 
    755     /**
    756      * Returns the CDMA ERI icon index to display
    757      */
    758     public int getCdmaEriIconIndex() {
    759         logUnexpectedCdmaMethodCall("getCdmaEriIconIndex");
    760         return -1;
    761     }
    762 
    763     /**
    764      * Returns the CDMA ERI icon mode,
    765      * 0 - ON
    766      * 1 - FLASHING
    767      */
    768     public int getCdmaEriIconMode() {
    769         logUnexpectedCdmaMethodCall("getCdmaEriIconMode");
    770         return -1;
    771     }
    772 
    773     /**
    774      * Returns the CDMA ERI text,
    775      */
    776     public String getCdmaEriText() {
    777         logUnexpectedCdmaMethodCall("getCdmaEriText");
    778         return "GSM nw, no ERI";
    779     }
    780 
    781     public String getCdmaMin() {
    782         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    783         logUnexpectedCdmaMethodCall("getCdmaMin");
    784         return null;
    785     }
    786 
    787     public boolean isMinInfoReady() {
    788         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    789         logUnexpectedCdmaMethodCall("isMinInfoReady");
    790         return false;
    791     }
    792 
    793     public String getCdmaPrlVersion(){
    794         //  This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    795         logUnexpectedCdmaMethodCall("getCdmaPrlVersion");
    796         return null;
    797     }
    798 
    799     public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
    800         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    801         logUnexpectedCdmaMethodCall("sendBurstDtmf");
    802     }
    803 
    804     public void exitEmergencyCallbackMode() {
    805         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    806         logUnexpectedCdmaMethodCall("exitEmergencyCallbackMode");
    807     }
    808 
    809     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
    810         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    811         logUnexpectedCdmaMethodCall("registerForCdmaOtaStatusChange");
    812     }
    813 
    814     public void unregisterForCdmaOtaStatusChange(Handler h) {
    815         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    816         logUnexpectedCdmaMethodCall("unregisterForCdmaOtaStatusChange");
    817     }
    818 
    819     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
    820         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    821         logUnexpectedCdmaMethodCall("registerForSubscriptionInfoReady");
    822     }
    823 
    824     public void unregisterForSubscriptionInfoReady(Handler h) {
    825         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    826         logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady");
    827     }
    828 
    829     public  boolean isOtaSpNumber(String dialStr) {
    830         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    831         logUnexpectedCdmaMethodCall("isOtaSpNumber");
    832         return false;
    833     }
    834 
    835     public void registerForCallWaiting(Handler h, int what, Object obj){
    836         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    837         logUnexpectedCdmaMethodCall("registerForCallWaiting");
    838     }
    839 
    840     public void unregisterForCallWaiting(Handler h){
    841         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    842         logUnexpectedCdmaMethodCall("unregisterForCallWaiting");
    843     }
    844 
    845     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
    846         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    847         logUnexpectedCdmaMethodCall("registerForEcmTimerReset");
    848     }
    849 
    850     public void unregisterForEcmTimerReset(Handler h) {
    851         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    852         logUnexpectedCdmaMethodCall("unregisterForEcmTimerReset");
    853     }
    854 
    855     public void registerForSignalInfo(Handler h, int what, Object obj) {
    856         mCM.registerForSignalInfo(h, what, obj);
    857     }
    858 
    859     public void unregisterForSignalInfo(Handler h) {
    860         mCM.unregisterForSignalInfo(h);
    861     }
    862 
    863     public void registerForDisplayInfo(Handler h, int what, Object obj) {
    864         mCM.registerForDisplayInfo(h, what, obj);
    865     }
    866 
    867      public void unregisterForDisplayInfo(Handler h) {
    868          mCM.unregisterForDisplayInfo(h);
    869      }
    870 
    871     public void registerForNumberInfo(Handler h, int what, Object obj) {
    872         mCM.registerForNumberInfo(h, what, obj);
    873     }
    874 
    875     public void unregisterForNumberInfo(Handler h) {
    876         mCM.unregisterForNumberInfo(h);
    877     }
    878 
    879     public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
    880         mCM.registerForRedirectedNumberInfo(h, what, obj);
    881     }
    882 
    883     public void unregisterForRedirectedNumberInfo(Handler h) {
    884         mCM.unregisterForRedirectedNumberInfo(h);
    885     }
    886 
    887     public void registerForLineControlInfo(Handler h, int what, Object obj) {
    888         mCM.registerForLineControlInfo( h, what, obj);
    889     }
    890 
    891     public void unregisterForLineControlInfo(Handler h) {
    892         mCM.unregisterForLineControlInfo(h);
    893     }
    894 
    895     public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
    896         mCM.registerFoT53ClirlInfo(h, what, obj);
    897     }
    898 
    899     public void unregisterForT53ClirInfo(Handler h) {
    900         mCM.unregisterForT53ClirInfo(h);
    901     }
    902 
    903     public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
    904         mCM.registerForT53AudioControlInfo( h, what, obj);
    905     }
    906 
    907     public void unregisterForT53AudioControlInfo(Handler h) {
    908         mCM.unregisterForT53AudioControlInfo(h);
    909     }
    910 
    911      public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
    912          // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    913          logUnexpectedCdmaMethodCall("setOnEcbModeExitResponse");
    914      }
    915 
    916      public void unsetOnEcbModeExitResponse(Handler h){
    917         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    918          logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse");
    919      }
    920 
    921     public String getInterfaceName(String apnType) {
    922         return mDataConnection.getInterfaceName(apnType);
    923     }
    924 
    925     public String getIpAddress(String apnType) {
    926         return mDataConnection.getIpAddress(apnType);
    927     }
    928 
    929     public boolean isDataConnectivityEnabled() {
    930         return mDataConnection.getDataEnabled();
    931     }
    932 
    933     public String getGateway(String apnType) {
    934         return mDataConnection.getGateway(apnType);
    935     }
    936 
    937     public String[] getDnsServers(String apnType) {
    938         return mDataConnection.getDnsServers(apnType);
    939     }
    940 
    941     public String[] getActiveApnTypes() {
    942         return mDataConnection.getActiveApnTypes();
    943     }
    944 
    945     public String getActiveApn() {
    946         return mDataConnection.getActiveApnString();
    947     }
    948 
    949     public int enableApnType(String type) {
    950         return mDataConnection.enableApnType(type);
    951     }
    952 
    953     public int disableApnType(String type) {
    954         return mDataConnection.disableApnType(type);
    955     }
    956 
    957     /**
    958      * simulateDataConnection
    959      *
    960      * simulates various data connection states. This messes with
    961      * DataConnectionTracker's internal states, but doesn't actually change
    962      * the underlying radio connection states.
    963      *
    964      * @param state Phone.DataState enum.
    965      */
    966     public void simulateDataConnection(Phone.DataState state) {
    967         DataConnectionTracker.State dcState;
    968 
    969         switch (state) {
    970             case CONNECTED:
    971                 dcState = DataConnectionTracker.State.CONNECTED;
    972                 break;
    973             case SUSPENDED:
    974                 dcState = DataConnectionTracker.State.CONNECTED;
    975                 break;
    976             case DISCONNECTED:
    977                 dcState = DataConnectionTracker.State.FAILED;
    978                 break;
    979             default:
    980                 dcState = DataConnectionTracker.State.CONNECTING;
    981                 break;
    982         }
    983 
    984         mDataConnection.setState(dcState);
    985         notifyDataConnection(null);
    986     }
    987 
    988     /**
    989      * Notify registrants of a new ringing Connection.
    990      * Subclasses of Phone probably want to replace this with a
    991      * version scoped to their packages
    992      */
    993     protected void notifyNewRingingConnectionP(Connection cn) {
    994         AsyncResult ar = new AsyncResult(null, cn, null);
    995         mNewRingingConnectionRegistrants.notifyRegistrants(ar);
    996     }
    997 
    998     /**
    999      * Notify registrants of a RING event.
   1000      */
   1001     private void notifyIncomingRing() {
   1002         AsyncResult ar = new AsyncResult(null, this, null);
   1003         mIncomingRingRegistrants.notifyRegistrants(ar);
   1004     }
   1005 
   1006     /**
   1007      * Send the incoming call Ring notification if conditions are right.
   1008      */
   1009     private void sendIncomingCallRingNotification(int token) {
   1010         if (!mDoesRilSendMultipleCallRing && (token == mCallRingContinueToken)) {
   1011             Log.d(LOG_TAG, "Sending notifyIncomingRing");
   1012             notifyIncomingRing();
   1013             sendMessageDelayed(
   1014                     obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
   1015         } else {
   1016             Log.d(LOG_TAG, "Ignoring ring notification request,"
   1017                     + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
   1018                     + " token=" + token
   1019                     + " mCallRingContinueToken=" + mCallRingContinueToken);
   1020         }
   1021     }
   1022 
   1023     /**
   1024      * Common error logger method for unexpected calls to CDMA-only methods.
   1025      */
   1026     private void logUnexpectedCdmaMethodCall(String name)
   1027     {
   1028         Log.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
   1029                 "called, CDMAPhone inactive.");
   1030     }
   1031 }
   1032