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