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