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