1 /* 2 * Copyright (C) 2006 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.cdma; 18 19 import android.app.ActivityManagerNative; 20 import android.content.ContentValues; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.SharedPreferences; 24 import android.database.SQLException; 25 import android.net.Uri; 26 import android.os.AsyncResult; 27 import android.os.Handler; 28 import android.os.Message; 29 import android.os.PowerManager; 30 import android.os.PowerManager.WakeLock; 31 import android.os.Registrant; 32 import android.os.RegistrantList; 33 import android.os.SystemProperties; 34 import android.os.UserHandle; 35 import android.preference.PreferenceManager; 36 import android.provider.Settings; 37 import android.provider.Telephony; 38 import android.telephony.CellLocation; 39 import android.telephony.PhoneNumberUtils; 40 import android.telephony.ServiceState; 41 import android.telephony.SubscriptionManager; 42 import android.telephony.cdma.CdmaCellLocation; 43 import android.text.TextUtils; 44 import android.telephony.Rlog; 45 import android.util.Log; 46 47 import android.telephony.TelephonyManager; 48 49 import com.android.ims.ImsManager; 50 import com.android.internal.telephony.Call; 51 import com.android.internal.telephony.CallStateException; 52 import com.android.internal.telephony.CallTracker; 53 import com.android.internal.telephony.CommandException; 54 import com.android.internal.telephony.CommandsInterface; 55 import com.android.internal.telephony.Connection; 56 import com.android.internal.telephony.IccPhoneBookInterfaceManager; 57 import com.android.internal.telephony.MccTable; 58 import com.android.internal.telephony.MmiCode; 59 import com.android.internal.telephony.PhoneBase; 60 import com.android.internal.telephony.PhoneConstants; 61 import com.android.internal.telephony.PhoneNotifier; 62 import com.android.internal.telephony.PhoneProxy; 63 import com.android.internal.telephony.PhoneSubInfo; 64 import com.android.internal.telephony.ServiceStateTracker; 65 import com.android.internal.telephony.SubscriptionController; 66 import com.android.internal.telephony.TelephonyIntents; 67 import com.android.internal.telephony.TelephonyProperties; 68 import com.android.internal.telephony.UUSInfo; 69 import com.android.internal.telephony.dataconnection.DcTracker; 70 import com.android.internal.telephony.imsphone.ImsPhone; 71 import com.android.internal.telephony.uicc.IccException; 72 import com.android.internal.telephony.uicc.IccRecords; 73 import com.android.internal.telephony.uicc.RuimRecords; 74 import com.android.internal.telephony.uicc.UiccCard; 75 import com.android.internal.telephony.uicc.UiccCardApplication; 76 import com.android.internal.telephony.uicc.UiccController; 77 78 import java.io.FileDescriptor; 79 import java.io.PrintWriter; 80 import java.util.ArrayList; 81 import java.util.List; 82 import java.util.regex.Matcher; 83 import java.util.regex.Pattern; 84 85 86 /** 87 * {@hide} 88 */ 89 public class CDMAPhone extends PhoneBase { 90 static final String LOG_TAG = "CDMAPhone"; 91 private static final boolean DBG = true; 92 private static final boolean VDBG = false; /* STOP SHIP if true */ 93 94 // Default Emergency Callback Mode exit timer 95 private static final int DEFAULT_ECM_EXIT_TIMER_VALUE = 300000; 96 97 private static final String VM_NUMBER_CDMA = "vm_number_key_cdma"; 98 private String mVmNumber = null; 99 100 static final int RESTART_ECM_TIMER = 0; // restart Ecm timer 101 static final int CANCEL_ECM_TIMER = 1; // cancel Ecm timer 102 103 // Instance Variables 104 CdmaCallTracker mCT; 105 CdmaServiceStateTracker mSST; 106 CdmaSubscriptionSourceManager mCdmaSSM; 107 ArrayList <CdmaMmiCode> mPendingMmis = new ArrayList<CdmaMmiCode>(); 108 RuimPhoneBookInterfaceManager mRuimPhoneBookInterfaceManager; 109 int mCdmaSubscriptionSource = 110 CdmaSubscriptionSourceManager.SUBSCRIPTION_SOURCE_UNKNOWN; 111 PhoneSubInfo mSubInfo; 112 EriManager mEriManager; 113 WakeLock mWakeLock; 114 115 // mEriFileLoadedRegistrants are informed after the ERI text has been loaded 116 private final RegistrantList mEriFileLoadedRegistrants = new RegistrantList(); 117 118 // mEcmTimerResetRegistrants are informed after Ecm timer is canceled or re-started 119 private final RegistrantList mEcmTimerResetRegistrants = new RegistrantList(); 120 121 // mEcmExitRespRegistrant is informed after the phone has been exited 122 //the emergency callback mode 123 //keep track of if phone is in emergency callback mode 124 protected boolean mIsPhoneInEcmState; 125 private Registrant mEcmExitRespRegistrant; 126 protected String mImei; 127 protected String mImeiSv; 128 private String mEsn; 129 private String mMeid; 130 // string to define how the carrier specifies its own ota sp number 131 protected String mCarrierOtaSpNumSchema; 132 133 // A runnable which is used to automatically exit from Ecm after a period of time. 134 private Runnable mExitEcmRunnable = new Runnable() { 135 @Override 136 public void run() { 137 exitEmergencyCallbackMode(); 138 } 139 }; 140 141 Registrant mPostDialHandler; 142 143 static String PROPERTY_CDMA_HOME_OPERATOR_NUMERIC = "ro.cdma.home.operator.numeric"; 144 CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, int phoneId)145 public CDMAPhone(Context context, CommandsInterface ci, PhoneNotifier notifier, 146 int phoneId) { 147 super("CDMA", notifier, context, ci, false, phoneId); 148 initSstIcc(); 149 init(context, notifier); 150 } 151 initSstIcc()152 protected void initSstIcc() { 153 mSST = new CdmaServiceStateTracker(this); 154 } 155 init(Context context, PhoneNotifier notifier)156 protected void init(Context context, PhoneNotifier notifier) { 157 mCi.setPhoneType(PhoneConstants.PHONE_TYPE_CDMA); 158 mCT = new CdmaCallTracker(this); 159 mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context, mCi, this, 160 EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null); 161 mDcTracker = new DcTracker(this); 162 mRuimPhoneBookInterfaceManager = new RuimPhoneBookInterfaceManager(this); 163 mSubInfo = new PhoneSubInfo(this); 164 mEriManager = new EriManager(this, context, EriManager.ERI_FROM_XML); 165 166 mCi.registerForAvailable(this, EVENT_RADIO_AVAILABLE, null); 167 mCi.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null); 168 mCi.registerForOn(this, EVENT_RADIO_ON, null); 169 mCi.setOnSuppServiceNotification(this, EVENT_SSN, null); 170 mSST.registerForNetworkAttached(this, EVENT_REGISTERED_TO_NETWORK, null); 171 mCi.setEmergencyCallbackMode(this, EVENT_EMERGENCY_CALLBACK_MODE_ENTER, null); 172 mCi.registerForExitEmergencyCallbackMode(this, EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE, 173 null); 174 175 PowerManager pm 176 = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 177 mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,LOG_TAG); 178 179 TelephonyManager tm = TelephonyManager.from(mContext); 180 //Change the system setting 181 tm.setPhoneType(getPhoneId(), PhoneConstants.PHONE_TYPE_CDMA); 182 183 // This is needed to handle phone process crashes 184 String inEcm=SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE, "false"); 185 mIsPhoneInEcmState = inEcm.equals("true"); 186 if (mIsPhoneInEcmState) { 187 // Send a message which will invoke handleExitEmergencyCallbackMode 188 mCi.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE)); 189 } 190 191 // get the string that specifies the carrier OTA Sp number 192 mCarrierOtaSpNumSchema = tm.getOtaSpNumberSchemaForPhone(getPhoneId(), ""); 193 194 // Sets operator properties by retrieving from build-time system property 195 String operatorAlpha = SystemProperties.get("ro.cdma.home.operator.alpha"); 196 String operatorNumeric = SystemProperties.get(PROPERTY_CDMA_HOME_OPERATOR_NUMERIC); 197 log("init: operatorAlpha='" + operatorAlpha 198 + "' operatorNumeric='" + operatorNumeric + "'"); 199 if (mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP) == null) { 200 log("init: APP_FAM_3GPP == NULL"); 201 if (!TextUtils.isEmpty(operatorAlpha)) { 202 log("init: set 'gsm.sim.operator.alpha' to operator='" + operatorAlpha + "'"); 203 tm.setSimOperatorNameForPhone(mPhoneId, operatorAlpha); 204 } 205 if (!TextUtils.isEmpty(operatorNumeric)) { 206 log("init: set 'gsm.sim.operator.numeric' to operator='" + operatorNumeric + "'"); 207 log("update icc_operator_numeric=" + operatorNumeric); 208 tm.setSimOperatorNumericForPhone(mPhoneId, operatorNumeric); 209 210 SubscriptionController.getInstance().setMccMnc(operatorNumeric, getSubId()); 211 } 212 setIsoCountryProperty(operatorNumeric); 213 } 214 215 // Sets current entry in the telephony carrier table 216 updateCurrentCarrierInProvider(operatorNumeric); 217 } 218 219 @Override dispose()220 public void dispose() { 221 synchronized(PhoneProxy.lockForRadioTechnologyChange) { 222 super.dispose(); 223 log("dispose"); 224 225 //Unregister from all former registered events 226 unregisterForRuimRecordEvents(); 227 mCi.unregisterForAvailable(this); //EVENT_RADIO_AVAILABLE 228 mCi.unregisterForOffOrNotAvailable(this); //EVENT_RADIO_OFF_OR_NOT_AVAILABLE 229 mCi.unregisterForOn(this); //EVENT_RADIO_ON 230 mSST.unregisterForNetworkAttached(this); //EVENT_REGISTERED_TO_NETWORK 231 mCi.unSetOnSuppServiceNotification(this); 232 mCi.unregisterForExitEmergencyCallbackMode(this); 233 removeCallbacks(mExitEcmRunnable); 234 235 mPendingMmis.clear(); 236 237 //Force all referenced classes to unregister their former registered events 238 mCT.dispose(); 239 mDcTracker.dispose(); 240 mSST.dispose(); 241 mCdmaSSM.dispose(this); 242 mRuimPhoneBookInterfaceManager.dispose(); 243 mSubInfo.dispose(); 244 mEriManager.dispose(); 245 } 246 } 247 248 @Override removeReferences()249 public void removeReferences() { 250 log("removeReferences"); 251 mRuimPhoneBookInterfaceManager = null; 252 mSubInfo = null; 253 mCT = null; 254 mSST = null; 255 mEriManager = null; 256 mExitEcmRunnable = null; 257 258 super.removeReferences(); 259 } 260 261 @Override finalize()262 protected void finalize() { 263 if(DBG) Rlog.d(LOG_TAG, "CDMAPhone finalized"); 264 if (mWakeLock.isHeld()) { 265 Rlog.e(LOG_TAG, "UNEXPECTED; mWakeLock is held when finalizing."); 266 mWakeLock.release(); 267 } 268 } 269 270 @Override getServiceState()271 public ServiceState getServiceState() { 272 if (mSST == null || mSST.mSS.getState() != ServiceState.STATE_IN_SERVICE) { 273 if (mImsPhone != null) { 274 return ServiceState.mergeServiceStates( 275 (mSST == null) ? new ServiceState() : mSST.mSS, 276 mImsPhone.getServiceState()); 277 } 278 } 279 280 if (mSST != null) { 281 return mSST.mSS; 282 } else { 283 // avoid potential NPE in EmergencyCallHelper during Phone switch 284 return new ServiceState(); 285 } 286 } 287 288 289 @Override getCallTracker()290 public CallTracker getCallTracker() { 291 return mCT; 292 } 293 294 @Override getState()295 public PhoneConstants.State getState() { 296 if (mImsPhone != null) { 297 PhoneConstants.State imsState = mImsPhone.getState(); 298 if (imsState != PhoneConstants.State.IDLE) { 299 return imsState; 300 } 301 } 302 303 return mCT.mState; 304 } 305 306 @Override getServiceStateTracker()307 public ServiceStateTracker getServiceStateTracker() { 308 return mSST; 309 } 310 311 @Override getPhoneType()312 public int getPhoneType() { 313 return PhoneConstants.PHONE_TYPE_CDMA; 314 } 315 316 @Override canTransfer()317 public boolean canTransfer() { 318 Rlog.e(LOG_TAG, "canTransfer: not possible in CDMA"); 319 return false; 320 } 321 322 @Override getRingingCall()323 public Call getRingingCall() { 324 ImsPhone imPhone = mImsPhone; 325 if ( mCT.mRingingCall != null && mCT.mRingingCall.isRinging() ) { 326 return mCT.mRingingCall; 327 } else if ( imPhone != null ) { 328 return imPhone.getRingingCall(); 329 } 330 return mCT.mRingingCall; 331 } 332 333 @Override setUiTTYMode(int uiTtyMode, Message onComplete)334 public void setUiTTYMode(int uiTtyMode, Message onComplete) { 335 if (mImsPhone != null) { 336 mImsPhone.setUiTTYMode(uiTtyMode, onComplete); 337 } 338 } 339 340 @Override setMute(boolean muted)341 public void setMute(boolean muted) { 342 mCT.setMute(muted); 343 } 344 345 @Override getMute()346 public boolean getMute() { 347 return mCT.getMute(); 348 } 349 350 @Override conference()351 public void conference() { 352 if (mImsPhone != null && mImsPhone.canConference()) { 353 log("conference() - delegated to IMS phone"); 354 mImsPhone.conference(); 355 return; 356 } 357 // three way calls in CDMA will be handled by feature codes 358 Rlog.e(LOG_TAG, "conference: not possible in CDMA"); 359 } 360 361 @Override enableEnhancedVoicePrivacy(boolean enable, Message onComplete)362 public void enableEnhancedVoicePrivacy(boolean enable, Message onComplete) { 363 mCi.setPreferredVoicePrivacy(enable, onComplete); 364 } 365 366 @Override getEnhancedVoicePrivacy(Message onComplete)367 public void getEnhancedVoicePrivacy(Message onComplete) { 368 mCi.getPreferredVoicePrivacy(onComplete); 369 } 370 371 @Override clearDisconnected()372 public void clearDisconnected() { 373 mCT.clearDisconnected(); 374 } 375 376 @Override getDataActivityState()377 public DataActivityState getDataActivityState() { 378 DataActivityState ret = DataActivityState.NONE; 379 380 if (mSST.getCurrentDataConnectionState() == ServiceState.STATE_IN_SERVICE) { 381 382 switch (mDcTracker.getActivity()) { 383 case DATAIN: 384 ret = DataActivityState.DATAIN; 385 break; 386 387 case DATAOUT: 388 ret = DataActivityState.DATAOUT; 389 break; 390 391 case DATAINANDOUT: 392 ret = DataActivityState.DATAINANDOUT; 393 break; 394 395 case DORMANT: 396 ret = DataActivityState.DORMANT; 397 break; 398 399 default: 400 ret = DataActivityState.NONE; 401 break; 402 } 403 } 404 return ret; 405 } 406 407 @Override 408 public Connection dial(String dialString, int videoState)409 dial (String dialString, int videoState) throws CallStateException { 410 ImsPhone imsPhone = mImsPhone; 411 412 boolean imsUseEnabled = 413 ImsManager.isVolteEnabledByPlatform(mContext) && 414 ImsManager.isEnhanced4gLteModeSettingEnabledByUser(mContext) && 415 ImsManager.isNonTtyOrTtyOnVolteEnabled(mContext); 416 if (!imsUseEnabled) { 417 Rlog.w(LOG_TAG, "IMS is disabled: forced to CS"); 418 } 419 420 if (DBG) { 421 Rlog.d(LOG_TAG, "imsUseEnabled=" + imsUseEnabled + ", imsPhone=" + imsPhone 422 + ", imsPhone.isVolteEnabled()=" 423 + ((imsPhone != null) ? imsPhone.isVolteEnabled() : "N/A") 424 + ", imsPhone.getServiceState().getState()=" 425 + ((imsPhone != null) ? imsPhone.getServiceState().getState() : "N/A")); 426 } 427 428 if (imsUseEnabled && imsPhone != null && imsPhone.isVolteEnabled() 429 && ((imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE 430 && !PhoneNumberUtils.isEmergencyNumber(dialString)) 431 || (PhoneNumberUtils.isEmergencyNumber(dialString) 432 && mContext.getResources().getBoolean( 433 com.android.internal.R.bool.useImsAlwaysForEmergencyCall))) ) { 434 try { 435 if (DBG) Rlog.d(LOG_TAG, "Trying IMS PS call"); 436 return imsPhone.dial(dialString, videoState); 437 } catch (CallStateException e) { 438 if (DBG) Rlog.d(LOG_TAG, "IMS PS call exception " + e + 439 "imsUseEnabled =" + imsUseEnabled + ", imsPhone =" + imsPhone); 440 if (!ImsPhone.CS_FALLBACK.equals(e.getMessage())) { 441 CallStateException ce = new CallStateException(e.getMessage()); 442 ce.setStackTrace(e.getStackTrace()); 443 throw ce; 444 } 445 } 446 } 447 448 if (DBG) Rlog.d(LOG_TAG, "Trying (non-IMS) CS call"); 449 return dialInternal(dialString, null, videoState); 450 } 451 452 453 @Override 454 protected Connection dialInternal(String dialString, UUSInfo uusInfo, int videoState)455 dialInternal (String dialString, UUSInfo uusInfo, 456 int videoState) throws CallStateException { 457 // Need to make sure dialString gets parsed properly 458 String newDialString = PhoneNumberUtils.stripSeparators(dialString); 459 return mCT.dial(newDialString); 460 } 461 462 @Override dial(String dialString, UUSInfo uusInfo, int videoState)463 public Connection dial(String dialString, UUSInfo uusInfo, int videoState) 464 throws CallStateException { 465 throw new CallStateException("Sending UUS information NOT supported in CDMA!"); 466 } 467 468 @Override 469 public List<? extends MmiCode> getPendingMmiCodes()470 getPendingMmiCodes() { 471 return mPendingMmis; 472 } 473 474 @Override registerForSuppServiceNotification( Handler h, int what, Object obj)475 public void registerForSuppServiceNotification( 476 Handler h, int what, Object obj) { 477 Rlog.e(LOG_TAG, "method registerForSuppServiceNotification is NOT supported in CDMA!"); 478 } 479 480 @Override getBackgroundCall()481 public CdmaCall getBackgroundCall() { 482 return mCT.mBackgroundCall; 483 } 484 485 @Override handleInCallMmiCommands(String dialString)486 public boolean handleInCallMmiCommands(String dialString) { 487 Rlog.e(LOG_TAG, "method handleInCallMmiCommands is NOT supported in CDMA!"); 488 return false; 489 } 490 isInCall()491 boolean isInCall() { 492 CdmaCall.State foregroundCallState = getForegroundCall().getState(); 493 CdmaCall.State backgroundCallState = getBackgroundCall().getState(); 494 CdmaCall.State ringingCallState = getRingingCall().getState(); 495 496 return (foregroundCallState.isAlive() || backgroundCallState.isAlive() || ringingCallState 497 .isAlive()); 498 } 499 500 @Override unregisterForSuppServiceNotification(Handler h)501 public void unregisterForSuppServiceNotification(Handler h) { 502 Rlog.e(LOG_TAG, "method unregisterForSuppServiceNotification is NOT supported in CDMA!"); 503 } 504 505 @Override 506 public void acceptCall(int videoState)507 acceptCall(int videoState) throws CallStateException { 508 ImsPhone imsPhone = mImsPhone; 509 if ( imsPhone != null && imsPhone.getRingingCall().isRinging() ) { 510 imsPhone.acceptCall(videoState); 511 } else { 512 mCT.acceptCall(); 513 } 514 } 515 516 @Override 517 public void rejectCall()518 rejectCall() throws CallStateException { 519 mCT.rejectCall(); 520 } 521 522 @Override 523 public void switchHoldingAndActive()524 switchHoldingAndActive() throws CallStateException { 525 mCT.switchWaitingOrHoldingAndActive(); 526 } 527 528 @Override getIccSerialNumber()529 public String getIccSerialNumber() { 530 IccRecords r = mIccRecords.get(); 531 if (r == null) { 532 // to get ICCID form SIMRecords because it is on MF. 533 r = mUiccController.getIccRecords(mPhoneId, UiccController.APP_FAM_3GPP); 534 } 535 return (r != null) ? r.getIccId() : null; 536 } 537 538 @Override getLine1Number()539 public String getLine1Number() { 540 return mSST.getMdnNumber(); 541 } 542 543 @Override getCdmaPrlVersion()544 public String getCdmaPrlVersion(){ 545 return mSST.getPrlVersion(); 546 } 547 548 @Override getCdmaMin()549 public String getCdmaMin() { 550 return mSST.getCdmaMin(); 551 } 552 553 @Override isMinInfoReady()554 public boolean isMinInfoReady() { 555 return mSST.isMinInfoReady(); 556 } 557 558 @Override getCallWaiting(Message onComplete)559 public void getCallWaiting(Message onComplete) { 560 mCi.queryCallWaiting(CommandsInterface.SERVICE_CLASS_VOICE, onComplete); 561 } 562 563 @Override 564 public void setRadioPower(boolean power)565 setRadioPower(boolean power) { 566 mSST.setRadioPower(power); 567 } 568 569 @Override getEsn()570 public String getEsn() { 571 return mEsn; 572 } 573 574 @Override getMeid()575 public String getMeid() { 576 return mMeid; 577 } 578 579 @Override getNai()580 public String getNai() { 581 IccRecords r = mIccRecords.get(); 582 if (Log.isLoggable(LOG_TAG, Log.VERBOSE)) { 583 Rlog.v(LOG_TAG, "IccRecords is " + r); 584 } 585 return (r != null) ? r.getNAI() : null; 586 } 587 588 //returns MEID or ESN in CDMA 589 @Override getDeviceId()590 public String getDeviceId() { 591 String id = getMeid(); 592 if ((id == null) || id.matches("^0*$")) { 593 Rlog.d(LOG_TAG, "getDeviceId(): MEID is not initialized use ESN"); 594 id = getEsn(); 595 } 596 return id; 597 } 598 599 @Override getDeviceSvn()600 public String getDeviceSvn() { 601 Rlog.d(LOG_TAG, "getDeviceSvn(): return 0"); 602 return "0"; 603 } 604 605 @Override getSubscriberId()606 public String getSubscriberId() { 607 return mSST.getImsi(); 608 } 609 610 @Override getGroupIdLevel1()611 public String getGroupIdLevel1() { 612 Rlog.e(LOG_TAG, "GID1 is not available in CDMA"); 613 return null; 614 } 615 616 @Override getImei()617 public String getImei() { 618 Rlog.e(LOG_TAG, "getImei() called for CDMAPhone"); 619 return mImei; 620 } 621 622 @Override canConference()623 public boolean canConference() { 624 if (mImsPhone != null && mImsPhone.canConference()) { 625 return true; 626 } 627 Rlog.e(LOG_TAG, "canConference: not possible in CDMA"); 628 return false; 629 } 630 631 @Override getCellLocation()632 public CellLocation getCellLocation() { 633 CdmaCellLocation loc = mSST.mCellLoc; 634 635 int mode = Settings.Secure.getInt(getContext().getContentResolver(), 636 Settings.Secure.LOCATION_MODE, Settings.Secure.LOCATION_MODE_OFF); 637 if (mode == Settings.Secure.LOCATION_MODE_OFF) { 638 // clear lat/long values for location privacy 639 CdmaCellLocation privateLoc = new CdmaCellLocation(); 640 privateLoc.setCellLocationData(loc.getBaseStationId(), 641 CdmaCellLocation.INVALID_LAT_LONG, 642 CdmaCellLocation.INVALID_LAT_LONG, 643 loc.getSystemId(), loc.getNetworkId()); 644 loc = privateLoc; 645 } 646 return loc; 647 } 648 649 @Override getForegroundCall()650 public CdmaCall getForegroundCall() { 651 return mCT.mForegroundCall; 652 } 653 654 @Override setOnPostDialCharacter(Handler h, int what, Object obj)655 public void setOnPostDialCharacter(Handler h, int what, Object obj) { 656 mPostDialHandler = new Registrant(h, what, obj); 657 } 658 659 @Override handlePinMmi(String dialString)660 public boolean handlePinMmi(String dialString) { 661 CdmaMmiCode mmi = CdmaMmiCode.newFromDialString(dialString, this, mUiccApplication.get()); 662 663 if (mmi == null) { 664 Rlog.e(LOG_TAG, "Mmi is NULL!"); 665 return false; 666 } else if (mmi.isPinPukCommand()) { 667 mPendingMmis.add(mmi); 668 mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 669 mmi.processCode(); 670 return true; 671 } 672 Rlog.e(LOG_TAG, "Unrecognized mmi!"); 673 return false; 674 } 675 676 /** 677 * Removes the given MMI from the pending list and notifies registrants that 678 * it is complete. 679 * 680 * @param mmi MMI that is done 681 */ onMMIDone(CdmaMmiCode mmi)682 void onMMIDone(CdmaMmiCode mmi) { 683 /* 684 * Only notify complete if it's on the pending list. Otherwise, it's 685 * already been handled (eg, previously canceled). 686 */ 687 if (mPendingMmis.remove(mmi)) { 688 mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null)); 689 } 690 } 691 692 @Override setLine1Number(String alphaTag, String number, final Message onComplete)693 public boolean setLine1Number(String alphaTag, String number, final Message onComplete) { 694 Rlog.e(LOG_TAG, "setLine1Number: not possible in CDMA"); 695 return false; 696 } 697 698 @Override setCallWaiting(boolean enable, Message onComplete)699 public void setCallWaiting(boolean enable, Message onComplete) { 700 Rlog.e(LOG_TAG, "method setCallWaiting is NOT supported in CDMA!"); 701 } 702 703 @Override updateServiceLocation()704 public void updateServiceLocation() { 705 mSST.enableSingleLocationUpdate(); 706 } 707 708 @Override setDataRoamingEnabled(boolean enable)709 public void setDataRoamingEnabled(boolean enable) { 710 mDcTracker.setDataOnRoamingEnabled(enable); 711 } 712 713 @Override registerForCdmaOtaStatusChange(Handler h, int what, Object obj)714 public void registerForCdmaOtaStatusChange(Handler h, int what, Object obj) { 715 mCi.registerForCdmaOtaProvision(h, what, obj); 716 } 717 718 @Override unregisterForCdmaOtaStatusChange(Handler h)719 public void unregisterForCdmaOtaStatusChange(Handler h) { 720 mCi.unregisterForCdmaOtaProvision(h); 721 } 722 723 @Override registerForSubscriptionInfoReady(Handler h, int what, Object obj)724 public void registerForSubscriptionInfoReady(Handler h, int what, Object obj) { 725 mSST.registerForSubscriptionInfoReady(h, what, obj); 726 } 727 728 @Override unregisterForSubscriptionInfoReady(Handler h)729 public void unregisterForSubscriptionInfoReady(Handler h) { 730 mSST.unregisterForSubscriptionInfoReady(h); 731 } 732 733 @Override setOnEcbModeExitResponse(Handler h, int what, Object obj)734 public void setOnEcbModeExitResponse(Handler h, int what, Object obj) { 735 mEcmExitRespRegistrant = new Registrant (h, what, obj); 736 } 737 738 @Override unsetOnEcbModeExitResponse(Handler h)739 public void unsetOnEcbModeExitResponse(Handler h) { 740 mEcmExitRespRegistrant.clear(); 741 } 742 743 @Override registerForCallWaiting(Handler h, int what, Object obj)744 public void registerForCallWaiting(Handler h, int what, Object obj) { 745 mCT.registerForCallWaiting(h, what, obj); 746 } 747 748 @Override unregisterForCallWaiting(Handler h)749 public void unregisterForCallWaiting(Handler h) { 750 mCT.unregisterForCallWaiting(h); 751 } 752 753 @Override 754 public void getNeighboringCids(Message response)755 getNeighboringCids(Message response) { 756 /* 757 * This is currently not implemented. At least as of June 758 * 2009, there is no neighbor cell information available for 759 * CDMA because some party is resisting making this 760 * information readily available. Consequently, calling this 761 * function can have no useful effect. This situation may 762 * (and hopefully will) change in the future. 763 */ 764 if (response != null) { 765 CommandException ce = new CommandException( 766 CommandException.Error.REQUEST_NOT_SUPPORTED); 767 AsyncResult.forMessage(response).exception = ce; 768 response.sendToTarget(); 769 } 770 } 771 772 @Override getDataConnectionState(String apnType)773 public PhoneConstants.DataState getDataConnectionState(String apnType) { 774 PhoneConstants.DataState ret = PhoneConstants.DataState.DISCONNECTED; 775 776 if (mSST == null) { 777 // Radio Technology Change is ongoning, dispose() and removeReferences() have 778 // already been called 779 780 ret = PhoneConstants.DataState.DISCONNECTED; 781 } else if (mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) { 782 // If we're out of service, open TCP sockets may still work 783 // but no data will flow 784 ret = PhoneConstants.DataState.DISCONNECTED; 785 } else if (mDcTracker.isApnTypeEnabled(apnType) == false || 786 mDcTracker.isApnTypeActive(apnType) == false) { 787 ret = PhoneConstants.DataState.DISCONNECTED; 788 } else { 789 switch (mDcTracker.getState(apnType)) { 790 case RETRYING: 791 case FAILED: 792 case IDLE: 793 ret = PhoneConstants.DataState.DISCONNECTED; 794 break; 795 796 case CONNECTED: 797 case DISCONNECTING: 798 if ( mCT.mState != PhoneConstants.State.IDLE 799 && !mSST.isConcurrentVoiceAndDataAllowed()) { 800 ret = PhoneConstants.DataState.SUSPENDED; 801 } else { 802 ret = PhoneConstants.DataState.CONNECTED; 803 } 804 break; 805 806 case CONNECTING: 807 case SCANNING: 808 ret = PhoneConstants.DataState.CONNECTING; 809 break; 810 } 811 } 812 813 log("getDataConnectionState apnType=" + apnType + " ret=" + ret); 814 return ret; 815 } 816 817 @Override sendUssdResponse(String ussdMessge)818 public void sendUssdResponse(String ussdMessge) { 819 Rlog.e(LOG_TAG, "sendUssdResponse: not possible in CDMA"); 820 } 821 822 @Override sendDtmf(char c)823 public void sendDtmf(char c) { 824 if (!PhoneNumberUtils.is12Key(c)) { 825 Rlog.e(LOG_TAG, 826 "sendDtmf called with invalid character '" + c + "'"); 827 } else { 828 if (mCT.mState == PhoneConstants.State.OFFHOOK) { 829 mCi.sendDtmf(c, null); 830 } 831 } 832 } 833 834 @Override startDtmf(char c)835 public void startDtmf(char c) { 836 if (!PhoneNumberUtils.is12Key(c)) { 837 Rlog.e(LOG_TAG, 838 "startDtmf called with invalid character '" + c + "'"); 839 } else { 840 mCi.startDtmf(c, null); 841 } 842 } 843 844 @Override stopDtmf()845 public void stopDtmf() { 846 mCi.stopDtmf(null); 847 } 848 849 @Override sendBurstDtmf(String dtmfString, int on, int off, Message onComplete)850 public void sendBurstDtmf(String dtmfString, int on, int off, Message onComplete) { 851 boolean check = true; 852 for (int itr = 0;itr < dtmfString.length(); itr++) { 853 if (!PhoneNumberUtils.is12Key(dtmfString.charAt(itr))) { 854 Rlog.e(LOG_TAG, 855 "sendDtmf called with invalid character '" + dtmfString.charAt(itr)+ "'"); 856 check = false; 857 break; 858 } 859 } 860 if ((mCT.mState == PhoneConstants.State.OFFHOOK)&&(check)) { 861 mCi.sendBurstDtmf(dtmfString, on, off, onComplete); 862 } 863 } 864 865 @Override getAvailableNetworks(Message response)866 public void getAvailableNetworks(Message response) { 867 Rlog.e(LOG_TAG, "getAvailableNetworks: not possible in CDMA"); 868 } 869 870 @Override setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete)871 public void setOutgoingCallerIdDisplay(int commandInterfaceCLIRMode, Message onComplete) { 872 Rlog.e(LOG_TAG, "setOutgoingCallerIdDisplay: not possible in CDMA"); 873 } 874 875 @Override enableLocationUpdates()876 public void enableLocationUpdates() { 877 mSST.enableLocationUpdates(); 878 } 879 880 @Override disableLocationUpdates()881 public void disableLocationUpdates() { 882 mSST.disableLocationUpdates(); 883 } 884 885 @Override getDataCallList(Message response)886 public void getDataCallList(Message response) { 887 mCi.getDataCallList(response); 888 } 889 890 @Override getDataRoamingEnabled()891 public boolean getDataRoamingEnabled() { 892 return mDcTracker.getDataOnRoamingEnabled(); 893 } 894 895 @Override setDataEnabled(boolean enable)896 public void setDataEnabled(boolean enable) { 897 mDcTracker.setDataEnabled(enable); 898 } 899 900 @Override getDataEnabled()901 public boolean getDataEnabled() { 902 return mDcTracker.getDataEnabled(); 903 } 904 905 @Override setVoiceMailNumber(String alphaTag, String voiceMailNumber, Message onComplete)906 public void setVoiceMailNumber(String alphaTag, 907 String voiceMailNumber, 908 Message onComplete) { 909 Message resp; 910 mVmNumber = voiceMailNumber; 911 resp = obtainMessage(EVENT_SET_VM_NUMBER_DONE, 0, 0, onComplete); 912 IccRecords r = mIccRecords.get(); 913 if (r != null) { 914 r.setVoiceMailNumber(alphaTag, mVmNumber, resp); 915 } 916 } 917 918 @Override getVoiceMailNumber()919 public String getVoiceMailNumber() { 920 String number = null; 921 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 922 number = sp.getString(VM_NUMBER_CDMA + getPhoneId(), null); 923 if (TextUtils.isEmpty(number)) { 924 String[] listArray = getContext().getResources() 925 .getStringArray(com.android.internal.R.array.config_default_vm_number); 926 if (listArray != null && listArray.length > 0) { 927 for (int i=0; i<listArray.length; i++) { 928 if (!TextUtils.isEmpty(listArray[i])) { 929 String[] defaultVMNumberArray = listArray[i].split(";"); 930 if (defaultVMNumberArray != null && defaultVMNumberArray.length > 0) { 931 if (defaultVMNumberArray.length == 1) { 932 number = defaultVMNumberArray[0]; 933 } else if (defaultVMNumberArray.length == 2 && 934 !TextUtils.isEmpty(defaultVMNumberArray[1]) && 935 defaultVMNumberArray[1].equalsIgnoreCase(getGroupIdLevel1())) { 936 number = defaultVMNumberArray[0]; 937 break; 938 } 939 } 940 } 941 } 942 } 943 } 944 if (TextUtils.isEmpty(number)) { 945 // Read platform settings for dynamic voicemail number 946 if (getContext().getResources().getBoolean(com.android.internal 947 .R.bool.config_telephony_use_own_number_for_voicemail)) { 948 number = getLine1Number(); 949 } else { 950 number = "*86"; 951 } 952 } 953 return number; 954 } 955 956 // pending voice mail count updated after phone creation updateVoiceMail()957 private void updateVoiceMail() { 958 setVoiceMessageCount(getStoredVoiceMessageCount()); 959 } 960 961 @Override getVoiceMailAlphaTag()962 public String getVoiceMailAlphaTag() { 963 // TODO: Where can we get this value has to be clarified with QC. 964 String ret = "";//TODO: Remove = "", if we know where to get this value. 965 966 //ret = mSIMRecords.getVoiceMailAlphaTag(); 967 968 if (ret == null || ret.length() == 0) { 969 return mContext.getText( 970 com.android.internal.R.string.defaultVoiceMailAlphaTag).toString(); 971 } 972 973 return ret; 974 } 975 976 @Override getCallForwardingOption(int commandInterfaceCFReason, Message onComplete)977 public void getCallForwardingOption(int commandInterfaceCFReason, Message onComplete) { 978 Rlog.e(LOG_TAG, "getCallForwardingOption: not possible in CDMA"); 979 } 980 981 @Override setCallForwardingOption(int commandInterfaceCFAction, int commandInterfaceCFReason, String dialingNumber, int timerSeconds, Message onComplete)982 public void setCallForwardingOption(int commandInterfaceCFAction, 983 int commandInterfaceCFReason, 984 String dialingNumber, 985 int timerSeconds, 986 Message onComplete) { 987 Rlog.e(LOG_TAG, "setCallForwardingOption: not possible in CDMA"); 988 } 989 990 @Override 991 public void getOutgoingCallerIdDisplay(Message onComplete)992 getOutgoingCallerIdDisplay(Message onComplete) { 993 Rlog.e(LOG_TAG, "getOutgoingCallerIdDisplay: not possible in CDMA"); 994 } 995 996 @Override 997 public boolean getCallForwardingIndicator()998 getCallForwardingIndicator() { 999 Rlog.e(LOG_TAG, "getCallForwardingIndicator: not possible in CDMA"); 1000 return false; 1001 } 1002 1003 @Override explicitCallTransfer()1004 public void explicitCallTransfer() { 1005 Rlog.e(LOG_TAG, "explicitCallTransfer: not possible in CDMA"); 1006 } 1007 1008 @Override getLine1AlphaTag()1009 public String getLine1AlphaTag() { 1010 Rlog.e(LOG_TAG, "getLine1AlphaTag: not possible in CDMA"); 1011 return null; 1012 } 1013 1014 /** 1015 * Notify any interested party of a Phone state change 1016 * {@link com.android.internal.telephony.PhoneConstants.State} 1017 */ notifyPhoneStateChanged()1018 /*package*/ void notifyPhoneStateChanged() { 1019 mNotifier.notifyPhoneState(this); 1020 } 1021 1022 /** 1023 * Notify registrants of a change in the call state. This notifies changes in 1024 * {@link com.android.internal.telephony.Call.State}. Use this when changes 1025 * in the precise call state are needed, else use notifyPhoneStateChanged. 1026 */ notifyPreciseCallStateChanged()1027 /*package*/ void notifyPreciseCallStateChanged() { 1028 /* we'd love it if this was package-scoped*/ 1029 super.notifyPreciseCallStateChangedP(); 1030 } 1031 notifyServiceStateChanged(ServiceState ss)1032 void notifyServiceStateChanged(ServiceState ss) { 1033 super.notifyServiceStateChangedP(ss); 1034 } 1035 notifyLocationChanged()1036 void notifyLocationChanged() { 1037 mNotifier.notifyCellLocation(this); 1038 } 1039 notifyNewRingingConnection(Connection c)1040 public void notifyNewRingingConnection(Connection c) { 1041 super.notifyNewRingingConnectionP(c); 1042 } 1043 notifyDisconnect(Connection cn)1044 /*package*/ void notifyDisconnect(Connection cn) { 1045 mDisconnectRegistrants.notifyResult(cn); 1046 1047 mNotifier.notifyDisconnectCause(cn.getDisconnectCause(), cn.getPreciseDisconnectCause()); 1048 } 1049 notifyUnknownConnection(Connection connection)1050 void notifyUnknownConnection(Connection connection) { 1051 mUnknownConnectionRegistrants.notifyResult(connection); 1052 } 1053 1054 @Override isInEmergencyCall()1055 public boolean isInEmergencyCall() { 1056 return mCT.isInEmergencyCall(); 1057 } 1058 1059 @Override isInEcm()1060 public boolean isInEcm() { 1061 return mIsPhoneInEcmState; 1062 } 1063 sendEmergencyCallbackModeChange()1064 void sendEmergencyCallbackModeChange(){ 1065 //Send an Intent 1066 Intent intent = new Intent(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED); 1067 intent.putExtra(PhoneConstants.PHONE_IN_ECM_STATE, mIsPhoneInEcmState); 1068 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, getPhoneId()); 1069 ActivityManagerNative.broadcastStickyIntent(intent,null,UserHandle.USER_ALL); 1070 if (DBG) Rlog.d(LOG_TAG, "sendEmergencyCallbackModeChange"); 1071 } 1072 1073 @Override exitEmergencyCallbackMode()1074 public void exitEmergencyCallbackMode() { 1075 if (mWakeLock.isHeld()) { 1076 mWakeLock.release(); 1077 } 1078 // Send a message which will invoke handleExitEmergencyCallbackMode 1079 mCi.exitEmergencyCallbackMode(obtainMessage(EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE)); 1080 } 1081 handleEnterEmergencyCallbackMode(Message msg)1082 private void handleEnterEmergencyCallbackMode(Message msg) { 1083 if (DBG) { 1084 Rlog.d(LOG_TAG, "handleEnterEmergencyCallbackMode,mIsPhoneInEcmState= " 1085 + mIsPhoneInEcmState); 1086 } 1087 // if phone is not in Ecm mode, and it's changed to Ecm mode 1088 if (mIsPhoneInEcmState == false) { 1089 mIsPhoneInEcmState = true; 1090 // notify change 1091 sendEmergencyCallbackModeChange(); 1092 setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "true"); 1093 1094 // Post this runnable so we will automatically exit 1095 // if no one invokes exitEmergencyCallbackMode() directly. 1096 long delayInMillis = SystemProperties.getLong( 1097 TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE); 1098 postDelayed(mExitEcmRunnable, delayInMillis); 1099 // We don't want to go to sleep while in Ecm 1100 mWakeLock.acquire(); 1101 } 1102 } 1103 handleExitEmergencyCallbackMode(Message msg)1104 private void handleExitEmergencyCallbackMode(Message msg) { 1105 AsyncResult ar = (AsyncResult)msg.obj; 1106 if (DBG) { 1107 Rlog.d(LOG_TAG, "handleExitEmergencyCallbackMode,ar.exception , mIsPhoneInEcmState " 1108 + ar.exception + mIsPhoneInEcmState); 1109 } 1110 // Remove pending exit Ecm runnable, if any 1111 removeCallbacks(mExitEcmRunnable); 1112 1113 if (mEcmExitRespRegistrant != null) { 1114 mEcmExitRespRegistrant.notifyRegistrant(ar); 1115 } 1116 // if exiting ecm success 1117 if (ar.exception == null) { 1118 if (mIsPhoneInEcmState) { 1119 mIsPhoneInEcmState = false; 1120 setSystemProperty(TelephonyProperties.PROPERTY_INECM_MODE, "false"); 1121 } 1122 // send an Intent 1123 sendEmergencyCallbackModeChange(); 1124 // Re-initiate data connection 1125 mDcTracker.setInternalDataEnabled(true); 1126 } 1127 } 1128 1129 /** 1130 * Handle to cancel or restart Ecm timer in emergency call back mode 1131 * if action is CANCEL_ECM_TIMER, cancel Ecm timer and notify apps the timer is canceled; 1132 * otherwise, restart Ecm timer and notify apps the timer is restarted. 1133 */ handleTimerInEmergencyCallbackMode(int action)1134 void handleTimerInEmergencyCallbackMode(int action) { 1135 switch(action) { 1136 case CANCEL_ECM_TIMER: 1137 removeCallbacks(mExitEcmRunnable); 1138 mEcmTimerResetRegistrants.notifyResult(Boolean.TRUE); 1139 break; 1140 case RESTART_ECM_TIMER: 1141 long delayInMillis = SystemProperties.getLong( 1142 TelephonyProperties.PROPERTY_ECM_EXIT_TIMER, DEFAULT_ECM_EXIT_TIMER_VALUE); 1143 postDelayed(mExitEcmRunnable, delayInMillis); 1144 mEcmTimerResetRegistrants.notifyResult(Boolean.FALSE); 1145 break; 1146 default: 1147 Rlog.e(LOG_TAG, "handleTimerInEmergencyCallbackMode, unsupported action " + action); 1148 } 1149 } 1150 notifyEcbmTimerReset(Boolean flag)1151 public void notifyEcbmTimerReset(Boolean flag) { 1152 mEcmTimerResetRegistrants.notifyResult(flag); 1153 } 1154 1155 /** 1156 * Registration point for Ecm timer reset 1157 * @param h handler to notify 1158 * @param what User-defined message code 1159 * @param obj placed in Message.obj 1160 */ 1161 @Override registerForEcmTimerReset(Handler h, int what, Object obj)1162 public void registerForEcmTimerReset(Handler h, int what, Object obj) { 1163 mEcmTimerResetRegistrants.addUnique(h, what, obj); 1164 } 1165 1166 @Override unregisterForEcmTimerReset(Handler h)1167 public void unregisterForEcmTimerReset(Handler h) { 1168 mEcmTimerResetRegistrants.remove(h); 1169 } 1170 1171 @Override handleMessage(Message msg)1172 public void handleMessage(Message msg) { 1173 AsyncResult ar; 1174 Message onComplete; 1175 1176 // messages to be handled whether or not the phone is being destroyed 1177 // should only include messages which are being re-directed and do not use 1178 // resources of the phone being destroyed 1179 switch (msg.what) { 1180 // handle the select network completion callbacks. 1181 case EVENT_SET_NETWORK_MANUAL_COMPLETE: 1182 case EVENT_SET_NETWORK_AUTOMATIC_COMPLETE: 1183 super.handleMessage(msg); 1184 return; 1185 } 1186 1187 if (!mIsTheCurrentActivePhone) { 1188 Rlog.e(LOG_TAG, "Received message " + msg + 1189 "[" + msg.what + "] while being destroyed. Ignoring."); 1190 return; 1191 } 1192 switch(msg.what) { 1193 case EVENT_RADIO_AVAILABLE: { 1194 mCi.getBasebandVersion(obtainMessage(EVENT_GET_BASEBAND_VERSION_DONE)); 1195 1196 mCi.getDeviceIdentity(obtainMessage(EVENT_GET_DEVICE_IDENTITY_DONE)); 1197 mCi.getRadioCapability(obtainMessage(EVENT_GET_RADIO_CAPABILITY)); 1198 } 1199 break; 1200 1201 case EVENT_GET_BASEBAND_VERSION_DONE:{ 1202 ar = (AsyncResult)msg.obj; 1203 1204 if (ar.exception != null) { 1205 break; 1206 } 1207 1208 if (DBG) Rlog.d(LOG_TAG, "Baseband version: " + ar.result); 1209 TelephonyManager.from(mContext).setBasebandVersionForPhone(getPhoneId(), 1210 (String)ar.result); 1211 } 1212 break; 1213 1214 case EVENT_GET_DEVICE_IDENTITY_DONE:{ 1215 ar = (AsyncResult)msg.obj; 1216 1217 if (ar.exception != null) { 1218 break; 1219 } 1220 String[] respId = (String[])ar.result; 1221 mImei = respId[0]; 1222 mImeiSv = respId[1]; 1223 mEsn = respId[2]; 1224 mMeid = respId[3]; 1225 } 1226 break; 1227 1228 case EVENT_EMERGENCY_CALLBACK_MODE_ENTER:{ 1229 handleEnterEmergencyCallbackMode(msg); 1230 } 1231 break; 1232 1233 case EVENT_EXIT_EMERGENCY_CALLBACK_RESPONSE:{ 1234 handleExitEmergencyCallbackMode(msg); 1235 } 1236 break; 1237 1238 case EVENT_RUIM_RECORDS_LOADED:{ 1239 Rlog.d(LOG_TAG, "Event EVENT_RUIM_RECORDS_LOADED Received"); 1240 updateCurrentCarrierInProvider(); 1241 // Notify voicemails. 1242 log("notifyMessageWaitingChanged"); 1243 mNotifier.notifyMessageWaitingChanged(this); 1244 updateVoiceMail(); 1245 } 1246 break; 1247 1248 case EVENT_RADIO_OFF_OR_NOT_AVAILABLE:{ 1249 Rlog.d(LOG_TAG, "Event EVENT_RADIO_OFF_OR_NOT_AVAILABLE Received"); 1250 ImsPhone imsPhone = mImsPhone; 1251 if (imsPhone != null) { 1252 imsPhone.getServiceState().setStateOff(); 1253 } 1254 } 1255 break; 1256 1257 case EVENT_RADIO_ON:{ 1258 Rlog.d(LOG_TAG, "Event EVENT_RADIO_ON Received"); 1259 handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource()); 1260 } 1261 break; 1262 1263 case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED:{ 1264 Rlog.d(LOG_TAG, "EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED"); 1265 handleCdmaSubscriptionSource(mCdmaSSM.getCdmaSubscriptionSource()); 1266 } 1267 break; 1268 1269 case EVENT_SSN:{ 1270 Rlog.d(LOG_TAG, "Event EVENT_SSN Received"); 1271 } 1272 break; 1273 1274 case EVENT_REGISTERED_TO_NETWORK:{ 1275 Rlog.d(LOG_TAG, "Event EVENT_REGISTERED_TO_NETWORK Received"); 1276 } 1277 break; 1278 1279 case EVENT_NV_READY:{ 1280 Rlog.d(LOG_TAG, "Event EVENT_NV_READY Received"); 1281 prepareEri(); 1282 // Notify voicemails. 1283 log("notifyMessageWaitingChanged"); 1284 mNotifier.notifyMessageWaitingChanged(this); 1285 updateVoiceMail(); 1286 } 1287 break; 1288 1289 case EVENT_SET_VM_NUMBER_DONE:{ 1290 ar = (AsyncResult)msg.obj; 1291 if (IccException.class.isInstance(ar.exception)) { 1292 storeVoiceMailNumber(mVmNumber); 1293 ar.exception = null; 1294 } 1295 onComplete = (Message) ar.userObj; 1296 if (onComplete != null) { 1297 AsyncResult.forMessage(onComplete, ar.result, ar.exception); 1298 onComplete.sendToTarget(); 1299 } 1300 } 1301 break; 1302 1303 default:{ 1304 super.handleMessage(msg); 1305 } 1306 } 1307 } 1308 getUiccCardApplication()1309 protected UiccCardApplication getUiccCardApplication() { 1310 return mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP2); 1311 } 1312 1313 @Override onUpdateIccAvailability()1314 protected void onUpdateIccAvailability() { 1315 if (mUiccController == null ) { 1316 return; 1317 } 1318 1319 UiccCardApplication newUiccApplication = getUiccCardApplication(); 1320 1321 if (newUiccApplication == null) { 1322 log("can't find 3GPP2 application; trying APP_FAM_3GPP"); 1323 newUiccApplication = 1324 mUiccController.getUiccCardApplication(mPhoneId, UiccController.APP_FAM_3GPP); 1325 } 1326 1327 UiccCardApplication app = mUiccApplication.get(); 1328 if (app != newUiccApplication) { 1329 if (app != null) { 1330 log("Removing stale icc objects."); 1331 if (mIccRecords.get() != null) { 1332 unregisterForRuimRecordEvents(); 1333 } 1334 mIccRecords.set(null); 1335 mUiccApplication.set(null); 1336 } 1337 if (newUiccApplication != null) { 1338 log("New Uicc application found"); 1339 mUiccApplication.set(newUiccApplication); 1340 mIccRecords.set(newUiccApplication.getIccRecords()); 1341 registerForRuimRecordEvents(); 1342 } 1343 } 1344 } 1345 1346 /** 1347 * Handles the call to get the subscription source 1348 * 1349 * @param newSubscriptionSource holds the new CDMA subscription source value 1350 */ handleCdmaSubscriptionSource(int newSubscriptionSource)1351 private void handleCdmaSubscriptionSource(int newSubscriptionSource) { 1352 if (newSubscriptionSource != mCdmaSubscriptionSource) { 1353 mCdmaSubscriptionSource = newSubscriptionSource; 1354 if (newSubscriptionSource == CDMA_SUBSCRIPTION_NV) { 1355 // NV is ready when subscription source is NV 1356 sendMessage(obtainMessage(EVENT_NV_READY)); 1357 } 1358 } 1359 } 1360 1361 /** 1362 * Retrieves the PhoneSubInfo of the CDMAPhone 1363 */ 1364 @Override getPhoneSubInfo()1365 public PhoneSubInfo getPhoneSubInfo() { 1366 return mSubInfo; 1367 } 1368 1369 /** 1370 * Retrieves the IccPhoneBookInterfaceManager of the CDMAPhone 1371 */ 1372 @Override getIccPhoneBookInterfaceManager()1373 public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager() { 1374 return mRuimPhoneBookInterfaceManager; 1375 } 1376 registerForEriFileLoaded(Handler h, int what, Object obj)1377 public void registerForEriFileLoaded(Handler h, int what, Object obj) { 1378 Registrant r = new Registrant (h, what, obj); 1379 mEriFileLoadedRegistrants.add(r); 1380 } 1381 unregisterForEriFileLoaded(Handler h)1382 public void unregisterForEriFileLoaded(Handler h) { 1383 mEriFileLoadedRegistrants.remove(h); 1384 } 1385 1386 // override for allowing access from other classes of this package 1387 /** 1388 * {@inheritDoc} 1389 */ 1390 @Override setSystemProperty(String property, String value)1391 public void setSystemProperty(String property, String value) { 1392 super.setSystemProperty(property, value); 1393 } 1394 1395 // override for allowing access from other classes of this package 1396 /** 1397 * {@inheritDoc} 1398 */ 1399 @Override getSystemProperty(String property, String defValue)1400 public String getSystemProperty(String property, String defValue) { 1401 return super.getSystemProperty(property, defValue); 1402 } 1403 1404 /** 1405 * Activate or deactivate cell broadcast SMS. 1406 * 1407 * @param activate 0 = activate, 1 = deactivate 1408 * @param response Callback message is empty on completion 1409 */ 1410 @Override activateCellBroadcastSms(int activate, Message response)1411 public void activateCellBroadcastSms(int activate, Message response) { 1412 Rlog.e(LOG_TAG, "[CDMAPhone] activateCellBroadcastSms() is obsolete; use SmsManager"); 1413 response.sendToTarget(); 1414 } 1415 1416 /** 1417 * Query the current configuration of cdma cell broadcast SMS. 1418 * 1419 * @param response Callback message is empty on completion 1420 */ 1421 @Override getCellBroadcastSmsConfig(Message response)1422 public void getCellBroadcastSmsConfig(Message response) { 1423 Rlog.e(LOG_TAG, "[CDMAPhone] getCellBroadcastSmsConfig() is obsolete; use SmsManager"); 1424 response.sendToTarget(); 1425 } 1426 1427 /** 1428 * Configure cdma cell broadcast SMS. 1429 * 1430 * @param response Callback message is empty on completion 1431 */ 1432 @Override setCellBroadcastSmsConfig(int[] configValuesArray, Message response)1433 public void setCellBroadcastSmsConfig(int[] configValuesArray, Message response) { 1434 Rlog.e(LOG_TAG, "[CDMAPhone] setCellBroadcastSmsConfig() is obsolete; use SmsManager"); 1435 response.sendToTarget(); 1436 } 1437 1438 /** 1439 * Returns true if OTA Service Provisioning needs to be performed. 1440 */ 1441 @Override needsOtaServiceProvisioning()1442 public boolean needsOtaServiceProvisioning() { 1443 return mSST.getOtasp() != ServiceStateTracker.OTASP_NOT_NEEDED; 1444 } 1445 1446 private static final String IS683A_FEATURE_CODE = "*228"; 1447 private static final int IS683A_FEATURE_CODE_NUM_DIGITS = 4; 1448 private static final int IS683A_SYS_SEL_CODE_NUM_DIGITS = 2; 1449 private static final int IS683A_SYS_SEL_CODE_OFFSET = 4; 1450 1451 private static final int IS683_CONST_800MHZ_A_BAND = 0; 1452 private static final int IS683_CONST_800MHZ_B_BAND = 1; 1453 private static final int IS683_CONST_1900MHZ_A_BLOCK = 2; 1454 private static final int IS683_CONST_1900MHZ_B_BLOCK = 3; 1455 private static final int IS683_CONST_1900MHZ_C_BLOCK = 4; 1456 private static final int IS683_CONST_1900MHZ_D_BLOCK = 5; 1457 private static final int IS683_CONST_1900MHZ_E_BLOCK = 6; 1458 private static final int IS683_CONST_1900MHZ_F_BLOCK = 7; 1459 private static final int INVALID_SYSTEM_SELECTION_CODE = -1; 1460 isIs683OtaSpDialStr(String dialStr)1461 private static boolean isIs683OtaSpDialStr(String dialStr) { 1462 int sysSelCodeInt; 1463 boolean isOtaspDialString = false; 1464 int dialStrLen = dialStr.length(); 1465 1466 if (dialStrLen == IS683A_FEATURE_CODE_NUM_DIGITS) { 1467 if (dialStr.equals(IS683A_FEATURE_CODE)) { 1468 isOtaspDialString = true; 1469 } 1470 } else { 1471 sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr); 1472 switch (sysSelCodeInt) { 1473 case IS683_CONST_800MHZ_A_BAND: 1474 case IS683_CONST_800MHZ_B_BAND: 1475 case IS683_CONST_1900MHZ_A_BLOCK: 1476 case IS683_CONST_1900MHZ_B_BLOCK: 1477 case IS683_CONST_1900MHZ_C_BLOCK: 1478 case IS683_CONST_1900MHZ_D_BLOCK: 1479 case IS683_CONST_1900MHZ_E_BLOCK: 1480 case IS683_CONST_1900MHZ_F_BLOCK: 1481 isOtaspDialString = true; 1482 break; 1483 default: 1484 break; 1485 } 1486 } 1487 return isOtaspDialString; 1488 } 1489 /** 1490 * This function extracts the system selection code from the dial string. 1491 */ extractSelCodeFromOtaSpNum(String dialStr)1492 private static int extractSelCodeFromOtaSpNum(String dialStr) { 1493 int dialStrLen = dialStr.length(); 1494 int sysSelCodeInt = INVALID_SYSTEM_SELECTION_CODE; 1495 1496 if ((dialStr.regionMatches(0, IS683A_FEATURE_CODE, 1497 0, IS683A_FEATURE_CODE_NUM_DIGITS)) && 1498 (dialStrLen >= (IS683A_FEATURE_CODE_NUM_DIGITS + 1499 IS683A_SYS_SEL_CODE_NUM_DIGITS))) { 1500 // Since we checked the condition above, the system selection code 1501 // extracted from dialStr will not cause any exception 1502 sysSelCodeInt = Integer.parseInt ( 1503 dialStr.substring (IS683A_FEATURE_CODE_NUM_DIGITS, 1504 IS683A_FEATURE_CODE_NUM_DIGITS + IS683A_SYS_SEL_CODE_NUM_DIGITS)); 1505 } 1506 if (DBG) Rlog.d(LOG_TAG, "extractSelCodeFromOtaSpNum " + sysSelCodeInt); 1507 return sysSelCodeInt; 1508 } 1509 1510 /** 1511 * This function checks if the system selection code extracted from 1512 * the dial string "sysSelCodeInt' is the system selection code specified 1513 * in the carrier ota sp number schema "sch". 1514 */ 1515 private static boolean checkOtaSpNumBasedOnSysSelCode(int sysSelCodeInt, String sch[])1516 checkOtaSpNumBasedOnSysSelCode (int sysSelCodeInt, String sch[]) { 1517 boolean isOtaSpNum = false; 1518 try { 1519 // Get how many number of system selection code ranges 1520 int selRc = Integer.parseInt(sch[1]); 1521 for (int i = 0; i < selRc; i++) { 1522 if (!TextUtils.isEmpty(sch[i+2]) && !TextUtils.isEmpty(sch[i+3])) { 1523 int selMin = Integer.parseInt(sch[i+2]); 1524 int selMax = Integer.parseInt(sch[i+3]); 1525 // Check if the selection code extracted from the dial string falls 1526 // within any of the range pairs specified in the schema. 1527 if ((sysSelCodeInt >= selMin) && (sysSelCodeInt <= selMax)) { 1528 isOtaSpNum = true; 1529 break; 1530 } 1531 } 1532 } 1533 } catch (NumberFormatException ex) { 1534 // If the carrier ota sp number schema is not correct, we still allow dial 1535 // and only log the error: 1536 Rlog.e(LOG_TAG, "checkOtaSpNumBasedOnSysSelCode, error", ex); 1537 } 1538 return isOtaSpNum; 1539 } 1540 1541 // Define the pattern/format for carrier specified OTASP number schema. 1542 // It separates by comma and/or whitespace. 1543 private static Pattern pOtaSpNumSchema = Pattern.compile("[,\\s]+"); 1544 1545 /** 1546 * The following function checks if a dial string is a carrier specified 1547 * OTASP number or not by checking against the OTASP number schema stored 1548 * in PROPERTY_OTASP_NUM_SCHEMA. 1549 * 1550 * Currently, there are 2 schemas for carriers to specify the OTASP number: 1551 * 1) Use system selection code: 1552 * The schema is: 1553 * SELC,the # of code pairs,min1,max1,min2,max2,... 1554 * e.g "SELC,3,10,20,30,40,60,70" indicates that there are 3 pairs of 1555 * selection codes, and they are {10,20}, {30,40} and {60,70} respectively. 1556 * 1557 * 2) Use feature code: 1558 * The schema is: 1559 * "FC,length of feature code,feature code". 1560 * e.g "FC,2,*2" indicates that the length of the feature code is 2, 1561 * and the code itself is "*2". 1562 */ isCarrierOtaSpNum(String dialStr)1563 private boolean isCarrierOtaSpNum(String dialStr) { 1564 boolean isOtaSpNum = false; 1565 int sysSelCodeInt = extractSelCodeFromOtaSpNum(dialStr); 1566 if (sysSelCodeInt == INVALID_SYSTEM_SELECTION_CODE) { 1567 return isOtaSpNum; 1568 } 1569 // mCarrierOtaSpNumSchema is retrieved from PROPERTY_OTASP_NUM_SCHEMA: 1570 if (!TextUtils.isEmpty(mCarrierOtaSpNumSchema)) { 1571 Matcher m = pOtaSpNumSchema.matcher(mCarrierOtaSpNumSchema); 1572 if (DBG) { 1573 Rlog.d(LOG_TAG, "isCarrierOtaSpNum,schema" + mCarrierOtaSpNumSchema); 1574 } 1575 1576 if (m.find()) { 1577 String sch[] = pOtaSpNumSchema.split(mCarrierOtaSpNumSchema); 1578 // If carrier uses system selection code mechanism 1579 if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("SELC")) { 1580 if (sysSelCodeInt!=INVALID_SYSTEM_SELECTION_CODE) { 1581 isOtaSpNum=checkOtaSpNumBasedOnSysSelCode(sysSelCodeInt,sch); 1582 } else { 1583 if (DBG) { 1584 Rlog.d(LOG_TAG, "isCarrierOtaSpNum,sysSelCodeInt is invalid"); 1585 } 1586 } 1587 } else if (!TextUtils.isEmpty(sch[0]) && sch[0].equals("FC")) { 1588 int fcLen = Integer.parseInt(sch[1]); 1589 String fc = sch[2]; 1590 if (dialStr.regionMatches(0,fc,0,fcLen)) { 1591 isOtaSpNum = true; 1592 } else { 1593 if (DBG) Rlog.d(LOG_TAG, "isCarrierOtaSpNum,not otasp number"); 1594 } 1595 } else { 1596 if (DBG) { 1597 Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema not supported" + sch[0]); 1598 } 1599 } 1600 } else { 1601 if (DBG) { 1602 Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern not right" + 1603 mCarrierOtaSpNumSchema); 1604 } 1605 } 1606 } else { 1607 if (DBG) Rlog.d(LOG_TAG, "isCarrierOtaSpNum,ota schema pattern empty"); 1608 } 1609 return isOtaSpNum; 1610 } 1611 1612 /** 1613 * isOTASPNumber: checks a given number against the IS-683A OTASP dial string and carrier 1614 * OTASP dial string. 1615 * 1616 * @param dialStr the number to look up. 1617 * @return true if the number is in IS-683A OTASP dial string or carrier OTASP dial string 1618 */ 1619 @Override isOtaSpNumber(String dialStr)1620 public boolean isOtaSpNumber(String dialStr){ 1621 boolean isOtaSpNum = false; 1622 String dialableStr = PhoneNumberUtils.extractNetworkPortionAlt(dialStr); 1623 if (dialableStr != null) { 1624 isOtaSpNum = isIs683OtaSpDialStr(dialableStr); 1625 if (isOtaSpNum == false) { 1626 isOtaSpNum = isCarrierOtaSpNum(dialableStr); 1627 } 1628 } 1629 if (DBG) Rlog.d(LOG_TAG, "isOtaSpNumber " + isOtaSpNum); 1630 return isOtaSpNum; 1631 } 1632 1633 @Override getCdmaEriIconIndex()1634 public int getCdmaEriIconIndex() { 1635 return getServiceState().getCdmaEriIconIndex(); 1636 } 1637 1638 /** 1639 * Returns the CDMA ERI icon mode, 1640 * 0 - ON 1641 * 1 - FLASHING 1642 */ 1643 @Override getCdmaEriIconMode()1644 public int getCdmaEriIconMode() { 1645 return getServiceState().getCdmaEriIconMode(); 1646 } 1647 1648 /** 1649 * Returns the CDMA ERI text, 1650 */ 1651 @Override getCdmaEriText()1652 public String getCdmaEriText() { 1653 int roamInd = getServiceState().getCdmaRoamingIndicator(); 1654 int defRoamInd = getServiceState().getCdmaDefaultRoamingIndicator(); 1655 return mEriManager.getCdmaEriText(roamInd, defRoamInd); 1656 } 1657 1658 /** 1659 * Store the voicemail number in preferences 1660 */ storeVoiceMailNumber(String number)1661 private void storeVoiceMailNumber(String number) { 1662 // Update the preference value of voicemail number 1663 SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(getContext()); 1664 SharedPreferences.Editor editor = sp.edit(); 1665 editor.putString(VM_NUMBER_CDMA + getPhoneId(), number); 1666 editor.apply(); 1667 } 1668 1669 /** 1670 * Sets PROPERTY_ICC_OPERATOR_ISO_COUNTRY property 1671 * 1672 */ setIsoCountryProperty(String operatorNumeric)1673 protected void setIsoCountryProperty(String operatorNumeric) { 1674 TelephonyManager tm = TelephonyManager.from(mContext); 1675 if (TextUtils.isEmpty(operatorNumeric)) { 1676 log("setIsoCountryProperty: clear 'gsm.sim.operator.iso-country'"); 1677 tm.setSimCountryIsoForPhone(mPhoneId, ""); 1678 } else { 1679 String iso = ""; 1680 try { 1681 iso = MccTable.countryCodeForMcc(Integer.parseInt( 1682 operatorNumeric.substring(0,3))); 1683 } catch (NumberFormatException ex) { 1684 loge("setIsoCountryProperty: countryCodeForMcc error", ex); 1685 } catch (StringIndexOutOfBoundsException ex) { 1686 loge("setIsoCountryProperty: countryCodeForMcc error", ex); 1687 } 1688 1689 log("setIsoCountryProperty: set 'gsm.sim.operator.iso-country' to iso=" + iso); 1690 tm.setSimCountryIsoForPhone(mPhoneId, iso); 1691 } 1692 } 1693 1694 /** 1695 * Sets the "current" field in the telephony provider according to the 1696 * build-time operator numeric property 1697 * 1698 * @return true for success; false otherwise. 1699 */ updateCurrentCarrierInProvider(String operatorNumeric)1700 boolean updateCurrentCarrierInProvider(String operatorNumeric) { 1701 log("CDMAPhone: updateCurrentCarrierInProvider called"); 1702 if (!TextUtils.isEmpty(operatorNumeric)) { 1703 try { 1704 Uri uri = Uri.withAppendedPath(Telephony.Carriers.CONTENT_URI, "current"); 1705 ContentValues map = new ContentValues(); 1706 map.put(Telephony.Carriers.NUMERIC, operatorNumeric); 1707 log("updateCurrentCarrierInProvider from system: numeric=" + operatorNumeric); 1708 getContext().getContentResolver().insert(uri, map); 1709 1710 // Updates MCC MNC device configuration information 1711 log("update mccmnc=" + operatorNumeric); 1712 MccTable.updateMccMncConfiguration(mContext, operatorNumeric, false); 1713 1714 return true; 1715 } catch (SQLException e) { 1716 Rlog.e(LOG_TAG, "Can't store current operator", e); 1717 } 1718 } 1719 return false; 1720 } 1721 1722 /** 1723 * Sets the "current" field in the telephony provider according to the SIM's operator. 1724 * Implemented in {@link CDMALTEPhone} for CDMA/LTE devices. 1725 * 1726 * @return true for success; false otherwise. 1727 */ updateCurrentCarrierInProvider()1728 boolean updateCurrentCarrierInProvider() { 1729 return true; 1730 } 1731 prepareEri()1732 public void prepareEri() { 1733 if (mEriManager == null) { 1734 Rlog.e(LOG_TAG, "PrepareEri: Trying to access stale objects"); 1735 return; 1736 } 1737 mEriManager.loadEriFile(); 1738 if(mEriManager.isEriFileLoaded()) { 1739 // when the ERI file is loaded 1740 log("ERI read, notify registrants"); 1741 mEriFileLoadedRegistrants.notifyRegistrants(); 1742 } 1743 } 1744 isEriFileLoaded()1745 public boolean isEriFileLoaded() { 1746 return mEriManager.isEriFileLoaded(); 1747 } 1748 registerForRuimRecordEvents()1749 protected void registerForRuimRecordEvents() { 1750 IccRecords r = mIccRecords.get(); 1751 if (r == null) { 1752 return; 1753 } 1754 r.registerForRecordsLoaded(this, EVENT_RUIM_RECORDS_LOADED, null); 1755 } 1756 unregisterForRuimRecordEvents()1757 protected void unregisterForRuimRecordEvents() { 1758 IccRecords r = mIccRecords.get(); 1759 if (r == null) { 1760 return; 1761 } 1762 r.unregisterForRecordsLoaded(this); 1763 } 1764 1765 /** 1766 * Sets the SIM voice message count 1767 * @param line Subscriber Profile Number, one-based. Only '1' is supported 1768 * @param countWaiting The number of messages waiting, if known. Use 1769 * -1 to indicate that an unknown number of 1770 * messages are waiting 1771 * This is a wrapper function for setVoiceMessageCount 1772 */ 1773 @Override setVoiceMessageWaiting(int line, int countWaiting)1774 public void setVoiceMessageWaiting(int line, int countWaiting) { 1775 setVoiceMessageCount(countWaiting); 1776 } 1777 log(String s)1778 protected void log(String s) { 1779 if (DBG) 1780 Rlog.d(LOG_TAG, s); 1781 } 1782 loge(String s, Exception e)1783 protected void loge(String s, Exception e) { 1784 if (DBG) 1785 Rlog.e(LOG_TAG, s, e); 1786 } 1787 1788 @Override dump(FileDescriptor fd, PrintWriter pw, String[] args)1789 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1790 pw.println("CDMAPhone extends:"); 1791 super.dump(fd, pw, args); 1792 pw.println(" mVmNumber=" + mVmNumber); 1793 pw.println(" mCT=" + mCT); 1794 pw.println(" mSST=" + mSST); 1795 pw.println(" mCdmaSSM=" + mCdmaSSM); 1796 pw.println(" mPendingMmis=" + mPendingMmis); 1797 pw.println(" mRuimPhoneBookInterfaceManager=" + mRuimPhoneBookInterfaceManager); 1798 pw.println(" mCdmaSubscriptionSource=" + mCdmaSubscriptionSource); 1799 pw.println(" mSubInfo=" + mSubInfo); 1800 pw.println(" mEriManager=" + mEriManager); 1801 pw.println(" mWakeLock=" + mWakeLock); 1802 pw.println(" mIsPhoneInEcmState=" + mIsPhoneInEcmState); 1803 if (VDBG) pw.println(" mImei=" + mImei); 1804 if (VDBG) pw.println(" mImeiSv=" + mImeiSv); 1805 if (VDBG) pw.println(" mEsn=" + mEsn); 1806 if (VDBG) pw.println(" mMeid=" + mMeid); 1807 pw.println(" mCarrierOtaSpNumSchema=" + mCarrierOtaSpNumSchema); 1808 pw.println(" getCdmaEriIconIndex()=" + getCdmaEriIconIndex()); 1809 pw.println(" getCdmaEriIconMode()=" + getCdmaEriIconMode()); 1810 pw.println(" getCdmaEriText()=" + getCdmaEriText()); 1811 pw.println(" isMinInfoReady()=" + isMinInfoReady()); 1812 pw.println(" isCspPlmnEnabled()=" + isCspPlmnEnabled()); 1813 } 1814 1815 @Override setOperatorBrandOverride(String brand)1816 public boolean setOperatorBrandOverride(String brand) { 1817 if (mUiccController == null) { 1818 return false; 1819 } 1820 1821 UiccCard card = mUiccController.getUiccCard(getPhoneId()); 1822 if (card == null) { 1823 return false; 1824 } 1825 1826 boolean status = card.setOperatorBrandOverride(brand); 1827 1828 // Refresh. 1829 if (status) { 1830 IccRecords iccRecords = mIccRecords.get(); 1831 if (iccRecords != null) { 1832 TelephonyManager.from(mContext).setSimOperatorNameForPhone( 1833 mPhoneId, iccRecords.getServiceProviderName()); 1834 } 1835 if (mSST != null) { 1836 mSST.pollState(); 1837 } 1838 } 1839 return status; 1840 } 1841 } 1842