1 /* 2 * Copyright (C) 2011-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 static android.telephony.TelephonyManager.UNINITIALIZED_CARD_ID; 20 import static android.telephony.TelephonyManager.UNSUPPORTED_CARD_ID; 21 22 import static java.util.Arrays.copyOf; 23 24 import android.app.BroadcastOptions; 25 import android.compat.annotation.UnsupportedAppUsage; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.SharedPreferences; 29 import android.content.pm.PackageManager; 30 import android.os.AsyncResult; 31 import android.os.Build; 32 import android.os.Handler; 33 import android.os.Message; 34 import android.os.Registrant; 35 import android.os.RegistrantList; 36 import android.os.storage.StorageManager; 37 import android.preference.PreferenceManager; 38 import android.sysprop.TelephonyProperties; 39 import android.telephony.CarrierConfigManager; 40 import android.telephony.SubscriptionManager; 41 import android.telephony.TelephonyManager; 42 import android.telephony.UiccCardInfo; 43 import android.text.TextUtils; 44 import android.util.LocalLog; 45 46 import com.android.internal.annotations.VisibleForTesting; 47 import com.android.internal.telephony.CommandException; 48 import com.android.internal.telephony.CommandsInterface; 49 import com.android.internal.telephony.IccCardConstants; 50 import com.android.internal.telephony.PhoneConfigurationManager; 51 import com.android.internal.telephony.PhoneConstants; 52 import com.android.internal.telephony.PhoneFactory; 53 import com.android.internal.telephony.RadioConfig; 54 import com.android.internal.telephony.SubscriptionInfoUpdater; 55 import com.android.internal.telephony.uicc.euicc.EuiccCard; 56 import com.android.internal.telephony.util.TelephonyUtils; 57 import com.android.telephony.Rlog; 58 59 import java.io.FileDescriptor; 60 import java.io.PrintWriter; 61 import java.util.ArrayList; 62 import java.util.Arrays; 63 import java.util.HashSet; 64 import java.util.Set; 65 66 /** 67 * This class is responsible for keeping all knowledge about 68 * Universal Integrated Circuit Card (UICC), also know as SIM's, 69 * in the system. It is also used as API to get appropriate 70 * applications to pass them to phone and service trackers. 71 * 72 * UiccController is created with the call to make() function. 73 * UiccController is a singleton and make() must only be called once 74 * and throws an exception if called multiple times. 75 * 76 * Once created UiccController registers with RIL for "on" and "unsol_sim_status_changed" 77 * notifications. When such notification arrives UiccController will call 78 * getIccCardStatus (GET_SIM_STATUS). Based on the response of GET_SIM_STATUS 79 * request appropriate tree of uicc objects will be created. 80 * 81 * Following is class diagram for uicc classes: 82 * 83 * UiccController 84 * # 85 * | 86 * UiccSlot[] 87 * # 88 * | 89 * UiccCard 90 * # 91 * | 92 * UiccProfile 93 * # # 94 * | ------------------ 95 * UiccCardApplication CatService 96 * # # 97 * | | 98 * IccRecords IccFileHandler 99 * ^ ^ ^ ^ ^ ^ ^ ^ 100 * SIMRecords---- | | | | | | ---SIMFileHandler 101 * RuimRecords----- | | | | ----RuimFileHandler 102 * IsimUiccRecords--- | | -----UsimFileHandler 103 * | ------CsimFileHandler 104 * ----IsimFileHandler 105 * 106 * Legend: # stands for Composition 107 * ^ stands for Generalization 108 * 109 * See also {@link com.android.internal.telephony.IccCard} 110 */ 111 public class UiccController extends Handler { 112 private static final boolean DBG = true; 113 private static final boolean VDBG = false; //STOPSHIP if true 114 private static final String LOG_TAG = "UiccController"; 115 116 public static final int INVALID_SLOT_ID = -1; 117 118 public static final int APP_FAM_3GPP = 1; 119 public static final int APP_FAM_3GPP2 = 2; 120 public static final int APP_FAM_IMS = 3; 121 122 private static final int EVENT_ICC_STATUS_CHANGED = 1; 123 private static final int EVENT_SLOT_STATUS_CHANGED = 2; 124 private static final int EVENT_GET_ICC_STATUS_DONE = 3; 125 private static final int EVENT_GET_SLOT_STATUS_DONE = 4; 126 private static final int EVENT_RADIO_ON = 5; 127 private static final int EVENT_RADIO_AVAILABLE = 6; 128 private static final int EVENT_RADIO_UNAVAILABLE = 7; 129 private static final int EVENT_SIM_REFRESH = 8; 130 private static final int EVENT_EID_READY = 9; 131 private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 10; 132 // NOTE: any new EVENT_* values must be added to eventToString. 133 134 // this needs to be here, because on bootup we dont know which index maps to which UiccSlot 135 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 136 private CommandsInterface[] mCis; 137 @VisibleForTesting 138 public UiccSlot[] mUiccSlots; 139 private int[] mPhoneIdToSlotId; 140 private boolean mIsSlotStatusSupported = true; 141 142 // This maps the externally exposed card ID (int) to the internal card ID string (ICCID/EID). 143 // The array index is the card ID (int). 144 // This mapping exists to expose card-based functionality without exposing the EID, which is 145 // considered sensetive information. 146 // mCardStrings is populated using values from the IccSlotStatus and IccCardStatus. For 147 // HAL < 1.2, these do not contain the EID or the ICCID, so mCardStrings will be empty 148 private ArrayList<String> mCardStrings; 149 150 // This is the card ID of the default eUICC. It starts as UNINITIALIZED_CARD_ID. 151 // When we load the EID (either with slot status or from the EuiccCard), we set it to the eUICC 152 // with the lowest slot index. 153 // If EID is not supported (e.g. on HAL version < 1.2), we set it to UNSUPPORTED_CARD_ID 154 private int mDefaultEuiccCardId; 155 156 // Default Euicc Card ID used when the device is temporarily unable to read the EID (e.g. on HAL 157 // 1.2-1.3 if the eUICC is currently inactive). This value is only used within the 158 // UiccController and should be converted to UNSUPPORTED_CARD_ID when others ask. 159 // (This value is -3 because UNSUPPORTED_CARD_ID and UNINITIALIZED_CARD_ID are -1 and -2) 160 private static final int TEMPORARILY_UNSUPPORTED_CARD_ID = -3; 161 162 // GSM SGP.02 section 2.2.2 states that the EID is always 32 digits long 163 private static final int EID_LENGTH = 32; 164 165 // SharedPreference key for saving the known card strings (ICCIDs and EIDs) ordered by card ID 166 private static final String CARD_STRINGS = "card_strings"; 167 168 // Whether the device has an eUICC built in. 169 private boolean mHasBuiltInEuicc = false; 170 171 // Whether the device has a currently active built in eUICC 172 private boolean mHasActiveBuiltInEuicc = false; 173 174 // The physical slots which correspond to built-in eUICCs 175 private final int[] mEuiccSlots; 176 177 // SharedPreferences key for saving the default euicc card ID 178 private static final String DEFAULT_CARD = "default_card"; 179 180 @UnsupportedAppUsage 181 private static final Object mLock = new Object(); 182 @UnsupportedAppUsage 183 private static UiccController mInstance; 184 @VisibleForTesting 185 public static ArrayList<IccSlotStatus> sLastSlotStatus; 186 187 @UnsupportedAppUsage 188 @VisibleForTesting 189 public Context mContext; 190 191 protected RegistrantList mIccChangedRegistrants = new RegistrantList(); 192 193 private UiccStateChangedLauncher mLauncher; 194 private RadioConfig mRadioConfig; 195 196 /* The storage for the PIN codes. */ 197 private final PinStorage mPinStorage; 198 199 // LocalLog buffer to hold important SIM related events for debugging 200 private static LocalLog sLocalLog = new LocalLog(TelephonyUtils.IS_DEBUGGABLE ? 250 : 100); 201 202 /** 203 * API to make UiccController singleton if not already created. 204 */ make(Context c)205 public static UiccController make(Context c) { 206 synchronized (mLock) { 207 if (mInstance != null) { 208 throw new RuntimeException("UiccController.make() should only be called once"); 209 } 210 mInstance = new UiccController(c); 211 return mInstance; 212 } 213 } 214 UiccController(Context c)215 private UiccController(Context c) { 216 if (DBG) log("Creating UiccController"); 217 mContext = c; 218 mCis = PhoneFactory.getCommandsInterfaces(); 219 int numPhysicalSlots = c.getResources().getInteger( 220 com.android.internal.R.integer.config_num_physical_slots); 221 numPhysicalSlots = TelephonyProperties.sim_slots_count().orElse(numPhysicalSlots); 222 if (DBG) { 223 logWithLocalLog("config_num_physical_slots = " + numPhysicalSlots); 224 } 225 // Minimum number of physical slot count should be equals to or greater than phone count, 226 // if it is less than phone count use phone count as physical slot count. 227 if (numPhysicalSlots < mCis.length) { 228 numPhysicalSlots = mCis.length; 229 } 230 231 mUiccSlots = new UiccSlot[numPhysicalSlots]; 232 mPhoneIdToSlotId = new int[mCis.length]; 233 Arrays.fill(mPhoneIdToSlotId, INVALID_SLOT_ID); 234 if (VDBG) logPhoneIdToSlotIdMapping(); 235 mRadioConfig = RadioConfig.getInstance(); 236 mRadioConfig.registerForSimSlotStatusChanged(this, EVENT_SLOT_STATUS_CHANGED, null); 237 for (int i = 0; i < mCis.length; i++) { 238 mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, i); 239 240 if (!StorageManager.inCryptKeeperBounce()) { 241 mCis[i].registerForAvailable(this, EVENT_RADIO_AVAILABLE, i); 242 } else { 243 mCis[i].registerForOn(this, EVENT_RADIO_ON, i); 244 } 245 246 mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, i); 247 mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, i); 248 } 249 250 mLauncher = new UiccStateChangedLauncher(c, this); 251 mCardStrings = loadCardStrings(); 252 mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; 253 254 mEuiccSlots = mContext.getResources() 255 .getIntArray(com.android.internal.R.array.non_removable_euicc_slots); 256 mHasBuiltInEuicc = hasBuiltInEuicc(); 257 258 PhoneConfigurationManager.registerForMultiSimConfigChange( 259 this, EVENT_MULTI_SIM_CONFIG_CHANGED, null); 260 261 mPinStorage = new PinStorage(mContext); 262 } 263 264 /** 265 * Given the slot index, return the phone ID, or -1 if no phone is associated with the given 266 * slot. 267 * @param slotId the slot index to check 268 * @return the associated phone ID or -1 269 */ getPhoneIdFromSlotId(int slotId)270 public int getPhoneIdFromSlotId(int slotId) { 271 for (int i = 0; i < mPhoneIdToSlotId.length; i++) { 272 if (mPhoneIdToSlotId[i] == slotId) { 273 return i; 274 } 275 } 276 return -1; 277 } 278 279 /** 280 * Return the physical slot id associated with the given phoneId, or INVALID_SLOT_ID. 281 * @param phoneId the phoneId to check 282 */ getSlotIdFromPhoneId(int phoneId)283 public int getSlotIdFromPhoneId(int phoneId) { 284 try { 285 return mPhoneIdToSlotId[phoneId]; 286 } catch (ArrayIndexOutOfBoundsException e) { 287 return INVALID_SLOT_ID; 288 } 289 } 290 291 @UnsupportedAppUsage getInstance()292 public static UiccController getInstance() { 293 synchronized (mLock) { 294 if (mInstance == null) { 295 throw new RuntimeException( 296 "UiccController.getInstance can't be called before make()"); 297 } 298 return mInstance; 299 } 300 } 301 302 @UnsupportedAppUsage getUiccCard(int phoneId)303 public UiccCard getUiccCard(int phoneId) { 304 synchronized (mLock) { 305 return getUiccCardForPhone(phoneId); 306 } 307 } 308 309 /** 310 * API to get UiccCard corresponding to given physical slot index 311 * @param slotId index of physical slot on the device 312 * @return UiccCard object corresponting to given physical slot index; null if card is 313 * absent 314 */ getUiccCardForSlot(int slotId)315 public UiccCard getUiccCardForSlot(int slotId) { 316 synchronized (mLock) { 317 UiccSlot uiccSlot = getUiccSlot(slotId); 318 if (uiccSlot != null) { 319 return uiccSlot.getUiccCard(); 320 } 321 return null; 322 } 323 } 324 325 /** 326 * API to get UiccCard corresponding to given phone id 327 * @return UiccCard object corresponding to given phone id; null if there is no card present for 328 * the phone id 329 */ getUiccCardForPhone(int phoneId)330 public UiccCard getUiccCardForPhone(int phoneId) { 331 synchronized (mLock) { 332 if (isValidPhoneIndex(phoneId)) { 333 UiccSlot uiccSlot = getUiccSlotForPhone(phoneId); 334 if (uiccSlot != null) { 335 return uiccSlot.getUiccCard(); 336 } 337 } 338 return null; 339 } 340 } 341 342 /** 343 * API to get UiccProfile corresponding to given phone id 344 * @return UiccProfile object corresponding to given phone id; null if there is no card/profile 345 * present for the phone id 346 */ getUiccProfileForPhone(int phoneId)347 public UiccProfile getUiccProfileForPhone(int phoneId) { 348 synchronized (mLock) { 349 if (isValidPhoneIndex(phoneId)) { 350 UiccCard uiccCard = getUiccCardForPhone(phoneId); 351 return uiccCard != null ? uiccCard.getUiccProfile() : null; 352 } 353 return null; 354 } 355 } 356 357 /** 358 * API to get all the UICC slots. 359 * @return UiccSlots array. 360 */ getUiccSlots()361 public UiccSlot[] getUiccSlots() { 362 synchronized (mLock) { 363 return mUiccSlots; 364 } 365 } 366 367 /** Map logicalSlot to physicalSlot, and activate the physicalSlot if it is inactive. */ switchSlots(int[] physicalSlots, Message response)368 public void switchSlots(int[] physicalSlots, Message response) { 369 logWithLocalLog("switchSlots: " + Arrays.toString(physicalSlots)); 370 mRadioConfig.setSimSlotsMapping(physicalSlots, response); 371 } 372 373 /** 374 * API to get UiccSlot object for a specific physical slot index on the device 375 * @return UiccSlot object for the given physical slot index 376 */ getUiccSlot(int slotId)377 public UiccSlot getUiccSlot(int slotId) { 378 synchronized (mLock) { 379 if (isValidSlotIndex(slotId)) { 380 return mUiccSlots[slotId]; 381 } 382 return null; 383 } 384 } 385 386 /** 387 * API to get UiccSlot object for a given phone id 388 * @return UiccSlot object for the given phone id 389 */ getUiccSlotForPhone(int phoneId)390 public UiccSlot getUiccSlotForPhone(int phoneId) { 391 synchronized (mLock) { 392 if (isValidPhoneIndex(phoneId)) { 393 int slotId = getSlotIdFromPhoneId(phoneId); 394 if (isValidSlotIndex(slotId)) { 395 return mUiccSlots[slotId]; 396 } 397 } 398 return null; 399 } 400 } 401 402 /** 403 * API to get UiccSlot object for a given cardId 404 * @param cardId Identifier for a SIM. This can be an ICCID, or an EID in case of an eSIM. 405 * @return int Index of UiccSlot for the given cardId if one is found, {@link #INVALID_SLOT_ID} 406 * otherwise 407 */ getUiccSlotForCardId(String cardId)408 public int getUiccSlotForCardId(String cardId) { 409 synchronized (mLock) { 410 // first look up based on cardId 411 for (int idx = 0; idx < mUiccSlots.length; idx++) { 412 if (mUiccSlots[idx] != null) { 413 UiccCard uiccCard = mUiccSlots[idx].getUiccCard(); 414 if (uiccCard != null && cardId.equals(uiccCard.getCardId())) { 415 return idx; 416 } 417 } 418 } 419 // if a match is not found, do a lookup based on ICCID 420 for (int idx = 0; idx < mUiccSlots.length; idx++) { 421 if (mUiccSlots[idx] != null && cardId.equals(mUiccSlots[idx].getIccId())) { 422 return idx; 423 } 424 } 425 return INVALID_SLOT_ID; 426 } 427 } 428 429 // Easy to use API 430 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getIccRecords(int phoneId, int family)431 public IccRecords getIccRecords(int phoneId, int family) { 432 synchronized (mLock) { 433 UiccCardApplication app = getUiccCardApplication(phoneId, family); 434 if (app != null) { 435 return app.getIccRecords(); 436 } 437 return null; 438 } 439 } 440 441 // Easy to use API 442 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getIccFileHandler(int phoneId, int family)443 public IccFileHandler getIccFileHandler(int phoneId, int family) { 444 synchronized (mLock) { 445 UiccCardApplication app = getUiccCardApplication(phoneId, family); 446 if (app != null) { 447 return app.getIccFileHandler(); 448 } 449 return null; 450 } 451 } 452 453 454 //Notifies when card status changes 455 @UnsupportedAppUsage registerForIccChanged(Handler h, int what, Object obj)456 public void registerForIccChanged(Handler h, int what, Object obj) { 457 synchronized (mLock) { 458 mIccChangedRegistrants.addUnique(h, what, obj); 459 } 460 //Notify registrant right after registering, so that it will get the latest ICC status, 461 //otherwise which may not happen until there is an actual change in ICC status. 462 Message.obtain(h, what, new AsyncResult(obj, null, null)).sendToTarget(); 463 } 464 unregisterForIccChanged(Handler h)465 public void unregisterForIccChanged(Handler h) { 466 synchronized (mLock) { 467 mIccChangedRegistrants.remove(h); 468 } 469 } 470 471 @Override handleMessage(Message msg)472 public void handleMessage (Message msg) { 473 synchronized (mLock) { 474 Integer phoneId = getCiIndex(msg); 475 String eventName = eventToString(msg.what); 476 477 if (phoneId < 0 || phoneId >= mCis.length) { 478 Rlog.e(LOG_TAG, "Invalid phoneId : " + phoneId + " received with event " 479 + eventName); 480 return; 481 } 482 483 logWithLocalLog("handleMessage: Received " + eventName + " for phoneId " + phoneId); 484 485 AsyncResult ar = (AsyncResult)msg.obj; 486 switch (msg.what) { 487 case EVENT_ICC_STATUS_CHANGED: 488 if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus"); 489 mCis[phoneId].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, 490 phoneId)); 491 break; 492 case EVENT_RADIO_AVAILABLE: 493 case EVENT_RADIO_ON: 494 if (DBG) { 495 log("Received EVENT_RADIO_AVAILABLE/EVENT_RADIO_ON, calling " 496 + "getIccCardStatus"); 497 } 498 mCis[phoneId].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, 499 phoneId)); 500 // slot status should be the same on all RILs; request it only for phoneId 0 501 if (phoneId == 0) { 502 if (DBG) { 503 log("Received EVENT_RADIO_AVAILABLE/EVENT_RADIO_ON for phoneId 0, " 504 + "calling getIccSlotsStatus"); 505 } 506 mRadioConfig.getSimSlotsStatus(obtainMessage(EVENT_GET_SLOT_STATUS_DONE, 507 phoneId)); 508 } 509 break; 510 case EVENT_GET_ICC_STATUS_DONE: 511 if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE"); 512 onGetIccCardStatusDone(ar, phoneId); 513 break; 514 case EVENT_SLOT_STATUS_CHANGED: 515 case EVENT_GET_SLOT_STATUS_DONE: 516 if (DBG) { 517 log("Received EVENT_SLOT_STATUS_CHANGED or EVENT_GET_SLOT_STATUS_DONE"); 518 } 519 onGetSlotStatusDone(ar); 520 break; 521 case EVENT_RADIO_UNAVAILABLE: 522 if (DBG) log("EVENT_RADIO_UNAVAILABLE, dispose card"); 523 UiccSlot uiccSlot = getUiccSlotForPhone(phoneId); 524 if (uiccSlot != null) { 525 uiccSlot.onRadioStateUnavailable(); 526 } 527 mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, phoneId, null)); 528 break; 529 case EVENT_SIM_REFRESH: 530 if (DBG) log("Received EVENT_SIM_REFRESH"); 531 onSimRefresh(ar, phoneId); 532 break; 533 case EVENT_EID_READY: 534 if (DBG) log("Received EVENT_EID_READY"); 535 onEidReady(ar, phoneId); 536 break; 537 case EVENT_MULTI_SIM_CONFIG_CHANGED: 538 if (DBG) log("Received EVENT_MULTI_SIM_CONFIG_CHANGED"); 539 int activeModemCount = (int) ((AsyncResult) msg.obj).result; 540 onMultiSimConfigChanged(activeModemCount); 541 break; 542 default: 543 Rlog.e(LOG_TAG, " Unknown Event " + msg.what); 544 break; 545 } 546 } 547 } 548 onMultiSimConfigChanged(int newActiveModemCount)549 private void onMultiSimConfigChanged(int newActiveModemCount) { 550 int prevActiveModemCount = mCis.length; 551 mCis = PhoneFactory.getCommandsInterfaces(); 552 553 logWithLocalLog("onMultiSimConfigChanged: prevActiveModemCount " + prevActiveModemCount 554 + ", newActiveModemCount " + newActiveModemCount); 555 556 // Resize array. 557 mPhoneIdToSlotId = copyOf(mPhoneIdToSlotId, newActiveModemCount); 558 559 // Register for new active modem for ss -> ds switch. 560 // For ds -> ss switch, there's no need to unregister as the mCis should unregister 561 // everything itself. 562 for (int i = prevActiveModemCount; i < newActiveModemCount; i++) { 563 mPhoneIdToSlotId[i] = INVALID_SLOT_ID; 564 mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, i); 565 566 /* 567 * To support FDE (deprecated), additional check is needed: 568 * 569 * if (!StorageManager.inCryptKeeperBounce()) { 570 * mCis[i].registerForAvailable(this, EVENT_RADIO_AVAILABLE, i); 571 * } else { 572 * mCis[i].registerForOn(this, EVENT_RADIO_ON, i); 573 * } 574 */ 575 mCis[i].registerForAvailable(this, EVENT_RADIO_AVAILABLE, i); 576 577 mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, i); 578 mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, i); 579 } 580 } 581 getCiIndex(Message msg)582 private Integer getCiIndex(Message msg) { 583 AsyncResult ar; 584 Integer index = new Integer(PhoneConstants.DEFAULT_SLOT_INDEX); 585 586 /* 587 * The events can be come in two ways. By explicitly sending it using 588 * sendMessage, in this case the user object passed is msg.obj and from 589 * the CommandsInterface, in this case the user object is msg.obj.userObj 590 */ 591 if (msg != null) { 592 if (msg.obj != null && msg.obj instanceof Integer) { 593 index = (Integer)msg.obj; 594 } else if(msg.obj != null && msg.obj instanceof AsyncResult) { 595 ar = (AsyncResult)msg.obj; 596 if (ar.userObj != null && ar.userObj instanceof Integer) { 597 index = (Integer)ar.userObj; 598 } 599 } 600 } 601 return index; 602 } 603 eventToString(int event)604 private static String eventToString(int event) { 605 switch (event) { 606 case EVENT_ICC_STATUS_CHANGED: return "ICC_STATUS_CHANGED"; 607 case EVENT_SLOT_STATUS_CHANGED: return "SLOT_STATUS_CHANGED"; 608 case EVENT_GET_ICC_STATUS_DONE: return "GET_ICC_STATUS_DONE"; 609 case EVENT_GET_SLOT_STATUS_DONE: return "GET_SLOT_STATUS_DONE"; 610 case EVENT_RADIO_ON: return "RADIO_ON"; 611 case EVENT_RADIO_AVAILABLE: return "RADIO_AVAILABLE"; 612 case EVENT_RADIO_UNAVAILABLE: return "RADIO_UNAVAILABLE"; 613 case EVENT_SIM_REFRESH: return "SIM_REFRESH"; 614 case EVENT_EID_READY: return "EID_READY"; 615 case EVENT_MULTI_SIM_CONFIG_CHANGED: return "MULTI_SIM_CONFIG_CHANGED"; 616 default: return "UNKNOWN(" + event + ")"; 617 } 618 } 619 620 // Easy to use API 621 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getUiccCardApplication(int phoneId, int family)622 public UiccCardApplication getUiccCardApplication(int phoneId, int family) { 623 synchronized (mLock) { 624 UiccCard uiccCard = getUiccCardForPhone(phoneId); 625 if (uiccCard != null) { 626 return uiccCard.getApplication(family); 627 } 628 return null; 629 } 630 } 631 632 /** 633 * Convert IccCardConstants.State enum values to corresponding IccCardConstants String 634 * constants 635 * @param state IccCardConstants.State enum value 636 * @return IccCardConstants String constant representing ICC state 637 */ getIccStateIntentString(IccCardConstants.State state)638 public static String getIccStateIntentString(IccCardConstants.State state) { 639 switch (state) { 640 case ABSENT: return IccCardConstants.INTENT_VALUE_ICC_ABSENT; 641 case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 642 case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 643 case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 644 case READY: return IccCardConstants.INTENT_VALUE_ICC_READY; 645 case NOT_READY: return IccCardConstants.INTENT_VALUE_ICC_NOT_READY; 646 case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 647 case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR; 648 case CARD_RESTRICTED: return IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED; 649 case LOADED: return IccCardConstants.INTENT_VALUE_ICC_LOADED; 650 default: return IccCardConstants.INTENT_VALUE_ICC_UNKNOWN; 651 } 652 } 653 updateInternalIccStateForInactiveSlot( Context context, int prevActivePhoneId, String iccId)654 static void updateInternalIccStateForInactiveSlot( 655 Context context, int prevActivePhoneId, String iccId) { 656 if (SubscriptionManager.isValidPhoneId(prevActivePhoneId)) { 657 // Mark SIM state as ABSENT on previously phoneId. 658 TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( 659 Context.TELEPHONY_SERVICE); 660 telephonyManager.setSimStateForPhone(prevActivePhoneId, 661 IccCardConstants.State.ABSENT.toString()); 662 } 663 664 SubscriptionInfoUpdater subInfoUpdator = PhoneFactory.getSubscriptionInfoUpdater(); 665 if (subInfoUpdator != null) { 666 subInfoUpdator.updateInternalIccStateForInactiveSlot(prevActivePhoneId, iccId); 667 } else { 668 Rlog.e(LOG_TAG, "subInfoUpdate is null."); 669 } 670 } 671 updateInternalIccState(Context context, IccCardConstants.State state, String reason, int phoneId)672 static void updateInternalIccState(Context context, IccCardConstants.State state, String reason, 673 int phoneId) { 674 TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService( 675 Context.TELEPHONY_SERVICE); 676 telephonyManager.setSimStateForPhone(phoneId, state.toString()); 677 678 SubscriptionInfoUpdater subInfoUpdator = PhoneFactory.getSubscriptionInfoUpdater(); 679 if (subInfoUpdator != null) { 680 subInfoUpdator.updateInternalIccState(getIccStateIntentString(state), reason, phoneId); 681 } else { 682 Rlog.e(LOG_TAG, "subInfoUpdate is null."); 683 } 684 } 685 onGetIccCardStatusDone(AsyncResult ar, Integer index)686 private synchronized void onGetIccCardStatusDone(AsyncResult ar, Integer index) { 687 if (ar.exception != null) { 688 Rlog.e(LOG_TAG,"Error getting ICC status. " 689 + "RIL_REQUEST_GET_ICC_STATUS should " 690 + "never return an error", ar.exception); 691 return; 692 } 693 if (!isValidPhoneIndex(index)) { 694 Rlog.e(LOG_TAG,"onGetIccCardStatusDone: invalid index : " + index); 695 return; 696 } 697 if (isShuttingDown()) { 698 // Do not process the SIM/SLOT events during device shutdown, 699 // as it may unnecessarily modify the persistent information 700 // like, SubscriptionManager.UICC_APPLICATIONS_ENABLED. 701 log("onGetIccCardStatusDone: shudown in progress ignore event"); 702 return; 703 } 704 705 IccCardStatus status = (IccCardStatus)ar.result; 706 707 logWithLocalLog("onGetIccCardStatusDone: phoneId " + index + " IccCardStatus: " + status); 708 709 int slotId = status.physicalSlotIndex; 710 if (VDBG) log("onGetIccCardStatusDone: phoneId " + index + " physicalSlotIndex " + slotId); 711 if (slotId == INVALID_SLOT_ID) { 712 slotId = index; 713 } 714 715 if (eidIsNotSupported(status)) { 716 // we will never get EID from the HAL, so set mDefaultEuiccCardId to UNSUPPORTED_CARD_ID 717 if (DBG) log("eid is not supported"); 718 mDefaultEuiccCardId = UNSUPPORTED_CARD_ID; 719 } 720 mPhoneIdToSlotId[index] = slotId; 721 722 if (VDBG) logPhoneIdToSlotIdMapping(); 723 724 if (mUiccSlots[slotId] == null) { 725 if (VDBG) { 726 log("Creating mUiccSlots[" + slotId + "]; mUiccSlots.length = " 727 + mUiccSlots.length); 728 } 729 mUiccSlots[slotId] = new UiccSlot(mContext, true); 730 } 731 732 mUiccSlots[slotId].update(mCis[index], status, index, slotId); 733 734 UiccCard card = mUiccSlots[slotId].getUiccCard(); 735 if (card == null) { 736 if (DBG) log("mUiccSlots[" + slotId + "] has no card. Notifying IccChangedRegistrants"); 737 mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 738 return; 739 } 740 741 String cardString = null; 742 boolean isEuicc = mUiccSlots[slotId].isEuicc(); 743 if (isEuicc) { 744 cardString = ((EuiccCard) card).getEid(); 745 } else { 746 cardString = card.getIccId(); 747 } 748 749 if (cardString != null) { 750 addCardId(cardString); 751 } 752 753 // EID is unpopulated if Radio HAL < 1.4 (RadioConfig < 1.2) 754 // If so, just register for EID loaded and skip this stuff 755 if (isEuicc && mDefaultEuiccCardId != UNSUPPORTED_CARD_ID) { 756 if (cardString == null) { 757 ((EuiccCard) card).registerForEidReady(this, EVENT_EID_READY, index); 758 } else { 759 // If we know the EID from IccCardStatus, just use it to set mDefaultEuiccCardId if 760 // it's not already set. 761 // This is needed in cases where slot status doesn't include EID, and we don't want 762 // to register for EID from APDU because we already know cardString from a previous 763 // APDU 764 if (mDefaultEuiccCardId == UNINITIALIZED_CARD_ID 765 || mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { 766 mDefaultEuiccCardId = convertToPublicCardId(cardString); 767 logWithLocalLog("IccCardStatus eid=" + cardString + " slot=" + slotId 768 + " mDefaultEuiccCardId=" + mDefaultEuiccCardId); 769 } 770 } 771 } 772 773 if (DBG) log("Notifying IccChangedRegistrants"); 774 mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 775 } 776 777 /** 778 * Returns true if EID is not supproted. 779 */ eidIsNotSupported(IccCardStatus status)780 private boolean eidIsNotSupported(IccCardStatus status) { 781 // if card status does not contain slot ID, we know we are on HAL < 1.2, so EID will never 782 // be available 783 return status.physicalSlotIndex == INVALID_SLOT_ID; 784 } 785 786 /** 787 * Add a cardString to mCardStrings. If this is an ICCID, trailing Fs will be automatically 788 * stripped. 789 */ addCardId(String cardString)790 private void addCardId(String cardString) { 791 if (TextUtils.isEmpty(cardString)) { 792 return; 793 } 794 if (cardString.length() < EID_LENGTH) { 795 cardString = IccUtils.stripTrailingFs(cardString); 796 } 797 if (!mCardStrings.contains(cardString)) { 798 mCardStrings.add(cardString); 799 saveCardStrings(); 800 } 801 } 802 803 /** 804 * Converts an integer cardId (public card ID) to a card string. 805 * @param cardId to convert 806 * @return cardString, or null if the cardId is not valid 807 */ convertToCardString(int cardId)808 public String convertToCardString(int cardId) { 809 if (cardId < 0 || cardId >= mCardStrings.size()) { 810 log("convertToCardString: cardId " + cardId + " is not valid"); 811 return null; 812 } 813 return mCardStrings.get(cardId); 814 } 815 816 /** 817 * Converts the card string (the ICCID/EID, formerly named card ID) to the public int cardId. 818 * If the given cardString is an ICCID, trailing Fs will be automatically stripped before trying 819 * to match to a card ID. 820 * 821 * @return the matching cardId, or UNINITIALIZED_CARD_ID if the card string does not map to a 822 * currently loaded cardId, or UNSUPPORTED_CARD_ID if the device does not support card IDs 823 */ convertToPublicCardId(String cardString)824 public int convertToPublicCardId(String cardString) { 825 if (mDefaultEuiccCardId == UNSUPPORTED_CARD_ID) { 826 // even if cardString is not an EID, if EID is not supported (e.g. HAL < 1.2) we can't 827 // guarentee a working card ID implementation, so return UNSUPPORTED_CARD_ID 828 return UNSUPPORTED_CARD_ID; 829 } 830 if (TextUtils.isEmpty(cardString)) { 831 return UNINITIALIZED_CARD_ID; 832 } 833 834 if (cardString.length() < EID_LENGTH) { 835 cardString = IccUtils.stripTrailingFs(cardString); 836 } 837 int id = mCardStrings.indexOf(cardString); 838 if (id == -1) { 839 return UNINITIALIZED_CARD_ID; 840 } else { 841 return id; 842 } 843 } 844 845 /** 846 * Returns the UiccCardInfo of all currently inserted UICCs and embedded eUICCs. 847 */ getAllUiccCardInfos()848 public ArrayList<UiccCardInfo> getAllUiccCardInfos() { 849 ArrayList<UiccCardInfo> infos = new ArrayList<>(); 850 for (int slotIndex = 0; slotIndex < mUiccSlots.length; slotIndex++) { 851 final UiccSlot slot = mUiccSlots[slotIndex]; 852 if (slot == null) continue; 853 boolean isEuicc = slot.isEuicc(); 854 String eid = null; 855 UiccCard card = slot.getUiccCard(); 856 String iccid = null; 857 int cardId = UNINITIALIZED_CARD_ID; 858 boolean isRemovable = slot.isRemovable(); 859 860 // first we try to populate UiccCardInfo using the UiccCard, but if it doesn't exist 861 // (e.g. the slot is for an inactive eUICC) then we try using the UiccSlot. 862 if (card != null) { 863 iccid = card.getIccId(); 864 if (isEuicc) { 865 eid = ((EuiccCard) card).getEid(); 866 cardId = convertToPublicCardId(eid); 867 } else { 868 // leave eid null if the UICC is not embedded 869 cardId = convertToPublicCardId(iccid); 870 } 871 } else { 872 iccid = slot.getIccId(); 873 // Fill in the fields we can 874 if (!isEuicc && !TextUtils.isEmpty(iccid)) { 875 cardId = convertToPublicCardId(iccid); 876 } 877 } 878 UiccCardInfo info = new UiccCardInfo(isEuicc, cardId, eid, 879 IccUtils.stripTrailingFs(iccid), slotIndex, isRemovable); 880 infos.add(info); 881 } 882 return infos; 883 } 884 885 /** 886 * Get the card ID of the default eUICC. 887 */ getCardIdForDefaultEuicc()888 public int getCardIdForDefaultEuicc() { 889 if (mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { 890 return UNSUPPORTED_CARD_ID; 891 } 892 return mDefaultEuiccCardId; 893 } 894 895 /** Get the {@link PinStorage}. */ getPinStorage()896 public PinStorage getPinStorage() { 897 return mPinStorage; 898 } 899 loadCardStrings()900 private ArrayList<String> loadCardStrings() { 901 String cardStrings = 902 PreferenceManager.getDefaultSharedPreferences(mContext).getString(CARD_STRINGS, ""); 903 if (TextUtils.isEmpty(cardStrings)) { 904 // just return an empty list, since String.split would return the list { "" } 905 return new ArrayList<String>(); 906 } 907 return new ArrayList<String>(Arrays.asList(cardStrings.split(","))); 908 } 909 saveCardStrings()910 private void saveCardStrings() { 911 SharedPreferences.Editor editor = 912 PreferenceManager.getDefaultSharedPreferences(mContext).edit(); 913 editor.putString(CARD_STRINGS, TextUtils.join(",", mCardStrings)); 914 editor.commit(); 915 } 916 onGetSlotStatusDone(AsyncResult ar)917 private synchronized void onGetSlotStatusDone(AsyncResult ar) { 918 if (!mIsSlotStatusSupported) { 919 if (VDBG) log("onGetSlotStatusDone: ignoring since mIsSlotStatusSupported is false"); 920 return; 921 } 922 Throwable e = ar.exception; 923 if (e != null) { 924 if (!(e instanceof CommandException) || ((CommandException) e).getCommandError() 925 != CommandException.Error.REQUEST_NOT_SUPPORTED) { 926 // this is not expected; there should be no exception other than 927 // REQUEST_NOT_SUPPORTED 928 logeWithLocalLog("Unexpected error getting slot status: " + ar.exception); 929 } else { 930 // REQUEST_NOT_SUPPORTED 931 logWithLocalLog("onGetSlotStatusDone: request not supported; marking " 932 + "mIsSlotStatusSupported to false"); 933 mIsSlotStatusSupported = false; 934 } 935 return; 936 } 937 if (isShuttingDown()) { 938 // Do not process the SIM/SLOT events during device shutdown, 939 // as it may unnecessarily modify the persistent information 940 // like, SubscriptionManager.UICC_APPLICATIONS_ENABLED. 941 log("onGetSlotStatusDone: shudown in progress ignore event"); 942 return; 943 } 944 945 ArrayList<IccSlotStatus> status = (ArrayList<IccSlotStatus>) ar.result; 946 947 if (!slotStatusChanged(status)) { 948 log("onGetSlotStatusDone: No change in slot status"); 949 return; 950 } 951 logWithLocalLog("onGetSlotStatusDone: " + status); 952 953 sLastSlotStatus = status; 954 955 int numActiveSlots = 0; 956 boolean isDefaultEuiccCardIdSet = false; 957 boolean anyEuiccIsActive = false; 958 mHasActiveBuiltInEuicc = false; 959 960 int numSlots = status.size(); 961 if (mUiccSlots.length < numSlots) { 962 logeWithLocalLog("The number of the physical slots reported " + numSlots 963 + " is greater than the expectation " + mUiccSlots.length); 964 numSlots = mUiccSlots.length; 965 } 966 967 for (int i = 0; i < numSlots; i++) { 968 IccSlotStatus iss = status.get(i); 969 boolean isActive = (iss.slotState == IccSlotStatus.SlotState.SLOTSTATE_ACTIVE); 970 if (isActive) { 971 numActiveSlots++; 972 973 // Correctness check: logicalSlotIndex should be valid for an active slot 974 if (!isValidPhoneIndex(iss.logicalSlotIndex)) { 975 Rlog.e(LOG_TAG, "Skipping slot " + i + " as phone " + iss.logicalSlotIndex 976 + " is not available to communicate with this slot"); 977 } else { 978 mPhoneIdToSlotId[iss.logicalSlotIndex] = i; 979 } 980 } 981 982 if (mUiccSlots[i] == null) { 983 if (VDBG) { 984 log("Creating mUiccSlot[" + i + "]; mUiccSlots.length = " + mUiccSlots.length); 985 } 986 mUiccSlots[i] = new UiccSlot(mContext, isActive); 987 } 988 989 if (!isValidPhoneIndex(iss.logicalSlotIndex)) { 990 mUiccSlots[i].update(null, iss, i /* slotIndex */); 991 } else { 992 mUiccSlots[i].update(isActive ? mCis[iss.logicalSlotIndex] : null, iss, 993 i /* slotIndex */); 994 } 995 996 if (mUiccSlots[i].isEuicc()) { 997 if (isActive) { 998 anyEuiccIsActive = true; 999 1000 if (isBuiltInEuiccSlot(i)) { 1001 mHasActiveBuiltInEuicc = true; 1002 } 1003 } 1004 String eid = iss.eid; 1005 if (TextUtils.isEmpty(eid)) { 1006 // iss.eid is not populated on HAL<1.4 1007 continue; 1008 } 1009 1010 addCardId(eid); 1011 1012 // whenever slot status is received, set default card to the non-removable eUICC 1013 // with the lowest slot index. 1014 if (!mUiccSlots[i].isRemovable() && !isDefaultEuiccCardIdSet) { 1015 isDefaultEuiccCardIdSet = true; 1016 mDefaultEuiccCardId = convertToPublicCardId(eid); 1017 logWithLocalLog("Using eid=" + eid + " in slot=" + i 1018 + " to set mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1019 } 1020 } 1021 } 1022 1023 if (!mHasActiveBuiltInEuicc && !isDefaultEuiccCardIdSet) { 1024 // if there are no active built-in eUICCs, then consider setting a removable eUICC to 1025 // the default. 1026 // Note that on HAL<1.2, it's possible that a built-in eUICC exists, but does not 1027 // correspond to any slot in mUiccSlots. This logic is still safe in that case because 1028 // SlotStatus is only for HAL >= 1.2 1029 for (int i = 0; i < numSlots; i++) { 1030 if (mUiccSlots[i].isEuicc()) { 1031 String eid = status.get(i).eid; 1032 if (!TextUtils.isEmpty(eid)) { 1033 isDefaultEuiccCardIdSet = true; 1034 mDefaultEuiccCardId = convertToPublicCardId(eid); 1035 logWithLocalLog("Using eid=" + eid + " from removable eUICC in slot=" 1036 + i + " to set mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1037 break; 1038 } 1039 } 1040 } 1041 } 1042 1043 if (mHasBuiltInEuicc && !anyEuiccIsActive && !isDefaultEuiccCardIdSet) { 1044 logWithLocalLog( 1045 "onGetSlotStatusDone: mDefaultEuiccCardId=TEMPORARILY_UNSUPPORTED_CARD_ID"); 1046 isDefaultEuiccCardIdSet = true; 1047 mDefaultEuiccCardId = TEMPORARILY_UNSUPPORTED_CARD_ID; 1048 } 1049 1050 1051 if (!isDefaultEuiccCardIdSet) { 1052 if (mDefaultEuiccCardId >= 0) { 1053 // if mDefaultEuiccCardId has already been set to an actual eUICC, 1054 // don't overwrite mDefaultEuiccCardId unless that eUICC is no longer inserted 1055 boolean defaultEuiccCardIdIsStillInserted = false; 1056 String cardString = mCardStrings.get(mDefaultEuiccCardId); 1057 for (UiccSlot slot : mUiccSlots) { 1058 if (slot.getUiccCard() == null) { 1059 continue; 1060 } 1061 if (cardString.equals( 1062 IccUtils.stripTrailingFs(slot.getUiccCard().getCardId()))) { 1063 defaultEuiccCardIdIsStillInserted = true; 1064 } 1065 } 1066 if (!defaultEuiccCardIdIsStillInserted) { 1067 logWithLocalLog("onGetSlotStatusDone: mDefaultEuiccCardId=" 1068 + mDefaultEuiccCardId 1069 + " is no longer inserted. Setting mDefaultEuiccCardId=UNINITIALIZED"); 1070 mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; 1071 } 1072 } else { 1073 // no known eUICCs at all (it's possible that an eUICC is inserted and we just don't 1074 // know it's EID) 1075 logWithLocalLog("onGetSlotStatusDone: mDefaultEuiccCardId=UNINITIALIZED"); 1076 mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; 1077 } 1078 } 1079 1080 if (VDBG) logPhoneIdToSlotIdMapping(); 1081 1082 // Correctness check: number of active slots should be valid 1083 if (numActiveSlots != mPhoneIdToSlotId.length) { 1084 Rlog.e(LOG_TAG, "Number of active slots " + numActiveSlots 1085 + " does not match the number of Phones" + mPhoneIdToSlotId.length); 1086 } 1087 1088 // Correctness check: slotIds should be unique in mPhoneIdToSlotId 1089 Set<Integer> slotIds = new HashSet<>(); 1090 for (int slotId : mPhoneIdToSlotId) { 1091 if (slotIds.contains(slotId)) { 1092 throw new RuntimeException("slotId " + slotId + " mapped to multiple phoneIds"); 1093 } 1094 slotIds.add(slotId); 1095 } 1096 1097 // broadcast slot status changed 1098 final BroadcastOptions options = BroadcastOptions.makeBasic(); 1099 options.setBackgroundActivityStartsAllowed(true); 1100 Intent intent = new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED); 1101 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1102 mContext.sendBroadcast(intent, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1103 options.toBundle()); 1104 } 1105 slotStatusChanged(ArrayList<IccSlotStatus> slotStatusList)1106 private boolean slotStatusChanged(ArrayList<IccSlotStatus> slotStatusList) { 1107 if (sLastSlotStatus == null || sLastSlotStatus.size() != slotStatusList.size()) { 1108 return true; 1109 } 1110 for (IccSlotStatus iccSlotStatus : slotStatusList) { 1111 if (!sLastSlotStatus.contains(iccSlotStatus)) { 1112 return true; 1113 } 1114 } 1115 return false; 1116 } 1117 logPhoneIdToSlotIdMapping()1118 private void logPhoneIdToSlotIdMapping() { 1119 log("mPhoneIdToSlotId mapping:"); 1120 for (int i = 0; i < mPhoneIdToSlotId.length; i++) { 1121 log(" phoneId " + i + " slotId " + mPhoneIdToSlotId[i]); 1122 } 1123 } 1124 onSimRefresh(AsyncResult ar, Integer index)1125 private void onSimRefresh(AsyncResult ar, Integer index) { 1126 if (ar.exception != null) { 1127 Rlog.e(LOG_TAG, "onSimRefresh: Sim REFRESH with exception: " + ar.exception); 1128 return; 1129 } 1130 1131 if (!isValidPhoneIndex(index)) { 1132 Rlog.e(LOG_TAG,"onSimRefresh: invalid index : " + index); 1133 return; 1134 } 1135 1136 IccRefreshResponse resp = (IccRefreshResponse) ar.result; 1137 logWithLocalLog("onSimRefresh: index " + index + ", " + resp); 1138 1139 if (resp == null) { 1140 Rlog.e(LOG_TAG, "onSimRefresh: received without input"); 1141 return; 1142 } 1143 1144 UiccCard uiccCard = getUiccCardForPhone(index); 1145 if (uiccCard == null) { 1146 Rlog.e(LOG_TAG,"onSimRefresh: refresh on null card : " + index); 1147 return; 1148 } 1149 1150 boolean changed = false; 1151 switch(resp.refreshResult) { 1152 // Reset the required apps when we know about the refresh so that 1153 // anyone interested does not get stale state. 1154 case IccRefreshResponse.REFRESH_RESULT_RESET: 1155 changed = uiccCard.resetAppWithAid(resp.aid, true /* reset */); 1156 break; 1157 case IccRefreshResponse.REFRESH_RESULT_INIT: 1158 // don't dispose CatService on SIM REFRESH of type INIT 1159 changed = uiccCard.resetAppWithAid(resp.aid, false /* initialize */); 1160 break; 1161 default: 1162 return; 1163 } 1164 1165 if (changed && resp.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET) { 1166 // If there is any change on RESET, reset carrier config as well. From carrier config 1167 // perspective, this is treated the same as sim state unknown 1168 CarrierConfigManager configManager = (CarrierConfigManager) 1169 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1170 configManager.updateConfigForPhoneId(index, IccCardConstants.INTENT_VALUE_ICC_UNKNOWN); 1171 } 1172 1173 // The card status could have changed. Get the latest state. 1174 mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index)); 1175 } 1176 1177 // for HAL 1.2-1.3 we register for EID ready, set mCardStrings and mDefaultEuiccCardId here. 1178 // Note that if there are multiple eUICCs on HAL 1.2-1.3, the default eUICC is the one whose EID 1179 // is first loaded onEidReady(AsyncResult ar, Integer index)1180 private void onEidReady(AsyncResult ar, Integer index) { 1181 if (ar.exception != null) { 1182 Rlog.e(LOG_TAG, "onEidReady: exception: " + ar.exception); 1183 return; 1184 } 1185 1186 if (!isValidPhoneIndex(index)) { 1187 Rlog.e(LOG_TAG, "onEidReady: invalid index: " + index); 1188 return; 1189 } 1190 int slotId = mPhoneIdToSlotId[index]; 1191 EuiccCard card = (EuiccCard) mUiccSlots[slotId].getUiccCard(); 1192 if (card == null) { 1193 Rlog.e(LOG_TAG, "onEidReady: UiccCard in slot " + slotId + " is null"); 1194 return; 1195 } 1196 1197 // set mCardStrings and the defaultEuiccCardId using the now available EID 1198 String eid = card.getEid(); 1199 addCardId(eid); 1200 if (mDefaultEuiccCardId == UNINITIALIZED_CARD_ID 1201 || mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { 1202 if (!mUiccSlots[slotId].isRemovable()) { 1203 mDefaultEuiccCardId = convertToPublicCardId(eid); 1204 logWithLocalLog("onEidReady: eid=" + eid + " slot=" + slotId 1205 + " mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1206 } else if (!mHasActiveBuiltInEuicc) { 1207 // we only set a removable eUICC to the default if there are no active non-removable 1208 // eUICCs 1209 mDefaultEuiccCardId = convertToPublicCardId(eid); 1210 logWithLocalLog("onEidReady: eid=" + eid + " from removable eUICC in slot=" + slotId 1211 + " mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1212 } 1213 } 1214 card.unregisterForEidReady(this); 1215 } 1216 1217 // Return true if the device has at least one built in eUICC based on the resource overlay hasBuiltInEuicc()1218 private boolean hasBuiltInEuicc() { 1219 return mEuiccSlots != null && mEuiccSlots.length > 0; 1220 } 1221 isBuiltInEuiccSlot(int slotIndex)1222 private boolean isBuiltInEuiccSlot(int slotIndex) { 1223 if (!mHasBuiltInEuicc) { 1224 return false; 1225 } 1226 for (int slot : mEuiccSlots) { 1227 if (slot == slotIndex) { 1228 return true; 1229 } 1230 } 1231 return false; 1232 } 1233 1234 /** 1235 * static method to return whether CDMA is supported on the device 1236 * @param context object representative of the application that is calling this method 1237 * @return true if CDMA is supported by the device 1238 */ isCdmaSupported(Context context)1239 public static boolean isCdmaSupported(Context context) { 1240 PackageManager packageManager = context.getPackageManager(); 1241 boolean isCdmaSupported = 1242 packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA); 1243 return isCdmaSupported; 1244 } 1245 isValidPhoneIndex(int index)1246 private boolean isValidPhoneIndex(int index) { 1247 return (index >= 0 && index < TelephonyManager.getDefault().getPhoneCount()); 1248 } 1249 isValidSlotIndex(int index)1250 private boolean isValidSlotIndex(int index) { 1251 return (index >= 0 && index < mUiccSlots.length); 1252 } 1253 isShuttingDown()1254 private boolean isShuttingDown() { 1255 for (int i = 0; i < TelephonyManager.getDefault().getActiveModemCount(); i++) { 1256 if (PhoneFactory.getPhone(i) != null && 1257 PhoneFactory.getPhone(i).isShuttingDown()) { 1258 return true; 1259 } 1260 } 1261 return false; 1262 } 1263 1264 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) log(String string)1265 private void log(String string) { 1266 Rlog.d(LOG_TAG, string); 1267 } 1268 logWithLocalLog(String string)1269 private void logWithLocalLog(String string) { 1270 Rlog.d(LOG_TAG, string); 1271 sLocalLog.log("UiccController: " + string); 1272 } 1273 logeWithLocalLog(String string)1274 private void logeWithLocalLog(String string) { 1275 Rlog.e(LOG_TAG, string); 1276 sLocalLog.log("UiccController: " + string); 1277 } 1278 1279 /** The supplied log should also indicate the caller to avoid ambiguity. */ addLocalLog(String data)1280 public static void addLocalLog(String data) { 1281 sLocalLog.log(data); 1282 } 1283 dump(FileDescriptor fd, PrintWriter pw, String[] args)1284 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1285 pw.println("UiccController: " + this); 1286 pw.println(" mContext=" + mContext); 1287 pw.println(" mInstance=" + mInstance); 1288 pw.println(" mIccChangedRegistrants: size=" + mIccChangedRegistrants.size()); 1289 for (int i = 0; i < mIccChangedRegistrants.size(); i++) { 1290 pw.println(" mIccChangedRegistrants[" + i + "]=" 1291 + ((Registrant)mIccChangedRegistrants.get(i)).getHandler()); 1292 } 1293 pw.println(); 1294 pw.flush(); 1295 pw.println(" mIsCdmaSupported=" + isCdmaSupported(mContext)); 1296 pw.println(" mHasBuiltInEuicc=" + mHasBuiltInEuicc); 1297 pw.println(" mHasActiveBuiltInEuicc=" + mHasActiveBuiltInEuicc); 1298 pw.println(" mCardStrings=" + mCardStrings); 1299 pw.println(" mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1300 pw.println(" mPhoneIdToSlotId=" + Arrays.toString(mPhoneIdToSlotId)); 1301 pw.println(" mUiccSlots: size=" + mUiccSlots.length); 1302 for (int i = 0; i < mUiccSlots.length; i++) { 1303 if (mUiccSlots[i] == null) { 1304 pw.println(" mUiccSlots[" + i + "]=null"); 1305 } else { 1306 pw.println(" mUiccSlots[" + i + "]=" + mUiccSlots[i]); 1307 mUiccSlots[i].dump(fd, pw, args); 1308 } 1309 } 1310 pw.println(" sLocalLog= "); 1311 sLocalLog.dump(fd, pw, args); 1312 mPinStorage.dump(fd, pw, args); 1313 } 1314 } 1315