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