Home | History | Annotate | Download | only in cdma
      1 /*
      2  * Copyright (C) 2006 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.cdma;
     18 
     19 import android.app.ActivityManagerNative;
     20 import android.content.ContentValues;
     21 import android.content.Context;
     22 import android.content.Intent;
     23 import android.content.SharedPreferences;
     24 import android.database.SQLException;
     25 import android.net.Uri;
     26 import android.os.AsyncResult;
     27 import android.os.Handler;
     28 import android.os.Message;
     29 import android.os.PowerManager;
     30 import android.os.PowerManager.WakeLock;
     31 import android.os.Registrant;
     32 import android.os.RegistrantList;
     33 import android.os.SystemProperties;
     34 import android.os.UserHandle;
     35 import android.preference.PreferenceManager;
     36 import android.provider.Telephony;
     37 import android.telephony.CellLocation;
     38 import android.telephony.PhoneNumberUtils;
     39 import android.telephony.ServiceState;
     40 import android.text.TextUtils;
     41 import android.telephony.Rlog;
     42 
     43 import com.android.internal.telephony.CallStateException;
     44 import com.android.internal.telephony.CallTracker;
     45 import com.android.internal.telephony.CommandException;
     46 import com.android.internal.telephony.CommandsInterface;
     47 import com.android.internal.telephony.Connection;
     48 import com.android.internal.telephony.IccPhoneBookInterfaceManager;
     49 import com.android.internal.telephony.IccSmsInterfaceManager;
     50 import com.android.internal.telephony.MccTable;
     51 import com.android.internal.telephony.MmiCode;
     52 import com.android.internal.telephony.OperatorInfo;
     53 import com.android.internal.telephony.PhoneBase;
     54 import com.android.internal.telephony.PhoneConstants;
     55 import com.android.internal.telephony.PhoneNotifier;
     56 import com.android.internal.telephony.PhoneProxy;
     57 import com.android.internal.telephony.PhoneSubInfo;
     58 import com.android.internal.telephony.ServiceStateTracker;
     59 import com.android.internal.telephony.TelephonyIntents;
     60 import com.android.internal.telephony.TelephonyProperties;
     61 import com.android.internal.telephony.UUSInfo;
     62 import com.android.internal.telephony.dataconnection.DcTracker;
     63 import com.android.internal.telephony.uicc.IccException;
     64 import com.android.internal.telephony.uicc.IccRecords;
     65 import com.android.internal.telephony.uicc.RuimRecords;
     66 import com.android.internal.telephony.uicc.UiccCardApplication;
     67 import com.android.internal.telephony.uicc.UiccController;
     68 import java.io.FileDescriptor;
     69 import java.io.PrintWriter;
     70 import java.util.ArrayList;
     71 import java.util.List;
     72 import java.util.regex.Matcher;
     73 import java.util.regex.Pattern;
     74 
     75 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ALPHA;
     76 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_ISO_COUNTRY;
     77 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_ICC_OPERATOR_NUMERIC;
     78 
     79 /**
     80  * {@hide}
     81  */
     82 public class CDMAPhone extends PhoneBase {
     83     static final String LOG_TAG = "CDMAPhone";
     84     private static final boolean DBG = true;
     85     private static final boolean VDBG = false; /* STOP SHIP if true */
     86 
     87     // Default Emergency Callback Mode exit timer
     88     private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000;
     89 
     90     static final String VM_COUNT_CDMA = "vm_count_key_cdma";
     91     private static final String VM_NUMBER_CDMA = "vm_number_key_cdma";
     92     private String mVmNumber = null;
     93 
     94     static final int RESTART_ECM_TIMER = 0; // restart Ecm timer
     95     static final int CANCEL_ECM_TIMER = 1; // cancel Ecm timer
     96 
     97     // Instance Variables
     98     CdmaCallTracker mCT;
     99     CdmaServiceStateTracker mSST;
    100     CdmaSubscriptionSourceManager mCdmaSSM;
    101     ArrayList <CdmaMmiCode> mPendingMmis = new ArrayList<CdmaMmiCode>();
    102     RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager;
    103     RuimSmsInterfaceManager mRuimSmsInterfaceManager;
    104     int mCdmaSubscriptionSource = CdmaSubscriptionSourceManager.SUBSCRIPTION_SOURCE_UNKNOWN;
    105     PhoneSubInfo mSubInfo;
    106     EriManager mEriManager;
    107     WakeLock mWakeLock;
    108 
    109     // mEriFileLoadedRegistrants are informed after the ERI text has been loaded
    110     private final RegistrantList mEriFileLoadedRegistrants = new RegistrantList();
    111 
    112     // mEcmTimerResetRegistrants are informed after Ecm timer is canceled or re-started
    113     private final RegistrantList mEcmTimerResetRegistrants = new RegistrantList();
    114 
    115     // mEcmExitRespRegistrant is informed after the phone has been exited
    116     //the emergency callback mode
    117     //keep track of if phone is in emergency callback mode
    118     private boolean mIsPhoneInEcmState;
    119     private Registrant mEcmExitRespRegistrant;
    120     protected String mImei;
    121     protected String mImeiSv;
    122     private String mEsn;
    123     private String mMeid;
    124     // string to define how the carrier specifies its own ota sp number
    125     private String mCarrierOtaSpNumSchema;
    126 
    127     // A runnable which is used to automatically exit from Ecm after a period of time.
    128     private Runnable mExitEcmRunnable = new Runnable() {
    129         @Override
    130         public void run() {
    131             exitEmergencyCallbackMode();
    132         }
    133     };
    134 
    135     Registrant mPostDialHandler;
    136 
    137     static String PROPERTY_CDMA_HOME_OPERATOR_NUMERIC = "ro.cdma.home.operator.numeric";
    138 
    139     // Constructors
    140     public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier) {
    141         super("CDMA", notifier, context, ci, false);
    142         initSstIcc();
    143         init(context, notifier);
    144     }
    145 
    146     public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
    147             boolean unitTestMode) {
    148         super("CDMA", notifier, context, ci, unitTestMode);
    149         initSstIcc();
    150         init(context, notifier);
    151     }
    152 
    153     protected void initSstIcc() {
    154         mSST = new CdmaServiceStateTracker(this);
    155     }
    156 
    157     protected void init(Context context, PhoneNotifier notifier) {
    158         mCi.setPhoneType(PhoneConstants.PHONE_TYPE_CDMA);
    159         mCT = new CdmaCallTracker(this);
    160         mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context, mCi, this,
    161                 EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
    162         mSMS = new CdmaSMSDispatcher(this, mSmsStorageMonitor, mSmsUsageMonitor);
    163         mDcTracker = new DcTracker(this);
    164         mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this);
    165         mRuimSmsInterfaceManager = new RuimSmsInterfaceManager(this, mSMS);
    166         mSubInfo = new PhoneSubInfo(this);
    167         mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML);
    168 
    169         mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
    170         mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
    171         mCi.registerForOn(this, EVENT_RADIO_ON, null);
    172         mCi.setOnSuppServiceNotification(this, EVENT_SSN, null);
    173         mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
    174         mCi.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
    175 
    176         PowerManager pm
    177             = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    178         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,LOG_TAG);
    179 
    180         //Change the system setting
    181         SystemProperties.set(TelephonyProperties.CURRENT_ACTIVE_PHONE,
    182                 Integer.toString(PhoneConstants.PHONE_TYPE_CDMA));
    183 
    184         // This is needed to handle phone process crashes
    185         String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false");
    186         mIsPhoneInEcmState = inEcm.equals("true");
    187         if (mIsPhoneInEcmState) {
    188             // Send a message which will invoke handleExitEmergencyCallbackMode
    189             mCi.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
    190         }
    191 
    192         // get the string that specifies the carrier OTA Sp number
    193         mCarrierOtaSpNumSchema = SystemProperties.get(
    194                 TelephonyProperties.PROPERTY_OTASP_NUM_SCHEMA,"");
    195 
    196         // Sets operator alpha property by retrieving from build-time system property
    197         String operatorAlpha = SystemProperties.get("ro.cdma.home.operator.alpha");
    198         setSystemProperty(PROPERTY_ICC_OPERATOR_ALPHA, operatorAlpha);
    199 
    200         // Sets operator numeric property by retrieving from build-time system property
    201         String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC);
    202         log("CDMAPhone: init set 'gsm.sim.operator.numeric' to operator='" +
    203                 operatorNumeric + "'");
    204         setSystemProperty(PROPERTY_ICC_OPERATOR_NUMERIC, operatorNumeric);
    205 
    206         // Sets iso country property by retrieving from build-time system property
    207         setIsoCountryProperty(operatorNumeric);
    208 
    209         // Sets current entry in the telephony carrier table
    210         updateCurrentCarrierInProvider(operatorNumeric);
    211 
    212         // Notify voicemails.
    213         notifier.notifyMessageWaitingChanged(this);
    214     }
    215 
    216     @Override
    217     public void dispose() {
    218         synchronized(PhoneProxy.lockForRadioTechnologyChange) {
    219             super.dispose();
    220             log("dispose");
    221 
    222             //Unregister from all former registered events
    223             unregisterForRuimRecordEvents();
    224             mCi.unregisterForAvailable(this); //EVENT_RADIO_AVAILABLE
    225             mCi.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE
    226             mCi.unregisterForOn(this); //EVENT_RADIO_ON
    227             mSST.unregisterForNetworkAttached(this); //EVENT_REGISTERED_TO_NETWORK
    228             mCi.unSetOnSuppServiceNotification(this);
    229             removeCallbacks(mExitEcmRunnable);
    230 
    231             mPendingMmis.clear();
    232 
    233             //Force all referenced classes to unregister their former registered events
    234             mCT.dispose();
    235             mDcTracker.dispose();
    236             mSST.dispose();
    237             mCdmaSSM.dispose(this);
    238             mSMS.dispose();
    239             mRuimPhoneBookInterfaceManager.dispose();
    240             mRuimSmsInterfaceManager.dispose();
    241             mSubInfo.dispose();
    242             mEriManager.dispose();
    243         }
    244     }
    245 
    246     @Override
    247     public void removeReferences() {
    248         log("removeReferences");
    249         mRuimPhoneBookInterfaceManager = null;
    250         mRuimSmsInterfaceManager = null;
    251         mSubInfo = null;
    252         mCT = null;
    253         mSST = null;
    254         mEriManager = null;
    255         mExitEcmRunnable = null;
    256         super.removeReferences();
    257     }
    258 
    259     @Override
    260     protected void finalize() {
    261         if(DBG) Rlog.d(LOG_TAG, "CDMAPhone finalized");
    262         if (mWakeLock.isHeld()) {
    263             Rlog.e(LOG_TAG, "UNEXPECTED; mWakeLock is held when finalizing.");
    264             mWakeLock.release();
    265         }
    266     }
    267 
    268     @Override
    269     public ServiceState getServiceState() {
    270         return mSST.mSS;
    271     }
    272 
    273     @Override
    274     public CallTracker getCallTracker() {
    275         return mCT;
    276     }
    277 
    278     @Override
    279     public PhoneConstants.State getState() {
    280         return mCT.mState;
    281     }
    282 
    283     @Override
    284     public ServiceStateTracker getServiceStateTracker() {
    285         return mSST;
    286     }
    287 
    288     @Override
    289     public int getPhoneType() {
    290         return PhoneConstants.PHONE_TYPE_CDMA;
    291     }
    292 
    293     @Override
    294     public boolean canTransfer() {
    295         Rlog.e(LOG_TAG, "canTransfer: not possible in CDMA");
    296         return false;
    297     }
    298 
    299     @Override
    300     public CdmaCall getRingingCall() {
    301         return mCT.mRingingCall;
    302     }
    303 
    304     @Override
    305     public void setMute(boolean muted) {
    306         mCT.setMute(muted);
    307     }
    308 
    309     @Override
    310     public boolean getMute() {
    311         return mCT.getMute();
    312     }
    313 
    314     @Override
    315     public void conference() {
    316         // three way calls in CDMA will be handled by feature codes
    317         Rlog.e(LOG_TAG, "conference: not possible in CDMA");
    318     }
    319 
    320     @Override
    321     public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
    322         mCi.setPreferredVoicePrivacy(enable, onComplete);
    323     }
    324 
    325     @Override
    326     public void getEnhancedVoicePrivacy(Message onComplete) {
    327         mCi.getPreferredVoicePrivacy(onComplete);
    328     }
    329 
    330     @Override
    331     public void clearDisconnected() {
    332         mCT.clearDisconnected();
    333     }
    334 
    335     @Override
    336     public DataActivityState getDataActivityState() {
    337         DataActivityState ret = DataActivityState.NONE;
    338 
    339         if (mSST.getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
    340 
    341             switch (mDcTracker.getActivity()) {
    342                 case DATAIN:
    343                     ret = DataActivityState.DATAIN;
    344                 break;
    345 
    346                 case DATAOUT:
    347                     ret = DataActivityState.DATAOUT;
    348                 break;
    349 
    350                 case DATAINANDOUT:
    351                     ret = DataActivityState.DATAINANDOUT;
    352                 break;
    353 
    354                 case DORMANT:
    355                     ret = DataActivityState.DORMANT;
    356                 break;
    357 
    358                 default:
    359                     ret = DataActivityState.NONE;
    360                 break;
    361             }
    362         }
    363         return ret;
    364     }
    365 
    366     @Override
    367     public Connection
    368     dial (String dialString) throws CallStateException {
    369         // Need to make sure dialString gets parsed properly
    370         String newDialString = PhoneNumberUtils.stripSeparators(dialString);
    371         return mCT.dial(newDialString);
    372     }
    373 
    374     @Override
    375     public Connection dial(String dialString, UUSInfo uusInfo) throws CallStateException {
    376         throw new CallStateException("Sending UUS information NOT supported in CDMA!");
    377     }
    378 
    379     @Override
    380     public boolean
    381     getMessageWaitingIndicator() {
    382         return (getVoiceMessageCount() > 0);
    383     }
    384 
    385     @Override
    386     public List<? extends MmiCode>
    387     getPendingMmiCodes() {
    388         return mPendingMmis;
    389     }
    390 
    391     @Override
    392     public void registerForSuppServiceNotification(
    393             Handler h, int what, Object obj) {
    394         Rlog.e(LOG_TAG, "method registerForSuppServiceNotification is NOT supported in CDMA!");
    395     }
    396 
    397     @Override
    398     public CdmaCall getBackgroundCall() {
    399         return mCT.mBackgroundCall;
    400     }
    401 
    402     @Override
    403     public boolean handleInCallMmiCommands(String dialString) {
    404         Rlog.e(LOG_TAG, "method handleInCallMmiCommands is NOT supported in CDMA!");
    405         return false;
    406     }
    407 
    408     boolean isInCall() {
    409         CdmaCall.State foregroundCallState = getForegroundCall().getState();
    410         CdmaCall.State backgroundCallState = getBackgroundCall().getState();
    411         CdmaCall.State ringingCallState = getRingingCall().getState();
    412 
    413         return (foregroundCallState.isAlive() || backgroundCallState.isAlive() || ringingCallState
    414                 .isAlive());
    415     }
    416 
    417     @Override
    418     public void
    419     setNetworkSelectionModeAutomatic(Message response) {
    420         Rlog.e(LOG_TAG, "method setNetworkSelectionModeAutomatic is NOT supported in CDMA!");
    421     }
    422 
    423     @Override
    424     public void unregisterForSuppServiceNotification(Handler h) {
    425         Rlog.e(LOG_TAG, "method unregisterForSuppServiceNotification is NOT supported in CDMA!");
    426     }
    427 
    428     @Override
    429     public void
    430     acceptCall() throws CallStateException {
    431         mCT.acceptCall();
    432     }
    433 
    434     @Override
    435     public void
    436     rejectCall() throws CallStateException {
    437         mCT.rejectCall();
    438     }
    439 
    440     @Override
    441     public void
    442     switchHoldingAndActive() throws CallStateException {
    443         mCT.switchWaitingOrHoldingAndActive();
    444     }
    445 
    446     @Override
    447     public String getLine1Number() {
    448         return mSST.getMdnNumber();
    449     }
    450 
    451     @Override
    452     public String getCdmaPrlVersion(){
    453         return mSST.getPrlVersion();
    454     }
    455 
    456     @Override
    457     public String getCdmaMin() {
    458         return mSST.getCdmaMin();
    459     }
    460 
    461     @Override
    462     public boolean isMinInfoReady() {
    463         return mSST.isMinInfoReady();
    464     }
    465 
    466     @Override
    467     public void getCallWaiting(Message onComplete) {
    468         mCi.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
    469     }
    470 
    471     @Override
    472     public void
    473     setRadioPower(boolean power) {
    474         mSST.setRadioPower(power);
    475     }
    476 
    477     @Override
    478     public String getEsn() {
    479         return mEsn;
    480     }
    481 
    482     @Override
    483     public String getMeid() {
    484         return mMeid;
    485     }
    486 
    487     //returns MEID or ESN in CDMA
    488     @Override
    489     public String getDeviceId() {
    490         String id = getMeid();
    491         if ((id == null) || id.matches("^0*$")) {
    492             Rlog.d(LOG_TAG, "getDeviceId(): MEID is not initialized use ESN");
    493             id = getEsn();
    494         }
    495         return id;
    496     }
    497 
    498     @Override
    499     public String getDeviceSvn() {
    500         Rlog.d(LOG_TAG, "getDeviceSvn(): return 0");
    501         return "0";
    502     }
    503 
    504     @Override
    505     public String getSubscriberId() {
    506         return mSST.getImsi();
    507     }
    508 
    509     @Override
    510     public String getGroupIdLevel1() {
    511         Rlog.e(LOG_TAG, "GID1 is not available in CDMA");
    512         return null;
    513     }
    514 
    515     @Override
    516     public String getImei() {
    517         Rlog.e(LOG_TAG, "IMEI is not available in CDMA");
    518         return null;
    519     }
    520 
    521     @Override
    522     public boolean canConference() {
    523         Rlog.e(LOG_TAG, "canConference: not possible in CDMA");
    524         return false;
    525     }
    526 
    527     @Override
    528     public CellLocation getCellLocation() {
    529         return mSST.mCellLoc;
    530     }
    531 
    532     @Override
    533     public CdmaCall getForegroundCall() {
    534         return mCT.mForegroundCall;
    535     }
    536 
    537     @Override
    538     public void
    539     selectNetworkManually(OperatorInfo network,
    540             Message response) {
    541         Rlog.e(LOG_TAG, "selectNetworkManually: not possible in CDMA");
    542     }
    543 
    544     @Override
    545     public void setOnPostDialCharacter(Handler h, int what, Object obj) {
    546         mPostDialHandler = new Registrant(h, what, obj);
    547     }
    548 
    549     @Override
    550     public boolean handlePinMmi(String dialString) {
    551         CdmaMmiCode mmi = CdmaMmiCode.newFromDialString(dialString, this);
    552 
    553         if (mmi == null) {
    554             Rlog.e(LOG_TAG, "Mmi is NULL!");
    555             return false;
    556         } else if (mmi.isPukCommand()) {
    557             mPendingMmis.add(mmi);
    558             mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
    559             mmi.processCode();
    560             return true;
    561         }
    562         Rlog.e(LOG_TAG, "Unrecognized mmi!");
    563         return false;
    564     }
    565 
    566     /**
    567      * Removes the given MMI from the pending list and notifies registrants that
    568      * it is complete.
    569      *
    570      * @param mmi MMI that is done
    571      */
    572     void onMMIDone(CdmaMmiCode mmi) {
    573         /*
    574          * Only notify complete if it's on the pending list. Otherwise, it's
    575          * already been handled (eg, previously canceled).
    576          */
    577         if (mPendingMmis.remove(mmi)) {
    578             mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
    579         }
    580     }
    581 
    582     @Override
    583     public void setLine1Number(String alphaTag, String number, Message onComplete) {
    584         Rlog.e(LOG_TAG, "setLine1Number: not possible in CDMA");
    585     }
    586 
    587     @Override
    588     public void setCallWaiting(boolean enable, Message onComplete) {
    589         Rlog.e(LOG_TAG, "method setCallWaiting is NOT supported in CDMA!");
    590     }
    591 
    592     @Override
    593     public void updateServiceLocation() {
    594         mSST.enableSingleLocationUpdate();
    595     }
    596 
    597     @Override
    598     public void setDataRoamingEnabled(boolean enable) {
    599         mDcTracker.setDataOnRoamingEnabled(enable);
    600     }
    601 
    602     @Override
    603     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
    604         mCi.registerForCdmaOtaProvision(h, what, obj);
    605     }
    606 
    607     @Override
    608     public void unregisterForCdmaOtaStatusChange(Handler h) {
    609         mCi.unregisterForCdmaOtaProvision(h);
    610     }
    611 
    612     @Override
    613     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
    614         mSST.registerForSubscriptionInfoReady(h, what, obj);
    615     }
    616 
    617     @Override
    618     public void unregisterForSubscriptionInfoReady(Handler h) {
    619         mSST.unregisterForSubscriptionInfoReady(h);
    620     }
    621 
    622     @Override
    623     public void setOnEcbModeExitResponse(Handler h, int what, Object obj) {
    624         mEcmExitRespRegistrant = new Registrant (h, what, obj);
    625     }
    626 
    627     @Override
    628     public void unsetOnEcbModeExitResponse(Handler h) {
    629         mEcmExitRespRegistrant.clear();
    630     }
    631 
    632     @Override
    633     public void registerForCallWaiting(Handler h, int what, Object obj) {
    634         mCT.registerForCallWaiting(h, what, obj);
    635     }
    636 
    637     @Override
    638     public void unregisterForCallWaiting(Handler h) {
    639         mCT.unregisterForCallWaiting(h);
    640     }
    641 
    642     @Override
    643     public void
    644     getNeighboringCids(Message response) {
    645         /*
    646          * This is currently not implemented.  At least as of June
    647          * 2009, there is no neighbor cell information available for
    648          * CDMA because some party is resisting making this
    649          * information readily available.  Consequently, calling this
    650          * function can have no useful effect.  This situation may
    651          * (and hopefully will) change in the future.
    652          */
    653         if (response != null) {
    654             CommandException ce = new CommandException(
    655                     CommandException.Error.REQUEST_NOT_SUPPORTED);
    656             AsyncResult.forMessage(response).exception = ce;
    657             response.sendToTarget();
    658         }
    659     }
    660 
    661     @Override
    662     public PhoneConstants.DataState getDataConnectionState(String apnType) {
    663         PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED;
    664 
    665         if (mSST == null) {
    666              // Radio Technology Change is ongoning, dispose() and removeReferences() have
    667              // already been called
    668 
    669              ret = PhoneConstants.DataState.DISCONNECTED;
    670         } else if (mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
    671             // If we're out of service, open TCP sockets may still work
    672             // but no data will flow
    673             ret = PhoneConstants.DataState.DISCONNECTED;
    674         } else if (mDcTracker.isApnTypeEnabled(apnType) == false ||
    675                 mDcTracker.isApnTypeActive(apnType) == false) {
    676             ret = PhoneConstants.DataState.DISCONNECTED;
    677         } else {
    678             switch (mDcTracker.getState(apnType)) {
    679                 case RETRYING:
    680                 case FAILED:
    681                 case IDLE:
    682                     ret = PhoneConstants.DataState.DISCONNECTED;
    683                 break;
    684 
    685                 case CONNECTED:
    686                 case DISCONNECTING:
    687                     if ( mCT.mState != PhoneConstants.State.IDLE
    688                             && !mSST.isConcurrentVoiceAndDataAllowed()) {
    689                         ret = PhoneConstants.DataState.SUSPENDED;
    690                     } else {
    691                         ret = PhoneConstants.DataState.CONNECTED;
    692                     }
    693                 break;
    694 
    695                 case CONNECTING:
    696                 case SCANNING:
    697                     ret = PhoneConstants.DataState.CONNECTING;
    698                 break;
    699             }
    700         }
    701 
    702         log("getDataConnectionState apnType=" + apnType + " ret=" + ret);
    703         return ret;
    704     }
    705 
    706     @Override
    707     public void sendUssdResponse(String ussdMessge) {
    708         Rlog.e(LOG_TAG, "sendUssdResponse: not possible in CDMA");
    709     }
    710 
    711     @Override
    712     public void sendDtmf(char c) {
    713         if (!PhoneNumberUtils.is12Key(c)) {
    714             Rlog.e(LOG_TAG,
    715                     "sendDtmf called with invalid character '" + c + "'");
    716         } else {
    717             if (mCT.mState ==  PhoneConstants.State.OFFHOOK) {
    718                 mCi.sendDtmf(c, null);
    719             }
    720         }
    721     }
    722 
    723     @Override
    724     public void startDtmf(char c) {
    725         if (!PhoneNumberUtils.is12Key(c)) {
    726             Rlog.e(LOG_TAG,
    727                     "startDtmf called with invalid character '" + c + "'");
    728         } else {
    729             mCi.startDtmf(c, null);
    730         }
    731     }
    732 
    733     @Override
    734     public void stopDtmf() {
    735         mCi.stopDtmf(null);
    736     }
    737 
    738     @Override
    739     public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
    740         boolean check = true;
    741         for (int itr = 0;itr < dtmfString.length(); itr++) {
    742             if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) {
    743                 Rlog.e(LOG_TAG,
    744                         "sendDtmf called with invalid character '" + dtmfString.charAt(itr)+ "'");
    745                 check = false;
    746                 break;
    747             }
    748         }
    749         if ((mCT.mState ==  PhoneConstants.State.OFFHOOK)&&(check)) {
    750             mCi.sendBurstDtmf(dtmfString, on, off, onComplete);
    751         }
    752      }
    753 
    754     @Override
    755     public void getAvailableNetworks(Message response) {
    756         Rlog.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA");
    757     }
    758 
    759     @Override
    760     public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
    761         Rlog.e(LOG_TAG, "setOutgoingCallerIdDisplay: not possible in CDMA");
    762     }
    763 
    764     @Override
    765     public void enableLocationUpdates() {
    766         mSST.enableLocationUpdates();
    767     }
    768 
    769     @Override
    770     public void disableLocationUpdates() {
    771         mSST.disableLocationUpdates();
    772     }
    773 
    774     @Override
    775     public void getDataCallList(Message response) {
    776         mCi.getDataCallList(response);
    777     }
    778 
    779     @Override
    780     public boolean getDataRoamingEnabled() {
    781         return mDcTracker.getDataOnRoamingEnabled();
    782     }
    783 
    784     @Override
    785     public void setVoiceMailNumber(String alphaTag,
    786                                    String voiceMailNumber,
    787                                    Message onComplete) {
    788         Message resp;
    789         mVmNumber = voiceMailNumber;
    790         resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
    791         IccRecords r = mIccRecords.get();
    792         if (r != null) {
    793             r.setVoiceMailNumber(alphaTag, mVmNumber, resp);
    794         }
    795     }
    796 
    797     @Override
    798     public String getVoiceMailNumber() {
    799         String number = null;
    800         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
    801         // TODO: The default value of voicemail number should be read from a system property
    802 
    803         // Read platform settings for dynamic voicemail number
    804         if (getContext().getResources().getBoolean(com.android.internal
    805                 .R.bool.config_telephony_use_own_number_for_voicemail)) {
    806             number = sp.getString(VM_NUMBER_CDMA, getLine1Number());
    807         } else {
    808             number = sp.getString(VM_NUMBER_CDMA, "*86");
    809         }
    810         return number;
    811     }
    812 
    813     /* Returns Number of Voicemails
    814      * @hide
    815      */
    816     @Override
    817     public int getVoiceMessageCount() {
    818         IccRecords r = mIccRecords.get();
    819         int voicemailCount =  (r != null) ? r.getVoiceMessageCount() : 0;
    820         // If mRuimRecords.getVoiceMessageCount returns zero, then there is possibility
    821         // that phone was power cycled and would have lost the voicemail count.
    822         // So get the count from preferences.
    823         if (voicemailCount == 0) {
    824             SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
    825             voicemailCount = sp.getInt(VM_COUNT_CDMA, 0);
    826         }
    827         return voicemailCount;
    828     }
    829 
    830     @Override
    831     public String getVoiceMailAlphaTag() {
    832         // TODO: Where can we get this value has to be clarified with QC.
    833         String ret = "";//TODO: Remove = "", if we know where to get this value.
    834 
    835         //ret = mSIMRecords.getVoiceMailAlphaTag();
    836 
    837         if (ret == null || ret.length() == 0) {
    838             return mContext.getText(
    839                 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString();
    840         }
    841 
    842         return ret;
    843     }
    844 
    845     @Override
    846     public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
    847         Rlog.e(LOG_TAG, "getCallForwardingOption: not possible in CDMA");
    848     }
    849 
    850     @Override
    851     public void setCallForwardingOption(int commandInterfaceCFAction,
    852             int commandInterfaceCFReason,
    853             String dialingNumber,
    854             int timerSeconds,
    855             Message onComplete) {
    856         Rlog.e(LOG_TAG, "setCallForwardingOption: not possible in CDMA");
    857     }
    858 
    859     @Override
    860     public void
    861     getOutgoingCallerIdDisplay(Message onComplete) {
    862         Rlog.e(LOG_TAG, "getOutgoingCallerIdDisplay: not possible in CDMA");
    863     }
    864 
    865     @Override
    866     public boolean
    867     getCallForwardingIndicator() {
    868         Rlog.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA");
    869         return false;
    870     }
    871 
    872     @Override
    873     public void explicitCallTransfer() {
    874         Rlog.e(LOG_TAG, "explicitCallTransfer: not possible in CDMA");
    875     }
    876 
    877     @Override
    878     public String getLine1AlphaTag() {
    879         Rlog.e(LOG_TAG, "getLine1AlphaTag: not possible in CDMA");
    880         return null;
    881     }
    882 
    883     /**
    884      * Notify any interested party of a Phone state change
    885      * {@link com.android.internal.telephony.PhoneConstants.State}
    886      */
    887     /*package*/ void notifyPhoneStateChanged() {
    888         mNotifier.notifyPhoneState(this);
    889     }
    890 
    891     /**
    892      * Notify registrants of a change in the call state. This notifies changes in
    893      * {@link com.android.internal.telephony.Call.State}. Use this when changes
    894      * in the precise call state are needed, else use notifyPhoneStateChanged.
    895      */
    896     /*package*/ void notifyPreciseCallStateChanged() {
    897         /* we'd love it if this was package-scoped*/
    898         super.notifyPreciseCallStateChangedP();
    899     }
    900 
    901      void notifyServiceStateChanged(ServiceState ss) {
    902          super.notifyServiceStateChangedP(ss);
    903      }
    904 
    905      void notifyLocationChanged() {
    906          mNotifier.notifyCellLocation(this);
    907      }
    908 
    909     /*package*/ void notifyNewRingingConnection(Connection c) {
    910         /* we'd love it if this was package-scoped*/
    911         super.notifyNewRingingConnectionP(c);
    912     }
    913 
    914     /*package*/ void notifyDisconnect(Connection cn) {
    915         mDisconnectRegistrants.notifyResult(cn);
    916     }
    917 
    918     void notifyUnknownConnection() {
    919         mUnknownConnectionRegistrants.notifyResult(this);
    920     }
    921 
    922     @Override
    923     public boolean isInEmergencyCall() {
    924         return mCT.isInEmergencyCall();
    925     }
    926 
    927     @Override
    928     public boolean isInEcm() {
    929         return mIsPhoneInEcmState;
    930     }
    931 
    932     void sendEmergencyCallbackModeChange(){
    933         //Send an Intent
    934         Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
    935         intent.putExtra(PhoneConstants.PHONE_IN_ECM_STATE, mIsPhoneInEcmState);
    936         ActivityManagerNative.broadcastStickyIntent(intent,null,UserHandle.USER_ALL);
    937         if (DBG) Rlog.d(LOG_TAG, "sendEmergencyCallbackModeChange");
    938     }
    939 
    940     @Override
    941     public void exitEmergencyCallbackMode() {
    942         if (mWakeLock.isHeld()) {
    943             mWakeLock.release();
    944         }
    945         // Send a message which will invoke handleExitEmergencyCallbackMode
    946         mCi.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
    947     }
    948 
    949     private void handleEnterEmergencyCallbackMode(Message msg) {
    950         if (DBG) {
    951             Rlog.d(LOG_TAG, "handleEnterEmergencyCallbackMode,mIsPhoneInEcmState= "
    952                     + mIsPhoneInEcmState);
    953         }
    954         // if phone is not in Ecm mode, and it's changed to Ecm mode
    955         if (mIsPhoneInEcmState == false) {
    956             mIsPhoneInEcmState = true;
    957             // notify change
    958             sendEmergencyCallbackModeChange();
    959             setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "true");
    960 
    961             // Post this runnable so we will automatically exit
    962             // if no one invokes exitEmergencyCallbackMode() directly.
    963             long delayInMillis = SystemProperties.getLong(
    964                     TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
    965             postDelayed(mExitEcmRunnable, delayInMillis);
    966             // We don't want to go to sleep while in Ecm
    967             mWakeLock.acquire();
    968         }
    969     }
    970 
    971     private void handleExitEmergencyCallbackMode(Message msg) {
    972         AsyncResult ar = (AsyncResult)msg.obj;
    973         if (DBG) {
    974             Rlog.d(LOG_TAG, "handleExitEmergencyCallbackMode,ar.exception , mIsPhoneInEcmState "
    975                     + ar.exception + mIsPhoneInEcmState);
    976         }
    977         // Remove pending exit Ecm runnable, if any
    978         removeCallbacks(mExitEcmRunnable);
    979 
    980         if (mEcmExitRespRegistrant != null) {
    981             mEcmExitRespRegistrant.notifyRegistrant(ar);
    982         }
    983         // if exiting ecm success
    984         if (ar.exception == null) {
    985             if (mIsPhoneInEcmState) {
    986                 mIsPhoneInEcmState = false;
    987                 setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "false");
    988             }
    989             // send an Intent
    990             sendEmergencyCallbackModeChange();
    991             // Re-initiate data connection
    992             mDcTracker.setInternalDataEnabled(true);
    993         }
    994     }
    995 
    996     /**
    997      * Handle to cancel or restart Ecm timer in emergency call back mode
    998      * if action is CANCEL_ECM_TIMER, cancel Ecm timer and notify apps the timer is canceled;
    999      * otherwise, restart Ecm timer and notify apps the timer is restarted.
   1000      */
   1001     void handleTimerInEmergencyCallbackMode(int action) {
   1002         switch(action) {
   1003         case CANCEL_ECM_TIMER:
   1004             removeCallbacks(mExitEcmRunnable);
   1005             mEcmTimerResetRegistrants.notifyResult(Boolean.TRUE);
   1006             break;
   1007         case RESTART_ECM_TIMER:
   1008             long delayInMillis = SystemProperties.getLong(
   1009                     TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
   1010             postDelayed(mExitEcmRunnable, delayInMillis);
   1011             mEcmTimerResetRegistrants.notifyResult(Boolean.FALSE);
   1012             break;
   1013         default:
   1014             Rlog.e(LOG_TAG, "handleTimerInEmergencyCallbackMode, unsupported action " + action);
   1015         }
   1016     }
   1017 
   1018     /**
   1019      * Registration point for Ecm timer reset
   1020      * @param h handler to notify
   1021      * @param what User-defined message code
   1022      * @param obj placed in Message.obj
   1023      */
   1024     @Override
   1025     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
   1026         mEcmTimerResetRegistrants.addUnique(h, what, obj);
   1027     }
   1028 
   1029     @Override
   1030     public void unregisterForEcmTimerReset(Handler h) {
   1031         mEcmTimerResetRegistrants.remove(h);
   1032     }
   1033 
   1034     @Override
   1035     public void handleMessage(Message msg) {
   1036         AsyncResult ar;
   1037         Message     onComplete;
   1038 
   1039         switch(msg.what) {
   1040             case EVENT_RADIO_AVAILABLE: {
   1041                 mCi.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
   1042 
   1043                 mCi.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));
   1044             }
   1045             break;
   1046 
   1047             case EVENT_GET_BASEBAND_VERSION_DONE:{
   1048                 ar = (AsyncResult)msg.obj;
   1049 
   1050                 if (ar.exception != null) {
   1051                     break;
   1052                 }
   1053 
   1054                 if (DBG) Rlog.d(LOG_TAG, "Baseband version: " + ar.result);
   1055                 setSystemProperty(TelephonyProperties.PROPERTY_BASEBAND_VERSION, (String)ar.result);
   1056             }
   1057             break;
   1058 
   1059             case EVENT_GET_DEVICE_IDENTITY_DONE:{
   1060                 ar = (AsyncResult)msg.obj;
   1061 
   1062                 if (ar.exception != null) {
   1063                     break;
   1064                 }
   1065                 String[] respId = (String[])ar.result;
   1066                 mImei = respId[0];
   1067                 mImeiSv = respId[1];
   1068                 mEsn  =  respId[2];
   1069                 mMeid =  respId[3];
   1070             }
   1071             break;
   1072 
   1073             case EVENT_EMERGENCY_CALLBACK_MODE_ENTER:{
   1074                 handleEnterEmergencyCallbackMode(msg);
   1075             }
   1076             break;
   1077 
   1078             case EVENT_ICC_RECORD_EVENTS:
   1079                 ar = (AsyncResult)msg.obj;
   1080                 processIccRecordEvents((Integer)ar.result);
   1081                 break;
   1082 
   1083             case  EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE:{
   1084                 handleExitEmergencyCallbackMode(msg);
   1085             }
   1086             break;
   1087 
   1088             case EVENT_RUIM_RECORDS_LOADED:{
   1089                 Rlog.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received");
   1090                 updateCurrentCarrierInProvider();
   1091             }
   1092             break;
   1093 
   1094             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:{
   1095                 Rlog.d(LOG_TAG, "Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received");
   1096             }
   1097             break;
   1098 
   1099             case EVENT_RADIO_ON:{
   1100                 Rlog.d(LOG_TAG, "Event EVENT_RADIO_ON Received");
   1101                 handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
   1102             }
   1103             break;
   1104 
   1105             case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:{
   1106                 Rlog.d(LOG_TAG, "EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED");
   1107                 handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
   1108             }
   1109             break;
   1110 
   1111             case EVENT_SSN:{
   1112                 Rlog.d(LOG_TAG, "Event EVENT_SSN Received");
   1113             }
   1114             break;
   1115 
   1116             case EVENT_REGISTERED_TO_NETWORK:{
   1117                 Rlog.d(LOG_TAG, "Event EVENT_REGISTERED_TO_NETWORK Received");
   1118             }
   1119             break;
   1120 
   1121             case EVENT_NV_READY:{
   1122                 Rlog.d(LOG_TAG, "Event EVENT_NV_READY Received");
   1123                 prepareEri();
   1124             }
   1125             break;
   1126 
   1127             case EVENT_SET_VM_NUMBER_DONE:{
   1128                 ar = (AsyncResult)msg.obj;
   1129                 if (IccException.class.isInstance(ar.exception)) {
   1130                     storeVoiceMailNumber(mVmNumber);
   1131                     ar.exception = null;
   1132                 }
   1133                 onComplete = (Message) ar.userObj;
   1134                 if (onComplete != null) {
   1135                     AsyncResult.forMessage(onComplete, ar.result, ar.exception);
   1136                     onComplete.sendToTarget();
   1137                 }
   1138             }
   1139             break;
   1140 
   1141             default:{
   1142                 super.handleMessage(msg);
   1143             }
   1144         }
   1145     }
   1146 
   1147     @Override
   1148     protected void onUpdateIccAvailability() {
   1149         if (mUiccController == null ) {
   1150             return;
   1151         }
   1152 
   1153         UiccCardApplication newUiccApplication =
   1154                 mUiccController.getUiccCardApplication(UiccController.APP_FAM_3GPP2);
   1155 
   1156         UiccCardApplication app = mUiccApplication.get();
   1157         if (app != newUiccApplication) {
   1158             if (app != null) {
   1159                 log("Removing stale icc objects.");
   1160                 if (mIccRecords.get() != null) {
   1161                     unregisterForRuimRecordEvents();
   1162                     mRuimPhoneBookInterfaceManager.updateIccRecords(null);
   1163                 }
   1164                 mIccRecords.set(null);
   1165                 mUiccApplication.set(null);
   1166             }
   1167             if (newUiccApplication != null) {
   1168                 log("New Uicc application found");
   1169                 mUiccApplication.set(newUiccApplication);
   1170                 mIccRecords.set(newUiccApplication.getIccRecords());
   1171                 registerForRuimRecordEvents();
   1172                 mRuimPhoneBookInterfaceManager.updateIccRecords(mIccRecords.get());
   1173             }
   1174         }
   1175     }
   1176 
   1177     private void processIccRecordEvents(int eventCode) {
   1178         switch (eventCode) {
   1179             case RuimRecords.EVENT_MWI:
   1180                 notifyMessageWaitingIndicator();
   1181                 break;
   1182 
   1183             default:
   1184                 Rlog.e(LOG_TAG,"Unknown icc records event code " + eventCode);
   1185                 break;
   1186         }
   1187     }
   1188 
   1189     /**
   1190      * Handles the call to get the subscription source
   1191      *
   1192      * @param newSubscriptionSource holds the new CDMA subscription source value
   1193      */
   1194     private void handleCdmaSubscriptionSource(int newSubscriptionSource) {
   1195         if (newSubscriptionSource != mCdmaSubscriptionSource) {
   1196              mCdmaSubscriptionSource = newSubscriptionSource;
   1197              if (newSubscriptionSource == CDMA_SUBSCRIPTION_NV) {
   1198                  // NV is ready when subscription source is NV
   1199                  sendMessage(obtainMessage(EVENT_NV_READY));
   1200              }
   1201         }
   1202     }
   1203 
   1204     /**
   1205      * Retrieves the PhoneSubInfo of the CDMAPhone
   1206      */
   1207     @Override
   1208     public PhoneSubInfo getPhoneSubInfo() {
   1209         return mSubInfo;
   1210     }
   1211 
   1212     /**
   1213      * Retrieves the IccSmsInterfaceManager of the CDMAPhone
   1214      */
   1215     @Override
   1216     public IccSmsInterfaceManager getIccSmsInterfaceManager() {
   1217         return mRuimSmsInterfaceManager;
   1218     }
   1219 
   1220     /**
   1221      * Retrieves the IccPhoneBookInterfaceManager of the CDMAPhone
   1222      */
   1223     @Override
   1224     public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager() {
   1225         return mRuimPhoneBookInterfaceManager;
   1226     }
   1227 
   1228     public void registerForEriFileLoaded(Handler h, int what, Object obj) {
   1229         Registrant r = new Registrant (h, what, obj);
   1230         mEriFileLoadedRegistrants.add(r);
   1231     }
   1232 
   1233     public void unregisterForEriFileLoaded(Handler h) {
   1234         mEriFileLoadedRegistrants.remove(h);
   1235     }
   1236 
   1237     // override for allowing access from other classes of this package
   1238     /**
   1239      * {@inheritDoc}
   1240      */
   1241     @Override
   1242     public final void setSystemProperty(String property, String value) {
   1243         super.setSystemProperty(property, value);
   1244     }
   1245 
   1246     /**
   1247      * Activate or deactivate cell broadcast SMS.
   1248      *
   1249      * @param activate 0 = activate, 1 = deactivate
   1250      * @param response Callback message is empty on completion
   1251      */
   1252     @Override
   1253     public void activateCellBroadcastSms(int activate, Message response) {
   1254         Rlog.e(LOG_TAG, "[CDMAPhone] activateCellBroadcastSms() is obsolete; use SmsManager");
   1255         response.sendToTarget();
   1256     }
   1257 
   1258     /**
   1259      * Query the current configuration of cdma cell broadcast SMS.
   1260      *
   1261      * @param response Callback message is empty on completion
   1262      */
   1263     @Override
   1264     public void getCellBroadcastSmsConfig(Message response) {
   1265         Rlog.e(LOG_TAG, "[CDMAPhone] getCellBroadcastSmsConfig() is obsolete; use SmsManager");
   1266         response.sendToTarget();
   1267     }
   1268 
   1269     /**
   1270      * Configure cdma cell broadcast SMS.
   1271      *
   1272      * @param response Callback message is empty on completion
   1273      */
   1274     @Override
   1275     public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) {
   1276         Rlog.e(LOG_TAG, "[CDMAPhone] setCellBroadcastSmsConfig() is obsolete; use SmsManager");
   1277         response.sendToTarget();
   1278     }
   1279 
   1280     /**
   1281      * Returns true if OTA Service Provisioning needs to be performed.
   1282      */
   1283     @Override
   1284     public boolean needsOtaServiceProvisioning() {
   1285         return mSST.getOtasp() != ServiceStateTracker.OTASP_NOT_NEEDED;
   1286     }
   1287 
   1288     private static final String IS683A_FEATURE_CODE = "*228";
   1289     private static final int IS683A_FEATURE_CODE_NUM_DIGITS = 4;
   1290     private static final int IS683A_SYS_SEL_CODE_NUM_DIGITS = 2;
   1291     private static final int IS683A_SYS_SEL_CODE_OFFSET = 4;
   1292 
   1293     private static final int IS683_CONST_800MHZ_A_BAND = 0;
   1294     private static final int IS683_CONST_800MHZ_B_BAND = 1;
   1295     private static final int IS683_CONST_1900MHZ_A_BLOCK = 2;
   1296     private static final int IS683_CONST_1900MHZ_B_BLOCK = 3;
   1297     private static final int IS683_CONST_1900MHZ_C_BLOCK = 4;
   1298     private static final int IS683_CONST_1900MHZ_D_BLOCK = 5;
   1299     private static final int IS683_CONST_1900MHZ_E_BLOCK = 6;
   1300     private static final int IS683_CONST_1900MHZ_F_BLOCK = 7;
   1301     private static final int INVALID_SYSTEM_SELECTION_CODE = -1;
   1302 
   1303     private static boolean isIs683OtaSpDialStr(String dialStr) {
   1304         int sysSelCodeInt;
   1305         boolean isOtaspDialString = false;
   1306         int dialStrLen = dialStr.length();
   1307 
   1308         if (dialStrLen == IS683A_FEATURE_CODE_NUM_DIGITS) {
   1309             if (dialStr.equals(IS683A_FEATURE_CODE)) {
   1310                 isOtaspDialString = true;
   1311             }
   1312         } else {
   1313             sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr);
   1314             switch (sysSelCodeInt) {
   1315                 case IS683_CONST_800MHZ_A_BAND:
   1316                 case IS683_CONST_800MHZ_B_BAND:
   1317                 case IS683_CONST_1900MHZ_A_BLOCK:
   1318                 case IS683_CONST_1900MHZ_B_BLOCK:
   1319                 case IS683_CONST_1900MHZ_C_BLOCK:
   1320                 case IS683_CONST_1900MHZ_D_BLOCK:
   1321                 case IS683_CONST_1900MHZ_E_BLOCK:
   1322                 case IS683_CONST_1900MHZ_F_BLOCK:
   1323                     isOtaspDialString = true;
   1324                     break;
   1325                 default:
   1326                     break;
   1327             }
   1328         }
   1329         return isOtaspDialString;
   1330     }
   1331     /**
   1332      * This function extracts the system selection code from the dial string.
   1333      */
   1334     private static int extractSelCodeFromOtaSpNum(String dialStr) {
   1335         int dialStrLen = dialStr.length();
   1336         int sysSelCodeInt = INVALID_SYSTEM_SELECTION_CODE;
   1337 
   1338         if ((dialStr.regionMatches(0, IS683A_FEATURE_CODE,
   1339                                    0, IS683A_FEATURE_CODE_NUM_DIGITS)) &&
   1340             (dialStrLen >= (IS683A_FEATURE_CODE_NUM_DIGITS +
   1341                             IS683A_SYS_SEL_CODE_NUM_DIGITS))) {
   1342                 // Since we checked the condition above, the system selection code
   1343                 // extracted from dialStr will not cause any exception
   1344                 sysSelCodeInt = Integer.parseInt (
   1345                                 dialStr.substring (IS683A_FEATURE_CODE_NUM_DIGITS,
   1346                                 IS683A_FEATURE_CODE_NUM_DIGITS + IS683A_SYS_SEL_CODE_NUM_DIGITS));
   1347         }
   1348         if (DBG) Rlog.d(LOG_TAG, "extractSelCodeFromOtaSpNum " + sysSelCodeInt);
   1349         return sysSelCodeInt;
   1350     }
   1351 
   1352     /**
   1353      * This function checks if the system selection code extracted from
   1354      * the dial string "sysSelCodeInt' is the system selection code specified
   1355      * in the carrier ota sp number schema "sch".
   1356      */
   1357     private static boolean
   1358     checkOtaSpNumBasedOnSysSelCode (int sysSelCodeInt, String sch[]) {
   1359         boolean isOtaSpNum = false;
   1360         try {
   1361             // Get how many number of system selection code ranges
   1362             int selRc = Integer.parseInt(sch[1]);
   1363             for (int i = 0; i < selRc; i++) {
   1364                 if (!TextUtils.isEmpty(sch[i+2]) && !TextUtils.isEmpty(sch[i+3])) {
   1365                     int selMin = Integer.parseInt(sch[i+2]);
   1366                     int selMax = Integer.parseInt(sch[i+3]);
   1367                     // Check if the selection code extracted from the dial string falls
   1368                     // within any of the range pairs specified in the schema.
   1369                     if ((sysSelCodeInt >= selMin) && (sysSelCodeInt <= selMax)) {
   1370                         isOtaSpNum = true;
   1371                         break;
   1372                     }
   1373                 }
   1374             }
   1375         } catch (NumberFormatException ex) {
   1376             // If the carrier ota sp number schema is not correct, we still allow dial
   1377             // and only log the error:
   1378             Rlog.e(LOG_TAG, "checkOtaSpNumBasedOnSysSelCode, error", ex);
   1379         }
   1380         return isOtaSpNum;
   1381     }
   1382 
   1383     // Define the pattern/format for carrier specified OTASP number schema.
   1384     // It separates by comma and/or whitespace.
   1385     private static Pattern pOtaSpNumSchema = Pattern.compile("[,\\s]+");
   1386 
   1387     /**
   1388      * The following function checks if a dial string is a carrier specified
   1389      * OTASP number or not by checking against the OTASP number schema stored
   1390      * in PROPERTY_OTASP_NUM_SCHEMA.
   1391      *
   1392      * Currently, there are 2 schemas for carriers to specify the OTASP number:
   1393      * 1) Use system selection code:
   1394      *    The schema is:
   1395      *    SELC,the # of code pairs,min1,max1,min2,max2,...
   1396      *    e.g "SELC,3,10,20,30,40,60,70" indicates that there are 3 pairs of
   1397      *    selection codes, and they are {10,20}, {30,40} and {60,70} respectively.
   1398      *
   1399      * 2) Use feature code:
   1400      *    The schema is:
   1401      *    "FC,length of feature code,feature code".
   1402      *     e.g "FC,2,*2" indicates that the length of the feature code is 2,
   1403      *     and the code itself is "*2".
   1404      */
   1405     private boolean isCarrierOtaSpNum(String dialStr) {
   1406         boolean isOtaSpNum = false;
   1407         int sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr);
   1408         if (sysSelCodeInt == INVALID_SYSTEM_SELECTION_CODE) {
   1409             return isOtaSpNum;
   1410         }
   1411         // mCarrierOtaSpNumSchema is retrieved from PROPERTY_OTASP_NUM_SCHEMA:
   1412         if (!TextUtils.isEmpty(mCarrierOtaSpNumSchema)) {
   1413             Matcher m = pOtaSpNumSchema.matcher(mCarrierOtaSpNumSchema);
   1414             if (DBG) {
   1415                 Rlog.d(LOG_TAG, "isCarrierOtaSpNum,schema" + mCarrierOtaSpNumSchema);
   1416             }
   1417 
   1418             if (m.find()) {
   1419                 String sch[] = pOtaSpNumSchema.split(mCarrierOtaSpNumSchema);
   1420                 // If carrier uses system selection code mechanism
   1421                 if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("SELC")) {
   1422                     if (sysSelCodeInt!=INVALID_SYSTEM_SELECTION_CODE) {
   1423                         isOtaSpNum=checkOtaSpNumBasedOnSysSelCode(sysSelCodeInt,sch);
   1424                     } else {
   1425                         if (DBG) {
   1426                             Rlog.d(LOG_TAG, "isCarrierOtaSpNum,sysSelCodeInt is invalid");
   1427                         }
   1428                     }
   1429                 } else if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("FC")) {
   1430                     int fcLen =  Integer.parseInt(sch[1]);
   1431                     String fc = sch[2];
   1432                     if (dialStr.regionMatches(0,fc,0,fcLen)) {
   1433                         isOtaSpNum = true;
   1434                     } else {
   1435                         if (DBG) Rlog.d(LOG_TAG, "isCarrierOtaSpNum,not otasp number");
   1436                     }
   1437                 } else {
   1438                     if (DBG) {
   1439                         Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema not supported" + sch[0]);
   1440                     }
   1441                 }
   1442             } else {
   1443                 if (DBG) {
   1444                     Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern not right" +
   1445                           mCarrierOtaSpNumSchema);
   1446                 }
   1447             }
   1448         } else {
   1449             if (DBG) Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern empty");
   1450         }
   1451         return isOtaSpNum;
   1452     }
   1453 
   1454     /**
   1455      * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier
   1456      * OTASP dial string.
   1457      *
   1458      * @param dialStr the number to look up.
   1459      * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string
   1460      */
   1461     @Override
   1462     public  boolean isOtaSpNumber(String dialStr){
   1463         boolean isOtaSpNum = false;
   1464         String dialableStr = PhoneNumberUtils.extractNetworkPortionAlt(dialStr);
   1465         if (dialableStr != null) {
   1466             isOtaSpNum = isIs683OtaSpDialStr(dialableStr);
   1467             if (isOtaSpNum == false) {
   1468                 isOtaSpNum = isCarrierOtaSpNum(dialableStr);
   1469             }
   1470         }
   1471         if (DBG) Rlog.d(LOG_TAG, "isOtaSpNumber " + isOtaSpNum);
   1472         return isOtaSpNum;
   1473     }
   1474 
   1475     @Override
   1476     public int getCdmaEriIconIndex() {
   1477         return getServiceState().getCdmaEriIconIndex();
   1478     }
   1479 
   1480     /**
   1481      * Returns the CDMA ERI icon mode,
   1482      * 0 - ON
   1483      * 1 - FLASHING
   1484      */
   1485     @Override
   1486     public int getCdmaEriIconMode() {
   1487         return getServiceState().getCdmaEriIconMode();
   1488     }
   1489 
   1490     /**
   1491      * Returns the CDMA ERI text,
   1492      */
   1493     @Override
   1494     public String getCdmaEriText() {
   1495         int roamInd = getServiceState().getCdmaRoamingIndicator();
   1496         int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
   1497         return mEriManager.getCdmaEriText(roamInd, defRoamInd);
   1498     }
   1499 
   1500     /**
   1501      * Store the voicemail number in preferences
   1502      */
   1503     private void storeVoiceMailNumber(String number) {
   1504         // Update the preference value of voicemail number
   1505         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
   1506         SharedPreferences.Editor editor = sp.edit();
   1507         editor.putString(VM_NUMBER_CDMA, number);
   1508         editor.apply();
   1509     }
   1510 
   1511     /**
   1512      * Sets PROPERTY_ICC_OPERATOR_ISO_COUNTRY property
   1513      *
   1514      */
   1515     private void setIsoCountryProperty(String operatorNumeric) {
   1516         if (TextUtils.isEmpty(operatorNumeric)) {
   1517             setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, "");
   1518         } else {
   1519             String iso = "";
   1520             try {
   1521                 iso = MccTable.countryCodeForMcc(Integer.parseInt(
   1522                         operatorNumeric.substring(0,3)));
   1523             } catch (NumberFormatException ex) {
   1524                 Rlog.w(LOG_TAG, "countryCodeForMcc error" + ex);
   1525             } catch (StringIndexOutOfBoundsException ex) {
   1526                 Rlog.w(LOG_TAG, "countryCodeForMcc error" + ex);
   1527             }
   1528 
   1529             setSystemProperty(PROPERTY_ICC_OPERATOR_ISO_COUNTRY, iso);
   1530         }
   1531     }
   1532 
   1533     /**
   1534      * Sets the "current" field in the telephony provider according to the
   1535      * build-time operator numeric property
   1536      *
   1537      * @return true for success; false otherwise.
   1538      */
   1539     boolean updateCurrentCarrierInProvider(String operatorNumeric) {
   1540         if (!TextUtils.isEmpty(operatorNumeric)) {
   1541             try {
   1542                 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
   1543                 ContentValues map = new ContentValues();
   1544                 map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
   1545                 log("updateCurrentCarrierInProvider from system: numeric=" + operatorNumeric);
   1546                 getContext().getContentResolver().insert(uri, map);
   1547 
   1548                 // Updates MCC MNC device configuration information
   1549                 MccTable.updateMccMncConfiguration(mContext, operatorNumeric);
   1550 
   1551                 return true;
   1552             } catch (SQLException e) {
   1553                 Rlog.e(LOG_TAG, "Can't store current operator", e);
   1554             }
   1555         }
   1556         return false;
   1557     }
   1558 
   1559     /**
   1560      * Sets the "current" field in the telephony provider according to the SIM's operator.
   1561      * Implemented in {@link CDMALTEPhone} for CDMA/LTE devices.
   1562      *
   1563      * @return true for success; false otherwise.
   1564      */
   1565     boolean updateCurrentCarrierInProvider() {
   1566         return true;
   1567     }
   1568 
   1569     public void prepareEri() {
   1570         mEriManager.loadEriFile();
   1571         if(mEriManager.isEriFileLoaded()) {
   1572             // when the ERI file is loaded
   1573             log("ERI read, notify registrants");
   1574             mEriFileLoadedRegistrants.notifyRegistrants();
   1575         }
   1576     }
   1577 
   1578     public boolean isEriFileLoaded() {
   1579         return mEriManager.isEriFileLoaded();
   1580     }
   1581 
   1582     protected void registerForRuimRecordEvents() {
   1583         IccRecords r = mIccRecords.get();
   1584         if (r == null) {
   1585             return;
   1586         }
   1587         r.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null);
   1588         r.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
   1589     }
   1590 
   1591     protected void unregisterForRuimRecordEvents() {
   1592         IccRecords r = mIccRecords.get();
   1593         if (r == null) {
   1594             return;
   1595         }
   1596         r.unregisterForRecordsEvents(this);
   1597         r.unregisterForRecordsLoaded(this);
   1598     }
   1599 
   1600     protected void log(String s) {
   1601         if (DBG)
   1602             Rlog.d(LOG_TAG, s);
   1603     }
   1604 
   1605     @Override
   1606     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1607         pw.println("CDMAPhone extends:");
   1608         super.dump(fd, pw, args);
   1609         pw.println(" mVmNumber=" + mVmNumber);
   1610         pw.println(" mCT=" + mCT);
   1611         pw.println(" mSST=" + mSST);
   1612         pw.println(" mCdmaSSM=" + mCdmaSSM);
   1613         pw.println(" mPendingMmis=" + mPendingMmis);
   1614         pw.println(" mRuimPhoneBookInterfaceManager=" + mRuimPhoneBookInterfaceManager);
   1615         pw.println(" mRuimSmsInterfaceManager=" + mRuimSmsInterfaceManager);
   1616         pw.println(" mCdmaSubscriptionSource=" + mCdmaSubscriptionSource);
   1617         pw.println(" mSubInfo=" + mSubInfo);
   1618         pw.println(" mEriManager=" + mEriManager);
   1619         pw.println(" mWakeLock=" + mWakeLock);
   1620         pw.println(" mIsPhoneInEcmState=" + mIsPhoneInEcmState);
   1621         if (VDBG) pw.println(" mImei=" + mImei);
   1622         if (VDBG) pw.println(" mImeiSv=" + mImeiSv);
   1623         if (VDBG) pw.println(" mEsn=" + mEsn);
   1624         if (VDBG) pw.println(" mMeid=" + mMeid);
   1625         pw.println(" mCarrierOtaSpNumSchema=" + mCarrierOtaSpNumSchema);
   1626         pw.println(" getCdmaEriIconIndex()=" + getCdmaEriIconIndex());
   1627         pw.println(" getCdmaEriIconMode()=" + getCdmaEriIconMode());
   1628         pw.println(" getCdmaEriText()=" + getCdmaEriText());
   1629         pw.println(" isMinInfoReady()=" + isMinInfoReady());
   1630         pw.println(" isCspPlmnEnabled()=" + isCspPlmnEnabled());
   1631     }
   1632 }
   1633