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