1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_DISABLE; 20 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ENABLE; 21 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_ERASURE; 22 import static com.android.internal.telephony.CommandsInterface.CF_ACTION_REGISTRATION; 23 import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL; 24 import static com.android.internal.telephony.CommandsInterface.CF_REASON_ALL_CONDITIONAL; 25 import static com.android.internal.telephony.CommandsInterface.CF_REASON_BUSY; 26 import static com.android.internal.telephony.CommandsInterface.CF_REASON_NOT_REACHABLE; 27 import static com.android.internal.telephony.CommandsInterface.CF_REASON_NO_REPLY; 28 import static com.android.internal.telephony.CommandsInterface.CF_REASON_UNCONDITIONAL; 29 import static com.android.internal.telephony.CommandsInterface.SERVICE_CLASS_VOICE; 30 31 import android.app.ActivityManager; 32 import android.content.BroadcastReceiver; 33 import android.content.ContentValues; 34 import android.content.Context; 35 import android.content.Intent; 36 import android.content.IntentFilter; 37 import android.content.SharedPreferences; 38 import android.database.SQLException; 39 import android.net.Uri; 40 import android.os.AsyncResult; 41 import android.os.Bundle; 42 import android.os.Handler; 43 import android.os.Message; 44 import android.os.PersistableBundle; 45 import android.os.PowerManager; 46 import android.os.Registrant; 47 import android.os.RegistrantList; 48 import android.os.ResultReceiver; 49 import android.os.SystemProperties; 50 import android.os.UserHandle; 51 import android.os.WorkSource; 52 import android.preference.PreferenceManager; 53 import android.provider.Settings; 54 import android.provider.Telephony; 55 import android.telecom.VideoProfile; 56 import android.telephony.CarrierConfigManager; 57 import android.telephony.CellLocation; 58 import android.telephony.PhoneNumberUtils; 59 import android.telephony.Rlog; 60 import android.telephony.ServiceState; 61 import android.telephony.SubscriptionInfo; 62 import android.telephony.SubscriptionManager; 63 import android.telephony.TelephonyManager; 64 import android.telephony.UssdResponse; 65 import android.telephony.cdma.CdmaCellLocation; 66 import android.text.TextUtils; 67 import android.util.Log; 68 69 import com.android.ims.ImsManager; 70 import com.android.internal.annotations.VisibleForTesting; 71 import com.android.internal.telephony.cdma.CdmaMmiCode; 72 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; 73 import com.android.internal.telephony.cdma.EriManager; 74 import com.android.internal.telephony.gsm.GsmMmiCode; 75 import com.android.internal.telephony.gsm.SuppServiceNotification; 76 import com.android.internal.telephony.imsphone.ImsPhone; 77 import com.android.internal.telephony.test.SimulatedRadioControl; 78 import com.android.internal.telephony.uicc.IccCardProxy; 79 import com.android.internal.telephony.uicc.IccException; 80 import com.android.internal.telephony.uicc.IccRecords; 81 import com.android.internal.telephony.uicc.IccVmNotSupportedException; 82 import com.android.internal.telephony.uicc.IsimRecords; 83 import com.android.internal.telephony.uicc.IsimUiccRecords; 84 import com.android.internal.telephony.uicc.RuimRecords; 85 import com.android.internal.telephony.uicc.SIMRecords; 86 import com.android.internal.telephony.uicc.UiccCard; 87 import com.android.internal.telephony.uicc.UiccCardApplication; 88 import com.android.internal.telephony.uicc.UiccController; 89 90 import java.io.FileDescriptor; 91 import java.io.PrintWriter; 92 import java.util.ArrayDeque; 93 import java.util.ArrayList; 94 import java.util.Deque; 95 import java.util.List; 96 import java.util.regex.Matcher; 97 import java.util.regex.Pattern; 98 99 /** 100 * {@hide} 101 */ 102 public 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 Cfu(String cfNumber, Message onComplete)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 GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId, int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory)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 GsmCdmaPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode, int phoneId, int precisePhoneType, TelephonyComponentFactory telephonyComponentFactory)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 initOnce(CommandsInterface ci)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 initRatSpecific(int precisePhoneType)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 */ setIsoCountryProperty(String operatorNumeric)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 isPhoneTypeGsm()353 public boolean isPhoneTypeGsm() { 354 return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_GSM; 355 } 356 isPhoneTypeCdma()357 public boolean isPhoneTypeCdma() { 358 return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_CDMA; 359 } 360 isPhoneTypeCdmaLte()361 public boolean isPhoneTypeCdmaLte() { 362 return mPrecisePhoneType == PhoneConstants.PHONE_TYPE_CDMA_LTE; 363 } 364 switchPhoneType(int precisePhoneType)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 finalize()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 getServiceState()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 getCellLocation(WorkSource workSource)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 getState()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 getPhoneType()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 getServiceStateTracker()458 public ServiceStateTracker getServiceStateTracker() { 459 return mSST; 460 } 461 462 @Override getCallTracker()463 public CallTracker getCallTracker() { 464 return mCT; 465 } 466 467 @Override updateVoiceMail()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> getPendingMmiCodes()489 getPendingMmiCodes() { 490 return mPendingMMIs; 491 } 492 493 @Override getDataConnectionState(String apnType)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 getDataActivityState()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 */ notifyPhoneStateChanged()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 */ notifyPreciseCallStateChanged()585 public void notifyPreciseCallStateChanged() { 586 /* we'd love it if this was package-scoped*/ 587 super.notifyPreciseCallStateChangedP(); 588 } 589 notifyNewRingingConnection(Connection c)590 public void notifyNewRingingConnection(Connection c) { 591 super.notifyNewRingingConnectionP(c); 592 } 593 notifyDisconnect(Connection cn)594 public void notifyDisconnect(Connection cn) { 595 mDisconnectRegistrants.notifyResult(cn); 596 597 mNotifier.notifyDisconnectCause(cn.getDisconnectCause(), cn.getPreciseDisconnectCause()); 598 } 599 notifyUnknownConnection(Connection cn)600 public void notifyUnknownConnection(Connection cn) { 601 super.notifyUnknownConnectionP(cn); 602 } 603 604 @Override isInEmergencyCall()605 public boolean isInEmergencyCall() { 606 if (isPhoneTypeGsm()) { 607 return false; 608 } else { 609 return mCT.isInEmergencyCall(); 610 } 611 } 612 613 @Override setIsInEmergencyCall()614 protected void setIsInEmergencyCall() { 615 if (!isPhoneTypeGsm()) { 616 mCT.setIsInEmergencyCall(); 617 } 618 } 619 620 @Override isInEcm()621 public boolean isInEcm() { 622 if (isPhoneTypeGsm()) { 623 return false; 624 } else { 625 return mIsPhoneInEcmState; 626 } 627 } 628 629 //CDMA sendEmergencyCallbackModeChange()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 sendEmergencyCallStateChange(boolean callActive)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 setBroadcastEmergencyCallStateChanges(boolean broadcast)651 public void setBroadcastEmergencyCallStateChanges(boolean broadcast) { 652 mBroadcastEmergencyCallStateChanges = broadcast; 653 } 654 notifySuppServiceFailed(SuppService code)655 public void notifySuppServiceFailed(SuppService code) { 656 mSuppServiceFailedRegistrants.notifyResult(code); 657 } 658 notifyServiceStateChanged(ServiceState ss)659 public void notifyServiceStateChanged(ServiceState ss) { 660 super.notifyServiceStateChangedP(ss); 661 } 662 notifyLocationChanged()663 public void notifyLocationChanged() { 664 mNotifier.notifyCellLocation(this); 665 } 666 667 @Override notifyCallForwardingIndicator()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 setSystemProperty(String property, String value)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 registerForSuppServiceNotification( Handler h, int what, Object obj)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 unregisterForSuppServiceNotification(Handler h)696 public void unregisterForSuppServiceNotification(Handler h) { 697 mSsnRegistrants.remove(h); 698 if (mSsnRegistrants.size() == 0) mCi.setSuppServiceNotifications(false, null); 699 } 700 701 @Override registerForSimRecordsLoaded(Handler h, int what, Object obj)702 public void registerForSimRecordsLoaded(Handler h, int what, Object obj) { 703 mSimRecordsLoadedRegistrants.addUnique(h, what, obj); 704 } 705 706 @Override unregisterForSimRecordsLoaded(Handler h)707 public void unregisterForSimRecordsLoaded(Handler h) { 708 mSimRecordsLoadedRegistrants.remove(h); 709 } 710 711 @Override acceptCall(int videoState)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 rejectCall()722 public void rejectCall() throws CallStateException { 723 mCT.rejectCall(); 724 } 725 726 @Override switchHoldingAndActive()727 public void switchHoldingAndActive() throws CallStateException { 728 mCT.switchWaitingOrHoldingAndActive(); 729 } 730 731 @Override getIccSerialNumber()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 getFullIccSerialNumber()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 canConference()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 conference()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 enableEnhancedVoicePrivacy(boolean enable, Message onComplete)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 getEnhancedVoicePrivacy(Message onComplete)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 clearDisconnected()802 public void clearDisconnected() { 803 mCT.clearDisconnected(); 804 } 805 806 @Override canTransfer()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 explicitCallTransfer()817 public void explicitCallTransfer() { 818 if (isPhoneTypeGsm()) { 819 mCT.explicitCallTransfer(); 820 } else { 821 loge("explicitCallTransfer: not possible in CDMA"); 822 } 823 } 824 825 @Override getForegroundCall()826 public GsmCdmaCall getForegroundCall() { 827 return mCT.mForegroundCall; 828 } 829 830 @Override getBackgroundCall()831 public GsmCdmaCall getBackgroundCall() { 832 return mCT.mBackgroundCall; 833 } 834 835 @Override getRingingCall()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 handleCallDeflectionIncallSupplementaryService( String dialString)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 handleCallWaitingIncallSupplementaryService(String dialString)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 handleCallHoldIncallSupplementaryService(String dialString)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 handleMultipartyIncallSupplementaryService(String dialString)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 handleEctIncallSupplementaryService(String dialString)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 handleCcbsIncallSupplementaryService(String dialString)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 handleInCallMmiCommands(String dialString)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 isInCall()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 dial(String dialString, int videoState)1051 public Connection dial(String dialString, int videoState) throws CallStateException { 1052 return dial(dialString, null, videoState, null); 1053 } 1054 1055 @Override dial(String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)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 */ isNotificationOfWfcCallRequired(String dialString)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 dialInternal(String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras)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 dialInternal(String dialString, UUSInfo uusInfo, int videoState, Bundle intentExtras, ResultReceiver wrappedCallback)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 handlePinMmi(String dialString)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 sendUssdResponse(String ussdRequest, CharSequence message, int returnCode, ResultReceiver wrappedCallback)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 handleUssdRequest(String ussdRequest, ResultReceiver wrappedCallback)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 sendUssdResponse(String ussdMessge)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 sendDtmf(char c)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 startDtmf(char c)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 stopDtmf()1323 public void stopDtmf() { 1324 mCi.stopDtmf(null); 1325 } 1326 1327 @Override sendBurstDtmf(String dtmfString, int on, int off, Message onComplete)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 setRadioPower(boolean power)1348 public void setRadioPower(boolean power) { 1349 mSST.setRadioPower(power); 1350 } 1351 storeVoiceMailNumber(String number)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 getVoiceMailNumber()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 getVmSimImsi()1407 private String getVmSimImsi() { 1408 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1409 return sp.getString(VM_SIM_IMSI + getPhoneId(), null); 1410 } 1411 setVmSimImsi(String imsi)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 getVoiceMailAlphaTag()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 getDeviceId()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 getDeviceSvn()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 getIsimRecords()1468 public IsimRecords getIsimRecords() { 1469 return mIsimUiccRecords; 1470 } 1471 1472 @Override getImei()1473 public String getImei() { 1474 return mImei; 1475 } 1476 1477 @Override getEsn()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 getMeid()1488 public String getMeid() { 1489 return mMeid; 1490 } 1491 1492 @Override getNai()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 getSubscriberId()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 getGroupIdLevel1()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 getGroupIdLevel2()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 getLine1Number()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 getCdmaPrlVersion()1550 public String getCdmaPrlVersion() { 1551 return mSST.getPrlVersion(); 1552 } 1553 1554 @Override getCdmaMin()1555 public String getCdmaMin() { 1556 return mSST.getCdmaMin(); 1557 } 1558 1559 @Override isMinInfoReady()1560 public boolean isMinInfoReady() { 1561 return mSST.isMinInfoReady(); 1562 } 1563 1564 @Override getMsisdn()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 getLine1AlphaTag()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 setLine1Number(String alphaTag, String number, Message onComplete)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 setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete)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 isValidCommandInterfaceCFReason(int commandInterfaceCFReason)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 getSystemProperty(String property, String defValue)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 isValidCommandInterfaceCFAction(int commandInterfaceCFAction)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 isCfEnable(int action)1653 private boolean isCfEnable(int action) { 1654 return (action == CF_ACTION_ENABLE) || (action == CF_ACTION_REGISTRATION); 1655 } 1656 1657 @Override getCallForwardingOption(int commandInterfaceCFReason, Message onComplete)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 setCallForwardingOption(int commandInterfaceCFAction, int commandInterfaceCFReason, String dialingNumber, int timerSeconds, Message onComplete)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 getOutgoingCallerIdDisplay(Message onComplete)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 setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete)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 getCallWaiting(Message onComplete)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 setCallWaiting(boolean enable, Message onComplete)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 getAvailableNetworks(Message response)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 getNeighboringCids(Message response, WorkSource workSource)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 setUiTTYMode(int uiTtyMode, Message onComplete)1824 public void setUiTTYMode(int uiTtyMode, Message onComplete) { 1825 if (mImsPhone != null) { 1826 mImsPhone.setUiTTYMode(uiTtyMode, onComplete); 1827 } 1828 } 1829 1830 @Override setMute(boolean muted)1831 public void setMute(boolean muted) { 1832 mCT.setMute(muted); 1833 } 1834 1835 @Override getMute()1836 public boolean getMute() { 1837 return mCT.getMute(); 1838 } 1839 1840 @Override getDataCallList(Message response)1841 public void getDataCallList(Message response) { 1842 mCi.getDataCallList(response); 1843 } 1844 1845 @Override updateServiceLocation()1846 public void updateServiceLocation() { 1847 mSST.enableSingleLocationUpdate(); 1848 } 1849 1850 @Override enableLocationUpdates()1851 public void enableLocationUpdates() { 1852 mSST.enableLocationUpdates(); 1853 } 1854 1855 @Override disableLocationUpdates()1856 public void disableLocationUpdates() { 1857 mSST.disableLocationUpdates(); 1858 } 1859 1860 @Override getDataRoamingEnabled()1861 public boolean getDataRoamingEnabled() { 1862 return mDcTracker.getDataRoamingEnabled(); 1863 } 1864 1865 @Override setDataRoamingEnabled(boolean enable)1866 public void setDataRoamingEnabled(boolean enable) { 1867 mDcTracker.setDataRoamingEnabled(enable); 1868 } 1869 1870 @Override registerForCdmaOtaStatusChange(Handler h, int what, Object obj)1871 public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) { 1872 mCi.registerForCdmaOtaProvision(h, what, obj); 1873 } 1874 1875 @Override unregisterForCdmaOtaStatusChange(Handler h)1876 public void unregisterForCdmaOtaStatusChange(Handler h) { 1877 mCi.unregisterForCdmaOtaProvision(h); 1878 } 1879 1880 @Override registerForSubscriptionInfoReady(Handler h, int what, Object obj)1881 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) { 1882 mSST.registerForSubscriptionInfoReady(h, what, obj); 1883 } 1884 1885 @Override unregisterForSubscriptionInfoReady(Handler h)1886 public void unregisterForSubscriptionInfoReady(Handler h) { 1887 mSST.unregisterForSubscriptionInfoReady(h); 1888 } 1889 1890 @Override setOnEcbModeExitResponse(Handler h, int what, Object obj)1891 public void setOnEcbModeExitResponse(Handler h, int what, Object obj) { 1892 mEcmExitRespRegistrant = new Registrant(h, what, obj); 1893 } 1894 1895 @Override unsetOnEcbModeExitResponse(Handler h)1896 public void unsetOnEcbModeExitResponse(Handler h) { 1897 mEcmExitRespRegistrant.clear(); 1898 } 1899 1900 @Override registerForCallWaiting(Handler h, int what, Object obj)1901 public void registerForCallWaiting(Handler h, int what, Object obj) { 1902 mCT.registerForCallWaiting(h, what, obj); 1903 } 1904 1905 @Override unregisterForCallWaiting(Handler h)1906 public void unregisterForCallWaiting(Handler h) { 1907 mCT.unregisterForCallWaiting(h); 1908 } 1909 1910 @Override getDataEnabled()1911 public boolean getDataEnabled() { 1912 return mDcTracker.getDataEnabled(); 1913 } 1914 1915 @Override setDataEnabled(boolean enable)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 */ onMMIDone(MmiCode mmi)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 supports3gppCallForwardingWhileRoaming()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 onNetworkInitiatedUssd(MmiCode mmi)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_* */ onIncomingUSSD(int ussdMode, String ussdMessage)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 */ syncClirSetting()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 handleRadioAvailable()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 handleRadioOn()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 handleRadioOffOrNotAvailable()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 handleMessage(Message msg)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 getUiccCardApplication()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 onUpdateIccAvailability()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 processIccRecordEvents(int eventCode)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 updateCurrentCarrierInProvider()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 */ updateCurrentCarrierInProvider(String operatorNumeric)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 handleCfuQueryResult(CallForwardInfo[] infos)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 getIccPhoneBookInterfaceManager()2595 public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){ 2596 return mIccPhoneBookIntManager; 2597 } 2598 2599 //CDMA registerForEriFileLoaded(Handler h, int what, Object obj)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 unregisterForEriFileLoaded(Handler h)2606 public void unregisterForEriFileLoaded(Handler h) { 2607 mEriFileLoadedRegistrants.remove(h); 2608 } 2609 2610 //CDMA prepareEri()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 isEriFileLoaded()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 activateCellBroadcastSms(int activate, Message response)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 getCellBroadcastSmsConfig(Message response)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 setCellBroadcastSmsConfig(int[] configValuesArray, Message response)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 needsOtaServiceProvisioning()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 isCspPlmnEnabled()2677 public boolean isCspPlmnEnabled() { 2678 IccRecords r = mIccRecords.get(); 2679 return (r != null) ? r.isCspPlmnEnabled() : false; 2680 } 2681 isManualNetSelAllowed()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 isManualSelProhibitedInGlobalMode()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 registerForIccRecordEvents()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 unregisterForIccRecordEvents()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 exitEmergencyCallbackMode()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 handleEnterEmergencyCallbackMode(Message msg)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 handleExitEmergencyCallbackMode(Message msg)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 notifyEmergencyCallRegistrants(boolean started)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 */ handleTimerInEmergencyCallbackMode(int action)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 isIs683OtaSpDialStr(String dialStr)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 */ extractSelCodeFromOtaSpNum(String dialStr)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 */ checkOtaSpNumBasedOnSysSelCode(int sysSelCodeInt, String sch[])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 */ isCarrierOtaSpNum(String dialStr)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 isOtaSpNumber(String dialStr)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 getCdmaEriIconIndex()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 getCdmaEriIconMode()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 getCdmaEriText()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 phoneObjectUpdater(int newVoiceRadioTech)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 switchVoiceRadioTech(int newVoiceRadioTech)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 getIccSmsInterfaceManager()3210 public IccSmsInterfaceManager getIccSmsInterfaceManager(){ 3211 return mIccSmsInterfaceManager; 3212 } 3213 3214 @Override updatePhoneObject(int voiceRadioTech)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 setImsRegistrationState(boolean registered)3221 public void setImsRegistrationState(boolean registered) { 3222 mSST.setImsRegistrationState(registered); 3223 } 3224 3225 @Override getIccRecordsLoaded()3226 public boolean getIccRecordsLoaded() { 3227 return mIccCardProxy.getIccRecordsLoaded(); 3228 } 3229 3230 @Override getIccCard()3231 public IccCard getIccCard() { 3232 return mIccCardProxy; 3233 } 3234 3235 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)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 setOperatorBrandOverride(String brand)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 */ getOperatorNumeric()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 */ getCountryIso()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 notifyEcbmTimerReset(Boolean flag)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 registerForEcmTimerReset(Handler h, int what, Object obj)3369 public void registerForEcmTimerReset(Handler h, int what, Object obj) { 3370 mEcmTimerResetRegistrants.addUnique(h, what, obj); 3371 } 3372 3373 @Override unregisterForEcmTimerReset(Handler h)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 setVoiceMessageWaiting(int line, int countWaiting)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 logd(String s)3399 private void logd(String s) { 3400 Rlog.d(LOG_TAG, "[GsmCdmaPhone] " + s); 3401 } 3402 loge(String s)3403 private void loge(String s) { 3404 Rlog.e(LOG_TAG, "[GsmCdmaPhone] " + s); 3405 } 3406 3407 @Override isUtEnabled()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 getDtmfToneDelayKey()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 getWakeLock()3425 public PowerManager.WakeLock getWakeLock() { 3426 return mWakeLock; 3427 } 3428 3429 } 3430