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