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 com.android.internal.telephony.util.TelephonyUtils.FORCE_VERBOSE_STATE_LOGGING; 23 24 import static java.util.Arrays.copyOf; 25 26 import android.Manifest; 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.app.BroadcastOptions; 30 import android.compat.annotation.UnsupportedAppUsage; 31 import android.content.Context; 32 import android.content.Intent; 33 import android.content.SharedPreferences; 34 import android.content.pm.PackageManager; 35 import android.os.AsyncResult; 36 import android.os.Build; 37 import android.os.Handler; 38 import android.os.Message; 39 import android.os.RegistrantList; 40 import android.os.UserHandle; 41 import android.preference.PreferenceManager; 42 import android.sysprop.TelephonyProperties; 43 import android.telephony.AnomalyReporter; 44 import android.telephony.CarrierConfigManager; 45 import android.telephony.SubscriptionInfo; 46 import android.telephony.SubscriptionManager; 47 import android.telephony.TelephonyManager; 48 import android.telephony.TelephonyManager.SimState; 49 import android.telephony.UiccCardInfo; 50 import android.telephony.UiccPortInfo; 51 import android.telephony.UiccSlotMapping; 52 import android.telephony.data.ApnSetting; 53 import android.text.TextUtils; 54 import android.util.IndentingPrintWriter; 55 import android.util.LocalLog; 56 import android.util.Log; 57 58 import com.android.internal.annotations.VisibleForTesting; 59 import com.android.internal.hidden_from_bootclasspath.com.android.internal.telephony.flags.Flags; 60 import com.android.internal.telephony.CarrierServiceBindHelper; 61 import com.android.internal.telephony.CommandException; 62 import com.android.internal.telephony.CommandsInterface; 63 import com.android.internal.telephony.IccCard; 64 import com.android.internal.telephony.IccCardConstants; 65 import com.android.internal.telephony.IntentBroadcaster; 66 import com.android.internal.telephony.PhoneConfigurationManager; 67 import com.android.internal.telephony.PhoneConstants; 68 import com.android.internal.telephony.PhoneFactory; 69 import com.android.internal.telephony.RadioConfig; 70 import com.android.internal.telephony.TelephonyIntents; 71 import com.android.internal.telephony.flags.FeatureFlags; 72 import com.android.internal.telephony.metrics.TelephonyMetrics; 73 import com.android.internal.telephony.subscription.SubscriptionManagerService; 74 import com.android.internal.telephony.uicc.euicc.EuiccCard; 75 import com.android.internal.telephony.util.ArrayUtils; 76 import com.android.internal.telephony.util.TelephonyUtils; 77 import com.android.telephony.Rlog; 78 79 import java.io.FileDescriptor; 80 import java.io.PrintWriter; 81 import java.util.ArrayList; 82 import java.util.Arrays; 83 import java.util.List; 84 import java.util.Objects; 85 import java.util.UUID; 86 import java.util.stream.Collectors; 87 import java.util.stream.IntStream; 88 89 /** 90 * This class is responsible for keeping all knowledge about 91 * Universal Integrated Circuit Card (UICC), also know as SIM's, 92 * in the system. It is also used as API to get appropriate 93 * applications to pass them to phone and service trackers. 94 * 95 * UiccController is created with the call to make() function. 96 * UiccController is a singleton and make() must only be called once 97 * and throws an exception if called multiple times. 98 * 99 * Once created UiccController registers with RIL for "on" and "unsol_sim_status_changed" 100 * notifications. When such notification arrives UiccController will call 101 * getIccCardStatus (GET_SIM_STATUS). Based on the response of GET_SIM_STATUS 102 * request appropriate tree of uicc objects will be created. 103 * 104 * Following is class diagram for uicc classes: 105 * 106 * UiccController 107 * # 108 * | 109 * UiccSlot[] 110 * # 111 * | 112 * UiccCard 113 * # 114 * | 115 * UiccPort[] 116 * # 117 * | 118 * UiccProfile 119 * # # 120 * | ------------------ 121 * UiccCardApplication CatService 122 * # # 123 * | | 124 * IccRecords IccFileHandler 125 * ^ ^ ^ ^ ^ ^ ^ ^ 126 * SIMRecords---- | | | | | | ---SIMFileHandler 127 * RuimRecords----- | | | | ----RuimFileHandler 128 * IsimUiccRecords--- | | -----UsimFileHandler 129 * | ------CsimFileHandler 130 * ----IsimFileHandler 131 * 132 * Legend: # stands for Composition 133 * ^ stands for Generalization 134 * 135 * See also {@link com.android.internal.telephony.IccCard} 136 */ 137 public class UiccController extends Handler { 138 private static final String LOG_TAG = "UiccController"; 139 private static final boolean DBG = true; 140 private static final boolean VDBG = FORCE_VERBOSE_STATE_LOGGING || 141 Rlog.isLoggable(LOG_TAG, Log.VERBOSE); 142 143 public static final int INVALID_SLOT_ID = -1; 144 145 public static final int APP_FAM_3GPP = 1; 146 public static final int APP_FAM_3GPP2 = 2; 147 public static final int APP_FAM_IMS = 3; 148 149 private static final int EVENT_ICC_STATUS_CHANGED = 1; 150 private static final int EVENT_SLOT_STATUS_CHANGED = 2; 151 private static final int EVENT_GET_ICC_STATUS_DONE = 3; 152 private static final int EVENT_GET_SLOT_STATUS_DONE = 4; 153 private static final int EVENT_RADIO_ON = 5; 154 private static final int EVENT_RADIO_AVAILABLE = 6; 155 private static final int EVENT_RADIO_UNAVAILABLE = 7; 156 private static final int EVENT_SIM_REFRESH = 8; 157 private static final int EVENT_EID_READY = 9; 158 private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 10; 159 // NOTE: any new EVENT_* values must be added to eventToString. 160 161 @NonNull 162 private final TelephonyManager mTelephonyManager; 163 164 // this needs to be here, because on bootup we dont know which index maps to which UiccSlot 165 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 166 private CommandsInterface[] mCis; 167 private UiccSlot[] mUiccSlots; 168 private int[] mPhoneIdToSlotId; 169 private boolean mIsSlotStatusSupported = true; 170 171 // This maps the externally exposed card ID (int) to the internal card ID string (ICCID/EID). 172 // The array index is the card ID (int). 173 // This mapping exists to expose card-based functionality without exposing the EID, which is 174 // considered sensitive information. 175 // mCardStrings is populated using values from the IccSlotStatus and IccCardStatus. For 176 // HAL < 1.2, these do not contain the EID or the ICCID, so mCardStrings will be empty 177 private ArrayList<String> mCardStrings; 178 179 /** 180 * SIM card state. 181 */ 182 @NonNull 183 @SimState 184 private final int[] mSimCardState; 185 186 /** 187 * SIM application state. 188 */ 189 @NonNull 190 @SimState 191 private final int[] mSimApplicationState; 192 193 // This is the card ID of the default eUICC. It starts as UNINITIALIZED_CARD_ID. 194 // When we load the EID (either with slot status or from the EuiccCard), we set it to the eUICC 195 // with the lowest slot index. 196 // If EID is not supported (e.g. on HAL version < 1.2), we set it to UNSUPPORTED_CARD_ID 197 private int mDefaultEuiccCardId; 198 199 // Default Euicc Card ID used when the device is temporarily unable to read the EID (e.g. on HAL 200 // 1.2-1.3 if the eUICC is currently inactive). This value is only used within the 201 // UiccController and should be converted to UNSUPPORTED_CARD_ID when others ask. 202 // (This value is -3 because UNSUPPORTED_CARD_ID and UNINITIALIZED_CARD_ID are -1 and -2) 203 private static final int TEMPORARILY_UNSUPPORTED_CARD_ID = -3; 204 205 // GSM SGP.02 section 2.2.2 states that the EID is always 32 digits long 206 private static final int EID_LENGTH = 32; 207 208 // SharedPreference key for saving the known card strings (ICCIDs and EIDs) ordered by card ID 209 private static final String CARD_STRINGS = "card_strings"; 210 211 // SharedPreference key for saving the flag to set removable eSIM as default eUICC or not. 212 private static final String REMOVABLE_ESIM_AS_DEFAULT = "removable_esim"; 213 214 // Whether the device has an eUICC built in. 215 private boolean mHasBuiltInEuicc = false; 216 217 // Whether the device has a currently active built in eUICC 218 private boolean mHasActiveBuiltInEuicc = false; 219 220 // Use removable eSIM as default eUICC. This flag will be set from phone debug hidden menu 221 private boolean mUseRemovableEsimAsDefault = false; 222 223 // The physical slots which correspond to built-in eUICCs 224 private final int[] mEuiccSlots; 225 226 // SharedPreferences key for saving the default euicc card ID 227 private static final String DEFAULT_CARD = "default_card"; 228 229 @UnsupportedAppUsage 230 private static final Object mLock = new Object(); 231 @UnsupportedAppUsage 232 private static UiccController mInstance; 233 @VisibleForTesting 234 public static ArrayList<IccSlotStatus> sLastSlotStatus; 235 236 @UnsupportedAppUsage 237 @VisibleForTesting 238 public Context mContext; 239 240 protected RegistrantList mIccChangedRegistrants = new RegistrantList(); 241 242 @NonNull 243 private final CarrierServiceBindHelper mCarrierServiceBindHelper; 244 245 private UiccStateChangedLauncher mLauncher; 246 private RadioConfig mRadioConfig; 247 248 /* The storage for the PIN codes. */ 249 private final PinStorage mPinStorage; 250 251 // LocalLog buffer to hold important SIM related events for debugging 252 private static LocalLog sLocalLog = new LocalLog(TelephonyUtils.IS_DEBUGGABLE ? 256 : 64); 253 254 @NonNull 255 private final FeatureFlags mFeatureFlags; 256 257 /** 258 * API to make UiccController singleton if not already created. 259 */ make(@onNull Context c, @NonNull FeatureFlags flags)260 public static UiccController make(@NonNull Context c, @NonNull FeatureFlags flags) { 261 synchronized (mLock) { 262 if (mInstance != null) { 263 throw new RuntimeException("UiccController.make() should only be called once"); 264 } 265 mInstance = new UiccController(c, flags); 266 return mInstance; 267 } 268 } 269 UiccController(@onNull Context c, @NonNull FeatureFlags flags)270 private UiccController(@NonNull Context c, @NonNull FeatureFlags flags) { 271 if (DBG) log("Creating UiccController"); 272 mContext = c; 273 mFeatureFlags = flags; 274 mCis = PhoneFactory.getCommandsInterfaces(); 275 int numPhysicalSlots = c.getResources().getInteger( 276 com.android.internal.R.integer.config_num_physical_slots); 277 numPhysicalSlots = TelephonyProperties.sim_slots_count().orElse(numPhysicalSlots); 278 if (DBG) { 279 logWithLocalLog("config_num_physical_slots = " + numPhysicalSlots); 280 } 281 282 mTelephonyManager = mContext.getSystemService(TelephonyManager.class); 283 284 mUiccSlots = new UiccSlot[numPhysicalSlots]; 285 mPhoneIdToSlotId = new int[mCis.length]; 286 int supportedModemCount = mTelephonyManager.getSupportedModemCount(); 287 mSimCardState = new int[supportedModemCount]; 288 mSimApplicationState = new int[supportedModemCount]; 289 Arrays.fill(mPhoneIdToSlotId, INVALID_SLOT_ID); 290 if (VDBG) logPhoneIdToSlotIdMapping(); 291 mRadioConfig = RadioConfig.getInstance(); 292 mRadioConfig.registerForSimSlotStatusChanged(this, EVENT_SLOT_STATUS_CHANGED, null); 293 for (int i = 0; i < mCis.length; i++) { 294 mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, i); 295 mCis[i].registerForAvailable(this, EVENT_RADIO_AVAILABLE, i); 296 mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, i); 297 mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, i); 298 } 299 300 mLauncher = new UiccStateChangedLauncher(c, this, mFeatureFlags); 301 mCardStrings = loadCardStrings(); 302 mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; 303 304 mCarrierServiceBindHelper = new CarrierServiceBindHelper(mContext); 305 306 mEuiccSlots = mContext.getResources() 307 .getIntArray(com.android.internal.R.array.non_removable_euicc_slots); 308 mHasBuiltInEuicc = hasBuiltInEuicc(); 309 310 PhoneConfigurationManager.registerForMultiSimConfigChange( 311 this, EVENT_MULTI_SIM_CONFIG_CHANGED, null); 312 313 mPinStorage = new PinStorage(mContext); 314 if (!TelephonyUtils.IS_USER) { 315 mUseRemovableEsimAsDefault = PreferenceManager.getDefaultSharedPreferences(mContext) 316 .getBoolean(REMOVABLE_ESIM_AS_DEFAULT, false); 317 } 318 } 319 320 /** 321 * Given the slot index and port index, return the phone ID, or -1 if no phone is associated 322 * with the given slot and port. 323 * @param slotId the slot index to check 324 * @param portIndex unique index referring to a port belonging to the SIM slot 325 * @return the associated phone ID or -1 326 */ getPhoneIdFromSlotPortIndex(int slotId, int portIndex)327 public int getPhoneIdFromSlotPortIndex(int slotId, int portIndex) { 328 UiccSlot slot = getUiccSlot(slotId); 329 return slot == null ? UiccSlot.INVALID_PHONE_ID : slot.getPhoneIdFromPortIndex(portIndex); 330 } 331 332 /** 333 * Return the physical slot id associated with the given phoneId, or INVALID_SLOT_ID. 334 * @param phoneId the phoneId to check 335 */ getSlotIdFromPhoneId(int phoneId)336 public int getSlotIdFromPhoneId(int phoneId) { 337 try { 338 return mPhoneIdToSlotId[phoneId]; 339 } catch (ArrayIndexOutOfBoundsException e) { 340 return INVALID_SLOT_ID; 341 } 342 } 343 344 @UnsupportedAppUsage getInstance()345 public static UiccController getInstance() { 346 if (mInstance == null) { 347 throw new RuntimeException( 348 "UiccController.getInstance can't be called before make()"); 349 } 350 return mInstance; 351 } 352 353 @UnsupportedAppUsage getUiccCard(int phoneId)354 public UiccCard getUiccCard(int phoneId) { 355 synchronized (mLock) { 356 return getUiccCardForPhone(phoneId); 357 } 358 } 359 360 /** 361 * Return the UiccPort associated with the given phoneId or null if no phoneId is associated. 362 * @param phoneId the phoneId to check 363 */ getUiccPort(int phoneId)364 public UiccPort getUiccPort(int phoneId) { 365 synchronized (mLock) { 366 return getUiccPortForPhone(phoneId); 367 } 368 } 369 370 /** 371 * API to get UiccPort corresponding to given physical slot index and port index 372 * @param slotId index of physical slot on the device 373 * @param portIdx index of port on the card 374 * @return UiccPort object corresponding to given physical slot index and port index; 375 * null if port does not exist. 376 */ getUiccPortForSlot(int slotId, int portIdx)377 public UiccPort getUiccPortForSlot(int slotId, int portIdx) { 378 synchronized (mLock) { 379 UiccSlot slot = getUiccSlot(slotId); 380 if (slot != null) { 381 UiccCard uiccCard = slot.getUiccCard(); 382 if (uiccCard != null) { 383 return uiccCard.getUiccPort(portIdx); 384 } 385 } 386 return null; 387 } 388 } 389 390 /** 391 * API to get UiccCard corresponding to given physical slot index 392 * @param slotId index of physical slot on the device 393 * @return UiccCard object corresponting to given physical slot index; null if card is 394 * absent 395 */ getUiccCardForSlot(int slotId)396 public UiccCard getUiccCardForSlot(int slotId) { 397 synchronized (mLock) { 398 UiccSlot uiccSlot = getUiccSlot(slotId); 399 if (uiccSlot != null) { 400 return uiccSlot.getUiccCard(); 401 } 402 return null; 403 } 404 } 405 406 /** 407 * API to get UiccCard corresponding to given phone id 408 * @return UiccCard object corresponding to given phone id; null if there is no card present for 409 * the phone id 410 */ getUiccCardForPhone(int phoneId)411 public UiccCard getUiccCardForPhone(int phoneId) { 412 synchronized (mLock) { 413 if (isValidPhoneIndex(phoneId)) { 414 UiccSlot uiccSlot = getUiccSlotForPhone(phoneId); 415 if (uiccSlot != null) { 416 return uiccSlot.getUiccCard(); 417 } 418 } 419 return null; 420 } 421 } 422 423 /** 424 * API to get UiccPort corresponding to given phone id 425 * @return UiccPort object corresponding to given phone id; null if there is no card present for 426 * the phone id 427 */ 428 @Nullable getUiccPortForPhone(int phoneId)429 public UiccPort getUiccPortForPhone(int phoneId) { 430 synchronized (mLock) { 431 if (isValidPhoneIndex(phoneId)) { 432 UiccSlot uiccSlot = getUiccSlotForPhone(phoneId); 433 if (uiccSlot != null) { 434 UiccCard uiccCard = uiccSlot.getUiccCard(); 435 if (uiccCard != null) { 436 return uiccCard.getUiccPortForPhone(phoneId); 437 } 438 } 439 } 440 return null; 441 } 442 } 443 444 /** 445 * API to get UiccProfile corresponding to given phone id 446 * @return UiccProfile object corresponding to given phone id; null if there is no card/profile 447 * present for the phone id 448 */ getUiccProfileForPhone(int phoneId)449 public UiccProfile getUiccProfileForPhone(int phoneId) { 450 synchronized (mLock) { 451 if (isValidPhoneIndex(phoneId)) { 452 UiccPort uiccPort = getUiccPortForPhone(phoneId); 453 return uiccPort != null ? uiccPort.getUiccProfile() : null; 454 } 455 return null; 456 } 457 } 458 459 /** 460 * API to get all the UICC slots. 461 * @return UiccSlots array. 462 */ getUiccSlots()463 public UiccSlot[] getUiccSlots() { 464 synchronized (mLock) { 465 return mUiccSlots; 466 } 467 } 468 469 /** Map logicalSlot to physicalSlot, portIndex and activate the physicalSlot with portIndex if 470 * it is inactive. */ switchSlots(List<UiccSlotMapping> slotMapping, Message response)471 public void switchSlots(List<UiccSlotMapping> slotMapping, Message response) { 472 logWithLocalLog("switchSlots: " + slotMapping); 473 mRadioConfig.setSimSlotsMapping(slotMapping, response); 474 } 475 476 /** 477 * API to get UiccSlot object for a specific physical slot index on the device 478 * @return UiccSlot object for the given physical slot index 479 */ getUiccSlot(int slotId)480 public UiccSlot getUiccSlot(int slotId) { 481 synchronized (mLock) { 482 if (isValidSlotIndex(slotId)) { 483 return mUiccSlots[slotId]; 484 } 485 return null; 486 } 487 } 488 489 /** 490 * Set UiccSlot object for a specific physical slot index on the device. 491 * 492 * This is only supposed to be used internally and by unit tests. 493 * 494 * @param slotId Slot index 495 * @param slot Slot object 496 */ 497 @VisibleForTesting setUiccSlot(int slotId, @NonNull UiccSlot slot)498 public void setUiccSlot(int slotId, @NonNull UiccSlot slot) { 499 synchronized (mLock) { 500 if (!isValidSlotIndex(slotId)) { 501 throw new ArrayIndexOutOfBoundsException("Invalid slot index: " + slotId); 502 } 503 if (mUiccSlots[slotId] != null) { 504 mUiccSlots[slotId].dispose(); 505 } 506 mUiccSlots[slotId] = Objects.requireNonNull(slot); 507 } 508 } 509 510 /** 511 * API to get UiccSlot object for a given phone id 512 * @return UiccSlot object for the given phone id 513 */ getUiccSlotForPhone(int phoneId)514 public UiccSlot getUiccSlotForPhone(int phoneId) { 515 synchronized (mLock) { 516 if (isValidPhoneIndex(phoneId)) { 517 int slotId = getSlotIdFromPhoneId(phoneId); 518 if (isValidSlotIndex(slotId)) { 519 return mUiccSlots[slotId]; 520 } 521 } 522 return null; 523 } 524 } 525 526 /** 527 * API to get UiccSlot object for a given cardId 528 * @param cardId Identifier for a SIM. This can be an ICCID, or an EID in case of an eSIM. 529 * @return int Index of UiccSlot for the given cardId if one is found, {@link #INVALID_SLOT_ID} 530 * otherwise 531 */ getUiccSlotForCardId(String cardId)532 public int getUiccSlotForCardId(String cardId) { 533 synchronized (mLock) { 534 // first look up based on cardId 535 for (int idx = 0; idx < mUiccSlots.length; idx++) { 536 if (mUiccSlots[idx] != null) { 537 UiccCard uiccCard = mUiccSlots[idx].getUiccCard(); 538 if (uiccCard != null && cardId.equals(uiccCard.getCardId())) { 539 return idx; 540 } 541 } 542 } 543 // if a match is not found, do a lookup based on ICCID 544 for (int idx = 0; idx < mUiccSlots.length; idx++) { 545 UiccSlot slot = mUiccSlots[idx]; 546 if (slot != null) { 547 if (IntStream.of(slot.getPortList()).anyMatch(porIdx -> cardId.equals( 548 slot.getIccId(porIdx)))) { 549 return idx; 550 } 551 } 552 } 553 return INVALID_SLOT_ID; 554 } 555 } 556 557 // Easy to use API 558 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getIccRecords(int phoneId, int family)559 public IccRecords getIccRecords(int phoneId, int family) { 560 synchronized (mLock) { 561 UiccCardApplication app = getUiccCardApplication(phoneId, family); 562 if (app != null) { 563 return app.getIccRecords(); 564 } 565 return null; 566 } 567 } 568 569 // Easy to use API 570 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getIccFileHandler(int phoneId, int family)571 public IccFileHandler getIccFileHandler(int phoneId, int family) { 572 synchronized (mLock) { 573 UiccCardApplication app = getUiccCardApplication(phoneId, family); 574 if (app != null) { 575 return app.getIccFileHandler(); 576 } 577 return null; 578 } 579 } 580 581 582 //Notifies when card status changes 583 @UnsupportedAppUsage registerForIccChanged(Handler h, int what, Object obj)584 public void registerForIccChanged(Handler h, int what, Object obj) { 585 synchronized (mLock) { 586 mIccChangedRegistrants.addUnique(h, what, obj); 587 } 588 //Notify registrant right after registering, so that it will get the latest ICC status, 589 //otherwise which may not happen until there is an actual change in ICC status. 590 Message.obtain(h, what, new AsyncResult(obj, null, null)).sendToTarget(); 591 } 592 unregisterForIccChanged(Handler h)593 public void unregisterForIccChanged(Handler h) { 594 synchronized (mLock) { 595 mIccChangedRegistrants.remove(h); 596 } 597 } 598 599 @Override handleMessage(Message msg)600 public void handleMessage (Message msg) { 601 synchronized (mLock) { 602 Integer phoneId = getCiIndex(msg); 603 String eventName = eventToString(msg.what); 604 605 if (phoneId < 0 || phoneId >= mCis.length) { 606 Rlog.e(LOG_TAG, "Invalid phoneId : " + phoneId + " received with event " 607 + eventName); 608 return; 609 } 610 611 logWithLocalLog("handleMessage: Received " + eventName + " for phoneId " + phoneId); 612 613 AsyncResult ar = (AsyncResult)msg.obj; 614 switch (msg.what) { 615 case EVENT_ICC_STATUS_CHANGED: 616 if (DBG) log("Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus"); 617 mCis[phoneId].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, 618 phoneId)); 619 break; 620 case EVENT_RADIO_AVAILABLE: 621 case EVENT_RADIO_ON: 622 if (DBG) { 623 log("Received EVENT_RADIO_AVAILABLE/EVENT_RADIO_ON, calling " 624 + "getIccCardStatus"); 625 } 626 // slot status should be the same on all RILs; request it only for phoneId 0 627 if (phoneId == 0) { 628 if (DBG) { 629 log("Received EVENT_RADIO_AVAILABLE/EVENT_RADIO_ON for phoneId 0, " 630 + "calling getSimSlotsStatus"); 631 } 632 mRadioConfig.getSimSlotsStatus(obtainMessage(EVENT_GET_SLOT_STATUS_DONE, 633 phoneId)); 634 } 635 mCis[phoneId].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, 636 phoneId)); 637 break; 638 case EVENT_GET_ICC_STATUS_DONE: 639 if (DBG) log("Received EVENT_GET_ICC_STATUS_DONE"); 640 onGetIccCardStatusDone(ar, phoneId); 641 break; 642 case EVENT_SLOT_STATUS_CHANGED: 643 case EVENT_GET_SLOT_STATUS_DONE: 644 if (DBG) { 645 log("Received EVENT_SLOT_STATUS_CHANGED or EVENT_GET_SLOT_STATUS_DONE"); 646 } 647 onGetSlotStatusDone(ar); 648 break; 649 case EVENT_RADIO_UNAVAILABLE: 650 if (DBG) log("EVENT_RADIO_UNAVAILABLE, dispose card"); 651 sLastSlotStatus = null; 652 UiccSlot uiccSlot = getUiccSlotForPhone(phoneId); 653 if (uiccSlot != null) { 654 uiccSlot.onRadioStateUnavailable(phoneId); 655 } 656 mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, phoneId, null)); 657 break; 658 case EVENT_SIM_REFRESH: 659 if (DBG) log("Received EVENT_SIM_REFRESH"); 660 onSimRefresh(ar, phoneId); 661 break; 662 case EVENT_EID_READY: 663 if (DBG) log("Received EVENT_EID_READY"); 664 onEidReady(ar, phoneId); 665 break; 666 case EVENT_MULTI_SIM_CONFIG_CHANGED: 667 if (DBG) log("Received EVENT_MULTI_SIM_CONFIG_CHANGED"); 668 int activeModemCount = (int) ((AsyncResult) msg.obj).result; 669 onMultiSimConfigChanged(activeModemCount); 670 break; 671 default: 672 Rlog.e(LOG_TAG, " Unknown Event " + msg.what); 673 break; 674 } 675 } 676 } 677 onMultiSimConfigChanged(int newActiveModemCount)678 private void onMultiSimConfigChanged(int newActiveModemCount) { 679 int prevActiveModemCount = mCis.length; 680 mCis = PhoneFactory.getCommandsInterfaces(); 681 682 logWithLocalLog("onMultiSimConfigChanged: prevActiveModemCount " + prevActiveModemCount 683 + ", newActiveModemCount " + newActiveModemCount); 684 685 // Resize array. 686 mPhoneIdToSlotId = copyOf(mPhoneIdToSlotId, newActiveModemCount); 687 688 // Register for new active modem for ss -> ds switch. 689 // For ds -> ss switch, there's no need to unregister as the mCis should unregister 690 // everything itself. 691 for (int i = prevActiveModemCount; i < newActiveModemCount; i++) { 692 mPhoneIdToSlotId[i] = INVALID_SLOT_ID; 693 mCis[i].registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, i); 694 mCis[i].registerForAvailable(this, EVENT_RADIO_AVAILABLE, i); 695 mCis[i].registerForNotAvailable(this, EVENT_RADIO_UNAVAILABLE, i); 696 mCis[i].registerForIccRefresh(this, EVENT_SIM_REFRESH, i); 697 } 698 } 699 getCiIndex(Message msg)700 private Integer getCiIndex(Message msg) { 701 AsyncResult ar; 702 Integer index = new Integer(PhoneConstants.DEFAULT_SLOT_INDEX); 703 704 /* 705 * The events can be come in two ways. By explicitly sending it using 706 * sendMessage, in this case the user object passed is msg.obj and from 707 * the CommandsInterface, in this case the user object is msg.obj.userObj 708 */ 709 if (msg != null) { 710 if (msg.obj != null && msg.obj instanceof Integer) { 711 index = (Integer)msg.obj; 712 } else if(msg.obj != null && msg.obj instanceof AsyncResult) { 713 ar = (AsyncResult)msg.obj; 714 if (ar.userObj != null && ar.userObj instanceof Integer) { 715 index = (Integer)ar.userObj; 716 } 717 } 718 } 719 return index; 720 } 721 eventToString(int event)722 private static String eventToString(int event) { 723 switch (event) { 724 case EVENT_ICC_STATUS_CHANGED: return "ICC_STATUS_CHANGED"; 725 case EVENT_SLOT_STATUS_CHANGED: return "SLOT_STATUS_CHANGED"; 726 case EVENT_GET_ICC_STATUS_DONE: return "GET_ICC_STATUS_DONE"; 727 case EVENT_GET_SLOT_STATUS_DONE: return "GET_SLOT_STATUS_DONE"; 728 case EVENT_RADIO_ON: return "RADIO_ON"; 729 case EVENT_RADIO_AVAILABLE: return "RADIO_AVAILABLE"; 730 case EVENT_RADIO_UNAVAILABLE: return "RADIO_UNAVAILABLE"; 731 case EVENT_SIM_REFRESH: return "SIM_REFRESH"; 732 case EVENT_EID_READY: return "EID_READY"; 733 case EVENT_MULTI_SIM_CONFIG_CHANGED: return "MULTI_SIM_CONFIG_CHANGED"; 734 default: return "UNKNOWN(" + event + ")"; 735 } 736 } 737 738 // Easy to use API 739 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getUiccCardApplication(int phoneId, int family)740 public UiccCardApplication getUiccCardApplication(int phoneId, int family) { 741 synchronized (mLock) { 742 UiccPort uiccPort = getUiccPortForPhone(phoneId); 743 if (uiccPort != null) { 744 return uiccPort.getApplication(family); 745 } 746 return null; 747 } 748 } 749 750 /** 751 * Convert IccCardConstants.State enum values to corresponding IccCardConstants String 752 * constants 753 * @param state IccCardConstants.State enum value 754 * @return IccCardConstants String constant representing ICC state 755 */ getIccStateIntentString(IccCardConstants.State state)756 public static String getIccStateIntentString(IccCardConstants.State state) { 757 switch (state) { 758 case ABSENT: return IccCardConstants.INTENT_VALUE_ICC_ABSENT; 759 case PIN_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 760 case PUK_REQUIRED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 761 case NETWORK_LOCKED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 762 case READY: return IccCardConstants.INTENT_VALUE_ICC_READY; 763 case NOT_READY: return IccCardConstants.INTENT_VALUE_ICC_NOT_READY; 764 case PERM_DISABLED: return IccCardConstants.INTENT_VALUE_ICC_LOCKED; 765 case CARD_IO_ERROR: return IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR; 766 case CARD_RESTRICTED: return IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED; 767 case LOADED: return IccCardConstants.INTENT_VALUE_ICC_LOADED; 768 default: return IccCardConstants.INTENT_VALUE_ICC_UNKNOWN; 769 } 770 } 771 772 /** 773 * Update SIM state for the inactive eSIM port. 774 * 775 * @param phoneId Previously active phone id. 776 * @param iccId ICCID of the SIM. 777 */ updateSimStateForInactivePort(int phoneId, String iccId)778 public void updateSimStateForInactivePort(int phoneId, String iccId) { 779 post(() -> { 780 if (SubscriptionManager.isValidPhoneId(phoneId)) { 781 // Mark SIM state as ABSENT on previously phoneId. 782 mTelephonyManager.setSimStateForPhone(phoneId, 783 IccCardConstants.State.ABSENT.toString()); 784 } 785 786 SubscriptionManagerService.getInstance().updateSimStateForInactivePort(phoneId, 787 TextUtils.emptyIfNull(iccId)); 788 }); 789 } 790 791 /** 792 * Broadcast the legacy SIM state changed event. 793 * 794 * @param phoneId The phone id. 795 * @param state The legacy SIM state. 796 * @param reason The reason of SIM state change. 797 */ broadcastSimStateChanged(int phoneId, @NonNull String state, @Nullable String reason)798 private void broadcastSimStateChanged(int phoneId, @NonNull String state, 799 @Nullable String reason) { 800 // Note: This intent is way deprecated and is only being kept around because there's no 801 // graceful way to deprecate a sticky broadcast that has a lot of listeners. 802 // DO NOT add any new extras to this broadcast -- it is not protected by any permissions. 803 Intent intent = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 804 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 805 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 806 intent.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone"); 807 intent.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, state); 808 intent.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason); 809 int subId = SubscriptionManager.getSubscriptionId(phoneId); 810 SubscriptionManager.putPhoneIdAndMaybeSubIdExtra(intent, phoneId, subId); 811 Rlog.d(LOG_TAG, "Broadcasting intent ACTION_SIM_STATE_CHANGED " + state + " reason " 812 + reason + " for phone: " + phoneId + " sub: " + subId); 813 IntentBroadcaster.getInstance().broadcastStickyIntent(mContext, intent, phoneId); 814 } 815 816 /** 817 * Broadcast SIM card state changed event. 818 * 819 * @param phoneId The phone id. 820 * @param state The SIM card state. 821 */ broadcastSimCardStateChanged(int phoneId, @SimState int state)822 private void broadcastSimCardStateChanged(int phoneId, @SimState int state) { 823 if (state != mSimCardState[phoneId]) { 824 mSimCardState[phoneId] = state; 825 Intent intent = new Intent(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED); 826 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 827 intent.putExtra(TelephonyManager.EXTRA_SIM_STATE, state); 828 int subId = SubscriptionManager.getSubscriptionId(phoneId); 829 SubscriptionManager.putPhoneIdAndMaybeSubIdExtra(intent, phoneId, subId); 830 // TODO(b/130664115) we manually populate this intent with the slotId. In the future we 831 // should do a review of whether to make this public 832 UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId); 833 int slotId = UiccController.getInstance().getSlotIdFromPhoneId(phoneId); 834 intent.putExtra(PhoneConstants.SLOT_KEY, slotId); 835 int portIndex = -1; 836 if (slot != null) { 837 portIndex = slot.getPortIndexFromPhoneId(phoneId); 838 intent.putExtra(PhoneConstants.PORT_KEY, portIndex); 839 } 840 Rlog.d(LOG_TAG, "Broadcasting intent ACTION_SIM_CARD_STATE_CHANGED " 841 + TelephonyManager.simStateToString(state) + " for phone: " + phoneId 842 + " slot: " + slotId + " port: " + portIndex + " sub: " + subId); 843 if (mFeatureFlags.hsumBroadcast()) { 844 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 845 Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 846 } else { 847 mContext.sendBroadcast(intent, Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 848 } 849 TelephonyMetrics.getInstance().updateSimState(phoneId, state); 850 } 851 } 852 853 /** 854 * Broadcast SIM application state changed event. 855 * 856 * @param phoneId The phone id. 857 * @param state The SIM application state. 858 */ broadcastSimApplicationStateChanged(int phoneId, @SimState int state)859 private void broadcastSimApplicationStateChanged(int phoneId, @SimState int state) { 860 // Broadcast if the state has changed, except if old state was UNKNOWN and new is NOT_READY, 861 // because that's the initial state and a broadcast should be sent only on a transition 862 // after SIM is PRESENT. The only exception is eSIM boot profile, where NOT_READY is the 863 // terminal state. 864 boolean isUnknownToNotReady = 865 (mSimApplicationState[phoneId] == TelephonyManager.SIM_STATE_UNKNOWN 866 && state == TelephonyManager.SIM_STATE_NOT_READY); 867 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); 868 boolean emptyProfile = iccCard != null && iccCard.isEmptyProfile(); 869 if (state != mSimApplicationState[phoneId] && (!isUnknownToNotReady || emptyProfile)) { 870 mSimApplicationState[phoneId] = state; 871 Intent intent = new Intent(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED); 872 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 873 intent.putExtra(TelephonyManager.EXTRA_SIM_STATE, state); 874 int subId = SubscriptionManager.getSubscriptionId(phoneId); 875 SubscriptionManager.putPhoneIdAndMaybeSubIdExtra(intent, phoneId, subId); 876 // TODO(b/130664115) we populate this intent with the actual slotId. In the future we 877 // should do a review of whether to make this public 878 UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId); 879 int slotId = UiccController.getInstance().getSlotIdFromPhoneId(phoneId); 880 intent.putExtra(PhoneConstants.SLOT_KEY, slotId); 881 if (slot != null) { 882 intent.putExtra(PhoneConstants.PORT_KEY, slot.getPortIndexFromPhoneId(phoneId)); 883 } 884 Rlog.d(LOG_TAG, "Broadcasting intent ACTION_SIM_APPLICATION_STATE_CHANGED " 885 + TelephonyManager.simStateToString(state) 886 + " for phone: " + phoneId + " slot: " + slotId + " port: " 887 + slot.getPortIndexFromPhoneId(phoneId) + " sub: " + subId); 888 if (mFeatureFlags.hsumBroadcast()) { 889 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 890 Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 891 } else { 892 mContext.sendBroadcast(intent, Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 893 } 894 TelephonyMetrics.getInstance().updateSimState(phoneId, state); 895 } 896 } 897 898 /** 899 * Get SIM state from SIM lock reason. 900 * 901 * @param lockedReason The SIM lock reason. 902 * 903 * @return The SIM state. 904 */ 905 @SimState getSimStateFromLockedReason(String lockedReason)906 private static int getSimStateFromLockedReason(String lockedReason) { 907 switch (lockedReason) { 908 case IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN: 909 return TelephonyManager.SIM_STATE_PIN_REQUIRED; 910 case IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK: 911 return TelephonyManager.SIM_STATE_PUK_REQUIRED; 912 case IccCardConstants.INTENT_VALUE_LOCKED_NETWORK: 913 return TelephonyManager.SIM_STATE_NETWORK_LOCKED; 914 case IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED: 915 return TelephonyManager.SIM_STATE_PERM_DISABLED; 916 default: 917 Rlog.e(LOG_TAG, "Unexpected SIM locked reason " + lockedReason); 918 return TelephonyManager.SIM_STATE_UNKNOWN; 919 } 920 } 921 922 /** 923 * Broadcast SIM state events. 924 * 925 * @param phoneId The phone id. 926 * @param simState The SIM state. 927 * @param reason SIM state changed reason. 928 */ broadcastSimStateEvents(int phoneId, IccCardConstants.State simState, @Nullable String reason)929 private void broadcastSimStateEvents(int phoneId, IccCardConstants.State simState, 930 @Nullable String reason) { 931 String legacyStringSimState = getIccStateIntentString(simState); 932 int cardState = TelephonyManager.SIM_STATE_UNKNOWN; 933 int applicationState = TelephonyManager.SIM_STATE_UNKNOWN; 934 935 switch (simState) { 936 case ABSENT: 937 cardState = TelephonyManager.SIM_STATE_ABSENT; 938 break; 939 case PIN_REQUIRED: 940 case PUK_REQUIRED: 941 case NETWORK_LOCKED: 942 case PERM_DISABLED: 943 cardState = TelephonyManager.SIM_STATE_PRESENT; 944 applicationState = getSimStateFromLockedReason(reason); 945 break; 946 case READY: 947 case NOT_READY: 948 // Both READY and NOT_READY have the same card state and application state. 949 cardState = TelephonyManager.SIM_STATE_PRESENT; 950 applicationState = TelephonyManager.SIM_STATE_NOT_READY; 951 break; 952 case CARD_IO_ERROR: 953 cardState = TelephonyManager.SIM_STATE_CARD_IO_ERROR; 954 applicationState = TelephonyManager.SIM_STATE_NOT_READY; 955 break; 956 case CARD_RESTRICTED: 957 cardState = TelephonyManager.SIM_STATE_CARD_RESTRICTED; 958 applicationState = TelephonyManager.SIM_STATE_NOT_READY; 959 break; 960 case LOADED: 961 cardState = TelephonyManager.SIM_STATE_PRESENT; 962 applicationState = TelephonyManager.SIM_STATE_LOADED; 963 break; 964 case UNKNOWN: 965 default: 966 break; 967 } 968 969 broadcastSimStateChanged(phoneId, legacyStringSimState, reason); 970 broadcastSimCardStateChanged(phoneId, cardState); 971 broadcastSimApplicationStateChanged(phoneId, applicationState); 972 } 973 974 /** 975 * Update carrier service. 976 * 977 * @param phoneId The phone id. 978 * @param simState The SIM state. 979 */ updateCarrierServices(int phoneId, @NonNull String simState)980 private void updateCarrierServices(int phoneId, @NonNull String simState) { 981 CarrierConfigManager configManager = mContext.getSystemService(CarrierConfigManager.class); 982 if (configManager != null) { 983 configManager.updateConfigForPhoneId(phoneId, simState); 984 } 985 mCarrierServiceBindHelper.updateForPhoneId(phoneId, simState); 986 } 987 988 /** 989 * Update the SIM state. 990 * 991 * @param phoneId Phone id. 992 * @param state SIM state (legacy). 993 * @param reason The reason for SIM state update. 994 */ updateSimState(int phoneId, @NonNull IccCardConstants.State state, @Nullable String reason)995 public void updateSimState(int phoneId, @NonNull IccCardConstants.State state, 996 @Nullable String reason) { 997 post(() -> { 998 log("updateSimState: phoneId=" + phoneId + ", state=" + state + ", reason=" 999 + reason); 1000 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 1001 Rlog.e(LOG_TAG, "updateSimState: Invalid phone id " + phoneId); 1002 return; 1003 } 1004 1005 mTelephonyManager.setSimStateForPhone(phoneId, state.toString()); 1006 1007 String legacySimState = getIccStateIntentString(state); 1008 int simState = state.ordinal(); 1009 SubscriptionManagerService.getInstance().updateSimState(phoneId, simState, 1010 this::post, 1011 () -> { 1012 // The following are executed after subscription update completed in 1013 // subscription manager service. 1014 1015 broadcastSimStateEvents(phoneId, state, reason); 1016 1017 UiccProfile uiccProfile = getUiccProfileForPhone(phoneId); 1018 1019 if (simState == TelephonyManager.SIM_STATE_READY) { 1020 // SIM_STATE_READY is not a final state. 1021 return; 1022 } 1023 1024 if (simState == TelephonyManager.SIM_STATE_NOT_READY 1025 && (uiccProfile != null && !uiccProfile.isEmptyProfile()) 1026 && SubscriptionManagerService.getInstance() 1027 .areUiccAppsEnabledOnCard(phoneId)) { 1028 // STATE_NOT_READY is not a final state for when both 1029 // 1) It's not an empty profile, and 1030 // 2) Its uicc applications are set to enabled. 1031 // 1032 // At this phase, we consider STATE_NOT_READY not a final state, so 1033 // return for now. 1034 log("updateSimState: SIM_STATE_NOT_READY is not a final " 1035 + "state."); 1036 return; 1037 } 1038 1039 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 1040 Rlog.e(LOG_TAG, "updateSimState: Cannot update carrier services. " 1041 + "Invalid phone id " + phoneId); 1042 return; 1043 } 1044 1045 // At this point, the SIM state must be a final state (meaning we won't 1046 // get more SIM state updates). So resolve the carrier id and update the 1047 // carrier services. 1048 log("updateSimState: resolve carrier id and update carrier " 1049 + "services."); 1050 PhoneFactory.getPhone(phoneId).resolveSubscriptionCarrierId( 1051 legacySimState); 1052 updateCarrierServices(phoneId, legacySimState); 1053 } 1054 ); 1055 }); 1056 } 1057 onGetIccCardStatusDone(AsyncResult ar, Integer index)1058 private synchronized void onGetIccCardStatusDone(AsyncResult ar, Integer index) { 1059 if (ar.exception != null) { 1060 Rlog.e(LOG_TAG,"Error getting ICC status. " 1061 + "RIL_REQUEST_GET_ICC_STATUS should " 1062 + "never return an error", ar.exception); 1063 return; 1064 } 1065 if (!isValidPhoneIndex(index)) { 1066 Rlog.e(LOG_TAG,"onGetIccCardStatusDone: invalid index : " + index); 1067 return; 1068 } 1069 if (isShuttingDown()) { 1070 // Do not process the SIM/SLOT events during device shutdown, 1071 // as it may unnecessarily modify the persistent information 1072 // like, SubscriptionManager.UICC_APPLICATIONS_ENABLED. 1073 log("onGetIccCardStatusDone: shudown in progress ignore event"); 1074 return; 1075 } 1076 1077 IccCardStatus status = (IccCardStatus)ar.result; 1078 1079 logWithLocalLog("onGetIccCardStatusDone: phoneId-" + index + " IccCardStatus: " + status); 1080 1081 int slotId = status.mSlotPortMapping.mPhysicalSlotIndex; 1082 if (VDBG) log("onGetIccCardStatusDone: phoneId-" + index + " physicalSlotIndex " + slotId); 1083 if (slotId == INVALID_SLOT_ID) { 1084 slotId = index; 1085 } 1086 1087 mPhoneIdToSlotId[index] = slotId; 1088 1089 if (VDBG) logPhoneIdToSlotIdMapping(); 1090 1091 if (mUiccSlots[slotId] == null) { 1092 if (VDBG) { 1093 log("Creating mUiccSlots[" + slotId + "]; mUiccSlots.length = " 1094 + mUiccSlots.length); 1095 } 1096 setUiccSlot(slotId, new UiccSlot(mContext, true)); 1097 } 1098 1099 mUiccSlots[slotId].update(mCis[index], status, index, slotId); 1100 1101 UiccCard card = mUiccSlots[slotId].getUiccCard(); 1102 if (card == null) { 1103 if (DBG) log("mUiccSlots[" + slotId + "] has no card. Notifying IccChangedRegistrants"); 1104 mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 1105 return; 1106 } 1107 1108 UiccPort port = card.getUiccPort(status.mSlotPortMapping.mPortIndex); 1109 if (port == null) { 1110 if (DBG) log("mUiccSlots[" + slotId + "] has no UiccPort with index[" 1111 + status.mSlotPortMapping.mPortIndex + "]. Notifying IccChangedRegistrants"); 1112 mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 1113 return; 1114 } 1115 1116 String cardString = null; 1117 boolean isEuicc = mUiccSlots[slotId].isEuicc(); 1118 if (isEuicc) { 1119 cardString = ((EuiccCard) card).getEid(); 1120 } else { 1121 cardString = card.getUiccPort(status.mSlotPortMapping.mPortIndex).getIccId(); 1122 } 1123 1124 if (cardString != null) { 1125 addCardId(cardString); 1126 } 1127 1128 // EID is unpopulated if Radio HAL < 1.4 (RadioConfig < 1.2) 1129 // If so, just register for EID loaded and skip this stuff 1130 if (isEuicc && mDefaultEuiccCardId != UNSUPPORTED_CARD_ID) { 1131 if (cardString == null) { 1132 ((EuiccCard) card).registerForEidReady(this, EVENT_EID_READY, index); 1133 } else { 1134 // If we know the EID from IccCardStatus, just use it to set mDefaultEuiccCardId if 1135 // it's not already set. 1136 // This is needed in cases where slot status doesn't include EID, and we don't want 1137 // to register for EID from APDU because we already know cardString from a previous 1138 // APDU 1139 if (mDefaultEuiccCardId == UNINITIALIZED_CARD_ID 1140 || mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { 1141 mDefaultEuiccCardId = convertToPublicCardId(cardString); 1142 logWithLocalLog("IccCardStatus eid=" 1143 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, cardString) + " slot=" + slotId 1144 + " mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1145 } 1146 } 1147 } 1148 1149 if (DBG) log("Notifying IccChangedRegistrants"); 1150 mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 1151 } 1152 1153 /** 1154 * Add a cardString to mCardStrings. If this is an ICCID, trailing Fs will be automatically 1155 * stripped. 1156 */ addCardId(String cardString)1157 private void addCardId(String cardString) { 1158 if (TextUtils.isEmpty(cardString)) { 1159 return; 1160 } 1161 if (cardString.length() < EID_LENGTH) { 1162 cardString = IccUtils.stripTrailingFs(cardString); 1163 } 1164 if (!mCardStrings.contains(cardString)) { 1165 mCardStrings.add(cardString); 1166 saveCardStrings(); 1167 } 1168 } 1169 1170 /** 1171 * Converts an integer cardId (public card ID) to a card string. 1172 * @param cardId to convert 1173 * @return cardString, or null if the cardId is not valid 1174 */ convertToCardString(int cardId)1175 public String convertToCardString(int cardId) { 1176 if (cardId < 0 || cardId >= mCardStrings.size()) { 1177 log("convertToCardString: cardId " + cardId + " is not valid"); 1178 return null; 1179 } 1180 return mCardStrings.get(cardId); 1181 } 1182 1183 /** 1184 * Converts the card string (the ICCID/EID, formerly named card ID) to the public int cardId. 1185 * If the given cardString is an ICCID, trailing Fs will be automatically stripped before trying 1186 * to match to a card ID. 1187 * 1188 * @return the matching cardId, or UNINITIALIZED_CARD_ID if the card string does not map to a 1189 * currently loaded cardId, or UNSUPPORTED_CARD_ID if the device does not support card IDs 1190 */ convertToPublicCardId(String cardString)1191 public int convertToPublicCardId(String cardString) { 1192 if (mDefaultEuiccCardId == UNSUPPORTED_CARD_ID) { 1193 // even if cardString is not an EID, if EID is not supported (e.g. HAL < 1.2) we can't 1194 // guarentee a working card ID implementation, so return UNSUPPORTED_CARD_ID 1195 return UNSUPPORTED_CARD_ID; 1196 } 1197 if (TextUtils.isEmpty(cardString)) { 1198 return UNINITIALIZED_CARD_ID; 1199 } 1200 1201 if (cardString.length() < EID_LENGTH) { 1202 cardString = IccUtils.stripTrailingFs(cardString); 1203 } 1204 int id = mCardStrings.indexOf(cardString); 1205 if (id == -1) { 1206 return UNINITIALIZED_CARD_ID; 1207 } else { 1208 return id; 1209 } 1210 } 1211 1212 /** 1213 * Returns the UiccCardInfo of all currently inserted UICCs and embedded eUICCs. 1214 */ getAllUiccCardInfos()1215 public ArrayList<UiccCardInfo> getAllUiccCardInfos() { 1216 synchronized (mLock) { 1217 ArrayList<UiccCardInfo> infos = new ArrayList<>(); 1218 for (int slotIndex = 0; slotIndex < mUiccSlots.length; slotIndex++) { 1219 final UiccSlot slot = mUiccSlots[slotIndex]; 1220 if (slot == null) continue; 1221 boolean isEuicc = slot.isEuicc(); 1222 String eid = null; 1223 UiccCard card = slot.getUiccCard(); 1224 int cardId = UNINITIALIZED_CARD_ID; 1225 boolean isRemovable = slot.isRemovable(); 1226 1227 // first we try to populate UiccCardInfo using the UiccCard, but if it doesn't exist 1228 // (e.g. the slot is for an inactive eUICC) then we try using the UiccSlot. 1229 if (card != null) { 1230 if (isEuicc) { 1231 eid = ((EuiccCard) card).getEid(); 1232 cardId = convertToPublicCardId(eid); 1233 } else { 1234 // In case of non Euicc, use default port index to get the IccId. 1235 UiccPort port = card.getUiccPort(TelephonyManager.DEFAULT_PORT_INDEX); 1236 if (port == null) { 1237 AnomalyReporter.reportAnomaly( 1238 UUID.fromString("92885ba7-98bb-490a-ba19-987b1c8b2055"), 1239 "UiccController: Found UiccPort Null object."); 1240 } 1241 String iccId = (port != null) ? port.getIccId() : null; 1242 cardId = convertToPublicCardId(iccId); 1243 } 1244 } else { 1245 // This iccid is used for non Euicc only, so use default port index 1246 String iccId = slot.getIccId(TelephonyManager.DEFAULT_PORT_INDEX); 1247 // Fill in the fields we can 1248 if (!isEuicc && !TextUtils.isEmpty(iccId)) { 1249 cardId = convertToPublicCardId(iccId); 1250 } 1251 } 1252 1253 List<UiccPortInfo> portInfos = new ArrayList<>(); 1254 int[] portIndexes = slot.getPortList(); 1255 for (int portIdx : portIndexes) { 1256 String iccId = IccUtils.stripTrailingFs(slot.getIccId(portIdx)); 1257 portInfos.add(new UiccPortInfo(iccId, portIdx, 1258 slot.getPhoneIdFromPortIndex(portIdx), slot.isPortActive(portIdx))); 1259 } 1260 UiccCardInfo info = new UiccCardInfo( 1261 isEuicc, cardId, eid, slotIndex, isRemovable, 1262 slot.isMultipleEnabledProfileSupported(), portInfos); 1263 infos.add(info); 1264 } 1265 return infos; 1266 } 1267 } 1268 1269 /** 1270 * Get the card ID of the default eUICC. 1271 */ getCardIdForDefaultEuicc()1272 public int getCardIdForDefaultEuicc() { 1273 if (mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { 1274 return UNSUPPORTED_CARD_ID; 1275 } 1276 // To support removable eSIM to pass GCT/PTCRB test in DSDS mode, we should make sure all 1277 // the download/activation requests are by default route to the removable eSIM slot. 1278 // To satisfy above condition, we should return removable eSIM cardId as default. 1279 if (mUseRemovableEsimAsDefault && !TelephonyUtils.IS_USER) { 1280 for (UiccSlot slot : mUiccSlots) { 1281 if (slot != null && slot.isRemovable() && slot.isEuicc() && slot.isActive()) { 1282 int cardId = convertToPublicCardId(slot.getEid()); 1283 Rlog.d(LOG_TAG, 1284 "getCardIdForDefaultEuicc: Removable eSIM is default, cardId: " 1285 + cardId); 1286 return cardId; 1287 } 1288 } 1289 Rlog.d(LOG_TAG, "getCardIdForDefaultEuicc: No removable eSIM slot is found"); 1290 } 1291 return mDefaultEuiccCardId; 1292 } 1293 1294 /** Get the {@link PinStorage}. */ getPinStorage()1295 public PinStorage getPinStorage() { 1296 return mPinStorage; 1297 } 1298 loadCardStrings()1299 private ArrayList<String> loadCardStrings() { 1300 String cardStrings = 1301 PreferenceManager.getDefaultSharedPreferences(mContext).getString(CARD_STRINGS, ""); 1302 if (TextUtils.isEmpty(cardStrings)) { 1303 // just return an empty list, since String.split would return the list { "" } 1304 return new ArrayList<String>(); 1305 } 1306 return new ArrayList<String>(Arrays.asList(cardStrings.split(","))); 1307 } 1308 saveCardStrings()1309 private void saveCardStrings() { 1310 SharedPreferences.Editor editor = 1311 PreferenceManager.getDefaultSharedPreferences(mContext).edit(); 1312 editor.putString(CARD_STRINGS, TextUtils.join(",", mCardStrings)); 1313 editor.commit(); 1314 } 1315 onGetSlotStatusDone(AsyncResult ar)1316 private synchronized void onGetSlotStatusDone(AsyncResult ar) { 1317 if (!mIsSlotStatusSupported) { 1318 if (VDBG) log("onGetSlotStatusDone: ignoring since mIsSlotStatusSupported is false"); 1319 return; 1320 } 1321 Throwable e = ar.exception; 1322 if (e != null) { 1323 if (!(e instanceof CommandException) || ((CommandException) e).getCommandError() 1324 != CommandException.Error.REQUEST_NOT_SUPPORTED) { 1325 // this is not expected; there should be no exception other than 1326 // REQUEST_NOT_SUPPORTED 1327 logeWithLocalLog("Unexpected error getting slot status: " + ar.exception); 1328 } else { 1329 // REQUEST_NOT_SUPPORTED 1330 logWithLocalLog("onGetSlotStatusDone: request not supported; marking " 1331 + "mIsSlotStatusSupported to false"); 1332 mIsSlotStatusSupported = false; 1333 } 1334 return; 1335 } 1336 if (isShuttingDown()) { 1337 // Do not process the SIM/SLOT events during device shutdown, 1338 // as it may unnecessarily modify the persistent information 1339 // like, SubscriptionManager.UICC_APPLICATIONS_ENABLED. 1340 log("onGetSlotStatusDone: shudown in progress ignore event"); 1341 return; 1342 } 1343 1344 ArrayList<IccSlotStatus> status = (ArrayList<IccSlotStatus>) ar.result; 1345 1346 if (!slotStatusChanged(status)) { 1347 log("onGetSlotStatusDone: No change in slot status"); 1348 return; 1349 } 1350 logWithLocalLog("onGetSlotStatusDone: " + status); 1351 1352 sLastSlotStatus = status; 1353 1354 int numActivePorts = 0; 1355 boolean isDefaultEuiccCardIdSet = false; 1356 boolean anyEuiccIsActive = false; 1357 mHasActiveBuiltInEuicc = false; 1358 1359 int numSlots = status.size(); 1360 if (mUiccSlots.length < numSlots) { 1361 logeWithLocalLog("The number of the physical slots reported " + numSlots 1362 + " is greater than the expectation " + mUiccSlots.length); 1363 numSlots = mUiccSlots.length; 1364 } 1365 1366 for (int i = 0; i < numSlots; i++) { 1367 IccSlotStatus iss = status.get(i); 1368 boolean isActive = hasActivePort(iss.mSimPortInfos); 1369 if (mUiccSlots[i] == null) { 1370 if (VDBG) { 1371 log("Creating mUiccSlot[" + i + "]; mUiccSlots.length = " + mUiccSlots.length); 1372 } 1373 setUiccSlot(i, new UiccSlot(mContext, isActive)); 1374 } 1375 1376 if (isActive) { // check isActive flag so that we don't have to iterate through all 1377 for (int j = 0; j < iss.mSimPortInfos.length; j++) { 1378 if (iss.mSimPortInfos[j].mPortActive) { 1379 int logicalSlotIndex = iss.mSimPortInfos[j].mLogicalSlotIndex; 1380 // Correctness check: logicalSlotIndex should be valid for an active slot 1381 if (!isValidPhoneIndex(logicalSlotIndex)) { 1382 Rlog.e(LOG_TAG, "Skipping slot " + i + " portIndex " + j + " as phone " 1383 + logicalSlotIndex 1384 + " is not available to communicate with this slot"); 1385 } else { 1386 mPhoneIdToSlotId[logicalSlotIndex] = i; 1387 } 1388 numActivePorts++; 1389 } 1390 } 1391 } 1392 1393 mUiccSlots[i].update(mCis, iss, i); 1394 1395 if (mUiccSlots[i].isEuicc()) { 1396 if (isActive) { 1397 anyEuiccIsActive = true; 1398 1399 if (isBuiltInEuiccSlot(i)) { 1400 mHasActiveBuiltInEuicc = true; 1401 } 1402 } 1403 String eid = iss.eid; 1404 if (TextUtils.isEmpty(eid)) { 1405 // iss.eid is not populated on HAL<1.4 1406 continue; 1407 } 1408 1409 addCardId(eid); 1410 1411 // whenever slot status is received, set default card to the non-removable eUICC 1412 // with the lowest slot index. 1413 if (!mUiccSlots[i].isRemovable() && !isDefaultEuiccCardIdSet) { 1414 isDefaultEuiccCardIdSet = true; 1415 mDefaultEuiccCardId = convertToPublicCardId(eid); 1416 logWithLocalLog("Using eid=" + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, eid) 1417 + " in slot=" + i + " to set mDefaultEuiccCardId=" 1418 + mDefaultEuiccCardId); 1419 } 1420 } 1421 } 1422 1423 if (!mHasActiveBuiltInEuicc && !isDefaultEuiccCardIdSet) { 1424 // if there are no active built-in eUICCs, then consider setting a removable eUICC to 1425 // the default. 1426 // Note that on HAL<1.2, it's possible that a built-in eUICC exists, but does not 1427 // correspond to any slot in mUiccSlots. This logic is still safe in that case because 1428 // SlotStatus is only for HAL >= 1.2 1429 for (int i = 0; i < numSlots; i++) { 1430 if (mUiccSlots[i].isEuicc()) { 1431 String eid = status.get(i).eid; 1432 if (!TextUtils.isEmpty(eid)) { 1433 isDefaultEuiccCardIdSet = true; 1434 mDefaultEuiccCardId = convertToPublicCardId(eid); 1435 logWithLocalLog("Using eid=" 1436 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, eid) 1437 + " from removable eUICC in slot=" + i 1438 + " to set mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1439 break; 1440 } 1441 } 1442 } 1443 } 1444 1445 if (mHasBuiltInEuicc && !anyEuiccIsActive && !isDefaultEuiccCardIdSet) { 1446 logWithLocalLog( 1447 "onGetSlotStatusDone: mDefaultEuiccCardId=TEMPORARILY_UNSUPPORTED_CARD_ID"); 1448 isDefaultEuiccCardIdSet = true; 1449 mDefaultEuiccCardId = TEMPORARILY_UNSUPPORTED_CARD_ID; 1450 } 1451 1452 1453 if (!isDefaultEuiccCardIdSet) { 1454 if (mDefaultEuiccCardId >= 0) { 1455 // if mDefaultEuiccCardId has already been set to an actual eUICC, 1456 // don't overwrite mDefaultEuiccCardId unless that eUICC is no longer inserted 1457 boolean defaultEuiccCardIdIsStillInserted = false; 1458 String cardString = mCardStrings.get(mDefaultEuiccCardId); 1459 for (UiccSlot slot : mUiccSlots) { 1460 if (slot.getUiccCard() == null) { 1461 continue; 1462 } 1463 if (cardString.equals( 1464 IccUtils.stripTrailingFs(slot.getUiccCard().getCardId()))) { 1465 defaultEuiccCardIdIsStillInserted = true; 1466 } 1467 } 1468 if (!defaultEuiccCardIdIsStillInserted) { 1469 logWithLocalLog("onGetSlotStatusDone: mDefaultEuiccCardId=" 1470 + mDefaultEuiccCardId 1471 + " is no longer inserted. Setting mDefaultEuiccCardId=UNINITIALIZED"); 1472 mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; 1473 } 1474 } else { 1475 // no known eUICCs at all (it's possible that an eUICC is inserted and we just don't 1476 // know it's EID) 1477 logWithLocalLog("onGetSlotStatusDone: mDefaultEuiccCardId=UNINITIALIZED"); 1478 mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; 1479 } 1480 } 1481 1482 if (VDBG) logPhoneIdToSlotIdMapping(); 1483 1484 // Correctness check: number of active ports should be valid 1485 if (numActivePorts != mPhoneIdToSlotId.length) { 1486 Rlog.e(LOG_TAG, "Number of active ports " + numActivePorts 1487 + " does not match the number of Phones" + mPhoneIdToSlotId.length); 1488 } 1489 1490 // broadcast slot status changed 1491 final BroadcastOptions options = BroadcastOptions.makeBasic(); 1492 options.setBackgroundActivityStartsAllowed(true); 1493 Intent intent = new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED); 1494 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1495 if (mFeatureFlags.hsumBroadcast()) { 1496 mContext.sendBroadcastAsUser(intent, UserHandle.ALL, 1497 android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, options.toBundle()); 1498 } else { 1499 mContext.sendBroadcast(intent, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1500 options.toBundle()); 1501 } 1502 } 1503 hasActivePort(IccSimPortInfo[] simPortInfos)1504 private boolean hasActivePort(IccSimPortInfo[] simPortInfos) { 1505 for (IccSimPortInfo simPortInfo : simPortInfos) { 1506 if (simPortInfo.mPortActive) { 1507 return true; 1508 } 1509 } 1510 return false; 1511 } 1512 1513 /** 1514 * Check if slot status has changed from the last received one 1515 */ 1516 @VisibleForTesting slotStatusChanged(ArrayList<IccSlotStatus> slotStatusList)1517 public boolean slotStatusChanged(ArrayList<IccSlotStatus> slotStatusList) { 1518 if (sLastSlotStatus == null || sLastSlotStatus.size() != slotStatusList.size()) { 1519 return true; 1520 } 1521 for (int i = 0; i < slotStatusList.size(); i++) { 1522 if (!sLastSlotStatus.get(i).equals(slotStatusList.get(i))) { 1523 return true; 1524 } 1525 } 1526 return false; 1527 } 1528 logPhoneIdToSlotIdMapping()1529 private void logPhoneIdToSlotIdMapping() { 1530 log("mPhoneIdToSlotId mapping:"); 1531 for (int i = 0; i < mPhoneIdToSlotId.length; i++) { 1532 log(" phoneId " + i + " slotId " + mPhoneIdToSlotId[i]); 1533 } 1534 } 1535 onSimRefresh(AsyncResult ar, Integer index)1536 private void onSimRefresh(AsyncResult ar, Integer index) { 1537 if (ar.exception != null) { 1538 Rlog.e(LOG_TAG, "onSimRefresh: Sim REFRESH with exception: " + ar.exception); 1539 return; 1540 } 1541 1542 if (!isValidPhoneIndex(index)) { 1543 Rlog.e(LOG_TAG,"onSimRefresh: invalid index : " + index); 1544 return; 1545 } 1546 1547 IccRefreshResponse resp = (IccRefreshResponse) ar.result; 1548 logWithLocalLog("onSimRefresh: index " + index + ", " + resp); 1549 1550 if (resp == null) { 1551 Rlog.e(LOG_TAG, "onSimRefresh: received without input"); 1552 return; 1553 } 1554 1555 UiccCard uiccCard = getUiccCardForPhone(index); 1556 if (uiccCard == null) { 1557 Rlog.e(LOG_TAG,"onSimRefresh: refresh on null card : " + index); 1558 return; 1559 } 1560 1561 UiccPort uiccPort = getUiccPortForPhone(index); 1562 if (uiccPort == null) { 1563 Rlog.e(LOG_TAG, "onSimRefresh: refresh on null port : " + index); 1564 return; 1565 } 1566 1567 boolean changed = false; 1568 switch(resp.refreshResult) { 1569 // Reset the required apps when we know about the refresh so that 1570 // anyone interested does not get stale state. 1571 case IccRefreshResponse.REFRESH_RESULT_RESET: 1572 changed = uiccPort.resetAppWithAid(resp.aid, true /* reset */); 1573 break; 1574 case IccRefreshResponse.REFRESH_RESULT_INIT: 1575 // don't dispose CatService on SIM REFRESH of type INIT 1576 changed = uiccPort.resetAppWithAid(resp.aid, false /* initialize */); 1577 break; 1578 default: 1579 return; 1580 } 1581 1582 if (changed && resp.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET) { 1583 // If there is any change on RESET, reset carrier config as well. From carrier config 1584 // perspective, this is treated the same as sim state unknown 1585 CarrierConfigManager configManager = (CarrierConfigManager) 1586 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1587 configManager.updateConfigForPhoneId(index, IccCardConstants.INTENT_VALUE_ICC_UNKNOWN); 1588 } 1589 1590 // The card status could have changed. Get the latest state. 1591 mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index)); 1592 } 1593 1594 // for HAL 1.2-1.3 we register for EID ready, set mCardStrings and mDefaultEuiccCardId here. 1595 // Note that if there are multiple eUICCs on HAL 1.2-1.3, the default eUICC is the one whose EID 1596 // is first loaded onEidReady(AsyncResult ar, Integer index)1597 private void onEidReady(AsyncResult ar, Integer index) { 1598 if (ar.exception != null) { 1599 Rlog.e(LOG_TAG, "onEidReady: exception: " + ar.exception); 1600 return; 1601 } 1602 1603 if (!isValidPhoneIndex(index)) { 1604 Rlog.e(LOG_TAG, "onEidReady: invalid index: " + index); 1605 return; 1606 } 1607 int slotId = mPhoneIdToSlotId[index]; 1608 EuiccCard card = (EuiccCard) mUiccSlots[slotId].getUiccCard(); 1609 if (card == null) { 1610 Rlog.e(LOG_TAG, "onEidReady: UiccCard in slot " + slotId + " is null"); 1611 return; 1612 } 1613 1614 // set mCardStrings and the defaultEuiccCardId using the now available EID 1615 String eid = card.getEid(); 1616 addCardId(eid); 1617 if (mDefaultEuiccCardId == UNINITIALIZED_CARD_ID 1618 || mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { 1619 if (!mUiccSlots[slotId].isRemovable()) { 1620 mDefaultEuiccCardId = convertToPublicCardId(eid); 1621 logWithLocalLog("onEidReady: eid=" 1622 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, eid) 1623 + " slot=" + slotId + " mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1624 } else if (!mHasActiveBuiltInEuicc) { 1625 // we only set a removable eUICC to the default if there are no active non-removable 1626 // eUICCs 1627 mDefaultEuiccCardId = convertToPublicCardId(eid); 1628 logWithLocalLog("onEidReady: eid=" 1629 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, eid) 1630 + " from removable eUICC in slot=" + slotId + " mDefaultEuiccCardId=" 1631 + mDefaultEuiccCardId); 1632 } 1633 } 1634 card.unregisterForEidReady(this); 1635 } 1636 1637 // Return true if the device has at least one built in eUICC based on the resource overlay hasBuiltInEuicc()1638 private boolean hasBuiltInEuicc() { 1639 return mEuiccSlots != null && mEuiccSlots.length > 0; 1640 } 1641 isBuiltInEuiccSlot(int slotIndex)1642 private boolean isBuiltInEuiccSlot(int slotIndex) { 1643 if (!mHasBuiltInEuicc) { 1644 return false; 1645 } 1646 for (int slot : mEuiccSlots) { 1647 if (slot == slotIndex) { 1648 return true; 1649 } 1650 } 1651 return false; 1652 } 1653 1654 /** 1655 * static method to return whether CDMA is supported on the device 1656 * @param context object representative of the application that is calling this method 1657 * @return true if CDMA is supported by the device 1658 */ isCdmaSupported(Context context)1659 public static boolean isCdmaSupported(Context context) { 1660 if (Flags.phoneTypeCleanup()) return false; 1661 PackageManager packageManager = context.getPackageManager(); 1662 boolean isCdmaSupported = 1663 packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA); 1664 return isCdmaSupported; 1665 } 1666 isValidPhoneIndex(int index)1667 private boolean isValidPhoneIndex(int index) { 1668 return (index >= 0 && index < mTelephonyManager.getActiveModemCount()); 1669 } 1670 isValidSlotIndex(int index)1671 private boolean isValidSlotIndex(int index) { 1672 return (index >= 0 && index < mUiccSlots.length); 1673 } 1674 isShuttingDown()1675 private boolean isShuttingDown() { 1676 for (int i = 0; i < mTelephonyManager.getActiveModemCount(); i++) { 1677 if (PhoneFactory.getPhone(i) != null && 1678 PhoneFactory.getPhone(i).isShuttingDown()) { 1679 return true; 1680 } 1681 } 1682 return false; 1683 } 1684 iccidMatches(String mvnoData, String iccId)1685 private static boolean iccidMatches(String mvnoData, String iccId) { 1686 String[] mvnoIccidList = mvnoData.split(","); 1687 for (String mvnoIccid : mvnoIccidList) { 1688 if (iccId.startsWith(mvnoIccid)) { 1689 Log.d(LOG_TAG, "mvno icc id match found"); 1690 return true; 1691 } 1692 } 1693 return false; 1694 } 1695 imsiMatches(String imsiDB, String imsiSIM)1696 private static boolean imsiMatches(String imsiDB, String imsiSIM) { 1697 // Note: imsiDB value has digit number or 'x' character for separating USIM information 1698 // for MVNO operator. And then digit number is matched at same order and 'x' character 1699 // could replace by any digit number. 1700 // ex) if imsiDB inserted '310260x10xxxxxx' for GG Operator, 1701 // that means first 6 digits, 8th and 9th digit 1702 // should be set in USIM for GG Operator. 1703 int len = imsiDB.length(); 1704 1705 if (len <= 0) return false; 1706 if (len > imsiSIM.length()) return false; 1707 1708 for (int idx = 0; idx < len; idx++) { 1709 char c = imsiDB.charAt(idx); 1710 if ((c == 'x') || (c == 'X') || (c == imsiSIM.charAt(idx))) { 1711 continue; 1712 } else { 1713 return false; 1714 } 1715 } 1716 return true; 1717 } 1718 1719 /** 1720 * Check if MVNO type and data match IccRecords. 1721 * 1722 * @param slotIndex SIM slot index. 1723 * @param mvnoType the MVNO type 1724 * @param mvnoMatchData the MVNO match data 1725 * @return {@code true} if MVNO type and data match IccRecords, {@code false} otherwise. 1726 */ mvnoMatches(int slotIndex, int mvnoType, String mvnoMatchData)1727 public boolean mvnoMatches(int slotIndex, int mvnoType, String mvnoMatchData) { 1728 IccRecords iccRecords = getIccRecords(slotIndex, UiccController.APP_FAM_3GPP); 1729 if (iccRecords == null) { 1730 Log.d(LOG_TAG, "isMvnoMatched# IccRecords is null"); 1731 return false; 1732 } 1733 if (mvnoType == ApnSetting.MVNO_TYPE_SPN) { 1734 String spn = iccRecords.getServiceProviderNameWithBrandOverride(); 1735 if ((spn != null) && spn.equalsIgnoreCase(mvnoMatchData)) { 1736 return true; 1737 } 1738 } else if (mvnoType == ApnSetting.MVNO_TYPE_IMSI) { 1739 String imsiSIM = iccRecords.getIMSI(); 1740 if ((imsiSIM != null) && imsiMatches(mvnoMatchData, imsiSIM)) { 1741 return true; 1742 } 1743 } else if (mvnoType == ApnSetting.MVNO_TYPE_GID) { 1744 String gid1 = iccRecords.getGid1(); 1745 int mvno_match_data_length = mvnoMatchData.length(); 1746 if ((gid1 != null) && (gid1.length() >= mvno_match_data_length) 1747 && gid1.substring(0, mvno_match_data_length).equalsIgnoreCase(mvnoMatchData)) { 1748 return true; 1749 } 1750 } else if (mvnoType == ApnSetting.MVNO_TYPE_ICCID) { 1751 String iccId = iccRecords.getIccId(); 1752 if ((iccId != null) && iccidMatches(mvnoMatchData, iccId)) { 1753 return true; 1754 } 1755 } 1756 1757 return false; 1758 } 1759 1760 /** 1761 * Set removable eSIM as default. 1762 * This API is added for test purpose to set removable eSIM as default eUICC. 1763 * @param isDefault Flag to set removable eSIM as default or not. 1764 */ setRemovableEsimAsDefaultEuicc(boolean isDefault)1765 public void setRemovableEsimAsDefaultEuicc(boolean isDefault) { 1766 mUseRemovableEsimAsDefault = isDefault; 1767 SharedPreferences.Editor editor = 1768 PreferenceManager.getDefaultSharedPreferences(mContext).edit(); 1769 editor.putBoolean(REMOVABLE_ESIM_AS_DEFAULT, isDefault); 1770 editor.apply(); 1771 Rlog.d(LOG_TAG, "setRemovableEsimAsDefaultEuicc isDefault: " + isDefault); 1772 } 1773 1774 /** 1775 * Returns whether the removable eSIM is default eUICC or not. 1776 * This API is added for test purpose to check whether removable eSIM is default eUICC or not. 1777 */ isRemovableEsimDefaultEuicc()1778 public boolean isRemovableEsimDefaultEuicc() { 1779 Rlog.d(LOG_TAG, "mUseRemovableEsimAsDefault: " + mUseRemovableEsimAsDefault); 1780 return mUseRemovableEsimAsDefault; 1781 } 1782 1783 /** 1784 * Returns the MEP mode supported by the UiccSlot associated with slotIndex. 1785 * @param slotIndex physical slot index 1786 * @return MultipleEnabledProfilesMode supported by the slot 1787 */ getSupportedMepMode(int slotIndex)1788 public IccSlotStatus.MultipleEnabledProfilesMode getSupportedMepMode(int slotIndex) { 1789 synchronized (mLock) { 1790 UiccSlot slot = getUiccSlot(slotIndex); 1791 return slot != null ? slot.getSupportedMepMode() 1792 : IccSlotStatus.MultipleEnabledProfilesMode.NONE; 1793 } 1794 } 1795 1796 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) log(String string)1797 private void log(String string) { 1798 Rlog.d(LOG_TAG, string); 1799 } 1800 logWithLocalLog(String string)1801 private void logWithLocalLog(String string) { 1802 Rlog.d(LOG_TAG, string); 1803 sLocalLog.log("UiccController: " + string); 1804 } 1805 logeWithLocalLog(String string)1806 private void logeWithLocalLog(String string) { 1807 Rlog.e(LOG_TAG, string); 1808 sLocalLog.log("UiccController: " + string); 1809 } 1810 1811 /** The supplied log should also indicate the caller to avoid ambiguity. */ addLocalLog(String data)1812 public static void addLocalLog(String data) { 1813 sLocalLog.log(data); 1814 } 1815 getPrintableCardStrings()1816 private List<String> getPrintableCardStrings() { 1817 if (!ArrayUtils.isEmpty(mCardStrings)) { 1818 return mCardStrings.stream().map(SubscriptionInfo::getPrintableId).collect( 1819 Collectors.toList()); 1820 } 1821 return mCardStrings; 1822 } 1823 1824 /** 1825 * Release resources. Must be called each time this class is used. 1826 */ 1827 @VisibleForTesting dispose()1828 public void dispose() { 1829 for (var slot : mUiccSlots) { 1830 slot.dispose(); 1831 } 1832 mUiccSlots = null; 1833 } 1834 dump(FileDescriptor fd, PrintWriter printWriter, String[] args)1835 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 1836 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 1837 pw.println("mIsCdmaSupported=" + isCdmaSupported(mContext)); 1838 pw.println("mHasBuiltInEuicc=" + mHasBuiltInEuicc); 1839 pw.println("mHasActiveBuiltInEuicc=" + mHasActiveBuiltInEuicc); 1840 pw.println("mCardStrings=" + getPrintableCardStrings()); 1841 pw.println("mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1842 pw.println("mPhoneIdToSlotId=" + Arrays.toString(mPhoneIdToSlotId)); 1843 pw.println("mUseRemovableEsimAsDefault=" + mUseRemovableEsimAsDefault); 1844 pw.println("mUiccSlots: size=" + mUiccSlots.length); 1845 pw.increaseIndent(); 1846 for (int i = 0; i < mUiccSlots.length; i++) { 1847 if (mUiccSlots[i] == null) { 1848 pw.println("mUiccSlots[" + i + "]=null"); 1849 } else { 1850 pw.println("mUiccSlots[" + i + "]:"); 1851 pw.increaseIndent(); 1852 mUiccSlots[i].dump(fd, pw, args); 1853 pw.decreaseIndent(); 1854 } 1855 } 1856 pw.decreaseIndent(); 1857 pw.println(); 1858 mCarrierServiceBindHelper.dump(fd, pw, args); 1859 pw.println(); 1860 pw.println("sLocalLog= "); 1861 pw.increaseIndent(); 1862 mPinStorage.dump(fd, pw, args); 1863 sLocalLog.dump(fd, pw, args); 1864 } 1865 } 1866