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