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