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