• 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 import static com.android.internal.telephony.CommandException.Error.GENERIC_FAILURE;
19 import static com.android.internal.telephony.CommandException.Error.SIM_BUSY;
20 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_DISABLE;
21 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE;
22 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ERASURE;
23 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_REGISTRATION;
24 import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL;
25 import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL_CONDITIONAL;
26 import static com.android.internal.telephony.CommandsInterface.CF_REASON_BUSY;
27 import static com.android.internal.telephony.CommandsInterface.CF_REASON_NOT_REACHABLE;
28 import static com.android.internal.telephony.CommandsInterface.CF_REASON_NO_REPLY;
29 import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL;
30 import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE;
31 
32 import android.annotation.NonNull;
33 import android.annotation.Nullable;
34 import android.compat.annotation.UnsupportedAppUsage;
35 import android.content.BroadcastReceiver;
36 import android.content.ContentValues;
37 import android.content.Context;
38 import android.content.Intent;
39 import android.content.IntentFilter;
40 import android.content.SharedPreferences;
41 import android.database.SQLException;
42 import android.net.Uri;
43 import android.os.AsyncResult;
44 import android.os.Build;
45 import android.os.Bundle;
46 import android.os.Handler;
47 import android.os.Message;
48 import android.os.PersistableBundle;
49 import android.os.PowerManager;
50 import android.os.Registrant;
51 import android.os.RegistrantList;
52 import android.os.ResultReceiver;
53 import android.os.SystemProperties;
54 import android.os.UserHandle;
55 import android.os.WorkSource;
56 import android.preference.PreferenceManager;
57 import android.provider.Settings;
58 import android.provider.Telephony;
59 import android.sysprop.TelephonyProperties;
60 import android.telecom.PhoneAccount;
61 import android.telecom.PhoneAccountHandle;
62 import android.telecom.TelecomManager;
63 import android.telecom.VideoProfile;
64 import android.telephony.AccessNetworkConstants;
65 import android.telephony.Annotation.RadioPowerState;
66 import android.telephony.BarringInfo;
67 import android.telephony.CarrierConfigManager;
68 import android.telephony.CellIdentity;
69 import android.telephony.ImsiEncryptionInfo;
70 import android.telephony.LinkCapacityEstimate;
71 import android.telephony.NetworkScanRequest;
72 import android.telephony.PhoneNumberUtils;
73 import android.telephony.RadioAccessFamily;
74 import android.telephony.ServiceState;
75 import android.telephony.ServiceState.RilRadioTechnology;
76 import android.telephony.SignalThresholdInfo;
77 import android.telephony.SubscriptionInfo;
78 import android.telephony.SubscriptionManager;
79 import android.telephony.TelephonyManager;
80 import android.telephony.UiccAccessRule;
81 import android.telephony.UssdResponse;
82 import android.telephony.data.ApnSetting;
83 import android.text.TextUtils;
84 import android.util.Log;
85 import android.util.Pair;
86 
87 import com.android.ims.ImsManager;
88 import com.android.internal.annotations.VisibleForTesting;
89 import com.android.internal.telephony.cdma.CdmaMmiCode;
90 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager;
91 import com.android.internal.telephony.dataconnection.DataEnabledSettings;
92 import com.android.internal.telephony.dataconnection.DcTracker;
93 import com.android.internal.telephony.dataconnection.LinkBandwidthEstimator;
94 import com.android.internal.telephony.dataconnection.TransportManager;
95 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
96 import com.android.internal.telephony.gsm.GsmMmiCode;
97 import com.android.internal.telephony.gsm.SuppServiceNotification;
98 import com.android.internal.telephony.imsphone.ImsPhone;
99 import com.android.internal.telephony.imsphone.ImsPhoneCallTracker;
100 import com.android.internal.telephony.imsphone.ImsPhoneMmiCode;
101 import com.android.internal.telephony.metrics.TelephonyMetrics;
102 import com.android.internal.telephony.metrics.VoiceCallSessionStats;
103 import com.android.internal.telephony.test.SimulatedRadioControl;
104 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType;
105 import com.android.internal.telephony.uicc.IccCardStatus;
106 import com.android.internal.telephony.uicc.IccException;
107 import com.android.internal.telephony.uicc.IccRecords;
108 import com.android.internal.telephony.uicc.IccUtils;
109 import com.android.internal.telephony.uicc.IccVmNotSupportedException;
110 import com.android.internal.telephony.uicc.IsimRecords;
111 import com.android.internal.telephony.uicc.IsimUiccRecords;
112 import com.android.internal.telephony.uicc.RuimRecords;
113 import com.android.internal.telephony.uicc.SIMRecords;
114 import com.android.internal.telephony.uicc.UiccCard;
115 import com.android.internal.telephony.uicc.UiccCardApplication;
116 import com.android.internal.telephony.uicc.UiccController;
117 import com.android.internal.telephony.uicc.UiccProfile;
118 import com.android.internal.telephony.uicc.UiccSlot;
119 import com.android.internal.telephony.util.ArrayUtils;
120 import com.android.telephony.Rlog;
121 
122 import java.io.FileDescriptor;
123 import java.io.PrintWriter;
124 import java.util.ArrayList;
125 import java.util.Arrays;
126 import java.util.Collections;
127 import java.util.Iterator;
128 import java.util.List;
129 import java.util.function.Consumer;
130 import java.util.regex.Matcher;
131 import java.util.regex.Pattern;
132 
133 /**
134  * {@hide}
135  */
136 public class GsmCdmaPhone extends Phone {
137     // NOTE that LOG_TAG here is "GsmCdma", which means that log messages
138     // from this file will go into the radio log rather than the main
139     // log.  (Use "adb logcat -b radio" to see them.)
140     public static final String LOG_TAG = "GsmCdmaPhone";
141     private static final boolean DBG = true;
142     private static final boolean VDBG = false; /* STOPSHIP if true */
143 
144     /** Required magnitude change between unsolicited SignalStrength reports. */
145     private static final int REPORTING_HYSTERESIS_DB = 2;
146     /** Required throughput change between unsolicited LinkCapacityEstimate reports. */
147     private static final int REPORTING_HYSTERESIS_KBPS = 50;
148     /** Minimum time between unsolicited SignalStrength and LinkCapacityEstimate reports. */
149     private static final int REPORTING_HYSTERESIS_MILLIS = 3000;
150 
151     //GSM
152     // Key used to read/write voice mail number
153     private static final String VM_NUMBER = "vm_number_key";
154     // Key used to read/write the SIM IMSI used for storing the voice mail
155     private static final String VM_SIM_IMSI = "vm_sim_imsi_key";
156     /** List of Registrants to receive Supplementary Service Notifications. */
157     private RegistrantList mSsnRegistrants = new RegistrantList();
158 
159     //CDMA
160     // Default Emergency Callback Mode exit timer
161     private static final long DEFAULT_ECM_EXIT_TIMER_VALUE = 300000;
162     private static final String VM_NUMBER_CDMA = "vm_number_key_cdma";
163     public static final int RESTART_ECM_TIMER = 0; // restart Ecm timer
164     public static final int CANCEL_ECM_TIMER = 1; // cancel Ecm timer
165     private static final String PREFIX_WPS = "*272";
166     // WPS prefix when CLIR is being deactivated for the call.
167     private static final String PREFIX_WPS_CLIR_DEACTIVATE = "#31#*272";
168     // WPS prefix when CLIS is being activated for the call.
169     private static final String PREFIX_WPS_CLIR_ACTIVATE = "*31#*272";
170     private CdmaSubscriptionSourceManager mCdmaSSM;
171     public int mCdmaSubscriptionSource = CdmaSubscriptionSourceManager.SUBSCRIPTION_SOURCE_UNKNOWN;
172     private PowerManager.WakeLock mWakeLock;
173     // mEcmExitRespRegistrant is informed after the phone has been exited
174     @UnsupportedAppUsage
175     private Registrant mEcmExitRespRegistrant;
176     private String mEsn;
177     private String mMeid;
178     // string to define how the carrier specifies its own ota sp number
179     private String mCarrierOtaSpNumSchema;
180     private Boolean mUiccApplicationsEnabled = null;
181     // keeps track of when we have triggered an emergency call due to the ril.test.emergencynumber
182     // param being set and we should generate a simulated exit from the modem upon exit of ECbM.
183     private boolean mIsTestingEmergencyCallbackMode = false;
184     @VisibleForTesting
185     public static int ENABLE_UICC_APPS_MAX_RETRIES = 3;
186     private static final int REAPPLY_UICC_APPS_SETTING_RETRY_TIME_GAP_IN_MS = 5000;
187 
188     // A runnable which is used to automatically exit from Ecm after a period of time.
189     private Runnable mExitEcmRunnable = new Runnable() {
190         @Override
191         public void run() {
192             exitEmergencyCallbackMode();
193         }
194     };
195     public static final String PROPERTY_CDMA_HOME_OPERATOR_NUMERIC =
196             "ro.cdma.home.operator.numeric";
197 
198     //CDMALTE
199     /** PHONE_TYPE_CDMA_LTE in addition to RuimRecords needs access to SIMRecords and
200      * IsimUiccRecords
201      */
202     private SIMRecords mSimRecords;
203 
204     // For non-persisted manual network selection
205     private String mManualNetworkSelectionPlmn;
206 
207     //Common
208     // Instance Variables
209     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
210     private IsimUiccRecords mIsimUiccRecords;
211     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
212     public GsmCdmaCallTracker mCT;
213     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
214     public ServiceStateTracker mSST;
215     public EmergencyNumberTracker mEmergencyNumberTracker;
216     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
217     private ArrayList <MmiCode> mPendingMMIs = new ArrayList<MmiCode>();
218     private IccPhoneBookInterfaceManager mIccPhoneBookIntManager;
219 
220     private int mPrecisePhoneType;
221 
222     // mEcmTimerResetRegistrants are informed after Ecm timer is canceled or re-started
223     private final RegistrantList mEcmTimerResetRegistrants = new RegistrantList();
224 
225     private final RegistrantList mVolteSilentRedialRegistrants = new RegistrantList();
226     private DialArgs mDialArgs = null;
227 
228     private String mImei;
229     private String mImeiSv;
230     private String mVmNumber;
231 
232     // Create Cfu (Call forward unconditional) so that dialing number &
233     // mOnComplete (Message object passed by client) can be packed &
234     // given as a single Cfu object as user data to RIL.
235     private static class Cfu {
236         final String mSetCfNumber;
237         final Message mOnComplete;
238 
239         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Cfu(String cfNumber, Message onComplete)240         Cfu(String cfNumber, Message onComplete) {
241             mSetCfNumber = cfNumber;
242             mOnComplete = onComplete;
243         }
244     }
245 
246     /**
247      * Used to create ImsManager instances, which may be injected during testing.
248      */
249     @VisibleForTesting
250     public interface ImsManagerFactory {
251         /**
252          * Create a new instance of ImsManager for the specified phoneId.
253          */
create(Context context, int phoneId)254         ImsManager create(Context context, int phoneId);
255     }
256 
257     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
258     private IccSmsInterfaceManager mIccSmsInterfaceManager;
259 
260     private boolean mResetModemOnRadioTechnologyChange = false;
261     private boolean mSsOverCdmaSupported = false;
262 
263     private int mRilVersion;
264     private boolean mBroadcastEmergencyCallStateChanges = false;
265     private CarrierKeyDownloadManager mCDM;
266     private CarrierInfoManager mCIM;
267 
268     private final SettingsObserver mSettingsObserver;
269 
270     private final ImsManagerFactory mImsManagerFactory;
271 
272     // Constructors
273 
GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId, int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory)274     public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId,
275                         int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory) {
276         this(context, ci, notifier, false, phoneId, precisePhoneType, telephonyComponentFactory);
277     }
278 
GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode, int phoneId, int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory)279     public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
280                         boolean unitTestMode, int phoneId, int precisePhoneType,
281                         TelephonyComponentFactory telephonyComponentFactory) {
282         this(context, ci, notifier,
283                 unitTestMode, phoneId, precisePhoneType,
284                 telephonyComponentFactory,
285                 ImsManager::getInstance);
286     }
287 
GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode, int phoneId, int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory, ImsManagerFactory imsManagerFactory)288     public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier,
289             boolean unitTestMode, int phoneId, int precisePhoneType,
290             TelephonyComponentFactory telephonyComponentFactory,
291             ImsManagerFactory imsManagerFactory) {
292         super(precisePhoneType == PhoneConstants.PHONE_TYPE_GSM ? "GSM" : "CDMA",
293                 notifier, context, ci, unitTestMode, phoneId, telephonyComponentFactory);
294 
295         // phone type needs to be set before other initialization as other objects rely on it
296         mPrecisePhoneType = precisePhoneType;
297         mVoiceCallSessionStats = new VoiceCallSessionStats(mPhoneId, this);
298         mImsManagerFactory = imsManagerFactory;
299         initOnce(ci);
300         initRatSpecific(precisePhoneType);
301         // CarrierSignalAgent uses CarrierActionAgent in construction so it needs to be created
302         // after CarrierActionAgent.
303         mCarrierActionAgent = mTelephonyComponentFactory.inject(CarrierActionAgent.class.getName())
304                 .makeCarrierActionAgent(this);
305         mCarrierSignalAgent = mTelephonyComponentFactory.inject(CarrierSignalAgent.class.getName())
306                 .makeCarrierSignalAgent(this);
307         mTransportManager = mTelephonyComponentFactory.inject(TransportManager.class.getName())
308                 .makeTransportManager(this);
309         mSST = mTelephonyComponentFactory.inject(ServiceStateTracker.class.getName())
310                 .makeServiceStateTracker(this, this.mCi);
311         mEmergencyNumberTracker = mTelephonyComponentFactory
312                 .inject(EmergencyNumberTracker.class.getName()).makeEmergencyNumberTracker(
313                         this, this.mCi);
314         mDataEnabledSettings = mTelephonyComponentFactory
315                 .inject(DataEnabledSettings.class.getName()).makeDataEnabledSettings(this);
316         mDeviceStateMonitor = mTelephonyComponentFactory.inject(DeviceStateMonitor.class.getName())
317                 .makeDeviceStateMonitor(this);
318 
319         // DisplayInfoController creates an OverrideNetworkTypeController, which uses
320         // DeviceStateMonitor so needs to be crated after it is instantiated.
321         mDisplayInfoController = mTelephonyComponentFactory.inject(
322                 DisplayInfoController.class.getName()).makeDisplayInfoController(this);
323 
324         // DcTracker uses ServiceStateTracker and DisplayInfoController so needs to be created
325         // after they are instantiated
326         for (int transport : mTransportManager.getAvailableTransports()) {
327             DcTracker dcTracker = mTelephonyComponentFactory.inject(DcTracker.class.getName())
328                     .makeDcTracker(this, transport);
329             mDcTrackers.put(transport, dcTracker);
330             mTransportManager.registerDataThrottler(dcTracker.getDataThrottler());
331         }
332 
333         mCarrierResolver = mTelephonyComponentFactory.inject(CarrierResolver.class.getName())
334                 .makeCarrierResolver(this);
335 
336         getCarrierActionAgent().registerForCarrierAction(
337                 CarrierActionAgent.CARRIER_ACTION_SET_METERED_APNS_ENABLED, this,
338                 EVENT_SET_CARRIER_DATA_ENABLED, null, false);
339 
340         mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null);
341         mSST.registerForVoiceRegStateOrRatChanged(this, EVENT_VRS_OR_RAT_CHANGED, null);
342 
343         mSettingsObserver = new SettingsObserver(context, this);
344         mSettingsObserver.observe(
345                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
346                 EVENT_DEVICE_PROVISIONED_CHANGE);
347         mSettingsObserver.observe(
348                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED),
349                 EVENT_DEVICE_PROVISIONING_DATA_SETTING_CHANGE);
350 
351         SubscriptionController.getInstance().registerForUiccAppsEnabled(this,
352                 EVENT_UICC_APPS_ENABLEMENT_SETTING_CHANGED, null, false);
353 
354         mLinkBandwidthEstimator = mTelephonyComponentFactory
355                 .inject(LinkBandwidthEstimator.class.getName())
356                 .makeLinkBandwidthEstimator(this);
357 
358         loadTtyMode();
359 
360         CallManager.getInstance().registerPhone(this);
361         logd("GsmCdmaPhone: constructor: sub = " + mPhoneId);
362     }
363 
364     private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
365         @Override
366         public void onReceive(Context context, Intent intent) {
367             Rlog.d(LOG_TAG, "mBroadcastReceiver: action " + intent.getAction());
368             String action = intent.getAction();
369             if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)) {
370                 // Only handle carrier config changes for this phone id.
371                 if (mPhoneId == intent.getIntExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, -1)) {
372                     sendMessage(obtainMessage(EVENT_CARRIER_CONFIG_CHANGED));
373                 }
374             } else if (TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED.equals(action)) {
375                 int ttyMode = intent.getIntExtra(
376                         TelecomManager.EXTRA_CURRENT_TTY_MODE, TelecomManager.TTY_MODE_OFF);
377                 updateTtyMode(ttyMode);
378             } else if (TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED.equals(action)) {
379                 int newPreferredTtyMode = intent.getIntExtra(
380                         TelecomManager.EXTRA_TTY_PREFERRED_MODE, TelecomManager.TTY_MODE_OFF);
381                 updateUiTtyMode(newPreferredTtyMode);
382             }
383         }
384     };
385 
initOnce(CommandsInterface ci)386     private void initOnce(CommandsInterface ci) {
387         if (ci instanceof SimulatedRadioControl) {
388             mSimulatedRadioControl = (SimulatedRadioControl) ci;
389         }
390 
391         mCT = mTelephonyComponentFactory.inject(GsmCdmaCallTracker.class.getName())
392                 .makeGsmCdmaCallTracker(this);
393         mIccPhoneBookIntManager = mTelephonyComponentFactory
394                 .inject(IccPhoneBookInterfaceManager.class.getName())
395                 .makeIccPhoneBookInterfaceManager(this);
396         PowerManager pm
397                 = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
398         mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG);
399         mIccSmsInterfaceManager = mTelephonyComponentFactory
400                 .inject(IccSmsInterfaceManager.class.getName())
401                 .makeIccSmsInterfaceManager(this);
402 
403         mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null);
404         mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
405         mCi.registerForOn(this, EVENT_RADIO_ON, null);
406         mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null);
407         mCi.registerUiccApplicationEnablementChanged(this,
408                 EVENT_UICC_APPS_ENABLEMENT_STATUS_CHANGED,
409                 null);
410         mCi.setOnSuppServiceNotification(this, EVENT_SSN, null);
411         mCi.setOnRegistrationFailed(this, EVENT_REGISTRATION_FAILED, null);
412         mCi.registerForBarringInfoChanged(this, EVENT_BARRING_INFO_CHANGED, null);
413 
414         //GSM
415         mCi.setOnUSSD(this, EVENT_USSD, null);
416         mCi.setOnSs(this, EVENT_SS, null);
417 
418         //CDMA
419         mCdmaSSM = mTelephonyComponentFactory.inject(CdmaSubscriptionSourceManager.class.getName())
420                 .getCdmaSubscriptionSourceManagerInstance(mContext,
421                 mCi, this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null);
422         mCi.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null);
423         mCi.registerForExitEmergencyCallbackMode(this, EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE,
424                 null);
425         mCi.registerForModemReset(this, EVENT_MODEM_RESET, null);
426         // get the string that specifies the carrier OTA Sp number
427         mCarrierOtaSpNumSchema = TelephonyManager.from(mContext).getOtaSpNumberSchemaForPhone(
428                 getPhoneId(), "");
429 
430         mResetModemOnRadioTechnologyChange = TelephonyProperties.reset_on_radio_tech_change()
431                 .orElse(false);
432 
433         mCi.registerForRilConnected(this, EVENT_RIL_CONNECTED, null);
434         mCi.registerForVoiceRadioTechChanged(this, EVENT_VOICE_RADIO_TECH_CHANGED, null);
435         mCi.registerForLceInfo(this, EVENT_LINK_CAPACITY_CHANGED, null);
436         mCi.registerForCarrierInfoForImsiEncryption(this,
437                 EVENT_RESET_CARRIER_KEY_IMSI_ENCRYPTION, null);
438         IntentFilter filter = new IntentFilter(
439                 CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
440         filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED);
441         filter.addAction(TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED);
442         mContext.registerReceiver(mBroadcastReceiver, filter);
443 
444         mCDM = new CarrierKeyDownloadManager(this);
445         mCIM = new CarrierInfoManager();
446     }
447 
initRatSpecific(int precisePhoneType)448     private void initRatSpecific(int precisePhoneType) {
449         mPendingMMIs.clear();
450         mIccPhoneBookIntManager.updateIccRecords(null);
451 
452         mPrecisePhoneType = precisePhoneType;
453         logd("Precise phone type " + mPrecisePhoneType);
454 
455         TelephonyManager tm = TelephonyManager.from(mContext);
456         UiccProfile uiccProfile = getUiccProfile();
457         if (isPhoneTypeGsm()) {
458             mCi.setPhoneType(PhoneConstants.PHONE_TYPE_GSM);
459             tm.setPhoneType(getPhoneId(), PhoneConstants.PHONE_TYPE_GSM);
460             if (uiccProfile != null) {
461                 uiccProfile.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS);
462             }
463         } else {
464             mCdmaSubscriptionSource = mCdmaSSM.getCdmaSubscriptionSource();
465             // This is needed to handle phone process crashes
466             mIsPhoneInEcmState = getInEcmMode();
467             if (mIsPhoneInEcmState) {
468                 // Send a message which will invoke handleExitEmergencyCallbackMode
469                 mCi.exitEmergencyCallbackMode(null);
470             }
471 
472             mCi.setPhoneType(PhoneConstants.PHONE_TYPE_CDMA);
473             tm.setPhoneType(getPhoneId(), PhoneConstants.PHONE_TYPE_CDMA);
474             if (uiccProfile != null) {
475                 uiccProfile.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT);
476             }
477             // Sets operator properties by retrieving from build-time system property
478             String operatorAlpha = SystemProperties.get("ro.cdma.home.operator.alpha");
479             String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC);
480             logd("init: operatorAlpha='" + operatorAlpha
481                     + "' operatorNumeric='" + operatorNumeric + "'");
482             if (!TextUtils.isEmpty(operatorAlpha)) {
483                 logd("init: set 'gsm.sim.operator.alpha' to operator='" + operatorAlpha + "'");
484                 tm.setSimOperatorNameForPhone(mPhoneId, operatorAlpha);
485             }
486             if (!TextUtils.isEmpty(operatorNumeric)) {
487                 logd("init: set 'gsm.sim.operator.numeric' to operator='" + operatorNumeric +
488                         "'");
489                 logd("update icc_operator_numeric=" + operatorNumeric);
490                 tm.setSimOperatorNumericForPhone(mPhoneId, operatorNumeric);
491 
492                 SubscriptionController.getInstance().setMccMnc(operatorNumeric, getSubId());
493 
494                 // Sets iso country property by retrieving from build-time system property
495                 String iso = "";
496                 try {
497                     iso = MccTable.countryCodeForMcc(operatorNumeric.substring(0, 3));
498                 } catch (StringIndexOutOfBoundsException ex) {
499                     Rlog.e(LOG_TAG, "init: countryCodeForMcc error", ex);
500                 }
501 
502                 logd("init: set 'gsm.sim.operator.iso-country' to iso=" + iso);
503                 tm.setSimCountryIsoForPhone(mPhoneId, iso);
504                 SubscriptionController.getInstance().setCountryIso(iso, getSubId());
505 
506                 // Updates MCC MNC device configuration information
507                 logd("update mccmnc=" + operatorNumeric);
508                 MccTable.updateMccMncConfiguration(mContext, operatorNumeric);
509             }
510 
511             // Sets current entry in the telephony carrier table
512             updateCurrentCarrierInProvider(operatorNumeric);
513         }
514     }
515 
516     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isPhoneTypeGsm()517     public boolean isPhoneTypeGsm() {
518         return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_GSM;
519     }
520 
isPhoneTypeCdma()521     public boolean isPhoneTypeCdma() {
522         return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_CDMA;
523     }
524 
isPhoneTypeCdmaLte()525     public boolean isPhoneTypeCdmaLte() {
526         return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_CDMA_LTE;
527     }
528 
switchPhoneType(int precisePhoneType)529     private void switchPhoneType(int precisePhoneType) {
530         removeCallbacks(mExitEcmRunnable);
531 
532         initRatSpecific(precisePhoneType);
533 
534         mSST.updatePhoneType();
535         setPhoneName(precisePhoneType == PhoneConstants.PHONE_TYPE_GSM ? "GSM" : "CDMA");
536         onUpdateIccAvailability();
537         // if is possible that onUpdateIccAvailability() does not unregister and re-register for
538         // ICC events, for example if mUiccApplication does not change which can happen if phone
539         // type is transitioning from CDMA to GSM but 3gpp2 application was not available.
540         // To handle such cases, unregister and re-register here. They still need to be called in
541         // onUpdateIccAvailability(), since in normal cases register/unregister calls can be on
542         // different IccRecords objects. Here they are on the same IccRecords object.
543         unregisterForIccRecordEvents();
544         registerForIccRecordEvents();
545 
546         mCT.updatePhoneType();
547 
548         int radioState = mCi.getRadioState();
549         if (radioState != TelephonyManager.RADIO_POWER_UNAVAILABLE) {
550             handleRadioAvailable();
551             if (radioState == TelephonyManager.RADIO_POWER_ON) {
552                 handleRadioOn();
553             }
554         }
555         if (radioState != TelephonyManager.RADIO_POWER_ON) {
556             handleRadioOffOrNotAvailable();
557         }
558     }
559 
updateLinkCapacityEstimate(List<LinkCapacityEstimate> linkCapacityEstimateList)560     private void updateLinkCapacityEstimate(List<LinkCapacityEstimate> linkCapacityEstimateList) {
561         if (DBG) logd("updateLinkCapacityEstimate: lce list=" + linkCapacityEstimateList);
562         if (linkCapacityEstimateList == null) {
563             return;
564         }
565         notifyLinkCapacityEstimateChanged(linkCapacityEstimateList);
566     }
567 
568     @Override
finalize()569     protected void finalize() {
570         if(DBG) logd("GsmCdmaPhone finalized");
571         if (mWakeLock != null && mWakeLock.isHeld()) {
572             Rlog.e(LOG_TAG, "UNEXPECTED; mWakeLock is held when finalizing.");
573             mWakeLock.release();
574         }
575     }
576 
577     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
578     @Override
579     @NonNull
getServiceState()580     public ServiceState getServiceState() {
581         if (mSST == null || mSST.mSS.getState() != ServiceState.STATE_IN_SERVICE) {
582             if (mImsPhone != null) {
583                 return mergeServiceStates((mSST == null) ? new ServiceState() : mSST.mSS,
584                         mImsPhone.getServiceState());
585             }
586         }
587 
588         if (mSST != null) {
589             return mSST.mSS;
590         } else {
591             // avoid potential NPE in EmergencyCallHelper during Phone switch
592             return new ServiceState();
593         }
594     }
595 
596     @Override
getCellIdentity(WorkSource workSource, Message rspMsg)597     public void getCellIdentity(WorkSource workSource, Message rspMsg) {
598         mSST.requestCellIdentity(workSource, rspMsg);
599     }
600 
601     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
602     @Override
getState()603     public PhoneConstants.State getState() {
604         if (mImsPhone != null) {
605             PhoneConstants.State imsState = mImsPhone.getState();
606             if (imsState != PhoneConstants.State.IDLE) {
607                 return imsState;
608             }
609         }
610 
611         return mCT.mState;
612     }
613 
614     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
615     @Override
getPhoneType()616     public int getPhoneType() {
617         if (mPrecisePhoneType == PhoneConstants.PHONE_TYPE_GSM) {
618             return PhoneConstants.PHONE_TYPE_GSM;
619         } else {
620             return PhoneConstants.PHONE_TYPE_CDMA;
621         }
622     }
623 
624     @Override
getServiceStateTracker()625     public ServiceStateTracker getServiceStateTracker() {
626         return mSST;
627     }
628 
629     @Override
getEmergencyNumberTracker()630     public EmergencyNumberTracker getEmergencyNumberTracker() {
631         return mEmergencyNumberTracker;
632     }
633 
634     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
635     @Override
getCallTracker()636     public CallTracker getCallTracker() {
637         return mCT;
638     }
639 
640     @Override
getTransportManager()641     public TransportManager getTransportManager() {
642         return mTransportManager;
643     }
644 
645     @Override
getDeviceStateMonitor()646     public DeviceStateMonitor getDeviceStateMonitor() {
647         return mDeviceStateMonitor;
648     }
649 
650     @Override
getDisplayInfoController()651     public DisplayInfoController getDisplayInfoController() {
652         return mDisplayInfoController;
653     }
654 
655     @Override
updateVoiceMail()656     public void updateVoiceMail() {
657         if (isPhoneTypeGsm()) {
658             int countVoiceMessages = 0;
659             IccRecords r = mIccRecords.get();
660             if (r != null) {
661                 // get voice mail count from SIM
662                 countVoiceMessages = r.getVoiceMessageCount();
663             }
664             if (countVoiceMessages == IccRecords.DEFAULT_VOICE_MESSAGE_COUNT) {
665                 countVoiceMessages = getStoredVoiceMessageCount();
666             }
667             logd("updateVoiceMail countVoiceMessages = " + countVoiceMessages
668                     + " subId " + getSubId());
669             setVoiceMessageCount(countVoiceMessages);
670         } else {
671             setVoiceMessageCount(getStoredVoiceMessageCount());
672         }
673     }
674 
675     @Override
676     public List<? extends MmiCode>
getPendingMmiCodes()677     getPendingMmiCodes() {
678         return mPendingMMIs;
679     }
680 
getActiveDcTrackerForApn(@onNull String apnType)681     private @NonNull DcTracker getActiveDcTrackerForApn(@NonNull String apnType) {
682         int currentTransport = mTransportManager.getCurrentTransport(
683                 ApnSetting.getApnTypesBitmaskFromString(apnType));
684         return getDcTracker(currentTransport);
685     }
686 
687     @Override
isDataSuspended()688     public boolean isDataSuspended() {
689         return mCT.mState != PhoneConstants.State.IDLE && !mSST.isConcurrentVoiceAndDataAllowed();
690     }
691 
692     @Override
getDataConnectionState(String apnType)693     public PhoneConstants.DataState getDataConnectionState(String apnType) {
694         PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED;
695 
696         if (mSST == null) {
697             // Radio Technology Change is ongoing, dispose() and removeReferences() have
698             // already been called
699 
700             ret = PhoneConstants.DataState.DISCONNECTED;
701         } else if (mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE
702                 && (isPhoneTypeCdma() || isPhoneTypeCdmaLte() ||
703                 (isPhoneTypeGsm() && !apnType.equals(ApnSetting.TYPE_EMERGENCY_STRING)))) {
704             // If we're out of service, open TCP sockets may still work
705             // but no data will flow
706 
707             // Emergency APN is available even in Out Of Service
708             // Pass the actual State of EPDN
709 
710             ret = PhoneConstants.DataState.DISCONNECTED;
711         } else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */
712             int currentTransport = mTransportManager.getCurrentTransport(
713                     ApnSetting.getApnTypesBitmaskFromString(apnType));
714             if (getDcTracker(currentTransport) != null) {
715                 switch (getDcTracker(currentTransport).getState(apnType)) {
716                     case CONNECTED:
717                     case DISCONNECTING:
718                         if (isDataSuspended()) {
719                             ret = PhoneConstants.DataState.SUSPENDED;
720                         } else {
721                             ret = PhoneConstants.DataState.CONNECTED;
722                         }
723                         break;
724                     case CONNECTING:
725                         ret = PhoneConstants.DataState.CONNECTING;
726                         break;
727                     default:
728                         ret = PhoneConstants.DataState.DISCONNECTED;
729                 }
730             }
731         }
732 
733         logd("getDataConnectionState apnType=" + apnType + " ret=" + ret);
734         return ret;
735     }
736 
737     @Override
getDataActivityState()738     public DataActivityState getDataActivityState() {
739         DataActivityState ret = DataActivityState.NONE;
740 
741         if (mSST.getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE
742                 && getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) != null) {
743             switch (getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).getActivity()) {
744                 case DATAIN:
745                     ret = DataActivityState.DATAIN;
746                 break;
747 
748                 case DATAOUT:
749                     ret = DataActivityState.DATAOUT;
750                 break;
751 
752                 case DATAINANDOUT:
753                     ret = DataActivityState.DATAINANDOUT;
754                 break;
755 
756                 case DORMANT:
757                     ret = DataActivityState.DORMANT;
758                 break;
759 
760                 default:
761                     ret = DataActivityState.NONE;
762                 break;
763             }
764         }
765 
766         return ret;
767     }
768 
769     /**
770      * Notify any interested party of a Phone state change
771      * {@link com.android.internal.telephony.PhoneConstants.State}
772      */
notifyPhoneStateChanged()773     public void notifyPhoneStateChanged() {
774         mNotifier.notifyPhoneState(this);
775     }
776 
777     /**
778      * Notify registrants of a change in the call state. This notifies changes in
779      * {@link com.android.internal.telephony.Call.State}. Use this when changes
780      * in the precise call state are needed, else use notifyPhoneStateChanged.
781      */
782     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
notifyPreciseCallStateChanged()783     public void notifyPreciseCallStateChanged() {
784         /* we'd love it if this was package-scoped*/
785         super.notifyPreciseCallStateChangedP();
786     }
787 
notifyNewRingingConnection(Connection c)788     public void notifyNewRingingConnection(Connection c) {
789         super.notifyNewRingingConnectionP(c);
790     }
791 
notifyDisconnect(Connection cn)792     public void notifyDisconnect(Connection cn) {
793         mDisconnectRegistrants.notifyResult(cn);
794 
795         mNotifier.notifyDisconnectCause(this, cn.getDisconnectCause(),
796                 cn.getPreciseDisconnectCause());
797     }
798 
notifyUnknownConnection(Connection cn)799     public void notifyUnknownConnection(Connection cn) {
800         super.notifyUnknownConnectionP(cn);
801     }
802 
803     @Override
isInEmergencyCall()804     public boolean isInEmergencyCall() {
805         if (isPhoneTypeGsm()) {
806             return false;
807         } else {
808             return mCT.isInEmergencyCall();
809         }
810     }
811 
812     @Override
setIsInEmergencyCall()813     protected void setIsInEmergencyCall() {
814         if (!isPhoneTypeGsm()) {
815             mCT.setIsInEmergencyCall();
816         }
817     }
818 
819     @Override
isInEmergencySmsMode()820     public boolean isInEmergencySmsMode() {
821         return super.isInEmergencySmsMode()
822                 || (mImsPhone != null && mImsPhone.isInEmergencySmsMode());
823     }
824 
825     //CDMA
sendEmergencyCallbackModeChange()826     private void sendEmergencyCallbackModeChange(){
827         //Send an Intent
828         Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
829         intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, isInEcm());
830         SubscriptionManager.putPhoneIdAndSubIdExtra(intent, getPhoneId());
831         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
832         logi("sendEmergencyCallbackModeChange");
833     }
834 
835     @Override
sendEmergencyCallStateChange(boolean callActive)836     public void sendEmergencyCallStateChange(boolean callActive) {
837         if (!isPhoneTypeCdma()) {
838             // It possible that this method got called from ImsPhoneCallTracker#
839             logi("sendEmergencyCallStateChange - skip for non-cdma");
840             return;
841         }
842         if (mBroadcastEmergencyCallStateChanges) {
843             Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED);
844             intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, callActive);
845             SubscriptionManager.putPhoneIdAndSubIdExtra(intent, getPhoneId());
846             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
847             if (DBG) Rlog.d(LOG_TAG, "sendEmergencyCallStateChange: callActive " + callActive);
848         }
849     }
850 
851     @Override
setBroadcastEmergencyCallStateChanges(boolean broadcast)852     public void setBroadcastEmergencyCallStateChanges(boolean broadcast) {
853         mBroadcastEmergencyCallStateChanges = broadcast;
854     }
855 
notifySuppServiceFailed(SuppService code)856     public void notifySuppServiceFailed(SuppService code) {
857         mSuppServiceFailedRegistrants.notifyResult(code);
858     }
859 
860     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
notifyServiceStateChanged(ServiceState ss)861     public void notifyServiceStateChanged(ServiceState ss) {
862         super.notifyServiceStateChangedP(ss);
863     }
864 
notifyServiceStateChangedForSubId(ServiceState ss, int subId)865     void notifyServiceStateChangedForSubId(ServiceState ss, int subId) {
866         super.notifyServiceStateChangedPForSubId(ss, subId);
867     }
868 
869     /**
870      * Notify that the cell location has changed.
871      *
872      * @param cellIdentity the new CellIdentity
873      */
notifyLocationChanged(CellIdentity cellIdentity)874     public void notifyLocationChanged(CellIdentity cellIdentity) {
875         mNotifier.notifyCellLocation(this, cellIdentity);
876     }
877 
878     @Override
notifyCallForwardingIndicator()879     public void notifyCallForwardingIndicator() {
880         mNotifier.notifyCallForwardingChanged(this);
881     }
882 
883     @Override
registerForSuppServiceNotification( Handler h, int what, Object obj)884     public void registerForSuppServiceNotification(
885             Handler h, int what, Object obj) {
886         mSsnRegistrants.addUnique(h, what, obj);
887     }
888 
889     @Override
unregisterForSuppServiceNotification(Handler h)890     public void unregisterForSuppServiceNotification(Handler h) {
891         mSsnRegistrants.remove(h);
892     }
893 
894     @Override
registerForSimRecordsLoaded(Handler h, int what, Object obj)895     public void registerForSimRecordsLoaded(Handler h, int what, Object obj) {
896         mSimRecordsLoadedRegistrants.addUnique(h, what, obj);
897     }
898 
899     @Override
unregisterForSimRecordsLoaded(Handler h)900     public void unregisterForSimRecordsLoaded(Handler h) {
901         mSimRecordsLoadedRegistrants.remove(h);
902     }
903 
904     @Override
acceptCall(int videoState)905     public void acceptCall(int videoState) throws CallStateException {
906         Phone imsPhone = mImsPhone;
907         if ( imsPhone != null && imsPhone.getRingingCall().isRinging() ) {
908             imsPhone.acceptCall(videoState);
909         } else {
910             mCT.acceptCall();
911         }
912     }
913 
914     @Override
rejectCall()915     public void rejectCall() throws CallStateException {
916         mCT.rejectCall();
917     }
918 
919     @Override
switchHoldingAndActive()920     public void switchHoldingAndActive() throws CallStateException {
921         mCT.switchWaitingOrHoldingAndActive();
922     }
923 
924     @Override
getIccSerialNumber()925     public String getIccSerialNumber() {
926         IccRecords r = mIccRecords.get();
927         if (!isPhoneTypeGsm() && r == null) {
928             // to get ICCID form SIMRecords because it is on MF.
929             r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP);
930         }
931         return (r != null) ? r.getIccId() : null;
932     }
933 
934     @Override
getFullIccSerialNumber()935     public String getFullIccSerialNumber() {
936         IccRecords r = mIccRecords.get();
937         if (!isPhoneTypeGsm() && r == null) {
938             // to get ICCID form SIMRecords because it is on MF.
939             r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP);
940         }
941         return (r != null) ? r.getFullIccId() : null;
942     }
943 
944     @Override
canConference()945     public boolean canConference() {
946         if (mImsPhone != null && mImsPhone.canConference()) {
947             return true;
948         }
949         if (isPhoneTypeGsm()) {
950             return mCT.canConference();
951         } else {
952             loge("canConference: not possible in CDMA");
953             return false;
954         }
955     }
956 
957     @Override
conference()958     public void conference() {
959         if (mImsPhone != null && mImsPhone.canConference()) {
960             logd("conference() - delegated to IMS phone");
961             try {
962                 mImsPhone.conference();
963             } catch (CallStateException e) {
964                 loge(e.toString());
965             }
966             return;
967         }
968         if (isPhoneTypeGsm()) {
969             mCT.conference();
970         } else {
971             // three way calls in CDMA will be handled by feature codes
972             loge("conference: not possible in CDMA");
973         }
974     }
975 
976     @Override
dispose()977     public void dispose() {
978         // Note: this API is currently never called. We are defining actions here in case
979         // we need to dispose GsmCdmaPhone/Phone object.
980         super.dispose();
981         SubscriptionController.getInstance().unregisterForUiccAppsEnabled(this);
982     }
983 
984     @Override
enableEnhancedVoicePrivacy(boolean enable, Message onComplete)985     public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) {
986         if (isPhoneTypeGsm()) {
987             loge("enableEnhancedVoicePrivacy: not expected on GSM");
988         } else {
989             mCi.setPreferredVoicePrivacy(enable, onComplete);
990         }
991     }
992 
993     @Override
getEnhancedVoicePrivacy(Message onComplete)994     public void getEnhancedVoicePrivacy(Message onComplete) {
995         if (isPhoneTypeGsm()) {
996             loge("getEnhancedVoicePrivacy: not expected on GSM");
997         } else {
998             mCi.getPreferredVoicePrivacy(onComplete);
999         }
1000     }
1001 
1002     @Override
clearDisconnected()1003     public void clearDisconnected() {
1004         mCT.clearDisconnected();
1005     }
1006 
1007     @Override
canTransfer()1008     public boolean canTransfer() {
1009         if (isPhoneTypeGsm()) {
1010             return mCT.canTransfer();
1011         } else {
1012             loge("canTransfer: not possible in CDMA");
1013             return false;
1014         }
1015     }
1016 
1017     @Override
explicitCallTransfer()1018     public void explicitCallTransfer() {
1019         if (isPhoneTypeGsm()) {
1020             mCT.explicitCallTransfer();
1021         } else {
1022             loge("explicitCallTransfer: not possible in CDMA");
1023         }
1024     }
1025 
1026     @Override
getForegroundCall()1027     public GsmCdmaCall getForegroundCall() {
1028         return mCT.mForegroundCall;
1029     }
1030 
1031     @Override
getBackgroundCall()1032     public GsmCdmaCall getBackgroundCall() {
1033         return mCT.mBackgroundCall;
1034     }
1035 
1036     @Override
getRingingCall()1037     public Call getRingingCall() {
1038         Phone imsPhone = mImsPhone;
1039         // It returns the ringing call of ImsPhone if the ringing call of GSMPhone isn't ringing.
1040         // In CallManager.registerPhone(), it always registers ringing call of ImsPhone, because
1041         // the ringing call of GSMPhone isn't ringing. Consequently, it can't answer GSM call
1042         // successfully by invoking TelephonyManager.answerRingingCall() since the implementation
1043         // in PhoneInterfaceManager.answerRingingCallInternal() could not get the correct ringing
1044         // call from CallManager. So we check the ringing call state of imsPhone first as
1045         // accpetCall() does.
1046         if ( imsPhone != null && imsPhone.getRingingCall().isRinging()) {
1047             return imsPhone.getRingingCall();
1048         }
1049         //It returns the ringing connections which during SRVCC handover
1050         if (!mCT.mRingingCall.isRinging()
1051                 && mCT.getRingingHandoverConnection() != null
1052                 && mCT.getRingingHandoverConnection().getCall() != null
1053                 && mCT.getRingingHandoverConnection().getCall().isRinging()) {
1054             return mCT.getRingingHandoverConnection().getCall();
1055         }
1056         return mCT.mRingingCall;
1057     }
1058 
1059     /**
1060      * ImsService reports "IN_SERVICE" for its voice registration state even if the device
1061      * has lost the physical link to the tower. This helper method merges the IMS and modem
1062      * ServiceState, only overriding the voice registration state when we are registered to IMS. In
1063      * this case the voice registration state may be "OUT_OF_SERVICE", so override the voice
1064      * registration state with the data registration state.
1065      */
mergeServiceStates(ServiceState baseSs, ServiceState imsSs)1066     private ServiceState mergeServiceStates(ServiceState baseSs, ServiceState imsSs) {
1067         // No need to merge states if the baseSs is IN_SERVICE.
1068         if (baseSs.getState() == ServiceState.STATE_IN_SERVICE) {
1069             return baseSs;
1070         }
1071         // "IN_SERVICE" in this case means IMS is registered.
1072         if (imsSs.getState() != ServiceState.STATE_IN_SERVICE) {
1073             return baseSs;
1074         }
1075 
1076         ServiceState newSs = new ServiceState(baseSs);
1077         // Voice override for IMS case. In this case, voice registration is OUT_OF_SERVICE, but
1078         // IMS is available, so use data registration state as a basis for determining
1079         // whether or not the physical link is available.
1080         newSs.setVoiceRegState(baseSs.getDataRegistrationState());
1081         newSs.setEmergencyOnly(false); // only get here if voice is IN_SERVICE
1082         return newSs;
1083     }
1084 
handleCallDeflectionIncallSupplementaryService( String dialString)1085     private boolean handleCallDeflectionIncallSupplementaryService(
1086             String dialString) {
1087         if (dialString.length() > 1) {
1088             return false;
1089         }
1090 
1091         if (getRingingCall().getState() != GsmCdmaCall.State.IDLE) {
1092             if (DBG) logd("MmiCode 0: rejectCall");
1093             try {
1094                 mCT.rejectCall();
1095             } catch (CallStateException e) {
1096                 if (DBG) Rlog.d(LOG_TAG,
1097                         "reject failed", e);
1098                 notifySuppServiceFailed(Phone.SuppService.REJECT);
1099             }
1100         } else if (getBackgroundCall().getState() != GsmCdmaCall.State.IDLE) {
1101             if (DBG) logd("MmiCode 0: hangupWaitingOrBackground");
1102             mCT.hangupWaitingOrBackground();
1103         }
1104 
1105         return true;
1106     }
1107 
1108     //GSM
handleCallWaitingIncallSupplementaryService(String dialString)1109     private boolean handleCallWaitingIncallSupplementaryService(String dialString) {
1110         int len = dialString.length();
1111 
1112         if (len > 2) {
1113             return false;
1114         }
1115 
1116         GsmCdmaCall call = getForegroundCall();
1117 
1118         try {
1119             if (len > 1) {
1120                 char ch = dialString.charAt(1);
1121                 int callIndex = ch - '0';
1122 
1123                 if (callIndex >= 1 && callIndex <= GsmCdmaCallTracker.MAX_CONNECTIONS_GSM) {
1124                     if (DBG) logd("MmiCode 1: hangupConnectionByIndex " + callIndex);
1125                     mCT.hangupConnectionByIndex(call, callIndex);
1126                 }
1127             } else {
1128                 if (call.getState() != GsmCdmaCall.State.IDLE) {
1129                     if (DBG) logd("MmiCode 1: hangup foreground");
1130                     //mCT.hangupForegroundResumeBackground();
1131                     mCT.hangup(call);
1132                 } else {
1133                     if (DBG) logd("MmiCode 1: switchWaitingOrHoldingAndActive");
1134                     mCT.switchWaitingOrHoldingAndActive();
1135                 }
1136             }
1137         } catch (CallStateException e) {
1138             if (DBG) Rlog.d(LOG_TAG,
1139                     "hangup failed", e);
1140             notifySuppServiceFailed(Phone.SuppService.HANGUP);
1141         }
1142 
1143         return true;
1144     }
1145 
handleCallHoldIncallSupplementaryService(String dialString)1146     private boolean handleCallHoldIncallSupplementaryService(String dialString) {
1147         int len = dialString.length();
1148 
1149         if (len > 2) {
1150             return false;
1151         }
1152 
1153         GsmCdmaCall call = getForegroundCall();
1154 
1155         if (len > 1) {
1156             try {
1157                 char ch = dialString.charAt(1);
1158                 int callIndex = ch - '0';
1159                 GsmCdmaConnection conn = mCT.getConnectionByIndex(call, callIndex);
1160 
1161                 // GsmCdma index starts at 1, up to 5 connections in a call,
1162                 if (conn != null && callIndex >= 1 && callIndex <= GsmCdmaCallTracker.MAX_CONNECTIONS_GSM) {
1163                     if (DBG) logd("MmiCode 2: separate call " + callIndex);
1164                     mCT.separate(conn);
1165                 } else {
1166                     if (DBG) logd("separate: invalid call index " + callIndex);
1167                     notifySuppServiceFailed(Phone.SuppService.SEPARATE);
1168                 }
1169             } catch (CallStateException e) {
1170                 if (DBG) Rlog.d(LOG_TAG, "separate failed", e);
1171                 notifySuppServiceFailed(Phone.SuppService.SEPARATE);
1172             }
1173         } else {
1174             try {
1175                 if (getRingingCall().getState() != GsmCdmaCall.State.IDLE) {
1176                     if (DBG) logd("MmiCode 2: accept ringing call");
1177                     mCT.acceptCall();
1178                 } else {
1179                     if (DBG) logd("MmiCode 2: switchWaitingOrHoldingAndActive");
1180                     mCT.switchWaitingOrHoldingAndActive();
1181                 }
1182             } catch (CallStateException e) {
1183                 if (DBG) Rlog.d(LOG_TAG, "switch failed", e);
1184                 notifySuppServiceFailed(Phone.SuppService.SWITCH);
1185             }
1186         }
1187 
1188         return true;
1189     }
1190 
handleMultipartyIncallSupplementaryService(String dialString)1191     private boolean handleMultipartyIncallSupplementaryService(String dialString) {
1192         if (dialString.length() > 1) {
1193             return false;
1194         }
1195 
1196         if (DBG) logd("MmiCode 3: merge calls");
1197         conference();
1198         return true;
1199     }
1200 
handleEctIncallSupplementaryService(String dialString)1201     private boolean handleEctIncallSupplementaryService(String dialString) {
1202 
1203         int len = dialString.length();
1204 
1205         if (len != 1) {
1206             return false;
1207         }
1208 
1209         if (DBG) logd("MmiCode 4: explicit call transfer");
1210         explicitCallTransfer();
1211         return true;
1212     }
1213 
handleCcbsIncallSupplementaryService(String dialString)1214     private boolean handleCcbsIncallSupplementaryService(String dialString) {
1215         if (dialString.length() > 1) {
1216             return false;
1217         }
1218 
1219         Rlog.i(LOG_TAG, "MmiCode 5: CCBS not supported!");
1220         // Treat it as an "unknown" service.
1221         notifySuppServiceFailed(Phone.SuppService.UNKNOWN);
1222         return true;
1223     }
1224 
1225     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1226     @Override
handleInCallMmiCommands(String dialString)1227     public boolean handleInCallMmiCommands(String dialString) throws CallStateException {
1228         if (!isPhoneTypeGsm()) {
1229             loge("method handleInCallMmiCommands is NOT supported in CDMA!");
1230             return false;
1231         }
1232 
1233         Phone imsPhone = mImsPhone;
1234         if (imsPhone != null
1235                 && imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE) {
1236             return imsPhone.handleInCallMmiCommands(dialString);
1237         }
1238 
1239         if (!isInCall()) {
1240             return false;
1241         }
1242 
1243         if (TextUtils.isEmpty(dialString)) {
1244             return false;
1245         }
1246 
1247         boolean result = false;
1248         char ch = dialString.charAt(0);
1249         switch (ch) {
1250             case '0':
1251                 result = handleCallDeflectionIncallSupplementaryService(dialString);
1252                 break;
1253             case '1':
1254                 result = handleCallWaitingIncallSupplementaryService(dialString);
1255                 break;
1256             case '2':
1257                 result = handleCallHoldIncallSupplementaryService(dialString);
1258                 break;
1259             case '3':
1260                 result = handleMultipartyIncallSupplementaryService(dialString);
1261                 break;
1262             case '4':
1263                 result = handleEctIncallSupplementaryService(dialString);
1264                 break;
1265             case '5':
1266                 result = handleCcbsIncallSupplementaryService(dialString);
1267                 break;
1268             default:
1269                 break;
1270         }
1271 
1272         return result;
1273     }
1274 
1275     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isInCall()1276     public boolean isInCall() {
1277         GsmCdmaCall.State foregroundCallState = getForegroundCall().getState();
1278         GsmCdmaCall.State backgroundCallState = getBackgroundCall().getState();
1279         GsmCdmaCall.State ringingCallState = getRingingCall().getState();
1280 
1281        return (foregroundCallState.isAlive() ||
1282                 backgroundCallState.isAlive() ||
1283                 ringingCallState.isAlive());
1284     }
1285 
useImsForCall(DialArgs dialArgs)1286     private boolean useImsForCall(DialArgs dialArgs) {
1287         return isImsUseEnabled()
1288                 && mImsPhone != null
1289                 && (mImsPhone.isVoiceOverCellularImsEnabled() || mImsPhone.isWifiCallingEnabled()
1290                 || (mImsPhone.isVideoEnabled() && VideoProfile.isVideo(dialArgs.videoState)))
1291                 && (mImsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE);
1292     }
1293 
useImsForEmergency()1294     public boolean useImsForEmergency() {
1295         CarrierConfigManager configManager =
1296                 (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
1297         boolean alwaysTryImsForEmergencyCarrierConfig = configManager.getConfigForSubId(getSubId())
1298                 .getBoolean(CarrierConfigManager.KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL);
1299         return mImsPhone != null
1300                 && alwaysTryImsForEmergencyCarrierConfig
1301                 && ImsManager.getInstance(mContext, mPhoneId).isNonTtyOrTtyOnVolteEnabled()
1302                 && mImsPhone.isImsAvailable();
1303     }
1304 
1305     @Override
startConference(String[] participantsToDial, DialArgs dialArgs)1306     public Connection startConference(String[] participantsToDial, DialArgs dialArgs)
1307             throws CallStateException {
1308         Phone imsPhone = mImsPhone;
1309         boolean useImsForCall = useImsForCall(dialArgs);
1310         logd("useImsForCall=" + useImsForCall);
1311         if (useImsForCall) {
1312             try {
1313                 if (DBG) logd("Trying IMS PS Conference call");
1314                 return imsPhone.startConference(participantsToDial, dialArgs);
1315             } catch (CallStateException e) {
1316                 if (DBG) logd("IMS PS conference call exception " + e +
1317                         "useImsForCall =" + useImsForCall + ", imsPhone =" + imsPhone);
1318                  CallStateException ce = new CallStateException(e.getError(), e.getMessage());
1319                  ce.setStackTrace(e.getStackTrace());
1320                  throw ce;
1321             }
1322         } else {
1323             throw new CallStateException(
1324                 CallStateException.ERROR_OUT_OF_SERVICE,
1325                 "cannot dial conference call in out of service");
1326         }
1327     }
1328 
1329     @Override
dial(String dialString, @NonNull DialArgs dialArgs, Consumer<Phone> chosenPhoneConsumer)1330     public Connection dial(String dialString, @NonNull DialArgs dialArgs,
1331             Consumer<Phone> chosenPhoneConsumer) throws CallStateException {
1332         if (!isPhoneTypeGsm() && dialArgs.uusInfo != null) {
1333             throw new CallStateException("Sending UUS information NOT supported in CDMA!");
1334         }
1335         String possibleEmergencyNumber = checkForTestEmergencyNumber(dialString);
1336         // Record if the dialed number was swapped for a test emergency number.
1337         boolean isDialedNumberSwapped = !TextUtils.equals(dialString, possibleEmergencyNumber);
1338         if (isDialedNumberSwapped) {
1339             logi("dialString replaced for possible emergency number: " + dialString + " -> "
1340                     + possibleEmergencyNumber);
1341             dialString = possibleEmergencyNumber;
1342         }
1343         TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
1344         boolean isEmergency = tm.isEmergencyNumber(dialString);
1345         /** Check if the call is Wireless Priority Service call */
1346         boolean isWpsCall = dialString != null ? (dialString.startsWith(PREFIX_WPS)
1347                 || dialString.startsWith(PREFIX_WPS_CLIR_ACTIVATE)
1348                 || dialString.startsWith(PREFIX_WPS_CLIR_DEACTIVATE)) : false;
1349 
1350         ImsPhone.ImsDialArgs.Builder imsDialArgsBuilder;
1351         imsDialArgsBuilder = ImsPhone.ImsDialArgs.Builder.from(dialArgs)
1352                                                  .setIsEmergency(isEmergency)
1353                                                  .setIsWpsCall(isWpsCall);
1354         mDialArgs = dialArgs = imsDialArgsBuilder.build();
1355 
1356         Phone imsPhone = mImsPhone;
1357 
1358         CarrierConfigManager configManager =
1359                 (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
1360 
1361         boolean allowWpsOverIms = configManager.getConfigForSubId(getSubId())
1362                 .getBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL);
1363 
1364         boolean useImsForEmergency = isEmergency && useImsForEmergency();
1365 
1366         String dialPart = PhoneNumberUtils.extractNetworkPortionAlt(PhoneNumberUtils.
1367                 stripSeparators(dialString));
1368         boolean isMmiCode = (dialPart.startsWith("*") || dialPart.startsWith("#"))
1369                 && dialPart.endsWith("#");
1370         boolean isSuppServiceCode = ImsPhoneMmiCode.isSuppServiceCodes(dialPart, this);
1371         boolean isPotentialUssdCode = isMmiCode && !isSuppServiceCode;
1372         boolean useImsForUt = imsPhone != null && imsPhone.isUtEnabled();
1373         boolean useImsForCall = useImsForCall(dialArgs)
1374                 && (isWpsCall ? allowWpsOverIms : true);
1375 
1376         if (DBG) {
1377             logd("useImsForCall=" + useImsForCall
1378                     + ", isEmergency=" + isEmergency
1379                     + ", useImsForEmergency=" + useImsForEmergency
1380                     + ", useImsForUt=" + useImsForUt
1381                     + ", isUt=" + isMmiCode
1382                     + ", isSuppServiceCode=" + isSuppServiceCode
1383                     + ", isPotentialUssdCode=" + isPotentialUssdCode
1384                     + ", isWpsCall=" + isWpsCall
1385                     + ", allowWpsOverIms=" + allowWpsOverIms
1386                     + ", imsPhone=" + imsPhone
1387                     + ", imsPhone.isVoiceOverCellularImsEnabled()="
1388                     + ((imsPhone != null) ? imsPhone.isVoiceOverCellularImsEnabled() : "N/A")
1389                     + ", imsPhone.isVowifiEnabled()="
1390                     + ((imsPhone != null) ? imsPhone.isWifiCallingEnabled() : "N/A")
1391                     + ", imsPhone.isVideoEnabled()="
1392                     + ((imsPhone != null) ? imsPhone.isVideoEnabled() : "N/A")
1393                     + ", imsPhone.getServiceState().getState()="
1394                     + ((imsPhone != null) ? imsPhone.getServiceState().getState() : "N/A"));
1395         }
1396 
1397         // Bypass WiFi Only WFC check if this is an emergency call - we should still try to
1398         // place over cellular if possible.
1399         if (!isEmergency) {
1400             Phone.checkWfcWifiOnlyModeBeforeDial(mImsPhone, mPhoneId, mContext);
1401         }
1402         if (imsPhone != null && !allowWpsOverIms && !useImsForCall && isWpsCall
1403                 && imsPhone.getCallTracker() instanceof ImsPhoneCallTracker) {
1404             logi("WPS call placed over CS; disconnecting all IMS calls..");
1405             ImsPhoneCallTracker tracker = (ImsPhoneCallTracker) imsPhone.getCallTracker();
1406             tracker.hangupAllConnections();
1407         }
1408 
1409         if ((useImsForCall && (!isMmiCode || isPotentialUssdCode))
1410                 || (isMmiCode && useImsForUt)
1411                 || useImsForEmergency) {
1412             try {
1413                 if (DBG) logd("Trying IMS PS call");
1414                 chosenPhoneConsumer.accept(imsPhone);
1415                 return imsPhone.dial(dialString, dialArgs);
1416             } catch (CallStateException e) {
1417                 if (DBG) logd("IMS PS call exception " + e +
1418                         "useImsForCall =" + useImsForCall + ", imsPhone =" + imsPhone);
1419                 // Do not throw a CallStateException and instead fall back to Circuit switch
1420                 // for emergency calls and MMI codes.
1421                 if (Phone.CS_FALLBACK.equals(e.getMessage()) || isEmergency) {
1422                     logi("IMS call failed with Exception: " + e.getMessage() + ". Falling back "
1423                             + "to CS.");
1424                 } else {
1425                     CallStateException ce = new CallStateException(e.getError(), e.getMessage());
1426                     ce.setStackTrace(e.getStackTrace());
1427                     throw ce;
1428                 }
1429             }
1430         }
1431 
1432         if (mSST != null && mSST.mSS.getState() == ServiceState.STATE_OUT_OF_SERVICE
1433                 && mSST.mSS.getDataRegistrationState() != ServiceState.STATE_IN_SERVICE
1434                 && !isEmergency) {
1435             throw new CallStateException("cannot dial in current state");
1436         }
1437         // Check non-emergency voice CS call - shouldn't dial when POWER_OFF
1438         if (mSST != null && mSST.mSS.getState() == ServiceState.STATE_POWER_OFF /* CS POWER_OFF */
1439                 && !VideoProfile.isVideo(dialArgs.videoState) /* voice call */
1440                 && !isEmergency /* non-emergency call */
1441                 && !(isMmiCode && useImsForUt) /* not UT */
1442                 /* If config_allow_ussd_over_ims is false, USSD is sent over the CS pipe instead */
1443                 && !isPotentialUssdCode) {
1444             throw new CallStateException(
1445                 CallStateException.ERROR_POWER_OFF,
1446                 "cannot dial voice call in airplane mode");
1447         }
1448         // Check for service before placing non emergency CS voice call.
1449         // Allow dial only if either CS is camped on any RAT (or) PS is in LTE/NR service.
1450         if (mSST != null
1451                 && mSST.mSS.getState() == ServiceState.STATE_OUT_OF_SERVICE /* CS out of service */
1452                 && !(mSST.mSS.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE
1453                 && ServiceState.isPsOnlyTech(
1454                         mSST.mSS.getRilDataRadioTechnology())) /* PS not in LTE/NR */
1455                 && !VideoProfile.isVideo(dialArgs.videoState) /* voice call */
1456                 && !isEmergency /* non-emergency call */
1457                 /* If config_allow_ussd_over_ims is false, USSD is sent over the CS pipe instead */
1458                 && !isPotentialUssdCode) {
1459             throw new CallStateException(
1460                 CallStateException.ERROR_OUT_OF_SERVICE,
1461                 "cannot dial voice call in out of service");
1462         }
1463         if (DBG) logd("Trying (non-IMS) CS call");
1464         if (isDialedNumberSwapped && isEmergency) {
1465             // Triggers ECM when CS call ends only for test emergency calls using
1466             // ril.test.emergencynumber.
1467             mIsTestingEmergencyCallbackMode = true;
1468             mCi.testingEmergencyCall();
1469         }
1470 
1471         chosenPhoneConsumer.accept(this);
1472         return dialInternal(dialString, dialArgs);
1473     }
1474 
1475     /**
1476      * @return {@code true} if the user should be informed of an attempt to dial an international
1477      * number while on WFC only, {@code false} otherwise.
1478      */
isNotificationOfWfcCallRequired(String dialString)1479     public boolean isNotificationOfWfcCallRequired(String dialString) {
1480         CarrierConfigManager configManager =
1481                 (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
1482         PersistableBundle config = configManager.getConfigForSubId(getSubId());
1483 
1484         // Determine if carrier config indicates that international calls over WFC should trigger a
1485         // notification to the user. This is controlled by carrier configuration and is off by
1486         // default.
1487         boolean shouldNotifyInternationalCallOnWfc = config != null
1488                 && config.getBoolean(
1489                         CarrierConfigManager.KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL);
1490 
1491         if (!shouldNotifyInternationalCallOnWfc) {
1492             return false;
1493         }
1494 
1495         Phone imsPhone = mImsPhone;
1496         TelephonyManager tm = mContext.getSystemService(TelephonyManager.class);
1497         boolean isEmergency = tm.isEmergencyNumber(dialString);
1498         boolean shouldConfirmCall =
1499                         // Using IMS
1500                         isImsUseEnabled()
1501                         && imsPhone != null
1502                         // VoLTE not available
1503                         && !imsPhone.isVoiceOverCellularImsEnabled()
1504                         // WFC is available
1505                         && imsPhone.isWifiCallingEnabled()
1506                         && !isEmergency
1507                         // Dialing international number
1508                         && PhoneNumberUtils.isInternationalNumber(dialString, getCountryIso());
1509         return shouldConfirmCall;
1510     }
1511 
1512     @Override
dialInternal(String dialString, DialArgs dialArgs)1513     protected Connection dialInternal(String dialString, DialArgs dialArgs)
1514             throws CallStateException {
1515         return dialInternal(dialString, dialArgs, null);
1516     }
1517 
dialInternal(String dialString, DialArgs dialArgs, ResultReceiver wrappedCallback)1518     protected Connection dialInternal(String dialString, DialArgs dialArgs,
1519             ResultReceiver wrappedCallback)
1520             throws CallStateException {
1521 
1522         // Need to make sure dialString gets parsed properly
1523         String newDialString = PhoneNumberUtils.stripSeparators(dialString);
1524 
1525         if (isPhoneTypeGsm()) {
1526             // handle in-call MMI first if applicable
1527             if (handleInCallMmiCommands(newDialString)) {
1528                 return null;
1529             }
1530 
1531             // Only look at the Network portion for mmi
1532             String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString);
1533             GsmMmiCode mmi = GsmMmiCode.newFromDialString(networkPortion, this,
1534                     mUiccApplication.get(), wrappedCallback);
1535             if (DBG) logd("dialInternal: dialing w/ mmi '" + mmi + "'...");
1536 
1537             if (mmi == null) {
1538                 return mCT.dialGsm(newDialString, dialArgs);
1539             } else if (mmi.isTemporaryModeCLIR()) {
1540                 return mCT.dialGsm(mmi.mDialingNumber, mmi.getCLIRMode(), dialArgs.uusInfo,
1541                         dialArgs.intentExtras);
1542             } else {
1543                 mPendingMMIs.add(mmi);
1544                 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
1545                 mmi.processCode();
1546                 return null;
1547             }
1548         } else {
1549             return mCT.dial(newDialString, dialArgs);
1550         }
1551     }
1552 
1553    @Override
handlePinMmi(String dialString)1554     public boolean handlePinMmi(String dialString) {
1555         MmiCode mmi;
1556         if (isPhoneTypeGsm()) {
1557             mmi = GsmMmiCode.newFromDialString(dialString, this, mUiccApplication.get());
1558         } else {
1559             mmi = CdmaMmiCode.newFromDialString(dialString, this, mUiccApplication.get());
1560         }
1561 
1562         if (mmi != null && mmi.isPinPukCommand()) {
1563             mPendingMMIs.add(mmi);
1564             mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
1565             try {
1566                 mmi.processCode();
1567             } catch (CallStateException e) {
1568                 //do nothing
1569             }
1570             return true;
1571         }
1572 
1573         loge("Mmi is null or unrecognized!");
1574         return false;
1575     }
1576 
sendUssdResponse(String ussdRequest, CharSequence message, int returnCode, ResultReceiver wrappedCallback)1577     private void sendUssdResponse(String ussdRequest, CharSequence message, int returnCode,
1578                                    ResultReceiver wrappedCallback) {
1579         UssdResponse response = new UssdResponse(ussdRequest, message);
1580         Bundle returnData = new Bundle();
1581         returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response);
1582         wrappedCallback.send(returnCode, returnData);
1583     }
1584 
1585     @Override
handleUssdRequest(String ussdRequest, ResultReceiver wrappedCallback)1586     public boolean handleUssdRequest(String ussdRequest, ResultReceiver wrappedCallback) {
1587         if (!isPhoneTypeGsm() || mPendingMMIs.size() > 0) {
1588             //todo: replace the generic failure with specific error code.
1589             sendUssdResponse(ussdRequest, null, TelephonyManager.USSD_RETURN_FAILURE,
1590                     wrappedCallback );
1591             return true;
1592         }
1593 
1594         // Try over IMS if possible.
1595         Phone imsPhone = mImsPhone;
1596         if ((imsPhone != null)
1597                 && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE)
1598                 || imsPhone.isUtEnabled())) {
1599             try {
1600                 logd("handleUssdRequest: attempting over IMS");
1601                 return imsPhone.handleUssdRequest(ussdRequest, wrappedCallback);
1602             } catch (CallStateException cse) {
1603                 if (!CS_FALLBACK.equals(cse.getMessage())) {
1604                     return false;
1605                 }
1606                 // At this point we've tried over IMS but have been informed we need to handover
1607                 // back to GSM.
1608                 logd("handleUssdRequest: fallback to CS required");
1609             }
1610         }
1611 
1612         // Try USSD over GSM.
1613         try {
1614             dialInternal(ussdRequest, new DialArgs.Builder<>().build(), wrappedCallback);
1615         } catch (Exception e) {
1616             logd("handleUssdRequest: exception" + e);
1617             return false;
1618         }
1619         return true;
1620     }
1621 
1622     @Override
sendUssdResponse(String ussdMessge)1623     public void sendUssdResponse(String ussdMessge) {
1624         if (isPhoneTypeGsm()) {
1625             GsmMmiCode mmi = GsmMmiCode.newFromUssdUserInput(ussdMessge, this, mUiccApplication.get());
1626             mPendingMMIs.add(mmi);
1627             mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
1628             mmi.sendUssd(ussdMessge);
1629         } else {
1630             loge("sendUssdResponse: not possible in CDMA");
1631         }
1632     }
1633 
1634     @Override
sendDtmf(char c)1635     public void sendDtmf(char c) {
1636         if (!PhoneNumberUtils.is12Key(c)) {
1637             loge("sendDtmf called with invalid character '" + c + "'");
1638         } else {
1639             if (mCT.mState ==  PhoneConstants.State.OFFHOOK) {
1640                 mCi.sendDtmf(c, null);
1641             }
1642         }
1643     }
1644 
1645     @Override
startDtmf(char c)1646     public void startDtmf(char c) {
1647         if (!PhoneNumberUtils.is12Key(c)) {
1648             loge("startDtmf called with invalid character '" + c + "'");
1649         } else {
1650             mCi.startDtmf(c, null);
1651         }
1652     }
1653 
1654     @Override
stopDtmf()1655     public void stopDtmf() {
1656         mCi.stopDtmf(null);
1657     }
1658 
1659     @Override
sendBurstDtmf(String dtmfString, int on, int off, Message onComplete)1660     public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) {
1661         if (isPhoneTypeGsm()) {
1662             loge("[GsmCdmaPhone] sendBurstDtmf() is a CDMA method");
1663         } else {
1664             boolean check = true;
1665             for (int itr = 0;itr < dtmfString.length(); itr++) {
1666                 if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) {
1667                     Rlog.e(LOG_TAG,
1668                             "sendDtmf called with invalid character '" + dtmfString.charAt(itr)+ "'");
1669                     check = false;
1670                     break;
1671                 }
1672             }
1673             if (mCT.mState == PhoneConstants.State.OFFHOOK && check) {
1674                 mCi.sendBurstDtmf(dtmfString, on, off, onComplete);
1675             }
1676         }
1677     }
1678 
1679     @Override
setRadioPowerOnForTestEmergencyCall(boolean isSelectedPhoneForEmergencyCall)1680     public void setRadioPowerOnForTestEmergencyCall(boolean isSelectedPhoneForEmergencyCall) {
1681         mSST.clearAllRadioOffReasons();
1682 
1683         // We don't want to have forEmergency call be true to prevent radio emergencyDial command
1684         // from being called for a test emergency number because the network may not be able to
1685         // find emergency routing for it and dial it do the default emergency services line.
1686         setRadioPower(true, false, isSelectedPhoneForEmergencyCall, false);
1687     }
1688 
1689     @Override
setRadioPower(boolean power, boolean forEmergencyCall, boolean isSelectedPhoneForEmergencyCall, boolean forceApply)1690     public void setRadioPower(boolean power, boolean forEmergencyCall,
1691             boolean isSelectedPhoneForEmergencyCall, boolean forceApply) {
1692         setRadioPowerForReason(power, forEmergencyCall, isSelectedPhoneForEmergencyCall, forceApply,
1693                 Phone.RADIO_POWER_REASON_USER);
1694     }
1695 
1696     @Override
setRadioPowerForReason(boolean power, boolean forEmergencyCall, boolean isSelectedPhoneForEmergencyCall, boolean forceApply, int reason)1697     public void setRadioPowerForReason(boolean power, boolean forEmergencyCall,
1698             boolean isSelectedPhoneForEmergencyCall, boolean forceApply, int reason) {
1699         mSST.setRadioPowerForReason(power, forEmergencyCall, isSelectedPhoneForEmergencyCall,
1700                 forceApply, reason);
1701     }
1702 
storeVoiceMailNumber(String number)1703     private void storeVoiceMailNumber(String number) {
1704         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1705         SharedPreferences.Editor editor = sp.edit();
1706         setVmSimImsi(getSubscriberId());
1707         logd("storeVoiceMailNumber: mPrecisePhoneType=" + mPrecisePhoneType + " vmNumber="
1708                 + Rlog.pii(LOG_TAG, number));
1709         if (isPhoneTypeGsm()) {
1710             editor.putString(VM_NUMBER + getPhoneId(), number);
1711             editor.apply();
1712         } else {
1713             editor.putString(VM_NUMBER_CDMA + getPhoneId(), number);
1714             editor.apply();
1715         }
1716     }
1717 
1718     @Override
getVoiceMailNumber()1719     public String getVoiceMailNumber() {
1720         String number = null;
1721         if (isPhoneTypeGsm() || mSimRecords != null) {
1722             // Read from the SIM. If its null, try reading from the shared preference area.
1723             IccRecords r = isPhoneTypeGsm() ? mIccRecords.get() : mSimRecords;
1724             number = (r != null) ? r.getVoiceMailNumber() : "";
1725             if (TextUtils.isEmpty(number)) {
1726                 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1727                 String spName = isPhoneTypeGsm() ? VM_NUMBER : VM_NUMBER_CDMA;
1728                 number = sp.getString(spName + getPhoneId(), null);
1729                 logd("getVoiceMailNumber: from " + spName + " number="
1730                         + Rlog.pii(LOG_TAG, number));
1731             } else {
1732                 logd("getVoiceMailNumber: from IccRecords number=" + Rlog.pii(LOG_TAG, number));
1733             }
1734         }
1735         if (!isPhoneTypeGsm() && TextUtils.isEmpty(number)) {
1736             SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1737             number = sp.getString(VM_NUMBER_CDMA + getPhoneId(), null);
1738             logd("getVoiceMailNumber: from VM_NUMBER_CDMA number=" + number);
1739         }
1740 
1741         if (TextUtils.isEmpty(number)) {
1742             CarrierConfigManager configManager = (CarrierConfigManager)
1743                     getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
1744             PersistableBundle b = configManager.getConfigForSubId(getSubId());
1745             if (b != null) {
1746                 String defaultVmNumber =
1747                         b.getString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_STRING);
1748                 String defaultVmNumberRoaming =
1749                         b.getString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_ROAMING_STRING);
1750                 String defaultVmNumberRoamingAndImsUnregistered = b.getString(
1751                         CarrierConfigManager
1752                                 .KEY_DEFAULT_VM_NUMBER_ROAMING_AND_IMS_UNREGISTERED_STRING);
1753 
1754                 if (!TextUtils.isEmpty(defaultVmNumber)) number = defaultVmNumber;
1755                 if (mSST.mSS.getRoaming()) {
1756                     if (!TextUtils.isEmpty(defaultVmNumberRoamingAndImsUnregistered)
1757                             && !mSST.isImsRegistered()) {
1758                         // roaming and IMS unregistered case if CC configured
1759                         number = defaultVmNumberRoamingAndImsUnregistered;
1760                     } else if (!TextUtils.isEmpty(defaultVmNumberRoaming)) {
1761                         // roaming default case if CC configured
1762                         number = defaultVmNumberRoaming;
1763                     }
1764                 }
1765             }
1766         }
1767 
1768         if (TextUtils.isEmpty(number)) {
1769             // Read platform settings for dynamic voicemail number
1770             CarrierConfigManager configManager = (CarrierConfigManager)
1771                     getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
1772             PersistableBundle b = configManager.getConfigForSubId(getSubId());
1773             if (b != null && b.getBoolean(
1774                     CarrierConfigManager.KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL)) {
1775                 number = getLine1Number();
1776             }
1777         }
1778 
1779         return number;
1780     }
1781 
getVmSimImsi()1782     private String getVmSimImsi() {
1783         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1784         return sp.getString(VM_SIM_IMSI + getPhoneId(), null);
1785     }
1786 
setVmSimImsi(String imsi)1787     private void setVmSimImsi(String imsi) {
1788         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
1789         SharedPreferences.Editor editor = sp.edit();
1790         editor.putString(VM_SIM_IMSI + getPhoneId(), imsi);
1791         editor.apply();
1792     }
1793 
1794     @Override
getVoiceMailAlphaTag()1795     public String getVoiceMailAlphaTag() {
1796         String ret = "";
1797 
1798         if (isPhoneTypeGsm() || mSimRecords != null) {
1799             IccRecords r = isPhoneTypeGsm() ? mIccRecords.get() : mSimRecords;
1800 
1801             ret = (r != null) ? r.getVoiceMailAlphaTag() : "";
1802         }
1803 
1804         if (ret == null || ret.length() == 0) {
1805             return mContext.getText(
1806                 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString();
1807         }
1808 
1809         return ret;
1810     }
1811 
1812     @Override
getDeviceId()1813     public String getDeviceId() {
1814         if (isPhoneTypeGsm()) {
1815             return mImei;
1816         } else {
1817             CarrierConfigManager configManager = (CarrierConfigManager)
1818                     mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
1819             boolean force_imei = configManager.getConfigForSubId(getSubId())
1820                     .getBoolean(CarrierConfigManager.KEY_FORCE_IMEI_BOOL);
1821             if (force_imei) return mImei;
1822 
1823             String id = getMeid();
1824             if ((id == null) || id.matches("^0*$")) {
1825                 loge("getDeviceId(): MEID is not initialized use ESN");
1826                 id = getEsn();
1827             }
1828             return id;
1829         }
1830     }
1831 
1832     @Override
getDeviceSvn()1833     public String getDeviceSvn() {
1834         if (isPhoneTypeGsm() || isPhoneTypeCdmaLte()) {
1835             return mImeiSv;
1836         } else {
1837             loge("getDeviceSvn(): return 0");
1838             return "0";
1839         }
1840     }
1841 
1842     @Override
getIsimRecords()1843     public IsimRecords getIsimRecords() {
1844         return mIsimUiccRecords;
1845     }
1846 
1847     @Override
getImei()1848     public String getImei() {
1849         return mImei;
1850     }
1851 
1852     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
1853     @Override
getEsn()1854     public String getEsn() {
1855         if (isPhoneTypeGsm()) {
1856             loge("[GsmCdmaPhone] getEsn() is a CDMA method");
1857             return "0";
1858         } else {
1859             return mEsn;
1860         }
1861     }
1862 
1863     @Override
getMeid()1864     public String getMeid() {
1865         return mMeid;
1866     }
1867 
1868     @Override
getNai()1869     public String getNai() {
1870         IccRecords r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP2);
1871         if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) {
1872             Rlog.v(LOG_TAG, "IccRecords is " + r);
1873         }
1874         return (r != null) ? r.getNAI() : null;
1875     }
1876 
1877     @Override
1878     @Nullable
getSubscriberId()1879     public String getSubscriberId() {
1880         String subscriberId = null;
1881         if (isPhoneTypeCdma()) {
1882             subscriberId = mSST.getImsi();
1883         } else {
1884             // Both Gsm and CdmaLte get the IMSI from Usim.
1885             IccRecords iccRecords = mUiccController.getIccRecords(
1886                     mPhoneId, UiccController.APP_FAM_3GPP);
1887             if (iccRecords != null) {
1888                 subscriberId = iccRecords.getIMSI();
1889             }
1890         }
1891         return subscriberId;
1892     }
1893 
1894     @Override
getCarrierInfoForImsiEncryption(int keyType, boolean fallback)1895     public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType, boolean fallback) {
1896         String operatorNumeric = TelephonyManager.from(mContext)
1897                 .getSimOperatorNumericForPhone(mPhoneId);
1898         return CarrierInfoManager.getCarrierInfoForImsiEncryption(keyType,
1899                 mContext, operatorNumeric, fallback, getSubId());
1900     }
1901 
1902     @Override
setCarrierInfoForImsiEncryption(ImsiEncryptionInfo imsiEncryptionInfo)1903     public void setCarrierInfoForImsiEncryption(ImsiEncryptionInfo imsiEncryptionInfo) {
1904         CarrierInfoManager.setCarrierInfoForImsiEncryption(imsiEncryptionInfo, mContext, mPhoneId);
1905         mCi.setCarrierInfoForImsiEncryption(imsiEncryptionInfo, null);
1906     }
1907 
1908     @Override
deleteCarrierInfoForImsiEncryption()1909     public void deleteCarrierInfoForImsiEncryption() {
1910         CarrierInfoManager.deleteCarrierInfoForImsiEncryption(mContext, getSubId());
1911     }
1912 
1913     @Override
getCarrierId()1914     public int getCarrierId() {
1915         return mCarrierResolver != null
1916                 ? mCarrierResolver.getCarrierId() : super.getCarrierId();
1917     }
1918 
1919     @Override
getCarrierName()1920     public String getCarrierName() {
1921         return mCarrierResolver != null
1922                 ? mCarrierResolver.getCarrierName() : super.getCarrierName();
1923     }
1924 
1925     @Override
getMNOCarrierId()1926     public int getMNOCarrierId() {
1927         return mCarrierResolver != null
1928                 ? mCarrierResolver.getMnoCarrierId() : super.getMNOCarrierId();
1929     }
1930 
1931     @Override
getSpecificCarrierId()1932     public int getSpecificCarrierId() {
1933         return mCarrierResolver != null
1934                 ? mCarrierResolver.getSpecificCarrierId() : super.getSpecificCarrierId();
1935     }
1936 
1937     @Override
getSpecificCarrierName()1938     public String getSpecificCarrierName() {
1939         return mCarrierResolver != null
1940                 ? mCarrierResolver.getSpecificCarrierName() : super.getSpecificCarrierName();
1941     }
1942 
1943     @Override
resolveSubscriptionCarrierId(String simState)1944     public void resolveSubscriptionCarrierId(String simState) {
1945         if (mCarrierResolver != null) {
1946             mCarrierResolver.resolveSubscriptionCarrierId(simState);
1947         }
1948     }
1949 
1950     @Override
getCarrierIdListVersion()1951     public int getCarrierIdListVersion() {
1952         return mCarrierResolver != null
1953                 ? mCarrierResolver.getCarrierListVersion() : super.getCarrierIdListVersion();
1954     }
1955 
1956     @Override
getEmergencyNumberDbVersion()1957     public int getEmergencyNumberDbVersion() {
1958         return getEmergencyNumberTracker().getEmergencyNumberDbVersion();
1959     }
1960 
1961     @Override
resetCarrierKeysForImsiEncryption()1962     public void resetCarrierKeysForImsiEncryption() {
1963         mCIM.resetCarrierKeysForImsiEncryption(mContext, mPhoneId);
1964     }
1965 
1966     @Override
setCarrierTestOverride(String mccmnc, String imsi, String iccid, String gid1, String gid2, String pnn, String spn, String carrierPrivilegeRules, String apn)1967     public void setCarrierTestOverride(String mccmnc, String imsi, String iccid, String gid1,
1968             String gid2, String pnn, String spn, String carrierPrivilegeRules, String apn) {
1969         mCarrierResolver.setTestOverrideApn(apn);
1970         UiccProfile uiccProfile = mUiccController.getUiccProfileForPhone(getPhoneId());
1971         if (uiccProfile != null) {
1972             List<UiccAccessRule> testRules;
1973             if (carrierPrivilegeRules == null) {
1974                 testRules = null;
1975             } else if (carrierPrivilegeRules.isEmpty()) {
1976                 testRules = Collections.emptyList();
1977             } else {
1978                 UiccAccessRule accessRule = new UiccAccessRule(
1979                         IccUtils.hexStringToBytes(carrierPrivilegeRules), null, 0);
1980                 testRules = Collections.singletonList(accessRule);
1981             }
1982             uiccProfile.setTestOverrideCarrierPrivilegeRules(testRules);
1983         } else {
1984             // TODO: Fix "privilege" typo throughout telephony.
1985             mCarrierResolver.setTestOverrideCarrierPriviledgeRule(carrierPrivilegeRules); // NOTYPO
1986         }
1987         IccRecords r = null;
1988         if (isPhoneTypeGsm()) {
1989             r = mIccRecords.get();
1990         } else if (isPhoneTypeCdmaLte()) {
1991             r = mSimRecords;
1992         } else {
1993             loge("setCarrierTestOverride fails in CDMA only");
1994         }
1995         if (r != null) {
1996             r.setCarrierTestOverride(mccmnc, imsi, iccid, gid1, gid2, pnn, spn);
1997         }
1998     }
1999 
2000     @Override
getGroupIdLevel1()2001     public String getGroupIdLevel1() {
2002         if (isPhoneTypeGsm()) {
2003             IccRecords r = mIccRecords.get();
2004             return (r != null) ? r.getGid1() : null;
2005         } else if (isPhoneTypeCdma()) {
2006             loge("GID1 is not available in CDMA");
2007             return null;
2008         } else { //isPhoneTypeCdmaLte()
2009             return (mSimRecords != null) ? mSimRecords.getGid1() : "";
2010         }
2011     }
2012 
2013     @Override
getGroupIdLevel2()2014     public String getGroupIdLevel2() {
2015         if (isPhoneTypeGsm()) {
2016             IccRecords r = mIccRecords.get();
2017             return (r != null) ? r.getGid2() : null;
2018         } else if (isPhoneTypeCdma()) {
2019             loge("GID2 is not available in CDMA");
2020             return null;
2021         } else { //isPhoneTypeCdmaLte()
2022             return (mSimRecords != null) ? mSimRecords.getGid2() : "";
2023         }
2024     }
2025 
2026     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2027     @Override
getLine1Number()2028     public String getLine1Number() {
2029         if (isPhoneTypeGsm()) {
2030             IccRecords r = mIccRecords.get();
2031             return (r != null) ? r.getMsisdnNumber() : null;
2032         } else {
2033             CarrierConfigManager configManager = (CarrierConfigManager)
2034                     mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);
2035             boolean use_usim = configManager.getConfigForSubId(getSubId()).getBoolean(
2036                     CarrierConfigManager.KEY_USE_USIM_BOOL);
2037             if (use_usim) {
2038                 return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null;
2039             }
2040             return mSST.getMdnNumber();
2041         }
2042     }
2043 
2044     @Override
getPlmn()2045     public String getPlmn() {
2046         if (isPhoneTypeGsm()) {
2047             IccRecords r = mIccRecords.get();
2048             return (r != null) ? r.getPnnHomeName() : null;
2049         } else if (isPhoneTypeCdma()) {
2050             loge("Plmn is not available in CDMA");
2051             return null;
2052         } else { //isPhoneTypeCdmaLte()
2053             return (mSimRecords != null) ? mSimRecords.getPnnHomeName() : null;
2054         }
2055     }
2056 
2057     /**
2058      * Update non-persisited manual network selection.
2059      *
2060      * @param nsm contains Plmn info
2061      */
2062     @Override
updateManualNetworkSelection(NetworkSelectMessage nsm)2063     protected void updateManualNetworkSelection(NetworkSelectMessage nsm) {
2064         int subId = getSubId();
2065         if (SubscriptionManager.isValidSubscriptionId(subId)) {
2066             mManualNetworkSelectionPlmn = nsm.operatorNumeric;
2067         } else {
2068         //on Phone0 in emergency mode (no SIM), or in some races then clear the cache
2069             mManualNetworkSelectionPlmn = null;
2070             Rlog.e(LOG_TAG, "Cannot update network selection due to invalid subId "
2071                     + subId);
2072         }
2073     }
2074 
2075     @Override
getManualNetworkSelectionPlmn()2076     public String getManualNetworkSelectionPlmn() {
2077         return (mManualNetworkSelectionPlmn == null) ? "" : mManualNetworkSelectionPlmn;
2078     }
2079 
2080     @Override
getCdmaPrlVersion()2081     public String getCdmaPrlVersion() {
2082         return mSST.getPrlVersion();
2083     }
2084 
2085     @Override
getCdmaMin()2086     public String getCdmaMin() {
2087         return mSST.getCdmaMin();
2088     }
2089 
2090     @Override
isMinInfoReady()2091     public boolean isMinInfoReady() {
2092         return mSST.isMinInfoReady();
2093     }
2094 
2095     @Override
getMsisdn()2096     public String getMsisdn() {
2097         if (isPhoneTypeGsm()) {
2098             IccRecords r = mIccRecords.get();
2099             return (r != null) ? r.getMsisdnNumber() : null;
2100         } else if (isPhoneTypeCdmaLte()) {
2101             return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null;
2102         } else {
2103             loge("getMsisdn: not expected on CDMA");
2104             return null;
2105         }
2106     }
2107 
2108     @Override
getLine1AlphaTag()2109     public String getLine1AlphaTag() {
2110         if (isPhoneTypeGsm()) {
2111             IccRecords r = mIccRecords.get();
2112             return (r != null) ? r.getMsisdnAlphaTag() : null;
2113         } else {
2114             loge("getLine1AlphaTag: not possible in CDMA");
2115             return null;
2116         }
2117     }
2118 
2119     @Override
setLine1Number(String alphaTag, String number, Message onComplete)2120     public boolean setLine1Number(String alphaTag, String number, Message onComplete) {
2121         if (isPhoneTypeGsm()) {
2122             IccRecords r = mIccRecords.get();
2123             if (r != null) {
2124                 r.setMsisdnNumber(alphaTag, number, onComplete);
2125                 return true;
2126             } else {
2127                 return false;
2128             }
2129         } else {
2130             loge("setLine1Number: not possible in CDMA");
2131             return false;
2132         }
2133     }
2134 
2135     @Override
setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete)2136     public void setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete) {
2137         Message resp;
2138         mVmNumber = voiceMailNumber;
2139         resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete);
2140 
2141         IccRecords r = mIccRecords.get();
2142 
2143         if (!isPhoneTypeGsm() && mSimRecords != null) {
2144             r = mSimRecords;
2145         }
2146 
2147         if (r != null) {
2148             r.setVoiceMailNumber(alphaTag, mVmNumber, resp);
2149         }
2150     }
2151 
2152     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isValidCommandInterfaceCFReason(int commandInterfaceCFReason)2153     private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) {
2154         switch (commandInterfaceCFReason) {
2155             case CF_REASON_UNCONDITIONAL:
2156             case CF_REASON_BUSY:
2157             case CF_REASON_NO_REPLY:
2158             case CF_REASON_NOT_REACHABLE:
2159             case CF_REASON_ALL:
2160             case CF_REASON_ALL_CONDITIONAL:
2161                 return true;
2162             default:
2163                 return false;
2164         }
2165     }
2166 
2167     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2168     @Override
getSystemProperty(String property, String defValue)2169     public String getSystemProperty(String property, String defValue) {
2170         if (getUnitTestMode()) {
2171             return null;
2172         }
2173         return TelephonyManager.getTelephonyProperty(mPhoneId, property, defValue);
2174     }
2175 
2176     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isValidCommandInterfaceCFAction(int commandInterfaceCFAction)2177     private boolean isValidCommandInterfaceCFAction (int commandInterfaceCFAction) {
2178         switch (commandInterfaceCFAction) {
2179             case CF_ACTION_DISABLE:
2180             case CF_ACTION_ENABLE:
2181             case CF_ACTION_REGISTRATION:
2182             case CF_ACTION_ERASURE:
2183                 return true;
2184             default:
2185                 return false;
2186         }
2187     }
2188 
2189     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isCfEnable(int action)2190     private boolean isCfEnable(int action) {
2191         return (action == CF_ACTION_ENABLE) || (action == CF_ACTION_REGISTRATION);
2192     }
2193 
isImsUtEnabledOverCdma()2194     private boolean isImsUtEnabledOverCdma() {
2195         return isPhoneTypeCdmaLte()
2196             && mImsPhone != null
2197             && mImsPhone.isUtEnabled();
2198     }
2199 
isCsRetry(Message onComplete)2200     private boolean isCsRetry(Message onComplete) {
2201         if (onComplete != null) {
2202             return onComplete.getData().getBoolean(CS_FALLBACK_SS, false);
2203         }
2204         return false;
2205     }
2206 
updateSsOverCdmaSupported(PersistableBundle b)2207     private void updateSsOverCdmaSupported(PersistableBundle b) {
2208         if (b == null) return;
2209         mSsOverCdmaSupported = b.getBoolean(CarrierConfigManager.KEY_SUPPORT_SS_OVER_CDMA_BOOL);
2210     }
2211 
2212     @Override
useSsOverIms(Message onComplete)2213     public boolean useSsOverIms(Message onComplete) {
2214         boolean isUtEnabled = isUtEnabled();
2215 
2216         Rlog.d(LOG_TAG, "useSsOverIms: isUtEnabled()= " + isUtEnabled +
2217                 " isCsRetry(onComplete))= " + isCsRetry(onComplete));
2218 
2219         if (isUtEnabled && !isCsRetry(onComplete)) {
2220             return true;
2221         }
2222         return false;
2223     }
2224 
2225     @Override
getCallForwardingOption(int commandInterfaceCFReason, Message onComplete)2226     public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) {
2227         getCallForwardingOption(commandInterfaceCFReason,
2228                 CommandsInterface.SERVICE_CLASS_VOICE, onComplete);
2229     }
2230 
2231     @Override
getCallForwardingOption(int commandInterfaceCFReason, int serviceClass, Message onComplete)2232     public void getCallForwardingOption(int commandInterfaceCFReason, int serviceClass,
2233             Message onComplete) {
2234         Phone imsPhone = mImsPhone;
2235         if (useSsOverIms(onComplete)) {
2236             imsPhone.getCallForwardingOption(commandInterfaceCFReason, serviceClass, onComplete);
2237             return;
2238         }
2239 
2240         if (isPhoneTypeGsm()) {
2241             if (isValidCommandInterfaceCFReason(commandInterfaceCFReason)) {
2242                 if (DBG) logd("requesting call forwarding query.");
2243                 Message resp;
2244                 if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) {
2245                     resp = obtainMessage(EVENT_GET_CALL_FORWARD_DONE, onComplete);
2246                 } else {
2247                     resp = onComplete;
2248                 }
2249                 mCi.queryCallForwardStatus(commandInterfaceCFReason, serviceClass, null, resp);
2250             }
2251         } else {
2252             if (!mSsOverCdmaSupported) {
2253                 // If SS over CDMA is not supported and UT is not at the time, notify the user of
2254                 // the error and disable the option.
2255                 AsyncResult.forMessage(onComplete, null,
2256                         new CommandException(CommandException.Error.INVALID_STATE,
2257                                 "Call Forwarding over CDMA unavailable"));
2258             } else {
2259                 loge("getCallForwardingOption: not possible in CDMA, just return empty result");
2260                 AsyncResult.forMessage(onComplete, makeEmptyCallForward(), null);
2261             }
2262             onComplete.sendToTarget();
2263         }
2264     }
2265 
2266     @Override
setCallForwardingOption(int commandInterfaceCFAction, int commandInterfaceCFReason, String dialingNumber, int timerSeconds, Message onComplete)2267     public void setCallForwardingOption(int commandInterfaceCFAction,
2268             int commandInterfaceCFReason,
2269             String dialingNumber,
2270             int timerSeconds,
2271             Message onComplete) {
2272         setCallForwardingOption(commandInterfaceCFAction, commandInterfaceCFReason,
2273                 dialingNumber, CommandsInterface.SERVICE_CLASS_VOICE, timerSeconds, onComplete);
2274     }
2275 
2276     @Override
setCallForwardingOption(int commandInterfaceCFAction, int commandInterfaceCFReason, String dialingNumber, int serviceClass, int timerSeconds, Message onComplete)2277     public void setCallForwardingOption(int commandInterfaceCFAction,
2278             int commandInterfaceCFReason,
2279             String dialingNumber,
2280             int serviceClass,
2281             int timerSeconds,
2282             Message onComplete) {
2283         Phone imsPhone = mImsPhone;
2284         if (useSsOverIms(onComplete)) {
2285             imsPhone.setCallForwardingOption(commandInterfaceCFAction, commandInterfaceCFReason,
2286                     dialingNumber, serviceClass, timerSeconds, onComplete);
2287             return;
2288         }
2289 
2290         if (isPhoneTypeGsm()) {
2291             if ((isValidCommandInterfaceCFAction(commandInterfaceCFAction)) &&
2292                     (isValidCommandInterfaceCFReason(commandInterfaceCFReason))) {
2293 
2294                 Message resp;
2295                 if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) {
2296                     Cfu cfu = new Cfu(dialingNumber, onComplete);
2297                     resp = obtainMessage(EVENT_SET_CALL_FORWARD_DONE,
2298                             isCfEnable(commandInterfaceCFAction) ? 1 : 0, 0, cfu);
2299                 } else {
2300                     resp = onComplete;
2301                 }
2302                 mCi.setCallForward(commandInterfaceCFAction,
2303                         commandInterfaceCFReason,
2304                         serviceClass,
2305                         dialingNumber,
2306                         timerSeconds,
2307                         resp);
2308             }
2309         } else if (mSsOverCdmaSupported) {
2310             String formatNumber = GsmCdmaConnection.formatDialString(dialingNumber);
2311             String cfNumber = CdmaMmiCode.getCallForwardingPrefixAndNumber(
2312                     commandInterfaceCFAction, commandInterfaceCFReason, formatNumber);
2313             loge("setCallForwardingOption: dial for set call forwarding"
2314                     + " prefixWithNumber= " + cfNumber + " number= " + dialingNumber);
2315 
2316             PhoneAccountHandle phoneAccountHandle = subscriptionIdToPhoneAccountHandle(getSubId());
2317             Bundle extras = new Bundle();
2318             extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
2319 
2320             final TelecomManager telecomManager = TelecomManager.from(mContext);
2321             telecomManager.placeCall(
2322                     Uri.fromParts(PhoneAccount.SCHEME_TEL, cfNumber, null), extras);
2323 
2324             AsyncResult.forMessage(onComplete, CommandsInterface.SS_STATUS_UNKNOWN, null);
2325             onComplete.sendToTarget();
2326         } else {
2327             loge("setCallForwardingOption: SS over CDMA not supported, can not complete");
2328             AsyncResult.forMessage(onComplete, CommandsInterface.SS_STATUS_UNKNOWN, null);
2329             onComplete.sendToTarget();
2330         }
2331     }
2332 
2333     @Override
getCallBarring(String facility, String password, Message onComplete, int serviceClass)2334     public void getCallBarring(String facility, String password, Message onComplete,
2335             int serviceClass) {
2336         Phone imsPhone = mImsPhone;
2337         if (useSsOverIms(onComplete)) {
2338             imsPhone.getCallBarring(facility, password, onComplete, serviceClass);
2339             return;
2340         }
2341 
2342         if (isPhoneTypeGsm()) {
2343             mCi.queryFacilityLock(facility, password, serviceClass, onComplete);
2344         } else {
2345             loge("getCallBarringOption: not possible in CDMA");
2346         }
2347     }
2348 
2349     @Override
setCallBarring(String facility, boolean lockState, String password, Message onComplete, int serviceClass)2350     public void setCallBarring(String facility, boolean lockState, String password,
2351             Message onComplete, int serviceClass) {
2352         Phone imsPhone = mImsPhone;
2353         if (useSsOverIms(onComplete)) {
2354             imsPhone.setCallBarring(facility, lockState, password, onComplete, serviceClass);
2355             return;
2356         }
2357 
2358         if (isPhoneTypeGsm()) {
2359             mCi.setFacilityLock(facility, lockState, password, serviceClass, onComplete);
2360         } else {
2361             loge("setCallBarringOption: not possible in CDMA");
2362         }
2363     }
2364 
2365     /**
2366      * Changes access code used for call barring
2367      *
2368      * @param facility is one of CB_FACILTY_*
2369      * @param oldPwd is old password
2370      * @param newPwd is new password
2371      * @param onComplete is callback message when the action is completed.
2372      */
changeCallBarringPassword(String facility, String oldPwd, String newPwd, Message onComplete)2373     public void changeCallBarringPassword(String facility, String oldPwd, String newPwd,
2374             Message onComplete) {
2375         if (isPhoneTypeGsm()) {
2376             mCi.changeBarringPassword(facility, oldPwd, newPwd, onComplete);
2377         } else {
2378             loge("changeCallBarringPassword: not possible in CDMA");
2379         }
2380     }
2381 
2382     @Override
getOutgoingCallerIdDisplay(Message onComplete)2383     public void getOutgoingCallerIdDisplay(Message onComplete) {
2384         Phone imsPhone = mImsPhone;
2385         if (useSsOverIms(onComplete)) {
2386             imsPhone.getOutgoingCallerIdDisplay(onComplete);
2387             return;
2388         }
2389 
2390         if (isPhoneTypeGsm()) {
2391             mCi.getCLIR(onComplete);
2392         } else {
2393             loge("getOutgoingCallerIdDisplay: not possible in CDMA");
2394             AsyncResult.forMessage(onComplete, null,
2395                     new CommandException(CommandException.Error.REQUEST_NOT_SUPPORTED));
2396             onComplete.sendToTarget();
2397         }
2398     }
2399 
2400     @Override
setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete)2401     public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) {
2402         Phone imsPhone = mImsPhone;
2403         if (useSsOverIms(onComplete)) {
2404             imsPhone.setOutgoingCallerIdDisplay(commandInterfaceCLIRMode, onComplete);
2405             return;
2406         }
2407 
2408         if (isPhoneTypeGsm()) {
2409             // Packing CLIR value in the message. This will be required for
2410             // SharedPreference caching, if the message comes back as part of
2411             // a success response.
2412             mCi.setCLIR(commandInterfaceCLIRMode,
2413                     obtainMessage(EVENT_SET_CLIR_COMPLETE, commandInterfaceCLIRMode, 0, onComplete));
2414         } else {
2415             loge("setOutgoingCallerIdDisplay: not possible in CDMA");
2416             AsyncResult.forMessage(onComplete, null,
2417                     new CommandException(CommandException.Error.REQUEST_NOT_SUPPORTED));
2418             onComplete.sendToTarget();
2419         }
2420     }
2421 
2422     @Override
queryCLIP(Message onComplete)2423     public void queryCLIP(Message onComplete) {
2424         Phone imsPhone = mImsPhone;
2425         if (useSsOverIms(onComplete)) {
2426             imsPhone.queryCLIP(onComplete);
2427             return;
2428         }
2429 
2430         if (isPhoneTypeGsm()) {
2431             mCi.queryCLIP(onComplete);
2432         } else {
2433             loge("queryCLIP: not possible in CDMA");
2434             AsyncResult.forMessage(onComplete, null,
2435                     new CommandException(CommandException.Error.REQUEST_NOT_SUPPORTED));
2436             onComplete.sendToTarget();
2437         }
2438     }
2439 
2440     @Override
getCallWaiting(Message onComplete)2441     public void getCallWaiting(Message onComplete) {
2442         Phone imsPhone = mImsPhone;
2443         if (useSsOverIms(onComplete)) {
2444             imsPhone.getCallWaiting(onComplete);
2445             return;
2446         }
2447 
2448         if (isPhoneTypeGsm()) {
2449             //As per 3GPP TS 24.083, section 1.6 UE doesn't need to send service
2450             //class parameter in call waiting interrogation  to network
2451             mCi.queryCallWaiting(CommandsInterface.SERVICE_CLASS_NONE, onComplete);
2452         } else {
2453             if (!mSsOverCdmaSupported) {
2454                 // If SS over CDMA is not supported and UT is not at the time, notify the user of
2455                 // the error and disable the option.
2456                 AsyncResult.forMessage(onComplete, null,
2457                         new CommandException(CommandException.Error.INVALID_STATE,
2458                                 "Call Waiting over CDMA unavailable"));
2459             } else {
2460                 int[] arr =
2461                         {CommandsInterface.SS_STATUS_UNKNOWN, CommandsInterface.SERVICE_CLASS_NONE};
2462                 AsyncResult.forMessage(onComplete, arr, null);
2463             }
2464             onComplete.sendToTarget();
2465         }
2466     }
2467 
2468     @Override
setCallWaiting(boolean enable, Message onComplete)2469     public void setCallWaiting(boolean enable, Message onComplete) {
2470         int serviceClass = CommandsInterface.SERVICE_CLASS_VOICE;
2471         CarrierConfigManager configManager = (CarrierConfigManager)
2472             getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
2473         PersistableBundle b = configManager.getConfigForSubId(getSubId());
2474         if (b != null) {
2475             serviceClass = b.getInt(CarrierConfigManager.KEY_CALL_WAITING_SERVICE_CLASS_INT,
2476                     CommandsInterface.SERVICE_CLASS_VOICE);
2477         }
2478         setCallWaiting(enable, serviceClass, onComplete);
2479     }
2480 
2481     @Override
setCallWaiting(boolean enable, int serviceClass, Message onComplete)2482     public void setCallWaiting(boolean enable, int serviceClass, Message onComplete) {
2483         Phone imsPhone = mImsPhone;
2484         if (useSsOverIms(onComplete)) {
2485             imsPhone.setCallWaiting(enable, onComplete);
2486             return;
2487         }
2488 
2489         if (isPhoneTypeGsm()) {
2490             mCi.setCallWaiting(enable, serviceClass, onComplete);
2491         } else if (mSsOverCdmaSupported) {
2492             String cwPrefix = CdmaMmiCode.getCallWaitingPrefix(enable);
2493             Rlog.i(LOG_TAG, "setCallWaiting in CDMA : dial for set call waiting" + " prefix= " + cwPrefix);
2494 
2495             PhoneAccountHandle phoneAccountHandle = subscriptionIdToPhoneAccountHandle(getSubId());
2496             Bundle extras = new Bundle();
2497             extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle);
2498 
2499             final TelecomManager telecomManager = TelecomManager.from(mContext);
2500             telecomManager.placeCall(
2501                     Uri.fromParts(PhoneAccount.SCHEME_TEL, cwPrefix, null), extras);
2502 
2503             AsyncResult.forMessage(onComplete, CommandsInterface.SS_STATUS_UNKNOWN, null);
2504             onComplete.sendToTarget();
2505         } else {
2506             loge("setCallWaiting: SS over CDMA not supported, can not complete");
2507             AsyncResult.forMessage(onComplete, CommandsInterface.SS_STATUS_UNKNOWN, null);
2508             onComplete.sendToTarget();
2509         }
2510     }
2511 
2512     @Override
getAvailableNetworks(Message response)2513     public void getAvailableNetworks(Message response) {
2514         if (isPhoneTypeGsm() || isPhoneTypeCdmaLte()) {
2515             Message msg = obtainMessage(EVENT_GET_AVAILABLE_NETWORKS_DONE, response);
2516             mCi.getAvailableNetworks(msg);
2517         } else {
2518             loge("getAvailableNetworks: not possible in CDMA");
2519         }
2520     }
2521 
2522     @Override
startNetworkScan(NetworkScanRequest nsr, Message response)2523     public void startNetworkScan(NetworkScanRequest nsr, Message response) {
2524         mCi.startNetworkScan(nsr, response);
2525     }
2526 
2527     @Override
stopNetworkScan(Message response)2528     public void stopNetworkScan(Message response) {
2529         mCi.stopNetworkScan(response);
2530     }
2531 
2532     @Override
setTTYMode(int ttyMode, Message onComplete)2533     public void setTTYMode(int ttyMode, Message onComplete) {
2534         // Send out the TTY Mode change over RIL as well
2535         super.setTTYMode(ttyMode, onComplete);
2536         if (mImsPhone != null) {
2537             mImsPhone.setTTYMode(ttyMode, onComplete);
2538         }
2539     }
2540 
2541     @Override
setUiTTYMode(int uiTtyMode, Message onComplete)2542     public void setUiTTYMode(int uiTtyMode, Message onComplete) {
2543        if (mImsPhone != null) {
2544            mImsPhone.setUiTTYMode(uiTtyMode, onComplete);
2545        }
2546     }
2547 
2548     @Override
setMute(boolean muted)2549     public void setMute(boolean muted) {
2550         mCT.setMute(muted);
2551     }
2552 
2553     @Override
getMute()2554     public boolean getMute() {
2555         return mCT.getMute();
2556     }
2557 
2558     @Override
updateServiceLocation(WorkSource workSource)2559     public void updateServiceLocation(WorkSource workSource) {
2560         mSST.enableSingleLocationUpdate(workSource);
2561     }
2562 
2563     @Override
enableLocationUpdates()2564     public void enableLocationUpdates() {
2565         mSST.enableLocationUpdates();
2566     }
2567 
2568     @Override
disableLocationUpdates()2569     public void disableLocationUpdates() {
2570         mSST.disableLocationUpdates();
2571     }
2572 
2573     @Override
getDataRoamingEnabled()2574     public boolean getDataRoamingEnabled() {
2575         if (getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) != null) {
2576             return getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).getDataRoamingEnabled();
2577         }
2578         return false;
2579     }
2580 
2581     @Override
setDataRoamingEnabled(boolean enable)2582     public void setDataRoamingEnabled(boolean enable) {
2583         if (getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) != null) {
2584             getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
2585                     .setDataRoamingEnabledByUser(enable);
2586         }
2587     }
2588 
2589     @Override
registerForCdmaOtaStatusChange(Handler h, int what, Object obj)2590     public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) {
2591         mCi.registerForCdmaOtaProvision(h, what, obj);
2592     }
2593 
2594     @Override
unregisterForCdmaOtaStatusChange(Handler h)2595     public void unregisterForCdmaOtaStatusChange(Handler h) {
2596         mCi.unregisterForCdmaOtaProvision(h);
2597     }
2598 
2599     @Override
registerForSubscriptionInfoReady(Handler h, int what, Object obj)2600     public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) {
2601         mSST.registerForSubscriptionInfoReady(h, what, obj);
2602     }
2603 
2604     @Override
unregisterForSubscriptionInfoReady(Handler h)2605     public void unregisterForSubscriptionInfoReady(Handler h) {
2606         mSST.unregisterForSubscriptionInfoReady(h);
2607     }
2608 
2609     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
2610     @Override
setOnEcbModeExitResponse(Handler h, int what, Object obj)2611     public void setOnEcbModeExitResponse(Handler h, int what, Object obj) {
2612         mEcmExitRespRegistrant = new Registrant(h, what, obj);
2613     }
2614 
2615     @Override
unsetOnEcbModeExitResponse(Handler h)2616     public void unsetOnEcbModeExitResponse(Handler h) {
2617         mEcmExitRespRegistrant.clear();
2618     }
2619 
2620     @Override
registerForCallWaiting(Handler h, int what, Object obj)2621     public void registerForCallWaiting(Handler h, int what, Object obj) {
2622         mCT.registerForCallWaiting(h, what, obj);
2623     }
2624 
2625     @Override
unregisterForCallWaiting(Handler h)2626     public void unregisterForCallWaiting(Handler h) {
2627         mCT.unregisterForCallWaiting(h);
2628     }
2629 
2630     /**
2631      * Whether data is enabled by user. Unlike isDataEnabled, this only
2632      * checks user setting stored in {@link android.provider.Settings.Global#MOBILE_DATA}
2633      * if not provisioning, or isProvisioningDataEnabled if provisioning.
2634      */
2635     @Override
isUserDataEnabled()2636     public boolean isUserDataEnabled() {
2637         if (mDataEnabledSettings.isProvisioning()) {
2638             return mDataEnabledSettings.isProvisioningDataEnabled();
2639         } else {
2640             return mDataEnabledSettings.isUserDataEnabled();
2641         }
2642     }
2643 
2644     /**
2645      * Removes the given MMI from the pending list and notifies
2646      * registrants that it is complete.
2647      * @param mmi MMI that is done
2648      */
onMMIDone(MmiCode mmi)2649     public void onMMIDone(MmiCode mmi) {
2650         /* Only notify complete if it's on the pending list.
2651          * Otherwise, it's already been handled (eg, previously canceled).
2652          * The exception is cancellation of an incoming USSD-REQUEST, which is
2653          * not on the list.
2654          */
2655         if (mPendingMMIs.remove(mmi) || (isPhoneTypeGsm() && (mmi.isUssdRequest() ||
2656                 ((GsmMmiCode)mmi).isSsInfo()))) {
2657             ResultReceiver receiverCallback = mmi.getUssdCallbackReceiver();
2658             if (receiverCallback != null) {
2659                 Rlog.i(LOG_TAG, "onMMIDone: invoking callback: " + mmi);
2660                 int returnCode = (mmi.getState() ==  MmiCode.State.COMPLETE) ?
2661                     TelephonyManager.USSD_RETURN_SUCCESS : TelephonyManager.USSD_RETURN_FAILURE;
2662                 sendUssdResponse(mmi.getDialString(), mmi.getMessage(), returnCode,
2663                         receiverCallback );
2664             } else {
2665                 Rlog.i(LOG_TAG, "onMMIDone: notifying registrants: " + mmi);
2666                 mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
2667             }
2668         } else {
2669             Rlog.i(LOG_TAG, "onMMIDone: invalid response or already handled; ignoring: " + mmi);
2670         }
2671     }
2672 
supports3gppCallForwardingWhileRoaming()2673     public boolean supports3gppCallForwardingWhileRoaming() {
2674         CarrierConfigManager configManager = (CarrierConfigManager)
2675                 getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
2676         PersistableBundle b = configManager.getConfigForSubId(getSubId());
2677         if (b != null) {
2678             return b.getBoolean(
2679                     CarrierConfigManager.KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL, true);
2680         } else {
2681             // Default value set in CarrierConfigManager
2682             return true;
2683         }
2684     }
2685 
onNetworkInitiatedUssd(MmiCode mmi)2686     private void onNetworkInitiatedUssd(MmiCode mmi) {
2687         Rlog.v(LOG_TAG, "onNetworkInitiatedUssd: mmi=" + mmi);
2688         mMmiCompleteRegistrants.notifyRegistrants(
2689             new AsyncResult(null, mmi, null));
2690     }
2691 
2692     /** ussdMode is one of CommandsInterface.USSD_MODE_* */
onIncomingUSSD(int ussdMode, String ussdMessage)2693     private void onIncomingUSSD (int ussdMode, String ussdMessage) {
2694         if (!isPhoneTypeGsm()) {
2695             loge("onIncomingUSSD: not expected on GSM");
2696         }
2697 
2698         boolean isUssdError;
2699         boolean isUssdRequest;
2700         boolean isUssdRelease;
2701 
2702         isUssdRequest
2703             = (ussdMode == CommandsInterface.USSD_MODE_REQUEST);
2704 
2705         isUssdError
2706             = (ussdMode != CommandsInterface.USSD_MODE_NOTIFY
2707                 && ussdMode != CommandsInterface.USSD_MODE_REQUEST);
2708 
2709         isUssdRelease = (ussdMode == CommandsInterface.USSD_MODE_NW_RELEASE);
2710 
2711 
2712         // See comments in GsmMmiCode.java
2713         // USSD requests aren't finished until one
2714         // of these two events happen
2715         GsmMmiCode found = null;
2716         for (int i = 0, s = mPendingMMIs.size() ; i < s; i++) {
2717             if(((GsmMmiCode)mPendingMMIs.get(i)).isPendingUSSD()) {
2718                 found = (GsmMmiCode)mPendingMMIs.get(i);
2719                 break;
2720             }
2721         }
2722 
2723         if (found != null) {
2724             // Complete pending USSD
2725             if (isUssdRelease) {
2726                 found.onUssdRelease();
2727             } else if (isUssdError) {
2728                 found.onUssdFinishedError();
2729             } else {
2730                 found.onUssdFinished(ussdMessage, isUssdRequest);
2731             }
2732         } else if (!isUssdError && !TextUtils.isEmpty(ussdMessage)) {
2733             // pending USSD not found
2734             // The network may initiate its own USSD request
2735 
2736             // ignore everything that isnt a Notify or a Request
2737             // also, discard if there is no message to present
2738             GsmMmiCode mmi;
2739             mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage,
2740                                                    isUssdRequest,
2741                                                    GsmCdmaPhone.this,
2742                                                    mUiccApplication.get());
2743             onNetworkInitiatedUssd(mmi);
2744         } else if (isUssdError && !isUssdRelease) {
2745             GsmMmiCode mmi;
2746             mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage,
2747                     true,
2748                     GsmCdmaPhone.this,
2749                     mUiccApplication.get());
2750             mmi.onUssdFinishedError();
2751         }
2752     }
2753 
2754     /**
2755      * Make sure the network knows our preferred setting.
2756      */
2757     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
syncClirSetting()2758     private void syncClirSetting() {
2759         SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext());
2760         migrateClirSettingIfNeeded(sp);
2761 
2762         int clirSetting = sp.getInt(CLIR_KEY + getSubId(), -1);
2763         Rlog.i(LOG_TAG, "syncClirSetting: " + CLIR_KEY + getSubId() + "=" + clirSetting);
2764         if (clirSetting >= 0) {
2765             mCi.setCLIR(clirSetting, null);
2766         } else {
2767             // if there is no preference set, ensure the CLIR is updated to the default value in
2768             // order to ensure that CLIR values in the RIL are not carried over during SIM swap.
2769             mCi.setCLIR(CommandsInterface.CLIR_DEFAULT, null);
2770         }
2771     }
2772 
2773     /**
2774      * Migrate CLIR setting with sudId mapping once if there's CLIR setting mapped with phoneId.
2775      */
migrateClirSettingIfNeeded(SharedPreferences sp)2776     private void migrateClirSettingIfNeeded(SharedPreferences sp) {
2777         // Get old CLIR setting mapped with phoneId
2778         int clirSetting = sp.getInt("clir_key" + getPhoneId(), -1);
2779         if (clirSetting >= 0) {
2780             // Migrate CLIR setting to new shared preference key with subId
2781             Rlog.i(LOG_TAG, "Migrate CLIR setting: value=" + clirSetting + ", clir_key"
2782                     + getPhoneId() + " -> " + CLIR_KEY + getSubId());
2783             SharedPreferences.Editor editor = sp.edit();
2784             editor.putInt(CLIR_KEY + getSubId(), clirSetting);
2785 
2786             // Remove old CLIR setting key
2787             editor.remove("clir_key" + getPhoneId()).commit();
2788         }
2789     }
2790 
handleRadioAvailable()2791     private void handleRadioAvailable() {
2792         mCi.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE));
2793 
2794         mCi.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE));
2795         mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));
2796         mCi.areUiccApplicationsEnabled(obtainMessage(EVENT_GET_UICC_APPS_ENABLEMENT_DONE));
2797 
2798         startLceAfterRadioIsAvailable();
2799     }
2800 
handleRadioOn()2801     private void handleRadioOn() {
2802         /* Proactively query voice radio technologies */
2803         mCi.getVoiceRadioTechnology(obtainMessage(EVENT_REQUEST_VOICE_RADIO_TECH_DONE));
2804 
2805         if (!isPhoneTypeGsm()) {
2806             mCdmaSubscriptionSource = mCdmaSSM.getCdmaSubscriptionSource();
2807         }
2808 
2809         // If this is on APM off, SIM may already be loaded. Send setPreferredNetworkType
2810         // request to RIL to preserve user setting across APM toggling
2811         setPreferredNetworkTypeIfSimLoaded();
2812     }
2813 
handleRadioOffOrNotAvailable()2814     private void handleRadioOffOrNotAvailable() {
2815         if (isPhoneTypeGsm()) {
2816             // Some MMI requests (eg USSD) are not completed
2817             // within the course of a CommandsInterface request
2818             // If the radio shuts off or resets while one of these
2819             // is pending, we need to clean up.
2820 
2821             for (int i = mPendingMMIs.size() - 1; i >= 0; i--) {
2822                 if (((GsmMmiCode) mPendingMMIs.get(i)).isPendingUSSD()) {
2823                     ((GsmMmiCode) mPendingMMIs.get(i)).onUssdFinishedError();
2824                 }
2825             }
2826         }
2827         mRadioOffOrNotAvailableRegistrants.notifyRegistrants();
2828     }
2829 
handleRadioPowerStateChange()2830     private void handleRadioPowerStateChange() {
2831         @RadioPowerState int newState = mCi.getRadioState();
2832         Rlog.d(LOG_TAG, "handleRadioPowerStateChange, state= " + newState);
2833         mNotifier.notifyRadioPowerStateChanged(this, newState);
2834         TelephonyMetrics.getInstance().writeRadioState(mPhoneId, newState);
2835     }
2836 
2837     @Override
handleMessage(Message msg)2838     public void handleMessage(Message msg) {
2839         AsyncResult ar;
2840         Message onComplete;
2841 
2842         switch (msg.what) {
2843             case EVENT_RADIO_AVAILABLE: {
2844                 handleRadioAvailable();
2845             }
2846             break;
2847 
2848             case EVENT_GET_DEVICE_IDENTITY_DONE:{
2849                 ar = (AsyncResult)msg.obj;
2850 
2851                 if (ar.exception != null) {
2852                     break;
2853                 }
2854                 String[] respId = (String[])ar.result;
2855                 mImei = respId[0];
2856                 mImeiSv = respId[1];
2857                 mEsn  =  respId[2];
2858                 mMeid =  respId[3];
2859                 // some modems return all 0's instead of null/empty string when MEID is unavailable
2860                 if (!TextUtils.isEmpty(mMeid) && mMeid.matches("^0*$")) {
2861                     logd("EVENT_GET_DEVICE_IDENTITY_DONE: set mMeid to null");
2862                     mMeid = null;
2863                 }
2864             }
2865             break;
2866 
2867             case EVENT_EMERGENCY_CALLBACK_MODE_ENTER:{
2868                 handleEnterEmergencyCallbackMode(msg);
2869             }
2870             break;
2871 
2872             case  EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE:{
2873                 handleExitEmergencyCallbackMode(msg);
2874             }
2875             break;
2876 
2877             case EVENT_MODEM_RESET: {
2878                 logd("Event EVENT_MODEM_RESET Received" + " isInEcm = " + isInEcm()
2879                         + " isPhoneTypeGsm = " + isPhoneTypeGsm() + " mImsPhone = " + mImsPhone);
2880                 if (isInEcm()) {
2881                     if (isPhoneTypeGsm()) {
2882                         if (mImsPhone != null) {
2883                             mImsPhone.handleExitEmergencyCallbackMode();
2884                         }
2885                     } else {
2886                         handleExitEmergencyCallbackMode(msg);
2887                     }
2888                 }
2889             }
2890             break;
2891 
2892             case EVENT_RUIM_RECORDS_LOADED:
2893                 logd("Event EVENT_RUIM_RECORDS_LOADED Received");
2894                 updateCurrentCarrierInProvider();
2895                 break;
2896 
2897             case EVENT_RADIO_ON:
2898                 logd("Event EVENT_RADIO_ON Received");
2899                 handleRadioOn();
2900                 break;
2901 
2902             case EVENT_RIL_CONNECTED:
2903                 ar = (AsyncResult) msg.obj;
2904                 if (ar.exception == null && ar.result != null) {
2905                     mRilVersion = (Integer) ar.result;
2906                 } else {
2907                     logd("Unexpected exception on EVENT_RIL_CONNECTED");
2908                     mRilVersion = -1;
2909                 }
2910                 break;
2911 
2912             case EVENT_VOICE_RADIO_TECH_CHANGED:
2913             case EVENT_REQUEST_VOICE_RADIO_TECH_DONE:
2914                 String what = (msg.what == EVENT_VOICE_RADIO_TECH_CHANGED) ?
2915                         "EVENT_VOICE_RADIO_TECH_CHANGED" : "EVENT_REQUEST_VOICE_RADIO_TECH_DONE";
2916                 ar = (AsyncResult) msg.obj;
2917                 if (ar.exception == null) {
2918                     if ((ar.result != null) && (((int[]) ar.result).length != 0)) {
2919                         int newVoiceTech = ((int[]) ar.result)[0];
2920                         logd(what + ": newVoiceTech=" + newVoiceTech);
2921                         phoneObjectUpdater(newVoiceTech);
2922                     } else {
2923                         loge(what + ": has no tech!");
2924                     }
2925                 } else {
2926                     loge(what + ": exception=" + ar.exception);
2927                 }
2928                 break;
2929 
2930             case EVENT_LINK_CAPACITY_CHANGED:
2931                 ar = (AsyncResult) msg.obj;
2932                 if (ar.exception == null && ar.result != null) {
2933                     updateLinkCapacityEstimate((List<LinkCapacityEstimate>) ar.result);
2934                 } else {
2935                     logd("Unexpected exception on EVENT_LINK_CAPACITY_CHANGED");
2936                 }
2937                 break;
2938 
2939             case EVENT_UPDATE_PHONE_OBJECT:
2940                 phoneObjectUpdater(msg.arg1);
2941                 break;
2942 
2943             case EVENT_CARRIER_CONFIG_CHANGED:
2944                 // Only check for the voice radio tech if it not going to be updated by the voice
2945                 // registration changes.
2946                 if (!mContext.getResources().getBoolean(
2947                         com.android.internal.R.bool
2948                                 .config_switch_phone_on_voice_reg_state_change)) {
2949                     mCi.getVoiceRadioTechnology(obtainMessage(EVENT_REQUEST_VOICE_RADIO_TECH_DONE));
2950                 }
2951 
2952                 CarrierConfigManager configMgr = (CarrierConfigManager)
2953                         getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
2954                 PersistableBundle b = configMgr.getConfigForSubId(getSubId());
2955 
2956                 updateBroadcastEmergencyCallStateChangesAfterCarrierConfigChanged(b);
2957 
2958                 updateCdmaRoamingSettingsAfterCarrierConfigChanged(b);
2959 
2960                 updateNrSettingsAfterCarrierConfigChanged(b);
2961                 updateSsOverCdmaSupported(b);
2962                 loadAllowedNetworksFromSubscriptionDatabase();
2963                 // Obtain new radio capabilities from the modem, since some are SIM-dependent
2964                 mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY));
2965                 break;
2966 
2967             case EVENT_SET_ROAMING_PREFERENCE_DONE:
2968                 logd("cdma_roaming_mode change is done");
2969                 break;
2970 
2971             case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:
2972                 logd("EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED");
2973                 mCdmaSubscriptionSource = mCdmaSSM.getCdmaSubscriptionSource();
2974                 break;
2975 
2976             case EVENT_REGISTERED_TO_NETWORK:
2977                 logd("Event EVENT_REGISTERED_TO_NETWORK Received");
2978                 if (isPhoneTypeGsm()) {
2979                     syncClirSetting();
2980                 }
2981                 break;
2982 
2983             case EVENT_SIM_RECORDS_LOADED:
2984                 updateCurrentCarrierInProvider();
2985 
2986                 // Check if this is a different SIM than the previous one. If so unset the
2987                 // voice mail number.
2988                 String imsi = getVmSimImsi();
2989                 String imsiFromSIM = getSubscriberId();
2990                 if ((!isPhoneTypeGsm() || imsi != null) && imsiFromSIM != null
2991                         && !imsiFromSIM.equals(imsi)) {
2992                     storeVoiceMailNumber(null);
2993                     setVmSimImsi(null);
2994                 }
2995 
2996                 updateVoiceMail();
2997 
2998                 mSimRecordsLoadedRegistrants.notifyRegistrants();
2999                 break;
3000 
3001             case EVENT_GET_BASEBAND_VERSION_DONE:
3002                 ar = (AsyncResult)msg.obj;
3003 
3004                 if (ar.exception != null) {
3005                     break;
3006                 }
3007 
3008                 if (DBG) logd("Baseband version: " + ar.result);
3009                 /* Android property value is limited to 91 characters, but low layer
3010                  could pass a larger version string. To avoid runtime exception,
3011                  truncate the string baseband version string to 45 characters at most
3012                  for this per sub property. Since the latter part of the version string
3013                  is meaningful, truncated the version string from the beginning and
3014                  keep the end of the version.
3015                 */
3016                 String version = (String)ar.result;
3017                 if (version != null) {
3018                     int length = version.length();
3019                     final int MAX_VERSION_LEN = SystemProperties.PROP_VALUE_MAX/2;
3020                     TelephonyManager.from(mContext).setBasebandVersionForPhone(getPhoneId(),
3021                             length <= MAX_VERSION_LEN ? version
3022                                 : version.substring(length - MAX_VERSION_LEN, length));
3023                 }
3024             break;
3025 
3026             case EVENT_GET_IMEI_DONE:
3027                 ar = (AsyncResult)msg.obj;
3028 
3029                 if (ar.exception != null) {
3030                     break;
3031                 }
3032 
3033                 mImei = (String)ar.result;
3034             break;
3035 
3036             case EVENT_GET_IMEISV_DONE:
3037                 ar = (AsyncResult)msg.obj;
3038 
3039                 if (ar.exception != null) {
3040                     break;
3041                 }
3042 
3043                 mImeiSv = (String)ar.result;
3044             break;
3045 
3046             case EVENT_USSD:
3047                 ar = (AsyncResult)msg.obj;
3048 
3049                 String[] ussdResult = (String[]) ar.result;
3050 
3051                 if (ussdResult.length > 1) {
3052                     try {
3053                         onIncomingUSSD(Integer.parseInt(ussdResult[0]), ussdResult[1]);
3054                     } catch (NumberFormatException e) {
3055                         Rlog.w(LOG_TAG, "error parsing USSD");
3056                     }
3057                 }
3058             break;
3059 
3060             case EVENT_RADIO_OFF_OR_NOT_AVAILABLE: {
3061                 logd("Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received");
3062                 handleRadioOffOrNotAvailable();
3063                 break;
3064             }
3065 
3066             case EVENT_RADIO_STATE_CHANGED: {
3067                 logd("EVENT EVENT_RADIO_STATE_CHANGED");
3068                 handleRadioPowerStateChange();
3069                 break;
3070             }
3071 
3072             case EVENT_SSN:
3073                 logd("Event EVENT_SSN Received");
3074                 if (isPhoneTypeGsm()) {
3075                     ar = (AsyncResult) msg.obj;
3076                     SuppServiceNotification not = (SuppServiceNotification) ar.result;
3077                     mSsnRegistrants.notifyRegistrants(ar);
3078                 }
3079                 break;
3080 
3081             case EVENT_REGISTRATION_FAILED:
3082                 logd("Event RegistrationFailed Received");
3083                 ar = (AsyncResult) msg.obj;
3084                 RegistrationFailedEvent rfe = (RegistrationFailedEvent) ar.result;
3085                 mNotifier.notifyRegistrationFailed(this, rfe.cellIdentity, rfe.chosenPlmn,
3086                         rfe.domain, rfe.causeCode, rfe.additionalCauseCode);
3087                 break;
3088 
3089             case EVENT_BARRING_INFO_CHANGED:
3090                 logd("Event BarringInfoChanged Received");
3091                 ar = (AsyncResult) msg.obj;
3092                 BarringInfo barringInfo = (BarringInfo) ar.result;
3093                 mNotifier.notifyBarringInfoChanged(this, barringInfo);
3094                 break;
3095 
3096             case EVENT_SET_CALL_FORWARD_DONE:
3097                 ar = (AsyncResult)msg.obj;
3098                 Cfu cfu = (Cfu) ar.userObj;
3099                 if (ar.exception == null) {
3100                     setVoiceCallForwardingFlag(1, msg.arg1 == 1, cfu.mSetCfNumber);
3101                 }
3102                 if (cfu.mOnComplete != null) {
3103                     AsyncResult.forMessage(cfu.mOnComplete, ar.result, ar.exception);
3104                     cfu.mOnComplete.sendToTarget();
3105                 }
3106                 break;
3107 
3108             case EVENT_SET_VM_NUMBER_DONE:
3109                 ar = (AsyncResult)msg.obj;
3110                 if (((isPhoneTypeGsm() || mSimRecords != null)
3111                         && IccVmNotSupportedException.class.isInstance(ar.exception))
3112                         || (!isPhoneTypeGsm() && mSimRecords == null
3113                         && IccException.class.isInstance(ar.exception))) {
3114                     storeVoiceMailNumber(mVmNumber);
3115                     ar.exception = null;
3116                 }
3117                 onComplete = (Message) ar.userObj;
3118                 if (onComplete != null) {
3119                     AsyncResult.forMessage(onComplete, ar.result, ar.exception);
3120                     onComplete.sendToTarget();
3121                 }
3122                 break;
3123 
3124 
3125             case EVENT_GET_CALL_FORWARD_DONE:
3126                 ar = (AsyncResult)msg.obj;
3127                 if (ar.exception == null) {
3128                     handleCfuQueryResult((CallForwardInfo[])ar.result);
3129                 }
3130                 onComplete = (Message) ar.userObj;
3131                 if (onComplete != null) {
3132                     AsyncResult.forMessage(onComplete, ar.result, ar.exception);
3133                     onComplete.sendToTarget();
3134                 }
3135                 break;
3136 
3137             case EVENT_SET_NETWORK_AUTOMATIC:
3138                 // Automatic network selection from EF_CSP SIM record
3139                 ar = (AsyncResult) msg.obj;
3140                 if (mSST.mSS.getIsManualSelection()) {
3141                     setNetworkSelectionModeAutomatic((Message) ar.result);
3142                     logd("SET_NETWORK_SELECTION_AUTOMATIC: set to automatic");
3143                 } else {
3144                     // prevent duplicate request which will push current PLMN to low priority
3145                     logd("SET_NETWORK_SELECTION_AUTOMATIC: already automatic, ignore");
3146                 }
3147                 break;
3148 
3149             case EVENT_ICC_RECORD_EVENTS:
3150                 ar = (AsyncResult)msg.obj;
3151                 processIccRecordEvents((Integer)ar.result);
3152                 break;
3153 
3154             case EVENT_SET_CLIR_COMPLETE:
3155                 ar = (AsyncResult)msg.obj;
3156                 if (ar.exception == null) {
3157                     saveClirSetting(msg.arg1);
3158                 }
3159                 onComplete = (Message) ar.userObj;
3160                 if (onComplete != null) {
3161                     AsyncResult.forMessage(onComplete, ar.result, ar.exception);
3162                     onComplete.sendToTarget();
3163                 }
3164                 break;
3165 
3166             case EVENT_SS:
3167                 ar = (AsyncResult)msg.obj;
3168                 logd("Event EVENT_SS received");
3169                 if (isPhoneTypeGsm()) {
3170                     // SS data is already being handled through MMI codes.
3171                     // So, this result if processed as MMI response would help
3172                     // in re-using the existing functionality.
3173                     GsmMmiCode mmi = new GsmMmiCode(this, mUiccApplication.get());
3174                     mmi.processSsData(ar);
3175                 }
3176                 break;
3177 
3178             case EVENT_GET_RADIO_CAPABILITY:
3179                 ar = (AsyncResult) msg.obj;
3180                 RadioCapability rc = (RadioCapability) ar.result;
3181                 if (ar.exception != null) {
3182                     Rlog.d(LOG_TAG, "get phone radio capability fail, no need to change " +
3183                             "mRadioCapability");
3184                 } else {
3185                     radioCapabilityUpdated(rc, false);
3186                 }
3187                 Rlog.d(LOG_TAG, "EVENT_GET_RADIO_CAPABILITY: phone rc: " + rc);
3188                 break;
3189             case EVENT_VRS_OR_RAT_CHANGED:
3190                 ar = (AsyncResult) msg.obj;
3191                 Pair<Integer, Integer> vrsRatPair = (Pair<Integer, Integer>) ar.result;
3192                 onVoiceRegStateOrRatChanged(vrsRatPair.first, vrsRatPair.second);
3193                 break;
3194 
3195             case EVENT_SET_CARRIER_DATA_ENABLED:
3196                 ar = (AsyncResult) msg.obj;
3197                 boolean enabled = (boolean) ar.result;
3198                 mDataEnabledSettings.setDataEnabled(TelephonyManager.DATA_ENABLED_REASON_CARRIER,
3199                         enabled);
3200                 break;
3201             case EVENT_DEVICE_PROVISIONED_CHANGE:
3202                 mDataEnabledSettings.updateProvisionedChanged();
3203                 break;
3204             case EVENT_DEVICE_PROVISIONING_DATA_SETTING_CHANGE:
3205                 mDataEnabledSettings.updateProvisioningDataEnabled();
3206                 break;
3207             case EVENT_GET_AVAILABLE_NETWORKS_DONE:
3208                 ar = (AsyncResult) msg.obj;
3209                 if (ar.exception == null && ar.result != null && mSST != null) {
3210                     List<OperatorInfo> operatorInfoList = (List<OperatorInfo>) ar.result;
3211                     List<OperatorInfo> filteredInfoList = new ArrayList<>();
3212                     for (OperatorInfo operatorInfo : operatorInfoList) {
3213                         if (OperatorInfo.State.CURRENT == operatorInfo.getState()) {
3214                             filteredInfoList.add(new OperatorInfo(
3215                                     mSST.filterOperatorNameByPattern(
3216                                             operatorInfo.getOperatorAlphaLong()),
3217                                     mSST.filterOperatorNameByPattern(
3218                                             operatorInfo.getOperatorAlphaShort()),
3219                                     operatorInfo.getOperatorNumeric(),
3220                                     operatorInfo.getState()
3221                             ));
3222                         } else {
3223                             filteredInfoList.add(operatorInfo);
3224                         }
3225                     }
3226                     ar.result = filteredInfoList;
3227                 }
3228 
3229                 onComplete = (Message) ar.userObj;
3230                 if (onComplete != null) {
3231                     AsyncResult.forMessage(onComplete, ar.result, ar.exception);
3232                     onComplete.sendToTarget();
3233                 }
3234                 break;
3235             case EVENT_GET_UICC_APPS_ENABLEMENT_DONE:
3236             case EVENT_UICC_APPS_ENABLEMENT_STATUS_CHANGED:
3237                 ar = (AsyncResult) msg.obj;
3238                 if (ar == null) return;
3239                 if (ar.exception != null) {
3240                     logd("Received exception on event" + msg.what + " : " + ar.exception);
3241                     return;
3242                 }
3243 
3244                 mUiccApplicationsEnabled = (Boolean) ar.result;
3245             // Intentional falling through.
3246             case EVENT_UICC_APPS_ENABLEMENT_SETTING_CHANGED:
3247                 reapplyUiccAppsEnablementIfNeeded(ENABLE_UICC_APPS_MAX_RETRIES);
3248                 break;
3249 
3250             case EVENT_REAPPLY_UICC_APPS_ENABLEMENT_DONE: {
3251                 ar = (AsyncResult) msg.obj;
3252                 if (ar == null || ar.exception == null) return;
3253                 Pair<Boolean, Integer> userObject = (Pair) ar.userObj;
3254                 if (userObject == null) return;
3255                 boolean expectedValue = userObject.first;
3256                 int retries = userObject.second;
3257                 CommandException.Error error = ((CommandException) ar.exception).getCommandError();
3258                 loge("Error received when re-applying uicc application"
3259                         + " setting to " +  expectedValue + " on phone " + mPhoneId
3260                         + " Error code: " + error + " retry count left: " + retries);
3261                 if (retries > 0 && (error == GENERIC_FAILURE || error == SIM_BUSY)) {
3262                     // Retry for certain errors, but not for others like RADIO_NOT_AVAILABLE or
3263                     // SIM_ABSENT, as they will trigger it whey they become available.
3264                     postDelayed(()->reapplyUiccAppsEnablementIfNeeded(retries - 1),
3265                             REAPPLY_UICC_APPS_SETTING_RETRY_TIME_GAP_IN_MS);
3266                 }
3267                 break;
3268             }
3269             case EVENT_RESET_CARRIER_KEY_IMSI_ENCRYPTION: {
3270                 resetCarrierKeysForImsiEncryption();
3271                 break;
3272             }
3273             default:
3274                 super.handleMessage(msg);
3275         }
3276     }
3277 
getUiccCardApplication()3278     public UiccCardApplication getUiccCardApplication() {
3279         if (isPhoneTypeGsm()) {
3280             return mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP);
3281         } else {
3282             return mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2);
3283         }
3284     }
3285 
3286     // todo: check if ICC availability needs to be handled here. mSimRecords should not be needed
3287     // now because APIs can be called directly on UiccProfile, and that should handle the requests
3288     // correctly based on supported apps, voice RAT, etc.
3289     @Override
onUpdateIccAvailability()3290     protected void onUpdateIccAvailability() {
3291         if (mUiccController == null ) {
3292             return;
3293         }
3294 
3295         UiccCardApplication newUiccApplication = null;
3296 
3297         // Update mIsimUiccRecords
3298         if (isPhoneTypeGsm() || isPhoneTypeCdmaLte()) {
3299             newUiccApplication =
3300                     mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_IMS);
3301             IsimUiccRecords newIsimUiccRecords = null;
3302 
3303             if (newUiccApplication != null) {
3304                 newIsimUiccRecords = (IsimUiccRecords) newUiccApplication.getIccRecords();
3305                 if (DBG) logd("New ISIM application found");
3306             }
3307             mIsimUiccRecords = newIsimUiccRecords;
3308         }
3309 
3310         // Update mSimRecords
3311         if (mSimRecords != null) {
3312             mSimRecords.unregisterForRecordsLoaded(this);
3313         }
3314         if (isPhoneTypeCdmaLte() || isPhoneTypeCdma()) {
3315             newUiccApplication = mUiccController.getUiccCardApplication(mPhoneId,
3316                     UiccController.APP_FAM_3GPP);
3317             SIMRecords newSimRecords = null;
3318             if (newUiccApplication != null) {
3319                 newSimRecords = (SIMRecords) newUiccApplication.getIccRecords();
3320             }
3321             mSimRecords = newSimRecords;
3322             if (mSimRecords != null) {
3323                 mSimRecords.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
3324             }
3325         } else {
3326             mSimRecords = null;
3327         }
3328 
3329         // Update mIccRecords, mUiccApplication, mIccPhoneBookIntManager
3330         newUiccApplication = getUiccCardApplication();
3331         if (!isPhoneTypeGsm() && newUiccApplication == null) {
3332             logd("can't find 3GPP2 application; trying APP_FAM_3GPP");
3333             newUiccApplication = mUiccController.getUiccCardApplication(mPhoneId,
3334                     UiccController.APP_FAM_3GPP);
3335         }
3336 
3337         UiccCardApplication app = mUiccApplication.get();
3338         if (app != newUiccApplication) {
3339             if (app != null) {
3340                 if (DBG) logd("Removing stale icc objects.");
3341                 if (mIccRecords.get() != null) {
3342                     unregisterForIccRecordEvents();
3343                     mIccPhoneBookIntManager.updateIccRecords(null);
3344                 }
3345                 mIccRecords.set(null);
3346                 mUiccApplication.set(null);
3347             }
3348             if (newUiccApplication != null) {
3349                 if (DBG) {
3350                     logd("New Uicc application found. type = " + newUiccApplication.getType());
3351                 }
3352                 final IccRecords iccRecords = newUiccApplication.getIccRecords();
3353                 mUiccApplication.set(newUiccApplication);
3354                 mIccRecords.set(iccRecords);
3355                 registerForIccRecordEvents();
3356                 mIccPhoneBookIntManager.updateIccRecords(iccRecords);
3357                 if (iccRecords != null) {
3358                     final String simOperatorNumeric = iccRecords.getOperatorNumeric();
3359                     if (DBG) {
3360                         logd("New simOperatorNumeric = " + simOperatorNumeric);
3361                     }
3362                     if (!TextUtils.isEmpty(simOperatorNumeric)) {
3363                         TelephonyManager.from(mContext).setSimOperatorNumericForPhone(mPhoneId,
3364                                 simOperatorNumeric);
3365                     }
3366                 }
3367                 updateCurrentCarrierInProvider();
3368             }
3369         }
3370 
3371         reapplyUiccAppsEnablementIfNeeded(ENABLE_UICC_APPS_MAX_RETRIES);
3372     }
3373 
processIccRecordEvents(int eventCode)3374     private void processIccRecordEvents(int eventCode) {
3375         switch (eventCode) {
3376             case IccRecords.EVENT_CFI:
3377                 logi("processIccRecordEvents: EVENT_CFI");
3378                 notifyCallForwardingIndicator();
3379                 break;
3380         }
3381     }
3382 
3383     /**
3384      * Sets the "current" field in the telephony provider according to the SIM's operator
3385      *
3386      * @return true for success; false otherwise.
3387      */
3388     @Override
updateCurrentCarrierInProvider()3389     public boolean updateCurrentCarrierInProvider() {
3390         long currentDds = SubscriptionManager.getDefaultDataSubscriptionId();
3391         String operatorNumeric = getOperatorNumeric();
3392 
3393         logd("updateCurrentCarrierInProvider: mSubId = " + getSubId()
3394                 + " currentDds = " + currentDds + " operatorNumeric = " + operatorNumeric);
3395 
3396         if (!TextUtils.isEmpty(operatorNumeric) && (getSubId() == currentDds)) {
3397             try {
3398                 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
3399                 ContentValues map = new ContentValues();
3400                 map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
3401                 mContext.getContentResolver().insert(uri, map);
3402                 return true;
3403             } catch (SQLException e) {
3404                 Rlog.e(LOG_TAG, "Can't store current operator", e);
3405             }
3406         }
3407         return false;
3408     }
3409 
3410     //CDMA
3411     /**
3412      * Sets the "current" field in the telephony provider according to the
3413      * build-time operator numeric property
3414      *
3415      * @return true for success; false otherwise.
3416      */
updateCurrentCarrierInProvider(String operatorNumeric)3417     private boolean updateCurrentCarrierInProvider(String operatorNumeric) {
3418         if (isPhoneTypeCdma()
3419                 || (isPhoneTypeCdmaLte() && mUiccController.getUiccCardApplication(mPhoneId,
3420                         UiccController.APP_FAM_3GPP) == null)) {
3421             logd("CDMAPhone: updateCurrentCarrierInProvider called");
3422             if (!TextUtils.isEmpty(operatorNumeric)) {
3423                 try {
3424                     Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current");
3425                     ContentValues map = new ContentValues();
3426                     map.put(Telephony.Carriers.NUMERIC, operatorNumeric);
3427                     logd("updateCurrentCarrierInProvider from system: numeric=" + operatorNumeric);
3428                     getContext().getContentResolver().insert(uri, map);
3429 
3430                     // Updates MCC MNC device configuration information
3431                     logd("update mccmnc=" + operatorNumeric);
3432                     MccTable.updateMccMncConfiguration(mContext, operatorNumeric);
3433 
3434                     return true;
3435                 } catch (SQLException e) {
3436                     Rlog.e(LOG_TAG, "Can't store current operator", e);
3437                 }
3438             }
3439             return false;
3440         } else { // isPhoneTypeCdmaLte()
3441             if (DBG) logd("updateCurrentCarrierInProvider not updated X retVal=" + true);
3442             return true;
3443         }
3444     }
3445 
handleCfuQueryResult(CallForwardInfo[] infos)3446     private void handleCfuQueryResult(CallForwardInfo[] infos) {
3447         if (infos == null || infos.length == 0) {
3448             // Assume the default is not active
3449             // Set unconditional CFF in SIM to false
3450             setVoiceCallForwardingFlag(1, false, null);
3451         } else {
3452             for (int i = 0, s = infos.length; i < s; i++) {
3453                 if ((infos[i].serviceClass & SERVICE_CLASS_VOICE) != 0) {
3454                     setVoiceCallForwardingFlag(1, (infos[i].status == 1),
3455                         infos[i].number);
3456                     // should only have the one
3457                     break;
3458                 }
3459             }
3460         }
3461     }
3462 
3463     /**
3464      * Retrieves the IccPhoneBookInterfaceManager of the GsmCdmaPhone
3465      */
3466     @Override
getIccPhoneBookInterfaceManager()3467     public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
3468         return mIccPhoneBookIntManager;
3469     }
3470 
3471     /**
3472      * Activate or deactivate cell broadcast SMS.
3473      *
3474      * @param activate 0 = activate, 1 = deactivate
3475      * @param response Callback message is empty on completion
3476      */
3477     @Override
activateCellBroadcastSms(int activate, Message response)3478     public void activateCellBroadcastSms(int activate, Message response) {
3479         loge("[GsmCdmaPhone] activateCellBroadcastSms() is obsolete; use SmsManager");
3480         response.sendToTarget();
3481     }
3482 
3483     /**
3484      * Query the current configuration of cdma cell broadcast SMS.
3485      *
3486      * @param response Callback message is empty on completion
3487      */
3488     @Override
getCellBroadcastSmsConfig(Message response)3489     public void getCellBroadcastSmsConfig(Message response) {
3490         loge("[GsmCdmaPhone] getCellBroadcastSmsConfig() is obsolete; use SmsManager");
3491         response.sendToTarget();
3492     }
3493 
3494     /**
3495      * Configure cdma cell broadcast SMS.
3496      *
3497      * @param response Callback message is empty on completion
3498      */
3499     @Override
setCellBroadcastSmsConfig(int[] configValuesArray, Message response)3500     public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) {
3501         loge("[GsmCdmaPhone] setCellBroadcastSmsConfig() is obsolete; use SmsManager");
3502         response.sendToTarget();
3503     }
3504 
3505     /**
3506      * Returns true if OTA Service Provisioning needs to be performed.
3507      */
3508     @Override
needsOtaServiceProvisioning()3509     public boolean needsOtaServiceProvisioning() {
3510         if (isPhoneTypeGsm()) {
3511             return false;
3512         } else {
3513             return mSST.getOtasp() != TelephonyManager.OTASP_NOT_NEEDED;
3514         }
3515     }
3516 
3517     @Override
isCspPlmnEnabled()3518     public boolean isCspPlmnEnabled() {
3519         IccRecords r = mIccRecords.get();
3520         return (r != null) ? r.isCspPlmnEnabled() : false;
3521     }
3522 
3523     /**
3524      * Whether manual select is now allowed and we should set
3525      * to auto network select mode.
3526      */
shouldForceAutoNetworkSelect()3527     public boolean shouldForceAutoNetworkSelect() {
3528 
3529         int networkTypeBitmask = RadioAccessFamily.getRafFromNetworkType(
3530                 RILConstants.PREFERRED_NETWORK_MODE);
3531         int subId = getSubId();
3532 
3533         // If it's invalid subId, we shouldn't force to auto network select mode.
3534         if (!SubscriptionManager.isValidSubscriptionId(subId)) {
3535             return false;
3536         }
3537 
3538         networkTypeBitmask = (int) getAllowedNetworkTypes(
3539                 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER);
3540 
3541         logd("shouldForceAutoNetworkSelect in mode = " + networkTypeBitmask);
3542         /*
3543          *  For multimode targets in global mode manual network
3544          *  selection is disallowed. So we should force auto select mode.
3545          */
3546         if (isManualSelProhibitedInGlobalMode()
3547                 && ((networkTypeBitmask == RadioAccessFamily.getRafFromNetworkType(
3548                 TelephonyManager.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA))
3549                 || (networkTypeBitmask == RadioAccessFamily.getRafFromNetworkType(
3550                 TelephonyManager.NETWORK_MODE_GLOBAL)))) {
3551             logd("Should force auto network select mode = " + networkTypeBitmask);
3552             return true;
3553         } else {
3554             logd("Should not force auto network select mode = " + networkTypeBitmask);
3555         }
3556 
3557         /*
3558          *  Single mode phone with - GSM network modes/global mode
3559          *  LTE only for 3GPP
3560          *  LTE centric + 3GPP Legacy
3561          *  Note: the actual enabling/disabling manual selection for these
3562          *  cases will be controlled by csp
3563          */
3564         return false;
3565     }
3566 
3567     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isManualSelProhibitedInGlobalMode()3568     private boolean isManualSelProhibitedInGlobalMode() {
3569         boolean isProhibited = false;
3570         final String configString = getContext().getResources().getString(com.android.internal
3571                 .R.string.prohibit_manual_network_selection_in_gobal_mode);
3572 
3573         if (!TextUtils.isEmpty(configString)) {
3574             String[] configArray = configString.split(";");
3575 
3576             if (configArray != null &&
3577                     ((configArray.length == 1 && configArray[0].equalsIgnoreCase("true")) ||
3578                         (configArray.length == 2 && !TextUtils.isEmpty(configArray[1]) &&
3579                             configArray[0].equalsIgnoreCase("true") &&
3580                             isMatchGid(configArray[1])))) {
3581                             isProhibited = true;
3582             }
3583         }
3584         logd("isManualNetSelAllowedInGlobal in current carrier is " + isProhibited);
3585         return isProhibited;
3586     }
3587 
registerForIccRecordEvents()3588     private void registerForIccRecordEvents() {
3589         IccRecords r = mIccRecords.get();
3590         if (r == null) {
3591             return;
3592         }
3593         if (isPhoneTypeGsm()) {
3594             r.registerForNetworkSelectionModeAutomatic(
3595                     this, EVENT_SET_NETWORK_AUTOMATIC, null);
3596             r.registerForRecordsEvents(this, EVENT_ICC_RECORD_EVENTS, null);
3597             r.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
3598         } else {
3599             r.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null);
3600             if (isPhoneTypeCdmaLte()) {
3601                 // notify simRecordsLoaded registrants for cdmaLte phone
3602                 r.registerForRecordsLoaded(this, EVENT_SIM_RECORDS_LOADED, null);
3603             }
3604         }
3605     }
3606 
unregisterForIccRecordEvents()3607     private void unregisterForIccRecordEvents() {
3608         IccRecords r = mIccRecords.get();
3609         if (r == null) {
3610             return;
3611         }
3612         r.unregisterForNetworkSelectionModeAutomatic(this);
3613         r.unregisterForRecordsEvents(this);
3614         r.unregisterForRecordsLoaded(this);
3615     }
3616 
3617     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
3618     @Override
exitEmergencyCallbackMode()3619     public void exitEmergencyCallbackMode() {
3620         if (DBG) {
3621             Rlog.d(LOG_TAG, "exitEmergencyCallbackMode: mImsPhone=" + mImsPhone
3622                     + " isPhoneTypeGsm=" + isPhoneTypeGsm());
3623         }
3624         if (mImsPhone != null && mImsPhone.isInImsEcm()) {
3625             mImsPhone.exitEmergencyCallbackMode();
3626         } else {
3627             if (mWakeLock.isHeld()) {
3628                 mWakeLock.release();
3629             }
3630             Message msg = null;
3631             if (mIsTestingEmergencyCallbackMode) {
3632                 // prevent duplicate exit messages from happening due to this message being handled
3633                 // as well as an UNSOL when the modem exits ECbM. Instead, only register for this
3634                 // message callback when this is a test and we will not be receiving the UNSOL from
3635                 // the modem.
3636                 msg = obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE);
3637             }
3638             mCi.exitEmergencyCallbackMode(msg);
3639         }
3640     }
3641 
3642     //CDMA
handleEnterEmergencyCallbackMode(Message msg)3643     private void handleEnterEmergencyCallbackMode(Message msg) {
3644         if (DBG) {
3645             Rlog.d(LOG_TAG, "handleEnterEmergencyCallbackMode, isInEcm()="
3646                     + isInEcm());
3647         }
3648         // if phone is not in Ecm mode, and it's changed to Ecm mode
3649         if (!isInEcm()) {
3650             setIsInEcm(true);
3651 
3652             // notify change
3653             sendEmergencyCallbackModeChange();
3654 
3655             // Post this runnable so we will automatically exit
3656             // if no one invokes exitEmergencyCallbackMode() directly.
3657             long delayInMillis = TelephonyProperties.ecm_exit_timer()
3658                     .orElse(DEFAULT_ECM_EXIT_TIMER_VALUE);
3659             postDelayed(mExitEcmRunnable, delayInMillis);
3660             // We don't want to go to sleep while in Ecm
3661             mWakeLock.acquire();
3662         }
3663     }
3664 
3665     //CDMA
handleExitEmergencyCallbackMode(Message msg)3666     private void handleExitEmergencyCallbackMode(Message msg) {
3667         AsyncResult ar = (AsyncResult)msg.obj;
3668         if (DBG) {
3669             Rlog.d(LOG_TAG, "handleExitEmergencyCallbackMode,ar.exception , isInEcm="
3670                     + ar.exception + isInEcm());
3671         }
3672         // Remove pending exit Ecm runnable, if any
3673         removeCallbacks(mExitEcmRunnable);
3674 
3675         if (mEcmExitRespRegistrant != null) {
3676             mEcmExitRespRegistrant.notifyRegistrant(ar);
3677         }
3678         // if exiting is successful or we are testing and the modem responded with an error upon
3679         // exit, which may occur in some IRadio implementations.
3680         if (ar.exception == null || mIsTestingEmergencyCallbackMode) {
3681             if (isInEcm()) {
3682                 setIsInEcm(false);
3683             }
3684 
3685             // release wakeLock
3686             if (mWakeLock.isHeld()) {
3687                 mWakeLock.release();
3688             }
3689 
3690             // send an Intent
3691             sendEmergencyCallbackModeChange();
3692             // Re-initiate data connection
3693             mDataEnabledSettings.setInternalDataEnabled(true);
3694             notifyEmergencyCallRegistrants(false);
3695         }
3696         mIsTestingEmergencyCallbackMode = false;
3697     }
3698 
3699     //CDMA
notifyEmergencyCallRegistrants(boolean started)3700     public void notifyEmergencyCallRegistrants(boolean started) {
3701         mEmergencyCallToggledRegistrants.notifyResult(started ? 1 : 0);
3702     }
3703 
3704     //CDMA
3705     /**
3706      * Handle to cancel or restart Ecm timer in emergency call back mode
3707      * if action is CANCEL_ECM_TIMER, cancel Ecm timer and notify apps the timer is canceled;
3708      * otherwise, restart Ecm timer and notify apps the timer is restarted.
3709      */
handleTimerInEmergencyCallbackMode(int action)3710     public void handleTimerInEmergencyCallbackMode(int action) {
3711         switch(action) {
3712             case CANCEL_ECM_TIMER:
3713                 removeCallbacks(mExitEcmRunnable);
3714                 mEcmTimerResetRegistrants.notifyResult(Boolean.TRUE);
3715                 setEcmCanceledForEmergency(true /*isCanceled*/);
3716                 break;
3717             case RESTART_ECM_TIMER:
3718                 long delayInMillis = TelephonyProperties.ecm_exit_timer()
3719                         .orElse(DEFAULT_ECM_EXIT_TIMER_VALUE);
3720                 postDelayed(mExitEcmRunnable, delayInMillis);
3721                 mEcmTimerResetRegistrants.notifyResult(Boolean.FALSE);
3722                 setEcmCanceledForEmergency(false /*isCanceled*/);
3723                 break;
3724             default:
3725                 Rlog.e(LOG_TAG, "handleTimerInEmergencyCallbackMode, unsupported action " + action);
3726         }
3727     }
3728 
3729     //CDMA
3730     private static final String IS683A_FEATURE_CODE = "*228";
3731     private static final int IS683A_FEATURE_CODE_NUM_DIGITS = 4;
3732     private static final int IS683A_SYS_SEL_CODE_NUM_DIGITS = 2;
3733     private static final int IS683A_SYS_SEL_CODE_OFFSET = 4;
3734 
3735     private static final int IS683_CONST_800MHZ_A_BAND = 0;
3736     private static final int IS683_CONST_800MHZ_B_BAND = 1;
3737     private static final int IS683_CONST_1900MHZ_A_BLOCK = 2;
3738     private static final int IS683_CONST_1900MHZ_B_BLOCK = 3;
3739     private static final int IS683_CONST_1900MHZ_C_BLOCK = 4;
3740     private static final int IS683_CONST_1900MHZ_D_BLOCK = 5;
3741     private static final int IS683_CONST_1900MHZ_E_BLOCK = 6;
3742     private static final int IS683_CONST_1900MHZ_F_BLOCK = 7;
3743     private static final int INVALID_SYSTEM_SELECTION_CODE = -1;
3744 
3745     // Define the pattern/format for carrier specified OTASP number schema.
3746     // It separates by comma and/or whitespace.
3747     private static Pattern pOtaSpNumSchema = Pattern.compile("[,\\s]+");
3748 
3749     //CDMA
isIs683OtaSpDialStr(String dialStr)3750     private static boolean isIs683OtaSpDialStr(String dialStr) {
3751         int sysSelCodeInt;
3752         boolean isOtaspDialString = false;
3753         int dialStrLen = dialStr.length();
3754 
3755         if (dialStrLen == IS683A_FEATURE_CODE_NUM_DIGITS) {
3756             if (dialStr.equals(IS683A_FEATURE_CODE)) {
3757                 isOtaspDialString = true;
3758             }
3759         } else {
3760             sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr);
3761             switch (sysSelCodeInt) {
3762                 case IS683_CONST_800MHZ_A_BAND:
3763                 case IS683_CONST_800MHZ_B_BAND:
3764                 case IS683_CONST_1900MHZ_A_BLOCK:
3765                 case IS683_CONST_1900MHZ_B_BLOCK:
3766                 case IS683_CONST_1900MHZ_C_BLOCK:
3767                 case IS683_CONST_1900MHZ_D_BLOCK:
3768                 case IS683_CONST_1900MHZ_E_BLOCK:
3769                 case IS683_CONST_1900MHZ_F_BLOCK:
3770                     isOtaspDialString = true;
3771                     break;
3772                 default:
3773                     break;
3774             }
3775         }
3776         return isOtaspDialString;
3777     }
3778 
3779     //CDMA
3780     /**
3781      * This function extracts the system selection code from the dial string.
3782      */
extractSelCodeFromOtaSpNum(String dialStr)3783     private static int extractSelCodeFromOtaSpNum(String dialStr) {
3784         int dialStrLen = dialStr.length();
3785         int sysSelCodeInt = INVALID_SYSTEM_SELECTION_CODE;
3786 
3787         if ((dialStr.regionMatches(0, IS683A_FEATURE_CODE,
3788                 0, IS683A_FEATURE_CODE_NUM_DIGITS)) &&
3789                 (dialStrLen >= (IS683A_FEATURE_CODE_NUM_DIGITS +
3790                         IS683A_SYS_SEL_CODE_NUM_DIGITS))) {
3791             // Since we checked the condition above, the system selection code
3792             // extracted from dialStr will not cause any exception
3793             sysSelCodeInt = Integer.parseInt (
3794                     dialStr.substring (IS683A_FEATURE_CODE_NUM_DIGITS,
3795                             IS683A_FEATURE_CODE_NUM_DIGITS + IS683A_SYS_SEL_CODE_NUM_DIGITS));
3796         }
3797         if (DBG) Rlog.d(LOG_TAG, "extractSelCodeFromOtaSpNum " + sysSelCodeInt);
3798         return sysSelCodeInt;
3799     }
3800 
3801     //CDMA
3802     /**
3803      * This function checks if the system selection code extracted from
3804      * the dial string "sysSelCodeInt' is the system selection code specified
3805      * in the carrier ota sp number schema "sch".
3806      */
checkOtaSpNumBasedOnSysSelCode(int sysSelCodeInt, String sch[])3807     private static boolean checkOtaSpNumBasedOnSysSelCode(int sysSelCodeInt, String sch[]) {
3808         boolean isOtaSpNum = false;
3809         try {
3810             // Get how many number of system selection code ranges
3811             int selRc = Integer.parseInt(sch[1]);
3812             for (int i = 0; i < selRc; i++) {
3813                 if (!TextUtils.isEmpty(sch[i*2+2]) && !TextUtils.isEmpty(sch[i*2+3])) {
3814                     int selMin = Integer.parseInt(sch[i*2+2]);
3815                     int selMax = Integer.parseInt(sch[i*2+3]);
3816                     // Check if the selection code extracted from the dial string falls
3817                     // within any of the range pairs specified in the schema.
3818                     if ((sysSelCodeInt >= selMin) && (sysSelCodeInt <= selMax)) {
3819                         isOtaSpNum = true;
3820                         break;
3821                     }
3822                 }
3823             }
3824         } catch (NumberFormatException ex) {
3825             // If the carrier ota sp number schema is not correct, we still allow dial
3826             // and only log the error:
3827             Rlog.e(LOG_TAG, "checkOtaSpNumBasedOnSysSelCode, error", ex);
3828         }
3829         return isOtaSpNum;
3830     }
3831 
3832     //CDMA
3833     /**
3834      * The following function checks if a dial string is a carrier specified
3835      * OTASP number or not by checking against the OTASP number schema stored
3836      * in PROPERTY_OTASP_NUM_SCHEMA.
3837      *
3838      * Currently, there are 2 schemas for carriers to specify the OTASP number:
3839      * 1) Use system selection code:
3840      *    The schema is:
3841      *    SELC,the # of code pairs,min1,max1,min2,max2,...
3842      *    e.g "SELC,3,10,20,30,40,60,70" indicates that there are 3 pairs of
3843      *    selection codes, and they are {10,20}, {30,40} and {60,70} respectively.
3844      *
3845      * 2) Use feature code:
3846      *    The schema is:
3847      *    "FC,length of feature code,feature code".
3848      *     e.g "FC,2,*2" indicates that the length of the feature code is 2,
3849      *     and the code itself is "*2".
3850      */
isCarrierOtaSpNum(String dialStr)3851     private boolean isCarrierOtaSpNum(String dialStr) {
3852         boolean isOtaSpNum = false;
3853         int sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr);
3854         if (sysSelCodeInt == INVALID_SYSTEM_SELECTION_CODE) {
3855             return isOtaSpNum;
3856         }
3857         // mCarrierOtaSpNumSchema is retrieved from PROPERTY_OTASP_NUM_SCHEMA:
3858         if (!TextUtils.isEmpty(mCarrierOtaSpNumSchema)) {
3859             Matcher m = pOtaSpNumSchema.matcher(mCarrierOtaSpNumSchema);
3860             if (DBG) {
3861                 Rlog.d(LOG_TAG, "isCarrierOtaSpNum,schema" + mCarrierOtaSpNumSchema);
3862             }
3863 
3864             if (m.find()) {
3865                 String sch[] = pOtaSpNumSchema.split(mCarrierOtaSpNumSchema);
3866                 // If carrier uses system selection code mechanism
3867                 if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("SELC")) {
3868                     if (sysSelCodeInt!=INVALID_SYSTEM_SELECTION_CODE) {
3869                         isOtaSpNum=checkOtaSpNumBasedOnSysSelCode(sysSelCodeInt,sch);
3870                     } else {
3871                         if (DBG) {
3872                             Rlog.d(LOG_TAG, "isCarrierOtaSpNum,sysSelCodeInt is invalid");
3873                         }
3874                     }
3875                 } else if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("FC")) {
3876                     int fcLen =  Integer.parseInt(sch[1]);
3877                     String fc = sch[2];
3878                     if (dialStr.regionMatches(0,fc,0,fcLen)) {
3879                         isOtaSpNum = true;
3880                     } else {
3881                         if (DBG) Rlog.d(LOG_TAG, "isCarrierOtaSpNum,not otasp number");
3882                     }
3883                 } else {
3884                     if (DBG) {
3885                         Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema not supported" + sch[0]);
3886                     }
3887                 }
3888             } else {
3889                 if (DBG) {
3890                     Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern not right" +
3891                             mCarrierOtaSpNumSchema);
3892                 }
3893             }
3894         } else {
3895             if (DBG) Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern empty");
3896         }
3897         return isOtaSpNum;
3898     }
3899 
3900     /**
3901      * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier
3902      * OTASP dial string.
3903      *
3904      * @param dialStr the number to look up.
3905      * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string
3906      */
3907     @Override
isOtaSpNumber(String dialStr)3908     public  boolean isOtaSpNumber(String dialStr) {
3909         if (isPhoneTypeGsm()) {
3910             return super.isOtaSpNumber(dialStr);
3911         } else {
3912             boolean isOtaSpNum = false;
3913             String dialableStr = PhoneNumberUtils.extractNetworkPortionAlt(dialStr);
3914             if (dialableStr != null) {
3915                 isOtaSpNum = isIs683OtaSpDialStr(dialableStr);
3916                 if (isOtaSpNum == false) {
3917                     isOtaSpNum = isCarrierOtaSpNum(dialableStr);
3918                 }
3919             }
3920             if (DBG) Rlog.d(LOG_TAG, "isOtaSpNumber " + isOtaSpNum);
3921             return isOtaSpNum;
3922         }
3923     }
3924 
3925     @Override
getOtasp()3926     public int getOtasp() {
3927         return mSST.getOtasp();
3928     }
3929 
3930     @Override
getCdmaEriIconIndex()3931     public int getCdmaEriIconIndex() {
3932         if (isPhoneTypeGsm()) {
3933             return super.getCdmaEriIconIndex();
3934         } else {
3935             return getServiceState().getCdmaEriIconIndex();
3936         }
3937     }
3938 
3939     /**
3940      * Returns the CDMA ERI icon mode,
3941      * 0 - ON
3942      * 1 - FLASHING
3943      */
3944     @Override
getCdmaEriIconMode()3945     public int getCdmaEriIconMode() {
3946         if (isPhoneTypeGsm()) {
3947             return super.getCdmaEriIconMode();
3948         } else {
3949             return getServiceState().getCdmaEriIconMode();
3950         }
3951     }
3952 
3953     /**
3954      * Returns the CDMA ERI text,
3955      */
3956     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
3957     @Override
getCdmaEriText()3958     public String getCdmaEriText() {
3959         if (isPhoneTypeGsm()) {
3960             return super.getCdmaEriText();
3961         } else {
3962             int roamInd = getServiceState().getCdmaRoamingIndicator();
3963             int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator();
3964             return mSST.getCdmaEriText(roamInd, defRoamInd);
3965         }
3966     }
3967 
3968     // Return true if either CSIM or RUIM app is present
3969     @Override
isCdmaSubscriptionAppPresent()3970     public boolean isCdmaSubscriptionAppPresent() {
3971         UiccCardApplication cdmaApplication =
3972                 mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2);
3973         return cdmaApplication != null && (cdmaApplication.getType() == AppType.APPTYPE_CSIM ||
3974                 cdmaApplication.getType() == AppType.APPTYPE_RUIM);
3975     }
3976 
phoneObjectUpdater(int newVoiceRadioTech)3977     protected void phoneObjectUpdater(int newVoiceRadioTech) {
3978         logd("phoneObjectUpdater: newVoiceRadioTech=" + newVoiceRadioTech);
3979 
3980         // Check for a voice over LTE/NR replacement
3981         if (ServiceState.isPsOnlyTech(newVoiceRadioTech)
3982                 || (newVoiceRadioTech == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN)) {
3983             CarrierConfigManager configMgr = (CarrierConfigManager)
3984                     getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
3985             PersistableBundle b = configMgr.getConfigForSubId(getSubId());
3986             if (b != null) {
3987                 int volteReplacementRat =
3988                         b.getInt(CarrierConfigManager.KEY_VOLTE_REPLACEMENT_RAT_INT);
3989                 logd("phoneObjectUpdater: volteReplacementRat=" + volteReplacementRat);
3990                 if (volteReplacementRat != ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN &&
3991                            //In cdma case, replace rat only if csim or ruim app present
3992                            (ServiceState.isGsm(volteReplacementRat) ||
3993                            isCdmaSubscriptionAppPresent())) {
3994                     newVoiceRadioTech = volteReplacementRat;
3995                 }
3996             } else {
3997                 loge("phoneObjectUpdater: didn't get volteReplacementRat from carrier config");
3998             }
3999         }
4000 
4001         if(mRilVersion == 6 && getLteOnCdmaMode() == PhoneConstants.LTE_ON_CDMA_TRUE) {
4002             /*
4003              * On v6 RIL, when LTE_ON_CDMA is TRUE, always create CDMALTEPhone
4004              * irrespective of the voice radio tech reported.
4005              */
4006             if (getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) {
4007                 logd("phoneObjectUpdater: LTE ON CDMA property is set. Use CDMA Phone" +
4008                         " newVoiceRadioTech=" + newVoiceRadioTech +
4009                         " mActivePhone=" + getPhoneName());
4010                 return;
4011             } else {
4012                 logd("phoneObjectUpdater: LTE ON CDMA property is set. Switch to CDMALTEPhone" +
4013                         " newVoiceRadioTech=" + newVoiceRadioTech +
4014                         " mActivePhone=" + getPhoneName());
4015                 newVoiceRadioTech = ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT;
4016             }
4017         } else {
4018 
4019             // If the device is shutting down, then there is no need to switch to the new phone
4020             // which might send unnecessary attach request to the modem.
4021             if (isShuttingDown()) {
4022                 logd("Device is shutting down. No need to switch phone now.");
4023                 return;
4024             }
4025 
4026             boolean matchCdma = ServiceState.isCdma(newVoiceRadioTech);
4027             boolean matchGsm = ServiceState.isGsm(newVoiceRadioTech);
4028             if ((matchCdma && getPhoneType() == PhoneConstants.PHONE_TYPE_CDMA) ||
4029                     (matchGsm && getPhoneType() == PhoneConstants.PHONE_TYPE_GSM)) {
4030                 // Nothing changed. Keep phone as it is.
4031                 logd("phoneObjectUpdater: No change ignore," +
4032                         " newVoiceRadioTech=" + newVoiceRadioTech +
4033                         " mActivePhone=" + getPhoneName());
4034                 return;
4035             }
4036             if (!matchCdma && !matchGsm) {
4037                 loge("phoneObjectUpdater: newVoiceRadioTech=" + newVoiceRadioTech +
4038                         " doesn't match either CDMA or GSM - error! No phone change");
4039                 return;
4040             }
4041         }
4042 
4043         if (newVoiceRadioTech == ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN) {
4044             // We need some voice phone object to be active always, so never
4045             // delete the phone without anything to replace it with!
4046             logd("phoneObjectUpdater: Unknown rat ignore, "
4047                     + " newVoiceRadioTech=Unknown. mActivePhone=" + getPhoneName());
4048             return;
4049         }
4050 
4051         boolean oldPowerState = false; // old power state to off
4052         if (mResetModemOnRadioTechnologyChange) {
4053             if (mCi.getRadioState() == TelephonyManager.RADIO_POWER_ON) {
4054                 oldPowerState = true;
4055                 logd("phoneObjectUpdater: Setting Radio Power to Off");
4056                 mCi.setRadioPower(false, null);
4057             }
4058         }
4059 
4060         switchVoiceRadioTech(newVoiceRadioTech);
4061 
4062         if (mResetModemOnRadioTechnologyChange && oldPowerState) { // restore power state
4063             logd("phoneObjectUpdater: Resetting Radio");
4064             mCi.setRadioPower(oldPowerState, null);
4065         }
4066 
4067         // update voice radio tech in UiccProfile
4068         UiccProfile uiccProfile = getUiccProfile();
4069         if (uiccProfile != null) {
4070             uiccProfile.setVoiceRadioTech(newVoiceRadioTech);
4071         }
4072 
4073         // Send an Intent to the PhoneApp that we had a radio technology change
4074         Intent intent = new Intent(TelephonyIntents.ACTION_RADIO_TECHNOLOGY_CHANGED);
4075         intent.putExtra(PhoneConstants.PHONE_NAME_KEY, getPhoneName());
4076         SubscriptionManager.putPhoneIdAndSubIdExtra(intent, mPhoneId);
4077         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
4078     }
4079 
switchVoiceRadioTech(int newVoiceRadioTech)4080     private void switchVoiceRadioTech(int newVoiceRadioTech) {
4081 
4082         String outgoingPhoneName = getPhoneName();
4083 
4084         logd("Switching Voice Phone : " + outgoingPhoneName + " >>> "
4085                 + (ServiceState.isGsm(newVoiceRadioTech) ? "GSM" : "CDMA"));
4086 
4087         if (ServiceState.isCdma(newVoiceRadioTech)) {
4088             UiccCardApplication cdmaApplication =
4089                     mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2);
4090             if (cdmaApplication != null && cdmaApplication.getType() == AppType.APPTYPE_RUIM) {
4091                 switchPhoneType(PhoneConstants.PHONE_TYPE_CDMA);
4092             } else {
4093                 switchPhoneType(PhoneConstants.PHONE_TYPE_CDMA_LTE);
4094             }
4095         } else if (ServiceState.isGsm(newVoiceRadioTech)) {
4096             switchPhoneType(PhoneConstants.PHONE_TYPE_GSM);
4097         } else {
4098             loge("deleteAndCreatePhone: newVoiceRadioTech=" + newVoiceRadioTech +
4099                     " is not CDMA or GSM (error) - aborting!");
4100             return;
4101         }
4102     }
4103 
4104     @Override
setSignalStrengthReportingCriteria(int signalStrengthMeasure, int[] systemThresholds, int ran, boolean isEnabledForSystem)4105     public void setSignalStrengthReportingCriteria(int signalStrengthMeasure,
4106             int[] systemThresholds, int ran, boolean isEnabledForSystem) {
4107         int[] consolidatedThresholds = mSST.getConsolidatedSignalThresholds(
4108                 ran,
4109                 signalStrengthMeasure,
4110                 isEnabledForSystem && mSST.shouldHonorSystemThresholds() ? systemThresholds
4111                         : new int[]{},
4112                 REPORTING_HYSTERESIS_DB);
4113         boolean isEnabledForAppRequest = mSST.shouldEnableSignalThresholdForAppRequest(
4114                 ran,
4115                 signalStrengthMeasure,
4116                 getSubId(),
4117                 isDeviceIdle());
4118         mCi.setSignalStrengthReportingCriteria(
4119                 new SignalThresholdInfo.Builder()
4120                         .setRadioAccessNetworkType(ran)
4121                         .setSignalMeasurementType(signalStrengthMeasure)
4122                         .setHysteresisMs(REPORTING_HYSTERESIS_MILLIS)
4123                         .setHysteresisDb(REPORTING_HYSTERESIS_DB)
4124                         .setThresholds(consolidatedThresholds, true /*isSystem*/)
4125                         .setIsEnabled(isEnabledForSystem || isEnabledForAppRequest)
4126                         .build(),
4127                 ran, null);
4128     }
4129 
4130     @Override
setLinkCapacityReportingCriteria(int[] dlThresholds, int[] ulThresholds, int ran)4131     public void setLinkCapacityReportingCriteria(int[] dlThresholds, int[] ulThresholds, int ran) {
4132         mCi.setLinkCapacityReportingCriteria(REPORTING_HYSTERESIS_MILLIS, REPORTING_HYSTERESIS_KBPS,
4133                 REPORTING_HYSTERESIS_KBPS, dlThresholds, ulThresholds, ran, null);
4134     }
4135 
4136     @Override
getIccSmsInterfaceManager()4137     public IccSmsInterfaceManager getIccSmsInterfaceManager(){
4138         return mIccSmsInterfaceManager;
4139     }
4140 
4141     @Override
updatePhoneObject(int voiceRadioTech)4142     public void updatePhoneObject(int voiceRadioTech) {
4143         logd("updatePhoneObject: radioTechnology=" + voiceRadioTech);
4144         sendMessage(obtainMessage(EVENT_UPDATE_PHONE_OBJECT, voiceRadioTech, 0, null));
4145     }
4146 
4147     @Override
setImsRegistrationState(boolean registered)4148     public void setImsRegistrationState(boolean registered) {
4149         mSST.setImsRegistrationState(registered);
4150     }
4151 
4152     @Override
getIccRecordsLoaded()4153     public boolean getIccRecordsLoaded() {
4154         UiccProfile uiccProfile = getUiccProfile();
4155         return uiccProfile != null && uiccProfile.getIccRecordsLoaded();
4156     }
4157 
4158     @Override
getIccCard()4159     public IccCard getIccCard() {
4160         // This function doesn't return null for backwards compatability purposes.
4161         // To differentiate between cases where SIM is absent vs. unknown we return a placeholder
4162         // IccCard with the sim state set.
4163         IccCard card = getUiccProfile();
4164         if (card != null) {
4165             return card;
4166         } else {
4167             UiccSlot slot = mUiccController.getUiccSlotForPhone(mPhoneId);
4168             if (slot == null || slot.isStateUnknown()) {
4169                 return new IccCard(IccCardConstants.State.UNKNOWN);
4170             } else {
4171                 return new IccCard(IccCardConstants.State.ABSENT);
4172             }
4173         }
4174     }
4175 
getUiccProfile()4176     private UiccProfile getUiccProfile() {
4177         return UiccController.getInstance().getUiccProfileForPhone(mPhoneId);
4178     }
4179 
4180     @Override
dump(FileDescriptor fd, PrintWriter pw, String[] args)4181     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
4182         pw.println("GsmCdmaPhone extends:");
4183         super.dump(fd, pw, args);
4184         pw.println(" mPrecisePhoneType=" + mPrecisePhoneType);
4185         pw.println(" mCT=" + mCT);
4186         pw.println(" mSST=" + mSST);
4187         pw.println(" mPendingMMIs=" + mPendingMMIs);
4188         pw.println(" mIccPhoneBookIntManager=" + mIccPhoneBookIntManager);
4189         pw.println(" mImei=" + pii(mImei));
4190         pw.println(" mImeiSv=" + pii(mImeiSv));
4191         pw.println(" mVmNumber=" + pii(mVmNumber));
4192         pw.println(" mCdmaSSM=" + mCdmaSSM);
4193         pw.println(" mCdmaSubscriptionSource=" + mCdmaSubscriptionSource);
4194         pw.println(" mWakeLock=" + mWakeLock);
4195         pw.println(" isInEcm()=" + isInEcm());
4196         pw.println(" mEsn=" + pii(mEsn));
4197         pw.println(" mMeid=" + pii(mMeid));
4198         pw.println(" mCarrierOtaSpNumSchema=" + mCarrierOtaSpNumSchema);
4199         if (!isPhoneTypeGsm()) {
4200             pw.println(" getCdmaEriIconIndex()=" + getCdmaEriIconIndex());
4201             pw.println(" getCdmaEriIconMode()=" + getCdmaEriIconMode());
4202             pw.println(" getCdmaEriText()=" + getCdmaEriText());
4203             pw.println(" isMinInfoReady()=" + isMinInfoReady());
4204         }
4205         pw.println(" isCspPlmnEnabled()=" + isCspPlmnEnabled());
4206         pw.println(" mManualNetworkSelectionPlmn=" + mManualNetworkSelectionPlmn);
4207         pw.flush();
4208     }
4209 
4210     @Override
setOperatorBrandOverride(String brand)4211     public boolean setOperatorBrandOverride(String brand) {
4212         if (mUiccController == null) {
4213             return false;
4214         }
4215 
4216         UiccCard card = mUiccController.getUiccCard(getPhoneId());
4217         if (card == null) {
4218             return false;
4219         }
4220 
4221         boolean status = card.setOperatorBrandOverride(brand);
4222 
4223         // Refresh.
4224         if (status) {
4225             TelephonyManager.from(mContext).setSimOperatorNameForPhone(
4226                     getPhoneId(), mSST.getServiceProviderName());
4227             // TODO: check if pollState is need when set operator brand override.
4228             mSST.pollState();
4229         }
4230         return status;
4231     }
4232 
4233     /**
4234      * This allows a short number to be remapped to a test emergency number for testing how the
4235      * frameworks handles Emergency Callback Mode without actually calling an emergency number.
4236      *
4237      * This is not a full test and is not a substitute for testing real emergency
4238      * numbers but can be useful.
4239      *
4240      * To use this feature, first set a test emergency number using
4241      * adb shell cmd phone emergency-number-test-mode -a 1-555-555-1212
4242      *
4243      * and then set the system property ril.test.emergencynumber to a pair of
4244      * numbers separated by a colon. If the first number matches the number parameter
4245      * this routine returns the second number. Example:
4246      *
4247      * ril.test.emergencynumber=411:1-555-555-1212
4248      *
4249      * To test Dial 411 take call then hang up on MO device to enter ECM.
4250      *
4251      * @param dialString to test if it should be remapped
4252      * @return the same number or the remapped number.
4253      */
checkForTestEmergencyNumber(String dialString)4254     private String checkForTestEmergencyNumber(String dialString) {
4255         String testEn = SystemProperties.get("ril.test.emergencynumber");
4256         if (!TextUtils.isEmpty(testEn)) {
4257             String[] values = testEn.split(":");
4258             logd("checkForTestEmergencyNumber: values.length=" + values.length);
4259             if (values.length == 2) {
4260                 if (values[0].equals(PhoneNumberUtils.stripSeparators(dialString))) {
4261                     logd("checkForTestEmergencyNumber: remap " + dialString + " to " + values[1]);
4262                     dialString = values[1];
4263                 }
4264             }
4265         }
4266         return dialString;
4267     }
4268 
4269     @Override
4270     @NonNull
getOperatorNumeric()4271     public String getOperatorNumeric() {
4272         String operatorNumeric = null;
4273         if (isPhoneTypeGsm()) {
4274             IccRecords r = mIccRecords.get();
4275             if (r != null) {
4276                 operatorNumeric = r.getOperatorNumeric();
4277             }
4278         } else { //isPhoneTypeCdmaLte()
4279             IccRecords curIccRecords = null;
4280             if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_NV) {
4281                 operatorNumeric = SystemProperties.get("ro.cdma.home.operator.numeric");
4282             } else if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_RUIM_SIM) {
4283                 UiccCardApplication uiccCardApplication = mUiccApplication.get();
4284                 if (uiccCardApplication != null
4285                         && uiccCardApplication.getType() == AppType.APPTYPE_RUIM) {
4286                     logd("Legacy RUIM app present");
4287                     curIccRecords = mIccRecords.get();
4288                 } else {
4289                     // Use sim-records for SimApp, USimApp, CSimApp and ISimApp.
4290                     curIccRecords = mSimRecords;
4291                 }
4292                 if (curIccRecords != null && curIccRecords == mSimRecords) {
4293                     operatorNumeric = curIccRecords.getOperatorNumeric();
4294                 } else {
4295                     curIccRecords = mIccRecords.get();
4296                     if (curIccRecords != null && (curIccRecords instanceof RuimRecords)) {
4297                         RuimRecords csim = (RuimRecords) curIccRecords;
4298                         operatorNumeric = csim.getRUIMOperatorNumeric();
4299                     }
4300                 }
4301             }
4302             if (operatorNumeric == null) {
4303                 loge("getOperatorNumeric: Cannot retrieve operatorNumeric:"
4304                         + " mCdmaSubscriptionSource = " + mCdmaSubscriptionSource +
4305                         " mIccRecords = " + ((curIccRecords != null) ?
4306                         curIccRecords.getRecordsLoaded() : null));
4307             }
4308 
4309             logd("getOperatorNumeric: mCdmaSubscriptionSource = " + mCdmaSubscriptionSource
4310                     + " operatorNumeric = " + operatorNumeric);
4311 
4312         }
4313         return TextUtils.emptyIfNull(operatorNumeric);
4314     }
4315 
4316     /**
4317      * @return The country ISO for the subscription associated with this phone.
4318      */
getCountryIso()4319     public String getCountryIso() {
4320         int subId = getSubId();
4321         SubscriptionInfo subInfo = SubscriptionManager.from(getContext())
4322                 .getActiveSubscriptionInfo(subId);
4323         if (subInfo == null || TextUtils.isEmpty(subInfo.getCountryIso())) {
4324             return null;
4325         }
4326         return subInfo.getCountryIso().toUpperCase();
4327     }
4328 
notifyEcbmTimerReset(Boolean flag)4329     public void notifyEcbmTimerReset(Boolean flag) {
4330         mEcmTimerResetRegistrants.notifyResult(flag);
4331     }
4332 
4333     private static final int[] VOICE_PS_CALL_RADIO_TECHNOLOGY = {
4334             ServiceState.RIL_RADIO_TECHNOLOGY_LTE,
4335             ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA,
4336             ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN,
4337             ServiceState.RIL_RADIO_TECHNOLOGY_NR
4338     };
4339 
4340     /**
4341      * Calculates current RIL voice radio technology for CS calls.
4342      *
4343      * This function should only be used in {@link com.android.internal.telephony.GsmCdmaConnection}
4344      * to indicate current CS call radio technology.
4345      *
4346      * @return the RIL voice radio technology used for CS calls,
4347      *         see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
4348      */
getCsCallRadioTech()4349     public @RilRadioTechnology int getCsCallRadioTech() {
4350         int calcVrat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
4351         if (mSST != null) {
4352             calcVrat = getCsCallRadioTech(mSST.mSS.getState(),
4353                     mSST.mSS.getRilVoiceRadioTechnology());
4354         }
4355 
4356         return calcVrat;
4357     }
4358 
4359     /**
4360      * Calculates current RIL voice radio technology for CS calls based on current voice
4361      * registration state and technology.
4362      *
4363      * Mark current RIL voice radio technology as unknow when any of below condtion is met:
4364      *  1) Current RIL voice registration state is not in-service.
4365      *  2) Current RIL voice radio technology is PS call technology, which means CSFB will
4366      *     happen later after call connection is established.
4367      *     It is inappropriate to notify upper layer the PS call technology while current call
4368      *     is CS call, so before CSFB happens, mark voice radio technology as unknow.
4369      *     After CSFB happens, {@link #onVoiceRegStateOrRatChanged} will update voice call radio
4370      *     technology with correct value.
4371      *
4372      * @param vrs the voice registration state
4373      * @param vrat the RIL voice radio technology
4374      *
4375      * @return the RIL voice radio technology used for CS calls,
4376      *         see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}.
4377      */
getCsCallRadioTech(int vrs, int vrat)4378     private @RilRadioTechnology int getCsCallRadioTech(int vrs, int vrat) {
4379         logd("getCsCallRadioTech, current vrs=" + vrs + ", vrat=" + vrat);
4380         int calcVrat = vrat;
4381         if (vrs != ServiceState.STATE_IN_SERVICE
4382                 || ArrayUtils.contains(VOICE_PS_CALL_RADIO_TECHNOLOGY, vrat)) {
4383             calcVrat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN;
4384         }
4385 
4386         logd("getCsCallRadioTech, result calcVrat=" + calcVrat);
4387         return calcVrat;
4388     }
4389 
4390     /**
4391      * Handler of RIL Voice Radio Technology changed event.
4392      */
onVoiceRegStateOrRatChanged(int vrs, int vrat)4393     private void onVoiceRegStateOrRatChanged(int vrs, int vrat) {
4394         logd("onVoiceRegStateOrRatChanged");
4395         mCT.dispatchCsCallRadioTech(getCsCallRadioTech(vrs, vrat));
4396     }
4397 
4398     /**
4399      * Registration point for Ecm timer reset
4400      *
4401      * @param h handler to notify
4402      * @param what User-defined message code
4403      * @param obj placed in Message.obj
4404      */
4405     @Override
registerForEcmTimerReset(Handler h, int what, Object obj)4406     public void registerForEcmTimerReset(Handler h, int what, Object obj) {
4407         mEcmTimerResetRegistrants.addUnique(h, what, obj);
4408     }
4409 
4410     @Override
unregisterForEcmTimerReset(Handler h)4411     public void unregisterForEcmTimerReset(Handler h) {
4412         mEcmTimerResetRegistrants.remove(h);
4413     }
4414 
4415     @Override
registerForVolteSilentRedial(Handler h, int what, Object obj)4416     public void registerForVolteSilentRedial(Handler h, int what, Object obj) {
4417         mVolteSilentRedialRegistrants.addUnique(h, what, obj);
4418     }
4419 
4420     @Override
unregisterForVolteSilentRedial(Handler h)4421     public void unregisterForVolteSilentRedial(Handler h) {
4422         mVolteSilentRedialRegistrants.remove(h);
4423     }
4424 
notifyVolteSilentRedial(String dialString, int causeCode)4425     public void notifyVolteSilentRedial(String dialString, int causeCode) {
4426         logd("notifyVolteSilentRedial: dialString=" + dialString + " causeCode=" + causeCode);
4427         AsyncResult ar = new AsyncResult(null,
4428                 new SilentRedialParam(dialString, causeCode, mDialArgs), null);
4429         mVolteSilentRedialRegistrants.notifyRegistrants(ar);
4430     }
4431 
4432     /**
4433      * Sets the SIM voice message waiting indicator records.
4434      * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported
4435      * @param countWaiting The number of messages waiting, if known. Use
4436      *                     -1 to indicate that an unknown number of
4437      *                      messages are waiting
4438      */
4439     @Override
setVoiceMessageWaiting(int line, int countWaiting)4440     public void setVoiceMessageWaiting(int line, int countWaiting) {
4441         if (isPhoneTypeGsm()) {
4442             IccRecords r = mIccRecords.get();
4443             if (r != null) {
4444                 r.setVoiceMessageWaiting(line, countWaiting);
4445             } else {
4446                 logd("SIM Records not found, MWI not updated");
4447             }
4448         } else {
4449             setVoiceMessageCount(countWaiting);
4450         }
4451     }
4452 
makeEmptyCallForward()4453     private CallForwardInfo[] makeEmptyCallForward() {
4454         CallForwardInfo infos[] = new CallForwardInfo[1];
4455 
4456         infos[0] = new CallForwardInfo();
4457         infos[0].status = CommandsInterface.SS_STATUS_UNKNOWN;
4458         infos[0].reason = 0;
4459         infos[0].serviceClass = CommandsInterface.SERVICE_CLASS_VOICE;
4460         infos[0].toa = PhoneNumberUtils.TOA_Unknown;
4461         infos[0].number = "";
4462         infos[0].timeSeconds = 0;
4463 
4464         return infos;
4465     }
4466 
subscriptionIdToPhoneAccountHandle(final int subId)4467     private PhoneAccountHandle subscriptionIdToPhoneAccountHandle(final int subId) {
4468         final TelecomManager telecomManager = TelecomManager.from(mContext);
4469         final TelephonyManager telephonyManager = TelephonyManager.from(mContext);
4470         final Iterator<PhoneAccountHandle> phoneAccounts =
4471             telecomManager.getCallCapablePhoneAccounts(true).listIterator();
4472 
4473         while (phoneAccounts.hasNext()) {
4474             final PhoneAccountHandle phoneAccountHandle = phoneAccounts.next();
4475             final PhoneAccount phoneAccount = telecomManager.getPhoneAccount(phoneAccountHandle);
4476             if (subId == telephonyManager.getSubIdForPhoneAccount(phoneAccount)) {
4477                 return phoneAccountHandle;
4478             }
4479         }
4480 
4481         return null;
4482     }
4483 
4484     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
logd(String s)4485     private void logd(String s) {
4486         Rlog.d(LOG_TAG, "[" + mPhoneId + "] " + s);
4487     }
4488 
logi(String s)4489     private void logi(String s) {
4490         Rlog.i(LOG_TAG, "[" + mPhoneId + "] " + s);
4491     }
4492 
4493     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
loge(String s)4494     private void loge(String s) {
4495         Rlog.e(LOG_TAG, "[" + mPhoneId + "] " + s);
4496     }
4497 
pii(String s)4498     private static String pii(String s) {
4499         return Rlog.pii(LOG_TAG, s);
4500     }
4501 
4502     @Override
isUtEnabled()4503     public boolean isUtEnabled() {
4504         Phone imsPhone = mImsPhone;
4505         if (imsPhone != null) {
4506             return imsPhone.isUtEnabled();
4507         } else {
4508             logd("isUtEnabled: called for GsmCdma");
4509             return false;
4510         }
4511     }
4512 
getDtmfToneDelayKey()4513     public String getDtmfToneDelayKey() {
4514         return isPhoneTypeGsm() ?
4515                 CarrierConfigManager.KEY_GSM_DTMF_TONE_DELAY_INT :
4516                 CarrierConfigManager.KEY_CDMA_DTMF_TONE_DELAY_INT;
4517     }
4518 
4519     @VisibleForTesting
getWakeLock()4520     public PowerManager.WakeLock getWakeLock() {
4521         return mWakeLock;
4522     }
4523 
getLteOnCdmaMode()4524     public int getLteOnCdmaMode() {
4525         int currentConfig = TelephonyProperties.lte_on_cdma_device()
4526                 .orElse(PhoneConstants.LTE_ON_CDMA_FALSE);
4527         int lteOnCdmaModeDynamicValue = currentConfig;
4528 
4529         UiccCardApplication cdmaApplication =
4530                     mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2);
4531         if (cdmaApplication != null && cdmaApplication.getType() == AppType.APPTYPE_RUIM) {
4532             //Legacy RUIM cards don't support LTE.
4533             lteOnCdmaModeDynamicValue = RILConstants.LTE_ON_CDMA_FALSE;
4534 
4535             //Override only if static configuration is TRUE.
4536             if (currentConfig == RILConstants.LTE_ON_CDMA_TRUE) {
4537                 return lteOnCdmaModeDynamicValue;
4538             }
4539         }
4540         return currentConfig;
4541     }
4542 
updateTtyMode(int ttyMode)4543     private void updateTtyMode(int ttyMode) {
4544         logi(String.format("updateTtyMode ttyMode=%d", ttyMode));
4545         setTTYMode(telecomModeToPhoneMode(ttyMode), null);
4546     }
updateUiTtyMode(int ttyMode)4547     private void updateUiTtyMode(int ttyMode) {
4548         logi(String.format("updateUiTtyMode ttyMode=%d", ttyMode));
4549         setUiTTYMode(telecomModeToPhoneMode(ttyMode), null);
4550     }
4551 
4552     /**
4553      * Given a telecom TTY mode, convert to a Telephony mode equivalent.
4554      * @param telecomMode Telecom TTY mode.
4555      * @return Telephony phone TTY mode.
4556      */
telecomModeToPhoneMode(int telecomMode)4557     private static int telecomModeToPhoneMode(int telecomMode) {
4558         switch (telecomMode) {
4559             // AT command only has 0 and 1, so mapping VCO
4560             // and HCO to FULL
4561             case TelecomManager.TTY_MODE_FULL:
4562             case TelecomManager.TTY_MODE_VCO:
4563             case TelecomManager.TTY_MODE_HCO:
4564                 return Phone.TTY_MODE_FULL;
4565             default:
4566                 return Phone.TTY_MODE_OFF;
4567         }
4568     }
4569 
4570     /**
4571      * Load the current TTY mode in GsmCdmaPhone based on Telecom and UI settings.
4572      */
loadTtyMode()4573     private void loadTtyMode() {
4574         int ttyMode = TelecomManager.TTY_MODE_OFF;
4575         TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
4576         if (telecomManager != null) {
4577             ttyMode = telecomManager.getCurrentTtyMode();
4578         }
4579         updateTtyMode(ttyMode);
4580         //Get preferred TTY mode from settings as UI Tty mode is always user preferred Tty mode.
4581         ttyMode = Settings.Secure.getInt(mContext.getContentResolver(),
4582                 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF);
4583         updateUiTtyMode(ttyMode);
4584     }
4585 
reapplyUiccAppsEnablementIfNeeded(int retries)4586     private void reapplyUiccAppsEnablementIfNeeded(int retries) {
4587         UiccSlot slot = mUiccController.getUiccSlotForPhone(mPhoneId);
4588 
4589         // If no card is present or we don't have mUiccApplicationsEnabled yet, do nothing.
4590         if (slot == null || slot.getCardState() != IccCardStatus.CardState.CARDSTATE_PRESENT
4591                 || mUiccApplicationsEnabled == null) {
4592             return;
4593         }
4594 
4595         String iccId = slot.getIccId();
4596         if (iccId == null) return;
4597 
4598         SubscriptionInfo info = SubscriptionController.getInstance().getSubInfoForIccId(
4599                 IccUtils.stripTrailingFs(iccId));
4600 
4601         // If info is null, it could be a new subscription. By default we enable it.
4602         boolean expectedValue = info == null ? true : info.areUiccApplicationsEnabled();
4603 
4604         // If for any reason current state is different from configured state, re-apply the
4605         // configured state.
4606         if (expectedValue != mUiccApplicationsEnabled) {
4607             mCi.enableUiccApplications(expectedValue, Message.obtain(
4608                     this, EVENT_REAPPLY_UICC_APPS_ENABLEMENT_DONE,
4609                     new Pair<Boolean, Integer>(expectedValue, retries)));
4610         }
4611     }
4612 
4613     // Enable or disable uicc applications.
4614     @Override
enableUiccApplications(boolean enable, Message onCompleteMessage)4615     public void enableUiccApplications(boolean enable, Message onCompleteMessage) {
4616         // First check if card is present. Otherwise mUiccApplicationsDisabled doesn't make
4617         // any sense.
4618         UiccSlot slot = mUiccController.getUiccSlotForPhone(mPhoneId);
4619         if (slot == null || slot.getCardState() != IccCardStatus.CardState.CARDSTATE_PRESENT) {
4620             if (onCompleteMessage != null) {
4621                 AsyncResult.forMessage(onCompleteMessage, null,
4622                         new IllegalStateException("No SIM card is present"));
4623                 onCompleteMessage.sendToTarget();
4624             }
4625             return;
4626         }
4627 
4628         mCi.enableUiccApplications(enable, onCompleteMessage);
4629     }
4630 
4631     /**
4632      * Whether disabling a physical subscription is supported or not.
4633      */
4634     @Override
canDisablePhysicalSubscription()4635     public boolean canDisablePhysicalSubscription() {
4636         return mCi.canToggleUiccApplicationsEnablement();
4637     }
4638 
4639     @Override
getEquivalentHomePlmns()4640     public @NonNull List<String> getEquivalentHomePlmns() {
4641         if (isPhoneTypeGsm()) {
4642             IccRecords r = mIccRecords.get();
4643             if (r != null && r.getEhplmns() != null) {
4644                 return Arrays.asList(r.getEhplmns());
4645             }
4646         } else if (isPhoneTypeCdma()) {
4647             loge("EHPLMN is not available in CDMA");
4648         }
4649         return Collections.emptyList();
4650     }
4651 
4652     /**
4653      * @return Currently bound data service package names.
4654      */
getDataServicePackages()4655     public @NonNull List<String> getDataServicePackages() {
4656         List<String> packages = new ArrayList<>();
4657         int[] transports = new int[]{AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
4658                 AccessNetworkConstants.TRANSPORT_TYPE_WLAN};
4659 
4660         for (int transport : transports) {
4661             DcTracker dct = getDcTracker(transport);
4662             if (dct != null) {
4663                 String pkg = dct.getDataServiceManager().getDataServicePackageName();
4664                 if (!TextUtils.isEmpty(pkg)) {
4665                     packages.add(pkg);
4666                 }
4667             }
4668         }
4669 
4670         return packages;
4671     }
4672 
updateBroadcastEmergencyCallStateChangesAfterCarrierConfigChanged( PersistableBundle config)4673     private void updateBroadcastEmergencyCallStateChangesAfterCarrierConfigChanged(
4674             PersistableBundle config) {
4675         if (config == null) {
4676             loge("didn't get broadcastEmergencyCallStateChanges from carrier config");
4677             return;
4678         }
4679 
4680         // get broadcastEmergencyCallStateChanges
4681         boolean broadcastEmergencyCallStateChanges = config.getBoolean(
4682                 CarrierConfigManager.KEY_BROADCAST_EMERGENCY_CALL_STATE_CHANGES_BOOL);
4683         logd("broadcastEmergencyCallStateChanges = " + broadcastEmergencyCallStateChanges);
4684         setBroadcastEmergencyCallStateChanges(broadcastEmergencyCallStateChanges);
4685     }
4686 
updateNrSettingsAfterCarrierConfigChanged(PersistableBundle config)4687     private void updateNrSettingsAfterCarrierConfigChanged(PersistableBundle config) {
4688         if (config == null) {
4689             loge("didn't get the carrier_nr_availability_int from the carrier config.");
4690             return;
4691         }
4692         int[] nrAvailabilities = config.getIntArray(
4693                 CarrierConfigManager.KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY);
4694         mIsCarrierNrSupported = !ArrayUtils.isEmpty(nrAvailabilities);
4695     }
4696 
updateCdmaRoamingSettingsAfterCarrierConfigChanged(PersistableBundle config)4697     private void updateCdmaRoamingSettingsAfterCarrierConfigChanged(PersistableBundle config) {
4698         if (config == null) {
4699             loge("didn't get the cdma_roaming_mode changes from the carrier config.");
4700             return;
4701         }
4702 
4703         // Changing the cdma roaming settings based carrier config.
4704         int config_cdma_roaming_mode = config.getInt(
4705                 CarrierConfigManager.KEY_CDMA_ROAMING_MODE_INT);
4706         int current_cdma_roaming_mode =
4707                 Settings.Global.getInt(getContext().getContentResolver(),
4708                         Settings.Global.CDMA_ROAMING_MODE,
4709                         TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT);
4710         switch (config_cdma_roaming_mode) {
4711             // Carrier's cdma_roaming_mode will overwrite the user's previous settings
4712             // Keep the user's previous setting in global variable which will be used
4713             // when carrier's setting is turn off.
4714             case TelephonyManager.CDMA_ROAMING_MODE_HOME:
4715             case TelephonyManager.CDMA_ROAMING_MODE_AFFILIATED:
4716             case TelephonyManager.CDMA_ROAMING_MODE_ANY:
4717                 logd("cdma_roaming_mode is going to changed to "
4718                         + config_cdma_roaming_mode);
4719                 setCdmaRoamingPreference(config_cdma_roaming_mode,
4720                         obtainMessage(EVENT_SET_ROAMING_PREFERENCE_DONE));
4721                 break;
4722 
4723             // When carrier's setting is turn off, change the cdma_roaming_mode to the
4724             // previous user's setting
4725             case TelephonyManager.CDMA_ROAMING_MODE_RADIO_DEFAULT:
4726                 if (current_cdma_roaming_mode != config_cdma_roaming_mode) {
4727                     logd("cdma_roaming_mode is going to changed to "
4728                             + current_cdma_roaming_mode);
4729                     setCdmaRoamingPreference(current_cdma_roaming_mode,
4730                             obtainMessage(EVENT_SET_ROAMING_PREFERENCE_DONE));
4731                 }
4732                 break;
4733             default:
4734                 loge("Invalid cdma_roaming_mode settings: " + config_cdma_roaming_mode);
4735         }
4736     }
4737 
4738     /**
4739      * Determines if IMS is enabled for call.
4740      *
4741      * @return {@code true} if IMS calling is enabled.
4742      */
isImsUseEnabled()4743     public boolean isImsUseEnabled() {
4744         ImsManager imsManager = mImsManagerFactory.create(mContext, mPhoneId);
4745         boolean imsUseEnabled = ((imsManager.isVolteEnabledByPlatform()
4746                 && imsManager.isEnhanced4gLteModeSettingEnabledByUser())
4747                 || (imsManager.isWfcEnabledByPlatform() && imsManager.isWfcEnabledByUser())
4748                 && imsManager.isNonTtyOrTtyOnVolteEnabled());
4749         return imsUseEnabled;
4750     }
4751 
4752     @Override
getInboundSmsHandler(boolean is3gpp2)4753     public InboundSmsHandler getInboundSmsHandler(boolean is3gpp2) {
4754         return mIccSmsInterfaceManager.getInboundSmsHandler(is3gpp2);
4755     }
4756 }
4757