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