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