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