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