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 
CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId)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 
initSstIcc()152     protected void initSstIcc() {
153         mSST = new CdmaServiceStateTracker(this);
154     }
155 
init(Context context, PhoneNotifier notifier)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
dispose()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
removeReferences()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
finalize()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
getServiceState()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
getCallTracker()290     public CallTracker getCallTracker() {
291         return mCT;
292     }
293 
294     @Override
getState()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
getServiceStateTracker()307     public ServiceStateTracker getServiceStateTracker() {
308         return mSST;
309     }
310 
311     @Override
getPhoneType()312     public int getPhoneType() {
313         return PhoneConstants.PHONE_TYPE_CDMA;
314     }
315 
316     @Override
canTransfer()317     public boolean canTransfer() {
318         Rlog.e(LOG_TAG, "canTransfer: not possible in CDMA");
319         return false;
320     }
321 
322     @Override
getRingingCall()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
setUiTTYMode(int uiTtyMode, Message onComplete)334     public void setUiTTYMode(int uiTtyMode, Message onComplete) {
335        if (mImsPhone != null) {
336            mImsPhone.setUiTTYMode(uiTtyMode, onComplete);
337        }
338     }
339 
340     @Override
setMute(boolean muted)341     public void setMute(boolean muted) {
342         mCT.setMute(muted);
343     }
344 
345     @Override
getMute()346     public boolean getMute() {
347         return mCT.getMute();
348     }
349 
350     @Override
conference()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
enableEnhancedVoicePrivacy(boolean enable, Message onComplete)362     public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
363         mCi.setPreferredVoicePrivacy(enable, onComplete);
364     }
365 
366     @Override
getEnhancedVoicePrivacy(Message onComplete)367     public void getEnhancedVoicePrivacy(Message onComplete) {
368         mCi.getPreferredVoicePrivacy(onComplete);
369     }
370 
371     @Override
clearDisconnected()372     public void clearDisconnected() {
373         mCT.clearDisconnected();
374     }
375 
376     @Override
getDataActivityState()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
dial(String dialString, int videoState)409     dial (String dialString, int videoState) throws CallStateException {
410         return dial(dialString, null, videoState, null);
411     }
412 
413 
414     @Override
415     protected Connection
dialInternal(String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)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
dial(String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)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>
getPendingMmiCodes()485     getPendingMmiCodes() {
486         return mPendingMmis;
487     }
488 
489     @Override
registerForSuppServiceNotification( Handler h, int what, Object obj)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
getBackgroundCall()496     public CdmaCall getBackgroundCall() {
497         return mCT.mBackgroundCall;
498     }
499 
500     @Override
handleInCallMmiCommands(String dialString)501     public boolean handleInCallMmiCommands(String dialString) {
502         Rlog.e(LOG_TAG, "method handleInCallMmiCommands is NOT supported in CDMA!");
503         return false;
504     }
505 
isInCall()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
unregisterForSuppServiceNotification(Handler h)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
acceptCall(int videoState)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
rejectCall()533     rejectCall() throws CallStateException {
534         mCT.rejectCall();
535     }
536 
537     @Override
538     public void
switchHoldingAndActive()539     switchHoldingAndActive() throws CallStateException {
540         mCT.switchWaitingOrHoldingAndActive();
541     }
542 
543     @Override
getIccSerialNumber()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
getLine1Number()554     public String getLine1Number() {
555         return mSST.getMdnNumber();
556     }
557 
558     @Override
getCdmaPrlVersion()559     public String getCdmaPrlVersion(){
560         return mSST.getPrlVersion();
561     }
562 
563     @Override
getCdmaMin()564     public String getCdmaMin() {
565         return mSST.getCdmaMin();
566     }
567 
568     @Override
isMinInfoReady()569     public boolean isMinInfoReady() {
570         return mSST.isMinInfoReady();
571     }
572 
573     @Override
getCallWaiting(Message onComplete)574     public void getCallWaiting(Message onComplete) {
575         mCi.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
576     }
577 
578     @Override
579     public void
setRadioPower(boolean power)580     setRadioPower(boolean power) {
581         mSST.setRadioPower(power);
582     }
583 
584     @Override
getEsn()585     public String getEsn() {
586         return mEsn;
587     }
588 
589     @Override
getMeid()590     public String getMeid() {
591         return mMeid;
592     }
593 
594     @Override
getNai()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
getDeviceId()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
getDeviceSvn()615     public String getDeviceSvn() {
616         Rlog.d(LOG_TAG, "getDeviceSvn(): return 0");
617         return "0";
618     }
619 
620     @Override
getSubscriberId()621     public String getSubscriberId() {
622         return mSST.getImsi();
623     }
624 
625     @Override
getGroupIdLevel1()626     public String getGroupIdLevel1() {
627         Rlog.e(LOG_TAG, "GID1 is not available in CDMA");
628         return null;
629     }
630 
631     @Override
getGroupIdLevel2()632     public String getGroupIdLevel2() {
633         Rlog.e(LOG_TAG, "GID2 is not available in CDMA");
634         return null;
635     }
636 
637     @Override
getImei()638     public String getImei() {
639         Rlog.e(LOG_TAG, "getImei() called for CDMAPhone");
640         return mImei;
641     }
642 
643     @Override
canConference()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
getCellLocation()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
getForegroundCall()671     public CdmaCall getForegroundCall() {
672         return mCT.mForegroundCall;
673     }
674 
675     @Override
setOnPostDialCharacter(Handler h, int what, Object obj)676     public void setOnPostDialCharacter(Handler h, int what, Object obj) {
677         mPostDialHandler = new Registrant(h, what, obj);
678     }
679 
680     @Override
handlePinMmi(String dialString)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      */
onMMIDone(CdmaMmiCode mmi)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
setLine1Number(String alphaTag, String number, final Message onComplete)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
setCallWaiting(boolean enable, Message onComplete)720     public void setCallWaiting(boolean enable, Message onComplete) {
721         Rlog.e(LOG_TAG, "method setCallWaiting is NOT supported in CDMA!");
722     }
723 
724     @Override
updateServiceLocation()725     public void updateServiceLocation() {
726         mSST.enableSingleLocationUpdate();
727     }
728 
729     @Override
setDataRoamingEnabled(boolean enable)730     public void setDataRoamingEnabled(boolean enable) {
731         mDcTracker.setDataOnRoamingEnabled(enable);
732     }
733 
734     @Override
registerForCdmaOtaStatusChange(Handler h, int what, Object obj)735     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
736         mCi.registerForCdmaOtaProvision(h, what, obj);
737     }
738 
739     @Override
unregisterForCdmaOtaStatusChange(Handler h)740     public void unregisterForCdmaOtaStatusChange(Handler h) {
741         mCi.unregisterForCdmaOtaProvision(h);
742     }
743 
744     @Override
registerForSubscriptionInfoReady(Handler h, int what, Object obj)745     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
746         mSST.registerForSubscriptionInfoReady(h, what, obj);
747     }
748 
749     @Override
unregisterForSubscriptionInfoReady(Handler h)750     public void unregisterForSubscriptionInfoReady(Handler h) {
751         mSST.unregisterForSubscriptionInfoReady(h);
752     }
753 
754     @Override
setOnEcbModeExitResponse(Handler h, int what, Object obj)755     public void setOnEcbModeExitResponse(Handler h, int what, Object obj) {
756         mEcmExitRespRegistrant = new Registrant (h, what, obj);
757     }
758 
759     @Override
unsetOnEcbModeExitResponse(Handler h)760     public void unsetOnEcbModeExitResponse(Handler h) {
761         mEcmExitRespRegistrant.clear();
762     }
763 
764     @Override
registerForCallWaiting(Handler h, int what, Object obj)765     public void registerForCallWaiting(Handler h, int what, Object obj) {
766         mCT.registerForCallWaiting(h, what, obj);
767     }
768 
769     @Override
unregisterForCallWaiting(Handler h)770     public void unregisterForCallWaiting(Handler h) {
771         mCT.unregisterForCallWaiting(h);
772     }
773 
774     @Override
775     public void
getNeighboringCids(Message response)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
getDataConnectionState(String apnType)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
sendUssdResponse(String ussdMessge)839     public void sendUssdResponse(String ussdMessge) {
840         Rlog.e(LOG_TAG, "sendUssdResponse: not possible in CDMA");
841     }
842 
843     @Override
sendDtmf(char c)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
startDtmf(char c)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
stopDtmf()866     public void stopDtmf() {
867         mCi.stopDtmf(null);
868     }
869 
870     @Override
sendBurstDtmf(String dtmfString, int on, int off, Message onComplete)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
getAvailableNetworks(Message response)887     public void getAvailableNetworks(Message response) {
888         Rlog.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA");
889     }
890 
891     @Override
setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete)892     public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
893         Rlog.e(LOG_TAG, "setOutgoingCallerIdDisplay: not possible in CDMA");
894     }
895 
896     @Override
enableLocationUpdates()897     public void enableLocationUpdates() {
898         mSST.enableLocationUpdates();
899     }
900 
901     @Override
disableLocationUpdates()902     public void disableLocationUpdates() {
903         mSST.disableLocationUpdates();
904     }
905 
906     @Override
getDataCallList(Message response)907     public void getDataCallList(Message response) {
908         mCi.getDataCallList(response);
909     }
910 
911     @Override
getDataRoamingEnabled()912     public boolean getDataRoamingEnabled() {
913         return mDcTracker.getDataOnRoamingEnabled();
914     }
915 
916     @Override
setDataEnabled(boolean enable)917     public void setDataEnabled(boolean enable) {
918         mDcTracker.setDataEnabled(enable);
919     }
920 
921     @Override
getDataEnabled()922     public boolean getDataEnabled() {
923         return mDcTracker.getDataEnabled();
924     }
925 
926     @Override
setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete)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
getVoiceMailNumber()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
updateVoiceMail()978     private void updateVoiceMail() {
979         setVoiceMessageCount(getStoredVoiceMessageCount());
980     }
981 
982     @Override
getVoiceMailAlphaTag()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
getCallForwardingOption(int commandInterfaceCFReason, Message onComplete)998     public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
999         Rlog.e(LOG_TAG, "getCallForwardingOption: not possible in CDMA");
1000     }
1001 
1002     @Override
setCallForwardingOption(int commandInterfaceCFAction, int commandInterfaceCFReason, String dialingNumber, int timerSeconds, Message onComplete)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
getOutgoingCallerIdDisplay(Message onComplete)1013     getOutgoingCallerIdDisplay(Message onComplete) {
1014         Rlog.e(LOG_TAG, "getOutgoingCallerIdDisplay: not possible in CDMA");
1015     }
1016 
1017     @Override
1018     public boolean
getCallForwardingIndicator()1019     getCallForwardingIndicator() {
1020         Rlog.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA");
1021         return false;
1022     }
1023 
1024     @Override
explicitCallTransfer()1025     public void explicitCallTransfer() {
1026         Rlog.e(LOG_TAG, "explicitCallTransfer: not possible in CDMA");
1027     }
1028 
1029     @Override
getLine1AlphaTag()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      */
notifyPhoneStateChanged()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      */
notifyPreciseCallStateChanged()1048     /*package*/ void notifyPreciseCallStateChanged() {
1049         /* we'd love it if this was package-scoped*/
1050         super.notifyPreciseCallStateChangedP();
1051     }
1052 
notifyServiceStateChanged(ServiceState ss)1053      void notifyServiceStateChanged(ServiceState ss) {
1054          super.notifyServiceStateChangedP(ss);
1055      }
1056 
notifyLocationChanged()1057      void notifyLocationChanged() {
1058          mNotifier.notifyCellLocation(this);
1059      }
1060 
notifyNewRingingConnection(Connection c)1061     public void notifyNewRingingConnection(Connection c) {
1062         super.notifyNewRingingConnectionP(c);
1063     }
1064 
notifyDisconnect(Connection cn)1065     /*package*/ void notifyDisconnect(Connection cn) {
1066         mDisconnectRegistrants.notifyResult(cn);
1067 
1068         mNotifier.notifyDisconnectCause(cn.getDisconnectCause(), cn.getPreciseDisconnectCause());
1069     }
1070 
notifyUnknownConnection(Connection connection)1071     void notifyUnknownConnection(Connection connection) {
1072         mUnknownConnectionRegistrants.notifyResult(connection);
1073     }
1074 
1075     @Override
isInEmergencyCall()1076     public boolean isInEmergencyCall() {
1077         return mCT.isInEmergencyCall();
1078     }
1079 
1080     @Override
isInEcm()1081     public boolean isInEcm() {
1082         return mIsPhoneInEcmState;
1083     }
1084 
sendEmergencyCallbackModeChange()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
exitEmergencyCallbackMode()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 
handleEnterEmergencyCallbackMode(Message msg)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 
handleExitEmergencyCallbackMode(Message msg)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 
notifyEmergencyCallRegistrants(boolean started)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      */
handleTimerInEmergencyCallbackMode(int action)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 
notifyEcbmTimerReset(Boolean flag)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
registerForEcmTimerReset(Handler h, int what, Object obj)1188     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
1189         mEcmTimerResetRegistrants.addUnique(h, what, obj);
1190     }
1191 
1192     @Override
unregisterForEcmTimerReset(Handler h)1193     public void unregisterForEcmTimerReset(Handler h) {
1194         mEcmTimerResetRegistrants.remove(h);
1195     }
1196 
1197     @Override
handleMessage(Message msg)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 
getUiccCardApplication()1339     protected UiccCardApplication getUiccCardApplication() {
1340         return  mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2);
1341     }
1342 
1343     @Override
onUpdateIccAvailability()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      */
handleCdmaSubscriptionSource(int newSubscriptionSource)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
getPhoneSubInfo()1395     public PhoneSubInfo getPhoneSubInfo() {
1396         return mSubInfo;
1397     }
1398 
1399     /**
1400      * Retrieves the IccPhoneBookInterfaceManager of the CDMAPhone
1401      */
1402     @Override
getIccPhoneBookInterfaceManager()1403     public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager() {
1404         return mRuimPhoneBookInterfaceManager;
1405     }
1406 
registerForEriFileLoaded(Handler h, int what, Object obj)1407     public void registerForEriFileLoaded(Handler h, int what, Object obj) {
1408         Registrant r = new Registrant (h, what, obj);
1409         mEriFileLoadedRegistrants.add(r);
1410     }
1411 
unregisterForEriFileLoaded(Handler h)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
setSystemProperty(String property, String value)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
getSystemProperty(String property, String defValue)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
activateCellBroadcastSms(int activate, Message response)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
getCellBroadcastSmsConfig(Message response)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
setCellBroadcastSmsConfig(int[] configValuesArray, Message response)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
needsOtaServiceProvisioning()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 
isIs683OtaSpDialStr(String dialStr)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      */
extractSelCodeFromOtaSpNum(String dialStr)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
checkOtaSpNumBasedOnSysSelCode(int sysSelCodeInt, String sch[])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      */
isCarrierOtaSpNum(String dialStr)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
isOtaSpNumber(String dialStr)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
getCdmaEriIconIndex()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
getCdmaEriIconMode()1674     public int getCdmaEriIconMode() {
1675         return getServiceState().getCdmaEriIconMode();
1676     }
1677 
1678     /**
1679      * Returns the CDMA ERI text,
1680      */
1681     @Override
getCdmaEriText()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      */
storeVoiceMailNumber(String number)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      */
setIsoCountryProperty(String operatorNumeric)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      */
updateCurrentCarrierInProvider(String operatorNumeric)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      */
updateCurrentCarrierInProvider()1758     boolean updateCurrentCarrierInProvider() {
1759         return true;
1760     }
1761 
prepareEri()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 
isEriFileLoaded()1775     public boolean isEriFileLoaded() {
1776         return mEriManager.isEriFileLoaded();
1777     }
1778 
registerForRuimRecordEvents()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 
unregisterForRuimRecordEvents()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
setVoiceMessageWaiting(int line, int countWaiting)1804     public void setVoiceMessageWaiting(int line, int countWaiting) {
1805         setVoiceMessageCount(countWaiting);
1806     }
1807 
log(String s)1808     protected void log(String s) {
1809         if (DBG)
1810             Rlog.d(LOG_TAG, s);
1811     }
1812 
loge(String s, Exception e)1813     protected void loge(String s, Exception e) {
1814         if (DBG)
1815             Rlog.e(LOG_TAG, s, e);
1816     }
1817 
1818     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)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
setOperatorBrandOverride(String brand)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