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