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