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