1 /* 2 * Copyright (C) 2006, 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 android.content.Context; 20 import android.os.AsyncResult; 21 import android.os.Handler; 22 import android.os.Message; 23 import android.os.Registrant; 24 import android.os.RegistrantList; 25 import android.util.Log; 26 27 import com.android.internal.telephony.IccCardApplicationStatus.AppState; 28 import com.android.internal.telephony.IccCardApplicationStatus.AppType; 29 import com.android.internal.telephony.IccCardApplicationStatus.PersoSubState; 30 import com.android.internal.telephony.IccCardStatus.PinState; 31 import com.android.internal.telephony.cdma.RuimFileHandler; 32 import com.android.internal.telephony.cdma.RuimRecords; 33 import com.android.internal.telephony.gsm.SIMFileHandler; 34 import com.android.internal.telephony.gsm.SIMRecords; 35 import com.android.internal.telephony.ims.IsimFileHandler; 36 import com.android.internal.telephony.ims.IsimUiccRecords; 37 38 /** 39 * {@hide} 40 */ 41 public class UiccCardApplication { 42 private static final String LOG_TAG = "RIL_UiccCardApplication"; 43 private static final boolean DBG = true; 44 45 private static final int EVENT_QUERY_FACILITY_FDN_DONE = 1; 46 private static final int EVENT_CHANGE_FACILITY_FDN_DONE = 2; 47 private static final int EVENT_QUERY_FACILITY_LOCK_DONE = 3; 48 private static final int EVENT_CHANGE_FACILITY_LOCK_DONE = 4; 49 50 private final Object mLock = new Object(); 51 private UiccCard mUiccCard; //parent 52 private AppState mAppState; 53 private AppType mAppType; 54 private PersoSubState mPersoSubState; 55 private String mAid; 56 private String mAppLabel; 57 private boolean mPin1Replaced; 58 private PinState mPin1State; 59 private PinState mPin2State; 60 private boolean mIccFdnEnabled; 61 private boolean mDesiredFdnEnabled; 62 private boolean mIccLockEnabled; 63 private boolean mDesiredPinLocked; 64 65 private CommandsInterface mCi; 66 private Context mContext; 67 private IccRecords mIccRecords; 68 private IccFileHandler mIccFh; 69 70 private boolean mDestroyed;//set to true once this App is commanded to be disposed of. 71 72 private RegistrantList mReadyRegistrants = new RegistrantList(); 73 private RegistrantList mPinLockedRegistrants = new RegistrantList(); 74 private RegistrantList mNetworkLockedRegistrants = new RegistrantList(); 75 76 UiccCardApplication(UiccCard uiccCard, 77 IccCardApplicationStatus as, 78 Context c, 79 CommandsInterface ci) { 80 if (DBG) log("Creating UiccApp: " + as); 81 mUiccCard = uiccCard; 82 mAppState = as.app_state; 83 mAppType = as.app_type; 84 mPersoSubState = as.perso_substate; 85 mAid = as.aid; 86 mAppLabel = as.app_label; 87 mPin1Replaced = (as.pin1_replaced != 0); 88 mPin1State = as.pin1; 89 mPin2State = as.pin2; 90 91 mContext = c; 92 mCi = ci; 93 94 mIccFh = createIccFileHandler(as.app_type); 95 mIccRecords = createIccRecords(as.app_type, mContext, mCi); 96 if (mAppState == AppState.APPSTATE_READY) { 97 queryFdn(); 98 queryPin1State(); 99 } 100 } 101 102 void update (IccCardApplicationStatus as, Context c, CommandsInterface ci) { 103 synchronized (mLock) { 104 if (mDestroyed) { 105 loge("Application updated after destroyed! Fix me!"); 106 return; 107 } 108 109 if (DBG) log(mAppType + " update. New " + as); 110 mContext = c; 111 mCi = ci; 112 AppType oldAppType = mAppType; 113 AppState oldAppState = mAppState; 114 PersoSubState oldPersoSubState = mPersoSubState; 115 mAppType = as.app_type; 116 mAppState = as.app_state; 117 mPersoSubState = as.perso_substate; 118 mAid = as.aid; 119 mAppLabel = as.app_label; 120 mPin1Replaced = (as.pin1_replaced != 0); 121 mPin1State = as.pin1; 122 mPin2State = as.pin2; 123 124 if (mAppType != oldAppType) { 125 if (mIccFh != null) { mIccFh.dispose();} 126 if (mIccRecords != null) { mIccRecords.dispose();} 127 mIccFh = createIccFileHandler(as.app_type); 128 mIccRecords = createIccRecords(as.app_type, c, ci); 129 } 130 131 if (mPersoSubState != oldPersoSubState && 132 mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) { 133 notifyNetworkLockedRegistrantsIfNeeded(null); 134 } 135 136 if (mAppState != oldAppState) { 137 if (DBG) log(oldAppType + " changed state: " + oldAppState + " -> " + mAppState); 138 // If the app state turns to APPSTATE_READY, then query FDN status, 139 //as it might have failed in earlier attempt. 140 if (mAppState == AppState.APPSTATE_READY) { 141 queryFdn(); 142 queryPin1State(); 143 } 144 notifyPinLockedRegistrantsIfNeeded(null); 145 notifyReadyRegistrantsIfNeeded(null); 146 } 147 } 148 } 149 150 void dispose() { 151 synchronized (mLock) { 152 if (DBG) log(mAppType + " being Disposed"); 153 mDestroyed = true; 154 if (mIccRecords != null) { mIccRecords.dispose();} 155 if (mIccFh != null) { mIccFh.dispose();} 156 mIccRecords = null; 157 mIccFh = null; 158 } 159 } 160 161 private IccRecords createIccRecords(AppType type, Context c, CommandsInterface ci) { 162 if (type == AppType.APPTYPE_USIM || type == AppType.APPTYPE_SIM) { 163 return new SIMRecords(this, c, ci); 164 } else if (type == AppType.APPTYPE_RUIM || type == AppType.APPTYPE_CSIM){ 165 return new RuimRecords(this, c, ci); 166 } else if (type == AppType.APPTYPE_ISIM) { 167 return new IsimUiccRecords(this, c, ci); 168 } else { 169 // Unknown app type (maybe detection is still in progress) 170 return null; 171 } 172 } 173 174 private IccFileHandler createIccFileHandler(AppType type) { 175 switch (type) { 176 case APPTYPE_SIM: 177 return new SIMFileHandler(this, mAid, mCi); 178 case APPTYPE_RUIM: 179 return new RuimFileHandler(this, mAid, mCi); 180 case APPTYPE_USIM: 181 return new UsimFileHandler(this, mAid, mCi); 182 case APPTYPE_CSIM: 183 return new CsimFileHandler(this, mAid, mCi); 184 case APPTYPE_ISIM: 185 return new IsimFileHandler(this, mAid, mCi); 186 default: 187 return null; 188 } 189 } 190 191 /** Assumes mLock is held. */ 192 private void queryFdn() { 193 //This shouldn't change run-time. So needs to be called only once. 194 int serviceClassX; 195 196 serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE + 197 CommandsInterface.SERVICE_CLASS_DATA + 198 CommandsInterface.SERVICE_CLASS_FAX; 199 mCi.queryFacilityLockForApp ( 200 CommandsInterface.CB_FACILITY_BA_FD, "", serviceClassX, 201 mAid, mHandler.obtainMessage(EVENT_QUERY_FACILITY_FDN_DONE)); 202 } 203 /** 204 * Interpret EVENT_QUERY_FACILITY_LOCK_DONE 205 * @param ar is asyncResult of Query_Facility_Locked 206 */ 207 private void onQueryFdnEnabled(AsyncResult ar) { 208 synchronized (mLock) { 209 if (ar.exception != null) { 210 if (DBG) log("Error in querying facility lock:" + ar.exception); 211 return; 212 } 213 214 int[] ints = (int[])ar.result; 215 if(ints.length != 0) { 216 mIccFdnEnabled = (0!=ints[0]); 217 if (DBG) log("Query facility lock : " + mIccFdnEnabled); 218 } else { 219 loge("Bogus facility lock response"); 220 } 221 } 222 } 223 224 private void onChangeFdnDone(AsyncResult ar) { 225 synchronized (mLock) { 226 if (ar.exception == null) { 227 mIccFdnEnabled = mDesiredFdnEnabled; 228 if (DBG) log("EVENT_CHANGE_FACILITY_FDN_DONE: " + 229 "mIccFdnEnabled=" + mIccFdnEnabled); 230 } else { 231 loge("Error change facility fdn with exception " + ar.exception); 232 } 233 Message response = (Message)ar.userObj; 234 AsyncResult.forMessage(response).exception = ar.exception; 235 response.sendToTarget(); 236 } 237 } 238 239 /** REMOVE when mIccLockEnabled is not needed, assumes mLock is held */ 240 private void queryPin1State() { 241 int serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE + 242 CommandsInterface.SERVICE_CLASS_DATA + 243 CommandsInterface.SERVICE_CLASS_FAX; 244 mCi.queryFacilityLockForApp ( 245 CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX, 246 mAid, mHandler.obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE)); 247 } 248 249 /** REMOVE when mIccLockEnabled is not needed*/ 250 private void onQueryFacilityLock(AsyncResult ar) { 251 synchronized (mLock) { 252 if(ar.exception != null) { 253 if (DBG) log("Error in querying facility lock:" + ar.exception); 254 return; 255 } 256 257 int[] ints = (int[])ar.result; 258 if(ints.length != 0) { 259 if (DBG) log("Query facility lock : " + ints[0]); 260 261 mIccLockEnabled = (ints[0] != 0); 262 263 if (mIccLockEnabled) { 264 mPinLockedRegistrants.notifyRegistrants(); 265 } 266 267 // Sanity check: we expect mPin1State to match mIccLockEnabled. 268 // When mPin1State is DISABLED mIccLockEanbled should be false. 269 // When mPin1State is ENABLED mIccLockEnabled should be true. 270 // 271 // Here we validate these assumptions to assist in identifying which ril/radio's 272 // have not correctly implemented GET_SIM_STATUS 273 switch (mPin1State) { 274 case PINSTATE_DISABLED: 275 if (mIccLockEnabled) { 276 loge("QUERY_FACILITY_LOCK:enabled GET_SIM_STATUS.Pin1:disabled." 277 + " Fixme"); 278 } 279 break; 280 case PINSTATE_ENABLED_NOT_VERIFIED: 281 case PINSTATE_ENABLED_VERIFIED: 282 case PINSTATE_ENABLED_BLOCKED: 283 case PINSTATE_ENABLED_PERM_BLOCKED: 284 if (!mIccLockEnabled) { 285 loge("QUERY_FACILITY_LOCK:disabled GET_SIM_STATUS.Pin1:enabled." 286 + " Fixme"); 287 } 288 } 289 } else { 290 loge("Bogus facility lock response"); 291 } 292 } 293 } 294 295 /** REMOVE when mIccLockEnabled is not needed */ 296 private void onChangeFacilityLock(AsyncResult ar) { 297 synchronized (mLock) { 298 if (ar.exception == null) { 299 mIccLockEnabled = mDesiredPinLocked; 300 if (DBG) log( "EVENT_CHANGE_FACILITY_LOCK_DONE: mIccLockEnabled= " 301 + mIccLockEnabled); 302 } else { 303 loge("Error change facility lock with exception " + ar.exception); 304 } 305 AsyncResult.forMessage(((Message)ar.userObj)).exception = ar.exception; 306 ((Message)ar.userObj).sendToTarget(); 307 } 308 } 309 310 private Handler mHandler = new Handler() { 311 @Override 312 public void handleMessage(Message msg){ 313 AsyncResult ar; 314 315 if (mDestroyed) { 316 loge("Received message " + msg + "[" + msg.what 317 + "] while being destroyed. Ignoring."); 318 return; 319 } 320 321 switch (msg.what) { 322 case EVENT_QUERY_FACILITY_FDN_DONE: 323 ar = (AsyncResult)msg.obj; 324 onQueryFdnEnabled(ar); 325 break; 326 case EVENT_CHANGE_FACILITY_FDN_DONE: 327 ar = (AsyncResult)msg.obj; 328 onChangeFdnDone(ar); 329 break; 330 case EVENT_QUERY_FACILITY_LOCK_DONE: 331 ar = (AsyncResult)msg.obj; 332 onQueryFacilityLock(ar); 333 break; 334 case EVENT_CHANGE_FACILITY_LOCK_DONE: 335 ar = (AsyncResult)msg.obj; 336 onChangeFacilityLock(ar); 337 break; 338 default: 339 loge("Unknown Event " + msg.what); 340 } 341 } 342 }; 343 344 public void registerForReady(Handler h, int what, Object obj) { 345 synchronized (mLock) { 346 Registrant r = new Registrant (h, what, obj); 347 mReadyRegistrants.add(r); 348 notifyReadyRegistrantsIfNeeded(r); 349 } 350 } 351 352 public void unregisterForReady(Handler h) { 353 synchronized (mLock) { 354 mReadyRegistrants.remove(h); 355 } 356 } 357 358 /** 359 * Notifies handler of any transition into State.isPinLocked() 360 */ 361 public void registerForLocked(Handler h, int what, Object obj) { 362 synchronized (mLock) { 363 Registrant r = new Registrant (h, what, obj); 364 mPinLockedRegistrants.add(r); 365 notifyPinLockedRegistrantsIfNeeded(r); 366 } 367 } 368 369 public void unregisterForLocked(Handler h) { 370 synchronized (mLock) { 371 mPinLockedRegistrants.remove(h); 372 } 373 } 374 375 /** 376 * Notifies handler of any transition into State.NETWORK_LOCKED 377 */ 378 public void registerForNetworkLocked(Handler h, int what, Object obj) { 379 synchronized (mLock) { 380 Registrant r = new Registrant (h, what, obj); 381 mNetworkLockedRegistrants.add(r); 382 notifyNetworkLockedRegistrantsIfNeeded(r); 383 } 384 } 385 386 public void unregisterForNetworkLocked(Handler h) { 387 synchronized (mLock) { 388 mNetworkLockedRegistrants.remove(h); 389 } 390 } 391 392 /** 393 * Notifies specified registrant, assume mLock is held. 394 * 395 * @param r Registrant to be notified. If null - all registrants will be notified 396 */ 397 private void notifyReadyRegistrantsIfNeeded(Registrant r) { 398 if (mDestroyed) { 399 return; 400 } 401 if (mAppState == AppState.APPSTATE_READY) { 402 if (mPin1State == PinState.PINSTATE_ENABLED_NOT_VERIFIED || 403 mPin1State == PinState.PINSTATE_ENABLED_BLOCKED || 404 mPin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) { 405 loge("Sanity check failed! APPSTATE is ready while PIN1 is not verified!!!"); 406 // Don't notify if application is in insane state 407 return; 408 } 409 if (r == null) { 410 if (DBG) log("Notifying registrants: READY"); 411 mReadyRegistrants.notifyRegistrants(); 412 } else { 413 if (DBG) log("Notifying 1 registrant: READY"); 414 r.notifyRegistrant(new AsyncResult(null, null, null)); 415 } 416 } 417 } 418 419 /** 420 * Notifies specified registrant, assume mLock is held. 421 * 422 * @param r Registrant to be notified. If null - all registrants will be notified 423 */ 424 private void notifyPinLockedRegistrantsIfNeeded(Registrant r) { 425 if (mDestroyed) { 426 return; 427 } 428 429 if (mAppState == AppState.APPSTATE_PIN || 430 mAppState == AppState.APPSTATE_PUK) { 431 if (mPin1State == PinState.PINSTATE_ENABLED_VERIFIED || 432 mPin1State == PinState.PINSTATE_DISABLED) { 433 loge("Sanity check failed! APPSTATE is locked while PIN1 is not!!!"); 434 //Don't notify if application is in insane state 435 return; 436 } 437 if (r == null) { 438 if (DBG) log("Notifying registrants: LOCKED"); 439 mPinLockedRegistrants.notifyRegistrants(); 440 } else { 441 if (DBG) log("Notifying 1 registrant: LOCKED"); 442 r.notifyRegistrant(new AsyncResult(null, null, null)); 443 } 444 } 445 } 446 447 /** 448 * Notifies specified registrant, assume mLock is held. 449 * 450 * @param r Registrant to be notified. If null - all registrants will be notified 451 */ 452 private void notifyNetworkLockedRegistrantsIfNeeded(Registrant r) { 453 if (mDestroyed) { 454 return; 455 } 456 457 if (mAppState == AppState.APPSTATE_SUBSCRIPTION_PERSO && 458 mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) { 459 if (r == null) { 460 if (DBG) log("Notifying registrants: NETWORK_LOCKED"); 461 mNetworkLockedRegistrants.notifyRegistrants(); 462 } else { 463 if (DBG) log("Notifying 1 registrant: NETWORK_LOCED"); 464 r.notifyRegistrant(new AsyncResult(null, null, null)); 465 } 466 } 467 } 468 469 public AppState getState() { 470 synchronized (mLock) { 471 return mAppState; 472 } 473 } 474 475 public AppType getType() { 476 synchronized (mLock) { 477 return mAppType; 478 } 479 } 480 481 public PersoSubState getPersoSubState() { 482 synchronized (mLock) { 483 return mPersoSubState; 484 } 485 } 486 487 public String getAid() { 488 synchronized (mLock) { 489 return mAid; 490 } 491 } 492 493 public PinState getPin1State() { 494 synchronized (mLock) { 495 if (mPin1Replaced) { 496 return mUiccCard.getUniversalPinState(); 497 } 498 return mPin1State; 499 } 500 } 501 502 public IccFileHandler getIccFileHandler() { 503 synchronized (mLock) { 504 return mIccFh; 505 } 506 } 507 508 public IccRecords getIccRecords() { 509 synchronized (mLock) { 510 return mIccRecords; 511 } 512 } 513 514 /** 515 * Supply the ICC PIN to the ICC 516 * 517 * When the operation is complete, onComplete will be sent to its 518 * Handler. 519 * 520 * onComplete.obj will be an AsyncResult 521 * 522 * ((AsyncResult)onComplete.obj).exception == null on success 523 * ((AsyncResult)onComplete.obj).exception != null on fail 524 * 525 * If the supplied PIN is incorrect: 526 * ((AsyncResult)onComplete.obj).exception != null 527 * && ((AsyncResult)onComplete.obj).exception 528 * instanceof com.android.internal.telephony.gsm.CommandException) 529 * && ((CommandException)(((AsyncResult)onComplete.obj).exception)) 530 * .getCommandError() == CommandException.Error.PASSWORD_INCORRECT 531 * 532 * 533 */ 534 public void supplyPin (String pin, Message onComplete) { 535 synchronized (mLock) { 536 mCi.supplyIccPin(pin, onComplete); 537 } 538 } 539 540 public void supplyPuk (String puk, String newPin, Message onComplete) { 541 synchronized (mLock) { 542 mCi.supplyIccPuk(puk, newPin, onComplete); 543 } 544 } 545 546 public void supplyPin2 (String pin2, Message onComplete) { 547 synchronized (mLock) { 548 mCi.supplyIccPin2(pin2, onComplete); 549 } 550 } 551 552 public void supplyPuk2 (String puk2, String newPin2, Message onComplete) { 553 synchronized (mLock) { 554 mCi.supplyIccPuk2(puk2, newPin2, onComplete); 555 } 556 } 557 558 public void supplyNetworkDepersonalization (String pin, Message onComplete) { 559 synchronized (mLock) { 560 if (DBG) log("supplyNetworkDepersonalization"); 561 mCi.supplyNetworkDepersonalization(pin, onComplete); 562 } 563 } 564 565 /** 566 * Check whether ICC pin lock is enabled 567 * This is a sync call which returns the cached pin enabled state 568 * 569 * @return true for ICC locked enabled 570 * false for ICC locked disabled 571 */ 572 public boolean getIccLockEnabled() { 573 return mIccLockEnabled; 574 /* STOPSHIP: Remove line above and all code associated with setting 575 mIccLockEanbled once all RIL correctly sends the pin1 state. 576 // Use getPin1State to take into account pin1Replaced flag 577 PinState pinState = getPin1State(); 578 return pinState == PinState.PINSTATE_ENABLED_NOT_VERIFIED || 579 pinState == PinState.PINSTATE_ENABLED_VERIFIED || 580 pinState == PinState.PINSTATE_ENABLED_BLOCKED || 581 pinState == PinState.PINSTATE_ENABLED_PERM_BLOCKED;*/ 582 } 583 584 /** 585 * Check whether ICC fdn (fixed dialing number) is enabled 586 * This is a sync call which returns the cached pin enabled state 587 * 588 * @return true for ICC fdn enabled 589 * false for ICC fdn disabled 590 */ 591 public boolean getIccFdnEnabled() { 592 synchronized (mLock) { 593 return mIccFdnEnabled; 594 } 595 } 596 597 /** 598 * Set the ICC pin lock enabled or disabled 599 * When the operation is complete, onComplete will be sent to its handler 600 * 601 * @param enabled "true" for locked "false" for unlocked. 602 * @param password needed to change the ICC pin state, aka. Pin1 603 * @param onComplete 604 * onComplete.obj will be an AsyncResult 605 * ((AsyncResult)onComplete.obj).exception == null on success 606 * ((AsyncResult)onComplete.obj).exception != null on fail 607 */ 608 public void setIccLockEnabled (boolean enabled, 609 String password, Message onComplete) { 610 synchronized (mLock) { 611 int serviceClassX; 612 serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE + 613 CommandsInterface.SERVICE_CLASS_DATA + 614 CommandsInterface.SERVICE_CLASS_FAX; 615 616 mDesiredPinLocked = enabled; 617 618 mCi.setFacilityLockForApp(CommandsInterface.CB_FACILITY_BA_SIM, 619 enabled, password, serviceClassX, mAid, 620 mHandler.obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete)); 621 } 622 } 623 624 /** 625 * Set the ICC fdn enabled or disabled 626 * When the operation is complete, onComplete will be sent to its handler 627 * 628 * @param enabled "true" for locked "false" for unlocked. 629 * @param password needed to change the ICC fdn enable, aka Pin2 630 * @param onComplete 631 * onComplete.obj will be an AsyncResult 632 * ((AsyncResult)onComplete.obj).exception == null on success 633 * ((AsyncResult)onComplete.obj).exception != null on fail 634 */ 635 public void setIccFdnEnabled (boolean enabled, 636 String password, Message onComplete) { 637 synchronized (mLock) { 638 int serviceClassX; 639 serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE + 640 CommandsInterface.SERVICE_CLASS_DATA + 641 CommandsInterface.SERVICE_CLASS_FAX + 642 CommandsInterface.SERVICE_CLASS_SMS; 643 644 mDesiredFdnEnabled = enabled; 645 646 mCi.setFacilityLockForApp(CommandsInterface.CB_FACILITY_BA_FD, 647 enabled, password, serviceClassX, mAid, 648 mHandler.obtainMessage(EVENT_CHANGE_FACILITY_FDN_DONE, onComplete)); 649 } 650 } 651 652 /** 653 * Change the ICC password used in ICC pin lock 654 * When the operation is complete, onComplete will be sent to its handler 655 * 656 * @param oldPassword is the old password 657 * @param newPassword is the new password 658 * @param onComplete 659 * onComplete.obj will be an AsyncResult 660 * ((AsyncResult)onComplete.obj).exception == null on success 661 * ((AsyncResult)onComplete.obj).exception != null on fail 662 */ 663 public void changeIccLockPassword(String oldPassword, String newPassword, 664 Message onComplete) { 665 synchronized (mLock) { 666 if (DBG) log("changeIccLockPassword"); 667 mCi.changeIccPinForApp(oldPassword, newPassword, mAid, 668 onComplete); 669 } 670 } 671 672 /** 673 * Change the ICC password used in ICC fdn enable 674 * When the operation is complete, onComplete will be sent to its handler 675 * 676 * @param oldPassword is the old password 677 * @param newPassword is the new password 678 * @param onComplete 679 * onComplete.obj will be an AsyncResult 680 * ((AsyncResult)onComplete.obj).exception == null on success 681 * ((AsyncResult)onComplete.obj).exception != null on fail 682 */ 683 public void changeIccFdnPassword(String oldPassword, String newPassword, 684 Message onComplete) { 685 synchronized (mLock) { 686 if (DBG) log("changeIccFdnPassword"); 687 mCi.changeIccPin2ForApp(oldPassword, newPassword, mAid, 688 onComplete); 689 } 690 } 691 692 private void log(String msg) { 693 Log.d(LOG_TAG, msg); 694 } 695 696 private void loge(String msg) { 697 Log.e(LOG_TAG, msg); 698 } 699 } 700