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