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