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.uicc; 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.telephony.Rlog; 26 27 import com.android.internal.telephony.CommandsInterface; 28 import com.android.internal.telephony.PhoneConstants; 29 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppState; 30 import com.android.internal.telephony.uicc.IccCardApplicationStatus.AppType; 31 import com.android.internal.telephony.uicc.IccCardApplicationStatus.PersoSubState; 32 import com.android.internal.telephony.uicc.IccCardStatus.PinState; 33 34 import java.io.FileDescriptor; 35 import java.io.PrintWriter; 36 37 /** 38 * {@hide} 39 */ 40 public class UiccCardApplication { 41 private static final String LOG_TAG = "UiccCardApplication"; 42 private static final boolean DBG = true; 43 44 private static final int EVENT_PIN1_PUK1_DONE = 1; 45 private static final int EVENT_CHANGE_PIN1_DONE = 2; 46 private static final int EVENT_CHANGE_PIN2_DONE = 3; 47 private static final int EVENT_QUERY_FACILITY_FDN_DONE = 4; 48 private static final int EVENT_CHANGE_FACILITY_FDN_DONE = 5; 49 private static final int EVENT_QUERY_FACILITY_LOCK_DONE = 6; 50 private static final int EVENT_CHANGE_FACILITY_LOCK_DONE = 7; 51 private static final int EVENT_PIN2_PUK2_DONE = 8; 52 private static final int EVENT_RADIO_UNAVAILABLE = 9; 53 54 /** 55 * These values are for authContext (parameter P2) per 3GPP TS 31.102 (Section 7.1.2) 56 */ 57 public static final int AUTH_CONTEXT_EAP_SIM = PhoneConstants.AUTH_CONTEXT_EAP_SIM; 58 public static final int AUTH_CONTEXT_EAP_AKA = PhoneConstants.AUTH_CONTEXT_EAP_AKA; 59 public static final int AUTH_CONTEXT_UNDEFINED = PhoneConstants.AUTH_CONTEXT_UNDEFINED; 60 61 private final Object mLock = new Object(); 62 private UiccProfile mUiccProfile; //parent 63 private AppState mAppState; 64 private AppType mAppType; 65 private int mAuthContext; 66 private PersoSubState mPersoSubState; 67 private String mAid; 68 private String mAppLabel; 69 private boolean mPin1Replaced; 70 private PinState mPin1State; 71 private PinState mPin2State; 72 private boolean mIccFdnEnabled; 73 private boolean mDesiredFdnEnabled; 74 private boolean mIccLockEnabled; 75 private boolean mDesiredPinLocked; 76 77 // App state will be ignored while deciding whether the card is ready or not. 78 private boolean mIgnoreApp; 79 private boolean mIccFdnAvailable = true; // Default is enabled. 80 81 private CommandsInterface mCi; 82 private Context mContext; 83 private IccRecords mIccRecords; 84 private IccFileHandler mIccFh; 85 86 private boolean mDestroyed;//set to true once this App is commanded to be disposed of. 87 88 private RegistrantList mReadyRegistrants = new RegistrantList(); 89 private RegistrantList mPinLockedRegistrants = new RegistrantList(); 90 private RegistrantList mNetworkLockedRegistrants = new RegistrantList(); 91 UiccCardApplication(UiccProfile uiccProfile, IccCardApplicationStatus as, Context c, CommandsInterface ci)92 public UiccCardApplication(UiccProfile uiccProfile, 93 IccCardApplicationStatus as, 94 Context c, 95 CommandsInterface ci) { 96 if (DBG) log("Creating UiccApp: " + as); 97 mUiccProfile = uiccProfile; 98 mAppState = as.app_state; 99 mAppType = as.app_type; 100 mAuthContext = getAuthContext(mAppType); 101 mPersoSubState = as.perso_substate; 102 mAid = as.aid; 103 mAppLabel = as.app_label; 104 mPin1Replaced = (as.pin1_replaced != 0); 105 mPin1State = as.pin1; 106 mPin2State = as.pin2; 107 mIgnoreApp = false; 108 109 mContext = c; 110 mCi = ci; 111 112 mIccFh = createIccFileHandler(as.app_type); 113 mIccRecords = createIccRecords(as.app_type, mContext, mCi); 114 if (mAppState == AppState.APPSTATE_READY) { 115 queryFdn(); 116 queryPin1State(); 117 } 118 mCi.registerForNotAvailable(mHandler, EVENT_RADIO_UNAVAILABLE, null); 119 } 120 update(IccCardApplicationStatus as, Context c, CommandsInterface ci)121 public void update (IccCardApplicationStatus as, Context c, CommandsInterface ci) { 122 synchronized (mLock) { 123 if (mDestroyed) { 124 loge("Application updated after destroyed! Fix me!"); 125 return; 126 } 127 128 if (DBG) log(mAppType + " update. New " + as); 129 mContext = c; 130 mCi = ci; 131 AppType oldAppType = mAppType; 132 AppState oldAppState = mAppState; 133 PersoSubState oldPersoSubState = mPersoSubState; 134 mAppType = as.app_type; 135 mAuthContext = getAuthContext(mAppType); 136 mAppState = as.app_state; 137 mPersoSubState = as.perso_substate; 138 mAid = as.aid; 139 mAppLabel = as.app_label; 140 mPin1Replaced = (as.pin1_replaced != 0); 141 mPin1State = as.pin1; 142 mPin2State = as.pin2; 143 144 if (mAppType != oldAppType) { 145 if (mIccFh != null) { mIccFh.dispose();} 146 if (mIccRecords != null) { mIccRecords.dispose();} 147 mIccFh = createIccFileHandler(as.app_type); 148 mIccRecords = createIccRecords(as.app_type, c, ci); 149 } 150 151 if (mPersoSubState != oldPersoSubState && 152 mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) { 153 notifyNetworkLockedRegistrantsIfNeeded(null); 154 } 155 156 if (mAppState != oldAppState) { 157 if (DBG) log(oldAppType + " changed state: " + oldAppState + " -> " + mAppState); 158 // If the app state turns to APPSTATE_READY, then query FDN status, 159 //as it might have failed in earlier attempt. 160 if (mAppState == AppState.APPSTATE_READY) { 161 queryFdn(); 162 queryPin1State(); 163 } 164 notifyPinLockedRegistrantsIfNeeded(null); 165 notifyReadyRegistrantsIfNeeded(null); 166 } 167 } 168 } 169 dispose()170 void dispose() { 171 synchronized (mLock) { 172 if (DBG) log(mAppType + " being Disposed"); 173 mDestroyed = true; 174 if (mIccRecords != null) { mIccRecords.dispose();} 175 if (mIccFh != null) { mIccFh.dispose();} 176 mIccRecords = null; 177 mIccFh = null; 178 mCi.unregisterForNotAvailable(mHandler); 179 } 180 } 181 createIccRecords(AppType type, Context c, CommandsInterface ci)182 private IccRecords createIccRecords(AppType type, Context c, CommandsInterface ci) { 183 if (type == AppType.APPTYPE_USIM || type == AppType.APPTYPE_SIM) { 184 return new SIMRecords(this, c, ci); 185 } else if (type == AppType.APPTYPE_RUIM || type == AppType.APPTYPE_CSIM){ 186 return new RuimRecords(this, c, ci); 187 } else if (type == AppType.APPTYPE_ISIM) { 188 return new IsimUiccRecords(this, c, ci); 189 } else { 190 // Unknown app type (maybe detection is still in progress) 191 return null; 192 } 193 } 194 createIccFileHandler(AppType type)195 private IccFileHandler createIccFileHandler(AppType type) { 196 switch (type) { 197 case APPTYPE_SIM: 198 return new SIMFileHandler(this, mAid, mCi); 199 case APPTYPE_RUIM: 200 return new RuimFileHandler(this, mAid, mCi); 201 case APPTYPE_USIM: 202 return new UsimFileHandler(this, mAid, mCi); 203 case APPTYPE_CSIM: 204 return new CsimFileHandler(this, mAid, mCi); 205 case APPTYPE_ISIM: 206 return new IsimFileHandler(this, mAid, mCi); 207 default: 208 return null; 209 } 210 } 211 212 /** Assumes mLock is held. */ queryFdn()213 public void queryFdn() { 214 //This shouldn't change run-time. So needs to be called only once. 215 int serviceClassX; 216 217 serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE + 218 CommandsInterface.SERVICE_CLASS_DATA + 219 CommandsInterface.SERVICE_CLASS_FAX; 220 mCi.queryFacilityLockForApp ( 221 CommandsInterface.CB_FACILITY_BA_FD, "", serviceClassX, 222 mAid, mHandler.obtainMessage(EVENT_QUERY_FACILITY_FDN_DONE)); 223 } 224 /** 225 * Interpret EVENT_QUERY_FACILITY_LOCK_DONE 226 * @param ar is asyncResult of Query_Facility_Locked 227 */ onQueryFdnEnabled(AsyncResult ar)228 private void onQueryFdnEnabled(AsyncResult ar) { 229 synchronized (mLock) { 230 if (ar.exception != null) { 231 if (DBG) log("Error in querying facility lock:" + ar.exception); 232 return; 233 } 234 235 int[] result = (int[])ar.result; 236 if(result.length != 0) { 237 //0 - Available & Disabled, 1-Available & Enabled, 2-Unavailable. 238 if (result[0] == 2) { 239 mIccFdnEnabled = false; 240 mIccFdnAvailable = false; 241 } else { 242 mIccFdnEnabled = (result[0] == 1) ? true : false; 243 mIccFdnAvailable = true; 244 } 245 log("Query facility FDN : FDN service available: "+ mIccFdnAvailable 246 +" enabled: " + mIccFdnEnabled); 247 } else { 248 loge("Bogus facility lock response"); 249 } 250 } 251 } 252 onChangeFdnDone(AsyncResult ar)253 private void onChangeFdnDone(AsyncResult ar) { 254 synchronized (mLock) { 255 int attemptsRemaining = -1; 256 257 if (ar.exception == null) { 258 mIccFdnEnabled = mDesiredFdnEnabled; 259 if (DBG) log("EVENT_CHANGE_FACILITY_FDN_DONE: " + 260 "mIccFdnEnabled=" + mIccFdnEnabled); 261 } else { 262 attemptsRemaining = parsePinPukErrorResult(ar); 263 loge("Error change facility fdn with exception " + ar.exception); 264 } 265 Message response = (Message)ar.userObj; 266 response.arg1 = attemptsRemaining; 267 AsyncResult.forMessage(response).exception = ar.exception; 268 response.sendToTarget(); 269 } 270 } 271 272 /** REMOVE when mIccLockEnabled is not needed, assumes mLock is held */ queryPin1State()273 private void queryPin1State() { 274 int serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE + 275 CommandsInterface.SERVICE_CLASS_DATA + 276 CommandsInterface.SERVICE_CLASS_FAX; 277 mCi.queryFacilityLockForApp ( 278 CommandsInterface.CB_FACILITY_BA_SIM, "", serviceClassX, 279 mAid, mHandler.obtainMessage(EVENT_QUERY_FACILITY_LOCK_DONE)); 280 } 281 282 /** REMOVE when mIccLockEnabled is not needed*/ onQueryFacilityLock(AsyncResult ar)283 private void onQueryFacilityLock(AsyncResult ar) { 284 synchronized (mLock) { 285 if(ar.exception != null) { 286 if (DBG) log("Error in querying facility lock:" + ar.exception); 287 return; 288 } 289 290 int[] ints = (int[])ar.result; 291 if(ints.length != 0) { 292 if (DBG) log("Query facility lock : " + ints[0]); 293 294 mIccLockEnabled = (ints[0] != 0); 295 296 if (mIccLockEnabled) { 297 mPinLockedRegistrants.notifyRegistrants(); 298 } 299 300 // Sanity check: we expect mPin1State to match mIccLockEnabled. 301 // When mPin1State is DISABLED mIccLockEanbled should be false. 302 // When mPin1State is ENABLED mIccLockEnabled should be true. 303 // 304 // Here we validate these assumptions to assist in identifying which ril/radio's 305 // have not correctly implemented GET_SIM_STATUS 306 switch (mPin1State) { 307 case PINSTATE_DISABLED: 308 if (mIccLockEnabled) { 309 loge("QUERY_FACILITY_LOCK:enabled GET_SIM_STATUS.Pin1:disabled." 310 + " Fixme"); 311 } 312 break; 313 case PINSTATE_ENABLED_NOT_VERIFIED: 314 case PINSTATE_ENABLED_VERIFIED: 315 case PINSTATE_ENABLED_BLOCKED: 316 case PINSTATE_ENABLED_PERM_BLOCKED: 317 if (!mIccLockEnabled) { 318 loge("QUERY_FACILITY_LOCK:disabled GET_SIM_STATUS.Pin1:enabled." 319 + " Fixme"); 320 } 321 case PINSTATE_UNKNOWN: 322 default: 323 if (DBG) log("Ignoring: pin1state=" + mPin1State); 324 break; 325 } 326 } else { 327 loge("Bogus facility lock response"); 328 } 329 } 330 } 331 332 /** REMOVE when mIccLockEnabled is not needed */ onChangeFacilityLock(AsyncResult ar)333 private void onChangeFacilityLock(AsyncResult ar) { 334 synchronized (mLock) { 335 int attemptsRemaining = -1; 336 337 if (ar.exception == null) { 338 mIccLockEnabled = mDesiredPinLocked; 339 if (DBG) log( "EVENT_CHANGE_FACILITY_LOCK_DONE: mIccLockEnabled= " 340 + mIccLockEnabled); 341 } else { 342 attemptsRemaining = parsePinPukErrorResult(ar); 343 loge("Error change facility lock with exception " + ar.exception); 344 } 345 Message response = (Message)ar.userObj; 346 AsyncResult.forMessage(response).exception = ar.exception; 347 response.arg1 = attemptsRemaining; 348 response.sendToTarget(); 349 } 350 } 351 352 /** 353 * Parse the error response to obtain number of attempts remaining 354 */ parsePinPukErrorResult(AsyncResult ar)355 private int parsePinPukErrorResult(AsyncResult ar) { 356 int[] result = (int[]) ar.result; 357 if (result == null) { 358 return -1; 359 } else { 360 int length = result.length; 361 int attemptsRemaining = -1; 362 if (length > 0) { 363 attemptsRemaining = result[0]; 364 } 365 log("parsePinPukErrorResult: attemptsRemaining=" + attemptsRemaining); 366 return attemptsRemaining; 367 } 368 } 369 370 private Handler mHandler = new Handler() { 371 @Override 372 public void handleMessage(Message msg){ 373 AsyncResult ar; 374 375 if (mDestroyed) { 376 loge("Received message " + msg + "[" + msg.what 377 + "] while being destroyed. Ignoring."); 378 return; 379 } 380 381 switch (msg.what) { 382 case EVENT_PIN1_PUK1_DONE: 383 case EVENT_PIN2_PUK2_DONE: 384 case EVENT_CHANGE_PIN1_DONE: 385 case EVENT_CHANGE_PIN2_DONE: 386 // a PIN/PUK/PIN2/PUK2 complete 387 // request has completed. ar.userObj is the response Message 388 ar = (AsyncResult)msg.obj; 389 int attemptsRemaining = parsePinPukErrorResult(ar); 390 Message response = (Message)ar.userObj; 391 AsyncResult.forMessage(response).exception = ar.exception; 392 response.arg1 = attemptsRemaining; 393 response.sendToTarget(); 394 break; 395 case EVENT_QUERY_FACILITY_FDN_DONE: 396 ar = (AsyncResult)msg.obj; 397 onQueryFdnEnabled(ar); 398 break; 399 case EVENT_CHANGE_FACILITY_FDN_DONE: 400 ar = (AsyncResult)msg.obj; 401 onChangeFdnDone(ar); 402 break; 403 case EVENT_QUERY_FACILITY_LOCK_DONE: 404 ar = (AsyncResult)msg.obj; 405 onQueryFacilityLock(ar); 406 break; 407 case EVENT_CHANGE_FACILITY_LOCK_DONE: 408 ar = (AsyncResult)msg.obj; 409 onChangeFacilityLock(ar); 410 break; 411 case EVENT_RADIO_UNAVAILABLE: 412 if (DBG) log("handleMessage (EVENT_RADIO_UNAVAILABLE)"); 413 mAppState = AppState.APPSTATE_UNKNOWN; 414 break; 415 default: 416 loge("Unknown Event " + msg.what); 417 } 418 } 419 }; 420 registerForReady(Handler h, int what, Object obj)421 public void registerForReady(Handler h, int what, Object obj) { 422 synchronized (mLock) { 423 Registrant r = new Registrant (h, what, obj); 424 mReadyRegistrants.add(r); 425 notifyReadyRegistrantsIfNeeded(r); 426 } 427 } 428 unregisterForReady(Handler h)429 public void unregisterForReady(Handler h) { 430 synchronized (mLock) { 431 mReadyRegistrants.remove(h); 432 } 433 } 434 435 /** 436 * Notifies handler of any transition into State.isPinLocked() 437 */ registerForLocked(Handler h, int what, Object obj)438 protected void registerForLocked(Handler h, int what, Object obj) { 439 synchronized (mLock) { 440 Registrant r = new Registrant (h, what, obj); 441 mPinLockedRegistrants.add(r); 442 notifyPinLockedRegistrantsIfNeeded(r); 443 } 444 } 445 unregisterForLocked(Handler h)446 protected void unregisterForLocked(Handler h) { 447 synchronized (mLock) { 448 mPinLockedRegistrants.remove(h); 449 } 450 } 451 452 /** 453 * Notifies handler of any transition into State.NETWORK_LOCKED 454 */ registerForNetworkLocked(Handler h, int what, Object obj)455 protected void registerForNetworkLocked(Handler h, int what, Object obj) { 456 synchronized (mLock) { 457 Registrant r = new Registrant (h, what, obj); 458 mNetworkLockedRegistrants.add(r); 459 notifyNetworkLockedRegistrantsIfNeeded(r); 460 } 461 } 462 unregisterForNetworkLocked(Handler h)463 protected void unregisterForNetworkLocked(Handler h) { 464 synchronized (mLock) { 465 mNetworkLockedRegistrants.remove(h); 466 } 467 } 468 469 /** 470 * Notifies specified registrant, assume mLock is held. 471 * 472 * @param r Registrant to be notified. If null - all registrants will be notified 473 */ notifyReadyRegistrantsIfNeeded(Registrant r)474 private void notifyReadyRegistrantsIfNeeded(Registrant r) { 475 if (mDestroyed) { 476 return; 477 } 478 if (mAppState == AppState.APPSTATE_READY) { 479 if (mPin1State == PinState.PINSTATE_ENABLED_NOT_VERIFIED || 480 mPin1State == PinState.PINSTATE_ENABLED_BLOCKED || 481 mPin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) { 482 loge("Sanity check failed! APPSTATE is ready while PIN1 is not verified!!!"); 483 // Don't notify if application is in insane state 484 return; 485 } 486 if (r == null) { 487 if (DBG) log("Notifying registrants: READY"); 488 mReadyRegistrants.notifyRegistrants(); 489 } else { 490 if (DBG) log("Notifying 1 registrant: READY"); 491 r.notifyRegistrant(new AsyncResult(null, null, null)); 492 } 493 } 494 } 495 496 /** 497 * Notifies specified registrant, assume mLock is held. 498 * 499 * @param r Registrant to be notified. If null - all registrants will be notified 500 */ notifyPinLockedRegistrantsIfNeeded(Registrant r)501 private void notifyPinLockedRegistrantsIfNeeded(Registrant r) { 502 if (mDestroyed) { 503 return; 504 } 505 506 if (mAppState == AppState.APPSTATE_PIN || 507 mAppState == AppState.APPSTATE_PUK) { 508 if (mPin1State == PinState.PINSTATE_ENABLED_VERIFIED || 509 mPin1State == PinState.PINSTATE_DISABLED) { 510 loge("Sanity check failed! APPSTATE is locked while PIN1 is not!!!"); 511 //Don't notify if application is in insane state 512 return; 513 } 514 if (r == null) { 515 if (DBG) log("Notifying registrants: LOCKED"); 516 mPinLockedRegistrants.notifyRegistrants(); 517 } else { 518 if (DBG) log("Notifying 1 registrant: LOCKED"); 519 r.notifyRegistrant(new AsyncResult(null, null, null)); 520 } 521 } 522 } 523 524 /** 525 * Notifies specified registrant, assume mLock is held. 526 * 527 * @param r Registrant to be notified. If null - all registrants will be notified 528 */ notifyNetworkLockedRegistrantsIfNeeded(Registrant r)529 private void notifyNetworkLockedRegistrantsIfNeeded(Registrant r) { 530 if (mDestroyed) { 531 return; 532 } 533 534 if (mAppState == AppState.APPSTATE_SUBSCRIPTION_PERSO && 535 mPersoSubState == PersoSubState.PERSOSUBSTATE_SIM_NETWORK) { 536 if (r == null) { 537 if (DBG) log("Notifying registrants: NETWORK_LOCKED"); 538 mNetworkLockedRegistrants.notifyRegistrants(); 539 } else { 540 if (DBG) log("Notifying 1 registrant: NETWORK_LOCED"); 541 r.notifyRegistrant(new AsyncResult(null, null, null)); 542 } 543 } 544 } 545 getState()546 public AppState getState() { 547 synchronized (mLock) { 548 return mAppState; 549 } 550 } 551 getType()552 public AppType getType() { 553 synchronized (mLock) { 554 return mAppType; 555 } 556 } 557 getAuthContext()558 public int getAuthContext() { 559 synchronized (mLock) { 560 return mAuthContext; 561 } 562 } 563 564 /** 565 * Returns the authContext based on the type of UiccCard. 566 * 567 * @param appType the app type 568 * @return authContext corresponding to the type or AUTH_CONTEXT_UNDEFINED if appType not 569 * supported 570 */ getAuthContext(AppType appType)571 private static int getAuthContext(AppType appType) { 572 int authContext; 573 574 switch (appType) { 575 case APPTYPE_SIM: 576 authContext = AUTH_CONTEXT_EAP_SIM; 577 break; 578 579 case APPTYPE_USIM: 580 authContext = AUTH_CONTEXT_EAP_AKA; 581 break; 582 583 default: 584 authContext = AUTH_CONTEXT_UNDEFINED; 585 break; 586 } 587 588 return authContext; 589 } 590 getPersoSubState()591 public PersoSubState getPersoSubState() { 592 synchronized (mLock) { 593 return mPersoSubState; 594 } 595 } 596 getAid()597 public String getAid() { 598 synchronized (mLock) { 599 return mAid; 600 } 601 } 602 getAppLabel()603 public String getAppLabel() { 604 return mAppLabel; 605 } 606 getPin1State()607 public PinState getPin1State() { 608 synchronized (mLock) { 609 if (mPin1Replaced) { 610 return mUiccProfile.getUniversalPinState(); 611 } 612 return mPin1State; 613 } 614 } 615 getIccFileHandler()616 public IccFileHandler getIccFileHandler() { 617 synchronized (mLock) { 618 return mIccFh; 619 } 620 } 621 getIccRecords()622 public IccRecords getIccRecords() { 623 synchronized (mLock) { 624 return mIccRecords; 625 } 626 } 627 628 /** 629 * Supply the ICC PIN to the ICC 630 * 631 * When the operation is complete, onComplete will be sent to its 632 * Handler. 633 * 634 * onComplete.obj will be an AsyncResult 635 * onComplete.arg1 = remaining attempts before puk locked or -1 if unknown 636 * 637 * ((AsyncResult)onComplete.obj).exception == null on success 638 * ((AsyncResult)onComplete.obj).exception != null on fail 639 * 640 * If the supplied PIN is incorrect: 641 * ((AsyncResult)onComplete.obj).exception != null 642 * && ((AsyncResult)onComplete.obj).exception 643 * instanceof com.android.internal.telephony.gsm.CommandException) 644 * && ((CommandException)(((AsyncResult)onComplete.obj).exception)) 645 * .getCommandError() == CommandException.Error.PASSWORD_INCORRECT 646 */ supplyPin(String pin, Message onComplete)647 public void supplyPin (String pin, Message onComplete) { 648 synchronized (mLock) { 649 mCi.supplyIccPinForApp(pin, mAid, mHandler.obtainMessage(EVENT_PIN1_PUK1_DONE, 650 onComplete)); 651 } 652 } 653 654 /** 655 * Supply the ICC PUK to the ICC 656 * 657 * When the operation is complete, onComplete will be sent to its 658 * Handler. 659 * 660 * onComplete.obj will be an AsyncResult 661 * onComplete.arg1 = remaining attempts before Icc will be permanently unusable 662 * or -1 if unknown 663 * 664 * ((AsyncResult)onComplete.obj).exception == null on success 665 * ((AsyncResult)onComplete.obj).exception != null on fail 666 * 667 * If the supplied PIN is incorrect: 668 * ((AsyncResult)onComplete.obj).exception != null 669 * && ((AsyncResult)onComplete.obj).exception 670 * instanceof com.android.internal.telephony.gsm.CommandException) 671 * && ((CommandException)(((AsyncResult)onComplete.obj).exception)) 672 * .getCommandError() == CommandException.Error.PASSWORD_INCORRECT 673 * 674 * 675 */ supplyPuk(String puk, String newPin, Message onComplete)676 public void supplyPuk (String puk, String newPin, Message onComplete) { 677 synchronized (mLock) { 678 mCi.supplyIccPukForApp(puk, newPin, mAid, 679 mHandler.obtainMessage(EVENT_PIN1_PUK1_DONE, onComplete)); 680 } 681 } 682 supplyPin2(String pin2, Message onComplete)683 public void supplyPin2 (String pin2, Message onComplete) { 684 synchronized (mLock) { 685 mCi.supplyIccPin2ForApp(pin2, mAid, 686 mHandler.obtainMessage(EVENT_PIN2_PUK2_DONE, onComplete)); 687 } 688 } 689 supplyPuk2(String puk2, String newPin2, Message onComplete)690 public void supplyPuk2 (String puk2, String newPin2, Message onComplete) { 691 synchronized (mLock) { 692 mCi.supplyIccPuk2ForApp(puk2, newPin2, mAid, 693 mHandler.obtainMessage(EVENT_PIN2_PUK2_DONE, onComplete)); 694 } 695 } 696 supplyNetworkDepersonalization(String pin, Message onComplete)697 public void supplyNetworkDepersonalization (String pin, Message onComplete) { 698 synchronized (mLock) { 699 if (DBG) log("supplyNetworkDepersonalization"); 700 mCi.supplyNetworkDepersonalization(pin, onComplete); 701 } 702 } 703 704 /** 705 * Check whether ICC pin lock is enabled 706 * This is a sync call which returns the cached pin enabled state 707 * 708 * @return true for ICC locked enabled 709 * false for ICC locked disabled 710 */ getIccLockEnabled()711 public boolean getIccLockEnabled() { 712 return mIccLockEnabled; 713 /* STOPSHIP: Remove line above and all code associated with setting 714 mIccLockEanbled once all RIL correctly sends the pin1 state. 715 // Use getPin1State to take into account pin1Replaced flag 716 PinState pinState = getPin1State(); 717 return pinState == PinState.PINSTATE_ENABLED_NOT_VERIFIED || 718 pinState == PinState.PINSTATE_ENABLED_VERIFIED || 719 pinState == PinState.PINSTATE_ENABLED_BLOCKED || 720 pinState == PinState.PINSTATE_ENABLED_PERM_BLOCKED;*/ 721 } 722 723 /** 724 * Check whether ICC fdn (fixed dialing number) is enabled 725 * This is a sync call which returns the cached pin enabled state 726 * 727 * @return true for ICC fdn enabled 728 * false for ICC fdn disabled 729 */ getIccFdnEnabled()730 public boolean getIccFdnEnabled() { 731 synchronized (mLock) { 732 return mIccFdnEnabled; 733 } 734 } 735 736 /** 737 * Check whether fdn (fixed dialing number) service is available. 738 * @return true if ICC fdn service available 739 * false if ICC fdn service not available 740 */ getIccFdnAvailable()741 public boolean getIccFdnAvailable() { 742 return mIccFdnAvailable; 743 } 744 745 /** 746 * Set the ICC pin lock enabled or disabled 747 * When the operation is complete, onComplete will be sent to its handler 748 * 749 * @param enabled "true" for locked "false" for unlocked. 750 * @param password needed to change the ICC pin state, aka. Pin1 751 * @param onComplete 752 * onComplete.obj will be an AsyncResult 753 * ((AsyncResult)onComplete.obj).exception == null on success 754 * ((AsyncResult)onComplete.obj).exception != null on fail 755 */ setIccLockEnabled(boolean enabled, String password, Message onComplete)756 public void setIccLockEnabled (boolean enabled, 757 String password, Message onComplete) { 758 synchronized (mLock) { 759 int serviceClassX; 760 serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE + 761 CommandsInterface.SERVICE_CLASS_DATA + 762 CommandsInterface.SERVICE_CLASS_FAX; 763 764 mDesiredPinLocked = enabled; 765 766 mCi.setFacilityLockForApp(CommandsInterface.CB_FACILITY_BA_SIM, 767 enabled, password, serviceClassX, mAid, 768 mHandler.obtainMessage(EVENT_CHANGE_FACILITY_LOCK_DONE, onComplete)); 769 } 770 } 771 772 /** 773 * Set the ICC fdn enabled or disabled 774 * When the operation is complete, onComplete will be sent to its handler 775 * 776 * @param enabled "true" for locked "false" for unlocked. 777 * @param password needed to change the ICC fdn enable, aka Pin2 778 * @param onComplete 779 * onComplete.obj will be an AsyncResult 780 * ((AsyncResult)onComplete.obj).exception == null on success 781 * ((AsyncResult)onComplete.obj).exception != null on fail 782 */ setIccFdnEnabled(boolean enabled, String password, Message onComplete)783 public void setIccFdnEnabled (boolean enabled, 784 String password, Message onComplete) { 785 synchronized (mLock) { 786 int serviceClassX; 787 serviceClassX = CommandsInterface.SERVICE_CLASS_VOICE + 788 CommandsInterface.SERVICE_CLASS_DATA + 789 CommandsInterface.SERVICE_CLASS_FAX + 790 CommandsInterface.SERVICE_CLASS_SMS; 791 792 mDesiredFdnEnabled = enabled; 793 794 mCi.setFacilityLockForApp(CommandsInterface.CB_FACILITY_BA_FD, 795 enabled, password, serviceClassX, mAid, 796 mHandler.obtainMessage(EVENT_CHANGE_FACILITY_FDN_DONE, onComplete)); 797 } 798 } 799 800 /** 801 * Change the ICC password used in ICC pin lock 802 * When the operation is complete, onComplete will be sent to its handler 803 * 804 * @param oldPassword is the old password 805 * @param newPassword is the new password 806 * @param onComplete 807 * onComplete.obj will be an AsyncResult 808 * onComplete.arg1 = attempts remaining or -1 if unknown 809 * ((AsyncResult)onComplete.obj).exception == null on success 810 * ((AsyncResult)onComplete.obj).exception != null on fail 811 */ changeIccLockPassword(String oldPassword, String newPassword, Message onComplete)812 public void changeIccLockPassword(String oldPassword, String newPassword, 813 Message onComplete) { 814 synchronized (mLock) { 815 if (DBG) log("changeIccLockPassword"); 816 mCi.changeIccPinForApp(oldPassword, newPassword, mAid, 817 mHandler.obtainMessage(EVENT_CHANGE_PIN1_DONE, onComplete)); 818 } 819 } 820 821 /** 822 * Change the ICC password used in ICC fdn enable 823 * When the operation is complete, onComplete will be sent to its handler 824 * 825 * @param oldPassword is the old password 826 * @param newPassword is the new password 827 * @param onComplete 828 * onComplete.obj will be an AsyncResult 829 * ((AsyncResult)onComplete.obj).exception == null on success 830 * ((AsyncResult)onComplete.obj).exception != null on fail 831 */ changeIccFdnPassword(String oldPassword, String newPassword, Message onComplete)832 public void changeIccFdnPassword(String oldPassword, String newPassword, 833 Message onComplete) { 834 synchronized (mLock) { 835 if (DBG) log("changeIccFdnPassword"); 836 mCi.changeIccPin2ForApp(oldPassword, newPassword, mAid, 837 mHandler.obtainMessage(EVENT_CHANGE_PIN2_DONE, onComplete)); 838 } 839 } 840 841 /** 842 * @return true if the UiccCardApplication is ready. 843 */ isReady()844 public boolean isReady() { 845 synchronized (mLock) { 846 if (mAppState != AppState.APPSTATE_READY) { 847 return false; 848 } else if (mPin1State == PinState.PINSTATE_ENABLED_NOT_VERIFIED 849 || mPin1State == PinState.PINSTATE_ENABLED_BLOCKED 850 || mPin1State == PinState.PINSTATE_ENABLED_PERM_BLOCKED) { 851 loge("Sanity check failed! APPSTATE is ready while PIN1 is not verified!!!"); 852 return false; 853 } else { 854 return true; 855 } 856 } 857 } 858 859 /** 860 * @return true if ICC card is PIN2 blocked 861 */ getIccPin2Blocked()862 public boolean getIccPin2Blocked() { 863 synchronized (mLock) { 864 return mPin2State == PinState.PINSTATE_ENABLED_BLOCKED; 865 } 866 } 867 868 /** 869 * @return true if ICC card is PUK2 blocked 870 */ getIccPuk2Blocked()871 public boolean getIccPuk2Blocked() { 872 synchronized (mLock) { 873 return mPin2State == PinState.PINSTATE_ENABLED_PERM_BLOCKED; 874 } 875 } 876 getPhoneId()877 public int getPhoneId() { 878 return mUiccProfile.getPhoneId(); 879 } 880 isAppIgnored()881 public boolean isAppIgnored() { 882 return mIgnoreApp; 883 } 884 setAppIgnoreState(boolean ignore)885 public void setAppIgnoreState(boolean ignore) { 886 mIgnoreApp = ignore; 887 } 888 getUiccProfile()889 protected UiccProfile getUiccProfile() { 890 return mUiccProfile; 891 } 892 log(String msg)893 private void log(String msg) { 894 Rlog.d(LOG_TAG, msg); 895 } 896 loge(String msg)897 private void loge(String msg) { 898 Rlog.e(LOG_TAG, msg); 899 } 900 dump(FileDescriptor fd, PrintWriter pw, String[] args)901 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 902 pw.println("UiccCardApplication: " + this); 903 pw.println(" mUiccProfile=" + mUiccProfile); 904 pw.println(" mAppState=" + mAppState); 905 pw.println(" mAppType=" + mAppType); 906 pw.println(" mPersoSubState=" + mPersoSubState); 907 pw.println(" mAid=" + mAid); 908 pw.println(" mAppLabel=" + mAppLabel); 909 pw.println(" mPin1Replaced=" + mPin1Replaced); 910 pw.println(" mPin1State=" + mPin1State); 911 pw.println(" mPin2State=" + mPin2State); 912 pw.println(" mIccFdnEnabled=" + mIccFdnEnabled); 913 pw.println(" mDesiredFdnEnabled=" + mDesiredFdnEnabled); 914 pw.println(" mIccLockEnabled=" + mIccLockEnabled); 915 pw.println(" mDesiredPinLocked=" + mDesiredPinLocked); 916 pw.println(" mCi=" + mCi); 917 pw.println(" mIccRecords=" + mIccRecords); 918 pw.println(" mIccFh=" + mIccFh); 919 pw.println(" mDestroyed=" + mDestroyed); 920 pw.println(" mReadyRegistrants: size=" + mReadyRegistrants.size()); 921 for (int i = 0; i < mReadyRegistrants.size(); i++) { 922 pw.println(" mReadyRegistrants[" + i + "]=" 923 + ((Registrant)mReadyRegistrants.get(i)).getHandler()); 924 } 925 pw.println(" mPinLockedRegistrants: size=" + mPinLockedRegistrants.size()); 926 for (int i = 0; i < mPinLockedRegistrants.size(); i++) { 927 pw.println(" mPinLockedRegistrants[" + i + "]=" 928 + ((Registrant)mPinLockedRegistrants.get(i)).getHandler()); 929 } 930 pw.println(" mNetworkLockedRegistrants: size=" + mNetworkLockedRegistrants.size()); 931 for (int i = 0; i < mNetworkLockedRegistrants.size(); i++) { 932 pw.println(" mNetworkLockedRegistrants[" + i + "]=" 933 + ((Registrant)mNetworkLockedRegistrants.get(i)).getHandler()); 934 } 935 pw.flush(); 936 } 937 } 938