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