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