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