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