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