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