1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.internal.telephony; 18 19 import static android.Manifest.permission.READ_PHONE_STATE; 20 import android.app.ActivityManagerNative; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.os.AsyncResult; 24 import android.os.Handler; 25 import android.os.Message; 26 import android.os.Registrant; 27 import android.os.RegistrantList; 28 import android.os.SystemProperties; 29 import android.os.UserHandle; 30 import android.util.Log; 31 import android.telephony.ServiceState; 32 import android.telephony.TelephonyManager; 33 34 import com.android.internal.telephony.IccCardConstants.State; 35 import com.android.internal.telephony.IccCardApplicationStatus.AppState; 36 import com.android.internal.telephony.IccCardApplicationStatus.PersoSubState; 37 import com.android.internal.telephony.IccCardStatus.CardState; 38 import com.android.internal.telephony.IccCardStatus.PinState; 39 import com.android.internal.telephony.cdma.CdmaSubscriptionSourceManager; 40 import com.android.internal.telephony.uicc.UiccController; 41 import com.android.internal.telephony.Phone; 42 43 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_STATE; 44 45 /** 46 * @Deprecated use {@link UiccController}.getUiccCard instead. 47 * 48 * The Phone App assumes that there is only one icc card, and one icc application 49 * available at a time. Moreover, it assumes such object (represented with IccCard) 50 * is available all the time (whether {@link RILConstants.RIL_REQUEST_GET_SIM_STATUS} returned 51 * or not, whether card has desired application or not, whether there really is a card in the 52 * slot or not). 53 * 54 * UiccController, however, can handle multiple instances of icc objects (multiple 55 * {@link UiccCardApplication}, multiple {@link IccFileHandler}, multiple {@link IccRecords}) 56 * created and destroyed dynamically during phone operation. 57 * 58 * This class implements the IccCard interface that is always available (right after default 59 * phone object is constructed) to expose the current (based on voice radio technology) 60 * application on the uicc card, so that external apps won't break. 61 */ 62 63 public class IccCardProxy extends Handler implements IccCard { 64 private static final boolean DBG = true; 65 private static final String LOG_TAG = "RIL_IccCardProxy"; 66 67 private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 1; 68 private static final int EVENT_RADIO_ON = 2; 69 private static final int EVENT_ICC_CHANGED = 3; 70 private static final int EVENT_ICC_ABSENT = 4; 71 private static final int EVENT_ICC_LOCKED = 5; 72 private static final int EVENT_APP_READY = 6; 73 private static final int EVENT_RECORDS_LOADED = 7; 74 private static final int EVENT_IMSI_READY = 8; 75 private static final int EVENT_NETWORK_LOCKED = 9; 76 private static final int EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 11; 77 78 private final Object mLock = new Object(); 79 private Context mContext; 80 private CommandsInterface mCi; 81 82 private RegistrantList mAbsentRegistrants = new RegistrantList(); 83 private RegistrantList mPinLockedRegistrants = new RegistrantList(); 84 private RegistrantList mNetworkLockedRegistrants = new RegistrantList(); 85 86 private int mCurrentAppType = UiccController.APP_FAM_3GPP; //default to 3gpp? 87 private UiccController mUiccController = null; 88 private UiccCard mUiccCard = null; 89 private UiccCardApplication mUiccApplication = null; 90 private IccRecords mIccRecords = null; 91 private CdmaSubscriptionSourceManager mCdmaSSM = null; 92 private boolean mRadioOn = false; 93 private boolean mQuietMode = false; // when set to true IccCardProxy will not broadcast 94 // ACTION_SIM_STATE_CHANGED intents 95 private boolean mInitialized = false; 96 private State mExternalState = State.UNKNOWN; 97 IccCardProxy(Context context, CommandsInterface ci)98 public IccCardProxy(Context context, CommandsInterface ci) { 99 log("Creating"); 100 this.mContext = context; 101 this.mCi = ci; 102 mCdmaSSM = CdmaSubscriptionSourceManager.getInstance(context, 103 ci, this, EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED, null); 104 mUiccController = UiccController.getInstance(); 105 mUiccController.registerForIccChanged(this, EVENT_ICC_CHANGED, null); 106 ci.registerForOn(this,EVENT_RADIO_ON, null); 107 ci.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_UNAVAILABLE, null); 108 setExternalState(State.NOT_READY); 109 } 110 dispose()111 public void dispose() { 112 synchronized (mLock) { 113 log("Disposing"); 114 //Cleanup icc references 115 mUiccController.unregisterForIccChanged(this); 116 mUiccController = null; 117 mCi.unregisterForOn(this); 118 mCi.unregisterForOffOrNotAvailable(this); 119 mCdmaSSM.dispose(this); 120 } 121 } 122 123 /* 124 * The card application that the external world sees will be based on the 125 * voice radio technology only! 126 */ setVoiceRadioTech(int radioTech)127 public void setVoiceRadioTech(int radioTech) { 128 synchronized (mLock) { 129 if (DBG) { 130 log("Setting radio tech " + ServiceState.rilRadioTechnologyToString(radioTech)); 131 } 132 if (ServiceState.isGsm(radioTech)) { 133 mCurrentAppType = UiccController.APP_FAM_3GPP; 134 } else { 135 mCurrentAppType = UiccController.APP_FAM_3GPP2; 136 } 137 updateQuietMode(); 138 } 139 } 140 141 /** 142 * In case of 3gpp2 we need to find out if subscription used is coming from 143 * NV in which case we shouldn't broadcast any sim states changes. 144 */ updateQuietMode()145 private void updateQuietMode() { 146 synchronized (mLock) { 147 boolean oldQuietMode = mQuietMode; 148 boolean newQuietMode; 149 int cdmaSource = Phone.CDMA_SUBSCRIPTION_UNKNOWN; 150 boolean isLteOnCdmaMode = TelephonyManager.getLteOnCdmaModeStatic() 151 == PhoneConstants.LTE_ON_CDMA_TRUE; 152 if (mCurrentAppType == UiccController.APP_FAM_3GPP) { 153 newQuietMode = false; 154 if (DBG) log("updateQuietMode: 3GPP subscription -> newQuietMode=" + newQuietMode); 155 } else { 156 if (isLteOnCdmaMode) { 157 log("updateQuietMode: is cdma/lte device, force IccCardProxy into 3gpp mode"); 158 mCurrentAppType = UiccController.APP_FAM_3GPP; 159 } 160 cdmaSource = mCdmaSSM != null ? 161 mCdmaSSM.getCdmaSubscriptionSource() : Phone.CDMA_SUBSCRIPTION_UNKNOWN; 162 163 newQuietMode = (cdmaSource == Phone.CDMA_SUBSCRIPTION_NV) 164 && (mCurrentAppType == UiccController.APP_FAM_3GPP2) 165 && !isLteOnCdmaMode; 166 } 167 168 if (mQuietMode == false && newQuietMode == true) { 169 // Last thing to do before switching to quiet mode is 170 // broadcast ICC_READY 171 log("Switching to QuietMode."); 172 setExternalState(State.READY); 173 mQuietMode = newQuietMode; 174 } else if (mQuietMode == true && newQuietMode == false) { 175 if (DBG) { 176 log("updateQuietMode: Switching out from QuietMode." 177 + " Force broadcast of current state=" + mExternalState); 178 } 179 mQuietMode = newQuietMode; 180 setExternalState(mExternalState, true); 181 } 182 if (DBG) { 183 log("updateQuietMode: QuietMode is " + mQuietMode + " (app_type=" 184 + mCurrentAppType + " isLteOnCdmaMode=" + isLteOnCdmaMode 185 + " cdmaSource=" + cdmaSource + ")"); 186 } 187 mInitialized = true; 188 sendMessage(obtainMessage(EVENT_ICC_CHANGED)); 189 } 190 } 191 handleMessage(Message msg)192 public void handleMessage(Message msg) { 193 switch (msg.what) { 194 case EVENT_RADIO_OFF_OR_UNAVAILABLE: 195 mRadioOn = false; 196 break; 197 case EVENT_RADIO_ON: 198 mRadioOn = true; 199 if (!mInitialized) { 200 updateQuietMode(); 201 } 202 break; 203 case EVENT_ICC_CHANGED: 204 if (mInitialized) { 205 updateIccAvailability(); 206 } 207 break; 208 case EVENT_ICC_ABSENT: 209 mAbsentRegistrants.notifyRegistrants(); 210 setExternalState(State.ABSENT); 211 break; 212 case EVENT_ICC_LOCKED: 213 processLockedState(); 214 break; 215 case EVENT_APP_READY: 216 setExternalState(State.READY); 217 break; 218 case EVENT_RECORDS_LOADED: 219 broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_LOADED, null); 220 break; 221 case EVENT_IMSI_READY: 222 broadcastIccStateChangedIntent(IccCardConstants.INTENT_VALUE_ICC_IMSI, null); 223 break; 224 case EVENT_NETWORK_LOCKED: 225 mNetworkLockedRegistrants.notifyRegistrants(); 226 setExternalState(State.NETWORK_LOCKED); 227 break; 228 case EVENT_CDMA_SUBSCRIPTION_SOURCE_CHANGED: 229 updateQuietMode(); 230 break; 231 default: 232 loge("Unhandled message with number: " + msg.what); 233 break; 234 } 235 } 236 updateIccAvailability()237 private void updateIccAvailability() { 238 synchronized (mLock) { 239 UiccCard newCard = mUiccController.getUiccCard(); 240 CardState state = CardState.CARDSTATE_ABSENT; 241 UiccCardApplication newApp = null; 242 IccRecords newRecords = null; 243 if (newCard != null) { 244 state = newCard.getCardState(); 245 newApp = newCard.getApplication(mCurrentAppType); 246 if (newApp != null) { 247 newRecords = newApp.getIccRecords(); 248 } 249 } 250 251 if (mIccRecords != newRecords || mUiccApplication != newApp || mUiccCard != newCard) { 252 if (DBG) log("Icc changed. Reregestering."); 253 unregisterUiccCardEvents(); 254 mUiccCard = newCard; 255 mUiccApplication = newApp; 256 mIccRecords = newRecords; 257 registerUiccCardEvents(); 258 } 259 260 updateExternalState(); 261 } 262 } 263 updateExternalState()264 private void updateExternalState() { 265 if (mUiccCard == null || mUiccCard.getCardState() == CardState.CARDSTATE_ABSENT) { 266 if (mRadioOn) { 267 setExternalState(State.ABSENT); 268 } else { 269 setExternalState(State.NOT_READY); 270 } 271 return; 272 } 273 274 if (mUiccCard.getCardState() == CardState.CARDSTATE_ERROR || 275 mUiccApplication == null) { 276 setExternalState(State.UNKNOWN); 277 return; 278 } 279 280 switch (mUiccApplication.getState()) { 281 case APPSTATE_UNKNOWN: 282 case APPSTATE_DETECTED: 283 setExternalState(State.UNKNOWN); 284 break; 285 case APPSTATE_PIN: 286 setExternalState(State.PIN_REQUIRED); 287 break; 288 case APPSTATE_PUK: 289 setExternalState(State.PUK_REQUIRED); 290 break; 291 case APPSTATE_SUBSCRIPTION_PERSO: 292 if (mUiccApplication.getPersoSubState() == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) { 293 setExternalState(State.NETWORK_LOCKED); 294 } else { 295 setExternalState(State.UNKNOWN); 296 } 297 break; 298 case APPSTATE_READY: 299 setExternalState(State.READY); 300 break; 301 } 302 } 303 registerUiccCardEvents()304 private void registerUiccCardEvents() { 305 if (mUiccCard != null) mUiccCard.registerForAbsent(this, EVENT_ICC_ABSENT, null); 306 if (mUiccApplication != null) { 307 mUiccApplication.registerForReady(this, EVENT_APP_READY, null); 308 mUiccApplication.registerForLocked(this, EVENT_ICC_LOCKED, null); 309 mUiccApplication.registerForNetworkLocked(this, EVENT_NETWORK_LOCKED, null); 310 } 311 if (mIccRecords != null) { 312 mIccRecords.registerForImsiReady(this, EVENT_IMSI_READY, null); 313 mIccRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null); 314 } 315 } 316 unregisterUiccCardEvents()317 private void unregisterUiccCardEvents() { 318 if (mUiccCard != null) mUiccCard.unregisterForAbsent(this); 319 if (mUiccApplication != null) mUiccApplication.unregisterForReady(this); 320 if (mUiccApplication != null) mUiccApplication.unregisterForLocked(this); 321 if (mUiccApplication != null) mUiccApplication.unregisterForNetworkLocked(this); 322 if (mIccRecords != null) mIccRecords.unregisterForImsiReady(this); 323 if (mIccRecords != null) mIccRecords.unregisterForRecordsLoaded(this); 324 } 325 broadcastIccStateChangedIntent(String value, String reason)326 private void broadcastIccStateChangedIntent(String value, String reason) { 327 synchronized (mLock) { 328 if (mQuietMode) { 329 log("QuietMode: NOT Broadcasting intent ACTION_SIM_STATE_CHANGED " + value 330 + " reason " + reason); 331 return; 332 } 333 334 Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 335 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 336 intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone"); 337 intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, value); 338 intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason); 339 340 if (DBG) log("Broadcasting intent ACTION_SIM_STATE_CHANGED " + value 341 + " reason " + reason); 342 ActivityManagerNative.broadcastStickyIntent(intent, READ_PHONE_STATE, 343 UserHandle.USER_ALL); 344 } 345 } 346 processLockedState()347 private void processLockedState() { 348 synchronized (mLock) { 349 if (mUiccApplication == null) { 350 //Don't need to do anything if non-existent application is locked 351 return; 352 } 353 PinState pin1State = mUiccApplication.getPin1State(); 354 if (pin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) { 355 setExternalState(State.PERM_DISABLED); 356 return; 357 } 358 359 AppState appState = mUiccApplication.getState(); 360 switch (appState) { 361 case APPSTATE_PIN: 362 mPinLockedRegistrants.notifyRegistrants(); 363 setExternalState(State.PIN_REQUIRED); 364 break; 365 case APPSTATE_PUK: 366 setExternalState(State.PUK_REQUIRED); 367 break; 368 } 369 } 370 } 371 setExternalState(State newState, boolean override)372 private void setExternalState(State newState, boolean override) { 373 synchronized (mLock) { 374 if (!override && newState == mExternalState) { 375 return; 376 } 377 mExternalState = newState; 378 SystemProperties.set(PROPERTY_SIM_STATE, mExternalState.toString()); 379 broadcastIccStateChangedIntent(getIccStateIntentString(mExternalState), 380 getIccStateReason(mExternalState)); 381 } 382 } 383 setExternalState(State newState)384 private void setExternalState(State newState) { 385 setExternalState(newState, false); 386 } 387 getIccRecordsLoaded()388 public boolean getIccRecordsLoaded() { 389 synchronized (mLock) { 390 if (mIccRecords != null) { 391 return mIccRecords.getRecordsLoaded(); 392 } 393 return false; 394 } 395 } 396 getIccStateIntentString(State state)397 private String getIccStateIntentString(State state) { 398 switch (state) { 399 case ABSENT: return IccCardConstants.INTENT_VALUE_ICC_ABSENT; 400 case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 401 case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 402 case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 403 case READY: return IccCardConstants.INTENT_VALUE_ICC_READY; 404 case NOT_READY: return IccCardConstants.INTENT_VALUE_ICC_NOT_READY; 405 case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 406 default: return IccCardConstants.INTENT_VALUE_ICC_UNKNOWN; 407 } 408 } 409 410 /** 411 * Locked state have a reason (PIN, PUK, NETWORK, PERM_DISABLED) 412 * @return reason 413 */ getIccStateReason(State state)414 private String getIccStateReason(State state) { 415 switch (state) { 416 case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN; 417 case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK; 418 case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_LOCKED_NETWORK; 419 case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED; 420 default: return null; 421 } 422 } 423 424 /* IccCard interface implementation */ 425 @Override getState()426 public State getState() { 427 synchronized (mLock) { 428 return mExternalState; 429 } 430 } 431 432 @Override getIccRecords()433 public IccRecords getIccRecords() { 434 synchronized (mLock) { 435 return mIccRecords; 436 } 437 } 438 439 @Override getIccFileHandler()440 public IccFileHandler getIccFileHandler() { 441 synchronized (mLock) { 442 if (mUiccApplication != null) { 443 return mUiccApplication.getIccFileHandler(); 444 } 445 return null; 446 } 447 } 448 449 /** 450 * Notifies handler of any transition into State.ABSENT 451 */ 452 @Override registerForAbsent(Handler h, int what, Object obj)453 public void registerForAbsent(Handler h, int what, Object obj) { 454 synchronized (mLock) { 455 Registrant r = new Registrant (h, what, obj); 456 457 mAbsentRegistrants.add(r); 458 459 if (getState() == State.ABSENT) { 460 r.notifyRegistrant(); 461 } 462 } 463 } 464 465 @Override unregisterForAbsent(Handler h)466 public void unregisterForAbsent(Handler h) { 467 synchronized (mLock) { 468 mAbsentRegistrants.remove(h); 469 } 470 } 471 472 /** 473 * Notifies handler of any transition into State.NETWORK_LOCKED 474 */ 475 @Override registerForNetworkLocked(Handler h, int what, Object obj)476 public void registerForNetworkLocked(Handler h, int what, Object obj) { 477 synchronized (mLock) { 478 Registrant r = new Registrant (h, what, obj); 479 480 mNetworkLockedRegistrants.add(r); 481 482 if (getState() == State.NETWORK_LOCKED) { 483 r.notifyRegistrant(); 484 } 485 } 486 } 487 488 @Override unregisterForNetworkLocked(Handler h)489 public void unregisterForNetworkLocked(Handler h) { 490 synchronized (mLock) { 491 mNetworkLockedRegistrants.remove(h); 492 } 493 } 494 495 /** 496 * Notifies handler of any transition into State.isPinLocked() 497 */ 498 @Override registerForLocked(Handler h, int what, Object obj)499 public void registerForLocked(Handler h, int what, Object obj) { 500 synchronized (mLock) { 501 Registrant r = new Registrant (h, what, obj); 502 503 mPinLockedRegistrants.add(r); 504 505 if (getState().isPinLocked()) { 506 r.notifyRegistrant(); 507 } 508 } 509 } 510 511 @Override unregisterForLocked(Handler h)512 public void unregisterForLocked(Handler h) { 513 synchronized (mLock) { 514 mPinLockedRegistrants.remove(h); 515 } 516 } 517 518 @Override supplyPin(String pin, Message onComplete)519 public void supplyPin(String pin, Message onComplete) { 520 synchronized (mLock) { 521 if (mUiccApplication != null) { 522 mUiccApplication.supplyPin(pin, onComplete); 523 } else if (onComplete != null) { 524 Exception e = new RuntimeException("ICC card is absent."); 525 AsyncResult.forMessage(onComplete).exception = e; 526 onComplete.sendToTarget(); 527 return; 528 } 529 } 530 } 531 532 @Override supplyPuk(String puk, String newPin, Message onComplete)533 public void supplyPuk(String puk, String newPin, Message onComplete) { 534 synchronized (mLock) { 535 if (mUiccApplication != null) { 536 mUiccApplication.supplyPuk(puk, newPin, onComplete); 537 } else if (onComplete != null) { 538 Exception e = new RuntimeException("ICC card is absent."); 539 AsyncResult.forMessage(onComplete).exception = e; 540 onComplete.sendToTarget(); 541 return; 542 } 543 } 544 } 545 546 @Override supplyPin2(String pin2, Message onComplete)547 public void supplyPin2(String pin2, Message onComplete) { 548 synchronized (mLock) { 549 if (mUiccApplication != null) { 550 mUiccApplication.supplyPin2(pin2, onComplete); 551 } else if (onComplete != null) { 552 Exception e = new RuntimeException("ICC card is absent."); 553 AsyncResult.forMessage(onComplete).exception = e; 554 onComplete.sendToTarget(); 555 return; 556 } 557 } 558 } 559 560 @Override supplyPuk2(String puk2, String newPin2, Message onComplete)561 public void supplyPuk2(String puk2, String newPin2, Message onComplete) { 562 synchronized (mLock) { 563 if (mUiccApplication != null) { 564 mUiccApplication.supplyPuk2(puk2, newPin2, onComplete); 565 } else if (onComplete != null) { 566 Exception e = new RuntimeException("ICC card is absent."); 567 AsyncResult.forMessage(onComplete).exception = e; 568 onComplete.sendToTarget(); 569 return; 570 } 571 } 572 } 573 574 @Override supplyNetworkDepersonalization(String pin, Message onComplete)575 public void supplyNetworkDepersonalization(String pin, Message onComplete) { 576 synchronized (mLock) { 577 if (mUiccApplication != null) { 578 mUiccApplication.supplyNetworkDepersonalization(pin, onComplete); 579 } else if (onComplete != null) { 580 Exception e = new RuntimeException("CommandsInterface is not set."); 581 AsyncResult.forMessage(onComplete).exception = e; 582 onComplete.sendToTarget(); 583 return; 584 } 585 } 586 } 587 588 @Override getIccLockEnabled()589 public boolean getIccLockEnabled() { 590 synchronized (mLock) { 591 /* defaults to true, if ICC is absent */ 592 Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccLockEnabled() : true; 593 return retValue; 594 } 595 } 596 597 @Override getIccFdnEnabled()598 public boolean getIccFdnEnabled() { 599 synchronized (mLock) { 600 Boolean retValue = mUiccApplication != null ? mUiccApplication.getIccFdnEnabled() : false; 601 return retValue; 602 } 603 } 604 605 @Override setIccLockEnabled(boolean enabled, String password, Message onComplete)606 public void setIccLockEnabled(boolean enabled, String password, Message onComplete) { 607 synchronized (mLock) { 608 if (mUiccApplication != null) { 609 mUiccApplication.setIccLockEnabled(enabled, password, onComplete); 610 } else if (onComplete != null) { 611 Exception e = new RuntimeException("ICC card is absent."); 612 AsyncResult.forMessage(onComplete).exception = e; 613 onComplete.sendToTarget(); 614 return; 615 } 616 } 617 } 618 619 @Override setIccFdnEnabled(boolean enabled, String password, Message onComplete)620 public void setIccFdnEnabled(boolean enabled, String password, Message onComplete) { 621 synchronized (mLock) { 622 if (mUiccApplication != null) { 623 mUiccApplication.setIccFdnEnabled(enabled, password, onComplete); 624 } else if (onComplete != null) { 625 Exception e = new RuntimeException("ICC card is absent."); 626 AsyncResult.forMessage(onComplete).exception = e; 627 onComplete.sendToTarget(); 628 return; 629 } 630 } 631 } 632 633 @Override changeIccLockPassword(String oldPassword, String newPassword, Message onComplete)634 public void changeIccLockPassword(String oldPassword, String newPassword, Message onComplete) { 635 synchronized (mLock) { 636 if (mUiccApplication != null) { 637 mUiccApplication.changeIccLockPassword(oldPassword, newPassword, onComplete); 638 } else if (onComplete != null) { 639 Exception e = new RuntimeException("ICC card is absent."); 640 AsyncResult.forMessage(onComplete).exception = e; 641 onComplete.sendToTarget(); 642 return; 643 } 644 } 645 } 646 647 @Override changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete)648 public void changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete) { 649 synchronized (mLock) { 650 if (mUiccApplication != null) { 651 mUiccApplication.changeIccFdnPassword(oldPassword, newPassword, onComplete); 652 } else if (onComplete != null) { 653 Exception e = new RuntimeException("ICC card is absent."); 654 AsyncResult.forMessage(onComplete).exception = e; 655 onComplete.sendToTarget(); 656 return; 657 } 658 } 659 } 660 661 @Override getServiceProviderName()662 public String getServiceProviderName() { 663 synchronized (mLock) { 664 if (mIccRecords != null) { 665 return mIccRecords.getServiceProviderName(); 666 } 667 return null; 668 } 669 } 670 671 @Override isApplicationOnIcc(IccCardApplicationStatus.AppType type)672 public boolean isApplicationOnIcc(IccCardApplicationStatus.AppType type) { 673 synchronized (mLock) { 674 Boolean retValue = mUiccCard != null ? mUiccCard.isApplicationOnIcc(type) : false; 675 return retValue; 676 } 677 } 678 679 @Override hasIccCard()680 public boolean hasIccCard() { 681 synchronized (mLock) { 682 if (mUiccCard != null && mUiccCard.getCardState() != CardState.CARDSTATE_ABSENT) { 683 return true; 684 } 685 return false; 686 } 687 } 688 log(String s)689 private void log(String s) { 690 Log.d(LOG_TAG, s); 691 } 692 loge(String msg)693 private void loge(String msg) { 694 Log.e(LOG_TAG, msg); 695 } 696 } 697