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 (!mCis[0].supportsEid()) { 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 * Add a cardString to mCardStrings. If this is an ICCID, trailing Fs will be automatically 779 * stripped. 780 */ addCardId(String cardString)781 private void addCardId(String cardString) { 782 if (TextUtils.isEmpty(cardString)) { 783 return; 784 } 785 if (cardString.length() < EID_LENGTH) { 786 cardString = IccUtils.stripTrailingFs(cardString); 787 } 788 if (!mCardStrings.contains(cardString)) { 789 mCardStrings.add(cardString); 790 saveCardStrings(); 791 } 792 } 793 794 /** 795 * Converts an integer cardId (public card ID) to a card string. 796 * @param cardId to convert 797 * @return cardString, or null if the cardId is not valid 798 */ convertToCardString(int cardId)799 public String convertToCardString(int cardId) { 800 if (cardId < 0 || cardId >= mCardStrings.size()) { 801 log("convertToCardString: cardId " + cardId + " is not valid"); 802 return null; 803 } 804 return mCardStrings.get(cardId); 805 } 806 807 /** 808 * Converts the card string (the ICCID/EID, formerly named card ID) to the public int cardId. 809 * If the given cardString is an ICCID, trailing Fs will be automatically stripped before trying 810 * to match to a card ID. 811 * 812 * @return the matching cardId, or UNINITIALIZED_CARD_ID if the card string does not map to a 813 * currently loaded cardId, or UNSUPPORTED_CARD_ID if the device does not support card IDs 814 */ convertToPublicCardId(String cardString)815 public int convertToPublicCardId(String cardString) { 816 if (mDefaultEuiccCardId == UNSUPPORTED_CARD_ID) { 817 // even if cardString is not an EID, if EID is not supported (e.g. HAL < 1.2) we can't 818 // guarentee a working card ID implementation, so return UNSUPPORTED_CARD_ID 819 return UNSUPPORTED_CARD_ID; 820 } 821 if (TextUtils.isEmpty(cardString)) { 822 return UNINITIALIZED_CARD_ID; 823 } 824 825 if (cardString.length() < EID_LENGTH) { 826 cardString = IccUtils.stripTrailingFs(cardString); 827 } 828 int id = mCardStrings.indexOf(cardString); 829 if (id == -1) { 830 return UNINITIALIZED_CARD_ID; 831 } else { 832 return id; 833 } 834 } 835 836 /** 837 * Returns the UiccCardInfo of all currently inserted UICCs and embedded eUICCs. 838 */ getAllUiccCardInfos()839 public ArrayList<UiccCardInfo> getAllUiccCardInfos() { 840 ArrayList<UiccCardInfo> infos = new ArrayList<>(); 841 for (int slotIndex = 0; slotIndex < mUiccSlots.length; slotIndex++) { 842 final UiccSlot slot = mUiccSlots[slotIndex]; 843 if (slot == null) continue; 844 boolean isEuicc = slot.isEuicc(); 845 String eid = null; 846 UiccCard card = slot.getUiccCard(); 847 String iccid = null; 848 int cardId = UNINITIALIZED_CARD_ID; 849 boolean isRemovable = slot.isRemovable(); 850 851 // first we try to populate UiccCardInfo using the UiccCard, but if it doesn't exist 852 // (e.g. the slot is for an inactive eUICC) then we try using the UiccSlot. 853 if (card != null) { 854 iccid = card.getIccId(); 855 if (isEuicc) { 856 eid = ((EuiccCard) card).getEid(); 857 cardId = convertToPublicCardId(eid); 858 } else { 859 // leave eid null if the UICC is not embedded 860 cardId = convertToPublicCardId(iccid); 861 } 862 } else { 863 iccid = slot.getIccId(); 864 // Fill in the fields we can 865 if (!isEuicc && !TextUtils.isEmpty(iccid)) { 866 cardId = convertToPublicCardId(iccid); 867 } 868 } 869 UiccCardInfo info = new UiccCardInfo(isEuicc, cardId, eid, 870 IccUtils.stripTrailingFs(iccid), slotIndex, isRemovable); 871 infos.add(info); 872 } 873 return infos; 874 } 875 876 /** 877 * Get the card ID of the default eUICC. 878 */ getCardIdForDefaultEuicc()879 public int getCardIdForDefaultEuicc() { 880 if (mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { 881 return UNSUPPORTED_CARD_ID; 882 } 883 return mDefaultEuiccCardId; 884 } 885 886 /** Get the {@link PinStorage}. */ getPinStorage()887 public PinStorage getPinStorage() { 888 return mPinStorage; 889 } 890 loadCardStrings()891 private ArrayList<String> loadCardStrings() { 892 String cardStrings = 893 PreferenceManager.getDefaultSharedPreferences(mContext).getString(CARD_STRINGS, ""); 894 if (TextUtils.isEmpty(cardStrings)) { 895 // just return an empty list, since String.split would return the list { "" } 896 return new ArrayList<String>(); 897 } 898 return new ArrayList<String>(Arrays.asList(cardStrings.split(","))); 899 } 900 saveCardStrings()901 private void saveCardStrings() { 902 SharedPreferences.Editor editor = 903 PreferenceManager.getDefaultSharedPreferences(mContext).edit(); 904 editor.putString(CARD_STRINGS, TextUtils.join(",", mCardStrings)); 905 editor.commit(); 906 } 907 onGetSlotStatusDone(AsyncResult ar)908 private synchronized void onGetSlotStatusDone(AsyncResult ar) { 909 if (!mIsSlotStatusSupported) { 910 if (VDBG) log("onGetSlotStatusDone: ignoring since mIsSlotStatusSupported is false"); 911 return; 912 } 913 Throwable e = ar.exception; 914 if (e != null) { 915 if (!(e instanceof CommandException) || ((CommandException) e).getCommandError() 916 != CommandException.Error.REQUEST_NOT_SUPPORTED) { 917 // this is not expected; there should be no exception other than 918 // REQUEST_NOT_SUPPORTED 919 logeWithLocalLog("Unexpected error getting slot status: " + ar.exception); 920 } else { 921 // REQUEST_NOT_SUPPORTED 922 logWithLocalLog("onGetSlotStatusDone: request not supported; marking " 923 + "mIsSlotStatusSupported to false"); 924 mIsSlotStatusSupported = false; 925 } 926 return; 927 } 928 if (isShuttingDown()) { 929 // Do not process the SIM/SLOT events during device shutdown, 930 // as it may unnecessarily modify the persistent information 931 // like, SubscriptionManager.UICC_APPLICATIONS_ENABLED. 932 log("onGetSlotStatusDone: shudown in progress ignore event"); 933 return; 934 } 935 936 ArrayList<IccSlotStatus> status = (ArrayList<IccSlotStatus>) ar.result; 937 938 if (!slotStatusChanged(status)) { 939 log("onGetSlotStatusDone: No change in slot status"); 940 return; 941 } 942 logWithLocalLog("onGetSlotStatusDone: " + status); 943 944 sLastSlotStatus = status; 945 946 int numActiveSlots = 0; 947 boolean isDefaultEuiccCardIdSet = false; 948 boolean anyEuiccIsActive = false; 949 mHasActiveBuiltInEuicc = false; 950 951 int numSlots = status.size(); 952 if (mUiccSlots.length < numSlots) { 953 logeWithLocalLog("The number of the physical slots reported " + numSlots 954 + " is greater than the expectation " + mUiccSlots.length); 955 numSlots = mUiccSlots.length; 956 } 957 958 for (int i = 0; i < numSlots; i++) { 959 IccSlotStatus iss = status.get(i); 960 boolean isActive = (iss.slotState == IccSlotStatus.SlotState.SLOTSTATE_ACTIVE); 961 if (isActive) { 962 numActiveSlots++; 963 964 // Correctness check: logicalSlotIndex should be valid for an active slot 965 if (!isValidPhoneIndex(iss.logicalSlotIndex)) { 966 Rlog.e(LOG_TAG, "Skipping slot " + i + " as phone " + iss.logicalSlotIndex 967 + " is not available to communicate with this slot"); 968 } else { 969 mPhoneIdToSlotId[iss.logicalSlotIndex] = i; 970 } 971 } 972 973 if (mUiccSlots[i] == null) { 974 if (VDBG) { 975 log("Creating mUiccSlot[" + i + "]; mUiccSlots.length = " + mUiccSlots.length); 976 } 977 mUiccSlots[i] = new UiccSlot(mContext, isActive); 978 } 979 980 if (!isValidPhoneIndex(iss.logicalSlotIndex)) { 981 mUiccSlots[i].update(null, iss, i /* slotIndex */); 982 } else { 983 mUiccSlots[i].update(isActive ? mCis[iss.logicalSlotIndex] : null, iss, 984 i /* slotIndex */); 985 } 986 987 if (mUiccSlots[i].isEuicc()) { 988 if (isActive) { 989 anyEuiccIsActive = true; 990 991 if (isBuiltInEuiccSlot(i)) { 992 mHasActiveBuiltInEuicc = true; 993 } 994 } 995 String eid = iss.eid; 996 if (TextUtils.isEmpty(eid)) { 997 // iss.eid is not populated on HAL<1.4 998 continue; 999 } 1000 1001 addCardId(eid); 1002 1003 // whenever slot status is received, set default card to the non-removable eUICC 1004 // with the lowest slot index. 1005 if (!mUiccSlots[i].isRemovable() && !isDefaultEuiccCardIdSet) { 1006 isDefaultEuiccCardIdSet = true; 1007 mDefaultEuiccCardId = convertToPublicCardId(eid); 1008 logWithLocalLog("Using eid=" + eid + " in slot=" + i 1009 + " to set mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1010 } 1011 } 1012 } 1013 1014 if (!mHasActiveBuiltInEuicc && !isDefaultEuiccCardIdSet) { 1015 // if there are no active built-in eUICCs, then consider setting a removable eUICC to 1016 // the default. 1017 // Note that on HAL<1.2, it's possible that a built-in eUICC exists, but does not 1018 // correspond to any slot in mUiccSlots. This logic is still safe in that case because 1019 // SlotStatus is only for HAL >= 1.2 1020 for (int i = 0; i < numSlots; i++) { 1021 if (mUiccSlots[i].isEuicc()) { 1022 String eid = status.get(i).eid; 1023 if (!TextUtils.isEmpty(eid)) { 1024 isDefaultEuiccCardIdSet = true; 1025 mDefaultEuiccCardId = convertToPublicCardId(eid); 1026 logWithLocalLog("Using eid=" + eid + " from removable eUICC in slot=" 1027 + i + " to set mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1028 break; 1029 } 1030 } 1031 } 1032 } 1033 1034 if (mHasBuiltInEuicc && !anyEuiccIsActive && !isDefaultEuiccCardIdSet) { 1035 logWithLocalLog( 1036 "onGetSlotStatusDone: mDefaultEuiccCardId=TEMPORARILY_UNSUPPORTED_CARD_ID"); 1037 isDefaultEuiccCardIdSet = true; 1038 mDefaultEuiccCardId = TEMPORARILY_UNSUPPORTED_CARD_ID; 1039 } 1040 1041 1042 if (!isDefaultEuiccCardIdSet) { 1043 if (mDefaultEuiccCardId >= 0) { 1044 // if mDefaultEuiccCardId has already been set to an actual eUICC, 1045 // don't overwrite mDefaultEuiccCardId unless that eUICC is no longer inserted 1046 boolean defaultEuiccCardIdIsStillInserted = false; 1047 String cardString = mCardStrings.get(mDefaultEuiccCardId); 1048 for (UiccSlot slot : mUiccSlots) { 1049 if (slot.getUiccCard() == null) { 1050 continue; 1051 } 1052 if (cardString.equals( 1053 IccUtils.stripTrailingFs(slot.getUiccCard().getCardId()))) { 1054 defaultEuiccCardIdIsStillInserted = true; 1055 } 1056 } 1057 if (!defaultEuiccCardIdIsStillInserted) { 1058 logWithLocalLog("onGetSlotStatusDone: mDefaultEuiccCardId=" 1059 + mDefaultEuiccCardId 1060 + " is no longer inserted. Setting mDefaultEuiccCardId=UNINITIALIZED"); 1061 mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; 1062 } 1063 } else { 1064 // no known eUICCs at all (it's possible that an eUICC is inserted and we just don't 1065 // know it's EID) 1066 logWithLocalLog("onGetSlotStatusDone: mDefaultEuiccCardId=UNINITIALIZED"); 1067 mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; 1068 } 1069 } 1070 1071 if (VDBG) logPhoneIdToSlotIdMapping(); 1072 1073 // Correctness check: number of active slots should be valid 1074 if (numActiveSlots != mPhoneIdToSlotId.length) { 1075 Rlog.e(LOG_TAG, "Number of active slots " + numActiveSlots 1076 + " does not match the number of Phones" + mPhoneIdToSlotId.length); 1077 } 1078 1079 // Correctness check: slotIds should be unique in mPhoneIdToSlotId 1080 Set<Integer> slotIds = new HashSet<>(); 1081 for (int slotId : mPhoneIdToSlotId) { 1082 if (slotIds.contains(slotId)) { 1083 throw new RuntimeException("slotId " + slotId + " mapped to multiple phoneIds"); 1084 } 1085 slotIds.add(slotId); 1086 } 1087 1088 // broadcast slot status changed 1089 final BroadcastOptions options = BroadcastOptions.makeBasic(); 1090 options.setBackgroundActivityStartsAllowed(true); 1091 Intent intent = new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED); 1092 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1093 mContext.sendBroadcast(intent, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1094 options.toBundle()); 1095 } 1096 1097 /** 1098 * Check if slot status has changed from the last received one 1099 */ 1100 @VisibleForTesting slotStatusChanged(ArrayList<IccSlotStatus> slotStatusList)1101 public boolean slotStatusChanged(ArrayList<IccSlotStatus> slotStatusList) { 1102 if (sLastSlotStatus == null || sLastSlotStatus.size() != slotStatusList.size()) { 1103 return true; 1104 } 1105 for (int i = 0; i < slotStatusList.size(); i++) { 1106 if (!sLastSlotStatus.get(i).equals(slotStatusList.get(i))) { 1107 return true; 1108 } 1109 } 1110 return false; 1111 } 1112 logPhoneIdToSlotIdMapping()1113 private void logPhoneIdToSlotIdMapping() { 1114 log("mPhoneIdToSlotId mapping:"); 1115 for (int i = 0; i < mPhoneIdToSlotId.length; i++) { 1116 log(" phoneId " + i + " slotId " + mPhoneIdToSlotId[i]); 1117 } 1118 } 1119 onSimRefresh(AsyncResult ar, Integer index)1120 private void onSimRefresh(AsyncResult ar, Integer index) { 1121 if (ar.exception != null) { 1122 Rlog.e(LOG_TAG, "onSimRefresh: Sim REFRESH with exception: " + ar.exception); 1123 return; 1124 } 1125 1126 if (!isValidPhoneIndex(index)) { 1127 Rlog.e(LOG_TAG,"onSimRefresh: invalid index : " + index); 1128 return; 1129 } 1130 1131 IccRefreshResponse resp = (IccRefreshResponse) ar.result; 1132 logWithLocalLog("onSimRefresh: index " + index + ", " + resp); 1133 1134 if (resp == null) { 1135 Rlog.e(LOG_TAG, "onSimRefresh: received without input"); 1136 return; 1137 } 1138 1139 UiccCard uiccCard = getUiccCardForPhone(index); 1140 if (uiccCard == null) { 1141 Rlog.e(LOG_TAG,"onSimRefresh: refresh on null card : " + index); 1142 return; 1143 } 1144 1145 boolean changed = false; 1146 switch(resp.refreshResult) { 1147 // Reset the required apps when we know about the refresh so that 1148 // anyone interested does not get stale state. 1149 case IccRefreshResponse.REFRESH_RESULT_RESET: 1150 changed = uiccCard.resetAppWithAid(resp.aid, true /* reset */); 1151 break; 1152 case IccRefreshResponse.REFRESH_RESULT_INIT: 1153 // don't dispose CatService on SIM REFRESH of type INIT 1154 changed = uiccCard.resetAppWithAid(resp.aid, false /* initialize */); 1155 break; 1156 default: 1157 return; 1158 } 1159 1160 if (changed && resp.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET) { 1161 // If there is any change on RESET, reset carrier config as well. From carrier config 1162 // perspective, this is treated the same as sim state unknown 1163 CarrierConfigManager configManager = (CarrierConfigManager) 1164 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1165 configManager.updateConfigForPhoneId(index, IccCardConstants.INTENT_VALUE_ICC_UNKNOWN); 1166 } 1167 1168 // The card status could have changed. Get the latest state. 1169 mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index)); 1170 } 1171 1172 // for HAL 1.2-1.3 we register for EID ready, set mCardStrings and mDefaultEuiccCardId here. 1173 // Note that if there are multiple eUICCs on HAL 1.2-1.3, the default eUICC is the one whose EID 1174 // is first loaded onEidReady(AsyncResult ar, Integer index)1175 private void onEidReady(AsyncResult ar, Integer index) { 1176 if (ar.exception != null) { 1177 Rlog.e(LOG_TAG, "onEidReady: exception: " + ar.exception); 1178 return; 1179 } 1180 1181 if (!isValidPhoneIndex(index)) { 1182 Rlog.e(LOG_TAG, "onEidReady: invalid index: " + index); 1183 return; 1184 } 1185 int slotId = mPhoneIdToSlotId[index]; 1186 EuiccCard card = (EuiccCard) mUiccSlots[slotId].getUiccCard(); 1187 if (card == null) { 1188 Rlog.e(LOG_TAG, "onEidReady: UiccCard in slot " + slotId + " is null"); 1189 return; 1190 } 1191 1192 // set mCardStrings and the defaultEuiccCardId using the now available EID 1193 String eid = card.getEid(); 1194 addCardId(eid); 1195 if (mDefaultEuiccCardId == UNINITIALIZED_CARD_ID 1196 || mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { 1197 if (!mUiccSlots[slotId].isRemovable()) { 1198 mDefaultEuiccCardId = convertToPublicCardId(eid); 1199 logWithLocalLog("onEidReady: eid=" + eid + " slot=" + slotId 1200 + " mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1201 } else if (!mHasActiveBuiltInEuicc) { 1202 // we only set a removable eUICC to the default if there are no active non-removable 1203 // eUICCs 1204 mDefaultEuiccCardId = convertToPublicCardId(eid); 1205 logWithLocalLog("onEidReady: eid=" + eid + " from removable eUICC in slot=" + slotId 1206 + " mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1207 } 1208 } 1209 card.unregisterForEidReady(this); 1210 } 1211 1212 // Return true if the device has at least one built in eUICC based on the resource overlay hasBuiltInEuicc()1213 private boolean hasBuiltInEuicc() { 1214 return mEuiccSlots != null && mEuiccSlots.length > 0; 1215 } 1216 isBuiltInEuiccSlot(int slotIndex)1217 private boolean isBuiltInEuiccSlot(int slotIndex) { 1218 if (!mHasBuiltInEuicc) { 1219 return false; 1220 } 1221 for (int slot : mEuiccSlots) { 1222 if (slot == slotIndex) { 1223 return true; 1224 } 1225 } 1226 return false; 1227 } 1228 1229 /** 1230 * static method to return whether CDMA is supported on the device 1231 * @param context object representative of the application that is calling this method 1232 * @return true if CDMA is supported by the device 1233 */ isCdmaSupported(Context context)1234 public static boolean isCdmaSupported(Context context) { 1235 PackageManager packageManager = context.getPackageManager(); 1236 boolean isCdmaSupported = 1237 packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA); 1238 return isCdmaSupported; 1239 } 1240 isValidPhoneIndex(int index)1241 private boolean isValidPhoneIndex(int index) { 1242 return (index >= 0 && index < TelephonyManager.getDefault().getPhoneCount()); 1243 } 1244 isValidSlotIndex(int index)1245 private boolean isValidSlotIndex(int index) { 1246 return (index >= 0 && index < mUiccSlots.length); 1247 } 1248 isShuttingDown()1249 private boolean isShuttingDown() { 1250 for (int i = 0; i < TelephonyManager.getDefault().getActiveModemCount(); i++) { 1251 if (PhoneFactory.getPhone(i) != null && 1252 PhoneFactory.getPhone(i).isShuttingDown()) { 1253 return true; 1254 } 1255 } 1256 return false; 1257 } 1258 1259 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) log(String string)1260 private void log(String string) { 1261 Rlog.d(LOG_TAG, string); 1262 } 1263 logWithLocalLog(String string)1264 private void logWithLocalLog(String string) { 1265 Rlog.d(LOG_TAG, string); 1266 sLocalLog.log("UiccController: " + string); 1267 } 1268 logeWithLocalLog(String string)1269 private void logeWithLocalLog(String string) { 1270 Rlog.e(LOG_TAG, string); 1271 sLocalLog.log("UiccController: " + string); 1272 } 1273 1274 /** The supplied log should also indicate the caller to avoid ambiguity. */ addLocalLog(String data)1275 public static void addLocalLog(String data) { 1276 sLocalLog.log(data); 1277 } 1278 dump(FileDescriptor fd, PrintWriter pw, String[] args)1279 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1280 pw.println("UiccController: " + this); 1281 pw.println(" mContext=" + mContext); 1282 pw.println(" mInstance=" + mInstance); 1283 pw.println(" mIccChangedRegistrants: size=" + mIccChangedRegistrants.size()); 1284 for (int i = 0; i < mIccChangedRegistrants.size(); i++) { 1285 pw.println(" mIccChangedRegistrants[" + i + "]=" 1286 + ((Registrant)mIccChangedRegistrants.get(i)).getHandler()); 1287 } 1288 pw.println(); 1289 pw.flush(); 1290 pw.println(" mIsCdmaSupported=" + isCdmaSupported(mContext)); 1291 pw.println(" mHasBuiltInEuicc=" + mHasBuiltInEuicc); 1292 pw.println(" mHasActiveBuiltInEuicc=" + mHasActiveBuiltInEuicc); 1293 pw.println(" mCardStrings=" + mCardStrings); 1294 pw.println(" mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1295 pw.println(" mPhoneIdToSlotId=" + Arrays.toString(mPhoneIdToSlotId)); 1296 pw.println(" mUiccSlots: size=" + mUiccSlots.length); 1297 for (int i = 0; i < mUiccSlots.length; i++) { 1298 if (mUiccSlots[i] == null) { 1299 pw.println(" mUiccSlots[" + i + "]=null"); 1300 } else { 1301 pw.println(" mUiccSlots[" + i + "]=" + mUiccSlots[i]); 1302 mUiccSlots[i].dump(fd, pw, args); 1303 } 1304 } 1305 pw.println(" sLocalLog= "); 1306 sLocalLog.dump(fd, pw, args); 1307 mPinStorage.dump(fd, pw, args); 1308 } 1309 } 1310