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.app.ActivityManager; 36 import android.compat.annotation.UnsupportedAppUsage; 37 import android.content.BroadcastReceiver; 38 import android.content.ContentValues; 39 import android.content.Context; 40 import android.content.Intent; 41 import android.content.IntentFilter; 42 import android.content.SharedPreferences; 43 import android.database.SQLException; 44 import android.net.Uri; 45 import android.os.AsyncResult; 46 import android.os.Bundle; 47 import android.os.Handler; 48 import android.os.Message; 49 import android.os.PersistableBundle; 50 import android.os.PowerManager; 51 import android.os.Registrant; 52 import android.os.RegistrantList; 53 import android.os.ResultReceiver; 54 import android.os.SystemProperties; 55 import android.os.UserHandle; 56 import android.os.WorkSource; 57 import android.preference.PreferenceManager; 58 import android.provider.Settings; 59 import android.provider.Telephony; 60 import android.sysprop.TelephonyProperties; 61 import android.telecom.PhoneAccount; 62 import android.telecom.PhoneAccountHandle; 63 import android.telecom.TelecomManager; 64 import android.telecom.VideoProfile; 65 import android.telephony.AccessNetworkConstants; 66 import android.telephony.BarringInfo; 67 import android.telephony.CarrierConfigManager; 68 import android.telephony.CellIdentity; 69 import android.telephony.DataFailCause; 70 import android.telephony.ImsiEncryptionInfo; 71 import android.telephony.NetworkScanRequest; 72 import android.telephony.PhoneNumberUtils; 73 import android.telephony.PreciseDataConnectionState; 74 import android.telephony.ServiceState; 75 import android.telephony.ServiceState.RilRadioTechnology; 76 import android.telephony.SignalThresholdInfo; 77 import android.telephony.SubscriptionInfo; 78 import android.telephony.SubscriptionManager; 79 import android.telephony.TelephonyManager; 80 import android.telephony.UssdResponse; 81 import android.telephony.data.ApnSetting; 82 import android.text.TextUtils; 83 import android.util.Log; 84 import android.util.Pair; 85 86 import com.android.ims.ImsManager; 87 import com.android.internal.annotations.VisibleForTesting; 88 import com.android.internal.telephony.CommandException; 89 import com.android.internal.telephony.cdma.CdmaMmiCode; 90 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; 91 import com.android.internal.telephony.dataconnection.DataEnabledSettings; 92 import com.android.internal.telephony.dataconnection.DcTracker; 93 import com.android.internal.telephony.dataconnection.TransportManager; 94 import com.android.internal.telephony.emergency.EmergencyNumberTracker; 95 import com.android.internal.telephony.gsm.GsmMmiCode; 96 import com.android.internal.telephony.gsm.SuppServiceNotification; 97 import com.android.internal.telephony.imsphone.ImsPhoneMmiCode; 98 import com.android.internal.telephony.metrics.VoiceCallSessionStats; 99 import com.android.internal.telephony.test.SimulatedRadioControl; 100 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType; 101 import com.android.internal.telephony.uicc.IccCardStatus; 102 import com.android.internal.telephony.uicc.IccException; 103 import com.android.internal.telephony.uicc.IccRecords; 104 import com.android.internal.telephony.uicc.IccUtils; 105 import com.android.internal.telephony.uicc.IccVmNotSupportedException; 106 import com.android.internal.telephony.uicc.IsimRecords; 107 import com.android.internal.telephony.uicc.IsimUiccRecords; 108 import com.android.internal.telephony.uicc.RuimRecords; 109 import com.android.internal.telephony.uicc.SIMRecords; 110 import com.android.internal.telephony.uicc.UiccCard; 111 import com.android.internal.telephony.uicc.UiccCardApplication; 112 import com.android.internal.telephony.uicc.UiccController; 113 import com.android.internal.telephony.uicc.UiccProfile; 114 import com.android.internal.telephony.uicc.UiccSlot; 115 import com.android.internal.telephony.util.ArrayUtils; 116 import com.android.telephony.Rlog; 117 118 import java.io.FileDescriptor; 119 import java.io.PrintWriter; 120 import java.util.ArrayList; 121 import java.util.Iterator; 122 import java.util.List; 123 import java.util.regex.Matcher; 124 import java.util.regex.Pattern; 125 126 /** 127 * {@hide} 128 */ 129 public class GsmCdmaPhone extends Phone { 130 // NOTE that LOG_TAG here is "GsmCdma", which means that log messages 131 // from this file will go into the radio log rather than the main 132 // log. (Use "adb logcat -b radio" to see them.) 133 public static final String LOG_TAG = "GsmCdmaPhone"; 134 private static final boolean DBG = true; 135 private static final boolean VDBG = false; /* STOPSHIP if true */ 136 137 /** Required magnitude change between unsolicited SignalStrength reports. */ 138 private static final int REPORTING_HYSTERESIS_DB = 2; 139 /** Required throughput change between unsolicited LinkCapacityEstimate reports. */ 140 private static final int REPORTING_HYSTERESIS_KBPS = 50; 141 /** Minimum time between unsolicited SignalStrength and LinkCapacityEstimate reports. */ 142 private static final int REPORTING_HYSTERESIS_MILLIS = 3000; 143 144 //GSM 145 // Key used to read/write voice mail number 146 private static final String VM_NUMBER = "vm_number_key"; 147 // Key used to read/write the SIM IMSI used for storing the voice mail 148 private static final String VM_SIM_IMSI = "vm_sim_imsi_key"; 149 /** List of Registrants to receive Supplementary Service Notifications. */ 150 private RegistrantList mSsnRegistrants = new RegistrantList(); 151 152 //CDMA 153 // Default Emergency Callback Mode exit timer 154 private static final long DEFAULT_ECM_EXIT_TIMER_VALUE = 300000; 155 private static final String VM_NUMBER_CDMA = "vm_number_key_cdma"; 156 public static final int RESTART_ECM_TIMER = 0; // restart Ecm timer 157 public static final int CANCEL_ECM_TIMER = 1; // cancel Ecm timer 158 private static final String PREFIX_WPS = "*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 //Common 194 // Instance Variables 195 @UnsupportedAppUsage 196 private IsimUiccRecords mIsimUiccRecords; 197 @UnsupportedAppUsage 198 public GsmCdmaCallTracker mCT; 199 @UnsupportedAppUsage 200 public ServiceStateTracker mSST; 201 public EmergencyNumberTracker mEmergencyNumberTracker; 202 @UnsupportedAppUsage 203 private ArrayList <MmiCode> mPendingMMIs = new ArrayList<MmiCode>(); 204 private IccPhoneBookInterfaceManager mIccPhoneBookIntManager; 205 206 private int mPrecisePhoneType; 207 208 // mEcmTimerResetRegistrants are informed after Ecm timer is canceled or re-started 209 private final RegistrantList mEcmTimerResetRegistrants = new RegistrantList(); 210 211 private final RegistrantList mVolteSilentRedialRegistrants = new RegistrantList(); 212 private DialArgs mDialArgs = null; 213 214 private String mImei; 215 private String mImeiSv; 216 private String mVmNumber; 217 218 // Create Cfu (Call forward unconditional) so that dialing number & 219 // mOnComplete (Message object passed by client) can be packed & 220 // given as a single Cfu object as user data to RIL. 221 private static class Cfu { 222 final String mSetCfNumber; 223 final Message mOnComplete; 224 225 @UnsupportedAppUsage Cfu(String cfNumber, Message onComplete)226 Cfu(String cfNumber, Message onComplete) { 227 mSetCfNumber = cfNumber; 228 mOnComplete = onComplete; 229 } 230 } 231 232 @UnsupportedAppUsage 233 private IccSmsInterfaceManager mIccSmsInterfaceManager; 234 235 private boolean mResetModemOnRadioTechnologyChange = false; 236 237 private int mRilVersion; 238 private boolean mBroadcastEmergencyCallStateChanges = false; 239 private CarrierKeyDownloadManager mCDM; 240 private CarrierInfoManager mCIM; 241 242 private final SettingsObserver mSettingsObserver; 243 244 // Constructors 245 GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId, int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory)246 public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId, 247 int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory) { 248 this(context, ci, notifier, false, phoneId, precisePhoneType, telephonyComponentFactory); 249 } 250 GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode, int phoneId, int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory)251 public GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, 252 boolean unitTestMode, int phoneId, int precisePhoneType, 253 TelephonyComponentFactory telephonyComponentFactory) { 254 super(precisePhoneType == PhoneConstants.PHONE_TYPE_GSM ? "GSM" : "CDMA", 255 notifier, context, ci, unitTestMode, phoneId, telephonyComponentFactory); 256 257 // phone type needs to be set before other initialization as other objects rely on it 258 mPrecisePhoneType = precisePhoneType; 259 mVoiceCallSessionStats = new VoiceCallSessionStats(mPhoneId, this); 260 initOnce(ci); 261 initRatSpecific(precisePhoneType); 262 // CarrierSignalAgent uses CarrierActionAgent in construction so it needs to be created 263 // after CarrierActionAgent. 264 mCarrierActionAgent = mTelephonyComponentFactory.inject(CarrierActionAgent.class.getName()) 265 .makeCarrierActionAgent(this); 266 mCarrierSignalAgent = mTelephonyComponentFactory.inject(CarrierSignalAgent.class.getName()) 267 .makeCarrierSignalAgent(this); 268 mTransportManager = mTelephonyComponentFactory.inject(TransportManager.class.getName()) 269 .makeTransportManager(this); 270 mSST = mTelephonyComponentFactory.inject(ServiceStateTracker.class.getName()) 271 .makeServiceStateTracker(this, this.mCi); 272 mEmergencyNumberTracker = mTelephonyComponentFactory 273 .inject(EmergencyNumberTracker.class.getName()).makeEmergencyNumberTracker( 274 this, this.mCi); 275 mDataEnabledSettings = mTelephonyComponentFactory 276 .inject(DataEnabledSettings.class.getName()).makeDataEnabledSettings(this); 277 mDeviceStateMonitor = mTelephonyComponentFactory.inject(DeviceStateMonitor.class.getName()) 278 .makeDeviceStateMonitor(this); 279 280 // DisplayInfoController creates an OverrideNetworkTypeController, which uses 281 // DeviceStateMonitor so needs to be crated after it is instantiated. 282 mDisplayInfoController = mTelephonyComponentFactory.inject( 283 DisplayInfoController.class.getName()).makeDisplayInfoController(this); 284 285 // DcTracker uses ServiceStateTracker and DisplayInfoController so needs to be created 286 // after they are instantiated 287 for (int transport : mTransportManager.getAvailableTransports()) { 288 mDcTrackers.put(transport, mTelephonyComponentFactory.inject(DcTracker.class.getName()) 289 .makeDcTracker(this, transport)); 290 } 291 292 mCarrierResolver = mTelephonyComponentFactory.inject(CarrierResolver.class.getName()) 293 .makeCarrierResolver(this); 294 295 getCarrierActionAgent().registerForCarrierAction( 296 CarrierActionAgent.CARRIER_ACTION_SET_METERED_APNS_ENABLED, this, 297 EVENT_SET_CARRIER_DATA_ENABLED, null, false); 298 299 mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null); 300 mSST.registerForVoiceRegStateOrRatChanged(this, EVENT_VRS_OR_RAT_CHANGED, null); 301 302 mSettingsObserver = new SettingsObserver(context, this); 303 mSettingsObserver.observe( 304 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED), 305 EVENT_DEVICE_PROVISIONED_CHANGE); 306 mSettingsObserver.observe( 307 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED), 308 EVENT_DEVICE_PROVISIONING_DATA_SETTING_CHANGE); 309 310 SubscriptionController.getInstance().registerForUiccAppsEnabled(this, 311 EVENT_UICC_APPS_ENABLEMENT_SETTING_CHANGED, null, false); 312 313 loadTtyMode(); 314 logd("GsmCdmaPhone: constructor: sub = " + mPhoneId); 315 } 316 317 private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { 318 @Override 319 public void onReceive(Context context, Intent intent) { 320 Rlog.d(LOG_TAG, "mBroadcastReceiver: action " + intent.getAction()); 321 String action = intent.getAction(); 322 if (CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED.equals(action)) { 323 // Only handle carrier config changes for this phone id. 324 if (mPhoneId == intent.getIntExtra(CarrierConfigManager.EXTRA_SLOT_INDEX, -1)) { 325 sendMessage(obtainMessage(EVENT_CARRIER_CONFIG_CHANGED)); 326 } 327 } else if (TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED.equals(action)) { 328 int ttyMode = intent.getIntExtra( 329 TelecomManager.EXTRA_CURRENT_TTY_MODE, TelecomManager.TTY_MODE_OFF); 330 updateTtyMode(ttyMode); 331 } else if (TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED.equals(action)) { 332 int newPreferredTtyMode = intent.getIntExtra( 333 TelecomManager.EXTRA_TTY_PREFERRED_MODE, TelecomManager.TTY_MODE_OFF); 334 updateUiTtyMode(newPreferredTtyMode); 335 } 336 } 337 }; 338 initOnce(CommandsInterface ci)339 private void initOnce(CommandsInterface ci) { 340 if (ci instanceof SimulatedRadioControl) { 341 mSimulatedRadioControl = (SimulatedRadioControl) ci; 342 } 343 344 mCT = mTelephonyComponentFactory.inject(GsmCdmaCallTracker.class.getName()) 345 .makeGsmCdmaCallTracker(this); 346 mIccPhoneBookIntManager = mTelephonyComponentFactory 347 .inject(IccPhoneBookInterfaceManager.class.getName()) 348 .makeIccPhoneBookInterfaceManager(this); 349 PowerManager pm 350 = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); 351 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG); 352 mIccSmsInterfaceManager = mTelephonyComponentFactory 353 .inject(IccSmsInterfaceManager.class.getName()) 354 .makeIccSmsInterfaceManager(this); 355 356 mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); 357 mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); 358 mCi.registerForOn(this, EVENT_RADIO_ON, null); 359 mCi.registerForRadioStateChanged(this, EVENT_RADIO_STATE_CHANGED, null); 360 mCi.registerUiccApplicationEnablementChanged(this, 361 EVENT_UICC_APPS_ENABLEMENT_STATUS_CHANGED, 362 null); 363 mCi.setOnSuppServiceNotification(this, EVENT_SSN, null); 364 mCi.setOnRegistrationFailed(this, EVENT_REGISTRATION_FAILED, null); 365 mCi.registerForBarringInfoChanged(this, EVENT_BARRING_INFO_CHANGED, null); 366 367 //GSM 368 mCi.setOnUSSD(this, EVENT_USSD, null); 369 mCi.setOnSs(this, EVENT_SS, null); 370 371 //CDMA 372 mCdmaSSM = mTelephonyComponentFactory.inject(CdmaSubscriptionSourceManager.class.getName()) 373 .getCdmaSubscriptionSourceManagerInstance(mContext, 374 mCi, this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null); 375 mCi.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null); 376 mCi.registerForExitEmergencyCallbackMode(this, EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE, 377 null); 378 mCi.registerForModemReset(this, EVENT_MODEM_RESET, null); 379 // get the string that specifies the carrier OTA Sp number 380 mCarrierOtaSpNumSchema = TelephonyManager.from(mContext).getOtaSpNumberSchemaForPhone( 381 getPhoneId(), ""); 382 383 mResetModemOnRadioTechnologyChange = TelephonyProperties.reset_on_radio_tech_change() 384 .orElse(false); 385 386 mCi.registerForRilConnected(this, EVENT_RIL_CONNECTED, null); 387 mCi.registerForVoiceRadioTechChanged(this, EVENT_VOICE_RADIO_TECH_CHANGED, null); 388 IntentFilter filter = new IntentFilter( 389 CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED); 390 filter.addAction(TelecomManager.ACTION_CURRENT_TTY_MODE_CHANGED); 391 filter.addAction(TelecomManager.ACTION_TTY_PREFERRED_MODE_CHANGED); 392 mContext.registerReceiver(mBroadcastReceiver, filter); 393 394 mCDM = new CarrierKeyDownloadManager(this); 395 mCIM = new CarrierInfoManager(); 396 } 397 initRatSpecific(int precisePhoneType)398 private void initRatSpecific(int precisePhoneType) { 399 mPendingMMIs.clear(); 400 mIccPhoneBookIntManager.updateIccRecords(null); 401 mEsn = null; 402 mMeid = null; 403 404 mPrecisePhoneType = precisePhoneType; 405 logd("Precise phone type " + mPrecisePhoneType); 406 407 TelephonyManager tm = TelephonyManager.from(mContext); 408 UiccProfile uiccProfile = getUiccProfile(); 409 if (isPhoneTypeGsm()) { 410 mCi.setPhoneType(PhoneConstants.PHONE_TYPE_GSM); 411 tm.setPhoneType(getPhoneId(), PhoneConstants.PHONE_TYPE_GSM); 412 if (uiccProfile != null) { 413 uiccProfile.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_UMTS); 414 } 415 } else { 416 mCdmaSubscriptionSource = mCdmaSSM.getCdmaSubscriptionSource(); 417 // This is needed to handle phone process crashes 418 mIsPhoneInEcmState = getInEcmMode(); 419 if (mIsPhoneInEcmState) { 420 // Send a message which will invoke handleExitEmergencyCallbackMode 421 mCi.exitEmergencyCallbackMode(null); 422 } 423 424 mCi.setPhoneType(PhoneConstants.PHONE_TYPE_CDMA); 425 tm.setPhoneType(getPhoneId(), PhoneConstants.PHONE_TYPE_CDMA); 426 if (uiccProfile != null) { 427 uiccProfile.setVoiceRadioTech(ServiceState.RIL_RADIO_TECHNOLOGY_1xRTT); 428 } 429 // Sets operator properties by retrieving from build-time system property 430 String operatorAlpha = SystemProperties.get("ro.cdma.home.operator.alpha"); 431 String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC); 432 logd("init: operatorAlpha='" + operatorAlpha 433 + "' operatorNumeric='" + operatorNumeric + "'"); 434 if (!TextUtils.isEmpty(operatorAlpha)) { 435 logd("init: set 'gsm.sim.operator.alpha' to operator='" + operatorAlpha + "'"); 436 tm.setSimOperatorNameForPhone(mPhoneId, operatorAlpha); 437 } 438 if (!TextUtils.isEmpty(operatorNumeric)) { 439 logd("init: set 'gsm.sim.operator.numeric' to operator='" + operatorNumeric + 440 "'"); 441 logd("update icc_operator_numeric=" + operatorNumeric); 442 tm.setSimOperatorNumericForPhone(mPhoneId, operatorNumeric); 443 444 SubscriptionController.getInstance().setMccMnc(operatorNumeric, getSubId()); 445 446 // Sets iso country property by retrieving from build-time system property 447 String iso = ""; 448 try { 449 iso = MccTable.countryCodeForMcc(operatorNumeric.substring(0, 3)); 450 } catch (StringIndexOutOfBoundsException ex) { 451 Rlog.e(LOG_TAG, "init: countryCodeForMcc error", ex); 452 } 453 454 logd("init: set 'gsm.sim.operator.iso-country' to iso=" + iso); 455 tm.setSimCountryIsoForPhone(mPhoneId, iso); 456 SubscriptionController.getInstance().setCountryIso(iso, getSubId()); 457 458 // Updates MCC MNC device configuration information 459 logd("update mccmnc=" + operatorNumeric); 460 MccTable.updateMccMncConfiguration(mContext, operatorNumeric); 461 } 462 463 // Sets current entry in the telephony carrier table 464 updateCurrentCarrierInProvider(operatorNumeric); 465 } 466 } 467 468 @UnsupportedAppUsage isPhoneTypeGsm()469 public boolean isPhoneTypeGsm() { 470 return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_GSM; 471 } 472 isPhoneTypeCdma()473 public boolean isPhoneTypeCdma() { 474 return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_CDMA; 475 } 476 isPhoneTypeCdmaLte()477 public boolean isPhoneTypeCdmaLte() { 478 return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_CDMA_LTE; 479 } 480 switchPhoneType(int precisePhoneType)481 private void switchPhoneType(int precisePhoneType) { 482 removeCallbacks(mExitEcmRunnable); 483 484 initRatSpecific(precisePhoneType); 485 486 mSST.updatePhoneType(); 487 setPhoneName(precisePhoneType == PhoneConstants.PHONE_TYPE_GSM ? "GSM" : "CDMA"); 488 onUpdateIccAvailability(); 489 // if is possible that onUpdateIccAvailability() does not unregister and re-register for 490 // ICC events, for example if mUiccApplication does not change which can happen if phone 491 // type is transitioning from CDMA to GSM but 3gpp2 application was not available. 492 // To handle such cases, unregister and re-register here. They still need to be called in 493 // onUpdateIccAvailability(), since in normal cases register/unregister calls can be on 494 // different IccRecords objects. Here they are on the same IccRecords object. 495 unregisterForIccRecordEvents(); 496 registerForIccRecordEvents(); 497 498 mCT.updatePhoneType(); 499 500 int radioState = mCi.getRadioState(); 501 if (radioState != TelephonyManager.RADIO_POWER_UNAVAILABLE) { 502 handleRadioAvailable(); 503 if (radioState == TelephonyManager.RADIO_POWER_ON) { 504 handleRadioOn(); 505 } 506 } 507 if (radioState != TelephonyManager.RADIO_POWER_ON) { 508 handleRadioOffOrNotAvailable(); 509 } 510 } 511 512 @Override finalize()513 protected void finalize() { 514 if(DBG) logd("GsmCdmaPhone finalized"); 515 if (mWakeLock != null && mWakeLock.isHeld()) { 516 Rlog.e(LOG_TAG, "UNEXPECTED; mWakeLock is held when finalizing."); 517 mWakeLock.release(); 518 } 519 } 520 521 @UnsupportedAppUsage 522 @Override 523 @NonNull getServiceState()524 public ServiceState getServiceState() { 525 if (mSST == null || mSST.mSS.getState() != ServiceState.STATE_IN_SERVICE) { 526 if (mImsPhone != null) { 527 return mergeServiceStates((mSST == null) ? new ServiceState() : mSST.mSS, 528 mImsPhone.getServiceState()); 529 } 530 } 531 532 if (mSST != null) { 533 return mSST.mSS; 534 } else { 535 // avoid potential NPE in EmergencyCallHelper during Phone switch 536 return new ServiceState(); 537 } 538 } 539 540 @Override getCellIdentity(WorkSource workSource, Message rspMsg)541 public void getCellIdentity(WorkSource workSource, Message rspMsg) { 542 mSST.requestCellIdentity(workSource, rspMsg); 543 } 544 545 @UnsupportedAppUsage 546 @Override getState()547 public PhoneConstants.State getState() { 548 if (mImsPhone != null) { 549 PhoneConstants.State imsState = mImsPhone.getState(); 550 if (imsState != PhoneConstants.State.IDLE) { 551 return imsState; 552 } 553 } 554 555 return mCT.mState; 556 } 557 558 @UnsupportedAppUsage 559 @Override getPhoneType()560 public int getPhoneType() { 561 if (mPrecisePhoneType == PhoneConstants.PHONE_TYPE_GSM) { 562 return PhoneConstants.PHONE_TYPE_GSM; 563 } else { 564 return PhoneConstants.PHONE_TYPE_CDMA; 565 } 566 } 567 568 @Override getServiceStateTracker()569 public ServiceStateTracker getServiceStateTracker() { 570 return mSST; 571 } 572 573 @Override getEmergencyNumberTracker()574 public EmergencyNumberTracker getEmergencyNumberTracker() { 575 return mEmergencyNumberTracker; 576 } 577 578 @UnsupportedAppUsage 579 @Override getCallTracker()580 public CallTracker getCallTracker() { 581 return mCT; 582 } 583 584 @Override getTransportManager()585 public TransportManager getTransportManager() { 586 return mTransportManager; 587 } 588 589 @Override getDeviceStateMonitor()590 public DeviceStateMonitor getDeviceStateMonitor() { 591 return mDeviceStateMonitor; 592 } 593 594 @Override getDisplayInfoController()595 public DisplayInfoController getDisplayInfoController() { 596 return mDisplayInfoController; 597 } 598 599 @Override updateVoiceMail()600 public void updateVoiceMail() { 601 if (isPhoneTypeGsm()) { 602 int countVoiceMessages = 0; 603 IccRecords r = mIccRecords.get(); 604 if (r != null) { 605 // get voice mail count from SIM 606 countVoiceMessages = r.getVoiceMessageCount(); 607 } 608 if (countVoiceMessages == IccRecords.DEFAULT_VOICE_MESSAGE_COUNT) { 609 countVoiceMessages = getStoredVoiceMessageCount(); 610 } 611 logd("updateVoiceMail countVoiceMessages = " + countVoiceMessages 612 + " subId " + getSubId()); 613 setVoiceMessageCount(countVoiceMessages); 614 } else { 615 setVoiceMessageCount(getStoredVoiceMessageCount()); 616 } 617 } 618 619 @Override 620 public List<? extends MmiCode> getPendingMmiCodes()621 getPendingMmiCodes() { 622 return mPendingMMIs; 623 } 624 getActiveDcTrackerForApn(@onNull String apnType)625 private @NonNull DcTracker getActiveDcTrackerForApn(@NonNull String apnType) { 626 int currentTransport = mTransportManager.getCurrentTransport( 627 ApnSetting.getApnTypesBitmaskFromString(apnType)); 628 return getDcTracker(currentTransport); 629 } 630 631 @Override getPreciseDataConnectionState(String apnType)632 public PreciseDataConnectionState getPreciseDataConnectionState(String apnType) { 633 // If we are OOS, then all data connections are null. 634 // FIXME: we need to figure out how to report the EIMS PDN connectivity here, which 635 // should imply emergency attach - today emergency attach is unknown at the AP, 636 // so, we take a guess. 637 boolean isEmergencyData = isPhoneTypeGsm() 638 && apnType.equals(PhoneConstants.APN_TYPE_EMERGENCY); 639 640 if (mSST == null 641 || ((mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) 642 && !isEmergencyData)) { 643 return new PreciseDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 644 TelephonyManager.NETWORK_TYPE_UNKNOWN, 645 ApnSetting.getApnTypesBitmaskFromString(apnType), 646 apnType, null, DataFailCause.NONE, null); 647 } 648 649 // must never be null 650 final DcTracker dctForApn = getActiveDcTrackerForApn(apnType); 651 652 int networkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; 653 // Always non-null 654 ServiceState ss = getServiceState(); 655 if (ss != null) { 656 networkType = ss.getDataNetworkType(); 657 } 658 659 return dctForApn.getPreciseDataConnectionState(apnType, isDataSuspended(), networkType); 660 } 661 isDataSuspended()662 boolean isDataSuspended() { 663 return mCT.mState != PhoneConstants.State.IDLE && !mSST.isConcurrentVoiceAndDataAllowed(); 664 } 665 666 @Override getDataConnectionState(String apnType)667 public PhoneConstants.DataState getDataConnectionState(String apnType) { 668 PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED; 669 670 if (mSST == null) { 671 // Radio Technology Change is ongoing, dispose() and removeReferences() have 672 // already been called 673 674 ret = PhoneConstants.DataState.DISCONNECTED; 675 } else if (mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE 676 && (isPhoneTypeCdma() || isPhoneTypeCdmaLte() || 677 (isPhoneTypeGsm() && !apnType.equals(PhoneConstants.APN_TYPE_EMERGENCY)))) { 678 // If we're out of service, open TCP sockets may still work 679 // but no data will flow 680 681 // Emergency APN is available even in Out Of Service 682 // Pass the actual State of EPDN 683 684 ret = PhoneConstants.DataState.DISCONNECTED; 685 } else { /* mSST.gprsState == ServiceState.STATE_IN_SERVICE */ 686 int currentTransport = mTransportManager.getCurrentTransport( 687 ApnSetting.getApnTypesBitmaskFromString(apnType)); 688 if (getDcTracker(currentTransport) != null) { 689 switch (getDcTracker(currentTransport).getState(apnType)) { 690 case CONNECTED: 691 case DISCONNECTING: 692 if (isDataSuspended()) { 693 ret = PhoneConstants.DataState.SUSPENDED; 694 } else { 695 ret = PhoneConstants.DataState.CONNECTED; 696 } 697 break; 698 case CONNECTING: 699 ret = PhoneConstants.DataState.CONNECTING; 700 break; 701 default: 702 ret = PhoneConstants.DataState.DISCONNECTED; 703 } 704 } 705 } 706 707 logd("getDataConnectionState apnType=" + apnType + " ret=" + ret); 708 return ret; 709 } 710 711 @Override getDataActivityState()712 public DataActivityState getDataActivityState() { 713 DataActivityState ret = DataActivityState.NONE; 714 715 if (mSST.getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE 716 && getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) != null) { 717 switch (getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).getActivity()) { 718 case DATAIN: 719 ret = DataActivityState.DATAIN; 720 break; 721 722 case DATAOUT: 723 ret = DataActivityState.DATAOUT; 724 break; 725 726 case DATAINANDOUT: 727 ret = DataActivityState.DATAINANDOUT; 728 break; 729 730 case DORMANT: 731 ret = DataActivityState.DORMANT; 732 break; 733 734 default: 735 ret = DataActivityState.NONE; 736 break; 737 } 738 } 739 740 return ret; 741 } 742 743 /** 744 * Notify any interested party of a Phone state change 745 * {@link com.android.internal.telephony.PhoneConstants.State} 746 */ notifyPhoneStateChanged()747 public void notifyPhoneStateChanged() { 748 mNotifier.notifyPhoneState(this); 749 } 750 751 /** 752 * Notify registrants of a change in the call state. This notifies changes in 753 * {@link com.android.internal.telephony.Call.State}. Use this when changes 754 * in the precise call state are needed, else use notifyPhoneStateChanged. 755 */ 756 @UnsupportedAppUsage notifyPreciseCallStateChanged()757 public void notifyPreciseCallStateChanged() { 758 /* we'd love it if this was package-scoped*/ 759 super.notifyPreciseCallStateChangedP(); 760 } 761 notifyNewRingingConnection(Connection c)762 public void notifyNewRingingConnection(Connection c) { 763 super.notifyNewRingingConnectionP(c); 764 } 765 notifyDisconnect(Connection cn)766 public void notifyDisconnect(Connection cn) { 767 mDisconnectRegistrants.notifyResult(cn); 768 769 mNotifier.notifyDisconnectCause(this, cn.getDisconnectCause(), 770 cn.getPreciseDisconnectCause()); 771 } 772 notifyUnknownConnection(Connection cn)773 public void notifyUnknownConnection(Connection cn) { 774 super.notifyUnknownConnectionP(cn); 775 } 776 777 @Override isInEmergencyCall()778 public boolean isInEmergencyCall() { 779 if (isPhoneTypeGsm()) { 780 return false; 781 } else { 782 return mCT.isInEmergencyCall(); 783 } 784 } 785 786 @Override setIsInEmergencyCall()787 protected void setIsInEmergencyCall() { 788 if (!isPhoneTypeGsm()) { 789 mCT.setIsInEmergencyCall(); 790 } 791 } 792 793 @Override isInEmergencySmsMode()794 public boolean isInEmergencySmsMode() { 795 return super.isInEmergencySmsMode() 796 || (mImsPhone != null && mImsPhone.isInEmergencySmsMode()); 797 } 798 799 //CDMA sendEmergencyCallbackModeChange()800 private void sendEmergencyCallbackModeChange(){ 801 //Send an Intent 802 Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 803 intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_ECM_STATE, isInEcm()); 804 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, getPhoneId()); 805 ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL); 806 logi("sendEmergencyCallbackModeChange"); 807 } 808 809 @Override sendEmergencyCallStateChange(boolean callActive)810 public void sendEmergencyCallStateChange(boolean callActive) { 811 if (!isPhoneTypeCdma()) { 812 // It possible that this method got called from ImsPhoneCallTracker# 813 logi("sendEmergencyCallStateChange - skip for non-cdma"); 814 return; 815 } 816 if (mBroadcastEmergencyCallStateChanges) { 817 Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALL_STATE_CHANGED); 818 intent.putExtra(TelephonyManager.EXTRA_PHONE_IN_EMERGENCY_CALL, callActive); 819 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, getPhoneId()); 820 ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_ALL); 821 if (DBG) Rlog.d(LOG_TAG, "sendEmergencyCallStateChange: callActive " + callActive); 822 } 823 } 824 825 @Override setBroadcastEmergencyCallStateChanges(boolean broadcast)826 public void setBroadcastEmergencyCallStateChanges(boolean broadcast) { 827 mBroadcastEmergencyCallStateChanges = broadcast; 828 } 829 notifySuppServiceFailed(SuppService code)830 public void notifySuppServiceFailed(SuppService code) { 831 mSuppServiceFailedRegistrants.notifyResult(code); 832 } 833 834 @UnsupportedAppUsage notifyServiceStateChanged(ServiceState ss)835 public void notifyServiceStateChanged(ServiceState ss) { 836 super.notifyServiceStateChangedP(ss); 837 } 838 839 /** 840 * Notify that the cell location has changed. 841 * 842 * @param cellIdentity the new CellIdentity 843 */ notifyLocationChanged(CellIdentity cellIdentity)844 public void notifyLocationChanged(CellIdentity cellIdentity) { 845 mNotifier.notifyCellLocation(this, cellIdentity); 846 } 847 848 @Override notifyCallForwardingIndicator()849 public void notifyCallForwardingIndicator() { 850 mNotifier.notifyCallForwardingChanged(this); 851 } 852 853 @Override registerForSuppServiceNotification( Handler h, int what, Object obj)854 public void registerForSuppServiceNotification( 855 Handler h, int what, Object obj) { 856 mSsnRegistrants.addUnique(h, what, obj); 857 if (mSsnRegistrants.size() == 1) mCi.setSuppServiceNotifications(true, null); 858 } 859 860 @Override unregisterForSuppServiceNotification(Handler h)861 public void unregisterForSuppServiceNotification(Handler h) { 862 mSsnRegistrants.remove(h); 863 if (mSsnRegistrants.size() == 0) mCi.setSuppServiceNotifications(false, null); 864 } 865 866 @Override registerForSimRecordsLoaded(Handler h, int what, Object obj)867 public void registerForSimRecordsLoaded(Handler h, int what, Object obj) { 868 mSimRecordsLoadedRegistrants.addUnique(h, what, obj); 869 } 870 871 @Override unregisterForSimRecordsLoaded(Handler h)872 public void unregisterForSimRecordsLoaded(Handler h) { 873 mSimRecordsLoadedRegistrants.remove(h); 874 } 875 876 @Override acceptCall(int videoState)877 public void acceptCall(int videoState) throws CallStateException { 878 Phone imsPhone = mImsPhone; 879 if ( imsPhone != null && imsPhone.getRingingCall().isRinging() ) { 880 imsPhone.acceptCall(videoState); 881 } else { 882 mCT.acceptCall(); 883 } 884 } 885 886 @Override rejectCall()887 public void rejectCall() throws CallStateException { 888 mCT.rejectCall(); 889 } 890 891 @Override switchHoldingAndActive()892 public void switchHoldingAndActive() throws CallStateException { 893 mCT.switchWaitingOrHoldingAndActive(); 894 } 895 896 @Override getIccSerialNumber()897 public String getIccSerialNumber() { 898 IccRecords r = mIccRecords.get(); 899 if (!isPhoneTypeGsm() && r == null) { 900 // to get ICCID form SIMRecords because it is on MF. 901 r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP); 902 } 903 return (r != null) ? r.getIccId() : null; 904 } 905 906 @Override getFullIccSerialNumber()907 public String getFullIccSerialNumber() { 908 IccRecords r = mIccRecords.get(); 909 if (!isPhoneTypeGsm() && r == null) { 910 // to get ICCID form SIMRecords because it is on MF. 911 r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP); 912 } 913 return (r != null) ? r.getFullIccId() : null; 914 } 915 916 @Override canConference()917 public boolean canConference() { 918 if (mImsPhone != null && mImsPhone.canConference()) { 919 return true; 920 } 921 if (isPhoneTypeGsm()) { 922 return mCT.canConference(); 923 } else { 924 loge("canConference: not possible in CDMA"); 925 return false; 926 } 927 } 928 929 @Override conference()930 public void conference() { 931 if (mImsPhone != null && mImsPhone.canConference()) { 932 logd("conference() - delegated to IMS phone"); 933 try { 934 mImsPhone.conference(); 935 } catch (CallStateException e) { 936 loge(e.toString()); 937 } 938 return; 939 } 940 if (isPhoneTypeGsm()) { 941 mCT.conference(); 942 } else { 943 // three way calls in CDMA will be handled by feature codes 944 loge("conference: not possible in CDMA"); 945 } 946 } 947 948 @Override dispose()949 public void dispose() { 950 // Note: this API is currently never called. We are defining actions here in case 951 // we need to dispose GsmCdmaPhone/Phone object. 952 super.dispose(); 953 SubscriptionController.getInstance().unregisterForUiccAppsEnabled(this); 954 } 955 956 @Override enableEnhancedVoicePrivacy(boolean enable, Message onComplete)957 public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) { 958 if (isPhoneTypeGsm()) { 959 loge("enableEnhancedVoicePrivacy: not expected on GSM"); 960 } else { 961 mCi.setPreferredVoicePrivacy(enable, onComplete); 962 } 963 } 964 965 @Override getEnhancedVoicePrivacy(Message onComplete)966 public void getEnhancedVoicePrivacy(Message onComplete) { 967 if (isPhoneTypeGsm()) { 968 loge("getEnhancedVoicePrivacy: not expected on GSM"); 969 } else { 970 mCi.getPreferredVoicePrivacy(onComplete); 971 } 972 } 973 974 @Override clearDisconnected()975 public void clearDisconnected() { 976 mCT.clearDisconnected(); 977 } 978 979 @Override canTransfer()980 public boolean canTransfer() { 981 if (isPhoneTypeGsm()) { 982 return mCT.canTransfer(); 983 } else { 984 loge("canTransfer: not possible in CDMA"); 985 return false; 986 } 987 } 988 989 @Override explicitCallTransfer()990 public void explicitCallTransfer() { 991 if (isPhoneTypeGsm()) { 992 mCT.explicitCallTransfer(); 993 } else { 994 loge("explicitCallTransfer: not possible in CDMA"); 995 } 996 } 997 998 @Override getForegroundCall()999 public GsmCdmaCall getForegroundCall() { 1000 return mCT.mForegroundCall; 1001 } 1002 1003 @Override getBackgroundCall()1004 public GsmCdmaCall getBackgroundCall() { 1005 return mCT.mBackgroundCall; 1006 } 1007 1008 @Override getRingingCall()1009 public Call getRingingCall() { 1010 Phone imsPhone = mImsPhone; 1011 // It returns the ringing call of ImsPhone if the ringing call of GSMPhone isn't ringing. 1012 // In CallManager.registerPhone(), it always registers ringing call of ImsPhone, because 1013 // the ringing call of GSMPhone isn't ringing. Consequently, it can't answer GSM call 1014 // successfully by invoking TelephonyManager.answerRingingCall() since the implementation 1015 // in PhoneInterfaceManager.answerRingingCallInternal() could not get the correct ringing 1016 // call from CallManager. So we check the ringing call state of imsPhone first as 1017 // accpetCall() does. 1018 if ( imsPhone != null && imsPhone.getRingingCall().isRinging()) { 1019 return imsPhone.getRingingCall(); 1020 } 1021 //It returns the ringing connections which during SRVCC handover 1022 if (!mCT.mRingingCall.isRinging() 1023 && mCT.getRingingHandoverConnection() != null 1024 && mCT.getRingingHandoverConnection().getCall() != null 1025 && mCT.getRingingHandoverConnection().getCall().isRinging()) { 1026 return mCT.getRingingHandoverConnection().getCall(); 1027 } 1028 return mCT.mRingingCall; 1029 } 1030 1031 /** 1032 * ImsService reports "IN_SERVICE" for its voice registration state even if the device 1033 * has lost the physical link to the tower. This helper method merges the IMS and modem 1034 * ServiceState, only overriding the voice registration state when we are registered to IMS. In 1035 * this case the voice registration state may be "OUT_OF_SERVICE", so override the voice 1036 * registration state with the data registration state. 1037 */ mergeServiceStates(ServiceState baseSs, ServiceState imsSs)1038 private ServiceState mergeServiceStates(ServiceState baseSs, ServiceState imsSs) { 1039 // No need to merge states if the baseSs is IN_SERVICE. 1040 if (baseSs.getState() == ServiceState.STATE_IN_SERVICE) { 1041 return baseSs; 1042 } 1043 // "IN_SERVICE" in this case means IMS is registered. 1044 if (imsSs.getState() != ServiceState.STATE_IN_SERVICE) { 1045 return baseSs; 1046 } 1047 1048 ServiceState newSs = new ServiceState(baseSs); 1049 // Voice override for IMS case. In this case, voice registration is OUT_OF_SERVICE, but 1050 // IMS is available, so use data registration state as a basis for determining 1051 // whether or not the physical link is available. 1052 newSs.setVoiceRegState(baseSs.getDataRegistrationState()); 1053 newSs.setEmergencyOnly(false); // only get here if voice is IN_SERVICE 1054 return newSs; 1055 } 1056 handleCallDeflectionIncallSupplementaryService( String dialString)1057 private boolean handleCallDeflectionIncallSupplementaryService( 1058 String dialString) { 1059 if (dialString.length() > 1) { 1060 return false; 1061 } 1062 1063 if (getRingingCall().getState() != GsmCdmaCall.State.IDLE) { 1064 if (DBG) logd("MmiCode 0: rejectCall"); 1065 try { 1066 mCT.rejectCall(); 1067 } catch (CallStateException e) { 1068 if (DBG) Rlog.d(LOG_TAG, 1069 "reject failed", e); 1070 notifySuppServiceFailed(Phone.SuppService.REJECT); 1071 } 1072 } else if (getBackgroundCall().getState() != GsmCdmaCall.State.IDLE) { 1073 if (DBG) logd("MmiCode 0: hangupWaitingOrBackground"); 1074 mCT.hangupWaitingOrBackground(); 1075 } 1076 1077 return true; 1078 } 1079 1080 //GSM handleCallWaitingIncallSupplementaryService(String dialString)1081 private boolean handleCallWaitingIncallSupplementaryService(String dialString) { 1082 int len = dialString.length(); 1083 1084 if (len > 2) { 1085 return false; 1086 } 1087 1088 GsmCdmaCall call = getForegroundCall(); 1089 1090 try { 1091 if (len > 1) { 1092 char ch = dialString.charAt(1); 1093 int callIndex = ch - '0'; 1094 1095 if (callIndex >= 1 && callIndex <= GsmCdmaCallTracker.MAX_CONNECTIONS_GSM) { 1096 if (DBG) logd("MmiCode 1: hangupConnectionByIndex " + callIndex); 1097 mCT.hangupConnectionByIndex(call, callIndex); 1098 } 1099 } else { 1100 if (call.getState() != GsmCdmaCall.State.IDLE) { 1101 if (DBG) logd("MmiCode 1: hangup foreground"); 1102 //mCT.hangupForegroundResumeBackground(); 1103 mCT.hangup(call); 1104 } else { 1105 if (DBG) logd("MmiCode 1: switchWaitingOrHoldingAndActive"); 1106 mCT.switchWaitingOrHoldingAndActive(); 1107 } 1108 } 1109 } catch (CallStateException e) { 1110 if (DBG) Rlog.d(LOG_TAG, 1111 "hangup failed", e); 1112 notifySuppServiceFailed(Phone.SuppService.HANGUP); 1113 } 1114 1115 return true; 1116 } 1117 handleCallHoldIncallSupplementaryService(String dialString)1118 private boolean handleCallHoldIncallSupplementaryService(String dialString) { 1119 int len = dialString.length(); 1120 1121 if (len > 2) { 1122 return false; 1123 } 1124 1125 GsmCdmaCall call = getForegroundCall(); 1126 1127 if (len > 1) { 1128 try { 1129 char ch = dialString.charAt(1); 1130 int callIndex = ch - '0'; 1131 GsmCdmaConnection conn = mCT.getConnectionByIndex(call, callIndex); 1132 1133 // GsmCdma index starts at 1, up to 5 connections in a call, 1134 if (conn != null && callIndex >= 1 && callIndex <= GsmCdmaCallTracker.MAX_CONNECTIONS_GSM) { 1135 if (DBG) logd("MmiCode 2: separate call " + callIndex); 1136 mCT.separate(conn); 1137 } else { 1138 if (DBG) logd("separate: invalid call index " + callIndex); 1139 notifySuppServiceFailed(Phone.SuppService.SEPARATE); 1140 } 1141 } catch (CallStateException e) { 1142 if (DBG) Rlog.d(LOG_TAG, "separate failed", e); 1143 notifySuppServiceFailed(Phone.SuppService.SEPARATE); 1144 } 1145 } else { 1146 try { 1147 if (getRingingCall().getState() != GsmCdmaCall.State.IDLE) { 1148 if (DBG) logd("MmiCode 2: accept ringing call"); 1149 mCT.acceptCall(); 1150 } else { 1151 if (DBG) logd("MmiCode 2: switchWaitingOrHoldingAndActive"); 1152 mCT.switchWaitingOrHoldingAndActive(); 1153 } 1154 } catch (CallStateException e) { 1155 if (DBG) Rlog.d(LOG_TAG, "switch failed", e); 1156 notifySuppServiceFailed(Phone.SuppService.SWITCH); 1157 } 1158 } 1159 1160 return true; 1161 } 1162 handleMultipartyIncallSupplementaryService(String dialString)1163 private boolean handleMultipartyIncallSupplementaryService(String dialString) { 1164 if (dialString.length() > 1) { 1165 return false; 1166 } 1167 1168 if (DBG) logd("MmiCode 3: merge calls"); 1169 conference(); 1170 return true; 1171 } 1172 handleEctIncallSupplementaryService(String dialString)1173 private boolean handleEctIncallSupplementaryService(String dialString) { 1174 1175 int len = dialString.length(); 1176 1177 if (len != 1) { 1178 return false; 1179 } 1180 1181 if (DBG) logd("MmiCode 4: explicit call transfer"); 1182 explicitCallTransfer(); 1183 return true; 1184 } 1185 handleCcbsIncallSupplementaryService(String dialString)1186 private boolean handleCcbsIncallSupplementaryService(String dialString) { 1187 if (dialString.length() > 1) { 1188 return false; 1189 } 1190 1191 Rlog.i(LOG_TAG, "MmiCode 5: CCBS not supported!"); 1192 // Treat it as an "unknown" service. 1193 notifySuppServiceFailed(Phone.SuppService.UNKNOWN); 1194 return true; 1195 } 1196 1197 @UnsupportedAppUsage 1198 @Override handleInCallMmiCommands(String dialString)1199 public boolean handleInCallMmiCommands(String dialString) throws CallStateException { 1200 if (!isPhoneTypeGsm()) { 1201 loge("method handleInCallMmiCommands is NOT supported in CDMA!"); 1202 return false; 1203 } 1204 1205 Phone imsPhone = mImsPhone; 1206 if (imsPhone != null 1207 && imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE) { 1208 return imsPhone.handleInCallMmiCommands(dialString); 1209 } 1210 1211 if (!isInCall()) { 1212 return false; 1213 } 1214 1215 if (TextUtils.isEmpty(dialString)) { 1216 return false; 1217 } 1218 1219 boolean result = false; 1220 char ch = dialString.charAt(0); 1221 switch (ch) { 1222 case '0': 1223 result = handleCallDeflectionIncallSupplementaryService(dialString); 1224 break; 1225 case '1': 1226 result = handleCallWaitingIncallSupplementaryService(dialString); 1227 break; 1228 case '2': 1229 result = handleCallHoldIncallSupplementaryService(dialString); 1230 break; 1231 case '3': 1232 result = handleMultipartyIncallSupplementaryService(dialString); 1233 break; 1234 case '4': 1235 result = handleEctIncallSupplementaryService(dialString); 1236 break; 1237 case '5': 1238 result = handleCcbsIncallSupplementaryService(dialString); 1239 break; 1240 default: 1241 break; 1242 } 1243 1244 return result; 1245 } 1246 1247 @UnsupportedAppUsage isInCall()1248 public boolean isInCall() { 1249 GsmCdmaCall.State foregroundCallState = getForegroundCall().getState(); 1250 GsmCdmaCall.State backgroundCallState = getBackgroundCall().getState(); 1251 GsmCdmaCall.State ringingCallState = getRingingCall().getState(); 1252 1253 return (foregroundCallState.isAlive() || 1254 backgroundCallState.isAlive() || 1255 ringingCallState.isAlive()); 1256 } 1257 useImsForCall(DialArgs dialArgs)1258 private boolean useImsForCall(DialArgs dialArgs) { 1259 return isImsUseEnabled() 1260 && mImsPhone != null 1261 && (mImsPhone.isVolteEnabled() || mImsPhone.isWifiCallingEnabled() || 1262 (mImsPhone.isVideoEnabled() && VideoProfile.isVideo(dialArgs.videoState))) 1263 && (mImsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE); 1264 } 1265 1266 @Override startConference(String[] participantsToDial, DialArgs dialArgs)1267 public Connection startConference(String[] participantsToDial, DialArgs dialArgs) 1268 throws CallStateException { 1269 Phone imsPhone = mImsPhone; 1270 boolean useImsForCall = useImsForCall(dialArgs); 1271 logd("useImsForCall=" + useImsForCall); 1272 if (useImsForCall) { 1273 try { 1274 if (DBG) logd("Trying IMS PS Conference call"); 1275 return imsPhone.startConference(participantsToDial, dialArgs); 1276 } catch (CallStateException e) { 1277 if (DBG) logd("IMS PS conference call exception " + e + 1278 "useImsForCall =" + useImsForCall + ", imsPhone =" + imsPhone); 1279 CallStateException ce = new CallStateException(e.getError(), e.getMessage()); 1280 ce.setStackTrace(e.getStackTrace()); 1281 throw ce; 1282 } 1283 } else { 1284 throw new CallStateException( 1285 CallStateException.ERROR_OUT_OF_SERVICE, 1286 "cannot dial conference call in out of service"); 1287 } 1288 } 1289 1290 @Override dial(String dialString, @NonNull DialArgs dialArgs)1291 public Connection dial(String dialString, @NonNull DialArgs dialArgs) 1292 throws CallStateException { 1293 if (!isPhoneTypeGsm() && dialArgs.uusInfo != null) { 1294 throw new CallStateException("Sending UUS information NOT supported in CDMA!"); 1295 } 1296 String possibleEmergencyNumber = checkForTestEmergencyNumber(dialString); 1297 // Record if the dialed number was swapped for a test emergency number. 1298 boolean isDialedNumberSwapped = !TextUtils.equals(dialString, possibleEmergencyNumber); 1299 if (isDialedNumberSwapped) { 1300 logi("dialString replaced for possible emergency number: " + dialString + " -> " 1301 + possibleEmergencyNumber); 1302 dialString = possibleEmergencyNumber; 1303 } 1304 boolean isEmergency = PhoneNumberUtils.isEmergencyNumber(getSubId(), dialString); 1305 Phone imsPhone = mImsPhone; 1306 mDialArgs = dialArgs; 1307 1308 CarrierConfigManager configManager = 1309 (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1310 boolean alwaysTryImsForEmergencyCarrierConfig = configManager.getConfigForSubId(getSubId()) 1311 .getBoolean(CarrierConfigManager.KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL); 1312 1313 /** Check if the call is Wireless Priority Service call */ 1314 boolean isWpsCall = dialString != null ? dialString.startsWith(PREFIX_WPS) : false; 1315 boolean allowWpsOverIms = configManager.getConfigForSubId(getSubId()) 1316 .getBoolean(CarrierConfigManager.KEY_SUPPORT_WPS_OVER_IMS_BOOL); 1317 1318 boolean useImsForEmergency = imsPhone != null 1319 && isEmergency 1320 && alwaysTryImsForEmergencyCarrierConfig 1321 && ImsManager.getInstance(mContext, mPhoneId).isNonTtyOrTtyOnVolteEnabled() 1322 && imsPhone.isImsAvailable(); 1323 1324 String dialPart = PhoneNumberUtils.extractNetworkPortionAlt(PhoneNumberUtils. 1325 stripSeparators(dialString)); 1326 boolean isMmiCode = (dialPart.startsWith("*") || dialPart.startsWith("#")) 1327 && dialPart.endsWith("#"); 1328 boolean isSuppServiceCode = ImsPhoneMmiCode.isSuppServiceCodes(dialPart, this); 1329 boolean isPotentialUssdCode = isMmiCode && !isSuppServiceCode; 1330 boolean useImsForUt = imsPhone != null && imsPhone.isUtEnabled(); 1331 boolean useImsForCall = useImsForCall(dialArgs) 1332 && (isWpsCall ? allowWpsOverIms : true); 1333 1334 if (DBG) { 1335 logd("useImsForCall=" + useImsForCall 1336 + ", isEmergency=" + isEmergency 1337 + ", useImsForEmergency=" + useImsForEmergency 1338 + ", useImsForUt=" + useImsForUt 1339 + ", isUt=" + isMmiCode 1340 + ", isSuppServiceCode=" + isSuppServiceCode 1341 + ", isPotentialUssdCode=" + isPotentialUssdCode 1342 + ", isWpsCall=" + isWpsCall 1343 + ", allowWpsOverIms=" + allowWpsOverIms 1344 + ", imsPhone=" + imsPhone 1345 + ", imsPhone.isVolteEnabled()=" 1346 + ((imsPhone != null) ? imsPhone.isVolteEnabled() : "N/A") 1347 + ", imsPhone.isVowifiEnabled()=" 1348 + ((imsPhone != null) ? imsPhone.isWifiCallingEnabled() : "N/A") 1349 + ", imsPhone.isVideoEnabled()=" 1350 + ((imsPhone != null) ? imsPhone.isVideoEnabled() : "N/A") 1351 + ", imsPhone.getServiceState().getState()=" 1352 + ((imsPhone != null) ? imsPhone.getServiceState().getState() : "N/A")); 1353 } 1354 1355 Phone.checkWfcWifiOnlyModeBeforeDial(mImsPhone, mPhoneId, mContext); 1356 1357 if ((useImsForCall && (!isMmiCode || isPotentialUssdCode)) 1358 || (isMmiCode && useImsForUt) 1359 || useImsForEmergency) { 1360 try { 1361 if (DBG) logd("Trying IMS PS call"); 1362 return imsPhone.dial(dialString, dialArgs); 1363 } catch (CallStateException e) { 1364 if (DBG) logd("IMS PS call exception " + e + 1365 "useImsForCall =" + useImsForCall + ", imsPhone =" + imsPhone); 1366 // Do not throw a CallStateException and instead fall back to Circuit switch 1367 // for emergency calls and MMI codes. 1368 if (Phone.CS_FALLBACK.equals(e.getMessage()) || isEmergency) { 1369 logi("IMS call failed with Exception: " + e.getMessage() + ". Falling back " 1370 + "to CS."); 1371 } else { 1372 CallStateException ce = new CallStateException(e.getError(), e.getMessage()); 1373 ce.setStackTrace(e.getStackTrace()); 1374 throw ce; 1375 } 1376 } 1377 } 1378 1379 if (mSST != null && mSST.mSS.getState() == ServiceState.STATE_OUT_OF_SERVICE 1380 && mSST.mSS.getDataRegistrationState() != ServiceState.STATE_IN_SERVICE 1381 && !isEmergency) { 1382 throw new CallStateException("cannot dial in current state"); 1383 } 1384 // Check non-emergency voice CS call - shouldn't dial when POWER_OFF 1385 if (mSST != null && mSST.mSS.getState() == ServiceState.STATE_POWER_OFF /* CS POWER_OFF */ 1386 && !VideoProfile.isVideo(dialArgs.videoState) /* voice call */ 1387 && !isEmergency /* non-emergency call */ 1388 && !(isMmiCode && useImsForUt) /* not UT */ 1389 /* If config_allow_ussd_over_ims is false, USSD is sent over the CS pipe instead */ 1390 && !isPotentialUssdCode) { 1391 throw new CallStateException( 1392 CallStateException.ERROR_POWER_OFF, 1393 "cannot dial voice call in airplane mode"); 1394 } 1395 // Check for service before placing non emergency CS voice call. 1396 // Allow dial only if either CS is camped on any RAT (or) PS is in LTE/NR service. 1397 if (mSST != null 1398 && mSST.mSS.getState() == ServiceState.STATE_OUT_OF_SERVICE /* CS out of service */ 1399 && !(mSST.mSS.getDataRegistrationState() == ServiceState.STATE_IN_SERVICE 1400 && ServiceState.isPsOnlyTech( 1401 mSST.mSS.getRilDataRadioTechnology())) /* PS not in LTE/NR */ 1402 && !VideoProfile.isVideo(dialArgs.videoState) /* voice call */ 1403 && !isEmergency /* non-emergency call */ 1404 /* If config_allow_ussd_over_ims is false, USSD is sent over the CS pipe instead */ 1405 && !isPotentialUssdCode) { 1406 throw new CallStateException( 1407 CallStateException.ERROR_OUT_OF_SERVICE, 1408 "cannot dial voice call in out of service"); 1409 } 1410 if (DBG) logd("Trying (non-IMS) CS call"); 1411 if (isDialedNumberSwapped && isEmergency) { 1412 // Triggers ECM when CS call ends only for test emergency calls using 1413 // ril.test.emergencynumber. 1414 mIsTestingEmergencyCallbackMode = true; 1415 mCi.testingEmergencyCall(); 1416 } 1417 if (isPhoneTypeGsm()) { 1418 return dialInternal(dialString, new DialArgs.Builder<>() 1419 .setIntentExtras(dialArgs.intentExtras) 1420 .build()); 1421 } else { 1422 return dialInternal(dialString, dialArgs); 1423 } 1424 } 1425 1426 /** 1427 * @return {@code true} if the user should be informed of an attempt to dial an international 1428 * number while on WFC only, {@code false} otherwise. 1429 */ isNotificationOfWfcCallRequired(String dialString)1430 public boolean isNotificationOfWfcCallRequired(String dialString) { 1431 CarrierConfigManager configManager = 1432 (CarrierConfigManager) mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1433 PersistableBundle config = configManager.getConfigForSubId(getSubId()); 1434 1435 // Determine if carrier config indicates that international calls over WFC should trigger a 1436 // notification to the user. This is controlled by carrier configuration and is off by 1437 // default. 1438 boolean shouldNotifyInternationalCallOnWfc = config != null 1439 && config.getBoolean( 1440 CarrierConfigManager.KEY_NOTIFY_INTERNATIONAL_CALL_ON_WFC_BOOL); 1441 1442 if (!shouldNotifyInternationalCallOnWfc) { 1443 return false; 1444 } 1445 1446 Phone imsPhone = mImsPhone; 1447 boolean isEmergency = PhoneNumberUtils.isEmergencyNumber(getSubId(), dialString); 1448 boolean shouldConfirmCall = 1449 // Using IMS 1450 isImsUseEnabled() 1451 && imsPhone != null 1452 // VoLTE not available 1453 && !imsPhone.isVolteEnabled() 1454 // WFC is available 1455 && imsPhone.isWifiCallingEnabled() 1456 && !isEmergency 1457 // Dialing international number 1458 && PhoneNumberUtils.isInternationalNumber(dialString, getCountryIso()); 1459 return shouldConfirmCall; 1460 } 1461 1462 @Override dialInternal(String dialString, DialArgs dialArgs)1463 protected Connection dialInternal(String dialString, DialArgs dialArgs) 1464 throws CallStateException { 1465 return dialInternal(dialString, dialArgs, null); 1466 } 1467 dialInternal(String dialString, DialArgs dialArgs, ResultReceiver wrappedCallback)1468 protected Connection dialInternal(String dialString, DialArgs dialArgs, 1469 ResultReceiver wrappedCallback) 1470 throws CallStateException { 1471 1472 // Need to make sure dialString gets parsed properly 1473 String newDialString = PhoneNumberUtils.stripSeparators(dialString); 1474 1475 if (isPhoneTypeGsm()) { 1476 // handle in-call MMI first if applicable 1477 if (handleInCallMmiCommands(newDialString)) { 1478 return null; 1479 } 1480 1481 // Only look at the Network portion for mmi 1482 String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString); 1483 GsmMmiCode mmi = GsmMmiCode.newFromDialString(networkPortion, this, 1484 mUiccApplication.get(), wrappedCallback); 1485 if (DBG) logd("dialInternal: dialing w/ mmi '" + mmi + "'..."); 1486 1487 if (mmi == null) { 1488 return mCT.dialGsm(newDialString, dialArgs.uusInfo, dialArgs.intentExtras); 1489 } else if (mmi.isTemporaryModeCLIR()) { 1490 return mCT.dialGsm(mmi.mDialingNumber, mmi.getCLIRMode(), dialArgs.uusInfo, 1491 dialArgs.intentExtras); 1492 } else { 1493 mPendingMMIs.add(mmi); 1494 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 1495 mmi.processCode(); 1496 return null; 1497 } 1498 } else { 1499 return mCT.dial(newDialString, dialArgs.intentExtras); 1500 } 1501 } 1502 1503 @Override handlePinMmi(String dialString)1504 public boolean handlePinMmi(String dialString) { 1505 MmiCode mmi; 1506 if (isPhoneTypeGsm()) { 1507 mmi = GsmMmiCode.newFromDialString(dialString, this, mUiccApplication.get()); 1508 } else { 1509 mmi = CdmaMmiCode.newFromDialString(dialString, this, mUiccApplication.get()); 1510 } 1511 1512 if (mmi != null && mmi.isPinPukCommand()) { 1513 mPendingMMIs.add(mmi); 1514 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 1515 try { 1516 mmi.processCode(); 1517 } catch (CallStateException e) { 1518 //do nothing 1519 } 1520 return true; 1521 } 1522 1523 loge("Mmi is null or unrecognized!"); 1524 return false; 1525 } 1526 sendUssdResponse(String ussdRequest, CharSequence message, int returnCode, ResultReceiver wrappedCallback)1527 private void sendUssdResponse(String ussdRequest, CharSequence message, int returnCode, 1528 ResultReceiver wrappedCallback) { 1529 UssdResponse response = new UssdResponse(ussdRequest, message); 1530 Bundle returnData = new Bundle(); 1531 returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response); 1532 wrappedCallback.send(returnCode, returnData); 1533 } 1534 1535 @Override handleUssdRequest(String ussdRequest, ResultReceiver wrappedCallback)1536 public boolean handleUssdRequest(String ussdRequest, ResultReceiver wrappedCallback) { 1537 if (!isPhoneTypeGsm() || mPendingMMIs.size() > 0) { 1538 //todo: replace the generic failure with specific error code. 1539 sendUssdResponse(ussdRequest, null, TelephonyManager.USSD_RETURN_FAILURE, 1540 wrappedCallback ); 1541 return true; 1542 } 1543 1544 // Try over IMS if possible. 1545 Phone imsPhone = mImsPhone; 1546 if ((imsPhone != null) 1547 && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE) 1548 || imsPhone.isUtEnabled())) { 1549 try { 1550 logd("handleUssdRequest: attempting over IMS"); 1551 return imsPhone.handleUssdRequest(ussdRequest, wrappedCallback); 1552 } catch (CallStateException cse) { 1553 if (!CS_FALLBACK.equals(cse.getMessage())) { 1554 return false; 1555 } 1556 // At this point we've tried over IMS but have been informed we need to handover 1557 // back to GSM. 1558 logd("handleUssdRequest: fallback to CS required"); 1559 } 1560 } 1561 1562 // Try USSD over GSM. 1563 try { 1564 dialInternal(ussdRequest, new DialArgs.Builder<>().build(), wrappedCallback); 1565 } catch (Exception e) { 1566 logd("handleUssdRequest: exception" + e); 1567 return false; 1568 } 1569 return true; 1570 } 1571 1572 @Override sendUssdResponse(String ussdMessge)1573 public void sendUssdResponse(String ussdMessge) { 1574 if (isPhoneTypeGsm()) { 1575 GsmMmiCode mmi = GsmMmiCode.newFromUssdUserInput(ussdMessge, this, mUiccApplication.get()); 1576 mPendingMMIs.add(mmi); 1577 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 1578 mmi.sendUssd(ussdMessge); 1579 } else { 1580 loge("sendUssdResponse: not possible in CDMA"); 1581 } 1582 } 1583 1584 @Override sendDtmf(char c)1585 public void sendDtmf(char c) { 1586 if (!PhoneNumberUtils.is12Key(c)) { 1587 loge("sendDtmf called with invalid character '" + c + "'"); 1588 } else { 1589 if (mCT.mState == PhoneConstants.State.OFFHOOK) { 1590 mCi.sendDtmf(c, null); 1591 } 1592 } 1593 } 1594 1595 @Override startDtmf(char c)1596 public void startDtmf(char c) { 1597 if (!PhoneNumberUtils.is12Key(c)) { 1598 loge("startDtmf called with invalid character '" + c + "'"); 1599 } else { 1600 mCi.startDtmf(c, null); 1601 } 1602 } 1603 1604 @Override stopDtmf()1605 public void stopDtmf() { 1606 mCi.stopDtmf(null); 1607 } 1608 1609 @Override sendBurstDtmf(String dtmfString, int on, int off, Message onComplete)1610 public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { 1611 if (isPhoneTypeGsm()) { 1612 loge("[GsmCdmaPhone] sendBurstDtmf() is a CDMA method"); 1613 } else { 1614 boolean check = true; 1615 for (int itr = 0;itr < dtmfString.length(); itr++) { 1616 if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) { 1617 Rlog.e(LOG_TAG, 1618 "sendDtmf called with invalid character '" + dtmfString.charAt(itr)+ "'"); 1619 check = false; 1620 break; 1621 } 1622 } 1623 if (mCT.mState == PhoneConstants.State.OFFHOOK && check) { 1624 mCi.sendBurstDtmf(dtmfString, on, off, onComplete); 1625 } 1626 } 1627 } 1628 1629 @Override setRadioPower(boolean power, boolean forEmergencyCall, boolean isSelectedPhoneForEmergencyCall, boolean forceApply)1630 public void setRadioPower(boolean power, boolean forEmergencyCall, 1631 boolean isSelectedPhoneForEmergencyCall, boolean forceApply) { 1632 mSST.setRadioPower(power, forEmergencyCall, isSelectedPhoneForEmergencyCall, forceApply); 1633 } 1634 storeVoiceMailNumber(String number)1635 private void storeVoiceMailNumber(String number) { 1636 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1637 SharedPreferences.Editor editor = sp.edit(); 1638 setVmSimImsi(getSubscriberId()); 1639 logd("storeVoiceMailNumber: mPrecisePhoneType=" + mPrecisePhoneType + " vmNumber=" 1640 + number); 1641 if (isPhoneTypeGsm()) { 1642 editor.putString(VM_NUMBER + getPhoneId(), number); 1643 editor.apply(); 1644 } else { 1645 editor.putString(VM_NUMBER_CDMA + getPhoneId(), number); 1646 editor.apply(); 1647 } 1648 } 1649 1650 @Override getVoiceMailNumber()1651 public String getVoiceMailNumber() { 1652 String number = null; 1653 if (isPhoneTypeGsm() || mSimRecords != null) { 1654 // Read from the SIM. If its null, try reading from the shared preference area. 1655 IccRecords r = isPhoneTypeGsm() ? mIccRecords.get() : mSimRecords; 1656 number = (r != null) ? r.getVoiceMailNumber() : ""; 1657 if (TextUtils.isEmpty(number)) { 1658 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1659 String spName = isPhoneTypeGsm() ? VM_NUMBER : VM_NUMBER_CDMA; 1660 number = sp.getString(spName + getPhoneId(), null); 1661 logd("getVoiceMailNumber: from " + spName + " number=" + number); 1662 } else { 1663 logd("getVoiceMailNumber: from IccRecords number=" + number); 1664 } 1665 } 1666 if (!isPhoneTypeGsm() && TextUtils.isEmpty(number)) { 1667 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1668 number = sp.getString(VM_NUMBER_CDMA + getPhoneId(), null); 1669 logd("getVoiceMailNumber: from VM_NUMBER_CDMA number=" + number); 1670 } 1671 1672 if (TextUtils.isEmpty(number)) { 1673 CarrierConfigManager configManager = (CarrierConfigManager) 1674 getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); 1675 PersistableBundle b = configManager.getConfigForSubId(getSubId()); 1676 if (b != null) { 1677 String defaultVmNumber = 1678 b.getString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_STRING); 1679 String defaultVmNumberRoaming = 1680 b.getString(CarrierConfigManager.KEY_DEFAULT_VM_NUMBER_ROAMING_STRING); 1681 String defaultVmNumberRoamingAndImsUnregistered = b.getString( 1682 CarrierConfigManager 1683 .KEY_DEFAULT_VM_NUMBER_ROAMING_AND_IMS_UNREGISTERED_STRING); 1684 1685 if (!TextUtils.isEmpty(defaultVmNumber)) number = defaultVmNumber; 1686 if (mSST.mSS.getRoaming()) { 1687 if (!TextUtils.isEmpty(defaultVmNumberRoamingAndImsUnregistered) 1688 && !mSST.isImsRegistered()) { 1689 // roaming and IMS unregistered case if CC configured 1690 number = defaultVmNumberRoamingAndImsUnregistered; 1691 } else if (!TextUtils.isEmpty(defaultVmNumberRoaming)) { 1692 // roaming default case if CC configured 1693 number = defaultVmNumberRoaming; 1694 } 1695 } 1696 } 1697 } 1698 1699 if (TextUtils.isEmpty(number)) { 1700 // Read platform settings for dynamic voicemail number 1701 CarrierConfigManager configManager = (CarrierConfigManager) 1702 getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); 1703 PersistableBundle b = configManager.getConfigForSubId(getSubId()); 1704 if (b != null && b.getBoolean( 1705 CarrierConfigManager.KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL)) { 1706 number = getLine1Number(); 1707 } 1708 } 1709 1710 return number; 1711 } 1712 getVmSimImsi()1713 private String getVmSimImsi() { 1714 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1715 return sp.getString(VM_SIM_IMSI + getPhoneId(), null); 1716 } 1717 setVmSimImsi(String imsi)1718 private void setVmSimImsi(String imsi) { 1719 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1720 SharedPreferences.Editor editor = sp.edit(); 1721 editor.putString(VM_SIM_IMSI + getPhoneId(), imsi); 1722 editor.apply(); 1723 } 1724 1725 @Override getVoiceMailAlphaTag()1726 public String getVoiceMailAlphaTag() { 1727 String ret = ""; 1728 1729 if (isPhoneTypeGsm() || mSimRecords != null) { 1730 IccRecords r = isPhoneTypeGsm() ? mIccRecords.get() : mSimRecords; 1731 1732 ret = (r != null) ? r.getVoiceMailAlphaTag() : ""; 1733 } 1734 1735 if (ret == null || ret.length() == 0) { 1736 return mContext.getText( 1737 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString(); 1738 } 1739 1740 return ret; 1741 } 1742 1743 @Override getDeviceId()1744 public String getDeviceId() { 1745 if (isPhoneTypeGsm()) { 1746 return mImei; 1747 } else { 1748 CarrierConfigManager configManager = (CarrierConfigManager) 1749 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1750 boolean force_imei = configManager.getConfigForSubId(getSubId()) 1751 .getBoolean(CarrierConfigManager.KEY_FORCE_IMEI_BOOL); 1752 if (force_imei) return mImei; 1753 1754 String id = getMeid(); 1755 if ((id == null) || id.matches("^0*$")) { 1756 loge("getDeviceId(): MEID is not initialized use ESN"); 1757 id = getEsn(); 1758 } 1759 return id; 1760 } 1761 } 1762 1763 @Override getDeviceSvn()1764 public String getDeviceSvn() { 1765 if (isPhoneTypeGsm() || isPhoneTypeCdmaLte()) { 1766 return mImeiSv; 1767 } else { 1768 loge("getDeviceSvn(): return 0"); 1769 return "0"; 1770 } 1771 } 1772 1773 @Override getIsimRecords()1774 public IsimRecords getIsimRecords() { 1775 return mIsimUiccRecords; 1776 } 1777 1778 @Override getImei()1779 public String getImei() { 1780 return mImei; 1781 } 1782 1783 @UnsupportedAppUsage 1784 @Override getEsn()1785 public String getEsn() { 1786 if (isPhoneTypeGsm()) { 1787 loge("[GsmCdmaPhone] getEsn() is a CDMA method"); 1788 return "0"; 1789 } else { 1790 return mEsn; 1791 } 1792 } 1793 1794 @Override getMeid()1795 public String getMeid() { 1796 return mMeid; 1797 } 1798 1799 @Override getNai()1800 public String getNai() { 1801 IccRecords r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP2); 1802 if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) { 1803 Rlog.v(LOG_TAG, "IccRecords is " + r); 1804 } 1805 return (r != null) ? r.getNAI() : null; 1806 } 1807 1808 @Override 1809 @Nullable getSubscriberId()1810 public String getSubscriberId() { 1811 String subscriberId = null; 1812 if (isPhoneTypeCdma()) { 1813 subscriberId = mSST.getImsi(); 1814 } else { 1815 // Both Gsm and CdmaLte get the IMSI from Usim. 1816 IccRecords iccRecords = mUiccController.getIccRecords( 1817 mPhoneId, UiccController.APP_FAM_3GPP); 1818 if (iccRecords != null) { 1819 subscriberId = iccRecords.getIMSI(); 1820 } 1821 } 1822 return subscriberId; 1823 } 1824 1825 @Override getCarrierInfoForImsiEncryption(int keyType)1826 public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) { 1827 String operatorNumeric = TelephonyManager.from(mContext) 1828 .getSimOperatorNumericForPhone(mPhoneId); 1829 return CarrierInfoManager.getCarrierInfoForImsiEncryption(keyType, 1830 mContext, operatorNumeric); 1831 } 1832 1833 @Override setCarrierInfoForImsiEncryption(ImsiEncryptionInfo imsiEncryptionInfo)1834 public void setCarrierInfoForImsiEncryption(ImsiEncryptionInfo imsiEncryptionInfo) { 1835 CarrierInfoManager.setCarrierInfoForImsiEncryption(imsiEncryptionInfo, mContext, mPhoneId); 1836 } 1837 1838 @Override getCarrierId()1839 public int getCarrierId() { 1840 return mCarrierResolver.getCarrierId(); 1841 } 1842 1843 @Override getCarrierName()1844 public String getCarrierName() { 1845 return mCarrierResolver.getCarrierName(); 1846 } 1847 1848 @Override getMNOCarrierId()1849 public int getMNOCarrierId() { 1850 return mCarrierResolver.getMnoCarrierId(); 1851 } 1852 1853 @Override getSpecificCarrierId()1854 public int getSpecificCarrierId() { 1855 return mCarrierResolver.getSpecificCarrierId(); 1856 } 1857 1858 @Override getSpecificCarrierName()1859 public String getSpecificCarrierName() { 1860 return mCarrierResolver.getSpecificCarrierName(); 1861 } 1862 1863 @Override resolveSubscriptionCarrierId(String simState)1864 public void resolveSubscriptionCarrierId(String simState) { 1865 mCarrierResolver.resolveSubscriptionCarrierId(simState); 1866 } 1867 1868 @Override getCarrierIdListVersion()1869 public int getCarrierIdListVersion() { 1870 return mCarrierResolver.getCarrierListVersion(); 1871 } 1872 1873 @Override getEmergencyNumberDbVersion()1874 public int getEmergencyNumberDbVersion() { 1875 return getEmergencyNumberTracker().getEmergencyNumberDbVersion(); 1876 } 1877 1878 @Override resetCarrierKeysForImsiEncryption()1879 public void resetCarrierKeysForImsiEncryption() { 1880 mCIM.resetCarrierKeysForImsiEncryption(mContext, mPhoneId); 1881 } 1882 1883 @Override setCarrierTestOverride(String mccmnc, String imsi, String iccid, String gid1, String gid2, String pnn, String spn, String carrierPrivilegeRules, String apn)1884 public void setCarrierTestOverride(String mccmnc, String imsi, String iccid, String gid1, 1885 String gid2, String pnn, String spn, String carrierPrivilegeRules, String apn) { 1886 mCarrierResolver.setTestOverrideApn(apn); 1887 mCarrierResolver.setTestOverrideCarrierPriviledgeRule(carrierPrivilegeRules); 1888 IccRecords r = null; 1889 if (isPhoneTypeGsm()) { 1890 r = mIccRecords.get(); 1891 } else if (isPhoneTypeCdmaLte()) { 1892 r = mSimRecords; 1893 } else { 1894 loge("setCarrierTestOverride fails in CDMA only"); 1895 } 1896 if (r != null) { 1897 r.setCarrierTestOverride(mccmnc, imsi, iccid, gid1, gid2, pnn, spn); 1898 } 1899 } 1900 1901 @Override getGroupIdLevel1()1902 public String getGroupIdLevel1() { 1903 if (isPhoneTypeGsm()) { 1904 IccRecords r = mIccRecords.get(); 1905 return (r != null) ? r.getGid1() : null; 1906 } else if (isPhoneTypeCdma()) { 1907 loge("GID1 is not available in CDMA"); 1908 return null; 1909 } else { //isPhoneTypeCdmaLte() 1910 return (mSimRecords != null) ? mSimRecords.getGid1() : ""; 1911 } 1912 } 1913 1914 @Override getGroupIdLevel2()1915 public String getGroupIdLevel2() { 1916 if (isPhoneTypeGsm()) { 1917 IccRecords r = mIccRecords.get(); 1918 return (r != null) ? r.getGid2() : null; 1919 } else if (isPhoneTypeCdma()) { 1920 loge("GID2 is not available in CDMA"); 1921 return null; 1922 } else { //isPhoneTypeCdmaLte() 1923 return (mSimRecords != null) ? mSimRecords.getGid2() : ""; 1924 } 1925 } 1926 1927 @UnsupportedAppUsage 1928 @Override getLine1Number()1929 public String getLine1Number() { 1930 if (isPhoneTypeGsm()) { 1931 IccRecords r = mIccRecords.get(); 1932 return (r != null) ? r.getMsisdnNumber() : null; 1933 } else { 1934 CarrierConfigManager configManager = (CarrierConfigManager) 1935 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1936 boolean use_usim = configManager.getConfigForSubId(getSubId()).getBoolean( 1937 CarrierConfigManager.KEY_USE_USIM_BOOL); 1938 if (use_usim) { 1939 return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null; 1940 } 1941 return mSST.getMdnNumber(); 1942 } 1943 } 1944 1945 @Override getPlmn()1946 public String getPlmn() { 1947 if (isPhoneTypeGsm()) { 1948 IccRecords r = mIccRecords.get(); 1949 return (r != null) ? r.getPnnHomeName() : null; 1950 } else if (isPhoneTypeCdma()) { 1951 loge("Plmn is not available in CDMA"); 1952 return null; 1953 } else { //isPhoneTypeCdmaLte() 1954 return (mSimRecords != null) ? mSimRecords.getPnnHomeName() : null; 1955 } 1956 } 1957 1958 @Override getCdmaPrlVersion()1959 public String getCdmaPrlVersion() { 1960 return mSST.getPrlVersion(); 1961 } 1962 1963 @Override getCdmaMin()1964 public String getCdmaMin() { 1965 return mSST.getCdmaMin(); 1966 } 1967 1968 @Override isMinInfoReady()1969 public boolean isMinInfoReady() { 1970 return mSST.isMinInfoReady(); 1971 } 1972 1973 @Override getMsisdn()1974 public String getMsisdn() { 1975 if (isPhoneTypeGsm()) { 1976 IccRecords r = mIccRecords.get(); 1977 return (r != null) ? r.getMsisdnNumber() : null; 1978 } else if (isPhoneTypeCdmaLte()) { 1979 return (mSimRecords != null) ? mSimRecords.getMsisdnNumber() : null; 1980 } else { 1981 loge("getMsisdn: not expected on CDMA"); 1982 return null; 1983 } 1984 } 1985 1986 @Override getLine1AlphaTag()1987 public String getLine1AlphaTag() { 1988 if (isPhoneTypeGsm()) { 1989 IccRecords r = mIccRecords.get(); 1990 return (r != null) ? r.getMsisdnAlphaTag() : null; 1991 } else { 1992 loge("getLine1AlphaTag: not possible in CDMA"); 1993 return null; 1994 } 1995 } 1996 1997 @Override setLine1Number(String alphaTag, String number, Message onComplete)1998 public boolean setLine1Number(String alphaTag, String number, Message onComplete) { 1999 if (isPhoneTypeGsm()) { 2000 IccRecords r = mIccRecords.get(); 2001 if (r != null) { 2002 r.setMsisdnNumber(alphaTag, number, onComplete); 2003 return true; 2004 } else { 2005 return false; 2006 } 2007 } else { 2008 loge("setLine1Number: not possible in CDMA"); 2009 return false; 2010 } 2011 } 2012 2013 @Override setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete)2014 public void setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete) { 2015 Message resp; 2016 mVmNumber = voiceMailNumber; 2017 resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete); 2018 2019 IccRecords r = mIccRecords.get(); 2020 2021 if (!isPhoneTypeGsm() && mSimRecords != null) { 2022 r = mSimRecords; 2023 } 2024 2025 if (r != null) { 2026 r.setVoiceMailNumber(alphaTag, mVmNumber, resp); 2027 } 2028 } 2029 2030 @UnsupportedAppUsage isValidCommandInterfaceCFReason(int commandInterfaceCFReason)2031 private boolean isValidCommandInterfaceCFReason (int commandInterfaceCFReason) { 2032 switch (commandInterfaceCFReason) { 2033 case CF_REASON_UNCONDITIONAL: 2034 case CF_REASON_BUSY: 2035 case CF_REASON_NO_REPLY: 2036 case CF_REASON_NOT_REACHABLE: 2037 case CF_REASON_ALL: 2038 case CF_REASON_ALL_CONDITIONAL: 2039 return true; 2040 default: 2041 return false; 2042 } 2043 } 2044 2045 @UnsupportedAppUsage 2046 @Override getSystemProperty(String property, String defValue)2047 public String getSystemProperty(String property, String defValue) { 2048 if (getUnitTestMode()) { 2049 return null; 2050 } 2051 return TelephonyManager.getTelephonyProperty(mPhoneId, property, defValue); 2052 } 2053 2054 @UnsupportedAppUsage isValidCommandInterfaceCFAction(int commandInterfaceCFAction)2055 private boolean isValidCommandInterfaceCFAction (int commandInterfaceCFAction) { 2056 switch (commandInterfaceCFAction) { 2057 case CF_ACTION_DISABLE: 2058 case CF_ACTION_ENABLE: 2059 case CF_ACTION_REGISTRATION: 2060 case CF_ACTION_ERASURE: 2061 return true; 2062 default: 2063 return false; 2064 } 2065 } 2066 2067 @UnsupportedAppUsage isCfEnable(int action)2068 private boolean isCfEnable(int action) { 2069 return (action == CF_ACTION_ENABLE) || (action == CF_ACTION_REGISTRATION); 2070 } 2071 isImsUtEnabledOverCdma()2072 private boolean isImsUtEnabledOverCdma() { 2073 return isPhoneTypeCdmaLte() 2074 && mImsPhone != null 2075 && mImsPhone.isUtEnabled(); 2076 } 2077 isCsRetry(Message onComplete)2078 private boolean isCsRetry(Message onComplete) { 2079 if (onComplete != null) { 2080 return onComplete.getData().getBoolean(CS_FALLBACK_SS, false); 2081 } 2082 return false; 2083 } 2084 2085 @Override useSsOverIms(Message onComplete)2086 public boolean useSsOverIms(Message onComplete) { 2087 boolean isUtEnabled = isUtEnabled(); 2088 2089 Rlog.d(LOG_TAG, "useSsOverIms: isUtEnabled()= " + isUtEnabled + 2090 " isCsRetry(onComplete))= " + isCsRetry(onComplete)); 2091 2092 if (isUtEnabled && !isCsRetry(onComplete)) { 2093 return true; 2094 } 2095 return false; 2096 } 2097 2098 @Override getCallForwardingOption(int commandInterfaceCFReason, Message onComplete)2099 public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) { 2100 getCallForwardingOption(commandInterfaceCFReason, 2101 CommandsInterface.SERVICE_CLASS_VOICE, onComplete); 2102 } 2103 2104 @Override getCallForwardingOption(int commandInterfaceCFReason, int serviceClass, Message onComplete)2105 public void getCallForwardingOption(int commandInterfaceCFReason, int serviceClass, 2106 Message onComplete) { 2107 Phone imsPhone = mImsPhone; 2108 if (useSsOverIms(onComplete)) { 2109 imsPhone.getCallForwardingOption(commandInterfaceCFReason, serviceClass, onComplete); 2110 return; 2111 } 2112 2113 if (isPhoneTypeGsm()) { 2114 if (isValidCommandInterfaceCFReason(commandInterfaceCFReason)) { 2115 if (DBG) logd("requesting call forwarding query."); 2116 Message resp; 2117 if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) { 2118 resp = obtainMessage(EVENT_GET_CALL_FORWARD_DONE, onComplete); 2119 } else { 2120 resp = onComplete; 2121 } 2122 mCi.queryCallForwardStatus(commandInterfaceCFReason, serviceClass, null, resp); 2123 } 2124 } else { 2125 loge("getCallForwardingOption: not possible in CDMA, just return empty result"); 2126 AsyncResult.forMessage(onComplete, makeEmptyCallForward(), null); 2127 onComplete.sendToTarget(); 2128 } 2129 } 2130 2131 @Override setCallForwardingOption(int commandInterfaceCFAction, int commandInterfaceCFReason, String dialingNumber, int timerSeconds, Message onComplete)2132 public void setCallForwardingOption(int commandInterfaceCFAction, 2133 int commandInterfaceCFReason, 2134 String dialingNumber, 2135 int timerSeconds, 2136 Message onComplete) { 2137 setCallForwardingOption(commandInterfaceCFAction, commandInterfaceCFReason, 2138 dialingNumber, CommandsInterface.SERVICE_CLASS_VOICE, timerSeconds, onComplete); 2139 } 2140 2141 @Override setCallForwardingOption(int commandInterfaceCFAction, int commandInterfaceCFReason, String dialingNumber, int serviceClass, int timerSeconds, Message onComplete)2142 public void setCallForwardingOption(int commandInterfaceCFAction, 2143 int commandInterfaceCFReason, 2144 String dialingNumber, 2145 int serviceClass, 2146 int timerSeconds, 2147 Message onComplete) { 2148 Phone imsPhone = mImsPhone; 2149 if (useSsOverIms(onComplete)) { 2150 imsPhone.setCallForwardingOption(commandInterfaceCFAction, commandInterfaceCFReason, 2151 dialingNumber, serviceClass, timerSeconds, onComplete); 2152 return; 2153 } 2154 2155 if (isPhoneTypeGsm()) { 2156 if ((isValidCommandInterfaceCFAction(commandInterfaceCFAction)) && 2157 (isValidCommandInterfaceCFReason(commandInterfaceCFReason))) { 2158 2159 Message resp; 2160 if (commandInterfaceCFReason == CF_REASON_UNCONDITIONAL) { 2161 Cfu cfu = new Cfu(dialingNumber, onComplete); 2162 resp = obtainMessage(EVENT_SET_CALL_FORWARD_DONE, 2163 isCfEnable(commandInterfaceCFAction) ? 1 : 0, 0, cfu); 2164 } else { 2165 resp = onComplete; 2166 } 2167 mCi.setCallForward(commandInterfaceCFAction, 2168 commandInterfaceCFReason, 2169 serviceClass, 2170 dialingNumber, 2171 timerSeconds, 2172 resp); 2173 } 2174 } else { 2175 String formatNumber = GsmCdmaConnection.formatDialString(dialingNumber); 2176 String cfNumber = CdmaMmiCode.getCallForwardingPrefixAndNumber( 2177 commandInterfaceCFAction, commandInterfaceCFReason, formatNumber); 2178 loge("setCallForwardingOption: dial for set call forwarding" 2179 + " prefixWithNumber= " + cfNumber + " number= " + dialingNumber); 2180 2181 PhoneAccountHandle phoneAccountHandle = subscriptionIdToPhoneAccountHandle(getSubId()); 2182 Bundle extras = new Bundle(); 2183 extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); 2184 2185 final TelecomManager telecomManager = TelecomManager.from(mContext); 2186 telecomManager.placeCall(Uri.parse(PhoneAccount.SCHEME_TEL + cfNumber), extras); 2187 2188 AsyncResult.forMessage(onComplete, CommandsInterface.SS_STATUS_UNKNOWN, null); 2189 onComplete.sendToTarget(); 2190 } 2191 } 2192 2193 @Override getCallBarring(String facility, String password, Message onComplete, int serviceClass)2194 public void getCallBarring(String facility, String password, Message onComplete, 2195 int serviceClass) { 2196 Phone imsPhone = mImsPhone; 2197 if (useSsOverIms(onComplete)) { 2198 imsPhone.getCallBarring(facility, password, onComplete, serviceClass); 2199 return; 2200 } 2201 2202 if (isPhoneTypeGsm()) { 2203 mCi.queryFacilityLock(facility, password, serviceClass, onComplete); 2204 } else { 2205 loge("getCallBarringOption: not possible in CDMA"); 2206 } 2207 } 2208 2209 @Override setCallBarring(String facility, boolean lockState, String password, Message onComplete, int serviceClass)2210 public void setCallBarring(String facility, boolean lockState, String password, 2211 Message onComplete, int serviceClass) { 2212 Phone imsPhone = mImsPhone; 2213 if (useSsOverIms(onComplete)) { 2214 imsPhone.setCallBarring(facility, lockState, password, onComplete, serviceClass); 2215 return; 2216 } 2217 2218 if (isPhoneTypeGsm()) { 2219 mCi.setFacilityLock(facility, lockState, password, serviceClass, onComplete); 2220 } else { 2221 loge("setCallBarringOption: not possible in CDMA"); 2222 } 2223 } 2224 2225 /** 2226 * Changes access code used for call barring 2227 * 2228 * @param facility is one of CB_FACILTY_* 2229 * @param oldPwd is old password 2230 * @param newPwd is new password 2231 * @param onComplete is callback message when the action is completed. 2232 */ changeCallBarringPassword(String facility, String oldPwd, String newPwd, Message onComplete)2233 public void changeCallBarringPassword(String facility, String oldPwd, String newPwd, 2234 Message onComplete) { 2235 if (isPhoneTypeGsm()) { 2236 mCi.changeBarringPassword(facility, oldPwd, newPwd, onComplete); 2237 } else { 2238 loge("changeCallBarringPassword: not possible in CDMA"); 2239 } 2240 } 2241 2242 @Override getOutgoingCallerIdDisplay(Message onComplete)2243 public void getOutgoingCallerIdDisplay(Message onComplete) { 2244 Phone imsPhone = mImsPhone; 2245 if (useSsOverIms(onComplete)) { 2246 imsPhone.getOutgoingCallerIdDisplay(onComplete); 2247 return; 2248 } 2249 2250 if (isPhoneTypeGsm()) { 2251 mCi.getCLIR(onComplete); 2252 } else { 2253 loge("getOutgoingCallerIdDisplay: not possible in CDMA"); 2254 AsyncResult.forMessage(onComplete, null, 2255 new CommandException(CommandException.Error.REQUEST_NOT_SUPPORTED)); 2256 onComplete.sendToTarget(); 2257 } 2258 } 2259 2260 @Override setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete)2261 public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) { 2262 Phone imsPhone = mImsPhone; 2263 if (useSsOverIms(onComplete)) { 2264 imsPhone.setOutgoingCallerIdDisplay(commandInterfaceCLIRMode, onComplete); 2265 return; 2266 } 2267 2268 if (isPhoneTypeGsm()) { 2269 // Packing CLIR value in the message. This will be required for 2270 // SharedPreference caching, if the message comes back as part of 2271 // a success response. 2272 mCi.setCLIR(commandInterfaceCLIRMode, 2273 obtainMessage(EVENT_SET_CLIR_COMPLETE, commandInterfaceCLIRMode, 0, onComplete)); 2274 } else { 2275 loge("setOutgoingCallerIdDisplay: not possible in CDMA"); 2276 AsyncResult.forMessage(onComplete, null, 2277 new CommandException(CommandException.Error.REQUEST_NOT_SUPPORTED)); 2278 onComplete.sendToTarget(); 2279 } 2280 } 2281 2282 @Override queryCLIP(Message onComplete)2283 public void queryCLIP(Message onComplete) { 2284 Phone imsPhone = mImsPhone; 2285 if (useSsOverIms(onComplete)) { 2286 imsPhone.queryCLIP(onComplete); 2287 return; 2288 } 2289 2290 if (isPhoneTypeGsm()) { 2291 mCi.queryCLIP(onComplete); 2292 } else { 2293 loge("queryCLIP: not possible in CDMA"); 2294 AsyncResult.forMessage(onComplete, null, 2295 new CommandException(CommandException.Error.REQUEST_NOT_SUPPORTED)); 2296 onComplete.sendToTarget(); 2297 } 2298 } 2299 2300 @Override getCallWaiting(Message onComplete)2301 public void getCallWaiting(Message onComplete) { 2302 Phone imsPhone = mImsPhone; 2303 if (useSsOverIms(onComplete)) { 2304 imsPhone.getCallWaiting(onComplete); 2305 return; 2306 } 2307 2308 if (isPhoneTypeGsm()) { 2309 //As per 3GPP TS 24.083, section 1.6 UE doesn't need to send service 2310 //class parameter in call waiting interrogation to network 2311 mCi.queryCallWaiting(CommandsInterface.SERVICE_CLASS_NONE, onComplete); 2312 } else { 2313 int arr[] = {CommandsInterface.SS_STATUS_UNKNOWN, CommandsInterface.SERVICE_CLASS_NONE}; 2314 AsyncResult.forMessage(onComplete, arr, null); 2315 onComplete.sendToTarget(); 2316 } 2317 } 2318 2319 @Override setCallWaiting(boolean enable, Message onComplete)2320 public void setCallWaiting(boolean enable, Message onComplete) { 2321 int serviceClass = CommandsInterface.SERVICE_CLASS_VOICE; 2322 CarrierConfigManager configManager = (CarrierConfigManager) 2323 getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); 2324 PersistableBundle b = configManager.getConfigForSubId(getSubId()); 2325 if (b != null) { 2326 serviceClass = b.getInt(CarrierConfigManager.KEY_CALL_WAITING_SERVICE_CLASS_INT, 2327 CommandsInterface.SERVICE_CLASS_VOICE); 2328 } 2329 setCallWaiting(enable, serviceClass, onComplete); 2330 } 2331 2332 @Override setCallWaiting(boolean enable, int serviceClass, Message onComplete)2333 public void setCallWaiting(boolean enable, int serviceClass, Message onComplete) { 2334 Phone imsPhone = mImsPhone; 2335 if (useSsOverIms(onComplete)) { 2336 imsPhone.setCallWaiting(enable, onComplete); 2337 return; 2338 } 2339 2340 if (isPhoneTypeGsm()) { 2341 mCi.setCallWaiting(enable, serviceClass, onComplete); 2342 } else { 2343 String cwPrefix = CdmaMmiCode.getCallWaitingPrefix(enable); 2344 Rlog.i(LOG_TAG, "setCallWaiting in CDMA : dial for set call waiting" + " prefix= " + cwPrefix); 2345 2346 PhoneAccountHandle phoneAccountHandle = subscriptionIdToPhoneAccountHandle(getSubId()); 2347 Bundle extras = new Bundle(); 2348 extras.putParcelable(TelecomManager.EXTRA_PHONE_ACCOUNT_HANDLE, phoneAccountHandle); 2349 2350 final TelecomManager telecomManager = TelecomManager.from(mContext); 2351 telecomManager.placeCall(Uri.parse(PhoneAccount.SCHEME_TEL + cwPrefix), extras); 2352 2353 AsyncResult.forMessage(onComplete, CommandsInterface.SS_STATUS_UNKNOWN, null); 2354 onComplete.sendToTarget(); 2355 } 2356 } 2357 2358 @Override getAvailableNetworks(Message response)2359 public void getAvailableNetworks(Message response) { 2360 if (isPhoneTypeGsm() || isPhoneTypeCdmaLte()) { 2361 Message msg = obtainMessage(EVENT_GET_AVAILABLE_NETWORKS_DONE, response); 2362 mCi.getAvailableNetworks(msg); 2363 } else { 2364 loge("getAvailableNetworks: not possible in CDMA"); 2365 } 2366 } 2367 2368 @Override startNetworkScan(NetworkScanRequest nsr, Message response)2369 public void startNetworkScan(NetworkScanRequest nsr, Message response) { 2370 mCi.startNetworkScan(nsr, response); 2371 } 2372 2373 @Override stopNetworkScan(Message response)2374 public void stopNetworkScan(Message response) { 2375 mCi.stopNetworkScan(response); 2376 } 2377 2378 @Override setTTYMode(int ttyMode, Message onComplete)2379 public void setTTYMode(int ttyMode, Message onComplete) { 2380 // Send out the TTY Mode change over RIL as well 2381 super.setTTYMode(ttyMode, onComplete); 2382 if (mImsPhone != null) { 2383 mImsPhone.setTTYMode(ttyMode, onComplete); 2384 } 2385 } 2386 2387 @Override setUiTTYMode(int uiTtyMode, Message onComplete)2388 public void setUiTTYMode(int uiTtyMode, Message onComplete) { 2389 if (mImsPhone != null) { 2390 mImsPhone.setUiTTYMode(uiTtyMode, onComplete); 2391 } 2392 } 2393 2394 @Override setMute(boolean muted)2395 public void setMute(boolean muted) { 2396 mCT.setMute(muted); 2397 } 2398 2399 @Override getMute()2400 public boolean getMute() { 2401 return mCT.getMute(); 2402 } 2403 2404 @Override updateServiceLocation(WorkSource workSource)2405 public void updateServiceLocation(WorkSource workSource) { 2406 mSST.enableSingleLocationUpdate(workSource); 2407 } 2408 2409 @Override enableLocationUpdates()2410 public void enableLocationUpdates() { 2411 mSST.enableLocationUpdates(); 2412 } 2413 2414 @Override disableLocationUpdates()2415 public void disableLocationUpdates() { 2416 mSST.disableLocationUpdates(); 2417 } 2418 2419 @Override getDataRoamingEnabled()2420 public boolean getDataRoamingEnabled() { 2421 if (getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) != null) { 2422 return getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).getDataRoamingEnabled(); 2423 } 2424 return false; 2425 } 2426 2427 @Override setDataRoamingEnabled(boolean enable)2428 public void setDataRoamingEnabled(boolean enable) { 2429 if (getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) != null) { 2430 getDcTracker(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) 2431 .setDataRoamingEnabledByUser(enable); 2432 } 2433 } 2434 2435 @Override registerForCdmaOtaStatusChange(Handler h, int what, Object obj)2436 public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) { 2437 mCi.registerForCdmaOtaProvision(h, what, obj); 2438 } 2439 2440 @Override unregisterForCdmaOtaStatusChange(Handler h)2441 public void unregisterForCdmaOtaStatusChange(Handler h) { 2442 mCi.unregisterForCdmaOtaProvision(h); 2443 } 2444 2445 @Override registerForSubscriptionInfoReady(Handler h, int what, Object obj)2446 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) { 2447 mSST.registerForSubscriptionInfoReady(h, what, obj); 2448 } 2449 2450 @Override unregisterForSubscriptionInfoReady(Handler h)2451 public void unregisterForSubscriptionInfoReady(Handler h) { 2452 mSST.unregisterForSubscriptionInfoReady(h); 2453 } 2454 2455 @UnsupportedAppUsage 2456 @Override setOnEcbModeExitResponse(Handler h, int what, Object obj)2457 public void setOnEcbModeExitResponse(Handler h, int what, Object obj) { 2458 mEcmExitRespRegistrant = new Registrant(h, what, obj); 2459 } 2460 2461 @Override unsetOnEcbModeExitResponse(Handler h)2462 public void unsetOnEcbModeExitResponse(Handler h) { 2463 mEcmExitRespRegistrant.clear(); 2464 } 2465 2466 @Override registerForCallWaiting(Handler h, int what, Object obj)2467 public void registerForCallWaiting(Handler h, int what, Object obj) { 2468 mCT.registerForCallWaiting(h, what, obj); 2469 } 2470 2471 @Override unregisterForCallWaiting(Handler h)2472 public void unregisterForCallWaiting(Handler h) { 2473 mCT.unregisterForCallWaiting(h); 2474 } 2475 2476 /** 2477 * Whether data is enabled by user. Unlike isDataEnabled, this only 2478 * checks user setting stored in {@link android.provider.Settings.Global#MOBILE_DATA} 2479 * if not provisioning, or isProvisioningDataEnabled if provisioning. 2480 */ 2481 @Override isUserDataEnabled()2482 public boolean isUserDataEnabled() { 2483 if (mDataEnabledSettings.isProvisioning()) { 2484 return mDataEnabledSettings.isProvisioningDataEnabled(); 2485 } else { 2486 return mDataEnabledSettings.isUserDataEnabled(); 2487 } 2488 } 2489 2490 /** 2491 * Removes the given MMI from the pending list and notifies 2492 * registrants that it is complete. 2493 * @param mmi MMI that is done 2494 */ onMMIDone(MmiCode mmi)2495 public void onMMIDone(MmiCode mmi) { 2496 2497 /* Only notify complete if it's on the pending list. 2498 * Otherwise, it's already been handled (eg, previously canceled). 2499 * The exception is cancellation of an incoming USSD-REQUEST, which is 2500 * not on the list. 2501 */ 2502 if (mPendingMMIs.remove(mmi) || (isPhoneTypeGsm() && (mmi.isUssdRequest() || 2503 ((GsmMmiCode)mmi).isSsInfo()))) { 2504 2505 ResultReceiver receiverCallback = mmi.getUssdCallbackReceiver(); 2506 if (receiverCallback != null) { 2507 Rlog.i(LOG_TAG, "onMMIDone: invoking callback: " + mmi); 2508 int returnCode = (mmi.getState() == MmiCode.State.COMPLETE) ? 2509 TelephonyManager.USSD_RETURN_SUCCESS : TelephonyManager.USSD_RETURN_FAILURE; 2510 sendUssdResponse(mmi.getDialString(), mmi.getMessage(), returnCode, 2511 receiverCallback ); 2512 } else { 2513 Rlog.i(LOG_TAG, "onMMIDone: notifying registrants: " + mmi); 2514 mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 2515 } 2516 } else { 2517 Rlog.i(LOG_TAG, "onMMIDone: invalid response or already handled; ignoring: " + mmi); 2518 } 2519 } 2520 supports3gppCallForwardingWhileRoaming()2521 public boolean supports3gppCallForwardingWhileRoaming() { 2522 CarrierConfigManager configManager = (CarrierConfigManager) 2523 getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); 2524 PersistableBundle b = configManager.getConfigForSubId(getSubId()); 2525 if (b != null) { 2526 return b.getBoolean( 2527 CarrierConfigManager.KEY_SUPPORT_3GPP_CALL_FORWARDING_WHILE_ROAMING_BOOL, true); 2528 } else { 2529 // Default value set in CarrierConfigManager 2530 return true; 2531 } 2532 } 2533 onNetworkInitiatedUssd(MmiCode mmi)2534 private void onNetworkInitiatedUssd(MmiCode mmi) { 2535 Rlog.v(LOG_TAG, "onNetworkInitiatedUssd: mmi=" + mmi); 2536 mMmiCompleteRegistrants.notifyRegistrants( 2537 new AsyncResult(null, mmi, null)); 2538 } 2539 2540 /** ussdMode is one of CommandsInterface.USSD_MODE_* */ onIncomingUSSD(int ussdMode, String ussdMessage)2541 private void onIncomingUSSD (int ussdMode, String ussdMessage) { 2542 if (!isPhoneTypeGsm()) { 2543 loge("onIncomingUSSD: not expected on GSM"); 2544 } 2545 boolean isUssdError; 2546 boolean isUssdRequest; 2547 boolean isUssdRelease; 2548 2549 isUssdRequest 2550 = (ussdMode == CommandsInterface.USSD_MODE_REQUEST); 2551 2552 isUssdError 2553 = (ussdMode != CommandsInterface.USSD_MODE_NOTIFY 2554 && ussdMode != CommandsInterface.USSD_MODE_REQUEST); 2555 2556 isUssdRelease = (ussdMode == CommandsInterface.USSD_MODE_NW_RELEASE); 2557 2558 2559 // See comments in GsmMmiCode.java 2560 // USSD requests aren't finished until one 2561 // of these two events happen 2562 GsmMmiCode found = null; 2563 for (int i = 0, s = mPendingMMIs.size() ; i < s; i++) { 2564 if(((GsmMmiCode)mPendingMMIs.get(i)).isPendingUSSD()) { 2565 found = (GsmMmiCode)mPendingMMIs.get(i); 2566 break; 2567 } 2568 } 2569 2570 if (found != null) { 2571 // Complete pending USSD 2572 2573 if (isUssdRelease) { 2574 found.onUssdRelease(); 2575 } else if (isUssdError) { 2576 found.onUssdFinishedError(); 2577 } else { 2578 found.onUssdFinished(ussdMessage, isUssdRequest); 2579 } 2580 } else if (!isUssdError && !TextUtils.isEmpty(ussdMessage)) { 2581 // pending USSD not found 2582 // The network may initiate its own USSD request 2583 2584 // ignore everything that isnt a Notify or a Request 2585 // also, discard if there is no message to present 2586 GsmMmiCode mmi; 2587 mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage, 2588 isUssdRequest, 2589 GsmCdmaPhone.this, 2590 mUiccApplication.get()); 2591 onNetworkInitiatedUssd(mmi); 2592 } 2593 } 2594 2595 /** 2596 * Make sure the network knows our preferred setting. 2597 */ 2598 @UnsupportedAppUsage syncClirSetting()2599 private void syncClirSetting() { 2600 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 2601 migrateClirSettingIfNeeded(sp); 2602 2603 int clirSetting = sp.getInt(CLIR_KEY + getSubId(), -1); 2604 Rlog.i(LOG_TAG, "syncClirSetting: " + CLIR_KEY + getSubId() + "=" + clirSetting); 2605 if (clirSetting >= 0) { 2606 mCi.setCLIR(clirSetting, null); 2607 } 2608 } 2609 2610 /** 2611 * Migrate CLIR setting with sudId mapping once if there's CLIR setting mapped with phoneId. 2612 */ migrateClirSettingIfNeeded(SharedPreferences sp)2613 private void migrateClirSettingIfNeeded(SharedPreferences sp) { 2614 // Get old CLIR setting mapped with phoneId 2615 int clirSetting = sp.getInt("clir_key" + getPhoneId(), -1); 2616 if (clirSetting >= 0) { 2617 // Migrate CLIR setting to new shared preference key with subId 2618 Rlog.i(LOG_TAG, "Migrate CLIR setting: value=" + clirSetting + ", clir_key" 2619 + getPhoneId() + " -> " + CLIR_KEY + getSubId()); 2620 SharedPreferences.Editor editor = sp.edit(); 2621 editor.putInt(CLIR_KEY + getSubId(), clirSetting); 2622 2623 // Remove old CLIR setting key 2624 editor.remove("clir_key" + getPhoneId()).commit(); 2625 } 2626 } 2627 handleRadioAvailable()2628 private void handleRadioAvailable() { 2629 mCi.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE)); 2630 2631 mCi.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE)); 2632 mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY)); 2633 mCi.areUiccApplicationsEnabled(obtainMessage(EVENT_GET_UICC_APPS_ENABLEMENT_DONE)); 2634 2635 startLceAfterRadioIsAvailable(); 2636 } 2637 handleRadioOn()2638 private void handleRadioOn() { 2639 /* Proactively query voice radio technologies */ 2640 mCi.getVoiceRadioTechnology(obtainMessage(EVENT_REQUEST_VOICE_RADIO_TECH_DONE)); 2641 2642 if (!isPhoneTypeGsm()) { 2643 mCdmaSubscriptionSource = mCdmaSSM.getCdmaSubscriptionSource(); 2644 } 2645 2646 // If this is on APM off, SIM may already be loaded. Send setPreferredNetworkType 2647 // request to RIL to preserve user setting across APM toggling 2648 setPreferredNetworkTypeIfSimLoaded(); 2649 } 2650 handleRadioOffOrNotAvailable()2651 private void handleRadioOffOrNotAvailable() { 2652 if (isPhoneTypeGsm()) { 2653 // Some MMI requests (eg USSD) are not completed 2654 // within the course of a CommandsInterface request 2655 // If the radio shuts off or resets while one of these 2656 // is pending, we need to clean up. 2657 2658 for (int i = mPendingMMIs.size() - 1; i >= 0; i--) { 2659 if (((GsmMmiCode) mPendingMMIs.get(i)).isPendingUSSD()) { 2660 ((GsmMmiCode) mPendingMMIs.get(i)).onUssdFinishedError(); 2661 } 2662 } 2663 } 2664 mRadioOffOrNotAvailableRegistrants.notifyRegistrants(); 2665 } 2666 handleRadioPowerStateChange()2667 private void handleRadioPowerStateChange() { 2668 Rlog.d(LOG_TAG, "handleRadioPowerStateChange, state= " + mCi.getRadioState()); 2669 mNotifier.notifyRadioPowerStateChanged(this, mCi.getRadioState()); 2670 } 2671 2672 @Override handleMessage(Message msg)2673 public void handleMessage(Message msg) { 2674 AsyncResult ar; 2675 Message onComplete; 2676 2677 switch (msg.what) { 2678 case EVENT_RADIO_AVAILABLE: { 2679 handleRadioAvailable(); 2680 } 2681 break; 2682 2683 case EVENT_GET_DEVICE_IDENTITY_DONE:{ 2684 ar = (AsyncResult)msg.obj; 2685 2686 if (ar.exception != null) { 2687 break; 2688 } 2689 String[] respId = (String[])ar.result; 2690 mImei = respId[0]; 2691 mImeiSv = respId[1]; 2692 mEsn = respId[2]; 2693 mMeid = respId[3]; 2694 } 2695 break; 2696 2697 case EVENT_EMERGENCY_CALLBACK_MODE_ENTER:{ 2698 handleEnterEmergencyCallbackMode(msg); 2699 } 2700 break; 2701 2702 case EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE:{ 2703 handleExitEmergencyCallbackMode(msg); 2704 } 2705 break; 2706 2707 case EVENT_MODEM_RESET: { 2708 logd("Event EVENT_MODEM_RESET Received" + " isInEcm = " + isInEcm() 2709 + " isPhoneTypeGsm = " + isPhoneTypeGsm() + " mImsPhone = " + mImsPhone); 2710 if (isInEcm()) { 2711 if (isPhoneTypeGsm()) { 2712 if (mImsPhone != null) { 2713 mImsPhone.handleExitEmergencyCallbackMode(); 2714 } 2715 } else { 2716 handleExitEmergencyCallbackMode(msg); 2717 } 2718 } 2719 } 2720 break; 2721 2722 case EVENT_RUIM_RECORDS_LOADED: 2723 logd("Event EVENT_RUIM_RECORDS_LOADED Received"); 2724 updateCurrentCarrierInProvider(); 2725 break; 2726 2727 case EVENT_RADIO_ON: 2728 logd("Event EVENT_RADIO_ON Received"); 2729 handleRadioOn(); 2730 break; 2731 2732 case EVENT_RIL_CONNECTED: 2733 ar = (AsyncResult) msg.obj; 2734 if (ar.exception == null && ar.result != null) { 2735 mRilVersion = (Integer) ar.result; 2736 } else { 2737 logd("Unexpected exception on EVENT_RIL_CONNECTED"); 2738 mRilVersion = -1; 2739 } 2740 break; 2741 2742 case EVENT_VOICE_RADIO_TECH_CHANGED: 2743 case EVENT_REQUEST_VOICE_RADIO_TECH_DONE: 2744 String what = (msg.what == EVENT_VOICE_RADIO_TECH_CHANGED) ? 2745 "EVENT_VOICE_RADIO_TECH_CHANGED" : "EVENT_REQUEST_VOICE_RADIO_TECH_DONE"; 2746 ar = (AsyncResult) msg.obj; 2747 if (ar.exception == null) { 2748 if ((ar.result != null) && (((int[]) ar.result).length != 0)) { 2749 int newVoiceTech = ((int[]) ar.result)[0]; 2750 logd(what + ": newVoiceTech=" + newVoiceTech); 2751 phoneObjectUpdater(newVoiceTech); 2752 } else { 2753 loge(what + ": has no tech!"); 2754 } 2755 } else { 2756 loge(what + ": exception=" + ar.exception); 2757 } 2758 break; 2759 2760 case EVENT_UPDATE_PHONE_OBJECT: 2761 phoneObjectUpdater(msg.arg1); 2762 break; 2763 2764 case EVENT_CARRIER_CONFIG_CHANGED: 2765 // Only check for the voice radio tech if it not going to be updated by the voice 2766 // registration changes. 2767 if (!mContext.getResources().getBoolean(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 ActivityManager.broadcastStickyIntent(intent, UserHandle.USER_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 placeholder 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.flush(); 4035 } 4036 4037 @Override setOperatorBrandOverride(String brand)4038 public boolean setOperatorBrandOverride(String brand) { 4039 if (mUiccController == null) { 4040 return false; 4041 } 4042 4043 UiccCard card = mUiccController.getUiccCard(getPhoneId()); 4044 if (card == null) { 4045 return false; 4046 } 4047 4048 boolean status = card.setOperatorBrandOverride(brand); 4049 4050 // Refresh. 4051 if (status) { 4052 TelephonyManager.from(mContext).setSimOperatorNameForPhone( 4053 getPhoneId(), mSST.getServiceProviderName()); 4054 // TODO: check if pollState is need when set operator brand override. 4055 mSST.pollState(); 4056 } 4057 return status; 4058 } 4059 4060 /** 4061 * This allows a short number to be remapped to a test emergency number for testing how the 4062 * frameworks handles Emergency Callback Mode without actually calling an emergency number. 4063 * 4064 * This is not a full test and is not a substitute for testing real emergency 4065 * numbers but can be useful. 4066 * 4067 * To use this feature, first set a test emergency number using 4068 * adb shell cmd phone emergency-number-test-mode -a 1-555-555-1212 4069 * 4070 * and then set the system property ril.test.emergencynumber to a pair of 4071 * numbers separated by a colon. If the first number matches the number parameter 4072 * this routine returns the second number. Example: 4073 * 4074 * ril.test.emergencynumber=411:1-555-555-1212 4075 * 4076 * To test Dial 411 take call then hang up on MO device to enter ECM. 4077 * 4078 * @param dialString to test if it should be remapped 4079 * @return the same number or the remapped number. 4080 */ checkForTestEmergencyNumber(String dialString)4081 private String checkForTestEmergencyNumber(String dialString) { 4082 String testEn = SystemProperties.get("ril.test.emergencynumber"); 4083 if (!TextUtils.isEmpty(testEn)) { 4084 String[] values = testEn.split(":"); 4085 logd("checkForTestEmergencyNumber: values.length=" + values.length); 4086 if (values.length == 2) { 4087 if (values[0].equals(PhoneNumberUtils.stripSeparators(dialString))) { 4088 logd("checkForTestEmergencyNumber: remap " + dialString + " to " + values[1]); 4089 dialString = values[1]; 4090 } 4091 } 4092 } 4093 return dialString; 4094 } 4095 4096 @Override 4097 @NonNull getOperatorNumeric()4098 public String getOperatorNumeric() { 4099 String operatorNumeric = null; 4100 if (isPhoneTypeGsm()) { 4101 IccRecords r = mIccRecords.get(); 4102 if (r != null) { 4103 operatorNumeric = r.getOperatorNumeric(); 4104 } 4105 } else { //isPhoneTypeCdmaLte() 4106 IccRecords curIccRecords = null; 4107 if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_NV) { 4108 operatorNumeric = SystemProperties.get("ro.cdma.home.operator.numeric"); 4109 } else if (mCdmaSubscriptionSource == CDMA_SUBSCRIPTION_RUIM_SIM) { 4110 UiccCardApplication uiccCardApplication = mUiccApplication.get(); 4111 if (uiccCardApplication != null 4112 && uiccCardApplication.getType() == AppType.APPTYPE_RUIM) { 4113 logd("Legacy RUIM app present"); 4114 curIccRecords = mIccRecords.get(); 4115 } else { 4116 // Use sim-records for SimApp, USimApp, CSimApp and ISimApp. 4117 curIccRecords = mSimRecords; 4118 } 4119 if (curIccRecords != null && curIccRecords == mSimRecords) { 4120 operatorNumeric = curIccRecords.getOperatorNumeric(); 4121 } else { 4122 curIccRecords = mIccRecords.get(); 4123 if (curIccRecords != null && (curIccRecords instanceof RuimRecords)) { 4124 RuimRecords csim = (RuimRecords) curIccRecords; 4125 operatorNumeric = csim.getRUIMOperatorNumeric(); 4126 } 4127 } 4128 } 4129 if (operatorNumeric == null) { 4130 loge("getOperatorNumeric: Cannot retrieve operatorNumeric:" 4131 + " mCdmaSubscriptionSource = " + mCdmaSubscriptionSource + 4132 " mIccRecords = " + ((curIccRecords != null) ? 4133 curIccRecords.getRecordsLoaded() : null)); 4134 } 4135 4136 logd("getOperatorNumeric: mCdmaSubscriptionSource = " + mCdmaSubscriptionSource 4137 + " operatorNumeric = " + operatorNumeric); 4138 4139 } 4140 return TextUtils.emptyIfNull(operatorNumeric); 4141 } 4142 4143 /** 4144 * @return The country ISO for the subscription associated with this phone. 4145 */ getCountryIso()4146 public String getCountryIso() { 4147 int subId = getSubId(); 4148 SubscriptionInfo subInfo = SubscriptionManager.from(getContext()) 4149 .getActiveSubscriptionInfo(subId); 4150 if (subInfo == null || TextUtils.isEmpty(subInfo.getCountryIso())) { 4151 return null; 4152 } 4153 return subInfo.getCountryIso().toUpperCase(); 4154 } 4155 notifyEcbmTimerReset(Boolean flag)4156 public void notifyEcbmTimerReset(Boolean flag) { 4157 mEcmTimerResetRegistrants.notifyResult(flag); 4158 } 4159 4160 private static final int[] VOICE_PS_CALL_RADIO_TECHNOLOGY = { 4161 ServiceState.RIL_RADIO_TECHNOLOGY_LTE, 4162 ServiceState.RIL_RADIO_TECHNOLOGY_LTE_CA, 4163 ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN, 4164 ServiceState.RIL_RADIO_TECHNOLOGY_NR 4165 }; 4166 4167 /** 4168 * Calculates current RIL voice radio technology for CS calls. 4169 * 4170 * This function should only be used in {@link com.android.internal.telephony.GsmCdmaConnection} 4171 * to indicate current CS call radio technology. 4172 * 4173 * @return the RIL voice radio technology used for CS calls, 4174 * see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}. 4175 */ getCsCallRadioTech()4176 public @RilRadioTechnology int getCsCallRadioTech() { 4177 int calcVrat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; 4178 if (mSST != null) { 4179 calcVrat = getCsCallRadioTech(mSST.mSS.getState(), 4180 mSST.mSS.getRilVoiceRadioTechnology()); 4181 } 4182 4183 return calcVrat; 4184 } 4185 4186 /** 4187 * Calculates current RIL voice radio technology for CS calls based on current voice 4188 * registration state and technology. 4189 * 4190 * Mark current RIL voice radio technology as unknow when any of below condtion is met: 4191 * 1) Current RIL voice registration state is not in-service. 4192 * 2) Current RIL voice radio technology is PS call technology, which means CSFB will 4193 * happen later after call connection is established. 4194 * It is inappropriate to notify upper layer the PS call technology while current call 4195 * is CS call, so before CSFB happens, mark voice radio technology as unknow. 4196 * After CSFB happens, {@link #onVoiceRegStateOrRatChanged} will update voice call radio 4197 * technology with correct value. 4198 * 4199 * @param vrs the voice registration state 4200 * @param vrat the RIL voice radio technology 4201 * 4202 * @return the RIL voice radio technology used for CS calls, 4203 * see {@code RIL_RADIO_TECHNOLOGY_*} in {@link android.telephony.ServiceState}. 4204 */ getCsCallRadioTech(int vrs, int vrat)4205 private @RilRadioTechnology int getCsCallRadioTech(int vrs, int vrat) { 4206 logd("getCsCallRadioTech, current vrs=" + vrs + ", vrat=" + vrat); 4207 int calcVrat = vrat; 4208 if (vrs != ServiceState.STATE_IN_SERVICE 4209 || ArrayUtils.contains(VOICE_PS_CALL_RADIO_TECHNOLOGY, vrat)) { 4210 calcVrat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; 4211 } 4212 4213 logd("getCsCallRadioTech, result calcVrat=" + calcVrat); 4214 return calcVrat; 4215 } 4216 4217 /** 4218 * Handler of RIL Voice Radio Technology changed event. 4219 */ onVoiceRegStateOrRatChanged(int vrs, int vrat)4220 private void onVoiceRegStateOrRatChanged(int vrs, int vrat) { 4221 logd("onVoiceRegStateOrRatChanged"); 4222 mCT.dispatchCsCallRadioTech(getCsCallRadioTech(vrs, vrat)); 4223 } 4224 4225 /** 4226 * Registration point for Ecm timer reset 4227 * 4228 * @param h handler to notify 4229 * @param what User-defined message code 4230 * @param obj placed in Message.obj 4231 */ 4232 @Override registerForEcmTimerReset(Handler h, int what, Object obj)4233 public void registerForEcmTimerReset(Handler h, int what, Object obj) { 4234 mEcmTimerResetRegistrants.addUnique(h, what, obj); 4235 } 4236 4237 @Override unregisterForEcmTimerReset(Handler h)4238 public void unregisterForEcmTimerReset(Handler h) { 4239 mEcmTimerResetRegistrants.remove(h); 4240 } 4241 4242 @Override registerForVolteSilentRedial(Handler h, int what, Object obj)4243 public void registerForVolteSilentRedial(Handler h, int what, Object obj) { 4244 mVolteSilentRedialRegistrants.addUnique(h, what, obj); 4245 } 4246 4247 @Override unregisterForVolteSilentRedial(Handler h)4248 public void unregisterForVolteSilentRedial(Handler h) { 4249 mVolteSilentRedialRegistrants.remove(h); 4250 } 4251 notifyVolteSilentRedial(String dialString, int causeCode)4252 public void notifyVolteSilentRedial(String dialString, int causeCode) { 4253 logd("notifyVolteSilentRedial: dialString=" + dialString + " causeCode=" + causeCode); 4254 AsyncResult ar = new AsyncResult(null, 4255 new SilentRedialParam(dialString, causeCode, mDialArgs), null); 4256 mVolteSilentRedialRegistrants.notifyRegistrants(ar); 4257 } 4258 4259 /** 4260 * Sets the SIM voice message waiting indicator records. 4261 * @param line GSM Subscriber Profile Number, one-based. Only '1' is supported 4262 * @param countWaiting The number of messages waiting, if known. Use 4263 * -1 to indicate that an unknown number of 4264 * messages are waiting 4265 */ 4266 @Override setVoiceMessageWaiting(int line, int countWaiting)4267 public void setVoiceMessageWaiting(int line, int countWaiting) { 4268 if (isPhoneTypeGsm()) { 4269 IccRecords r = mIccRecords.get(); 4270 if (r != null) { 4271 r.setVoiceMessageWaiting(line, countWaiting); 4272 } else { 4273 logd("SIM Records not found, MWI not updated"); 4274 } 4275 } else { 4276 setVoiceMessageCount(countWaiting); 4277 } 4278 } 4279 makeEmptyCallForward()4280 private CallForwardInfo[] makeEmptyCallForward() { 4281 CallForwardInfo infos[] = new CallForwardInfo[1]; 4282 4283 infos[0] = new CallForwardInfo(); 4284 infos[0].status = CommandsInterface.SS_STATUS_UNKNOWN; 4285 infos[0].reason = 0; 4286 infos[0].serviceClass = CommandsInterface.SERVICE_CLASS_VOICE; 4287 infos[0].toa = PhoneNumberUtils.TOA_Unknown; 4288 infos[0].number = ""; 4289 infos[0].timeSeconds = 0; 4290 4291 return infos; 4292 } 4293 subscriptionIdToPhoneAccountHandle(final int subId)4294 private PhoneAccountHandle subscriptionIdToPhoneAccountHandle(final int subId) { 4295 final TelecomManager telecomManager = TelecomManager.from(mContext); 4296 final TelephonyManager telephonyManager = TelephonyManager.from(mContext); 4297 final Iterator<PhoneAccountHandle> phoneAccounts = 4298 telecomManager.getCallCapablePhoneAccounts(true).listIterator(); 4299 4300 while (phoneAccounts.hasNext()) { 4301 final PhoneAccountHandle phoneAccountHandle = phoneAccounts.next(); 4302 final PhoneAccount phoneAccount = telecomManager.getPhoneAccount(phoneAccountHandle); 4303 if (subId == telephonyManager.getSubIdForPhoneAccount(phoneAccount)) { 4304 return phoneAccountHandle; 4305 } 4306 } 4307 4308 return null; 4309 } 4310 4311 @UnsupportedAppUsage logd(String s)4312 private void logd(String s) { 4313 Rlog.d(LOG_TAG, "[" + mPhoneId + "] " + s); 4314 } 4315 logi(String s)4316 private void logi(String s) { 4317 Rlog.i(LOG_TAG, "[" + mPhoneId + "] " + s); 4318 } 4319 4320 @UnsupportedAppUsage loge(String s)4321 private void loge(String s) { 4322 Rlog.e(LOG_TAG, "[" + mPhoneId + "] " + s); 4323 } 4324 pii(String s)4325 private static String pii(String s) { 4326 return Rlog.pii(LOG_TAG, s); 4327 } 4328 4329 @Override isUtEnabled()4330 public boolean isUtEnabled() { 4331 Phone imsPhone = mImsPhone; 4332 if (imsPhone != null) { 4333 return imsPhone.isUtEnabled(); 4334 } else { 4335 logd("isUtEnabled: called for GsmCdma"); 4336 return false; 4337 } 4338 } 4339 getDtmfToneDelayKey()4340 public String getDtmfToneDelayKey() { 4341 return isPhoneTypeGsm() ? 4342 CarrierConfigManager.KEY_GSM_DTMF_TONE_DELAY_INT : 4343 CarrierConfigManager.KEY_CDMA_DTMF_TONE_DELAY_INT; 4344 } 4345 4346 @VisibleForTesting getWakeLock()4347 public PowerManager.WakeLock getWakeLock() { 4348 return mWakeLock; 4349 } 4350 getLteOnCdmaMode()4351 public int getLteOnCdmaMode() { 4352 int currentConfig = TelephonyProperties.lte_on_cdma_device() 4353 .orElse(PhoneConstants.LTE_ON_CDMA_FALSE); 4354 int lteOnCdmaModeDynamicValue = currentConfig; 4355 4356 UiccCardApplication cdmaApplication = 4357 mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2); 4358 if (cdmaApplication != null && cdmaApplication.getType() == AppType.APPTYPE_RUIM) { 4359 //Legacy RUIM cards don't support LTE. 4360 lteOnCdmaModeDynamicValue = RILConstants.LTE_ON_CDMA_FALSE; 4361 4362 //Override only if static configuration is TRUE. 4363 if (currentConfig == RILConstants.LTE_ON_CDMA_TRUE) { 4364 return lteOnCdmaModeDynamicValue; 4365 } 4366 } 4367 return currentConfig; 4368 } 4369 updateTtyMode(int ttyMode)4370 private void updateTtyMode(int ttyMode) { 4371 logi(String.format("updateTtyMode ttyMode=%d", ttyMode)); 4372 setTTYMode(telecomModeToPhoneMode(ttyMode), null); 4373 } updateUiTtyMode(int ttyMode)4374 private void updateUiTtyMode(int ttyMode) { 4375 logi(String.format("updateUiTtyMode ttyMode=%d", ttyMode)); 4376 setUiTTYMode(telecomModeToPhoneMode(ttyMode), null); 4377 } 4378 4379 /** 4380 * Given a telecom TTY mode, convert to a Telephony mode equivalent. 4381 * @param telecomMode Telecom TTY mode. 4382 * @return Telephony phone TTY mode. 4383 */ telecomModeToPhoneMode(int telecomMode)4384 private static int telecomModeToPhoneMode(int telecomMode) { 4385 switch (telecomMode) { 4386 // AT command only has 0 and 1, so mapping VCO 4387 // and HCO to FULL 4388 case TelecomManager.TTY_MODE_FULL: 4389 case TelecomManager.TTY_MODE_VCO: 4390 case TelecomManager.TTY_MODE_HCO: 4391 return Phone.TTY_MODE_FULL; 4392 default: 4393 return Phone.TTY_MODE_OFF; 4394 } 4395 } 4396 4397 /** 4398 * Load the current TTY mode in GsmCdmaPhone based on Telecom and UI settings. 4399 */ loadTtyMode()4400 private void loadTtyMode() { 4401 int ttyMode = TelecomManager.TTY_MODE_OFF; 4402 TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class); 4403 if (telecomManager != null) { 4404 ttyMode = telecomManager.getCurrentTtyMode(); 4405 } 4406 updateTtyMode(ttyMode); 4407 //Get preferred TTY mode from settings as UI Tty mode is always user preferred Tty mode. 4408 ttyMode = Settings.Secure.getInt(mContext.getContentResolver(), 4409 Settings.Secure.PREFERRED_TTY_MODE, TelecomManager.TTY_MODE_OFF); 4410 updateUiTtyMode(ttyMode); 4411 } 4412 reapplyUiccAppsEnablementIfNeeded(int retries)4413 private void reapplyUiccAppsEnablementIfNeeded(int retries) { 4414 UiccSlot slot = mUiccController.getUiccSlotForPhone(mPhoneId); 4415 4416 // If no card is present or we don't have mUiccApplicationsEnabled yet, do nothing. 4417 if (slot == null || slot.getCardState() != IccCardStatus.CardState.CARDSTATE_PRESENT 4418 || mUiccApplicationsEnabled == null) { 4419 return; 4420 } 4421 4422 String iccId = slot.getIccId(); 4423 if (iccId == null) return; 4424 4425 SubscriptionInfo info = SubscriptionController.getInstance().getSubInfoForIccId( 4426 IccUtils.stripTrailingFs(iccId)); 4427 4428 // If info is null, it could be a new subscription. By default we enable it. 4429 boolean expectedValue = info == null ? true : info.areUiccApplicationsEnabled(); 4430 4431 // If for any reason current state is different from configured state, re-apply the 4432 // configured state. 4433 if (expectedValue != mUiccApplicationsEnabled) { 4434 mCi.enableUiccApplications(expectedValue, Message.obtain( 4435 this, EVENT_REAPPLY_UICC_APPS_ENABLEMENT_DONE, 4436 new Pair<Boolean, Integer>(expectedValue, retries))); 4437 } 4438 } 4439 4440 // Enable or disable uicc applications. 4441 @Override enableUiccApplications(boolean enable, Message onCompleteMessage)4442 public void enableUiccApplications(boolean enable, Message onCompleteMessage) { 4443 // First check if card is present. Otherwise mUiccApplicationsDisabled doesn't make 4444 // any sense. 4445 UiccSlot slot = mUiccController.getUiccSlotForPhone(mPhoneId); 4446 if (slot == null || slot.getCardState() != IccCardStatus.CardState.CARDSTATE_PRESENT) { 4447 if (onCompleteMessage != null) { 4448 AsyncResult.forMessage(onCompleteMessage, null, 4449 new IllegalStateException("No SIM card is present")); 4450 onCompleteMessage.sendToTarget(); 4451 } 4452 return; 4453 } 4454 4455 mCi.enableUiccApplications(enable, onCompleteMessage); 4456 } 4457 4458 /** 4459 * Whether disabling a physical subscription is supported or not. 4460 */ 4461 @Override canDisablePhysicalSubscription()4462 public boolean canDisablePhysicalSubscription() { 4463 return mCi.canToggleUiccApplicationsEnablement(); 4464 } 4465 } 4466