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.commit();
    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     /**
    509      * Subclasses of Phone probably want to replace this with a
    510      * version scoped to their packages
    511      */
    512     protected void notifyServiceStateChangedP(ServiceState ss) {
    513         AsyncResult ar = new AsyncResult(null, ss, null);
    514         mServiceStateRegistrants.notifyRegistrants(ar);
    515 
    516         mNotifier.notifyServiceState(this);
    517     }
    518 
    519     // Inherited documentation suffices.
    520     public SimulatedRadioControl getSimulatedRadioControl() {
    521         return mSimulatedRadioControl;
    522     }
    523 
    524     /**
    525      * Verifies the current thread is the same as the thread originally
    526      * used in the initialization of this instance. Throws RuntimeException
    527      * if not.
    528      *
    529      * @exception RuntimeException if the current thread is not
    530      * the thread that originally obtained this PhoneBase instance.
    531      */
    532     private void checkCorrectThread(Handler h) {
    533         if (h.getLooper() != mLooper) {
    534             throw new RuntimeException(
    535                     "com.android.internal.telephony.Phone must be used from within one thread");
    536         }
    537     }
    538 
    539     /**
    540      * Set the properties by matching the carrier string in
    541      * a string-array resource
    542      */
    543     private void setPropertiesByCarrier() {
    544         String carrier = SystemProperties.get("ro.carrier");
    545 
    546         if (null == carrier || 0 == carrier.length()) {
    547             return;
    548         }
    549 
    550         CharSequence[] carrierLocales = mContext.
    551                 getResources().getTextArray(R.array.carrier_properties);
    552 
    553         for (int i = 0; i < carrierLocales.length; i+=3) {
    554             String c = carrierLocales[i].toString();
    555             if (carrier.equals(c)) {
    556                 String l = carrierLocales[i+1].toString();
    557                 int wifiChannels = 0;
    558                 try {
    559                     wifiChannels = Integer.parseInt(
    560                             carrierLocales[i+2].toString());
    561                 } catch (NumberFormatException e) { }
    562 
    563                 String language = l.substring(0, 2);
    564                 String country = "";
    565                 if (l.length() >=5) {
    566                     country = l.substring(3, 5);
    567                 }
    568                 setSystemLocale(language, country);
    569 
    570                 if (wifiChannels != 0) {
    571                     try {
    572                         Settings.Secure.getInt(mContext.getContentResolver(),
    573                                 Settings.Secure.WIFI_NUM_ALLOWED_CHANNELS);
    574                     } catch (Settings.SettingNotFoundException e) {
    575                         // note this is not persisting
    576                         WifiManager wM = (WifiManager)
    577                                 mContext.getSystemService(Context.WIFI_SERVICE);
    578                         wM.setNumAllowedChannels(wifiChannels, false);
    579                     }
    580                 }
    581                 return;
    582             }
    583         }
    584     }
    585 
    586     /**
    587      * Utility code to set the system locale if it's not set already
    588      * @param language Two character language code desired
    589      * @param country Two character country code desired
    590      *
    591      *  {@hide}
    592      */
    593     public void setSystemLocale(String language, String country) {
    594         String l = SystemProperties.get("persist.sys.language");
    595         String c = SystemProperties.get("persist.sys.country");
    596 
    597         if (null == language) {
    598             return; // no match possible
    599         }
    600         language = language.toLowerCase();
    601         if (null == country) {
    602             country = "";
    603         }
    604         country = country.toUpperCase();
    605 
    606         if((null == l || 0 == l.length()) && (null == c || 0 == c.length())) {
    607             try {
    608                 // try to find a good match
    609                 String[] locales = mContext.getAssets().getLocales();
    610                 final int N = locales.length;
    611                 String bestMatch = null;
    612                 for(int i = 0; i < N; i++) {
    613                     // only match full (lang + country) locales
    614                     if (locales[i]!=null && locales[i].length() >= 5 &&
    615                             locales[i].substring(0,2).equals(language)) {
    616                         if (locales[i].substring(3,5).equals(country)) {
    617                             bestMatch = locales[i];
    618                             break;
    619                         } else if (null == bestMatch) {
    620                             bestMatch = locales[i];
    621                         }
    622                     }
    623                 }
    624                 if (null != bestMatch) {
    625                     IActivityManager am = ActivityManagerNative.getDefault();
    626                     Configuration config = am.getConfiguration();
    627                     config.locale = new Locale(bestMatch.substring(0,2),
    628                                                bestMatch.substring(3,5));
    629                     config.userSetLocale = true;
    630                     am.updateConfiguration(config);
    631                 }
    632             } catch (Exception e) {
    633                 // Intentionally left blank
    634             }
    635         }
    636     }
    637 
    638     /**
    639      * Get state
    640      */
    641     public abstract Phone.State getState();
    642 
    643     /**
    644      * Retrieves the IccFileHandler of the Phone instance
    645      */
    646     public abstract IccFileHandler getIccFileHandler();
    647 
    648     /*
    649      * Retrieves the Handler of the Phone instance
    650      */
    651     public Handler getHandler() {
    652         return this;
    653     }
    654 
    655     /**
    656      *  Query the status of the CDMA roaming preference
    657      */
    658     public void queryCdmaRoamingPreference(Message response) {
    659         mCM.queryCdmaRoamingPreference(response);
    660     }
    661 
    662     /**
    663      *  Set the status of the CDMA roaming preference
    664      */
    665     public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) {
    666         mCM.setCdmaRoamingPreference(cdmaRoamingType, response);
    667     }
    668 
    669     /**
    670      *  Set the status of the CDMA subscription mode
    671      */
    672     public void setCdmaSubscription(int cdmaSubscriptionType, Message response) {
    673         mCM.setCdmaSubscription(cdmaSubscriptionType, response);
    674     }
    675 
    676     /**
    677      *  Set the preferred Network Type: Global, CDMA only or GSM/UMTS only
    678      */
    679     public void setPreferredNetworkType(int networkType, Message response) {
    680         mCM.setPreferredNetworkType(networkType, response);
    681     }
    682 
    683     public void getPreferredNetworkType(Message response) {
    684         mCM.getPreferredNetworkType(response);
    685     }
    686 
    687     public void getSmscAddress(Message result) {
    688         mCM.getSmscAddress(result);
    689     }
    690 
    691     public void setSmscAddress(String address, Message result) {
    692         mCM.setSmscAddress(address, result);
    693     }
    694 
    695     public void setTTYMode(int ttyMode, Message onComplete) {
    696         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    697         logUnexpectedCdmaMethodCall("setTTYMode");
    698     }
    699 
    700     public void queryTTYMode(Message onComplete) {
    701         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    702         logUnexpectedCdmaMethodCall("queryTTYMode");
    703     }
    704 
    705     public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
    706         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    707         logUnexpectedCdmaMethodCall("enableEnhancedVoicePrivacy");
    708     }
    709 
    710     public void getEnhancedVoicePrivacy(Message onComplete) {
    711         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    712         logUnexpectedCdmaMethodCall("getEnhancedVoicePrivacy");
    713     }
    714 
    715     public void setBandMode(int bandMode, Message response) {
    716         mCM.setBandMode(bandMode, response);
    717     }
    718 
    719     public void queryAvailableBandMode(Message response) {
    720         mCM.queryAvailableBandMode(response);
    721     }
    722 
    723     public void invokeOemRilRequestRaw(byte[] data, Message response) {
    724         mCM.invokeOemRilRequestRaw(data, response);
    725     }
    726 
    727     public void invokeOemRilRequestStrings(String[] strings, Message response) {
    728         mCM.invokeOemRilRequestStrings(strings, response);
    729     }
    730 
    731     public void notifyDataActivity() {
    732         mNotifier.notifyDataActivity(this);
    733     }
    734 
    735     public void notifyMessageWaitingIndicator() {
    736         // This function is added to send the notification to DefaultPhoneNotifier.
    737         mNotifier.notifyMessageWaitingChanged(this);
    738     }
    739 
    740     public void notifyDataConnection(String reason) {
    741         mNotifier.notifyDataConnection(this, reason);
    742     }
    743 
    744     public abstract String getPhoneName();
    745 
    746     public abstract int getPhoneType();
    747 
    748     /** @hide */
    749     public int getVoiceMessageCount(){
    750         return 0;
    751     }
    752 
    753     /**
    754      * Returns the CDMA ERI icon index to display
    755      */
    756     public int getCdmaEriIconIndex() {
    757         logUnexpectedCdmaMethodCall("getCdmaEriIconIndex");
    758         return -1;
    759     }
    760 
    761     /**
    762      * Returns the CDMA ERI icon mode,
    763      * 0 - ON
    764      * 1 - FLASHING
    765      */
    766     public int getCdmaEriIconMode() {
    767         logUnexpectedCdmaMethodCall("getCdmaEriIconMode");
    768         return -1;
    769     }
    770 
    771     /**
    772      * Returns the CDMA ERI text,
    773      */
    774     public String getCdmaEriText() {
    775         logUnexpectedCdmaMethodCall("getCdmaEriText");
    776         return "GSM nw, no ERI";
    777     }
    778 
    779     public String getCdmaMin() {
    780         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    781         logUnexpectedCdmaMethodCall("getCdmaMin");
    782         return null;
    783     }
    784 
    785     public boolean isMinInfoReady() {
    786         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    787         logUnexpectedCdmaMethodCall("isMinInfoReady");
    788         return false;
    789     }
    790 
    791     public String getCdmaPrlVersion(){
    792         //  This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    793         logUnexpectedCdmaMethodCall("getCdmaPrlVersion");
    794         return null;
    795     }
    796 
    797     public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
    798         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    799         logUnexpectedCdmaMethodCall("sendBurstDtmf");
    800     }
    801 
    802     public void exitEmergencyCallbackMode() {
    803         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    804         logUnexpectedCdmaMethodCall("exitEmergencyCallbackMode");
    805     }
    806 
    807     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
    808         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    809         logUnexpectedCdmaMethodCall("registerForCdmaOtaStatusChange");
    810     }
    811 
    812     public void unregisterForCdmaOtaStatusChange(Handler h) {
    813         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    814         logUnexpectedCdmaMethodCall("unregisterForCdmaOtaStatusChange");
    815     }
    816 
    817     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
    818         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    819         logUnexpectedCdmaMethodCall("registerForSubscriptionInfoReady");
    820     }
    821 
    822     public void unregisterForSubscriptionInfoReady(Handler h) {
    823         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    824         logUnexpectedCdmaMethodCall("unregisterForSubscriptionInfoReady");
    825     }
    826 
    827     public  boolean isOtaSpNumber(String dialStr) {
    828         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    829         logUnexpectedCdmaMethodCall("isOtaSpNumber");
    830         return false;
    831     }
    832 
    833     public void registerForCallWaiting(Handler h, int what, Object obj){
    834         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    835         logUnexpectedCdmaMethodCall("registerForCallWaiting");
    836     }
    837 
    838     public void unregisterForCallWaiting(Handler h){
    839         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    840         logUnexpectedCdmaMethodCall("unregisterForCallWaiting");
    841     }
    842 
    843     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
    844         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    845         logUnexpectedCdmaMethodCall("registerForEcmTimerReset");
    846     }
    847 
    848     public void unregisterForEcmTimerReset(Handler h) {
    849         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    850         logUnexpectedCdmaMethodCall("unregisterForEcmTimerReset");
    851     }
    852 
    853     public void registerForSignalInfo(Handler h, int what, Object obj) {
    854         mCM.registerForSignalInfo(h, what, obj);
    855     }
    856 
    857     public void unregisterForSignalInfo(Handler h) {
    858         mCM.unregisterForSignalInfo(h);
    859     }
    860 
    861     public void registerForDisplayInfo(Handler h, int what, Object obj) {
    862         mCM.registerForDisplayInfo(h, what, obj);
    863     }
    864 
    865      public void unregisterForDisplayInfo(Handler h) {
    866          mCM.unregisterForDisplayInfo(h);
    867      }
    868 
    869     public void registerForNumberInfo(Handler h, int what, Object obj) {
    870         mCM.registerForNumberInfo(h, what, obj);
    871     }
    872 
    873     public void unregisterForNumberInfo(Handler h) {
    874         mCM.unregisterForNumberInfo(h);
    875     }
    876 
    877     public void registerForRedirectedNumberInfo(Handler h, int what, Object obj) {
    878         mCM.registerForRedirectedNumberInfo(h, what, obj);
    879     }
    880 
    881     public void unregisterForRedirectedNumberInfo(Handler h) {
    882         mCM.unregisterForRedirectedNumberInfo(h);
    883     }
    884 
    885     public void registerForLineControlInfo(Handler h, int what, Object obj) {
    886         mCM.registerForLineControlInfo( h, what, obj);
    887     }
    888 
    889     public void unregisterForLineControlInfo(Handler h) {
    890         mCM.unregisterForLineControlInfo(h);
    891     }
    892 
    893     public void registerFoT53ClirlInfo(Handler h, int what, Object obj) {
    894         mCM.registerFoT53ClirlInfo(h, what, obj);
    895     }
    896 
    897     public void unregisterForT53ClirInfo(Handler h) {
    898         mCM.unregisterForT53ClirInfo(h);
    899     }
    900 
    901     public void registerForT53AudioControlInfo(Handler h, int what, Object obj) {
    902         mCM.registerForT53AudioControlInfo( h, what, obj);
    903     }
    904 
    905     public void unregisterForT53AudioControlInfo(Handler h) {
    906         mCM.unregisterForT53AudioControlInfo(h);
    907     }
    908 
    909      public void setOnEcbModeExitResponse(Handler h, int what, Object obj){
    910          // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    911          logUnexpectedCdmaMethodCall("setOnEcbModeExitResponse");
    912      }
    913 
    914      public void unsetOnEcbModeExitResponse(Handler h){
    915         // This function should be overridden by the class CDMAPhone. Not implemented in GSMPhone.
    916          logUnexpectedCdmaMethodCall("unsetOnEcbModeExitResponse");
    917      }
    918 
    919     public String getInterfaceName(String apnType) {
    920         return mDataConnection.getInterfaceName(apnType);
    921     }
    922 
    923     public String getIpAddress(String apnType) {
    924         return mDataConnection.getIpAddress(apnType);
    925     }
    926 
    927     public boolean isDataConnectivityEnabled() {
    928         return mDataConnection.getDataEnabled();
    929     }
    930 
    931     public String getGateway(String apnType) {
    932         return mDataConnection.getGateway(apnType);
    933     }
    934 
    935     public String[] getDnsServers(String apnType) {
    936         return mDataConnection.getDnsServers(apnType);
    937     }
    938 
    939     public String[] getActiveApnTypes() {
    940         return mDataConnection.getActiveApnTypes();
    941     }
    942 
    943     public String getActiveApn() {
    944         return mDataConnection.getActiveApnString();
    945     }
    946 
    947     public int enableApnType(String type) {
    948         return mDataConnection.enableApnType(type);
    949     }
    950 
    951     public int disableApnType(String type) {
    952         return mDataConnection.disableApnType(type);
    953     }
    954 
    955     /**
    956      * simulateDataConnection
    957      *
    958      * simulates various data connection states. This messes with
    959      * DataConnectionTracker's internal states, but doesn't actually change
    960      * the underlying radio connection states.
    961      *
    962      * @param state Phone.DataState enum.
    963      */
    964     public void simulateDataConnection(Phone.DataState state) {
    965         DataConnectionTracker.State dcState;
    966 
    967         switch (state) {
    968             case CONNECTED:
    969                 dcState = DataConnectionTracker.State.CONNECTED;
    970                 break;
    971             case SUSPENDED:
    972                 dcState = DataConnectionTracker.State.CONNECTED;
    973                 break;
    974             case DISCONNECTED:
    975                 dcState = DataConnectionTracker.State.FAILED;
    976                 break;
    977             default:
    978                 dcState = DataConnectionTracker.State.CONNECTING;
    979                 break;
    980         }
    981 
    982         mDataConnection.setState(dcState);
    983         notifyDataConnection(null);
    984     }
    985 
    986     /**
    987      * Notify registrants of a new ringing Connection.
    988      * Subclasses of Phone probably want to replace this with a
    989      * version scoped to their packages
    990      */
    991     protected void notifyNewRingingConnectionP(Connection cn) {
    992         AsyncResult ar = new AsyncResult(null, cn, null);
    993         mNewRingingConnectionRegistrants.notifyRegistrants(ar);
    994     }
    995 
    996     /**
    997      * Notify registrants of a RING event.
    998      */
    999     private void notifyIncomingRing() {
   1000         AsyncResult ar = new AsyncResult(null, this, null);
   1001         mIncomingRingRegistrants.notifyRegistrants(ar);
   1002     }
   1003 
   1004     /**
   1005      * Send the incoming call Ring notification if conditions are right.
   1006      */
   1007     private void sendIncomingCallRingNotification(int token) {
   1008         if (!mDoesRilSendMultipleCallRing && (token == mCallRingContinueToken)) {
   1009             Log.d(LOG_TAG, "Sending notifyIncomingRing");
   1010             notifyIncomingRing();
   1011             sendMessageDelayed(
   1012                     obtainMessage(EVENT_CALL_RING_CONTINUE, token, 0), mCallRingDelay);
   1013         } else {
   1014             Log.d(LOG_TAG, "Ignoring ring notification request,"
   1015                     + " mDoesRilSendMultipleCallRing=" + mDoesRilSendMultipleCallRing
   1016                     + " token=" + token
   1017                     + " mCallRingContinueToken=" + mCallRingContinueToken);
   1018         }
   1019     }
   1020 
   1021     /**
   1022      * Common error logger method for unexpected calls to CDMA-only methods.
   1023      */
   1024     private void logUnexpectedCdmaMethodCall(String name)
   1025     {
   1026         Log.e(LOG_TAG, "Error! " + name + "() in PhoneBase should not be " +
   1027                 "called, CDMAPhone inactive.");
   1028     }
   1029 }
   1030