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