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