• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 import android.util.Log;
46 
47 import android.telephony.TelephonyManager;
48 
49 import com.android.ims.ImsManager;
50 import com.android.internal.telephony.Call;
51 import com.android.internal.telephony.CallStateException;
52 import com.android.internal.telephony.CallTracker;
53 import com.android.internal.telephony.CommandException;
54 import com.android.internal.telephony.CommandsInterface;
55 import com.android.internal.telephony.Connection;
56 import com.android.internal.telephony.IccPhoneBookInterfaceManager;
57 import com.android.internal.telephony.MccTable;
58 import com.android.internal.telephony.MmiCode;
59 import com.android.internal.telephony.PhoneBase;
60 import com.android.internal.telephony.PhoneConstants;
61 import com.android.internal.telephony.PhoneNotifier;
62 import com.android.internal.telephony.PhoneProxy;
63 import com.android.internal.telephony.PhoneSubInfo;
64 import com.android.internal.telephony.ServiceStateTracker;
65 import com.android.internal.telephony.SubscriptionController;
66 import com.android.internal.telephony.TelephonyIntents;
67 import com.android.internal.telephony.TelephonyProperties;
68 import com.android.internal.telephony.UUSInfo;
69 import com.android.internal.telephony.dataconnection.DcTracker;
70 import com.android.internal.telephony.imsphone.ImsPhone;
71 import com.android.internal.telephony.uicc.IccException;
72 import com.android.internal.telephony.uicc.IccRecords;
73 import com.android.internal.telephony.uicc.RuimRecords;
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         ImsPhone imsPhone = mImsPhone;
411 
412         boolean imsUseEnabled =
413                 ImsManager.isVolteEnabledByPlatform(mContext) &&
414                 ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mContext) &&
415                 ImsManager.isNonTtyOrTtyOnVolteEnabled(mContext);
416         if (!imsUseEnabled) {
417             Rlog.w(LOG_TAG, "IMS is disabled: forced to CS");
418         }
419 
420         if (DBG) {
421             Rlog.d(LOG_TAG, "imsUseEnabled=" + imsUseEnabled + ", imsPhone=" + imsPhone
422                     + ", imsPhone.isVolteEnabled()="
423                     + ((imsPhone != null) ? imsPhone.isVolteEnabled() : "N/A")
424                     + ", imsPhone.getServiceState().getState()="
425                     + ((imsPhone != null) ? imsPhone.getServiceState().getState() : "N/A"));
426         }
427 
428         if (imsUseEnabled && imsPhone != null && imsPhone.isVolteEnabled()
429                 && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE
430                 && !PhoneNumberUtils.isEmergencyNumber(dialString))
431                 || (PhoneNumberUtils.isEmergencyNumber(dialString)
432                 && mContext.getResources().getBoolean(
433                         com.android.internal.R.bool.useImsAlwaysForEmergencyCall))) ) {
434             try {
435                 if (DBG) Rlog.d(LOG_TAG, "Trying IMS PS call");
436                 return imsPhone.dial(dialString, videoState);
437             } catch (CallStateException e) {
438                 if (DBG) Rlog.d(LOG_TAG, "IMS PS call exception " + e +
439                         "imsUseEnabled =" + imsUseEnabled + ", imsPhone =" + imsPhone);
440                 if (!ImsPhone.CS_FALLBACK.equals(e.getMessage())) {
441                     CallStateException ce = new CallStateException(e.getMessage());
442                     ce.setStackTrace(e.getStackTrace());
443                     throw ce;
444                 }
445             }
446         }
447 
448         if (DBG) Rlog.d(LOG_TAG, "Trying (non-IMS) CS call");
449         return dialInternal(dialString, null, videoState);
450     }
451 
452 
453     @Override
454     protected Connection
dialInternal(String dialString, UUSInfo uusInfo, int videoState)455     dialInternal (String dialString, UUSInfo uusInfo,
456             int videoState) throws CallStateException {
457         // Need to make sure dialString gets parsed properly
458         String newDialString = PhoneNumberUtils.stripSeparators(dialString);
459         return mCT.dial(newDialString);
460     }
461 
462     @Override
dial(String dialString, UUSInfo uusInfo, int videoState)463     public Connection dial(String dialString, UUSInfo uusInfo, int videoState)
464             throws CallStateException {
465         throw new CallStateException("Sending UUS information NOT supported in CDMA!");
466     }
467 
468     @Override
469     public List<? extends MmiCode>
getPendingMmiCodes()470     getPendingMmiCodes() {
471         return mPendingMmis;
472     }
473 
474     @Override
registerForSuppServiceNotification( Handler h, int what, Object obj)475     public void registerForSuppServiceNotification(
476             Handler h, int what, Object obj) {
477         Rlog.e(LOG_TAG, "method registerForSuppServiceNotification is NOT supported in CDMA!");
478     }
479 
480     @Override
getBackgroundCall()481     public CdmaCall getBackgroundCall() {
482         return mCT.mBackgroundCall;
483     }
484 
485     @Override
handleInCallMmiCommands(String dialString)486     public boolean handleInCallMmiCommands(String dialString) {
487         Rlog.e(LOG_TAG, "method handleInCallMmiCommands is NOT supported in CDMA!");
488         return false;
489     }
490 
isInCall()491     boolean isInCall() {
492         CdmaCall.State foregroundCallState = getForegroundCall().getState();
493         CdmaCall.State backgroundCallState = getBackgroundCall().getState();
494         CdmaCall.State ringingCallState = getRingingCall().getState();
495 
496         return (foregroundCallState.isAlive() || backgroundCallState.isAlive() || ringingCallState
497                 .isAlive());
498     }
499 
500     @Override
unregisterForSuppServiceNotification(Handler h)501     public void unregisterForSuppServiceNotification(Handler h) {
502         Rlog.e(LOG_TAG, "method unregisterForSuppServiceNotification is NOT supported in CDMA!");
503     }
504 
505     @Override
506     public void
acceptCall(int videoState)507     acceptCall(int videoState) throws CallStateException {
508         ImsPhone imsPhone = mImsPhone;
509         if ( imsPhone != null && imsPhone.getRingingCall().isRinging() ) {
510             imsPhone.acceptCall(videoState);
511         } else {
512             mCT.acceptCall();
513         }
514     }
515 
516     @Override
517     public void
rejectCall()518     rejectCall() throws CallStateException {
519         mCT.rejectCall();
520     }
521 
522     @Override
523     public void
switchHoldingAndActive()524     switchHoldingAndActive() throws CallStateException {
525         mCT.switchWaitingOrHoldingAndActive();
526     }
527 
528     @Override
getIccSerialNumber()529     public String getIccSerialNumber() {
530         IccRecords r = mIccRecords.get();
531         if (r == null) {
532             // to get ICCID form SIMRecords because it is on MF.
533             r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP);
534         }
535         return (r != null) ? r.getIccId() : null;
536     }
537 
538     @Override
getLine1Number()539     public String getLine1Number() {
540         return mSST.getMdnNumber();
541     }
542 
543     @Override
getCdmaPrlVersion()544     public String getCdmaPrlVersion(){
545         return mSST.getPrlVersion();
546     }
547 
548     @Override
getCdmaMin()549     public String getCdmaMin() {
550         return mSST.getCdmaMin();
551     }
552 
553     @Override
isMinInfoReady()554     public boolean isMinInfoReady() {
555         return mSST.isMinInfoReady();
556     }
557 
558     @Override
getCallWaiting(Message onComplete)559     public void getCallWaiting(Message onComplete) {
560         mCi.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
561     }
562 
563     @Override
564     public void
setRadioPower(boolean power)565     setRadioPower(boolean power) {
566         mSST.setRadioPower(power);
567     }
568 
569     @Override
getEsn()570     public String getEsn() {
571         return mEsn;
572     }
573 
574     @Override
getMeid()575     public String getMeid() {
576         return mMeid;
577     }
578 
579     @Override
getNai()580     public String getNai() {
581         IccRecords r = mIccRecords.get();
582         if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
583             Rlog.v(LOG_TAG, "IccRecords is " + r);
584         }
585         return (r != null) ? r.getNAI() : null;
586     }
587 
588     //returns MEID or ESN in CDMA
589     @Override
getDeviceId()590     public String getDeviceId() {
591         String id = getMeid();
592         if ((id == null) || id.matches("^0*$")) {
593             Rlog.d(LOG_TAG, "getDeviceId(): MEID is not initialized use ESN");
594             id = getEsn();
595         }
596         return id;
597     }
598 
599     @Override
getDeviceSvn()600     public String getDeviceSvn() {
601         Rlog.d(LOG_TAG, "getDeviceSvn(): return 0");
602         return "0";
603     }
604 
605     @Override
getSubscriberId()606     public String getSubscriberId() {
607         return mSST.getImsi();
608     }
609 
610     @Override
getGroupIdLevel1()611     public String getGroupIdLevel1() {
612         Rlog.e(LOG_TAG, "GID1 is not available in CDMA");
613         return null;
614     }
615 
616     @Override
getImei()617     public String getImei() {
618         Rlog.e(LOG_TAG, "getImei() called for CDMAPhone");
619         return mImei;
620     }
621 
622     @Override
canConference()623     public boolean canConference() {
624         if (mImsPhone != null && mImsPhone.canConference()) {
625             return true;
626         }
627         Rlog.e(LOG_TAG, "canConference: not possible in CDMA");
628         return false;
629     }
630 
631     @Override
getCellLocation()632     public CellLocation getCellLocation() {
633         CdmaCellLocation loc = mSST.mCellLoc;
634 
635         int mode = Settings.Secure.getInt(getContext().getContentResolver(),
636                 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
637         if (mode == Settings.Secure.LOCATION_MODE_OFF) {
638             // clear lat/long values for location privacy
639             CdmaCellLocation privateLoc = new CdmaCellLocation();
640             privateLoc.setCellLocationData(loc.getBaseStationId(),
641                     CdmaCellLocation.INVALID_LAT_LONG,
642                     CdmaCellLocation.INVALID_LAT_LONG,
643                     loc.getSystemId(), loc.getNetworkId());
644             loc = privateLoc;
645         }
646         return loc;
647     }
648 
649     @Override
getForegroundCall()650     public CdmaCall getForegroundCall() {
651         return mCT.mForegroundCall;
652     }
653 
654     @Override
setOnPostDialCharacter(Handler h, int what, Object obj)655     public void setOnPostDialCharacter(Handler h, int what, Object obj) {
656         mPostDialHandler = new Registrant(h, what, obj);
657     }
658 
659     @Override
handlePinMmi(String dialString)660     public boolean handlePinMmi(String dialString) {
661         CdmaMmiCode mmi = CdmaMmiCode.newFromDialString(dialString, this, mUiccApplication.get());
662 
663         if (mmi == null) {
664             Rlog.e(LOG_TAG, "Mmi is NULL!");
665             return false;
666         } else if (mmi.isPinPukCommand()) {
667             mPendingMmis.add(mmi);
668             mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
669             mmi.processCode();
670             return true;
671         }
672         Rlog.e(LOG_TAG, "Unrecognized mmi!");
673         return false;
674     }
675 
676     /**
677      * Removes the given MMI from the pending list and notifies registrants that
678      * it is complete.
679      *
680      * @param mmi MMI that is done
681      */
onMMIDone(CdmaMmiCode mmi)682     void onMMIDone(CdmaMmiCode mmi) {
683         /*
684          * Only notify complete if it's on the pending list. Otherwise, it's
685          * already been handled (eg, previously canceled).
686          */
687         if (mPendingMmis.remove(mmi)) {
688             mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
689         }
690     }
691 
692     @Override
setLine1Number(String alphaTag, String number, final Message onComplete)693     public boolean setLine1Number(String alphaTag, String number, final Message onComplete) {
694         Rlog.e(LOG_TAG, "setLine1Number: not possible in CDMA");
695         return false;
696     }
697 
698     @Override
setCallWaiting(boolean enable, Message onComplete)699     public void setCallWaiting(boolean enable, Message onComplete) {
700         Rlog.e(LOG_TAG, "method setCallWaiting is NOT supported in CDMA!");
701     }
702 
703     @Override
updateServiceLocation()704     public void updateServiceLocation() {
705         mSST.enableSingleLocationUpdate();
706     }
707 
708     @Override
setDataRoamingEnabled(boolean enable)709     public void setDataRoamingEnabled(boolean enable) {
710         mDcTracker.setDataOnRoamingEnabled(enable);
711     }
712 
713     @Override
registerForCdmaOtaStatusChange(Handler h, int what, Object obj)714     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
715         mCi.registerForCdmaOtaProvision(h, what, obj);
716     }
717 
718     @Override
unregisterForCdmaOtaStatusChange(Handler h)719     public void unregisterForCdmaOtaStatusChange(Handler h) {
720         mCi.unregisterForCdmaOtaProvision(h);
721     }
722 
723     @Override
registerForSubscriptionInfoReady(Handler h, int what, Object obj)724     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
725         mSST.registerForSubscriptionInfoReady(h, what, obj);
726     }
727 
728     @Override
unregisterForSubscriptionInfoReady(Handler h)729     public void unregisterForSubscriptionInfoReady(Handler h) {
730         mSST.unregisterForSubscriptionInfoReady(h);
731     }
732 
733     @Override
setOnEcbModeExitResponse(Handler h, int what, Object obj)734     public void setOnEcbModeExitResponse(Handler h, int what, Object obj) {
735         mEcmExitRespRegistrant = new Registrant (h, what, obj);
736     }
737 
738     @Override
unsetOnEcbModeExitResponse(Handler h)739     public void unsetOnEcbModeExitResponse(Handler h) {
740         mEcmExitRespRegistrant.clear();
741     }
742 
743     @Override
registerForCallWaiting(Handler h, int what, Object obj)744     public void registerForCallWaiting(Handler h, int what, Object obj) {
745         mCT.registerForCallWaiting(h, what, obj);
746     }
747 
748     @Override
unregisterForCallWaiting(Handler h)749     public void unregisterForCallWaiting(Handler h) {
750         mCT.unregisterForCallWaiting(h);
751     }
752 
753     @Override
754     public void
getNeighboringCids(Message response)755     getNeighboringCids(Message response) {
756         /*
757          * This is currently not implemented.  At least as of June
758          * 2009, there is no neighbor cell information available for
759          * CDMA because some party is resisting making this
760          * information readily available.  Consequently, calling this
761          * function can have no useful effect.  This situation may
762          * (and hopefully will) change in the future.
763          */
764         if (response != null) {
765             CommandException ce = new CommandException(
766                     CommandException.Error.REQUEST_NOT_SUPPORTED);
767             AsyncResult.forMessage(response).exception = ce;
768             response.sendToTarget();
769         }
770     }
771 
772     @Override
getDataConnectionState(String apnType)773     public PhoneConstants.DataState getDataConnectionState(String apnType) {
774         PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED;
775 
776         if (mSST == null) {
777              // Radio Technology Change is ongoning, dispose() and removeReferences() have
778              // already been called
779 
780              ret = PhoneConstants.DataState.DISCONNECTED;
781         } else if (mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
782             // If we're out of service, open TCP sockets may still work
783             // but no data will flow
784             ret = PhoneConstants.DataState.DISCONNECTED;
785         } else if (mDcTracker.isApnTypeEnabled(apnType) == false ||
786                 mDcTracker.isApnTypeActive(apnType) == false) {
787             ret = PhoneConstants.DataState.DISCONNECTED;
788         } else {
789             switch (mDcTracker.getState(apnType)) {
790                 case RETRYING:
791                 case FAILED:
792                 case IDLE:
793                     ret = PhoneConstants.DataState.DISCONNECTED;
794                 break;
795 
796                 case CONNECTED:
797                 case DISCONNECTING:
798                     if ( mCT.mState != PhoneConstants.State.IDLE
799                             && !mSST.isConcurrentVoiceAndDataAllowed()) {
800                         ret = PhoneConstants.DataState.SUSPENDED;
801                     } else {
802                         ret = PhoneConstants.DataState.CONNECTED;
803                     }
804                 break;
805 
806                 case CONNECTING:
807                 case SCANNING:
808                     ret = PhoneConstants.DataState.CONNECTING;
809                 break;
810             }
811         }
812 
813         log("getDataConnectionState apnType=" + apnType + " ret=" + ret);
814         return ret;
815     }
816 
817     @Override
sendUssdResponse(String ussdMessge)818     public void sendUssdResponse(String ussdMessge) {
819         Rlog.e(LOG_TAG, "sendUssdResponse: not possible in CDMA");
820     }
821 
822     @Override
sendDtmf(char c)823     public void sendDtmf(char c) {
824         if (!PhoneNumberUtils.is12Key(c)) {
825             Rlog.e(LOG_TAG,
826                     "sendDtmf called with invalid character '" + c + "'");
827         } else {
828             if (mCT.mState ==  PhoneConstants.State.OFFHOOK) {
829                 mCi.sendDtmf(c, null);
830             }
831         }
832     }
833 
834     @Override
startDtmf(char c)835     public void startDtmf(char c) {
836         if (!PhoneNumberUtils.is12Key(c)) {
837             Rlog.e(LOG_TAG,
838                     "startDtmf called with invalid character '" + c + "'");
839         } else {
840             mCi.startDtmf(c, null);
841         }
842     }
843 
844     @Override
stopDtmf()845     public void stopDtmf() {
846         mCi.stopDtmf(null);
847     }
848 
849     @Override
sendBurstDtmf(String dtmfString, int on, int off, Message onComplete)850     public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
851         boolean check = true;
852         for (int itr = 0;itr < dtmfString.length(); itr++) {
853             if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) {
854                 Rlog.e(LOG_TAG,
855                         "sendDtmf called with invalid character '" + dtmfString.charAt(itr)+ "'");
856                 check = false;
857                 break;
858             }
859         }
860         if ((mCT.mState ==  PhoneConstants.State.OFFHOOK)&&(check)) {
861             mCi.sendBurstDtmf(dtmfString, on, off, onComplete);
862         }
863      }
864 
865     @Override
getAvailableNetworks(Message response)866     public void getAvailableNetworks(Message response) {
867         Rlog.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA");
868     }
869 
870     @Override
setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete)871     public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
872         Rlog.e(LOG_TAG, "setOutgoingCallerIdDisplay: not possible in CDMA");
873     }
874 
875     @Override
enableLocationUpdates()876     public void enableLocationUpdates() {
877         mSST.enableLocationUpdates();
878     }
879 
880     @Override
disableLocationUpdates()881     public void disableLocationUpdates() {
882         mSST.disableLocationUpdates();
883     }
884 
885     @Override
getDataCallList(Message response)886     public void getDataCallList(Message response) {
887         mCi.getDataCallList(response);
888     }
889 
890     @Override
getDataRoamingEnabled()891     public boolean getDataRoamingEnabled() {
892         return mDcTracker.getDataOnRoamingEnabled();
893     }
894 
895     @Override
setDataEnabled(boolean enable)896     public void setDataEnabled(boolean enable) {
897         mDcTracker.setDataEnabled(enable);
898     }
899 
900     @Override
getDataEnabled()901     public boolean getDataEnabled() {
902         return mDcTracker.getDataEnabled();
903     }
904 
905     @Override
setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete)906     public void setVoiceMailNumber(String alphaTag,
907                                    String voiceMailNumber,
908                                    Message onComplete) {
909         Message resp;
910         mVmNumber = voiceMailNumber;
911         resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
912         IccRecords r = mIccRecords.get();
913         if (r != null) {
914             r.setVoiceMailNumber(alphaTag, mVmNumber, resp);
915         }
916     }
917 
918     @Override
getVoiceMailNumber()919     public String getVoiceMailNumber() {
920         String number = null;
921         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
922         number = sp.getString(VM_NUMBER_CDMA + getPhoneId(), null);
923         if (TextUtils.isEmpty(number)) {
924             String[] listArray = getContext().getResources()
925                 .getStringArray(com.android.internal.R.array.config_default_vm_number);
926             if (listArray != null && listArray.length > 0) {
927                 for (int i=0; i<listArray.length; i++) {
928                     if (!TextUtils.isEmpty(listArray[i])) {
929                         String[] defaultVMNumberArray = listArray[i].split(";");
930                         if (defaultVMNumberArray != null && defaultVMNumberArray.length > 0) {
931                             if (defaultVMNumberArray.length == 1) {
932                                 number = defaultVMNumberArray[0];
933                             } else if (defaultVMNumberArray.length == 2 &&
934                                     !TextUtils.isEmpty(defaultVMNumberArray[1]) &&
935                                     defaultVMNumberArray[1].equalsIgnoreCase(getGroupIdLevel1())) {
936                                 number = defaultVMNumberArray[0];
937                                 break;
938                             }
939                         }
940                     }
941                 }
942             }
943         }
944         if (TextUtils.isEmpty(number)) {
945             // Read platform settings for dynamic voicemail number
946             if (getContext().getResources().getBoolean(com.android.internal
947                     .R.bool.config_telephony_use_own_number_for_voicemail)) {
948                 number = getLine1Number();
949             } else {
950                 number = "*86";
951             }
952         }
953         return number;
954     }
955 
956     // pending voice mail count updated after phone creation
updateVoiceMail()957     private void updateVoiceMail() {
958         setVoiceMessageCount(getStoredVoiceMessageCount());
959     }
960 
961     @Override
getVoiceMailAlphaTag()962     public String getVoiceMailAlphaTag() {
963         // TODO: Where can we get this value has to be clarified with QC.
964         String ret = "";//TODO: Remove = "", if we know where to get this value.
965 
966         //ret = mSIMRecords.getVoiceMailAlphaTag();
967 
968         if (ret == null || ret.length() == 0) {
969             return mContext.getText(
970                 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString();
971         }
972 
973         return ret;
974     }
975 
976     @Override
getCallForwardingOption(int commandInterfaceCFReason, Message onComplete)977     public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
978         Rlog.e(LOG_TAG, "getCallForwardingOption: not possible in CDMA");
979     }
980 
981     @Override
setCallForwardingOption(int commandInterfaceCFAction, int commandInterfaceCFReason, String dialingNumber, int timerSeconds, Message onComplete)982     public void setCallForwardingOption(int commandInterfaceCFAction,
983             int commandInterfaceCFReason,
984             String dialingNumber,
985             int timerSeconds,
986             Message onComplete) {
987         Rlog.e(LOG_TAG, "setCallForwardingOption: not possible in CDMA");
988     }
989 
990     @Override
991     public void
getOutgoingCallerIdDisplay(Message onComplete)992     getOutgoingCallerIdDisplay(Message onComplete) {
993         Rlog.e(LOG_TAG, "getOutgoingCallerIdDisplay: not possible in CDMA");
994     }
995 
996     @Override
997     public boolean
getCallForwardingIndicator()998     getCallForwardingIndicator() {
999         Rlog.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA");
1000         return false;
1001     }
1002 
1003     @Override
explicitCallTransfer()1004     public void explicitCallTransfer() {
1005         Rlog.e(LOG_TAG, "explicitCallTransfer: not possible in CDMA");
1006     }
1007 
1008     @Override
getLine1AlphaTag()1009     public String getLine1AlphaTag() {
1010         Rlog.e(LOG_TAG, "getLine1AlphaTag: not possible in CDMA");
1011         return null;
1012     }
1013 
1014     /**
1015      * Notify any interested party of a Phone state change
1016      * {@link com.android.internal.telephony.PhoneConstants.State}
1017      */
notifyPhoneStateChanged()1018     /*package*/ void notifyPhoneStateChanged() {
1019         mNotifier.notifyPhoneState(this);
1020     }
1021 
1022     /**
1023      * Notify registrants of a change in the call state. This notifies changes in
1024      * {@link com.android.internal.telephony.Call.State}. Use this when changes
1025      * in the precise call state are needed, else use notifyPhoneStateChanged.
1026      */
notifyPreciseCallStateChanged()1027     /*package*/ void notifyPreciseCallStateChanged() {
1028         /* we'd love it if this was package-scoped*/
1029         super.notifyPreciseCallStateChangedP();
1030     }
1031 
notifyServiceStateChanged(ServiceState ss)1032      void notifyServiceStateChanged(ServiceState ss) {
1033          super.notifyServiceStateChangedP(ss);
1034      }
1035 
notifyLocationChanged()1036      void notifyLocationChanged() {
1037          mNotifier.notifyCellLocation(this);
1038      }
1039 
notifyNewRingingConnection(Connection c)1040     public void notifyNewRingingConnection(Connection c) {
1041         super.notifyNewRingingConnectionP(c);
1042     }
1043 
notifyDisconnect(Connection cn)1044     /*package*/ void notifyDisconnect(Connection cn) {
1045         mDisconnectRegistrants.notifyResult(cn);
1046 
1047         mNotifier.notifyDisconnectCause(cn.getDisconnectCause(), cn.getPreciseDisconnectCause());
1048     }
1049 
notifyUnknownConnection(Connection connection)1050     void notifyUnknownConnection(Connection connection) {
1051         mUnknownConnectionRegistrants.notifyResult(connection);
1052     }
1053 
1054     @Override
isInEmergencyCall()1055     public boolean isInEmergencyCall() {
1056         return mCT.isInEmergencyCall();
1057     }
1058 
1059     @Override
isInEcm()1060     public boolean isInEcm() {
1061         return mIsPhoneInEcmState;
1062     }
1063 
sendEmergencyCallbackModeChange()1064     void sendEmergencyCallbackModeChange(){
1065         //Send an Intent
1066         Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
1067         intent.putExtra(PhoneConstants.PHONE_IN_ECM_STATE, mIsPhoneInEcmState);
1068         SubscriptionManager.putPhoneIdAndSubIdExtra(intent, getPhoneId());
1069         ActivityManagerNative.broadcastStickyIntent(intent,null,UserHandle.USER_ALL);
1070         if (DBG) Rlog.d(LOG_TAG, "sendEmergencyCallbackModeChange");
1071     }
1072 
1073     @Override
exitEmergencyCallbackMode()1074     public void exitEmergencyCallbackMode() {
1075         if (mWakeLock.isHeld()) {
1076             mWakeLock.release();
1077         }
1078         // Send a message which will invoke handleExitEmergencyCallbackMode
1079         mCi.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
1080     }
1081 
handleEnterEmergencyCallbackMode(Message msg)1082     private void handleEnterEmergencyCallbackMode(Message msg) {
1083         if (DBG) {
1084             Rlog.d(LOG_TAG, "handleEnterEmergencyCallbackMode,mIsPhoneInEcmState= "
1085                     + mIsPhoneInEcmState);
1086         }
1087         // if phone is not in Ecm mode, and it's changed to Ecm mode
1088         if (mIsPhoneInEcmState == false) {
1089             mIsPhoneInEcmState = true;
1090             // notify change
1091             sendEmergencyCallbackModeChange();
1092             setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "true");
1093 
1094             // Post this runnable so we will automatically exit
1095             // if no one invokes exitEmergencyCallbackMode() directly.
1096             long delayInMillis = SystemProperties.getLong(
1097                     TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
1098             postDelayed(mExitEcmRunnable, delayInMillis);
1099             // We don't want to go to sleep while in Ecm
1100             mWakeLock.acquire();
1101         }
1102     }
1103 
handleExitEmergencyCallbackMode(Message msg)1104     private void handleExitEmergencyCallbackMode(Message msg) {
1105         AsyncResult ar = (AsyncResult)msg.obj;
1106         if (DBG) {
1107             Rlog.d(LOG_TAG, "handleExitEmergencyCallbackMode,ar.exception , mIsPhoneInEcmState "
1108                     + ar.exception + mIsPhoneInEcmState);
1109         }
1110         // Remove pending exit Ecm runnable, if any
1111         removeCallbacks(mExitEcmRunnable);
1112 
1113         if (mEcmExitRespRegistrant != null) {
1114             mEcmExitRespRegistrant.notifyRegistrant(ar);
1115         }
1116         // if exiting ecm success
1117         if (ar.exception == null) {
1118             if (mIsPhoneInEcmState) {
1119                 mIsPhoneInEcmState = false;
1120                 setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "false");
1121             }
1122             // send an Intent
1123             sendEmergencyCallbackModeChange();
1124             // Re-initiate data connection
1125             mDcTracker.setInternalDataEnabled(true);
1126         }
1127     }
1128 
1129     /**
1130      * Handle to cancel or restart Ecm timer in emergency call back mode
1131      * if action is CANCEL_ECM_TIMER, cancel Ecm timer and notify apps the timer is canceled;
1132      * otherwise, restart Ecm timer and notify apps the timer is restarted.
1133      */
handleTimerInEmergencyCallbackMode(int action)1134     void handleTimerInEmergencyCallbackMode(int action) {
1135         switch(action) {
1136         case CANCEL_ECM_TIMER:
1137             removeCallbacks(mExitEcmRunnable);
1138             mEcmTimerResetRegistrants.notifyResult(Boolean.TRUE);
1139             break;
1140         case RESTART_ECM_TIMER:
1141             long delayInMillis = SystemProperties.getLong(
1142                     TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
1143             postDelayed(mExitEcmRunnable, delayInMillis);
1144             mEcmTimerResetRegistrants.notifyResult(Boolean.FALSE);
1145             break;
1146         default:
1147             Rlog.e(LOG_TAG, "handleTimerInEmergencyCallbackMode, unsupported action " + action);
1148         }
1149     }
1150 
notifyEcbmTimerReset(Boolean flag)1151     public void notifyEcbmTimerReset(Boolean flag) {
1152         mEcmTimerResetRegistrants.notifyResult(flag);
1153     }
1154 
1155     /**
1156      * Registration point for Ecm timer reset
1157      * @param h handler to notify
1158      * @param what User-defined message code
1159      * @param obj placed in Message.obj
1160      */
1161     @Override
registerForEcmTimerReset(Handler h, int what, Object obj)1162     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
1163         mEcmTimerResetRegistrants.addUnique(h, what, obj);
1164     }
1165 
1166     @Override
unregisterForEcmTimerReset(Handler h)1167     public void unregisterForEcmTimerReset(Handler h) {
1168         mEcmTimerResetRegistrants.remove(h);
1169     }
1170 
1171     @Override
handleMessage(Message msg)1172     public void handleMessage(Message msg) {
1173         AsyncResult ar;
1174         Message     onComplete;
1175 
1176         // messages to be handled whether or not the phone is being destroyed
1177         // should only include messages which are being re-directed and do not use
1178         // resources of the phone being destroyed
1179         switch (msg.what) {
1180             // handle the select network completion callbacks.
1181             case EVENT_SET_NETWORK_MANUAL_COMPLETE:
1182             case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE:
1183                 super.handleMessage(msg);
1184                 return;
1185         }
1186 
1187         if (!mIsTheCurrentActivePhone) {
1188             Rlog.e(LOG_TAG, "Received message " + msg +
1189                     "[" + msg.what + "] while being destroyed. Ignoring.");
1190             return;
1191         }
1192         switch(msg.what) {
1193             case EVENT_RADIO_AVAILABLE: {
1194                 mCi.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
1195 
1196                 mCi.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));
1197                 mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));
1198             }
1199             break;
1200 
1201             case EVENT_GET_BASEBAND_VERSION_DONE:{
1202                 ar = (AsyncResult)msg.obj;
1203 
1204                 if (ar.exception != null) {
1205                     break;
1206                 }
1207 
1208                 if (DBG) Rlog.d(LOG_TAG, "Baseband version: " + ar.result);
1209                 TelephonyManager.from(mContext).setBasebandVersionForPhone(getPhoneId(),
1210                         (String)ar.result);
1211             }
1212             break;
1213 
1214             case EVENT_GET_DEVICE_IDENTITY_DONE:{
1215                 ar = (AsyncResult)msg.obj;
1216 
1217                 if (ar.exception != null) {
1218                     break;
1219                 }
1220                 String[] respId = (String[])ar.result;
1221                 mImei = respId[0];
1222                 mImeiSv = respId[1];
1223                 mEsn  =  respId[2];
1224                 mMeid =  respId[3];
1225             }
1226             break;
1227 
1228             case EVENT_EMERGENCY_CALLBACK_MODE_ENTER:{
1229                 handleEnterEmergencyCallbackMode(msg);
1230             }
1231             break;
1232 
1233             case  EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE:{
1234                 handleExitEmergencyCallbackMode(msg);
1235             }
1236             break;
1237 
1238             case EVENT_RUIM_RECORDS_LOADED:{
1239                 Rlog.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received");
1240                 updateCurrentCarrierInProvider();
1241                 // Notify voicemails.
1242                 log("notifyMessageWaitingChanged");
1243                 mNotifier.notifyMessageWaitingChanged(this);
1244                 updateVoiceMail();
1245             }
1246             break;
1247 
1248             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:{
1249                 Rlog.d(LOG_TAG, "Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received");
1250                 ImsPhone imsPhone = mImsPhone;
1251                 if (imsPhone != null) {
1252                     imsPhone.getServiceState().setStateOff();
1253                 }
1254             }
1255             break;
1256 
1257             case EVENT_RADIO_ON:{
1258                 Rlog.d(LOG_TAG, "Event EVENT_RADIO_ON Received");
1259                 handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
1260             }
1261             break;
1262 
1263             case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:{
1264                 Rlog.d(LOG_TAG, "EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED");
1265                 handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource());
1266             }
1267             break;
1268 
1269             case EVENT_SSN:{
1270                 Rlog.d(LOG_TAG, "Event EVENT_SSN Received");
1271             }
1272             break;
1273 
1274             case EVENT_REGISTERED_TO_NETWORK:{
1275                 Rlog.d(LOG_TAG, "Event EVENT_REGISTERED_TO_NETWORK Received");
1276             }
1277             break;
1278 
1279             case EVENT_NV_READY:{
1280                 Rlog.d(LOG_TAG, "Event EVENT_NV_READY Received");
1281                 prepareEri();
1282                 // Notify voicemails.
1283                 log("notifyMessageWaitingChanged");
1284                 mNotifier.notifyMessageWaitingChanged(this);
1285                 updateVoiceMail();
1286             }
1287             break;
1288 
1289             case EVENT_SET_VM_NUMBER_DONE:{
1290                 ar = (AsyncResult)msg.obj;
1291                 if (IccException.class.isInstance(ar.exception)) {
1292                     storeVoiceMailNumber(mVmNumber);
1293                     ar.exception = null;
1294                 }
1295                 onComplete = (Message) ar.userObj;
1296                 if (onComplete != null) {
1297                     AsyncResult.forMessage(onComplete, ar.result, ar.exception);
1298                     onComplete.sendToTarget();
1299                 }
1300             }
1301             break;
1302 
1303             default:{
1304                 super.handleMessage(msg);
1305             }
1306         }
1307     }
1308 
getUiccCardApplication()1309     protected UiccCardApplication getUiccCardApplication() {
1310         return  mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2);
1311     }
1312 
1313     @Override
onUpdateIccAvailability()1314     protected void onUpdateIccAvailability() {
1315         if (mUiccController == null ) {
1316             return;
1317         }
1318 
1319         UiccCardApplication newUiccApplication = getUiccCardApplication();
1320 
1321         if (newUiccApplication == null) {
1322             log("can't find 3GPP2 application; trying APP_FAM_3GPP");
1323             newUiccApplication =
1324                     mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP);
1325         }
1326 
1327         UiccCardApplication app = mUiccApplication.get();
1328         if (app != newUiccApplication) {
1329             if (app != null) {
1330                 log("Removing stale icc objects.");
1331                 if (mIccRecords.get() != null) {
1332                     unregisterForRuimRecordEvents();
1333                 }
1334                 mIccRecords.set(null);
1335                 mUiccApplication.set(null);
1336             }
1337             if (newUiccApplication != null) {
1338                 log("New Uicc application found");
1339                 mUiccApplication.set(newUiccApplication);
1340                 mIccRecords.set(newUiccApplication.getIccRecords());
1341                 registerForRuimRecordEvents();
1342             }
1343         }
1344     }
1345 
1346     /**
1347      * Handles the call to get the subscription source
1348      *
1349      * @param newSubscriptionSource holds the new CDMA subscription source value
1350      */
handleCdmaSubscriptionSource(int newSubscriptionSource)1351     private void handleCdmaSubscriptionSource(int newSubscriptionSource) {
1352         if (newSubscriptionSource != mCdmaSubscriptionSource) {
1353              mCdmaSubscriptionSource = newSubscriptionSource;
1354              if (newSubscriptionSource == CDMA_SUBSCRIPTION_NV) {
1355                  // NV is ready when subscription source is NV
1356                  sendMessage(obtainMessage(EVENT_NV_READY));
1357              }
1358         }
1359     }
1360 
1361     /**
1362      * Retrieves the PhoneSubInfo of the CDMAPhone
1363      */
1364     @Override
getPhoneSubInfo()1365     public PhoneSubInfo getPhoneSubInfo() {
1366         return mSubInfo;
1367     }
1368 
1369     /**
1370      * Retrieves the IccPhoneBookInterfaceManager of the CDMAPhone
1371      */
1372     @Override
getIccPhoneBookInterfaceManager()1373     public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager() {
1374         return mRuimPhoneBookInterfaceManager;
1375     }
1376 
registerForEriFileLoaded(Handler h, int what, Object obj)1377     public void registerForEriFileLoaded(Handler h, int what, Object obj) {
1378         Registrant r = new Registrant (h, what, obj);
1379         mEriFileLoadedRegistrants.add(r);
1380     }
1381 
unregisterForEriFileLoaded(Handler h)1382     public void unregisterForEriFileLoaded(Handler h) {
1383         mEriFileLoadedRegistrants.remove(h);
1384     }
1385 
1386     // override for allowing access from other classes of this package
1387     /**
1388      * {@inheritDoc}
1389      */
1390     @Override
setSystemProperty(String property, String value)1391     public void setSystemProperty(String property, String value) {
1392         super.setSystemProperty(property, value);
1393     }
1394 
1395     // override for allowing access from other classes of this package
1396     /**
1397      * {@inheritDoc}
1398      */
1399     @Override
getSystemProperty(String property, String defValue)1400     public String getSystemProperty(String property, String defValue) {
1401         return super.getSystemProperty(property, defValue);
1402     }
1403 
1404     /**
1405      * Activate or deactivate cell broadcast SMS.
1406      *
1407      * @param activate 0 = activate, 1 = deactivate
1408      * @param response Callback message is empty on completion
1409      */
1410     @Override
activateCellBroadcastSms(int activate, Message response)1411     public void activateCellBroadcastSms(int activate, Message response) {
1412         Rlog.e(LOG_TAG, "[CDMAPhone] activateCellBroadcastSms() is obsolete; use SmsManager");
1413         response.sendToTarget();
1414     }
1415 
1416     /**
1417      * Query the current configuration of cdma cell broadcast SMS.
1418      *
1419      * @param response Callback message is empty on completion
1420      */
1421     @Override
getCellBroadcastSmsConfig(Message response)1422     public void getCellBroadcastSmsConfig(Message response) {
1423         Rlog.e(LOG_TAG, "[CDMAPhone] getCellBroadcastSmsConfig() is obsolete; use SmsManager");
1424         response.sendToTarget();
1425     }
1426 
1427     /**
1428      * Configure cdma cell broadcast SMS.
1429      *
1430      * @param response Callback message is empty on completion
1431      */
1432     @Override
setCellBroadcastSmsConfig(int[] configValuesArray, Message response)1433     public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) {
1434         Rlog.e(LOG_TAG, "[CDMAPhone] setCellBroadcastSmsConfig() is obsolete; use SmsManager");
1435         response.sendToTarget();
1436     }
1437 
1438     /**
1439      * Returns true if OTA Service Provisioning needs to be performed.
1440      */
1441     @Override
needsOtaServiceProvisioning()1442     public boolean needsOtaServiceProvisioning() {
1443         return mSST.getOtasp() != ServiceStateTracker.OTASP_NOT_NEEDED;
1444     }
1445 
1446     private static final String IS683A_FEATURE_CODE = "*228";
1447     private static final int IS683A_FEATURE_CODE_NUM_DIGITS = 4;
1448     private static final int IS683A_SYS_SEL_CODE_NUM_DIGITS = 2;
1449     private static final int IS683A_SYS_SEL_CODE_OFFSET = 4;
1450 
1451     private static final int IS683_CONST_800MHZ_A_BAND = 0;
1452     private static final int IS683_CONST_800MHZ_B_BAND = 1;
1453     private static final int IS683_CONST_1900MHZ_A_BLOCK = 2;
1454     private static final int IS683_CONST_1900MHZ_B_BLOCK = 3;
1455     private static final int IS683_CONST_1900MHZ_C_BLOCK = 4;
1456     private static final int IS683_CONST_1900MHZ_D_BLOCK = 5;
1457     private static final int IS683_CONST_1900MHZ_E_BLOCK = 6;
1458     private static final int IS683_CONST_1900MHZ_F_BLOCK = 7;
1459     private static final int INVALID_SYSTEM_SELECTION_CODE = -1;
1460 
isIs683OtaSpDialStr(String dialStr)1461     private static boolean isIs683OtaSpDialStr(String dialStr) {
1462         int sysSelCodeInt;
1463         boolean isOtaspDialString = false;
1464         int dialStrLen = dialStr.length();
1465 
1466         if (dialStrLen == IS683A_FEATURE_CODE_NUM_DIGITS) {
1467             if (dialStr.equals(IS683A_FEATURE_CODE)) {
1468                 isOtaspDialString = true;
1469             }
1470         } else {
1471             sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr);
1472             switch (sysSelCodeInt) {
1473                 case IS683_CONST_800MHZ_A_BAND:
1474                 case IS683_CONST_800MHZ_B_BAND:
1475                 case IS683_CONST_1900MHZ_A_BLOCK:
1476                 case IS683_CONST_1900MHZ_B_BLOCK:
1477                 case IS683_CONST_1900MHZ_C_BLOCK:
1478                 case IS683_CONST_1900MHZ_D_BLOCK:
1479                 case IS683_CONST_1900MHZ_E_BLOCK:
1480                 case IS683_CONST_1900MHZ_F_BLOCK:
1481                     isOtaspDialString = true;
1482                     break;
1483                 default:
1484                     break;
1485             }
1486         }
1487         return isOtaspDialString;
1488     }
1489     /**
1490      * This function extracts the system selection code from the dial string.
1491      */
extractSelCodeFromOtaSpNum(String dialStr)1492     private static int extractSelCodeFromOtaSpNum(String dialStr) {
1493         int dialStrLen = dialStr.length();
1494         int sysSelCodeInt = INVALID_SYSTEM_SELECTION_CODE;
1495 
1496         if ((dialStr.regionMatches(0, IS683A_FEATURE_CODE,
1497                                    0, IS683A_FEATURE_CODE_NUM_DIGITS)) &&
1498             (dialStrLen >= (IS683A_FEATURE_CODE_NUM_DIGITS +
1499                             IS683A_SYS_SEL_CODE_NUM_DIGITS))) {
1500                 // Since we checked the condition above, the system selection code
1501                 // extracted from dialStr will not cause any exception
1502                 sysSelCodeInt = Integer.parseInt (
1503                                 dialStr.substring (IS683A_FEATURE_CODE_NUM_DIGITS,
1504                                 IS683A_FEATURE_CODE_NUM_DIGITS + IS683A_SYS_SEL_CODE_NUM_DIGITS));
1505         }
1506         if (DBG) Rlog.d(LOG_TAG, "extractSelCodeFromOtaSpNum " + sysSelCodeInt);
1507         return sysSelCodeInt;
1508     }
1509 
1510     /**
1511      * This function checks if the system selection code extracted from
1512      * the dial string "sysSelCodeInt' is the system selection code specified
1513      * in the carrier ota sp number schema "sch".
1514      */
1515     private static boolean
checkOtaSpNumBasedOnSysSelCode(int sysSelCodeInt, String sch[])1516     checkOtaSpNumBasedOnSysSelCode (int sysSelCodeInt, String sch[]) {
1517         boolean isOtaSpNum = false;
1518         try {
1519             // Get how many number of system selection code ranges
1520             int selRc = Integer.parseInt(sch[1]);
1521             for (int i = 0; i < selRc; i++) {
1522                 if (!TextUtils.isEmpty(sch[i+2]) && !TextUtils.isEmpty(sch[i+3])) {
1523                     int selMin = Integer.parseInt(sch[i+2]);
1524                     int selMax = Integer.parseInt(sch[i+3]);
1525                     // Check if the selection code extracted from the dial string falls
1526                     // within any of the range pairs specified in the schema.
1527                     if ((sysSelCodeInt >= selMin) && (sysSelCodeInt <= selMax)) {
1528                         isOtaSpNum = true;
1529                         break;
1530                     }
1531                 }
1532             }
1533         } catch (NumberFormatException ex) {
1534             // If the carrier ota sp number schema is not correct, we still allow dial
1535             // and only log the error:
1536             Rlog.e(LOG_TAG, "checkOtaSpNumBasedOnSysSelCode, error", ex);
1537         }
1538         return isOtaSpNum;
1539     }
1540 
1541     // Define the pattern/format for carrier specified OTASP number schema.
1542     // It separates by comma and/or whitespace.
1543     private static Pattern pOtaSpNumSchema = Pattern.compile("[,\\s]+");
1544 
1545     /**
1546      * The following function checks if a dial string is a carrier specified
1547      * OTASP number or not by checking against the OTASP number schema stored
1548      * in PROPERTY_OTASP_NUM_SCHEMA.
1549      *
1550      * Currently, there are 2 schemas for carriers to specify the OTASP number:
1551      * 1) Use system selection code:
1552      *    The schema is:
1553      *    SELC,the # of code pairs,min1,max1,min2,max2,...
1554      *    e.g "SELC,3,10,20,30,40,60,70" indicates that there are 3 pairs of
1555      *    selection codes, and they are {10,20}, {30,40} and {60,70} respectively.
1556      *
1557      * 2) Use feature code:
1558      *    The schema is:
1559      *    "FC,length of feature code,feature code".
1560      *     e.g "FC,2,*2" indicates that the length of the feature code is 2,
1561      *     and the code itself is "*2".
1562      */
isCarrierOtaSpNum(String dialStr)1563     private boolean isCarrierOtaSpNum(String dialStr) {
1564         boolean isOtaSpNum = false;
1565         int sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr);
1566         if (sysSelCodeInt == INVALID_SYSTEM_SELECTION_CODE) {
1567             return isOtaSpNum;
1568         }
1569         // mCarrierOtaSpNumSchema is retrieved from PROPERTY_OTASP_NUM_SCHEMA:
1570         if (!TextUtils.isEmpty(mCarrierOtaSpNumSchema)) {
1571             Matcher m = pOtaSpNumSchema.matcher(mCarrierOtaSpNumSchema);
1572             if (DBG) {
1573                 Rlog.d(LOG_TAG, "isCarrierOtaSpNum,schema" + mCarrierOtaSpNumSchema);
1574             }
1575 
1576             if (m.find()) {
1577                 String sch[] = pOtaSpNumSchema.split(mCarrierOtaSpNumSchema);
1578                 // If carrier uses system selection code mechanism
1579                 if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("SELC")) {
1580                     if (sysSelCodeInt!=INVALID_SYSTEM_SELECTION_CODE) {
1581                         isOtaSpNum=checkOtaSpNumBasedOnSysSelCode(sysSelCodeInt,sch);
1582                     } else {
1583                         if (DBG) {
1584                             Rlog.d(LOG_TAG, "isCarrierOtaSpNum,sysSelCodeInt is invalid");
1585                         }
1586                     }
1587                 } else if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("FC")) {
1588                     int fcLen =  Integer.parseInt(sch[1]);
1589                     String fc = sch[2];
1590                     if (dialStr.regionMatches(0,fc,0,fcLen)) {
1591                         isOtaSpNum = true;
1592                     } else {
1593                         if (DBG) Rlog.d(LOG_TAG, "isCarrierOtaSpNum,not otasp number");
1594                     }
1595                 } else {
1596                     if (DBG) {
1597                         Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema not supported" + sch[0]);
1598                     }
1599                 }
1600             } else {
1601                 if (DBG) {
1602                     Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern not right" +
1603                           mCarrierOtaSpNumSchema);
1604                 }
1605             }
1606         } else {
1607             if (DBG) Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern empty");
1608         }
1609         return isOtaSpNum;
1610     }
1611 
1612     /**
1613      * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier
1614      * OTASP dial string.
1615      *
1616      * @param dialStr the number to look up.
1617      * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string
1618      */
1619     @Override
isOtaSpNumber(String dialStr)1620     public  boolean isOtaSpNumber(String dialStr){
1621         boolean isOtaSpNum = false;
1622         String dialableStr = PhoneNumberUtils.extractNetworkPortionAlt(dialStr);
1623         if (dialableStr != null) {
1624             isOtaSpNum = isIs683OtaSpDialStr(dialableStr);
1625             if (isOtaSpNum == false) {
1626                 isOtaSpNum = isCarrierOtaSpNum(dialableStr);
1627             }
1628         }
1629         if (DBG) Rlog.d(LOG_TAG, "isOtaSpNumber " + isOtaSpNum);
1630         return isOtaSpNum;
1631     }
1632 
1633     @Override
getCdmaEriIconIndex()1634     public int getCdmaEriIconIndex() {
1635         return getServiceState().getCdmaEriIconIndex();
1636     }
1637 
1638     /**
1639      * Returns the CDMA ERI icon mode,
1640      * 0 - ON
1641      * 1 - FLASHING
1642      */
1643     @Override
getCdmaEriIconMode()1644     public int getCdmaEriIconMode() {
1645         return getServiceState().getCdmaEriIconMode();
1646     }
1647 
1648     /**
1649      * Returns the CDMA ERI text,
1650      */
1651     @Override
getCdmaEriText()1652     public String getCdmaEriText() {
1653         int roamInd = getServiceState().getCdmaRoamingIndicator();
1654         int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
1655         return mEriManager.getCdmaEriText(roamInd, defRoamInd);
1656     }
1657 
1658     /**
1659      * Store the voicemail number in preferences
1660      */
storeVoiceMailNumber(String number)1661     private void storeVoiceMailNumber(String number) {
1662         // Update the preference value of voicemail number
1663         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1664         SharedPreferences.Editor editor = sp.edit();
1665         editor.putString(VM_NUMBER_CDMA + getPhoneId(), number);
1666         editor.apply();
1667     }
1668 
1669     /**
1670      * Sets PROPERTY_ICC_OPERATOR_ISO_COUNTRY property
1671      *
1672      */
setIsoCountryProperty(String operatorNumeric)1673     protected void setIsoCountryProperty(String operatorNumeric) {
1674         TelephonyManager tm = TelephonyManager.from(mContext);
1675         if (TextUtils.isEmpty(operatorNumeric)) {
1676             log("setIsoCountryProperty: clear 'gsm.sim.operator.iso-country'");
1677             tm.setSimCountryIsoForPhone(mPhoneId, "");
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             tm.setSimCountryIsoForPhone(mPhoneId, 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      */
updateCurrentCarrierInProvider(String operatorNumeric)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      */
updateCurrentCarrierInProvider()1728     boolean updateCurrentCarrierInProvider() {
1729         return true;
1730     }
1731 
prepareEri()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 
isEriFileLoaded()1745     public boolean isEriFileLoaded() {
1746         return mEriManager.isEriFileLoaded();
1747     }
1748 
registerForRuimRecordEvents()1749     protected void registerForRuimRecordEvents() {
1750         IccRecords r = mIccRecords.get();
1751         if (r == null) {
1752             return;
1753         }
1754         r.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
1755     }
1756 
unregisterForRuimRecordEvents()1757     protected void unregisterForRuimRecordEvents() {
1758         IccRecords r = mIccRecords.get();
1759         if (r == null) {
1760             return;
1761         }
1762         r.unregisterForRecordsLoaded(this);
1763     }
1764 
1765      /**
1766      * Sets the SIM voice message count
1767      * @param line Subscriber Profile Number, one-based. Only '1' is supported
1768      * @param countWaiting The number of messages waiting, if known. Use
1769      *                     -1 to indicate that an unknown number of
1770      *                      messages are waiting
1771      * This is a wrapper function for setVoiceMessageCount
1772      */
1773     @Override
setVoiceMessageWaiting(int line, int countWaiting)1774     public void setVoiceMessageWaiting(int line, int countWaiting) {
1775         setVoiceMessageCount(countWaiting);
1776     }
1777 
log(String s)1778     protected void log(String s) {
1779         if (DBG)
1780             Rlog.d(LOG_TAG, s);
1781     }
1782 
loge(String s, Exception e)1783     protected void loge(String s, Exception e) {
1784         if (DBG)
1785             Rlog.e(LOG_TAG, s, e);
1786     }
1787 
1788     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)1789     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
1790         pw.println("CDMAPhone extends:");
1791         super.dump(fd, pw, args);
1792         pw.println(" mVmNumber=" + mVmNumber);
1793         pw.println(" mCT=" + mCT);
1794         pw.println(" mSST=" + mSST);
1795         pw.println(" mCdmaSSM=" + mCdmaSSM);
1796         pw.println(" mPendingMmis=" + mPendingMmis);
1797         pw.println(" mRuimPhoneBookInterfaceManager=" + mRuimPhoneBookInterfaceManager);
1798         pw.println(" mCdmaSubscriptionSource=" + mCdmaSubscriptionSource);
1799         pw.println(" mSubInfo=" + mSubInfo);
1800         pw.println(" mEriManager=" + mEriManager);
1801         pw.println(" mWakeLock=" + mWakeLock);
1802         pw.println(" mIsPhoneInEcmState=" + mIsPhoneInEcmState);
1803         if (VDBG) pw.println(" mImei=" + mImei);
1804         if (VDBG) pw.println(" mImeiSv=" + mImeiSv);
1805         if (VDBG) pw.println(" mEsn=" + mEsn);
1806         if (VDBG) pw.println(" mMeid=" + mMeid);
1807         pw.println(" mCarrierOtaSpNumSchema=" + mCarrierOtaSpNumSchema);
1808         pw.println(" getCdmaEriIconIndex()=" + getCdmaEriIconIndex());
1809         pw.println(" getCdmaEriIconMode()=" + getCdmaEriIconMode());
1810         pw.println(" getCdmaEriText()=" + getCdmaEriText());
1811         pw.println(" isMinInfoReady()=" + isMinInfoReady());
1812         pw.println(" isCspPlmnEnabled()=" + isCspPlmnEnabled());
1813     }
1814 
1815     @Override
setOperatorBrandOverride(String brand)1816     public boolean setOperatorBrandOverride(String brand) {
1817         if (mUiccController == null) {
1818             return false;
1819         }
1820 
1821         UiccCard card = mUiccController.getUiccCard(getPhoneId());
1822         if (card == null) {
1823             return false;
1824         }
1825 
1826         boolean status = card.setOperatorBrandOverride(brand);
1827 
1828         // Refresh.
1829         if (status) {
1830             IccRecords iccRecords = mIccRecords.get();
1831             if (iccRecords != null) {
1832                 TelephonyManager.from(mContext).setSimOperatorNameForPhone(
1833                         mPhoneId, iccRecords.getServiceProviderName());
1834             }
1835             if (mSST != null) {
1836                 mSST.pollState();
1837             }
1838         }
1839         return status;
1840     }
1841 }
1842