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