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