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 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 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 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 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 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 */ 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 376 public boolean isPhoneTypeGsm() { 377 return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_GSM; 378 } 379 380 public boolean isPhoneTypeCdma() { 381 return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_CDMA; 382 } 383 384 public boolean isPhoneTypeCdmaLte() { 385 return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_CDMA_LTE; 386 } 387 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 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 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 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 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 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 481 public ServiceStateTracker getServiceStateTracker() { 482 return mSST; 483 } 484 485 @Override 486 public CallTracker getCallTracker() { 487 return mCT; 488 } 489 490 @Override 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> 512 getPendingMmiCodes() { 513 return mPendingMMIs; 514 } 515 516 @Override 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 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 */ 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 */ 602 public void notifyPreciseCallStateChanged() { 603 /* we'd love it if this was package-scoped*/ 604 super.notifyPreciseCallStateChangedP(); 605 } 606 607 public void notifyNewRingingConnection(Connection c) { 608 super.notifyNewRingingConnectionP(c); 609 } 610 611 public void notifyDisconnect(Connection cn) { 612 mDisconnectRegistrants.notifyResult(cn); 613 614 mNotifier.notifyDisconnectCause(cn.getDisconnectCause(), cn.getPreciseDisconnectCause()); 615 } 616 617 public void notifyUnknownConnection(Connection cn) { 618 super.notifyUnknownConnectionP(cn); 619 } 620 621 @Override 622 public boolean isInEmergencyCall() { 623 if (isPhoneTypeGsm()) { 624 return false; 625 } else { 626 return mCT.isInEmergencyCall(); 627 } 628 } 629 630 @Override 631 protected void setIsInEmergencyCall() { 632 if (!isPhoneTypeGsm()) { 633 mCT.setIsInEmergencyCall(); 634 } 635 } 636 637 //CDMA 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 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 659 public void setBroadcastEmergencyCallStateChanges(boolean broadcast) { 660 mBroadcastEmergencyCallStateChanges = broadcast; 661 } 662 663 public void notifySuppServiceFailed(SuppService code) { 664 mSuppServiceFailedRegistrants.notifyResult(code); 665 } 666 667 public void notifyServiceStateChanged(ServiceState ss) { 668 super.notifyServiceStateChangedP(ss); 669 } 670 671 public void notifyLocationChanged() { 672 mNotifier.notifyCellLocation(this); 673 } 674 675 @Override 676 public void notifyCallForwardingIndicator() { 677 mNotifier.notifyCallForwardingChanged(this); 678 } 679 680 @Override 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 688 public void unregisterForSuppServiceNotification(Handler h) { 689 mSsnRegistrants.remove(h); 690 if (mSsnRegistrants.size() == 0) mCi.setSuppServiceNotifications(false, null); 691 } 692 693 @Override 694 public void registerForSimRecordsLoaded(Handler h, int what, Object obj) { 695 mSimRecordsLoadedRegistrants.addUnique(h, what, obj); 696 } 697 698 @Override 699 public void unregisterForSimRecordsLoaded(Handler h) { 700 mSimRecordsLoadedRegistrants.remove(h); 701 } 702 703 @Override 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 714 public void rejectCall() throws CallStateException { 715 mCT.rejectCall(); 716 } 717 718 @Override 719 public void switchHoldingAndActive() throws CallStateException { 720 mCT.switchWaitingOrHoldingAndActive(); 721 } 722 723 @Override 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 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 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 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 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 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 794 public void clearDisconnected() { 795 mCT.clearDisconnected(); 796 } 797 798 @Override 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 809 public void explicitCallTransfer() { 810 if (isPhoneTypeGsm()) { 811 mCT.explicitCallTransfer(); 812 } else { 813 loge("explicitCallTransfer: not possible in CDMA"); 814 } 815 } 816 817 @Override 818 public GsmCdmaCall getForegroundCall() { 819 return mCT.mForegroundCall; 820 } 821 822 @Override 823 public GsmCdmaCall getBackgroundCall() { 824 return mCT.mBackgroundCall; 825 } 826 827 @Override 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 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 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 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 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 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 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 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 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 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 */ 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 1186 protected Connection dialInternal(String dialString, DialArgs dialArgs) 1187 throws CallStateException { 1188 return dialInternal(dialString, dialArgs, null); 1189 } 1190 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 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 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 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 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 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 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 1328 public void stopDtmf() { 1329 mCi.stopDtmf(null); 1330 } 1331 1332 @Override 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 1353 public void setRadioPower(boolean power) { 1354 mSST.setRadioPower(power); 1355 } 1356 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 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 1419 private String getVmSimImsi() { 1420 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1421 return sp.getString(VM_SIM_IMSI + getPhoneId(), null); 1422 } 1423 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 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 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 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 1480 public IsimRecords getIsimRecords() { 1481 return mIsimUiccRecords; 1482 } 1483 1484 @Override 1485 public String getImei() { 1486 return mImei; 1487 } 1488 1489 @Override 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 1500 public String getMeid() { 1501 return mMeid; 1502 } 1503 1504 @Override 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 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 1531 public ImsiEncryptionInfo getCarrierInfoForImsiEncryption(int keyType) { 1532 return CarrierInfoManager.getCarrierInfoForImsiEncryption(keyType, mContext); 1533 } 1534 1535 @Override 1536 public void setCarrierInfoForImsiEncryption(ImsiEncryptionInfo imsiEncryptionInfo) { 1537 CarrierInfoManager.setCarrierInfoForImsiEncryption(imsiEncryptionInfo, mContext, mPhoneId); 1538 } 1539 1540 @Override 1541 public int getCarrierId() { 1542 return mCarrerIdentifier.getCarrierId(); 1543 } 1544 1545 @Override 1546 public String getCarrierName() { 1547 return mCarrerIdentifier.getCarrierName(); 1548 } 1549 1550 @Override 1551 public int getCarrierIdListVersion() { 1552 return mCarrerIdentifier.getCarrierListVersion(); 1553 } 1554 1555 @Override 1556 public void resetCarrierKeysForImsiEncryption() { 1557 mCIM.resetCarrierKeysForImsiEncryption(mContext, mPhoneId); 1558 } 1559 1560 @Override 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 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 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 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 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 1626 public String getCdmaPrlVersion() { 1627 return mSST.getPrlVersion(); 1628 } 1629 1630 @Override 1631 public String getCdmaMin() { 1632 return mSST.getCdmaMin(); 1633 } 1634 1635 @Override 1636 public boolean isMinInfoReady() { 1637 return mSST.isMinInfoReady(); 1638 } 1639 1640 @Override 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 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 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 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 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 1706 public String getSystemProperty(String property, String defValue) { 1707 if (getUnitTestMode()) { 1708 return null; 1709 } 1710 return TelephonyManager.getTelephonyProperty(mPhoneId, property, defValue); 1711 } 1712 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 1725 private boolean isCfEnable(int action) { 1726 return (action == CF_ACTION_ENABLE) || (action == CF_ACTION_REGISTRATION); 1727 } 1728 1729 @Override 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 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 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 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 */ 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 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 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 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 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 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 1928 public void startNetworkScan(NetworkScanRequest nsr, Message response) { 1929 mCi.startNetworkScan(nsr, response); 1930 } 1931 1932 @Override 1933 public void stopNetworkScan(Message response) { 1934 mCi.stopNetworkScan(response); 1935 } 1936 1937 @Override 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 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 1969 public void setUiTTYMode(int uiTtyMode, Message onComplete) { 1970 if (mImsPhone != null) { 1971 mImsPhone.setUiTTYMode(uiTtyMode, onComplete); 1972 } 1973 } 1974 1975 @Override 1976 public void setMute(boolean muted) { 1977 mCT.setMute(muted); 1978 } 1979 1980 @Override 1981 public boolean getMute() { 1982 return mCT.getMute(); 1983 } 1984 1985 @Override 1986 public void updateServiceLocation() { 1987 mSST.enableSingleLocationUpdate(); 1988 } 1989 1990 @Override 1991 public void enableLocationUpdates() { 1992 mSST.enableLocationUpdates(); 1993 } 1994 1995 @Override 1996 public void disableLocationUpdates() { 1997 mSST.disableLocationUpdates(); 1998 } 1999 2000 @Override 2001 public boolean getDataRoamingEnabled() { 2002 return mDcTracker.getDataRoamingEnabled(); 2003 } 2004 2005 @Override 2006 public void setDataRoamingEnabled(boolean enable) { 2007 mDcTracker.setDataRoamingEnabledByUser(enable); 2008 } 2009 2010 @Override 2011 public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) { 2012 mCi.registerForCdmaOtaProvision(h, what, obj); 2013 } 2014 2015 @Override 2016 public void unregisterForCdmaOtaStatusChange(Handler h) { 2017 mCi.unregisterForCdmaOtaProvision(h); 2018 } 2019 2020 @Override 2021 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) { 2022 mSST.registerForSubscriptionInfoReady(h, what, obj); 2023 } 2024 2025 @Override 2026 public void unregisterForSubscriptionInfoReady(Handler h) { 2027 mSST.unregisterForSubscriptionInfoReady(h); 2028 } 2029 2030 @Override 2031 public void setOnEcbModeExitResponse(Handler h, int what, Object obj) { 2032 mEcmExitRespRegistrant = new Registrant(h, what, obj); 2033 } 2034 2035 @Override 2036 public void unsetOnEcbModeExitResponse(Handler h) { 2037 mEcmExitRespRegistrant.clear(); 2038 } 2039 2040 @Override 2041 public void registerForCallWaiting(Handler h, int what, Object obj) { 2042 mCT.registerForCallWaiting(h, what, obj); 2043 } 2044 2045 @Override 2046 public void unregisterForCallWaiting(Handler h) { 2047 mCT.unregisterForCallWaiting(h); 2048 } 2049 2050 @Override 2051 public boolean isUserDataEnabled() { 2052 return mDcTracker.isUserDataEnabled(); 2053 } 2054 2055 @Override 2056 public boolean isDataEnabled() { 2057 return mDcTracker.isDataEnabled(); 2058 } 2059 2060 @Override 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 */ 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 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 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_* */ 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 */ 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 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 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 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 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 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 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 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 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 */ 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 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 2755 public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){ 2756 return mIccPhoneBookIntManager; 2757 } 2758 2759 //CDMA 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 2766 public void unregisterForEriFileLoaded(Handler h) { 2767 mEriFileLoadedRegistrants.remove(h); 2768 } 2769 2770 //CDMA 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 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 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 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 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 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 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 */ 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 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 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 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 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 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 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 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 */ 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 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 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 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 3404 public IccSmsInterfaceManager getIccSmsInterfaceManager(){ 3405 return mIccSmsInterfaceManager; 3406 } 3407 3408 @Override 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 3415 public void setImsRegistrationState(boolean registered) { 3416 mSST.setImsRegistrationState(registered); 3417 } 3418 3419 @Override 3420 public boolean getIccRecordsLoaded() { 3421 UiccProfile uiccProfile = getUiccProfile(); 3422 return uiccProfile != null && uiccProfile.getIccRecordsLoaded(); 3423 } 3424 3425 @Override 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 3443 private UiccProfile getUiccProfile() { 3444 return UiccController.getInstance().getUiccProfileForPhone(mPhoneId); 3445 } 3446 3447 @Override 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 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 */ 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 */ 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 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 3577 public void registerForEcmTimerReset(Handler h, int what, Object obj) { 3578 mEcmTimerResetRegistrants.addUnique(h, what, obj); 3579 } 3580 3581 @Override 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 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 3607 private void logd(String s) { 3608 Rlog.d(LOG_TAG, "[" + mPhoneId + "] " + s); 3609 } 3610 3611 private void logi(String s) { 3612 Rlog.i(LOG_TAG, "[" + mPhoneId + "] " + s); 3613 } 3614 3615 private void loge(String s) { 3616 Rlog.e(LOG_TAG, "[" + mPhoneId + "] " + s); 3617 } 3618 3619 @Override 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 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 3637 public PowerManager.WakeLock getWakeLock() { 3638 return mWakeLock; 3639 } 3640 3641 @Override 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