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