• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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;
18 
19 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_DISABLE;
20 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE;
21 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ERASURE;
22 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_REGISTRATION;
23 import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL;
24 import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL_CONDITIONAL;
25 import static com.android.internal.telephony.CommandsInterface.CF_REASON_BUSY;
26 import static com.android.internal.telephony.CommandsInterface.CF_REASON_NOT_REACHABLE;
27 import static com.android.internal.telephony.CommandsInterface.CF_REASON_NO_REPLY;
28 import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL;
29 import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE;
30 
31 import android.app.ActivityManager;
32 import android.content.BroadcastReceiver;
33 import android.content.ContentValues;
34 import android.content.Context;
35 import android.content.Intent;
36 import android.content.IntentFilter;
37 import android.content.SharedPreferences;
38 import android.database.SQLException;
39 import android.net.Uri;
40 import android.os.AsyncResult;
41 import android.os.Bundle;
42 import android.os.Handler;
43 import android.os.Message;
44 import android.os.PersistableBundle;
45 import android.os.PowerManager;
46 import android.os.Registrant;
47 import android.os.RegistrantList;
48 import android.os.ResultReceiver;
49 import android.os.SystemProperties;
50 import android.os.UserHandle;
51 import android.os.WorkSource;
52 import android.preference.PreferenceManager;
53 import android.provider.Settings;
54 import android.provider.Telephony;
55 import android.telecom.VideoProfile;
56 import android.telephony.CarrierConfigManager;
57 import android.telephony.CellLocation;
58 import android.telephony.ImsiEncryptionInfo;
59 import android.telephony.NetworkScanRequest;
60 import android.telephony.PhoneNumberUtils;
61 import android.telephony.Rlog;
62 import android.telephony.ServiceState;
63 import android.telephony.SubscriptionInfo;
64 import android.telephony.SubscriptionManager;
65 import android.telephony.TelephonyManager;
66 import android.telephony.UssdResponse;
67 import android.telephony.cdma.CdmaCellLocation;
68 import android.text.TextUtils;
69 import android.util.Log;
70 
71 import com.android.ims.ImsManager;
72 import com.android.internal.annotations.VisibleForTesting;
73 import com.android.internal.telephony.cdma.CdmaMmiCode;
74 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
75 import com.android.internal.telephony.cdma.EriManager;
76 import com.android.internal.telephony.gsm.GsmMmiCode;
77 import com.android.internal.telephony.gsm.SuppServiceNotification;
78 import com.android.internal.telephony.test.SimulatedRadioControl;
79 import com.android.internal.telephony.uicc.IccCardProxy;
80 import com.android.internal.telephony.uicc.IccException;
81 import com.android.internal.telephony.uicc.IccRecords;
82 import com.android.internal.telephony.uicc.IccVmNotSupportedException;
83 import com.android.internal.telephony.uicc.IsimRecords;
84 import com.android.internal.telephony.uicc.IsimUiccRecords;
85 import com.android.internal.telephony.uicc.RuimRecords;
86 import com.android.internal.telephony.uicc.SIMRecords;
87 import com.android.internal.telephony.uicc.UiccCard;
88 import com.android.internal.telephony.uicc.UiccCardApplication;
89 import com.android.internal.telephony.uicc.UiccController;
90 
91 import java.io.FileDescriptor;
92 import java.io.PrintWriter;
93 import java.util.ArrayList;
94 import java.util.List;
95 import java.util.regex.Matcher;
96 import java.util.regex.Pattern;
97 
98 /**
99  * {@hide}
100  */
101 public class GsmCdmaPhone extends Phone {
102     // NOTE that LOG_TAG here is "GsmCdma", which means that log messages
103     // from this file will go into the radio log rather than the main
104     // log.  (Use "adb logcat -b radio" to see them.)
105     public static final String LOG_TAG = "GsmCdmaPhone";
106     private static final boolean DBG = true;
107     private static final boolean VDBG = false; /* STOPSHIP if true */
108 
109     //GSM
110     // Key used to read/write voice mail number
111     private static final String VM_NUMBER = "vm_number_key";
112     // Key used to read/write the SIM IMSI used for storing the voice mail
113     private static final String VM_SIM_IMSI = "vm_sim_imsi_key";
114     /** List of Registrants to receive Supplementary Service Notifications. */
115     private RegistrantList mSsnRegistrants = new RegistrantList();
116 
117     //CDMA
118     // Default Emergency Callback Mode exit timer
119     private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000;
120     private static final String VM_NUMBER_CDMA = "vm_number_key_cdma";
121     public static final int RESTART_ECM_TIMER = 0; // restart Ecm timer
122     public static final int CANCEL_ECM_TIMER = 1; // cancel Ecm timer
123     private CdmaSubscriptionSourceManager mCdmaSSM;
124     public int mCdmaSubscriptionSource = CdmaSubscriptionSourceManager.SUBSCRIPTION_SOURCE_UNKNOWN;
125     public EriManager mEriManager;
126     private PowerManager.WakeLock mWakeLock;
127     // mEriFileLoadedRegistrants are informed after the ERI text has been loaded
128     private final RegistrantList mEriFileLoadedRegistrants = new RegistrantList();
129     // mEcmExitRespRegistrant is informed after the phone has been exited
130     private Registrant mEcmExitRespRegistrant;
131     private String mEsn;
132     private String mMeid;
133     // string to define how the carrier specifies its own ota sp number
134     private String mCarrierOtaSpNumSchema;
135 
136     // A runnable which is used to automatically exit from Ecm after a period of time.
137     private Runnable mExitEcmRunnable = new Runnable() {
138         @Override
139         public void run() {
140             exitEmergencyCallbackMode();
141         }
142     };
143     public static final String PROPERTY_CDMA_HOME_OPERATOR_NUMERIC =
144             "ro.cdma.home.operator.numeric";
145 
146     //CDMALTE
147     /** PHONE_TYPE_CDMA_LTE in addition to RuimRecords needs access to SIMRecords and
148      * IsimUiccRecords
149      */
150     private SIMRecords mSimRecords;
151 
152     //Common
153     // Instance Variables
154     private IsimUiccRecords mIsimUiccRecords;
155     public GsmCdmaCallTracker mCT;
156     public ServiceStateTracker mSST;
157     private ArrayList <MmiCode> mPendingMMIs = new ArrayList<MmiCode>();
158     private IccPhoneBookInterfaceManager mIccPhoneBookIntManager;
159     private DeviceStateMonitor mDeviceStateMonitor;
160 
161     private int mPrecisePhoneType;
162 
163     // mEcmTimerResetRegistrants are informed after Ecm timer is canceled or re-started
164     private final RegistrantList mEcmTimerResetRegistrants = new RegistrantList();
165 
166     private String mImei;
167     private String mImeiSv;
168     private String mVmNumber;
169 
170     // Create Cfu (Call forward unconditional) so that dialing number &
171     // mOnComplete (Message object passed by client) can be packed &
172     // given as a single Cfu object as user data to RIL.
173     private static class Cfu {
174         final String mSetCfNumber;
175         final Message mOnComplete;
176 
Cfu(String cfNumber, Message onComplete)177         Cfu(String cfNumber, Message onComplete) {
178             mSetCfNumber = cfNumber;
179             mOnComplete = onComplete;
180         }
181     }
182 
183     private IccSmsInterfaceManager mIccSmsInterfaceManager;
184     private IccCardProxy mIccCardProxy;
185 
186     private boolean mResetModemOnRadioTechnologyChange = false;
187 
188     private int mRilVersion;
189     private boolean mBroadcastEmergencyCallStateChanges = false;
190     private CarrierKeyDownloadManager mCDM;
191     // Constructors
192 
GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId, int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory)193     public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId,
194                         int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory) {
195         this(context, ci, notifier, false, phoneId, precisePhoneType, telephonyComponentFactory);
196     }
197 
GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode, int phoneId, int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory)198     public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
199                         boolean unitTestMode, int phoneId, int precisePhoneType,
200                         TelephonyComponentFactory telephonyComponentFactory) {
201         super(precisePhoneType == PhoneConstants.PHONE_TYPE_GSM ? "GSM" : "CDMA",
202                 notifier, context, ci, unitTestMode, phoneId, telephonyComponentFactory);
203 
204         // phone type needs to be set before other initialization as other objects rely on it
205         mPrecisePhoneType = precisePhoneType;
206         initOnce(ci);
207         initRatSpecific(precisePhoneType);
208         // CarrierSignalAgent uses CarrierActionAgent in construction so it needs to be created
209         // after CarrierActionAgent.
210         mCarrierActionAgent = mTelephonyComponentFactory.makeCarrierActionAgent(this);
211         mCarrierSignalAgent = mTelephonyComponentFactory.makeCarrierSignalAgent(this);
212         mSST = mTelephonyComponentFactory.makeServiceStateTracker(this, this.mCi);
213         // DcTracker uses SST so needs to be created after it is instantiated
214         mDcTracker = mTelephonyComponentFactory.makeDcTracker(this);
215         mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
216         mDeviceStateMonitor = mTelephonyComponentFactory.makeDeviceStateMonitor(this);
217         logd("GsmCdmaPhone: constructor: sub = " + mPhoneId);
218     }
219 
220     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
221         @Override
222         public void onReceive(Context context, Intent intent) {
223             Rlog.d(LOG_TAG, "mBroadcastReceiver: action " + intent.getAction());
224             if (intent.getAction().equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
225                 sendMessage(obtainMessage(EVENT_CARRIER_CONFIG_CHANGED));
226             }
227         }
228     };
229 
initOnce(CommandsInterface ci)230     private void initOnce(CommandsInterface ci) {
231         if (ci instanceof SimulatedRadioControl) {
232             mSimulatedRadioControl = (SimulatedRadioControl) ci;
233         }
234 
235         mCT = mTelephonyComponentFactory.makeGsmCdmaCallTracker(this);
236         mIccPhoneBookIntManager = mTelephonyComponentFactory.makeIccPhoneBookInterfaceManager(this);
237         PowerManager pm
238                 = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
239         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
240         mIccSmsInterfaceManager = mTelephonyComponentFactory.makeIccSmsInterfaceManager(this);
241         mIccCardProxy = mTelephonyComponentFactory.makeIccCardProxy(mContext, mCi, mPhoneId);
242 
243         mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
244         mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
245         mCi.registerForOn(this, EVENT_RADIO_ON, null);
246         mCi.setOnSuppServiceNotification(this, EVENT_SSN, null);
247 
248         //GSM
249         mCi.setOnUSSD(this, EVENT_USSD, null);
250         mCi.setOnSs(this, EVENT_SS, null);
251 
252         //CDMA
253         mCdmaSSM = mTelephonyComponentFactory.getCdmaSubscriptionSourceManagerInstance(mContext,
254                 mCi, this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
255         mEriManager = mTelephonyComponentFactory.makeEriManager(this, mContext,
256                 EriManager.ERI_FROM_XML);
257         mCi.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
258         mCi.registerForExitEmergencyCallbackMode(this, EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE,
259                 null);
260         mCi.registerForModemReset(this, EVENT_MODEM_RESET, null);
261         // get the string that specifies the carrier OTA Sp number
262         mCarrierOtaSpNumSchema = TelephonyManager.from(mContext).getOtaSpNumberSchemaForPhone(
263                 getPhoneId(), "");
264 
265         mResetModemOnRadioTechnologyChange = SystemProperties.getBoolean(
266                 TelephonyProperties.PROPERTY_RESET_ON_RADIO_TECH_CHANGE, false);
267 
268         mCi.registerForRilConnected(this, EVENT_RIL_CONNECTED, null);
269         mCi.registerForVoiceRadioTechChanged(this, EVENT_VOICE_RADIO_TECH_CHANGED, null);
270         mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(
271                 CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
272         mCDM = new CarrierKeyDownloadManager(this);
273     }
274 
initRatSpecific(int precisePhoneType)275     private void initRatSpecific(int precisePhoneType) {
276         mPendingMMIs.clear();
277         mIccPhoneBookIntManager.updateIccRecords(null);
278         mEsn = null;
279         mMeid = null;
280 
281         mPrecisePhoneType = precisePhoneType;
282 
283         TelephonyManager tm = TelephonyManager.from(mContext);
284         if (isPhoneTypeGsm()) {
285             mCi.setPhoneType(PhoneConstants.PHONE_TYPE_GSM);
286             tm.setPhoneType(getPhoneId(), PhoneConstants.PHONE_TYPE_GSM);
287             mIccCardProxy.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS);
288         } else {
289             mCdmaSubscriptionSource = CdmaSubscriptionSourceManager.SUBSCRIPTION_SOURCE_UNKNOWN;
290             // This is needed to handle phone process crashes
291             mIsPhoneInEcmState = getInEcmMode();
292             if (mIsPhoneInEcmState) {
293                 // Send a message which will invoke handleExitEmergencyCallbackMode
294                 mCi.exitEmergencyCallbackMode(
295                         obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
296             }
297 
298             mCi.setPhoneType(PhoneConstants.PHONE_TYPE_CDMA);
299             tm.setPhoneType(getPhoneId(), PhoneConstants.PHONE_TYPE_CDMA);
300             mIccCardProxy.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT);
301             // Sets operator properties by retrieving from build-time system property
302             String operatorAlpha = SystemProperties.get("ro.cdma.home.operator.alpha");
303             String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC);
304             logd("init: operatorAlpha='" + operatorAlpha
305                     + "' operatorNumeric='" + operatorNumeric + "'");
306             if (mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP) ==
307                     null || isPhoneTypeCdmaLte()) {
308                 if (!TextUtils.isEmpty(operatorAlpha)) {
309                     logd("init: set 'gsm.sim.operator.alpha' to operator='" + operatorAlpha + "'");
310                     tm.setSimOperatorNameForPhone(mPhoneId, operatorAlpha);
311                 }
312                 if (!TextUtils.isEmpty(operatorNumeric)) {
313                     logd("init: set 'gsm.sim.operator.numeric' to operator='" + operatorNumeric +
314                             "'");
315                     logd("update icc_operator_numeric=" + operatorNumeric);
316                     tm.setSimOperatorNumericForPhone(mPhoneId, operatorNumeric);
317 
318                     SubscriptionController.getInstance().setMccMnc(operatorNumeric, getSubId());
319                     // Sets iso country property by retrieving from build-time system property
320                     setIsoCountryProperty(operatorNumeric);
321                     // Updates MCC MNC device configuration information
322                     logd("update mccmnc=" + operatorNumeric);
323                     MccTable.updateMccMncConfiguration(mContext, operatorNumeric, false);
324                 }
325             }
326 
327             // Sets current entry in the telephony carrier table
328             updateCurrentCarrierInProvider(operatorNumeric);
329         }
330     }
331 
332     //CDMA
333     /**
334      * Sets PROPERTY_ICC_OPERATOR_ISO_COUNTRY property
335      *
336      */
setIsoCountryProperty(String operatorNumeric)337     private void setIsoCountryProperty(String operatorNumeric) {
338         TelephonyManager tm = TelephonyManager.from(mContext);
339         if (TextUtils.isEmpty(operatorNumeric)) {
340             logd("setIsoCountryProperty: clear 'gsm.sim.operator.iso-country'");
341             tm.setSimCountryIsoForPhone(mPhoneId, "");
342         } else {
343             String iso = "";
344             try {
345                 iso = MccTable.countryCodeForMcc(Integer.parseInt(
346                         operatorNumeric.substring(0,3)));
347             } catch (NumberFormatException ex) {
348                 Rlog.e(LOG_TAG, "setIsoCountryProperty: countryCodeForMcc error", ex);
349             } catch (StringIndexOutOfBoundsException ex) {
350                 Rlog.e(LOG_TAG, "setIsoCountryProperty: countryCodeForMcc error", ex);
351             }
352 
353             logd("setIsoCountryProperty: set 'gsm.sim.operator.iso-country' to iso=" + iso);
354             tm.setSimCountryIsoForPhone(mPhoneId, iso);
355         }
356     }
357 
isPhoneTypeGsm()358     public boolean isPhoneTypeGsm() {
359         return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_GSM;
360     }
361 
isPhoneTypeCdma()362     public boolean isPhoneTypeCdma() {
363         return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_CDMA;
364     }
365 
isPhoneTypeCdmaLte()366     public boolean isPhoneTypeCdmaLte() {
367         return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_CDMA_LTE;
368     }
369 
switchPhoneType(int precisePhoneType)370     private void switchPhoneType(int precisePhoneType) {
371         removeCallbacks(mExitEcmRunnable);
372 
373         initRatSpecific(precisePhoneType);
374 
375         mSST.updatePhoneType();
376         setPhoneName(precisePhoneType == PhoneConstants.PHONE_TYPE_GSM ? "GSM" : "CDMA");
377         onUpdateIccAvailability();
378         mCT.updatePhoneType();
379 
380         CommandsInterface.RadioState radioState = mCi.getRadioState();
381         if (radioState.isAvailable()) {
382             handleRadioAvailable();
383             if (radioState.isOn()) {
384                 handleRadioOn();
385             }
386         }
387         if (!radioState.isAvailable() || !radioState.isOn()) {
388             handleRadioOffOrNotAvailable();
389         }
390     }
391 
392     @Override
finalize()393     protected void finalize() {
394         if(DBG) logd("GsmCdmaPhone finalized");
395         if (mWakeLock != null && mWakeLock.isHeld()) {
396             Rlog.e(LOG_TAG, "UNEXPECTED; mWakeLock is held when finalizing.");
397             mWakeLock.release();
398         }
399     }
400 
401     @Override
getServiceState()402     public ServiceState getServiceState() {
403         if (mSST == null || mSST.mSS.getState() != ServiceState.STATE_IN_SERVICE) {
404             if (mImsPhone != null) {
405                 return ServiceState.mergeServiceStates(
406                         (mSST == null) ? new ServiceState() : mSST.mSS,
407                         mImsPhone.getServiceState());
408             }
409         }
410 
411         if (mSST != null) {
412             return mSST.mSS;
413         } else {
414             // avoid potential NPE in EmergencyCallHelper during Phone switch
415             return new ServiceState();
416         }
417     }
418 
419     @Override
getCellLocation(WorkSource workSource)420     public CellLocation getCellLocation(WorkSource workSource) {
421         if (isPhoneTypeGsm()) {
422             return mSST.getCellLocation(workSource);
423         } else {
424             CdmaCellLocation loc = (CdmaCellLocation)mSST.mCellLoc;
425 
426             int mode = Settings.Secure.getInt(getContext().getContentResolver(),
427                     Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF);
428             if (mode == Settings.Secure.LOCATION_MODE_OFF) {
429                 // clear lat/long values for location privacy
430                 CdmaCellLocation privateLoc = new CdmaCellLocation();
431                 privateLoc.setCellLocationData(loc.getBaseStationId(),
432                         CdmaCellLocation.INVALID_LAT_LONG,
433                         CdmaCellLocation.INVALID_LAT_LONG,
434                         loc.getSystemId(), loc.getNetworkId());
435                 loc = privateLoc;
436             }
437             return loc;
438         }
439     }
440 
441     @Override
getState()442     public PhoneConstants.State getState() {
443         if (mImsPhone != null) {
444             PhoneConstants.State imsState = mImsPhone.getState();
445             if (imsState != PhoneConstants.State.IDLE) {
446                 return imsState;
447             }
448         }
449 
450         return mCT.mState;
451     }
452 
453     @Override
getPhoneType()454     public int getPhoneType() {
455         if (mPrecisePhoneType == PhoneConstants.PHONE_TYPE_GSM) {
456             return PhoneConstants.PHONE_TYPE_GSM;
457         } else {
458             return PhoneConstants.PHONE_TYPE_CDMA;
459         }
460     }
461 
462     @Override
getServiceStateTracker()463     public ServiceStateTracker getServiceStateTracker() {
464         return mSST;
465     }
466 
467     @Override
getCallTracker()468     public CallTracker getCallTracker() {
469         return mCT;
470     }
471 
472     @Override
updateVoiceMail()473     public void updateVoiceMail() {
474         if (isPhoneTypeGsm()) {
475             int countVoiceMessages = 0;
476             IccRecords r = mIccRecords.get();
477             if (r != null) {
478                 // get voice mail count from SIM
479                 countVoiceMessages = r.getVoiceMessageCount();
480             }
481             if (countVoiceMessages == IccRecords.DEFAULT_VOICE_MESSAGE_COUNT) {
482                 countVoiceMessages = getStoredVoiceMessageCount();
483             }
484             logd("updateVoiceMail countVoiceMessages = " + countVoiceMessages
485                     + " subId " + getSubId());
486             setVoiceMessageCount(countVoiceMessages);
487         } else {
488             setVoiceMessageCount(getStoredVoiceMessageCount());
489         }
490     }
491 
492     @Override
493     public List<? extends MmiCode>
getPendingMmiCodes()494     getPendingMmiCodes() {
495         return mPendingMMIs;
496     }
497 
498     @Override
getDataConnectionState(String apnType)499     public PhoneConstants.DataState getDataConnectionState(String apnType) {
500         PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED;
501 
502         if (mSST == null) {
503             // Radio Technology Change is ongoning, dispose() and removeReferences() have
504             // already been called
505 
506             ret = PhoneConstants.DataState.DISCONNECTED;
507         } else if (mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE
508                 && (isPhoneTypeCdma() ||
509                 (isPhoneTypeGsm() && !apnType.equals(PhoneConstants.APN_TYPE_EMERGENCY)))) {
510             // If we're out of service, open TCP sockets may still work
511             // but no data will flow
512 
513             // Emergency APN is available even in Out Of Service
514             // Pass the actual State of EPDN
515 
516             ret = PhoneConstants.DataState.DISCONNECTED;
517         } else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */
518             switch (mDcTracker.getState(apnType)) {
519                 case RETRYING:
520                 case FAILED:
521                 case IDLE:
522                     ret = PhoneConstants.DataState.DISCONNECTED;
523                 break;
524 
525                 case CONNECTED:
526                 case DISCONNECTING:
527                     if ( mCT.mState != PhoneConstants.State.IDLE
528                             && !mSST.isConcurrentVoiceAndDataAllowed()) {
529                         ret = PhoneConstants.DataState.SUSPENDED;
530                     } else {
531                         ret = PhoneConstants.DataState.CONNECTED;
532                     }
533                 break;
534 
535                 case CONNECTING:
536                 case SCANNING:
537                     ret = PhoneConstants.DataState.CONNECTING;
538                 break;
539             }
540         }
541 
542         logd("getDataConnectionState apnType=" + apnType + " ret=" + ret);
543         return ret;
544     }
545 
546     @Override
getDataActivityState()547     public DataActivityState getDataActivityState() {
548         DataActivityState ret = DataActivityState.NONE;
549 
550         if (mSST.getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) {
551             switch (mDcTracker.getActivity()) {
552                 case DATAIN:
553                     ret = DataActivityState.DATAIN;
554                 break;
555 
556                 case DATAOUT:
557                     ret = DataActivityState.DATAOUT;
558                 break;
559 
560                 case DATAINANDOUT:
561                     ret = DataActivityState.DATAINANDOUT;
562                 break;
563 
564                 case DORMANT:
565                     ret = DataActivityState.DORMANT;
566                 break;
567 
568                 default:
569                     ret = DataActivityState.NONE;
570                 break;
571             }
572         }
573 
574         return ret;
575     }
576 
577     /**
578      * Notify any interested party of a Phone state change
579      * {@link com.android.internal.telephony.PhoneConstants.State}
580      */
notifyPhoneStateChanged()581     public void notifyPhoneStateChanged() {
582         mNotifier.notifyPhoneState(this);
583     }
584 
585     /**
586      * Notify registrants of a change in the call state. This notifies changes in
587      * {@link com.android.internal.telephony.Call.State}. Use this when changes
588      * in the precise call state are needed, else use notifyPhoneStateChanged.
589      */
notifyPreciseCallStateChanged()590     public void notifyPreciseCallStateChanged() {
591         /* we'd love it if this was package-scoped*/
592         super.notifyPreciseCallStateChangedP();
593     }
594 
notifyNewRingingConnection(Connection c)595     public void notifyNewRingingConnection(Connection c) {
596         super.notifyNewRingingConnectionP(c);
597     }
598 
notifyDisconnect(Connection cn)599     public void notifyDisconnect(Connection cn) {
600         mDisconnectRegistrants.notifyResult(cn);
601 
602         mNotifier.notifyDisconnectCause(cn.getDisconnectCause(), cn.getPreciseDisconnectCause());
603     }
604 
notifyUnknownConnection(Connection cn)605     public void notifyUnknownConnection(Connection cn) {
606         super.notifyUnknownConnectionP(cn);
607     }
608 
609     @Override
isInEmergencyCall()610     public boolean isInEmergencyCall() {
611         if (isPhoneTypeGsm()) {
612             return false;
613         } else {
614             return mCT.isInEmergencyCall();
615         }
616     }
617 
618     @Override
setIsInEmergencyCall()619     protected void setIsInEmergencyCall() {
620         if (!isPhoneTypeGsm()) {
621             mCT.setIsInEmergencyCall();
622         }
623     }
624 
625     //CDMA
sendEmergencyCallbackModeChange()626     private void sendEmergencyCallbackModeChange(){
627         //Send an Intent
628         Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
629         intent.putExtra(PhoneConstants.PHONE_IN_ECM_STATE, isInEcm());
630         SubscriptionManager.putPhoneIdAndSubIdExtra(intent, getPhoneId());
631         ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
632         if (DBG) logd("sendEmergencyCallbackModeChange");
633     }
634 
635     @Override
sendEmergencyCallStateChange(boolean callActive)636     public void sendEmergencyCallStateChange(boolean callActive) {
637         if (mBroadcastEmergencyCallStateChanges) {
638             Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED);
639             intent.putExtra(PhoneConstants.PHONE_IN_EMERGENCY_CALL, callActive);
640             SubscriptionManager.putPhoneIdAndSubIdExtra(intent, getPhoneId());
641             ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
642             if (DBG) Rlog.d(LOG_TAG, "sendEmergencyCallStateChange: callActive " + callActive);
643         }
644     }
645 
646     @Override
setBroadcastEmergencyCallStateChanges(boolean broadcast)647     public void setBroadcastEmergencyCallStateChanges(boolean broadcast) {
648         mBroadcastEmergencyCallStateChanges = broadcast;
649     }
650 
notifySuppServiceFailed(SuppService code)651     public void notifySuppServiceFailed(SuppService code) {
652         mSuppServiceFailedRegistrants.notifyResult(code);
653     }
654 
notifyServiceStateChanged(ServiceState ss)655     public void notifyServiceStateChanged(ServiceState ss) {
656         super.notifyServiceStateChangedP(ss);
657     }
658 
notifyLocationChanged()659     public void notifyLocationChanged() {
660         mNotifier.notifyCellLocation(this);
661     }
662 
663     @Override
notifyCallForwardingIndicator()664     public void notifyCallForwardingIndicator() {
665         mNotifier.notifyCallForwardingChanged(this);
666     }
667 
668     // override for allowing access from other classes of this package
669     /**
670      * {@inheritDoc}
671      */
672     @Override
setSystemProperty(String property, String value)673     public void setSystemProperty(String property, String value) {
674         if (getUnitTestMode()) {
675             return;
676         }
677         if (isPhoneTypeGsm() || isPhoneTypeCdmaLte()) {
678             TelephonyManager.setTelephonyProperty(mPhoneId, property, value);
679         } else {
680             super.setSystemProperty(property, value);
681         }
682     }
683 
684     @Override
registerForSuppServiceNotification( Handler h, int what, Object obj)685     public void registerForSuppServiceNotification(
686             Handler h, int what, Object obj) {
687         mSsnRegistrants.addUnique(h, what, obj);
688         if (mSsnRegistrants.size() == 1) mCi.setSuppServiceNotifications(true, null);
689     }
690 
691     @Override
unregisterForSuppServiceNotification(Handler h)692     public void unregisterForSuppServiceNotification(Handler h) {
693         mSsnRegistrants.remove(h);
694         if (mSsnRegistrants.size() == 0) mCi.setSuppServiceNotifications(false, null);
695     }
696 
697     @Override
registerForSimRecordsLoaded(Handler h, int what, Object obj)698     public void registerForSimRecordsLoaded(Handler h, int what, Object obj) {
699         mSimRecordsLoadedRegistrants.addUnique(h, what, obj);
700     }
701 
702     @Override
unregisterForSimRecordsLoaded(Handler h)703     public void unregisterForSimRecordsLoaded(Handler h) {
704         mSimRecordsLoadedRegistrants.remove(h);
705     }
706 
707     @Override
acceptCall(int videoState)708     public void acceptCall(int videoState) throws CallStateException {
709         Phone imsPhone = mImsPhone;
710         if ( imsPhone != null && imsPhone.getRingingCall().isRinging() ) {
711             imsPhone.acceptCall(videoState);
712         } else {
713             mCT.acceptCall();
714         }
715     }
716 
717     @Override
rejectCall()718     public void rejectCall() throws CallStateException {
719         mCT.rejectCall();
720     }
721 
722     @Override
switchHoldingAndActive()723     public void switchHoldingAndActive() throws CallStateException {
724         mCT.switchWaitingOrHoldingAndActive();
725     }
726 
727     @Override
getIccSerialNumber()728     public String getIccSerialNumber() {
729         IccRecords r = mIccRecords.get();
730         if (!isPhoneTypeGsm() && r == null) {
731             // to get ICCID form SIMRecords because it is on MF.
732             r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP);
733         }
734         return (r != null) ? r.getIccId() : null;
735     }
736 
737     @Override
getFullIccSerialNumber()738     public String getFullIccSerialNumber() {
739         IccRecords r = mIccRecords.get();
740         if (!isPhoneTypeGsm() && r == null) {
741             // to get ICCID form SIMRecords because it is on MF.
742             r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP);
743         }
744         return (r != null) ? r.getFullIccId() : null;
745     }
746 
747     @Override
canConference()748     public boolean canConference() {
749         if (mImsPhone != null && mImsPhone.canConference()) {
750             return true;
751         }
752         if (isPhoneTypeGsm()) {
753             return mCT.canConference();
754         } else {
755             loge("canConference: not possible in CDMA");
756             return false;
757         }
758     }
759 
760     @Override
conference()761     public void conference() {
762         if (mImsPhone != null && mImsPhone.canConference()) {
763             logd("conference() - delegated to IMS phone");
764             try {
765                 mImsPhone.conference();
766             } catch (CallStateException e) {
767                 loge(e.toString());
768             }
769             return;
770         }
771         if (isPhoneTypeGsm()) {
772             mCT.conference();
773         } else {
774             // three way calls in CDMA will be handled by feature codes
775             loge("conference: not possible in CDMA");
776         }
777     }
778 
779     @Override
enableEnhancedVoicePrivacy(boolean enable, Message onComplete)780     public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
781         if (isPhoneTypeGsm()) {
782             loge("enableEnhancedVoicePrivacy: not expected on GSM");
783         } else {
784             mCi.setPreferredVoicePrivacy(enable, onComplete);
785         }
786     }
787 
788     @Override
getEnhancedVoicePrivacy(Message onComplete)789     public void getEnhancedVoicePrivacy(Message onComplete) {
790         if (isPhoneTypeGsm()) {
791             loge("getEnhancedVoicePrivacy: not expected on GSM");
792         } else {
793             mCi.getPreferredVoicePrivacy(onComplete);
794         }
795     }
796 
797     @Override
clearDisconnected()798     public void clearDisconnected() {
799         mCT.clearDisconnected();
800     }
801 
802     @Override
canTransfer()803     public boolean canTransfer() {
804         if (isPhoneTypeGsm()) {
805             return mCT.canTransfer();
806         } else {
807             loge("canTransfer: not possible in CDMA");
808             return false;
809         }
810     }
811 
812     @Override
explicitCallTransfer()813     public void explicitCallTransfer() {
814         if (isPhoneTypeGsm()) {
815             mCT.explicitCallTransfer();
816         } else {
817             loge("explicitCallTransfer: not possible in CDMA");
818         }
819     }
820 
821     @Override
getForegroundCall()822     public GsmCdmaCall getForegroundCall() {
823         return mCT.mForegroundCall;
824     }
825 
826     @Override
getBackgroundCall()827     public GsmCdmaCall getBackgroundCall() {
828         return mCT.mBackgroundCall;
829     }
830 
831     @Override
getRingingCall()832     public Call getRingingCall() {
833         Phone imsPhone = mImsPhone;
834         // It returns the ringing call of ImsPhone if the ringing call of GSMPhone isn't ringing.
835         // In CallManager.registerPhone(), it always registers ringing call of ImsPhone, because
836         // the ringing call of GSMPhone isn't ringing. Consequently, it can't answer GSM call
837         // successfully by invoking TelephonyManager.answerRingingCall() since the implementation
838         // in PhoneInterfaceManager.answerRingingCallInternal() could not get the correct ringing
839         // call from CallManager. So we check the ringing call state of imsPhone first as
840         // accpetCall() does.
841         if ( imsPhone != null && imsPhone.getRingingCall().isRinging()) {
842             return imsPhone.getRingingCall();
843         }
844         return mCT.mRingingCall;
845     }
846 
handleCallDeflectionIncallSupplementaryService( String dialString)847     private boolean handleCallDeflectionIncallSupplementaryService(
848             String dialString) {
849         if (dialString.length() > 1) {
850             return false;
851         }
852 
853         if (getRingingCall().getState() != GsmCdmaCall.State.IDLE) {
854             if (DBG) logd("MmiCode 0: rejectCall");
855             try {
856                 mCT.rejectCall();
857             } catch (CallStateException e) {
858                 if (DBG) Rlog.d(LOG_TAG,
859                         "reject failed", e);
860                 notifySuppServiceFailed(Phone.SuppService.REJECT);
861             }
862         } else if (getBackgroundCall().getState() != GsmCdmaCall.State.IDLE) {
863             if (DBG) logd("MmiCode 0: hangupWaitingOrBackground");
864             mCT.hangupWaitingOrBackground();
865         }
866 
867         return true;
868     }
869 
870     //GSM
handleCallWaitingIncallSupplementaryService(String dialString)871     private boolean handleCallWaitingIncallSupplementaryService(String dialString) {
872         int len = dialString.length();
873 
874         if (len > 2) {
875             return false;
876         }
877 
878         GsmCdmaCall call = getForegroundCall();
879 
880         try {
881             if (len > 1) {
882                 char ch = dialString.charAt(1);
883                 int callIndex = ch - '0';
884 
885                 if (callIndex >= 1 && callIndex <= GsmCdmaCallTracker.MAX_CONNECTIONS_GSM) {
886                     if (DBG) logd("MmiCode 1: hangupConnectionByIndex " + callIndex);
887                     mCT.hangupConnectionByIndex(call, callIndex);
888                 }
889             } else {
890                 if (call.getState() != GsmCdmaCall.State.IDLE) {
891                     if (DBG) logd("MmiCode 1: hangup foreground");
892                     //mCT.hangupForegroundResumeBackground();
893                     mCT.hangup(call);
894                 } else {
895                     if (DBG) logd("MmiCode 1: switchWaitingOrHoldingAndActive");
896                     mCT.switchWaitingOrHoldingAndActive();
897                 }
898             }
899         } catch (CallStateException e) {
900             if (DBG) Rlog.d(LOG_TAG,
901                     "hangup failed", e);
902             notifySuppServiceFailed(Phone.SuppService.HANGUP);
903         }
904 
905         return true;
906     }
907 
handleCallHoldIncallSupplementaryService(String dialString)908     private boolean handleCallHoldIncallSupplementaryService(String dialString) {
909         int len = dialString.length();
910 
911         if (len > 2) {
912             return false;
913         }
914 
915         GsmCdmaCall call = getForegroundCall();
916 
917         if (len > 1) {
918             try {
919                 char ch = dialString.charAt(1);
920                 int callIndex = ch - '0';
921                 GsmCdmaConnection conn = mCT.getConnectionByIndex(call, callIndex);
922 
923                 // GsmCdma index starts at 1, up to 5 connections in a call,
924                 if (conn != null && callIndex >= 1 && callIndex <= GsmCdmaCallTracker.MAX_CONNECTIONS_GSM) {
925                     if (DBG) logd("MmiCode 2: separate call " + callIndex);
926                     mCT.separate(conn);
927                 } else {
928                     if (DBG) logd("separate: invalid call index " + callIndex);
929                     notifySuppServiceFailed(Phone.SuppService.SEPARATE);
930                 }
931             } catch (CallStateException e) {
932                 if (DBG) Rlog.d(LOG_TAG, "separate failed", e);
933                 notifySuppServiceFailed(Phone.SuppService.SEPARATE);
934             }
935         } else {
936             try {
937                 if (getRingingCall().getState() != GsmCdmaCall.State.IDLE) {
938                     if (DBG) logd("MmiCode 2: accept ringing call");
939                     mCT.acceptCall();
940                 } else {
941                     if (DBG) logd("MmiCode 2: switchWaitingOrHoldingAndActive");
942                     mCT.switchWaitingOrHoldingAndActive();
943                 }
944             } catch (CallStateException e) {
945                 if (DBG) Rlog.d(LOG_TAG, "switch failed", e);
946                 notifySuppServiceFailed(Phone.SuppService.SWITCH);
947             }
948         }
949 
950         return true;
951     }
952 
handleMultipartyIncallSupplementaryService(String dialString)953     private boolean handleMultipartyIncallSupplementaryService(String dialString) {
954         if (dialString.length() > 1) {
955             return false;
956         }
957 
958         if (DBG) logd("MmiCode 3: merge calls");
959         conference();
960         return true;
961     }
962 
handleEctIncallSupplementaryService(String dialString)963     private boolean handleEctIncallSupplementaryService(String dialString) {
964 
965         int len = dialString.length();
966 
967         if (len != 1) {
968             return false;
969         }
970 
971         if (DBG) logd("MmiCode 4: explicit call transfer");
972         explicitCallTransfer();
973         return true;
974     }
975 
handleCcbsIncallSupplementaryService(String dialString)976     private boolean handleCcbsIncallSupplementaryService(String dialString) {
977         if (dialString.length() > 1) {
978             return false;
979         }
980 
981         Rlog.i(LOG_TAG, "MmiCode 5: CCBS not supported!");
982         // Treat it as an "unknown" service.
983         notifySuppServiceFailed(Phone.SuppService.UNKNOWN);
984         return true;
985     }
986 
987     @Override
handleInCallMmiCommands(String dialString)988     public boolean handleInCallMmiCommands(String dialString) throws CallStateException {
989         if (!isPhoneTypeGsm()) {
990             loge("method handleInCallMmiCommands is NOT supported in CDMA!");
991             return false;
992         }
993 
994         Phone imsPhone = mImsPhone;
995         if (imsPhone != null
996                 && imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE) {
997             return imsPhone.handleInCallMmiCommands(dialString);
998         }
999 
1000         if (!isInCall()) {
1001             return false;
1002         }
1003 
1004         if (TextUtils.isEmpty(dialString)) {
1005             return false;
1006         }
1007 
1008         boolean result = false;
1009         char ch = dialString.charAt(0);
1010         switch (ch) {
1011             case '0':
1012                 result = handleCallDeflectionIncallSupplementaryService(dialString);
1013                 break;
1014             case '1':
1015                 result = handleCallWaitingIncallSupplementaryService(dialString);
1016                 break;
1017             case '2':
1018                 result = handleCallHoldIncallSupplementaryService(dialString);
1019                 break;
1020             case '3':
1021                 result = handleMultipartyIncallSupplementaryService(dialString);
1022                 break;
1023             case '4':
1024                 result = handleEctIncallSupplementaryService(dialString);
1025                 break;
1026             case '5':
1027                 result = handleCcbsIncallSupplementaryService(dialString);
1028                 break;
1029             default:
1030                 break;
1031         }
1032 
1033         return result;
1034     }
1035 
isInCall()1036     public boolean isInCall() {
1037         GsmCdmaCall.State foregroundCallState = getForegroundCall().getState();
1038         GsmCdmaCall.State backgroundCallState = getBackgroundCall().getState();
1039         GsmCdmaCall.State ringingCallState = getRingingCall().getState();
1040 
1041        return (foregroundCallState.isAlive() ||
1042                 backgroundCallState.isAlive() ||
1043                 ringingCallState.isAlive());
1044     }
1045 
1046     @Override
dial(String dialString, int videoState)1047     public Connection dial(String dialString, int videoState) throws CallStateException {
1048         return dial(dialString, null, videoState, null);
1049     }
1050 
1051     @Override
dial(String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)1052     public Connection dial(String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)
1053             throws CallStateException {
1054         if (!isPhoneTypeGsm() && uusInfo != null) {
1055             throw new CallStateException("Sending UUS information NOT supported in CDMA!");
1056         }
1057 
1058         boolean isEmergency = PhoneNumberUtils.isEmergencyNumber(getSubId(), dialString);
1059         Phone imsPhone = mImsPhone;
1060 
1061         CarrierConfigManager configManager =
1062                 (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
1063         boolean alwaysTryImsForEmergencyCarrierConfig = configManager.getConfigForSubId(getSubId())
1064                 .getBoolean(CarrierConfigManager.KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL);
1065 
1066         boolean imsUseEnabled = isImsUseEnabled()
1067                  && imsPhone != null
1068                  && (imsPhone.isVolteEnabled() || imsPhone.isWifiCallingEnabled() ||
1069                  (imsPhone.isVideoEnabled() && VideoProfile.isVideo(videoState)))
1070                  && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE);
1071 
1072         boolean useImsForEmergency = imsPhone != null
1073                 && isEmergency
1074                 && alwaysTryImsForEmergencyCarrierConfig
1075                 && ImsManager.isNonTtyOrTtyOnVolteEnabled(mContext)
1076                 && imsPhone.isImsAvailable();
1077 
1078         String dialPart = PhoneNumberUtils.extractNetworkPortionAlt(PhoneNumberUtils.
1079                 stripSeparators(dialString));
1080         boolean isUt = (dialPart.startsWith("*") || dialPart.startsWith("#"))
1081                 && dialPart.endsWith("#");
1082 
1083         boolean useImsForUt = imsPhone != null && imsPhone.isUtEnabled();
1084 
1085         if (DBG) {
1086             logd("imsUseEnabled=" + imsUseEnabled
1087                     + ", useImsForEmergency=" + useImsForEmergency
1088                     + ", useImsForUt=" + useImsForUt
1089                     + ", isUt=" + isUt
1090                     + ", imsPhone=" + imsPhone
1091                     + ", imsPhone.isVolteEnabled()="
1092                     + ((imsPhone != null) ? imsPhone.isVolteEnabled() : "N/A")
1093                     + ", imsPhone.isVowifiEnabled()="
1094                     + ((imsPhone != null) ? imsPhone.isWifiCallingEnabled() : "N/A")
1095                     + ", imsPhone.isVideoEnabled()="
1096                     + ((imsPhone != null) ? imsPhone.isVideoEnabled() : "N/A")
1097                     + ", imsPhone.getServiceState().getState()="
1098                     + ((imsPhone != null) ? imsPhone.getServiceState().getState() : "N/A"));
1099         }
1100 
1101         Phone.checkWfcWifiOnlyModeBeforeDial(mImsPhone, mContext);
1102 
1103         if ((imsUseEnabled && (!isUt || useImsForUt)) || useImsForEmergency) {
1104             try {
1105                 if (DBG) logd("Trying IMS PS call");
1106                 return imsPhone.dial(dialString, uusInfo, videoState, intentExtras);
1107             } catch (CallStateException e) {
1108                 if (DBG) logd("IMS PS call exception " + e +
1109                         "imsUseEnabled =" + imsUseEnabled + ", imsPhone =" + imsPhone);
1110                 // Do not throw a CallStateException and instead fall back to Circuit switch
1111                 // for emergency calls and MMI codes.
1112                 if (Phone.CS_FALLBACK.equals(e.getMessage()) || isEmergency) {
1113                     logi("IMS call failed with Exception: " + e.getMessage() + ". Falling back "
1114                             + "to CS.");
1115                 } else {
1116                     CallStateException ce = new CallStateException(e.getMessage());
1117                     ce.setStackTrace(e.getStackTrace());
1118                     throw ce;
1119                 }
1120             }
1121         }
1122 
1123         if (mSST != null && mSST.mSS.getState() == ServiceState.STATE_OUT_OF_SERVICE
1124                 && mSST.mSS.getDataRegState() != ServiceState.STATE_IN_SERVICE && !isEmergency) {
1125             throw new CallStateException("cannot dial in current state");
1126         }
1127         // Check non-emergency voice CS call - shouldn't dial when POWER_OFF
1128         if (mSST != null && mSST.mSS.getState() == ServiceState.STATE_POWER_OFF /* CS POWER_OFF */
1129                 && !VideoProfile.isVideo(videoState) /* voice call */
1130                 && !isEmergency /* non-emergency call */) {
1131             throw new CallStateException(
1132                 CallStateException.ERROR_POWER_OFF,
1133                 "cannot dial voice call in airplane mode");
1134         }
1135         // Check for service before placing non emergency CS voice call.
1136         // Allow dial only if either CS is camped on any RAT (or) PS is in LTE service.
1137         if (mSST != null
1138                 && mSST.mSS.getState() == ServiceState.STATE_OUT_OF_SERVICE /* CS out of service */
1139                 && !(mSST.mSS.getDataRegState() == ServiceState.STATE_IN_SERVICE
1140                     && ServiceState.isLte(mSST.mSS.getRilDataRadioTechnology())) /* PS not in LTE */
1141                 && !VideoProfile.isVideo(videoState) /* voice call */
1142                 && !isEmergency /* non-emergency call */) {
1143             throw new CallStateException(
1144                 CallStateException.ERROR_OUT_OF_SERVICE,
1145                 "cannot dial voice call in out of service");
1146         }
1147         if (DBG) logd("Trying (non-IMS) CS call");
1148 
1149         if (isPhoneTypeGsm()) {
1150             return dialInternal(dialString, null, VideoProfile.STATE_AUDIO_ONLY, intentExtras);
1151         } else {
1152             return dialInternal(dialString, null, videoState, intentExtras);
1153         }
1154     }
1155 
1156     /**
1157      * @return {@code true} if the user should be informed of an attempt to dial an international
1158      * number while on WFC only, {@code false} otherwise.
1159      */
isNotificationOfWfcCallRequired(String dialString)1160     public boolean isNotificationOfWfcCallRequired(String dialString) {
1161         CarrierConfigManager configManager =
1162                 (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
1163         PersistableBundle config = configManager.getConfigForSubId(getSubId());
1164 
1165         // Determine if carrier config indicates that international calls over WFC should trigger a
1166         // notification to the user. This is controlled by carrier configuration and is off by
1167         // default.
1168         boolean shouldNotifyInternationalCallOnWfc = config != null
1169                 && config.getBoolean(
1170                         CarrierConfigManager.KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL);
1171 
1172         if (!shouldNotifyInternationalCallOnWfc) {
1173             return false;
1174         }
1175 
1176         Phone imsPhone = mImsPhone;
1177         boolean isEmergency = PhoneNumberUtils.isEmergencyNumber(getSubId(), dialString);
1178         boolean shouldConfirmCall =
1179                         // Using IMS
1180                         isImsUseEnabled()
1181                         && imsPhone != null
1182                         // VoLTE not available
1183                         && !imsPhone.isVolteEnabled()
1184                         // WFC is available
1185                         && imsPhone.isWifiCallingEnabled()
1186                         && !isEmergency
1187                         // Dialing international number
1188                         && PhoneNumberUtils.isInternationalNumber(dialString, getCountryIso());
1189         return shouldConfirmCall;
1190     }
1191 
1192     @Override
dialInternal(String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)1193     protected Connection dialInternal(String dialString, UUSInfo uusInfo, int videoState,
1194                                       Bundle intentExtras)
1195             throws CallStateException {
1196         return dialInternal(dialString, uusInfo, videoState, intentExtras, null);
1197     }
1198 
dialInternal(String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras, ResultReceiver wrappedCallback)1199     protected Connection dialInternal(String dialString, UUSInfo uusInfo, int videoState,
1200                                       Bundle intentExtras, ResultReceiver wrappedCallback)
1201             throws CallStateException {
1202 
1203         // Need to make sure dialString gets parsed properly
1204         String newDialString = PhoneNumberUtils.stripSeparators(dialString);
1205 
1206         if (isPhoneTypeGsm()) {
1207             // handle in-call MMI first if applicable
1208             if (handleInCallMmiCommands(newDialString)) {
1209                 return null;
1210             }
1211 
1212             // Only look at the Network portion for mmi
1213             String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString);
1214             GsmMmiCode mmi = GsmMmiCode.newFromDialString(networkPortion, this,
1215                     mUiccApplication.get(), wrappedCallback);
1216             if (DBG) logd("dialInternal: dialing w/ mmi '" + mmi + "'...");
1217 
1218             if (mmi == null) {
1219                 return mCT.dial(newDialString, uusInfo, intentExtras);
1220             } else if (mmi.isTemporaryModeCLIR()) {
1221                 return mCT.dial(mmi.mDialingNumber, mmi.getCLIRMode(), uusInfo, intentExtras);
1222             } else {
1223                 mPendingMMIs.add(mmi);
1224                 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
1225                 mmi.processCode();
1226                 return null;
1227             }
1228         } else {
1229             return mCT.dial(newDialString);
1230         }
1231     }
1232 
1233    @Override
handlePinMmi(String dialString)1234     public boolean handlePinMmi(String dialString) {
1235         MmiCode mmi;
1236         if (isPhoneTypeGsm()) {
1237             mmi = GsmMmiCode.newFromDialString(dialString, this, mUiccApplication.get());
1238         } else {
1239             mmi = CdmaMmiCode.newFromDialString(dialString, this, mUiccApplication.get());
1240         }
1241 
1242         if (mmi != null && mmi.isPinPukCommand()) {
1243             mPendingMMIs.add(mmi);
1244             mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
1245             try {
1246                 mmi.processCode();
1247             } catch (CallStateException e) {
1248                 //do nothing
1249             }
1250             return true;
1251         }
1252 
1253         loge("Mmi is null or unrecognized!");
1254         return false;
1255     }
1256 
sendUssdResponse(String ussdRequest, CharSequence message, int returnCode, ResultReceiver wrappedCallback)1257     private void sendUssdResponse(String ussdRequest, CharSequence message, int returnCode,
1258                                    ResultReceiver wrappedCallback) {
1259         UssdResponse response = new UssdResponse(ussdRequest, message);
1260         Bundle returnData = new Bundle();
1261         returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response);
1262         wrappedCallback.send(returnCode, returnData);
1263     }
1264 
1265     @Override
handleUssdRequest(String ussdRequest, ResultReceiver wrappedCallback)1266     public boolean handleUssdRequest(String ussdRequest, ResultReceiver wrappedCallback) {
1267         if (!isPhoneTypeGsm() || mPendingMMIs.size() > 0) {
1268             //todo: replace the generic failure with specific error code.
1269             sendUssdResponse(ussdRequest, null, TelephonyManager.USSD_RETURN_FAILURE,
1270                     wrappedCallback );
1271             return true;
1272         }
1273 
1274         // Try over IMS if possible.
1275         Phone imsPhone = mImsPhone;
1276         if ((imsPhone != null)
1277                 && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
1278                 || imsPhone.isUtEnabled())) {
1279             try {
1280                 logd("handleUssdRequest: attempting over IMS");
1281                 return imsPhone.handleUssdRequest(ussdRequest, wrappedCallback);
1282             } catch (CallStateException cse) {
1283                 if (!CS_FALLBACK.equals(cse.getMessage())) {
1284                     return false;
1285                 }
1286                 // At this point we've tried over IMS but have been informed we need to handover
1287                 // back to GSM.
1288                 logd("handleUssdRequest: fallback to CS required");
1289             }
1290         }
1291 
1292         // Try USSD over GSM.
1293         try {
1294             dialInternal(ussdRequest, null, VideoProfile.STATE_AUDIO_ONLY, null,
1295                     wrappedCallback);
1296         } catch (Exception e) {
1297             logd("handleUssdRequest: exception" + e);
1298             return false;
1299         }
1300         return true;
1301     }
1302 
1303     @Override
sendUssdResponse(String ussdMessge)1304     public void sendUssdResponse(String ussdMessge) {
1305         if (isPhoneTypeGsm()) {
1306             GsmMmiCode mmi = GsmMmiCode.newFromUssdUserInput(ussdMessge, this, mUiccApplication.get());
1307             mPendingMMIs.add(mmi);
1308             mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
1309             mmi.sendUssd(ussdMessge);
1310         } else {
1311             loge("sendUssdResponse: not possible in CDMA");
1312         }
1313     }
1314 
1315     @Override
sendDtmf(char c)1316     public void sendDtmf(char c) {
1317         if (!PhoneNumberUtils.is12Key(c)) {
1318             loge("sendDtmf called with invalid character '" + c + "'");
1319         } else {
1320             if (mCT.mState ==  PhoneConstants.State.OFFHOOK) {
1321                 mCi.sendDtmf(c, null);
1322             }
1323         }
1324     }
1325 
1326     @Override
startDtmf(char c)1327     public void startDtmf(char c) {
1328         if (!PhoneNumberUtils.is12Key(c)) {
1329             loge("startDtmf called with invalid character '" + c + "'");
1330         } else {
1331             mCi.startDtmf(c, null);
1332         }
1333     }
1334 
1335     @Override
stopDtmf()1336     public void stopDtmf() {
1337         mCi.stopDtmf(null);
1338     }
1339 
1340     @Override
sendBurstDtmf(String dtmfString, int on, int off, Message onComplete)1341     public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
1342         if (isPhoneTypeGsm()) {
1343             loge("[GsmCdmaPhone] sendBurstDtmf() is a CDMA method");
1344         } else {
1345             boolean check = true;
1346             for (int itr = 0;itr < dtmfString.length(); itr++) {
1347                 if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) {
1348                     Rlog.e(LOG_TAG,
1349                             "sendDtmf called with invalid character '" + dtmfString.charAt(itr)+ "'");
1350                     check = false;
1351                     break;
1352                 }
1353             }
1354             if (mCT.mState == PhoneConstants.State.OFFHOOK && check) {
1355                 mCi.sendBurstDtmf(dtmfString, on, off, onComplete);
1356             }
1357         }
1358     }
1359 
1360     @Override
setRadioPower(boolean power)1361     public void setRadioPower(boolean power) {
1362         mSST.setRadioPower(power);
1363     }
1364 
storeVoiceMailNumber(String number)1365     private void storeVoiceMailNumber(String number) {
1366         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1367         SharedPreferences.Editor editor = sp.edit();
1368         if (isPhoneTypeGsm()) {
1369             editor.putString(VM_NUMBER + getPhoneId(), number);
1370             editor.apply();
1371             setVmSimImsi(getSubscriberId());
1372         } else {
1373             editor.putString(VM_NUMBER_CDMA + getPhoneId(), number);
1374             editor.apply();
1375         }
1376     }
1377 
1378     @Override
getVoiceMailNumber()1379     public String getVoiceMailNumber() {
1380         String number = null;
1381         if (isPhoneTypeGsm()) {
1382             // Read from the SIM. If its null, try reading from the shared preference area.
1383             IccRecords r = mIccRecords.get();
1384             number = (r != null) ? r.getVoiceMailNumber() : "";
1385             if (TextUtils.isEmpty(number)) {
1386                 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1387                 number = sp.getString(VM_NUMBER + getPhoneId(), null);
1388             }
1389         } else {
1390             SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1391             number = sp.getString(VM_NUMBER_CDMA + getPhoneId(), null);
1392         }
1393 
1394         if (TextUtils.isEmpty(number)) {
1395             CarrierConfigManager configManager = (CarrierConfigManager)
1396                     getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
1397             PersistableBundle b = configManager.getConfig();
1398             if (b != null) {
1399                 String defaultVmNumber =
1400                         b.getString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_STRING);
1401                 if (!TextUtils.isEmpty(defaultVmNumber)) {
1402                     number = defaultVmNumber;
1403                 }
1404             }
1405         }
1406 
1407         if (!isPhoneTypeGsm() && TextUtils.isEmpty(number)) {
1408             // Read platform settings for dynamic voicemail number
1409             if (getContext().getResources().getBoolean(com.android.internal
1410                     .R.bool.config_telephony_use_own_number_for_voicemail)) {
1411                 number = getLine1Number();
1412             } else {
1413                 number = "*86";
1414             }
1415         }
1416 
1417         return number;
1418     }
1419 
getVmSimImsi()1420     private String getVmSimImsi() {
1421         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1422         return sp.getString(VM_SIM_IMSI + getPhoneId(), null);
1423     }
1424 
setVmSimImsi(String imsi)1425     private void setVmSimImsi(String imsi) {
1426         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1427         SharedPreferences.Editor editor = sp.edit();
1428         editor.putString(VM_SIM_IMSI + getPhoneId(), imsi);
1429         editor.apply();
1430     }
1431 
1432     @Override
getVoiceMailAlphaTag()1433     public String getVoiceMailAlphaTag() {
1434         String ret = "";
1435 
1436         if (isPhoneTypeGsm()) {
1437             IccRecords r = mIccRecords.get();
1438 
1439             ret = (r != null) ? r.getVoiceMailAlphaTag() : "";
1440         }
1441 
1442         if (ret == null || ret.length() == 0) {
1443             return mContext.getText(
1444                 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString();
1445         }
1446 
1447         return ret;
1448     }
1449 
1450     @Override
getDeviceId()1451     public String getDeviceId() {
1452         if (isPhoneTypeGsm()) {
1453             return mImei;
1454         } else {
1455             CarrierConfigManager configManager = (CarrierConfigManager)
1456                     mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
1457             boolean force_imei = configManager.getConfigForSubId(getSubId())
1458                     .getBoolean(CarrierConfigManager.KEY_FORCE_IMEI_BOOL);
1459             if (force_imei) return mImei;
1460 
1461             String id = getMeid();
1462             if ((id == null) || id.matches("^0*$")) {
1463                 loge("getDeviceId(): MEID is not initialized use ESN");
1464                 id = getEsn();
1465             }
1466             return id;
1467         }
1468     }
1469 
1470     @Override
getDeviceSvn()1471     public String getDeviceSvn() {
1472         if (isPhoneTypeGsm() || isPhoneTypeCdmaLte()) {
1473             return mImeiSv;
1474         } else {
1475             loge("getDeviceSvn(): return 0");
1476             return "0";
1477         }
1478     }
1479 
1480     @Override
getIsimRecords()1481     public IsimRecords getIsimRecords() {
1482         return mIsimUiccRecords;
1483     }
1484 
1485     @Override
getImei()1486     public String getImei() {
1487         return mImei;
1488     }
1489 
1490     @Override
getEsn()1491     public String getEsn() {
1492         if (isPhoneTypeGsm()) {
1493             loge("[GsmCdmaPhone] getEsn() is a CDMA method");
1494             return "0";
1495         } else {
1496             return mEsn;
1497         }
1498     }
1499 
1500     @Override
getMeid()1501     public String getMeid() {
1502         return mMeid;
1503     }
1504 
1505     @Override
getNai()1506     public String getNai() {
1507         IccRecords r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP2);
1508         if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
1509             Rlog.v(LOG_TAG, "IccRecords is " + r);
1510         }
1511         return (r != null) ? r.getNAI() : null;
1512     }
1513 
1514     @Override
getSubscriberId()1515     public String getSubscriberId() {
1516         if (isPhoneTypeGsm()) {
1517             IccRecords r = mIccRecords.get();
1518             return (r != null) ? r.getIMSI() : null;
1519         } else if (isPhoneTypeCdma()) {
1520             return mSST.getImsi();
1521         } else { //isPhoneTypeCdmaLte()
1522             return (mSimRecords != null) ? mSimRecords.getIMSI() : "";
1523         }
1524     }
1525 
1526     @Override
getCarrierInfoForImsiEncryption(int keyType)1527     public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) {
1528         return CarrierInfoManager.getCarrierInfoForImsiEncryption(keyType, mContext);
1529     }
1530 
1531     @Override
setCarrierInfoForImsiEncryption(ImsiEncryptionInfo imsiEncryptionInfo)1532     public void setCarrierInfoForImsiEncryption(ImsiEncryptionInfo imsiEncryptionInfo) {
1533         CarrierInfoManager.setCarrierInfoForImsiEncryption(imsiEncryptionInfo, mContext);
1534     }
1535 
1536     @Override
getGroupIdLevel1()1537     public String getGroupIdLevel1() {
1538         if (isPhoneTypeGsm()) {
1539             IccRecords r = mIccRecords.get();
1540             return (r != null) ? r.getGid1() : null;
1541         } else if (isPhoneTypeCdma()) {
1542             loge("GID1 is not available in CDMA");
1543             return null;
1544         } else { //isPhoneTypeCdmaLte()
1545             return (mSimRecords != null) ? mSimRecords.getGid1() : "";
1546         }
1547     }
1548 
1549     @Override
getGroupIdLevel2()1550     public String getGroupIdLevel2() {
1551         if (isPhoneTypeGsm()) {
1552             IccRecords r = mIccRecords.get();
1553             return (r != null) ? r.getGid2() : null;
1554         } else if (isPhoneTypeCdma()) {
1555             loge("GID2 is not available in CDMA");
1556             return null;
1557         } else { //isPhoneTypeCdmaLte()
1558             return (mSimRecords != null) ? mSimRecords.getGid2() : "";
1559         }
1560     }
1561 
1562     @Override
getLine1Number()1563     public String getLine1Number() {
1564         if (isPhoneTypeGsm()) {
1565             IccRecords r = mIccRecords.get();
1566             return (r != null) ? r.getMsisdnNumber() : null;
1567         } else {
1568             return mSST.getMdnNumber();
1569         }
1570     }
1571 
1572     @Override
getCdmaPrlVersion()1573     public String getCdmaPrlVersion() {
1574         return mSST.getPrlVersion();
1575     }
1576 
1577     @Override
getCdmaMin()1578     public String getCdmaMin() {
1579         return mSST.getCdmaMin();
1580     }
1581 
1582     @Override
isMinInfoReady()1583     public boolean isMinInfoReady() {
1584         return mSST.isMinInfoReady();
1585     }
1586 
1587     @Override
getMsisdn()1588     public String getMsisdn() {
1589         if (isPhoneTypeGsm()) {
1590             IccRecords r = mIccRecords.get();
1591             return (r != null) ? r.getMsisdnNumber() : null;
1592         } else if (isPhoneTypeCdmaLte()) {
1593             return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null;
1594         } else {
1595             loge("getMsisdn: not expected on CDMA");
1596             return null;
1597         }
1598     }
1599 
1600     @Override
getLine1AlphaTag()1601     public String getLine1AlphaTag() {
1602         if (isPhoneTypeGsm()) {
1603             IccRecords r = mIccRecords.get();
1604             return (r != null) ? r.getMsisdnAlphaTag() : null;
1605         } else {
1606             loge("getLine1AlphaTag: not possible in CDMA");
1607             return null;
1608         }
1609     }
1610 
1611     @Override
setLine1Number(String alphaTag, String number, Message onComplete)1612     public boolean setLine1Number(String alphaTag, String number, Message onComplete) {
1613         if (isPhoneTypeGsm()) {
1614             IccRecords r = mIccRecords.get();
1615             if (r != null) {
1616                 r.setMsisdnNumber(alphaTag, number, onComplete);
1617                 return true;
1618             } else {
1619                 return false;
1620             }
1621         } else {
1622             loge("setLine1Number: not possible in CDMA");
1623             return false;
1624         }
1625     }
1626 
1627     @Override
setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete)1628     public void setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete) {
1629         Message resp;
1630         mVmNumber = voiceMailNumber;
1631         resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
1632         IccRecords r = mIccRecords.get();
1633         if (r != null) {
1634             r.setVoiceMailNumber(alphaTag, mVmNumber, resp);
1635         }
1636     }
1637 
isValidCommandInterfaceCFReason(int commandInterfaceCFReason)1638     private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) {
1639         switch (commandInterfaceCFReason) {
1640             case CF_REASON_UNCONDITIONAL:
1641             case CF_REASON_BUSY:
1642             case CF_REASON_NO_REPLY:
1643             case CF_REASON_NOT_REACHABLE:
1644             case CF_REASON_ALL:
1645             case CF_REASON_ALL_CONDITIONAL:
1646                 return true;
1647             default:
1648                 return false;
1649         }
1650     }
1651 
1652     @Override
getSystemProperty(String property, String defValue)1653     public String getSystemProperty(String property, String defValue) {
1654         if (isPhoneTypeGsm() || isPhoneTypeCdmaLte()) {
1655             if (getUnitTestMode()) {
1656                 return null;
1657             }
1658             return TelephonyManager.getTelephonyProperty(mPhoneId, property, defValue);
1659         } else {
1660             return super.getSystemProperty(property, defValue);
1661         }
1662     }
1663 
isValidCommandInterfaceCFAction(int commandInterfaceCFAction)1664     private boolean isValidCommandInterfaceCFAction (int commandInterfaceCFAction) {
1665         switch (commandInterfaceCFAction) {
1666             case CF_ACTION_DISABLE:
1667             case CF_ACTION_ENABLE:
1668             case CF_ACTION_REGISTRATION:
1669             case CF_ACTION_ERASURE:
1670                 return true;
1671             default:
1672                 return false;
1673         }
1674     }
1675 
isCfEnable(int action)1676     private boolean isCfEnable(int action) {
1677         return (action == CF_ACTION_ENABLE) || (action == CF_ACTION_REGISTRATION);
1678     }
1679 
1680     @Override
getCallForwardingOption(int commandInterfaceCFReason, Message onComplete)1681     public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
1682         if (isPhoneTypeGsm()) {
1683             Phone imsPhone = mImsPhone;
1684             if ((imsPhone != null)
1685                     && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
1686                     || imsPhone.isUtEnabled())) {
1687                 imsPhone.getCallForwardingOption(commandInterfaceCFReason, onComplete);
1688                 return;
1689             }
1690 
1691             if (isValidCommandInterfaceCFReason(commandInterfaceCFReason)) {
1692                 if (DBG) logd("requesting call forwarding query.");
1693                 Message resp;
1694                 if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) {
1695                     resp = obtainMessage(EVENT_GET_CALL_FORWARD_DONE, onComplete);
1696                 } else {
1697                     resp = onComplete;
1698                 }
1699                 mCi.queryCallForwardStatus(commandInterfaceCFReason, 0, null, resp);
1700             }
1701         } else {
1702             loge("getCallForwardingOption: not possible in CDMA");
1703         }
1704     }
1705 
1706     @Override
setCallForwardingOption(int commandInterfaceCFAction, int commandInterfaceCFReason, String dialingNumber, int timerSeconds, Message onComplete)1707     public void setCallForwardingOption(int commandInterfaceCFAction,
1708             int commandInterfaceCFReason,
1709             String dialingNumber,
1710             int timerSeconds,
1711             Message onComplete) {
1712         if (isPhoneTypeGsm()) {
1713             Phone imsPhone = mImsPhone;
1714             if ((imsPhone != null)
1715                     && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
1716                     || imsPhone.isUtEnabled())) {
1717                 imsPhone.setCallForwardingOption(commandInterfaceCFAction,
1718                         commandInterfaceCFReason, dialingNumber, timerSeconds, onComplete);
1719                 return;
1720             }
1721 
1722             if ((isValidCommandInterfaceCFAction(commandInterfaceCFAction)) &&
1723                     (isValidCommandInterfaceCFReason(commandInterfaceCFReason))) {
1724 
1725                 Message resp;
1726                 if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) {
1727                     Cfu cfu = new Cfu(dialingNumber, onComplete);
1728                     resp = obtainMessage(EVENT_SET_CALL_FORWARD_DONE,
1729                             isCfEnable(commandInterfaceCFAction) ? 1 : 0, 0, cfu);
1730                 } else {
1731                     resp = onComplete;
1732                 }
1733                 mCi.setCallForward(commandInterfaceCFAction,
1734                         commandInterfaceCFReason,
1735                         CommandsInterface.SERVICE_CLASS_VOICE,
1736                         dialingNumber,
1737                         timerSeconds,
1738                         resp);
1739             }
1740         } else {
1741             loge("setCallForwardingOption: not possible in CDMA");
1742         }
1743     }
1744 
1745     @Override
getOutgoingCallerIdDisplay(Message onComplete)1746     public void getOutgoingCallerIdDisplay(Message onComplete) {
1747         if (isPhoneTypeGsm()) {
1748             Phone imsPhone = mImsPhone;
1749             if ((imsPhone != null)
1750                     && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)) {
1751                 imsPhone.getOutgoingCallerIdDisplay(onComplete);
1752                 return;
1753             }
1754             mCi.getCLIR(onComplete);
1755         } else {
1756             loge("getOutgoingCallerIdDisplay: not possible in CDMA");
1757         }
1758     }
1759 
1760     @Override
setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete)1761     public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
1762         if (isPhoneTypeGsm()) {
1763             Phone imsPhone = mImsPhone;
1764             if ((imsPhone != null)
1765                     && (imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)) {
1766                 imsPhone.setOutgoingCallerIdDisplay(commandInterfaceCLIRMode, onComplete);
1767                 return;
1768             }
1769             // Packing CLIR value in the message. This will be required for
1770             // SharedPreference caching, if the message comes back as part of
1771             // a success response.
1772             mCi.setCLIR(commandInterfaceCLIRMode,
1773                     obtainMessage(EVENT_SET_CLIR_COMPLETE, commandInterfaceCLIRMode, 0, onComplete));
1774         } else {
1775             loge("setOutgoingCallerIdDisplay: not possible in CDMA");
1776         }
1777     }
1778 
1779     @Override
getCallWaiting(Message onComplete)1780     public void getCallWaiting(Message onComplete) {
1781         if (isPhoneTypeGsm()) {
1782             Phone imsPhone = mImsPhone;
1783             if ((imsPhone != null)
1784                     && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
1785                     || imsPhone.isUtEnabled())) {
1786                 imsPhone.getCallWaiting(onComplete);
1787                 return;
1788             }
1789 
1790             //As per 3GPP TS 24.083, section 1.6 UE doesn't need to send service
1791             //class parameter in call waiting interrogation  to network
1792             mCi.queryCallWaiting(CommandsInterface.SERVICE_CLASS_NONE, onComplete);
1793         } else {
1794             mCi.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
1795         }
1796     }
1797 
1798     @Override
setCallWaiting(boolean enable, Message onComplete)1799     public void setCallWaiting(boolean enable, Message onComplete) {
1800         if (isPhoneTypeGsm()) {
1801             Phone imsPhone = mImsPhone;
1802             if ((imsPhone != null)
1803                     && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
1804                     || imsPhone.isUtEnabled())) {
1805                 imsPhone.setCallWaiting(enable, onComplete);
1806                 return;
1807             }
1808 
1809             mCi.setCallWaiting(enable, CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
1810         } else {
1811             loge("method setCallWaiting is NOT supported in CDMA!");
1812         }
1813     }
1814 
1815     @Override
getAvailableNetworks(Message response)1816     public void getAvailableNetworks(Message response) {
1817         if (isPhoneTypeGsm() || isPhoneTypeCdmaLte()) {
1818             mCi.getAvailableNetworks(response);
1819         } else {
1820             loge("getAvailableNetworks: not possible in CDMA");
1821         }
1822     }
1823 
1824     @Override
startNetworkScan(NetworkScanRequest nsr, Message response)1825     public void startNetworkScan(NetworkScanRequest nsr, Message response) {
1826         mCi.startNetworkScan(nsr, response);
1827     }
1828 
1829     @Override
stopNetworkScan(Message response)1830     public void stopNetworkScan(Message response) {
1831         mCi.stopNetworkScan(response);
1832     }
1833 
1834     @Override
getNeighboringCids(Message response, WorkSource workSource)1835     public void getNeighboringCids(Message response, WorkSource workSource) {
1836         if (isPhoneTypeGsm()) {
1837             mCi.getNeighboringCids(response, workSource);
1838         } else {
1839             /*
1840              * This is currently not implemented.  At least as of June
1841              * 2009, there is no neighbor cell information available for
1842              * CDMA because some party is resisting making this
1843              * information readily available.  Consequently, calling this
1844              * function can have no useful effect.  This situation may
1845              * (and hopefully will) change in the future.
1846              */
1847             if (response != null) {
1848                 CommandException ce = new CommandException(
1849                         CommandException.Error.REQUEST_NOT_SUPPORTED);
1850                 AsyncResult.forMessage(response).exception = ce;
1851                 response.sendToTarget();
1852             }
1853         }
1854     }
1855 
1856     @Override
setTTYMode(int ttyMode, Message onComplete)1857     public void setTTYMode(int ttyMode, Message onComplete) {
1858         // Send out the TTY Mode change over RIL as well
1859         super.setTTYMode(ttyMode, onComplete);
1860         if (mImsPhone != null) {
1861             mImsPhone.setTTYMode(ttyMode, onComplete);
1862         }
1863     }
1864 
1865     @Override
setUiTTYMode(int uiTtyMode, Message onComplete)1866     public void setUiTTYMode(int uiTtyMode, Message onComplete) {
1867        if (mImsPhone != null) {
1868            mImsPhone.setUiTTYMode(uiTtyMode, onComplete);
1869        }
1870     }
1871 
1872     @Override
setMute(boolean muted)1873     public void setMute(boolean muted) {
1874         mCT.setMute(muted);
1875     }
1876 
1877     @Override
getMute()1878     public boolean getMute() {
1879         return mCT.getMute();
1880     }
1881 
1882     @Override
getDataCallList(Message response)1883     public void getDataCallList(Message response) {
1884         mCi.getDataCallList(response);
1885     }
1886 
1887     @Override
updateServiceLocation()1888     public void updateServiceLocation() {
1889         mSST.enableSingleLocationUpdate();
1890     }
1891 
1892     @Override
enableLocationUpdates()1893     public void enableLocationUpdates() {
1894         mSST.enableLocationUpdates();
1895     }
1896 
1897     @Override
disableLocationUpdates()1898     public void disableLocationUpdates() {
1899         mSST.disableLocationUpdates();
1900     }
1901 
1902     @Override
getDataRoamingEnabled()1903     public boolean getDataRoamingEnabled() {
1904         return mDcTracker.getDataRoamingEnabled();
1905     }
1906 
1907     @Override
setDataRoamingEnabled(boolean enable)1908     public void setDataRoamingEnabled(boolean enable) {
1909         mDcTracker.setDataRoamingEnabledByUser(enable);
1910     }
1911 
1912     @Override
registerForCdmaOtaStatusChange(Handler h, int what, Object obj)1913     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
1914         mCi.registerForCdmaOtaProvision(h, what, obj);
1915     }
1916 
1917     @Override
unregisterForCdmaOtaStatusChange(Handler h)1918     public void unregisterForCdmaOtaStatusChange(Handler h) {
1919         mCi.unregisterForCdmaOtaProvision(h);
1920     }
1921 
1922     @Override
registerForSubscriptionInfoReady(Handler h, int what, Object obj)1923     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
1924         mSST.registerForSubscriptionInfoReady(h, what, obj);
1925     }
1926 
1927     @Override
unregisterForSubscriptionInfoReady(Handler h)1928     public void unregisterForSubscriptionInfoReady(Handler h) {
1929         mSST.unregisterForSubscriptionInfoReady(h);
1930     }
1931 
1932     @Override
setOnEcbModeExitResponse(Handler h, int what, Object obj)1933     public void setOnEcbModeExitResponse(Handler h, int what, Object obj) {
1934         mEcmExitRespRegistrant = new Registrant(h, what, obj);
1935     }
1936 
1937     @Override
unsetOnEcbModeExitResponse(Handler h)1938     public void unsetOnEcbModeExitResponse(Handler h) {
1939         mEcmExitRespRegistrant.clear();
1940     }
1941 
1942     @Override
registerForCallWaiting(Handler h, int what, Object obj)1943     public void registerForCallWaiting(Handler h, int what, Object obj) {
1944         mCT.registerForCallWaiting(h, what, obj);
1945     }
1946 
1947     @Override
unregisterForCallWaiting(Handler h)1948     public void unregisterForCallWaiting(Handler h) {
1949         mCT.unregisterForCallWaiting(h);
1950     }
1951 
1952     @Override
getDataEnabled()1953     public boolean getDataEnabled() {
1954         return mDcTracker.getDataEnabled();
1955     }
1956 
1957     @Override
setDataEnabled(boolean enable)1958     public void setDataEnabled(boolean enable) {
1959         mDcTracker.setDataEnabled(enable);
1960     }
1961 
1962     /**
1963      * Removes the given MMI from the pending list and notifies
1964      * registrants that it is complete.
1965      * @param mmi MMI that is done
1966      */
onMMIDone(MmiCode mmi)1967     public void onMMIDone(MmiCode mmi) {
1968 
1969         /* Only notify complete if it's on the pending list.
1970          * Otherwise, it's already been handled (eg, previously canceled).
1971          * The exception is cancellation of an incoming USSD-REQUEST, which is
1972          * not on the list.
1973          */
1974         if (mPendingMMIs.remove(mmi) || (isPhoneTypeGsm() && (mmi.isUssdRequest() ||
1975                 ((GsmMmiCode)mmi).isSsInfo()))) {
1976 
1977             ResultReceiver receiverCallback = mmi.getUssdCallbackReceiver();
1978             if (receiverCallback != null) {
1979                 Rlog.i(LOG_TAG, "onMMIDone: invoking callback: " + mmi);
1980                 int returnCode = (mmi.getState() ==  MmiCode.State.COMPLETE) ?
1981                     TelephonyManager.USSD_RETURN_SUCCESS : TelephonyManager.USSD_RETURN_FAILURE;
1982                 sendUssdResponse(mmi.getDialString(), mmi.getMessage(), returnCode,
1983                         receiverCallback );
1984             } else {
1985                 Rlog.i(LOG_TAG, "onMMIDone: notifying registrants: " + mmi);
1986                 mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
1987             }
1988         } else {
1989             Rlog.i(LOG_TAG, "onMMIDone: invalid response or already handled; ignoring: " + mmi);
1990         }
1991     }
1992 
supports3gppCallForwardingWhileRoaming()1993     public boolean supports3gppCallForwardingWhileRoaming() {
1994         CarrierConfigManager configManager = (CarrierConfigManager)
1995                 getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
1996         PersistableBundle b = configManager.getConfig();
1997         if (b != null) {
1998             return b.getBoolean(
1999                     CarrierConfigManager.KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL, true);
2000         } else {
2001             // Default value set in CarrierConfigManager
2002             return true;
2003         }
2004     }
2005 
onNetworkInitiatedUssd(MmiCode mmi)2006     private void onNetworkInitiatedUssd(MmiCode mmi) {
2007         Rlog.v(LOG_TAG, "onNetworkInitiatedUssd: mmi=" + mmi);
2008         mMmiCompleteRegistrants.notifyRegistrants(
2009             new AsyncResult(null, mmi, null));
2010     }
2011 
2012     /** ussdMode is one of CommandsInterface.USSD_MODE_* */
onIncomingUSSD(int ussdMode, String ussdMessage)2013     private void onIncomingUSSD (int ussdMode, String ussdMessage) {
2014         if (!isPhoneTypeGsm()) {
2015             loge("onIncomingUSSD: not expected on GSM");
2016         }
2017         boolean isUssdError;
2018         boolean isUssdRequest;
2019         boolean isUssdRelease;
2020 
2021         isUssdRequest
2022             = (ussdMode == CommandsInterface.USSD_MODE_REQUEST);
2023 
2024         isUssdError
2025             = (ussdMode != CommandsInterface.USSD_MODE_NOTIFY
2026                 && ussdMode != CommandsInterface.USSD_MODE_REQUEST);
2027 
2028         isUssdRelease = (ussdMode == CommandsInterface.USSD_MODE_NW_RELEASE);
2029 
2030 
2031         // See comments in GsmMmiCode.java
2032         // USSD requests aren't finished until one
2033         // of these two events happen
2034         GsmMmiCode found = null;
2035         for (int i = 0, s = mPendingMMIs.size() ; i < s; i++) {
2036             if(((GsmMmiCode)mPendingMMIs.get(i)).isPendingUSSD()) {
2037                 found = (GsmMmiCode)mPendingMMIs.get(i);
2038                 break;
2039             }
2040         }
2041 
2042         if (found != null) {
2043             // Complete pending USSD
2044 
2045             if (isUssdRelease) {
2046                 found.onUssdRelease();
2047             } else if (isUssdError) {
2048                 found.onUssdFinishedError();
2049             } else {
2050                 found.onUssdFinished(ussdMessage, isUssdRequest);
2051             }
2052         } else if (!isUssdError && ussdMessage != null) {
2053             // pending USSD not found
2054             // The network may initiate its own USSD request
2055 
2056             // ignore everything that isnt a Notify or a Request
2057             // also, discard if there is no message to present
2058             GsmMmiCode mmi;
2059             mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage,
2060                                                    isUssdRequest,
2061                                                    GsmCdmaPhone.this,
2062                                                    mUiccApplication.get());
2063             onNetworkInitiatedUssd(mmi);
2064         }
2065     }
2066 
2067     /**
2068      * Make sure the network knows our preferred setting.
2069      */
syncClirSetting()2070     private void syncClirSetting() {
2071         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
2072         int clirSetting = sp.getInt(CLIR_KEY + getPhoneId(), -1);
2073         Rlog.i(LOG_TAG, "syncClirSetting: " + CLIR_KEY + getPhoneId() + "=" + clirSetting);
2074         if (clirSetting >= 0) {
2075             mCi.setCLIR(clirSetting, null);
2076         }
2077     }
2078 
handleRadioAvailable()2079     private void handleRadioAvailable() {
2080         mCi.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
2081 
2082         mCi.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));
2083         mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));
2084         startLceAfterRadioIsAvailable();
2085     }
2086 
handleRadioOn()2087     private void handleRadioOn() {
2088         /* Proactively query voice radio technologies */
2089         mCi.getVoiceRadioTechnology(obtainMessage(EVENT_REQUEST_VOICE_RADIO_TECH_DONE));
2090 
2091         if (!isPhoneTypeGsm()) {
2092             mCdmaSubscriptionSource = mCdmaSSM.getCdmaSubscriptionSource();
2093         }
2094 
2095         // If this is on APM off, SIM may already be loaded. Send setPreferredNetworkType
2096         // request to RIL to preserve user setting across APM toggling
2097         setPreferredNetworkTypeIfSimLoaded();
2098     }
2099 
handleRadioOffOrNotAvailable()2100     private void handleRadioOffOrNotAvailable() {
2101         if (isPhoneTypeGsm()) {
2102             // Some MMI requests (eg USSD) are not completed
2103             // within the course of a CommandsInterface request
2104             // If the radio shuts off or resets while one of these
2105             // is pending, we need to clean up.
2106 
2107             for (int i = mPendingMMIs.size() - 1; i >= 0; i--) {
2108                 if (((GsmMmiCode) mPendingMMIs.get(i)).isPendingUSSD()) {
2109                     ((GsmMmiCode) mPendingMMIs.get(i)).onUssdFinishedError();
2110                 }
2111             }
2112         }
2113         mRadioOffOrNotAvailableRegistrants.notifyRegistrants();
2114     }
2115 
2116     @Override
handleMessage(Message msg)2117     public void handleMessage(Message msg) {
2118         AsyncResult ar;
2119         Message onComplete;
2120 
2121         switch (msg.what) {
2122             case EVENT_RADIO_AVAILABLE: {
2123                 handleRadioAvailable();
2124             }
2125             break;
2126 
2127             case EVENT_GET_DEVICE_IDENTITY_DONE:{
2128                 ar = (AsyncResult)msg.obj;
2129 
2130                 if (ar.exception != null) {
2131                     break;
2132                 }
2133                 String[] respId = (String[])ar.result;
2134                 mImei = respId[0];
2135                 mImeiSv = respId[1];
2136                 mEsn  =  respId[2];
2137                 mMeid =  respId[3];
2138             }
2139             break;
2140 
2141             case EVENT_EMERGENCY_CALLBACK_MODE_ENTER:{
2142                 handleEnterEmergencyCallbackMode(msg);
2143             }
2144             break;
2145 
2146             case  EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE:{
2147                 handleExitEmergencyCallbackMode(msg);
2148             }
2149             break;
2150 
2151             case EVENT_MODEM_RESET: {
2152                 logd("Event EVENT_MODEM_RESET Received" + " isInEcm = " + isInEcm()
2153                         + " isPhoneTypeGsm = " + isPhoneTypeGsm() + " mImsPhone = " + mImsPhone);
2154                 if (isInEcm()) {
2155                     if (isPhoneTypeGsm()) {
2156                         if (mImsPhone != null) {
2157                             mImsPhone.handleExitEmergencyCallbackMode();
2158                         }
2159                     } else {
2160                         handleExitEmergencyCallbackMode(msg);
2161                     }
2162                 }
2163             }
2164             break;
2165 
2166             case EVENT_RUIM_RECORDS_LOADED:
2167                 logd("Event EVENT_RUIM_RECORDS_LOADED Received");
2168                 updateCurrentCarrierInProvider();
2169                 break;
2170 
2171             case EVENT_RADIO_ON:
2172                 logd("Event EVENT_RADIO_ON Received");
2173                 handleRadioOn();
2174                 break;
2175 
2176             case EVENT_RIL_CONNECTED:
2177                 ar = (AsyncResult) msg.obj;
2178                 if (ar.exception == null && ar.result != null) {
2179                     mRilVersion = (Integer) ar.result;
2180                 } else {
2181                     logd("Unexpected exception on EVENT_RIL_CONNECTED");
2182                     mRilVersion = -1;
2183                 }
2184                 break;
2185 
2186             case EVENT_VOICE_RADIO_TECH_CHANGED:
2187             case EVENT_REQUEST_VOICE_RADIO_TECH_DONE:
2188                 String what = (msg.what == EVENT_VOICE_RADIO_TECH_CHANGED) ?
2189                         "EVENT_VOICE_RADIO_TECH_CHANGED" : "EVENT_REQUEST_VOICE_RADIO_TECH_DONE";
2190                 ar = (AsyncResult) msg.obj;
2191                 if (ar.exception == null) {
2192                     if ((ar.result != null) && (((int[]) ar.result).length != 0)) {
2193                         int newVoiceTech = ((int[]) ar.result)[0];
2194                         logd(what + ": newVoiceTech=" + newVoiceTech);
2195                         phoneObjectUpdater(newVoiceTech);
2196                     } else {
2197                         loge(what + ": has no tech!");
2198                     }
2199                 } else {
2200                     loge(what + ": exception=" + ar.exception);
2201                 }
2202                 break;
2203 
2204             case EVENT_UPDATE_PHONE_OBJECT:
2205                 phoneObjectUpdater(msg.arg1);
2206                 break;
2207 
2208             case EVENT_CARRIER_CONFIG_CHANGED:
2209                 // Only check for the voice radio tech if it not going to be updated by the voice
2210                 // registration changes.
2211                 if (!mContext.getResources().getBoolean(com.android.internal.R.bool.
2212                         config_switch_phone_on_voice_reg_state_change)) {
2213                     mCi.getVoiceRadioTechnology(obtainMessage(EVENT_REQUEST_VOICE_RADIO_TECH_DONE));
2214                 }
2215                 // Force update IMS service
2216                 ImsManager.updateImsServiceConfig(mContext, mPhoneId, true);
2217 
2218                 // Update broadcastEmergencyCallStateChanges
2219                 CarrierConfigManager configMgr = (CarrierConfigManager)
2220                         getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
2221                 PersistableBundle b = configMgr.getConfigForSubId(getSubId());
2222                 if (b != null) {
2223                     boolean broadcastEmergencyCallStateChanges = b.getBoolean(
2224                             CarrierConfigManager.KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL);
2225                     logd("broadcastEmergencyCallStateChanges = " +
2226                             broadcastEmergencyCallStateChanges);
2227                     setBroadcastEmergencyCallStateChanges(broadcastEmergencyCallStateChanges);
2228                 } else {
2229                     loge("didn't get broadcastEmergencyCallStateChanges from carrier config");
2230                 }
2231 
2232                 // Changing the cdma roaming settings based carrier config.
2233                 if (b != null) {
2234                     int config_cdma_roaming_mode = b.getInt(
2235                             CarrierConfigManager.KEY_CDMA_ROAMING_MODE_INT);
2236                     int current_cdma_roaming_mode =
2237                             Settings.Global.getInt(getContext().getContentResolver(),
2238                             Settings.Global.CDMA_ROAMING_MODE,
2239                             CarrierConfigManager.CDMA_ROAMING_MODE_RADIO_DEFAULT);
2240                     switch (config_cdma_roaming_mode) {
2241                         // Carrier's cdma_roaming_mode will overwrite the user's previous settings
2242                         // Keep the user's previous setting in global variable which will be used
2243                         // when carrier's setting is turn off.
2244                         case CarrierConfigManager.CDMA_ROAMING_MODE_HOME:
2245                         case CarrierConfigManager.CDMA_ROAMING_MODE_AFFILIATED:
2246                         case CarrierConfigManager.CDMA_ROAMING_MODE_ANY:
2247                             logd("cdma_roaming_mode is going to changed to "
2248                                     + config_cdma_roaming_mode);
2249                             setCdmaRoamingPreference(config_cdma_roaming_mode,
2250                                     obtainMessage(EVENT_SET_ROAMING_PREFERENCE_DONE));
2251                             break;
2252 
2253                         // When carrier's setting is turn off, change the cdma_roaming_mode to the
2254                         // previous user's setting
2255                         case CarrierConfigManager.CDMA_ROAMING_MODE_RADIO_DEFAULT:
2256                             if (current_cdma_roaming_mode != config_cdma_roaming_mode) {
2257                                 logd("cdma_roaming_mode is going to changed to "
2258                                         + current_cdma_roaming_mode);
2259                                 setCdmaRoamingPreference(current_cdma_roaming_mode,
2260                                         obtainMessage(EVENT_SET_ROAMING_PREFERENCE_DONE));
2261                             }
2262 
2263                         default:
2264                             loge("Invalid cdma_roaming_mode settings: "
2265                                     + config_cdma_roaming_mode);
2266                     }
2267                 } else {
2268                     loge("didn't get the cdma_roaming_mode changes from the carrier config.");
2269                 }
2270 
2271                 // Load the ERI based on carrier config. Carrier might have their specific ERI.
2272                 prepareEri();
2273                 if (!isPhoneTypeGsm()) {
2274                     mSST.pollState();
2275                 }
2276 
2277                 break;
2278 
2279             case EVENT_SET_ROAMING_PREFERENCE_DONE:
2280                 logd("cdma_roaming_mode change is done");
2281                 break;
2282 
2283             case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
2284                 logd("EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED");
2285                 mCdmaSubscriptionSource = mCdmaSSM.getCdmaSubscriptionSource();
2286                 break;
2287 
2288             case EVENT_REGISTERED_TO_NETWORK:
2289                 logd("Event EVENT_REGISTERED_TO_NETWORK Received");
2290                 if (isPhoneTypeGsm()) {
2291                     syncClirSetting();
2292                 }
2293                 break;
2294 
2295             case EVENT_SIM_RECORDS_LOADED:
2296                 updateCurrentCarrierInProvider();
2297 
2298                 // Check if this is a different SIM than the previous one. If so unset the
2299                 // voice mail number.
2300                 String imsi = getVmSimImsi();
2301                 String imsiFromSIM = getSubscriberId();
2302                 if ((!isPhoneTypeGsm() || imsi != null) && imsiFromSIM != null
2303                         && !imsiFromSIM.equals(imsi)) {
2304                     storeVoiceMailNumber(null);
2305                     setVmSimImsi(null);
2306                 }
2307 
2308                 mSimRecordsLoadedRegistrants.notifyRegistrants();
2309                 break;
2310 
2311             case EVENT_GET_BASEBAND_VERSION_DONE:
2312                 ar = (AsyncResult)msg.obj;
2313 
2314                 if (ar.exception != null) {
2315                     break;
2316                 }
2317 
2318                 if (DBG) logd("Baseband version: " + ar.result);
2319                 TelephonyManager.from(mContext).setBasebandVersionForPhone(getPhoneId(),
2320                         (String)ar.result);
2321             break;
2322 
2323             case EVENT_GET_IMEI_DONE:
2324                 ar = (AsyncResult)msg.obj;
2325 
2326                 if (ar.exception != null) {
2327                     break;
2328                 }
2329 
2330                 mImei = (String)ar.result;
2331             break;
2332 
2333             case EVENT_GET_IMEISV_DONE:
2334                 ar = (AsyncResult)msg.obj;
2335 
2336                 if (ar.exception != null) {
2337                     break;
2338                 }
2339 
2340                 mImeiSv = (String)ar.result;
2341             break;
2342 
2343             case EVENT_USSD:
2344                 ar = (AsyncResult)msg.obj;
2345 
2346                 String[] ussdResult = (String[]) ar.result;
2347 
2348                 if (ussdResult.length > 1) {
2349                     try {
2350                         onIncomingUSSD(Integer.parseInt(ussdResult[0]), ussdResult[1]);
2351                     } catch (NumberFormatException e) {
2352                         Rlog.w(LOG_TAG, "error parsing USSD");
2353                     }
2354                 }
2355             break;
2356 
2357             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE: {
2358                 logd("Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received");
2359                 handleRadioOffOrNotAvailable();
2360                 break;
2361             }
2362 
2363             case EVENT_SSN:
2364                 logd("Event EVENT_SSN Received");
2365                 if (isPhoneTypeGsm()) {
2366                     ar = (AsyncResult) msg.obj;
2367                     SuppServiceNotification not = (SuppServiceNotification) ar.result;
2368                     mSsnRegistrants.notifyRegistrants(ar);
2369                 }
2370                 break;
2371 
2372             case EVENT_SET_CALL_FORWARD_DONE:
2373                 ar = (AsyncResult)msg.obj;
2374                 IccRecords r = mIccRecords.get();
2375                 Cfu cfu = (Cfu) ar.userObj;
2376                 if (ar.exception == null && r != null) {
2377                     setVoiceCallForwardingFlag(1, msg.arg1 == 1, cfu.mSetCfNumber);
2378                 }
2379                 if (cfu.mOnComplete != null) {
2380                     AsyncResult.forMessage(cfu.mOnComplete, ar.result, ar.exception);
2381                     cfu.mOnComplete.sendToTarget();
2382                 }
2383                 break;
2384 
2385             case EVENT_SET_VM_NUMBER_DONE:
2386                 ar = (AsyncResult)msg.obj;
2387                 if ((isPhoneTypeGsm() && IccVmNotSupportedException.class.isInstance(ar.exception)) ||
2388                         (!isPhoneTypeGsm() && IccException.class.isInstance(ar.exception))){
2389                     storeVoiceMailNumber(mVmNumber);
2390                     ar.exception = null;
2391                 }
2392                 onComplete = (Message) ar.userObj;
2393                 if (onComplete != null) {
2394                     AsyncResult.forMessage(onComplete, ar.result, ar.exception);
2395                     onComplete.sendToTarget();
2396                 }
2397                 break;
2398 
2399 
2400             case EVENT_GET_CALL_FORWARD_DONE:
2401                 ar = (AsyncResult)msg.obj;
2402                 if (ar.exception == null) {
2403                     handleCfuQueryResult((CallForwardInfo[])ar.result);
2404                 }
2405                 onComplete = (Message) ar.userObj;
2406                 if (onComplete != null) {
2407                     AsyncResult.forMessage(onComplete, ar.result, ar.exception);
2408                     onComplete.sendToTarget();
2409                 }
2410                 break;
2411 
2412             case EVENT_SET_NETWORK_AUTOMATIC:
2413                 // Automatic network selection from EF_CSP SIM record
2414                 ar = (AsyncResult) msg.obj;
2415                 if (mSST.mSS.getIsManualSelection()) {
2416                     setNetworkSelectionModeAutomatic((Message) ar.result);
2417                     logd("SET_NETWORK_SELECTION_AUTOMATIC: set to automatic");
2418                 } else {
2419                     // prevent duplicate request which will push current PLMN to low priority
2420                     logd("SET_NETWORK_SELECTION_AUTOMATIC: already automatic, ignore");
2421                 }
2422                 break;
2423 
2424             case EVENT_ICC_RECORD_EVENTS:
2425                 ar = (AsyncResult)msg.obj;
2426                 processIccRecordEvents((Integer)ar.result);
2427                 break;
2428 
2429             case EVENT_SET_CLIR_COMPLETE:
2430                 ar = (AsyncResult)msg.obj;
2431                 if (ar.exception == null) {
2432                     saveClirSetting(msg.arg1);
2433                 }
2434                 onComplete = (Message) ar.userObj;
2435                 if (onComplete != null) {
2436                     AsyncResult.forMessage(onComplete, ar.result, ar.exception);
2437                     onComplete.sendToTarget();
2438                 }
2439                 break;
2440 
2441             case EVENT_SS:
2442                 ar = (AsyncResult)msg.obj;
2443                 logd("Event EVENT_SS received");
2444                 if (isPhoneTypeGsm()) {
2445                     // SS data is already being handled through MMI codes.
2446                     // So, this result if processed as MMI response would help
2447                     // in re-using the existing functionality.
2448                     GsmMmiCode mmi = new GsmMmiCode(this, mUiccApplication.get());
2449                     mmi.processSsData(ar);
2450                 }
2451                 break;
2452 
2453             case EVENT_GET_RADIO_CAPABILITY:
2454                 ar = (AsyncResult) msg.obj;
2455                 RadioCapability rc = (RadioCapability) ar.result;
2456                 if (ar.exception != null) {
2457                     Rlog.d(LOG_TAG, "get phone radio capability fail, no need to change " +
2458                             "mRadioCapability");
2459                 } else {
2460                     radioCapabilityUpdated(rc);
2461                 }
2462                 Rlog.d(LOG_TAG, "EVENT_GET_RADIO_CAPABILITY: phone rc: " + rc);
2463                 break;
2464 
2465             default:
2466                 super.handleMessage(msg);
2467         }
2468     }
2469 
getUiccCardApplication()2470     public UiccCardApplication getUiccCardApplication() {
2471         if (isPhoneTypeGsm()) {
2472             return mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP);
2473         } else {
2474             return mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2);
2475         }
2476     }
2477 
2478     @Override
onUpdateIccAvailability()2479     protected void onUpdateIccAvailability() {
2480         if (mUiccController == null ) {
2481             return;
2482         }
2483 
2484         UiccCardApplication newUiccApplication = null;
2485 
2486         // Update mIsimUiccRecords
2487         if (isPhoneTypeGsm() || isPhoneTypeCdmaLte()) {
2488             newUiccApplication =
2489                     mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_IMS);
2490             IsimUiccRecords newIsimUiccRecords = null;
2491 
2492             if (newUiccApplication != null) {
2493                 newIsimUiccRecords = (IsimUiccRecords) newUiccApplication.getIccRecords();
2494                 if (DBG) logd("New ISIM application found");
2495             }
2496             mIsimUiccRecords = newIsimUiccRecords;
2497         }
2498 
2499         // Update mSimRecords
2500         if (mSimRecords != null) {
2501             mSimRecords.unregisterForRecordsLoaded(this);
2502         }
2503         if (isPhoneTypeCdmaLte()) {
2504             newUiccApplication = mUiccController.getUiccCardApplication(mPhoneId,
2505                     UiccController.APP_FAM_3GPP);
2506             SIMRecords newSimRecords = null;
2507             if (newUiccApplication != null) {
2508                 newSimRecords = (SIMRecords) newUiccApplication.getIccRecords();
2509             }
2510             mSimRecords = newSimRecords;
2511             if (mSimRecords != null) {
2512                 mSimRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
2513             }
2514         } else {
2515             mSimRecords = null;
2516         }
2517 
2518         // Update mIccRecords, mUiccApplication, mIccPhoneBookIntManager
2519         newUiccApplication = getUiccCardApplication();
2520         if (!isPhoneTypeGsm() && newUiccApplication == null) {
2521             logd("can't find 3GPP2 application; trying APP_FAM_3GPP");
2522             newUiccApplication = mUiccController.getUiccCardApplication(mPhoneId,
2523                     UiccController.APP_FAM_3GPP);
2524         }
2525 
2526         UiccCardApplication app = mUiccApplication.get();
2527         if (app != newUiccApplication) {
2528             if (app != null) {
2529                 if (DBG) logd("Removing stale icc objects.");
2530                 if (mIccRecords.get() != null) {
2531                     unregisterForIccRecordEvents();
2532                     mIccPhoneBookIntManager.updateIccRecords(null);
2533                 }
2534                 mIccRecords.set(null);
2535                 mUiccApplication.set(null);
2536             }
2537             if (newUiccApplication != null) {
2538                 if (DBG) {
2539                     logd("New Uicc application found. type = " + newUiccApplication.getType());
2540                 }
2541                 mUiccApplication.set(newUiccApplication);
2542                 mIccRecords.set(newUiccApplication.getIccRecords());
2543                 registerForIccRecordEvents();
2544                 mIccPhoneBookIntManager.updateIccRecords(mIccRecords.get());
2545             }
2546         }
2547     }
2548 
processIccRecordEvents(int eventCode)2549     private void processIccRecordEvents(int eventCode) {
2550         switch (eventCode) {
2551             case IccRecords.EVENT_CFI:
2552                 logi("processIccRecordEvents: EVENT_CFI");
2553                 notifyCallForwardingIndicator();
2554                 break;
2555         }
2556     }
2557 
2558     /**
2559      * Sets the "current" field in the telephony provider according to the SIM's operator
2560      *
2561      * @return true for success; false otherwise.
2562      */
2563     @Override
updateCurrentCarrierInProvider()2564     public boolean updateCurrentCarrierInProvider() {
2565         if (isPhoneTypeGsm() || isPhoneTypeCdmaLte()) {
2566             long currentDds = SubscriptionManager.getDefaultDataSubscriptionId();
2567             String operatorNumeric = getOperatorNumeric();
2568 
2569             logd("updateCurrentCarrierInProvider: mSubId = " + getSubId()
2570                     + " currentDds = " + currentDds + " operatorNumeric = " + operatorNumeric);
2571 
2572             if (!TextUtils.isEmpty(operatorNumeric) && (getSubId() == currentDds)) {
2573                 try {
2574                     Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
2575                     ContentValues map = new ContentValues();
2576                     map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
2577                     mContext.getContentResolver().insert(uri, map);
2578                     return true;
2579                 } catch (SQLException e) {
2580                     Rlog.e(LOG_TAG, "Can't store current operator", e);
2581                 }
2582             }
2583             return false;
2584         } else {
2585             return true;
2586         }
2587     }
2588 
2589     //CDMA
2590     /**
2591      * Sets the "current" field in the telephony provider according to the
2592      * build-time operator numeric property
2593      *
2594      * @return true for success; false otherwise.
2595      */
updateCurrentCarrierInProvider(String operatorNumeric)2596     private boolean updateCurrentCarrierInProvider(String operatorNumeric) {
2597         if (isPhoneTypeCdma()
2598                 || (isPhoneTypeCdmaLte() && mUiccController.getUiccCardApplication(mPhoneId,
2599                         UiccController.APP_FAM_3GPP) == null)) {
2600             logd("CDMAPhone: updateCurrentCarrierInProvider called");
2601             if (!TextUtils.isEmpty(operatorNumeric)) {
2602                 try {
2603                     Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
2604                     ContentValues map = new ContentValues();
2605                     map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
2606                     logd("updateCurrentCarrierInProvider from system: numeric=" + operatorNumeric);
2607                     getContext().getContentResolver().insert(uri, map);
2608 
2609                     // Updates MCC MNC device configuration information
2610                     logd("update mccmnc=" + operatorNumeric);
2611                     MccTable.updateMccMncConfiguration(mContext, operatorNumeric, false);
2612 
2613                     return true;
2614                 } catch (SQLException e) {
2615                     Rlog.e(LOG_TAG, "Can't store current operator", e);
2616                 }
2617             }
2618             return false;
2619         } else { // isPhoneTypeCdmaLte()
2620             if (DBG) logd("updateCurrentCarrierInProvider not updated X retVal=" + true);
2621             return true;
2622         }
2623     }
2624 
handleCfuQueryResult(CallForwardInfo[] infos)2625     private void handleCfuQueryResult(CallForwardInfo[] infos) {
2626         IccRecords r = mIccRecords.get();
2627         if (r != null) {
2628             if (infos == null || infos.length == 0) {
2629                 // Assume the default is not active
2630                 // Set unconditional CFF in SIM to false
2631                 setVoiceCallForwardingFlag(1, false, null);
2632             } else {
2633                 for (int i = 0, s = infos.length; i < s; i++) {
2634                     if ((infos[i].serviceClass & SERVICE_CLASS_VOICE) != 0) {
2635                         setVoiceCallForwardingFlag(1, (infos[i].status == 1),
2636                             infos[i].number);
2637                         // should only have the one
2638                         break;
2639                     }
2640                 }
2641             }
2642         }
2643     }
2644 
2645     /**
2646      * Retrieves the IccPhoneBookInterfaceManager of the GsmCdmaPhone
2647      */
2648     @Override
getIccPhoneBookInterfaceManager()2649     public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
2650         return mIccPhoneBookIntManager;
2651     }
2652 
2653     //CDMA
registerForEriFileLoaded(Handler h, int what, Object obj)2654     public void registerForEriFileLoaded(Handler h, int what, Object obj) {
2655         Registrant r = new Registrant (h, what, obj);
2656         mEriFileLoadedRegistrants.add(r);
2657     }
2658 
2659     //CDMA
unregisterForEriFileLoaded(Handler h)2660     public void unregisterForEriFileLoaded(Handler h) {
2661         mEriFileLoadedRegistrants.remove(h);
2662     }
2663 
2664     //CDMA
prepareEri()2665     public void prepareEri() {
2666         if (mEriManager == null) {
2667             Rlog.e(LOG_TAG, "PrepareEri: Trying to access stale objects");
2668             return;
2669         }
2670         mEriManager.loadEriFile();
2671         if(mEriManager.isEriFileLoaded()) {
2672             // when the ERI file is loaded
2673             logd("ERI read, notify registrants");
2674             mEriFileLoadedRegistrants.notifyRegistrants();
2675         }
2676     }
2677 
2678     //CDMA
isEriFileLoaded()2679     public boolean isEriFileLoaded() {
2680         return mEriManager.isEriFileLoaded();
2681     }
2682 
2683 
2684     /**
2685      * Activate or deactivate cell broadcast SMS.
2686      *
2687      * @param activate 0 = activate, 1 = deactivate
2688      * @param response Callback message is empty on completion
2689      */
2690     @Override
activateCellBroadcastSms(int activate, Message response)2691     public void activateCellBroadcastSms(int activate, Message response) {
2692         loge("[GsmCdmaPhone] activateCellBroadcastSms() is obsolete; use SmsManager");
2693         response.sendToTarget();
2694     }
2695 
2696     /**
2697      * Query the current configuration of cdma cell broadcast SMS.
2698      *
2699      * @param response Callback message is empty on completion
2700      */
2701     @Override
getCellBroadcastSmsConfig(Message response)2702     public void getCellBroadcastSmsConfig(Message response) {
2703         loge("[GsmCdmaPhone] getCellBroadcastSmsConfig() is obsolete; use SmsManager");
2704         response.sendToTarget();
2705     }
2706 
2707     /**
2708      * Configure cdma cell broadcast SMS.
2709      *
2710      * @param response Callback message is empty on completion
2711      */
2712     @Override
setCellBroadcastSmsConfig(int[] configValuesArray, Message response)2713     public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) {
2714         loge("[GsmCdmaPhone] setCellBroadcastSmsConfig() is obsolete; use SmsManager");
2715         response.sendToTarget();
2716     }
2717 
2718     /**
2719      * Returns true if OTA Service Provisioning needs to be performed.
2720      */
2721     @Override
needsOtaServiceProvisioning()2722     public boolean needsOtaServiceProvisioning() {
2723         if (isPhoneTypeGsm()) {
2724             return false;
2725         } else {
2726             return mSST.getOtasp() != TelephonyManager.OTASP_NOT_NEEDED;
2727         }
2728     }
2729 
2730     @Override
isCspPlmnEnabled()2731     public boolean isCspPlmnEnabled() {
2732         IccRecords r = mIccRecords.get();
2733         return (r != null) ? r.isCspPlmnEnabled() : false;
2734     }
2735 
2736     /**
2737      * Whether manual select is now allowed and we should set
2738      * to auto network select mode.
2739      */
shouldForceAutoNetworkSelect()2740     public boolean shouldForceAutoNetworkSelect() {
2741 
2742         int nwMode = Phone.PREFERRED_NT_MODE;
2743         int subId = getSubId();
2744 
2745         // If it's invalid subId, we shouldn't force to auto network select mode.
2746         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
2747             return false;
2748         }
2749 
2750         nwMode = android.provider.Settings.Global.getInt(mContext.getContentResolver(),
2751                     android.provider.Settings.Global.PREFERRED_NETWORK_MODE + subId, nwMode);
2752 
2753         logd("shouldForceAutoNetworkSelect in mode = " + nwMode);
2754         /*
2755          *  For multimode targets in global mode manual network
2756          *  selection is disallowed. So we should force auto select mode.
2757          */
2758         if (isManualSelProhibitedInGlobalMode()
2759                 && ((nwMode == Phone.NT_MODE_LTE_CDMA_EVDO_GSM_WCDMA)
2760                         || (nwMode == Phone.NT_MODE_GLOBAL)) ){
2761             logd("Should force auto network select mode = " + nwMode);
2762             return true;
2763         } else {
2764             logd("Should not force auto network select mode = " + nwMode);
2765         }
2766 
2767         /*
2768          *  Single mode phone with - GSM network modes/global mode
2769          *  LTE only for 3GPP
2770          *  LTE centric + 3GPP Legacy
2771          *  Note: the actual enabling/disabling manual selection for these
2772          *  cases will be controlled by csp
2773          */
2774         return false;
2775     }
2776 
isManualSelProhibitedInGlobalMode()2777     private boolean isManualSelProhibitedInGlobalMode() {
2778         boolean isProhibited = false;
2779         final String configString = getContext().getResources().getString(com.android.internal.
2780                 R.string.prohibit_manual_network_selection_in_gobal_mode);
2781 
2782         if (!TextUtils.isEmpty(configString)) {
2783             String[] configArray = configString.split(";");
2784 
2785             if (configArray != null &&
2786                     ((configArray.length == 1 && configArray[0].equalsIgnoreCase("true")) ||
2787                         (configArray.length == 2 && !TextUtils.isEmpty(configArray[1]) &&
2788                             configArray[0].equalsIgnoreCase("true") &&
2789                             isMatchGid(configArray[1])))) {
2790                             isProhibited = true;
2791             }
2792         }
2793         logd("isManualNetSelAllowedInGlobal in current carrier is " + isProhibited);
2794         return isProhibited;
2795     }
2796 
registerForIccRecordEvents()2797     private void registerForIccRecordEvents() {
2798         IccRecords r = mIccRecords.get();
2799         if (r == null) {
2800             return;
2801         }
2802         if (isPhoneTypeGsm()) {
2803             r.registerForNetworkSelectionModeAutomatic(
2804                     this, EVENT_SET_NETWORK_AUTOMATIC, null);
2805             r.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null);
2806             r.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
2807         } else {
2808             r.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
2809             if (isPhoneTypeCdmaLte()) {
2810                 // notify simRecordsLoaded registrants for cdmaLte phone
2811                 r.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
2812             }
2813         }
2814     }
2815 
unregisterForIccRecordEvents()2816     private void unregisterForIccRecordEvents() {
2817         IccRecords r = mIccRecords.get();
2818         if (r == null) {
2819             return;
2820         }
2821         r.unregisterForNetworkSelectionModeAutomatic(this);
2822         r.unregisterForRecordsEvents(this);
2823         r.unregisterForRecordsLoaded(this);
2824     }
2825 
2826     @Override
exitEmergencyCallbackMode()2827     public void exitEmergencyCallbackMode() {
2828         if (DBG) {
2829             Rlog.d(LOG_TAG, "exitEmergencyCallbackMode: mImsPhone=" + mImsPhone
2830                     + " isPhoneTypeGsm=" + isPhoneTypeGsm());
2831         }
2832         if (isPhoneTypeGsm()) {
2833             if (mImsPhone != null) {
2834                 mImsPhone.exitEmergencyCallbackMode();
2835             }
2836         } else {
2837             if (mWakeLock.isHeld()) {
2838                 mWakeLock.release();
2839             }
2840             // Send a message which will invoke handleExitEmergencyCallbackMode
2841             mCi.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE));
2842         }
2843     }
2844 
2845     //CDMA
handleEnterEmergencyCallbackMode(Message msg)2846     private void handleEnterEmergencyCallbackMode(Message msg) {
2847         if (DBG) {
2848             Rlog.d(LOG_TAG, "handleEnterEmergencyCallbackMode, isInEcm()="
2849                     + isInEcm());
2850         }
2851         // if phone is not in Ecm mode, and it's changed to Ecm mode
2852         if (!isInEcm()) {
2853             setIsInEcm(true);
2854 
2855             // notify change
2856             sendEmergencyCallbackModeChange();
2857 
2858             // Post this runnable so we will automatically exit
2859             // if no one invokes exitEmergencyCallbackMode() directly.
2860             long delayInMillis = SystemProperties.getLong(
2861                     TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
2862             postDelayed(mExitEcmRunnable, delayInMillis);
2863             // We don't want to go to sleep while in Ecm
2864             mWakeLock.acquire();
2865         }
2866     }
2867 
2868     //CDMA
handleExitEmergencyCallbackMode(Message msg)2869     private void handleExitEmergencyCallbackMode(Message msg) {
2870         AsyncResult ar = (AsyncResult)msg.obj;
2871         if (DBG) {
2872             Rlog.d(LOG_TAG, "handleExitEmergencyCallbackMode,ar.exception , isInEcm="
2873                     + ar.exception + isInEcm());
2874         }
2875         // Remove pending exit Ecm runnable, if any
2876         removeCallbacks(mExitEcmRunnable);
2877 
2878         if (mEcmExitRespRegistrant != null) {
2879             mEcmExitRespRegistrant.notifyRegistrant(ar);
2880         }
2881         // if exiting ecm success
2882         if (ar.exception == null) {
2883             if (isInEcm()) {
2884                 setIsInEcm(false);
2885             }
2886 
2887             // release wakeLock
2888             if (mWakeLock.isHeld()) {
2889                 mWakeLock.release();
2890             }
2891 
2892             // send an Intent
2893             sendEmergencyCallbackModeChange();
2894             // Re-initiate data connection
2895             mDcTracker.setInternalDataEnabled(true);
2896             notifyEmergencyCallRegistrants(false);
2897         }
2898     }
2899 
2900     //CDMA
notifyEmergencyCallRegistrants(boolean started)2901     public void notifyEmergencyCallRegistrants(boolean started) {
2902         mEmergencyCallToggledRegistrants.notifyResult(started ? 1 : 0);
2903     }
2904 
2905     //CDMA
2906     /**
2907      * Handle to cancel or restart Ecm timer in emergency call back mode
2908      * if action is CANCEL_ECM_TIMER, cancel Ecm timer and notify apps the timer is canceled;
2909      * otherwise, restart Ecm timer and notify apps the timer is restarted.
2910      */
handleTimerInEmergencyCallbackMode(int action)2911     public void handleTimerInEmergencyCallbackMode(int action) {
2912         switch(action) {
2913             case CANCEL_ECM_TIMER:
2914                 removeCallbacks(mExitEcmRunnable);
2915                 mEcmTimerResetRegistrants.notifyResult(Boolean.TRUE);
2916                 break;
2917             case RESTART_ECM_TIMER:
2918                 long delayInMillis = SystemProperties.getLong(
2919                         TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE);
2920                 postDelayed(mExitEcmRunnable, delayInMillis);
2921                 mEcmTimerResetRegistrants.notifyResult(Boolean.FALSE);
2922                 break;
2923             default:
2924                 Rlog.e(LOG_TAG, "handleTimerInEmergencyCallbackMode, unsupported action " + action);
2925         }
2926     }
2927 
2928     //CDMA
2929     private static final String IS683A_FEATURE_CODE = "*228";
2930     private static final int IS683A_FEATURE_CODE_NUM_DIGITS = 4;
2931     private static final int IS683A_SYS_SEL_CODE_NUM_DIGITS = 2;
2932     private static final int IS683A_SYS_SEL_CODE_OFFSET = 4;
2933 
2934     private static final int IS683_CONST_800MHZ_A_BAND = 0;
2935     private static final int IS683_CONST_800MHZ_B_BAND = 1;
2936     private static final int IS683_CONST_1900MHZ_A_BLOCK = 2;
2937     private static final int IS683_CONST_1900MHZ_B_BLOCK = 3;
2938     private static final int IS683_CONST_1900MHZ_C_BLOCK = 4;
2939     private static final int IS683_CONST_1900MHZ_D_BLOCK = 5;
2940     private static final int IS683_CONST_1900MHZ_E_BLOCK = 6;
2941     private static final int IS683_CONST_1900MHZ_F_BLOCK = 7;
2942     private static final int INVALID_SYSTEM_SELECTION_CODE = -1;
2943 
2944     // Define the pattern/format for carrier specified OTASP number schema.
2945     // It separates by comma and/or whitespace.
2946     private static Pattern pOtaSpNumSchema = Pattern.compile("[,\\s]+");
2947 
2948     //CDMA
isIs683OtaSpDialStr(String dialStr)2949     private static boolean isIs683OtaSpDialStr(String dialStr) {
2950         int sysSelCodeInt;
2951         boolean isOtaspDialString = false;
2952         int dialStrLen = dialStr.length();
2953 
2954         if (dialStrLen == IS683A_FEATURE_CODE_NUM_DIGITS) {
2955             if (dialStr.equals(IS683A_FEATURE_CODE)) {
2956                 isOtaspDialString = true;
2957             }
2958         } else {
2959             sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr);
2960             switch (sysSelCodeInt) {
2961                 case IS683_CONST_800MHZ_A_BAND:
2962                 case IS683_CONST_800MHZ_B_BAND:
2963                 case IS683_CONST_1900MHZ_A_BLOCK:
2964                 case IS683_CONST_1900MHZ_B_BLOCK:
2965                 case IS683_CONST_1900MHZ_C_BLOCK:
2966                 case IS683_CONST_1900MHZ_D_BLOCK:
2967                 case IS683_CONST_1900MHZ_E_BLOCK:
2968                 case IS683_CONST_1900MHZ_F_BLOCK:
2969                     isOtaspDialString = true;
2970                     break;
2971                 default:
2972                     break;
2973             }
2974         }
2975         return isOtaspDialString;
2976     }
2977 
2978     //CDMA
2979     /**
2980      * This function extracts the system selection code from the dial string.
2981      */
extractSelCodeFromOtaSpNum(String dialStr)2982     private static int extractSelCodeFromOtaSpNum(String dialStr) {
2983         int dialStrLen = dialStr.length();
2984         int sysSelCodeInt = INVALID_SYSTEM_SELECTION_CODE;
2985 
2986         if ((dialStr.regionMatches(0, IS683A_FEATURE_CODE,
2987                 0, IS683A_FEATURE_CODE_NUM_DIGITS)) &&
2988                 (dialStrLen >= (IS683A_FEATURE_CODE_NUM_DIGITS +
2989                         IS683A_SYS_SEL_CODE_NUM_DIGITS))) {
2990             // Since we checked the condition above, the system selection code
2991             // extracted from dialStr will not cause any exception
2992             sysSelCodeInt = Integer.parseInt (
2993                     dialStr.substring (IS683A_FEATURE_CODE_NUM_DIGITS,
2994                             IS683A_FEATURE_CODE_NUM_DIGITS + IS683A_SYS_SEL_CODE_NUM_DIGITS));
2995         }
2996         if (DBG) Rlog.d(LOG_TAG, "extractSelCodeFromOtaSpNum " + sysSelCodeInt);
2997         return sysSelCodeInt;
2998     }
2999 
3000     //CDMA
3001     /**
3002      * This function checks if the system selection code extracted from
3003      * the dial string "sysSelCodeInt' is the system selection code specified
3004      * in the carrier ota sp number schema "sch".
3005      */
checkOtaSpNumBasedOnSysSelCode(int sysSelCodeInt, String sch[])3006     private static boolean checkOtaSpNumBasedOnSysSelCode(int sysSelCodeInt, String sch[]) {
3007         boolean isOtaSpNum = false;
3008         try {
3009             // Get how many number of system selection code ranges
3010             int selRc = Integer.parseInt(sch[1]);
3011             for (int i = 0; i < selRc; i++) {
3012                 if (!TextUtils.isEmpty(sch[i+2]) && !TextUtils.isEmpty(sch[i+3])) {
3013                     int selMin = Integer.parseInt(sch[i+2]);
3014                     int selMax = Integer.parseInt(sch[i+3]);
3015                     // Check if the selection code extracted from the dial string falls
3016                     // within any of the range pairs specified in the schema.
3017                     if ((sysSelCodeInt >= selMin) && (sysSelCodeInt <= selMax)) {
3018                         isOtaSpNum = true;
3019                         break;
3020                     }
3021                 }
3022             }
3023         } catch (NumberFormatException ex) {
3024             // If the carrier ota sp number schema is not correct, we still allow dial
3025             // and only log the error:
3026             Rlog.e(LOG_TAG, "checkOtaSpNumBasedOnSysSelCode, error", ex);
3027         }
3028         return isOtaSpNum;
3029     }
3030 
3031     //CDMA
3032     /**
3033      * The following function checks if a dial string is a carrier specified
3034      * OTASP number or not by checking against the OTASP number schema stored
3035      * in PROPERTY_OTASP_NUM_SCHEMA.
3036      *
3037      * Currently, there are 2 schemas for carriers to specify the OTASP number:
3038      * 1) Use system selection code:
3039      *    The schema is:
3040      *    SELC,the # of code pairs,min1,max1,min2,max2,...
3041      *    e.g "SELC,3,10,20,30,40,60,70" indicates that there are 3 pairs of
3042      *    selection codes, and they are {10,20}, {30,40} and {60,70} respectively.
3043      *
3044      * 2) Use feature code:
3045      *    The schema is:
3046      *    "FC,length of feature code,feature code".
3047      *     e.g "FC,2,*2" indicates that the length of the feature code is 2,
3048      *     and the code itself is "*2".
3049      */
isCarrierOtaSpNum(String dialStr)3050     private boolean isCarrierOtaSpNum(String dialStr) {
3051         boolean isOtaSpNum = false;
3052         int sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr);
3053         if (sysSelCodeInt == INVALID_SYSTEM_SELECTION_CODE) {
3054             return isOtaSpNum;
3055         }
3056         // mCarrierOtaSpNumSchema is retrieved from PROPERTY_OTASP_NUM_SCHEMA:
3057         if (!TextUtils.isEmpty(mCarrierOtaSpNumSchema)) {
3058             Matcher m = pOtaSpNumSchema.matcher(mCarrierOtaSpNumSchema);
3059             if (DBG) {
3060                 Rlog.d(LOG_TAG, "isCarrierOtaSpNum,schema" + mCarrierOtaSpNumSchema);
3061             }
3062 
3063             if (m.find()) {
3064                 String sch[] = pOtaSpNumSchema.split(mCarrierOtaSpNumSchema);
3065                 // If carrier uses system selection code mechanism
3066                 if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("SELC")) {
3067                     if (sysSelCodeInt!=INVALID_SYSTEM_SELECTION_CODE) {
3068                         isOtaSpNum=checkOtaSpNumBasedOnSysSelCode(sysSelCodeInt,sch);
3069                     } else {
3070                         if (DBG) {
3071                             Rlog.d(LOG_TAG, "isCarrierOtaSpNum,sysSelCodeInt is invalid");
3072                         }
3073                     }
3074                 } else if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("FC")) {
3075                     int fcLen =  Integer.parseInt(sch[1]);
3076                     String fc = sch[2];
3077                     if (dialStr.regionMatches(0,fc,0,fcLen)) {
3078                         isOtaSpNum = true;
3079                     } else {
3080                         if (DBG) Rlog.d(LOG_TAG, "isCarrierOtaSpNum,not otasp number");
3081                     }
3082                 } else {
3083                     if (DBG) {
3084                         Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema not supported" + sch[0]);
3085                     }
3086                 }
3087             } else {
3088                 if (DBG) {
3089                     Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern not right" +
3090                             mCarrierOtaSpNumSchema);
3091                 }
3092             }
3093         } else {
3094             if (DBG) Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern empty");
3095         }
3096         return isOtaSpNum;
3097     }
3098 
3099     /**
3100      * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier
3101      * OTASP dial string.
3102      *
3103      * @param dialStr the number to look up.
3104      * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string
3105      */
3106     @Override
isOtaSpNumber(String dialStr)3107     public  boolean isOtaSpNumber(String dialStr) {
3108         if (isPhoneTypeGsm()) {
3109             return super.isOtaSpNumber(dialStr);
3110         } else {
3111             boolean isOtaSpNum = false;
3112             String dialableStr = PhoneNumberUtils.extractNetworkPortionAlt(dialStr);
3113             if (dialableStr != null) {
3114                 isOtaSpNum = isIs683OtaSpDialStr(dialableStr);
3115                 if (isOtaSpNum == false) {
3116                     isOtaSpNum = isCarrierOtaSpNum(dialableStr);
3117                 }
3118             }
3119             if (DBG) Rlog.d(LOG_TAG, "isOtaSpNumber " + isOtaSpNum);
3120             return isOtaSpNum;
3121         }
3122     }
3123 
3124     @Override
getCdmaEriIconIndex()3125     public int getCdmaEriIconIndex() {
3126         if (isPhoneTypeGsm()) {
3127             return super.getCdmaEriIconIndex();
3128         } else {
3129             return getServiceState().getCdmaEriIconIndex();
3130         }
3131     }
3132 
3133     /**
3134      * Returns the CDMA ERI icon mode,
3135      * 0 - ON
3136      * 1 - FLASHING
3137      */
3138     @Override
getCdmaEriIconMode()3139     public int getCdmaEriIconMode() {
3140         if (isPhoneTypeGsm()) {
3141             return super.getCdmaEriIconMode();
3142         } else {
3143             return getServiceState().getCdmaEriIconMode();
3144         }
3145     }
3146 
3147     /**
3148      * Returns the CDMA ERI text,
3149      */
3150     @Override
getCdmaEriText()3151     public String getCdmaEriText() {
3152         if (isPhoneTypeGsm()) {
3153             return super.getCdmaEriText();
3154         } else {
3155             int roamInd = getServiceState().getCdmaRoamingIndicator();
3156             int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
3157             return mEriManager.getCdmaEriText(roamInd, defRoamInd);
3158         }
3159     }
3160 
phoneObjectUpdater(int newVoiceRadioTech)3161     private void phoneObjectUpdater(int newVoiceRadioTech) {
3162         logd("phoneObjectUpdater: newVoiceRadioTech=" + newVoiceRadioTech);
3163 
3164         // Check for a voice over lte replacement
3165         if (ServiceState.isLte(newVoiceRadioTech)
3166                 || (newVoiceRadioTech == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)) {
3167             CarrierConfigManager configMgr = (CarrierConfigManager)
3168                     getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
3169             PersistableBundle b = configMgr.getConfigForSubId(getSubId());
3170             if (b != null) {
3171                 int volteReplacementRat =
3172                         b.getInt(CarrierConfigManager.KEY_VOLTE_REPLACEMENT_RAT_INT);
3173                 logd("phoneObjectUpdater: volteReplacementRat=" + volteReplacementRat);
3174                 if (volteReplacementRat != ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
3175                     newVoiceRadioTech = volteReplacementRat;
3176                 }
3177             } else {
3178                 loge("phoneObjectUpdater: didn't get volteReplacementRat from carrier config");
3179             }
3180         }
3181 
3182         if(mRilVersion == 6 && getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) {
3183             /*
3184              * On v6 RIL, when LTE_ON_CDMA is TRUE, always create CDMALTEPhone
3185              * irrespective of the voice radio tech reported.
3186              */
3187             if (getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
3188                 logd("phoneObjectUpdater: LTE ON CDMA property is set. Use CDMA Phone" +
3189                         " newVoiceRadioTech=" + newVoiceRadioTech +
3190                         " mActivePhone=" + getPhoneName());
3191                 return;
3192             } else {
3193                 logd("phoneObjectUpdater: LTE ON CDMA property is set. Switch to CDMALTEPhone" +
3194                         " newVoiceRadioTech=" + newVoiceRadioTech +
3195                         " mActivePhone=" + getPhoneName());
3196                 newVoiceRadioTech = ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT;
3197             }
3198         } else {
3199 
3200             // If the device is shutting down, then there is no need to switch to the new phone
3201             // which might send unnecessary attach request to the modem.
3202             if (isShuttingDown()) {
3203                 logd("Device is shutting down. No need to switch phone now.");
3204                 return;
3205             }
3206 
3207             boolean matchCdma = ServiceState.isCdma(newVoiceRadioTech);
3208             boolean matchGsm = ServiceState.isGsm(newVoiceRadioTech);
3209             if ((matchCdma && getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) ||
3210                     (matchGsm && getPhoneType() == PhoneConstants.PHONE_TYPE_GSM)) {
3211                 // Nothing changed. Keep phone as it is.
3212                 logd("phoneObjectUpdater: No change ignore," +
3213                         " newVoiceRadioTech=" + newVoiceRadioTech +
3214                         " mActivePhone=" + getPhoneName());
3215                 return;
3216             }
3217             if (!matchCdma && !matchGsm) {
3218                 loge("phoneObjectUpdater: newVoiceRadioTech=" + newVoiceRadioTech +
3219                         " doesn't match either CDMA or GSM - error! No phone change");
3220                 return;
3221             }
3222         }
3223 
3224         if (newVoiceRadioTech == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
3225             // We need some voice phone object to be active always, so never
3226             // delete the phone without anything to replace it with!
3227             logd("phoneObjectUpdater: Unknown rat ignore, "
3228                     + " newVoiceRadioTech=Unknown. mActivePhone=" + getPhoneName());
3229             return;
3230         }
3231 
3232         boolean oldPowerState = false; // old power state to off
3233         if (mResetModemOnRadioTechnologyChange) {
3234             if (mCi.getRadioState().isOn()) {
3235                 oldPowerState = true;
3236                 logd("phoneObjectUpdater: Setting Radio Power to Off");
3237                 mCi.setRadioPower(false, null);
3238             }
3239         }
3240 
3241         switchVoiceRadioTech(newVoiceRadioTech);
3242 
3243         if (mResetModemOnRadioTechnologyChange && oldPowerState) { // restore power state
3244             logd("phoneObjectUpdater: Resetting Radio");
3245             mCi.setRadioPower(oldPowerState, null);
3246         }
3247 
3248         // update voice radio tech in icc card proxy
3249         mIccCardProxy.setVoiceRadioTech(newVoiceRadioTech);
3250 
3251         // Send an Intent to the PhoneApp that we had a radio technology change
3252         Intent intent = new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
3253         intent.putExtra(PhoneConstants.PHONE_NAME_KEY, getPhoneName());
3254         SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhoneId);
3255         ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL);
3256     }
3257 
switchVoiceRadioTech(int newVoiceRadioTech)3258     private void switchVoiceRadioTech(int newVoiceRadioTech) {
3259 
3260         String outgoingPhoneName = getPhoneName();
3261 
3262         logd("Switching Voice Phone : " + outgoingPhoneName + " >>> "
3263                 + (ServiceState.isGsm(newVoiceRadioTech) ? "GSM" : "CDMA"));
3264 
3265         if (ServiceState.isCdma(newVoiceRadioTech)) {
3266             switchPhoneType(PhoneConstants.PHONE_TYPE_CDMA_LTE);
3267         } else if (ServiceState.isGsm(newVoiceRadioTech)) {
3268             switchPhoneType(PhoneConstants.PHONE_TYPE_GSM);
3269         } else {
3270             loge("deleteAndCreatePhone: newVoiceRadioTech=" + newVoiceRadioTech +
3271                     " is not CDMA or GSM (error) - aborting!");
3272             return;
3273         }
3274     }
3275 
3276     @Override
getIccSmsInterfaceManager()3277     public IccSmsInterfaceManager getIccSmsInterfaceManager(){
3278         return mIccSmsInterfaceManager;
3279     }
3280 
3281     @Override
updatePhoneObject(int voiceRadioTech)3282     public void updatePhoneObject(int voiceRadioTech) {
3283         logd("updatePhoneObject: radioTechnology=" + voiceRadioTech);
3284         sendMessage(obtainMessage(EVENT_UPDATE_PHONE_OBJECT, voiceRadioTech, 0, null));
3285     }
3286 
3287     @Override
setImsRegistrationState(boolean registered)3288     public void setImsRegistrationState(boolean registered) {
3289         mSST.setImsRegistrationState(registered);
3290     }
3291 
3292     @Override
getIccRecordsLoaded()3293     public boolean getIccRecordsLoaded() {
3294         return mIccCardProxy.getIccRecordsLoaded();
3295     }
3296 
3297     @Override
getIccCard()3298     public IccCard getIccCard() {
3299         return mIccCardProxy;
3300     }
3301 
3302     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)3303     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
3304         pw.println("GsmCdmaPhone extends:");
3305         super.dump(fd, pw, args);
3306         pw.println(" mPrecisePhoneType=" + mPrecisePhoneType);
3307         pw.println(" mCT=" + mCT);
3308         pw.println(" mSST=" + mSST);
3309         pw.println(" mPendingMMIs=" + mPendingMMIs);
3310         pw.println(" mIccPhoneBookIntManager=" + mIccPhoneBookIntManager);
3311         if (VDBG) pw.println(" mImei=" + mImei);
3312         if (VDBG) pw.println(" mImeiSv=" + mImeiSv);
3313         if (VDBG) pw.println(" mVmNumber=" + mVmNumber);
3314         pw.println(" mCdmaSSM=" + mCdmaSSM);
3315         pw.println(" mCdmaSubscriptionSource=" + mCdmaSubscriptionSource);
3316         pw.println(" mEriManager=" + mEriManager);
3317         pw.println(" mWakeLock=" + mWakeLock);
3318         pw.println(" isInEcm()=" + isInEcm());
3319         if (VDBG) pw.println(" mEsn=" + mEsn);
3320         if (VDBG) pw.println(" mMeid=" + mMeid);
3321         pw.println(" mCarrierOtaSpNumSchema=" + mCarrierOtaSpNumSchema);
3322         if (!isPhoneTypeGsm()) {
3323             pw.println(" getCdmaEriIconIndex()=" + getCdmaEriIconIndex());
3324             pw.println(" getCdmaEriIconMode()=" + getCdmaEriIconMode());
3325             pw.println(" getCdmaEriText()=" + getCdmaEriText());
3326             pw.println(" isMinInfoReady()=" + isMinInfoReady());
3327         }
3328         pw.println(" isCspPlmnEnabled()=" + isCspPlmnEnabled());
3329         pw.flush();
3330         pw.println("++++++++++++++++++++++++++++++++");
3331 
3332         try {
3333             mIccCardProxy.dump(fd, pw, args);
3334         } catch (Exception e) {
3335             e.printStackTrace();
3336         }
3337         pw.flush();
3338         pw.println("++++++++++++++++++++++++++++++++");
3339         pw.println("DeviceStateMonitor:");
3340         mDeviceStateMonitor.dump(fd, pw, args);
3341         pw.println("++++++++++++++++++++++++++++++++");
3342     }
3343 
3344     @Override
setOperatorBrandOverride(String brand)3345     public boolean setOperatorBrandOverride(String brand) {
3346         if (mUiccController == null) {
3347             return false;
3348         }
3349 
3350         UiccCard card = mUiccController.getUiccCard(getPhoneId());
3351         if (card == null) {
3352             return false;
3353         }
3354 
3355         boolean status = card.setOperatorBrandOverride(brand);
3356 
3357         // Refresh.
3358         if (status) {
3359             IccRecords iccRecords = mIccRecords.get();
3360             if (iccRecords != null) {
3361                 TelephonyManager.from(mContext).setSimOperatorNameForPhone(
3362                         getPhoneId(), iccRecords.getServiceProviderName());
3363             }
3364             if (mSST != null) {
3365                 mSST.pollState();
3366             }
3367         }
3368         return status;
3369     }
3370 
3371     /**
3372      * @return operator numeric.
3373      */
getOperatorNumeric()3374     private String getOperatorNumeric() {
3375         String operatorNumeric = null;
3376         if (isPhoneTypeGsm()) {
3377             IccRecords r = mIccRecords.get();
3378             if (r != null) {
3379                 operatorNumeric = r.getOperatorNumeric();
3380             }
3381         } else { //isPhoneTypeCdmaLte()
3382             IccRecords curIccRecords = null;
3383             if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_NV) {
3384                 operatorNumeric = SystemProperties.get("ro.cdma.home.operator.numeric");
3385             } else if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_RUIM_SIM) {
3386                 curIccRecords = mSimRecords;
3387                 if (curIccRecords != null) {
3388                     operatorNumeric = curIccRecords.getOperatorNumeric();
3389                 } else {
3390                     curIccRecords = mIccRecords.get();
3391                     if (curIccRecords != null && (curIccRecords instanceof RuimRecords)) {
3392                         RuimRecords csim = (RuimRecords) curIccRecords;
3393                         operatorNumeric = csim.getRUIMOperatorNumeric();
3394                     }
3395                 }
3396             }
3397             if (operatorNumeric == null) {
3398                 loge("getOperatorNumeric: Cannot retrieve operatorNumeric:"
3399                         + " mCdmaSubscriptionSource = " + mCdmaSubscriptionSource +
3400                         " mIccRecords = " + ((curIccRecords != null) ?
3401                         curIccRecords.getRecordsLoaded() : null));
3402             }
3403 
3404             logd("getOperatorNumeric: mCdmaSubscriptionSource = " + mCdmaSubscriptionSource
3405                     + " operatorNumeric = " + operatorNumeric);
3406 
3407         }
3408         return operatorNumeric;
3409     }
3410 
3411     /**
3412      * @return The country ISO for the subscription associated with this phone.
3413      */
getCountryIso()3414     public String getCountryIso() {
3415         int subId = getSubId();
3416         SubscriptionInfo subInfo = SubscriptionManager.from(getContext())
3417                 .getActiveSubscriptionInfo(subId);
3418         if (subInfo == null) {
3419             return null;
3420         }
3421         return subInfo.getCountryIso().toUpperCase();
3422     }
3423 
notifyEcbmTimerReset(Boolean flag)3424     public void notifyEcbmTimerReset(Boolean flag) {
3425         mEcmTimerResetRegistrants.notifyResult(flag);
3426     }
3427 
3428     /**
3429      * Registration point for Ecm timer reset
3430      *
3431      * @param h handler to notify
3432      * @param what User-defined message code
3433      * @param obj placed in Message.obj
3434      */
3435     @Override
registerForEcmTimerReset(Handler h, int what, Object obj)3436     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
3437         mEcmTimerResetRegistrants.addUnique(h, what, obj);
3438     }
3439 
3440     @Override
unregisterForEcmTimerReset(Handler h)3441     public void unregisterForEcmTimerReset(Handler h) {
3442         mEcmTimerResetRegistrants.remove(h);
3443     }
3444 
3445     /**
3446      * Sets the SIM voice message waiting indicator records.
3447      * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
3448      * @param countWaiting The number of messages waiting, if known. Use
3449      *                     -1 to indicate that an unknown number of
3450      *                      messages are waiting
3451      */
3452     @Override
setVoiceMessageWaiting(int line, int countWaiting)3453     public void setVoiceMessageWaiting(int line, int countWaiting) {
3454         if (isPhoneTypeGsm()) {
3455             IccRecords r = mIccRecords.get();
3456             if (r != null) {
3457                 r.setVoiceMessageWaiting(line, countWaiting);
3458             } else {
3459                 logd("SIM Records not found, MWI not updated");
3460             }
3461         } else {
3462             setVoiceMessageCount(countWaiting);
3463         }
3464     }
3465 
logd(String s)3466     private void logd(String s) {
3467         Rlog.d(LOG_TAG, "[GsmCdmaPhone] " + s);
3468     }
3469 
logi(String s)3470     private void logi(String s) {
3471         Rlog.i(LOG_TAG, "[GsmCdmaPhone] " + s);
3472     }
3473 
loge(String s)3474     private void loge(String s) {
3475         Rlog.e(LOG_TAG, "[GsmCdmaPhone] " + s);
3476     }
3477 
3478     @Override
isUtEnabled()3479     public boolean isUtEnabled() {
3480         Phone imsPhone = mImsPhone;
3481         if (imsPhone != null) {
3482             return imsPhone.isUtEnabled();
3483         } else {
3484             logd("isUtEnabled: called for GsmCdma");
3485             return false;
3486         }
3487     }
3488 
getDtmfToneDelayKey()3489     public String getDtmfToneDelayKey() {
3490         return isPhoneTypeGsm() ?
3491                 CarrierConfigManager.KEY_GSM_DTMF_TONE_DELAY_INT :
3492                 CarrierConfigManager.KEY_CDMA_DTMF_TONE_DELAY_INT;
3493     }
3494 
3495     @VisibleForTesting
getWakeLock()3496     public PowerManager.WakeLock getWakeLock() {
3497         return mWakeLock;
3498     }
3499 
3500 }
3501