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