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 mCis[phoneId].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, 601 phoneId)); 602 // slot status should be the same on all RILs; request it only for phoneId 0 603 if (phoneId == 0) { 604 if (DBG) { 605 log("Received EVENT_RADIO_AVAILABLE/EVENT_RADIO_ON for phoneId 0, " 606 + "calling getIccSlotsStatus"); 607 } 608 mRadioConfig.getSimSlotsStatus(obtainMessage(EVENT_GET_SLOT_STATUS_DONE, 609 phoneId)); 610 } 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 if (slot != null) { 808 intent.putExtra(PhoneConstants.PORT_KEY, slot.getPortIndexFromPhoneId(phoneId)); 809 } 810 Rlog.d(LOG_TAG, "Broadcasting intent ACTION_SIM_CARD_STATE_CHANGED " 811 + TelephonyManager.simStateToString(state) + " for phone: " + phoneId 812 + " slot: " + slotId + " port: " + slot.getPortIndexFromPhoneId(phoneId)); 813 mContext.sendBroadcast(intent, Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 814 TelephonyMetrics.getInstance().updateSimState(phoneId, state); 815 } 816 } 817 818 /** 819 * Broadcast SIM application state changed event. 820 * 821 * @param phoneId The phone id. 822 * @param state The SIM application state. 823 */ broadcastSimApplicationStateChanged(int phoneId, @SimState int state)824 private void broadcastSimApplicationStateChanged(int phoneId, @SimState int state) { 825 // Broadcast if the state has changed, except if old state was UNKNOWN and new is NOT_READY, 826 // because that's the initial state and a broadcast should be sent only on a transition 827 // after SIM is PRESENT. The only exception is eSIM boot profile, where NOT_READY is the 828 // terminal state. 829 boolean isUnknownToNotReady = 830 (mSimApplicationState[phoneId] == TelephonyManager.SIM_STATE_UNKNOWN 831 && state == TelephonyManager.SIM_STATE_NOT_READY); 832 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); 833 boolean emptyProfile = iccCard != null && iccCard.isEmptyProfile(); 834 if (state != mSimApplicationState[phoneId] && (!isUnknownToNotReady || emptyProfile)) { 835 mSimApplicationState[phoneId] = state; 836 Intent intent = new Intent(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED); 837 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 838 intent.putExtra(TelephonyManager.EXTRA_SIM_STATE, state); 839 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId); 840 // TODO(b/130664115) we populate this intent with the actual slotId. In the future we 841 // should do a review of whether to make this public 842 UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId); 843 int slotId = UiccController.getInstance().getSlotIdFromPhoneId(phoneId); 844 intent.putExtra(PhoneConstants.SLOT_KEY, slotId); 845 if (slot != null) { 846 intent.putExtra(PhoneConstants.PORT_KEY, slot.getPortIndexFromPhoneId(phoneId)); 847 } 848 Rlog.d(LOG_TAG, "Broadcasting intent ACTION_SIM_APPLICATION_STATE_CHANGED " 849 + TelephonyManager.simStateToString(state) 850 + " for phone: " + phoneId + " slot: " + slotId + "port: " 851 + slot.getPortIndexFromPhoneId(phoneId)); 852 mContext.sendBroadcast(intent, Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 853 TelephonyMetrics.getInstance().updateSimState(phoneId, state); 854 } 855 } 856 857 /** 858 * Get SIM state from SIM lock reason. 859 * 860 * @param lockedReason The SIM lock reason. 861 * 862 * @return The SIM state. 863 */ 864 @SimState getSimStateFromLockedReason(String lockedReason)865 private static int getSimStateFromLockedReason(String lockedReason) { 866 switch (lockedReason) { 867 case IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN: 868 return TelephonyManager.SIM_STATE_PIN_REQUIRED; 869 case IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK: 870 return TelephonyManager.SIM_STATE_PUK_REQUIRED; 871 case IccCardConstants.INTENT_VALUE_LOCKED_NETWORK: 872 return TelephonyManager.SIM_STATE_NETWORK_LOCKED; 873 case IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED: 874 return TelephonyManager.SIM_STATE_PERM_DISABLED; 875 default: 876 Rlog.e(LOG_TAG, "Unexpected SIM locked reason " + lockedReason); 877 return TelephonyManager.SIM_STATE_UNKNOWN; 878 } 879 } 880 881 /** 882 * Broadcast SIM state events. 883 * 884 * @param phoneId The phone id. 885 * @param simState The SIM state. 886 * @param reason SIM state changed reason. 887 */ broadcastSimStateEvents(int phoneId, IccCardConstants.State simState, @Nullable String reason)888 private void broadcastSimStateEvents(int phoneId, IccCardConstants.State simState, 889 @Nullable String reason) { 890 String legacyStringSimState = getIccStateIntentString(simState); 891 int cardState = TelephonyManager.SIM_STATE_UNKNOWN; 892 int applicationState = TelephonyManager.SIM_STATE_UNKNOWN; 893 894 switch (simState) { 895 case ABSENT: 896 cardState = TelephonyManager.SIM_STATE_ABSENT; 897 break; 898 case PIN_REQUIRED: 899 case PUK_REQUIRED: 900 case NETWORK_LOCKED: 901 case PERM_DISABLED: 902 cardState = TelephonyManager.SIM_STATE_PRESENT; 903 applicationState = getSimStateFromLockedReason(reason); 904 break; 905 case READY: 906 case NOT_READY: 907 // Both READY and NOT_READY have the same card state and application state. 908 cardState = TelephonyManager.SIM_STATE_PRESENT; 909 applicationState = TelephonyManager.SIM_STATE_NOT_READY; 910 break; 911 case CARD_IO_ERROR: 912 cardState = TelephonyManager.SIM_STATE_CARD_IO_ERROR; 913 applicationState = TelephonyManager.SIM_STATE_NOT_READY; 914 break; 915 case CARD_RESTRICTED: 916 cardState = TelephonyManager.SIM_STATE_CARD_RESTRICTED; 917 applicationState = TelephonyManager.SIM_STATE_NOT_READY; 918 break; 919 case LOADED: 920 cardState = TelephonyManager.SIM_STATE_PRESENT; 921 applicationState = TelephonyManager.SIM_STATE_LOADED; 922 break; 923 case UNKNOWN: 924 default: 925 break; 926 } 927 928 broadcastSimStateChanged(phoneId, legacyStringSimState, reason); 929 broadcastSimCardStateChanged(phoneId, cardState); 930 broadcastSimApplicationStateChanged(phoneId, applicationState); 931 } 932 933 /** 934 * Update carrier service. 935 * 936 * @param phoneId The phone id. 937 * @param simState The SIM state. 938 */ updateCarrierServices(int phoneId, @NonNull String simState)939 private void updateCarrierServices(int phoneId, @NonNull String simState) { 940 CarrierConfigManager configManager = mContext.getSystemService(CarrierConfigManager.class); 941 if (configManager != null) { 942 configManager.updateConfigForPhoneId(phoneId, simState); 943 } 944 mCarrierServiceBindHelper.updateForPhoneId(phoneId, simState); 945 } 946 947 /** 948 * Update the SIM state. 949 * 950 * @param phoneId Phone id. 951 * @param state SIM state (legacy). 952 * @param reason The reason for SIM state update. 953 */ updateSimState(int phoneId, @NonNull IccCardConstants.State state, @Nullable String reason)954 public void updateSimState(int phoneId, @NonNull IccCardConstants.State state, 955 @Nullable String reason) { 956 post(() -> { 957 log("updateSimState: phoneId=" + phoneId + ", state=" + state + ", reason=" 958 + reason); 959 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 960 Rlog.e(LOG_TAG, "updateSimState: Invalid phone id " + phoneId); 961 return; 962 } 963 964 mTelephonyManager.setSimStateForPhone(phoneId, state.toString()); 965 966 String legacySimState = getIccStateIntentString(state); 967 int simState = state.ordinal(); 968 SubscriptionManagerService.getInstance().updateSimState(phoneId, simState, 969 this::post, 970 () -> { 971 // The following are executed after subscription update completed in 972 // subscription manager service. 973 974 broadcastSimStateEvents(phoneId, state, reason); 975 976 UiccProfile uiccProfile = getUiccProfileForPhone(phoneId); 977 978 if (simState == TelephonyManager.SIM_STATE_READY) { 979 // SIM_STATE_READY is not a final state. 980 return; 981 } 982 983 if (simState == TelephonyManager.SIM_STATE_NOT_READY 984 && (uiccProfile != null && !uiccProfile.isEmptyProfile()) 985 && SubscriptionManagerService.getInstance() 986 .areUiccAppsEnabledOnCard(phoneId)) { 987 // STATE_NOT_READY is not a final state for when both 988 // 1) It's not an empty profile, and 989 // 2) Its uicc applications are set to enabled. 990 // 991 // At this phase, we consider STATE_NOT_READY not a final state, so 992 // return for now. 993 log("updateSimState: SIM_STATE_NOT_READY is not a final " 994 + "state."); 995 return; 996 } 997 998 // At this point, the SIM state must be a final state (meaning we won't 999 // get more SIM state updates). So resolve the carrier id and update the 1000 // carrier services. 1001 log("updateSimState: resolve carrier id and update carrier " 1002 + "services."); 1003 PhoneFactory.getPhone(phoneId).resolveSubscriptionCarrierId( 1004 legacySimState); 1005 updateCarrierServices(phoneId, legacySimState); 1006 } 1007 ); 1008 }); 1009 } 1010 onGetIccCardStatusDone(AsyncResult ar, Integer index)1011 private synchronized void onGetIccCardStatusDone(AsyncResult ar, Integer index) { 1012 if (ar.exception != null) { 1013 Rlog.e(LOG_TAG,"Error getting ICC status. " 1014 + "RIL_REQUEST_GET_ICC_STATUS should " 1015 + "never return an error", ar.exception); 1016 return; 1017 } 1018 if (!isValidPhoneIndex(index)) { 1019 Rlog.e(LOG_TAG,"onGetIccCardStatusDone: invalid index : " + index); 1020 return; 1021 } 1022 if (isShuttingDown()) { 1023 // Do not process the SIM/SLOT events during device shutdown, 1024 // as it may unnecessarily modify the persistent information 1025 // like, SubscriptionManager.UICC_APPLICATIONS_ENABLED. 1026 log("onGetIccCardStatusDone: shudown in progress ignore event"); 1027 return; 1028 } 1029 1030 IccCardStatus status = (IccCardStatus)ar.result; 1031 1032 logWithLocalLog("onGetIccCardStatusDone: phoneId-" + index + " IccCardStatus: " + status); 1033 1034 int slotId = status.mSlotPortMapping.mPhysicalSlotIndex; 1035 if (VDBG) log("onGetIccCardStatusDone: phoneId-" + index + " physicalSlotIndex " + slotId); 1036 if (slotId == INVALID_SLOT_ID) { 1037 slotId = index; 1038 } 1039 1040 if (!mCis[0].supportsEid()) { 1041 // we will never get EID from the HAL, so set mDefaultEuiccCardId to UNSUPPORTED_CARD_ID 1042 if (DBG) log("eid is not supported"); 1043 mDefaultEuiccCardId = UNSUPPORTED_CARD_ID; 1044 } 1045 mPhoneIdToSlotId[index] = slotId; 1046 1047 if (VDBG) logPhoneIdToSlotIdMapping(); 1048 1049 if (mUiccSlots[slotId] == null) { 1050 if (VDBG) { 1051 log("Creating mUiccSlots[" + slotId + "]; mUiccSlots.length = " 1052 + mUiccSlots.length); 1053 } 1054 mUiccSlots[slotId] = new UiccSlot(mContext, true); 1055 } 1056 1057 mUiccSlots[slotId].update(mCis[index], status, index, slotId); 1058 1059 UiccCard card = mUiccSlots[slotId].getUiccCard(); 1060 if (card == null) { 1061 if (DBG) log("mUiccSlots[" + slotId + "] has no card. Notifying IccChangedRegistrants"); 1062 mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 1063 return; 1064 } 1065 1066 UiccPort port = card.getUiccPort(status.mSlotPortMapping.mPortIndex); 1067 if (port == null) { 1068 if (DBG) log("mUiccSlots[" + slotId + "] has no UiccPort with index[" 1069 + status.mSlotPortMapping.mPortIndex + "]. Notifying IccChangedRegistrants"); 1070 mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 1071 return; 1072 } 1073 1074 String cardString = null; 1075 boolean isEuicc = mUiccSlots[slotId].isEuicc(); 1076 if (isEuicc) { 1077 cardString = ((EuiccCard) card).getEid(); 1078 } else { 1079 cardString = card.getUiccPort(status.mSlotPortMapping.mPortIndex).getIccId(); 1080 } 1081 1082 if (cardString != null) { 1083 addCardId(cardString); 1084 } 1085 1086 // EID is unpopulated if Radio HAL < 1.4 (RadioConfig < 1.2) 1087 // If so, just register for EID loaded and skip this stuff 1088 if (isEuicc && mDefaultEuiccCardId != UNSUPPORTED_CARD_ID) { 1089 if (cardString == null) { 1090 ((EuiccCard) card).registerForEidReady(this, EVENT_EID_READY, index); 1091 } else { 1092 // If we know the EID from IccCardStatus, just use it to set mDefaultEuiccCardId if 1093 // it's not already set. 1094 // This is needed in cases where slot status doesn't include EID, and we don't want 1095 // to register for EID from APDU because we already know cardString from a previous 1096 // APDU 1097 if (mDefaultEuiccCardId == UNINITIALIZED_CARD_ID 1098 || mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { 1099 mDefaultEuiccCardId = convertToPublicCardId(cardString); 1100 logWithLocalLog("IccCardStatus eid=" 1101 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, cardString) + " slot=" + slotId 1102 + " mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1103 } 1104 } 1105 } 1106 1107 if (DBG) log("Notifying IccChangedRegistrants"); 1108 mIccChangedRegistrants.notifyRegistrants(new AsyncResult(null, index, null)); 1109 } 1110 1111 /** 1112 * Add a cardString to mCardStrings. If this is an ICCID, trailing Fs will be automatically 1113 * stripped. 1114 */ addCardId(String cardString)1115 private void addCardId(String cardString) { 1116 if (TextUtils.isEmpty(cardString)) { 1117 return; 1118 } 1119 if (cardString.length() < EID_LENGTH) { 1120 cardString = IccUtils.stripTrailingFs(cardString); 1121 } 1122 if (!mCardStrings.contains(cardString)) { 1123 mCardStrings.add(cardString); 1124 saveCardStrings(); 1125 } 1126 } 1127 1128 /** 1129 * Converts an integer cardId (public card ID) to a card string. 1130 * @param cardId to convert 1131 * @return cardString, or null if the cardId is not valid 1132 */ convertToCardString(int cardId)1133 public String convertToCardString(int cardId) { 1134 if (cardId < 0 || cardId >= mCardStrings.size()) { 1135 log("convertToCardString: cardId " + cardId + " is not valid"); 1136 return null; 1137 } 1138 return mCardStrings.get(cardId); 1139 } 1140 1141 /** 1142 * Converts the card string (the ICCID/EID, formerly named card ID) to the public int cardId. 1143 * If the given cardString is an ICCID, trailing Fs will be automatically stripped before trying 1144 * to match to a card ID. 1145 * 1146 * @return the matching cardId, or UNINITIALIZED_CARD_ID if the card string does not map to a 1147 * currently loaded cardId, or UNSUPPORTED_CARD_ID if the device does not support card IDs 1148 */ convertToPublicCardId(String cardString)1149 public int convertToPublicCardId(String cardString) { 1150 if (mDefaultEuiccCardId == UNSUPPORTED_CARD_ID) { 1151 // even if cardString is not an EID, if EID is not supported (e.g. HAL < 1.2) we can't 1152 // guarentee a working card ID implementation, so return UNSUPPORTED_CARD_ID 1153 return UNSUPPORTED_CARD_ID; 1154 } 1155 if (TextUtils.isEmpty(cardString)) { 1156 return UNINITIALIZED_CARD_ID; 1157 } 1158 1159 if (cardString.length() < EID_LENGTH) { 1160 cardString = IccUtils.stripTrailingFs(cardString); 1161 } 1162 int id = mCardStrings.indexOf(cardString); 1163 if (id == -1) { 1164 return UNINITIALIZED_CARD_ID; 1165 } else { 1166 return id; 1167 } 1168 } 1169 1170 /** 1171 * Returns the UiccCardInfo of all currently inserted UICCs and embedded eUICCs. 1172 */ getAllUiccCardInfos()1173 public ArrayList<UiccCardInfo> getAllUiccCardInfos() { 1174 synchronized (mLock) { 1175 ArrayList<UiccCardInfo> infos = new ArrayList<>(); 1176 for (int slotIndex = 0; slotIndex < mUiccSlots.length; slotIndex++) { 1177 final UiccSlot slot = mUiccSlots[slotIndex]; 1178 if (slot == null) continue; 1179 boolean isEuicc = slot.isEuicc(); 1180 String eid = null; 1181 UiccCard card = slot.getUiccCard(); 1182 int cardId = UNINITIALIZED_CARD_ID; 1183 boolean isRemovable = slot.isRemovable(); 1184 1185 // first we try to populate UiccCardInfo using the UiccCard, but if it doesn't exist 1186 // (e.g. the slot is for an inactive eUICC) then we try using the UiccSlot. 1187 if (card != null) { 1188 if (isEuicc) { 1189 eid = ((EuiccCard) card).getEid(); 1190 cardId = convertToPublicCardId(eid); 1191 } else { 1192 // In case of non Euicc, use default port index to get the IccId. 1193 UiccPort port = card.getUiccPort(TelephonyManager.DEFAULT_PORT_INDEX); 1194 if (port == null) { 1195 AnomalyReporter.reportAnomaly( 1196 UUID.fromString("92885ba7-98bb-490a-ba19-987b1c8b2055"), 1197 "UiccController: Found UiccPort Null object."); 1198 } 1199 String iccId = (port != null) ? port.getIccId() : null; 1200 cardId = convertToPublicCardId(iccId); 1201 } 1202 } else { 1203 // This iccid is used for non Euicc only, so use default port index 1204 String iccId = slot.getIccId(TelephonyManager.DEFAULT_PORT_INDEX); 1205 // Fill in the fields we can 1206 if (!isEuicc && !TextUtils.isEmpty(iccId)) { 1207 cardId = convertToPublicCardId(iccId); 1208 } 1209 } 1210 1211 List<UiccPortInfo> portInfos = new ArrayList<>(); 1212 int[] portIndexes = slot.getPortList(); 1213 for (int portIdx : portIndexes) { 1214 String iccId = IccUtils.stripTrailingFs(slot.getIccId(portIdx)); 1215 portInfos.add(new UiccPortInfo(iccId, portIdx, 1216 slot.getPhoneIdFromPortIndex(portIdx), slot.isPortActive(portIdx))); 1217 } 1218 UiccCardInfo info = new UiccCardInfo( 1219 isEuicc, cardId, eid, slotIndex, isRemovable, 1220 slot.isMultipleEnabledProfileSupported(), portInfos); 1221 infos.add(info); 1222 } 1223 return infos; 1224 } 1225 } 1226 1227 /** 1228 * Get the card ID of the default eUICC. 1229 */ getCardIdForDefaultEuicc()1230 public int getCardIdForDefaultEuicc() { 1231 if (mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { 1232 return UNSUPPORTED_CARD_ID; 1233 } 1234 // To support removable eSIM to pass GCT/PTCRB test in DSDS mode, we should make sure all 1235 // the download/activation requests are by default route to the removable eSIM slot. 1236 // To satisfy above condition, we should return removable eSIM cardId as default. 1237 if (mUseRemovableEsimAsDefault && !TelephonyUtils.IS_USER) { 1238 for (UiccSlot slot : mUiccSlots) { 1239 if (slot != null && slot.isRemovable() && slot.isEuicc() && slot.isActive()) { 1240 int cardId = convertToPublicCardId(slot.getEid()); 1241 Rlog.d(LOG_TAG, 1242 "getCardIdForDefaultEuicc: Removable eSIM is default, cardId: " 1243 + cardId); 1244 return cardId; 1245 } 1246 } 1247 Rlog.d(LOG_TAG, "getCardIdForDefaultEuicc: No removable eSIM slot is found"); 1248 } 1249 return mDefaultEuiccCardId; 1250 } 1251 1252 /** Get the {@link PinStorage}. */ getPinStorage()1253 public PinStorage getPinStorage() { 1254 return mPinStorage; 1255 } 1256 loadCardStrings()1257 private ArrayList<String> loadCardStrings() { 1258 String cardStrings = 1259 PreferenceManager.getDefaultSharedPreferences(mContext).getString(CARD_STRINGS, ""); 1260 if (TextUtils.isEmpty(cardStrings)) { 1261 // just return an empty list, since String.split would return the list { "" } 1262 return new ArrayList<String>(); 1263 } 1264 return new ArrayList<String>(Arrays.asList(cardStrings.split(","))); 1265 } 1266 saveCardStrings()1267 private void saveCardStrings() { 1268 SharedPreferences.Editor editor = 1269 PreferenceManager.getDefaultSharedPreferences(mContext).edit(); 1270 editor.putString(CARD_STRINGS, TextUtils.join(",", mCardStrings)); 1271 editor.commit(); 1272 } 1273 onGetSlotStatusDone(AsyncResult ar)1274 private synchronized void onGetSlotStatusDone(AsyncResult ar) { 1275 if (!mIsSlotStatusSupported) { 1276 if (VDBG) log("onGetSlotStatusDone: ignoring since mIsSlotStatusSupported is false"); 1277 return; 1278 } 1279 Throwable e = ar.exception; 1280 if (e != null) { 1281 if (!(e instanceof CommandException) || ((CommandException) e).getCommandError() 1282 != CommandException.Error.REQUEST_NOT_SUPPORTED) { 1283 // this is not expected; there should be no exception other than 1284 // REQUEST_NOT_SUPPORTED 1285 logeWithLocalLog("Unexpected error getting slot status: " + ar.exception); 1286 } else { 1287 // REQUEST_NOT_SUPPORTED 1288 logWithLocalLog("onGetSlotStatusDone: request not supported; marking " 1289 + "mIsSlotStatusSupported to false"); 1290 mIsSlotStatusSupported = false; 1291 } 1292 return; 1293 } 1294 if (isShuttingDown()) { 1295 // Do not process the SIM/SLOT events during device shutdown, 1296 // as it may unnecessarily modify the persistent information 1297 // like, SubscriptionManager.UICC_APPLICATIONS_ENABLED. 1298 log("onGetSlotStatusDone: shudown in progress ignore event"); 1299 return; 1300 } 1301 1302 ArrayList<IccSlotStatus> status = (ArrayList<IccSlotStatus>) ar.result; 1303 1304 if (!slotStatusChanged(status)) { 1305 log("onGetSlotStatusDone: No change in slot status"); 1306 return; 1307 } 1308 logWithLocalLog("onGetSlotStatusDone: " + status); 1309 1310 sLastSlotStatus = status; 1311 1312 int numActivePorts = 0; 1313 boolean isDefaultEuiccCardIdSet = false; 1314 boolean anyEuiccIsActive = false; 1315 mHasActiveBuiltInEuicc = false; 1316 1317 int numSlots = status.size(); 1318 if (mUiccSlots.length < numSlots) { 1319 logeWithLocalLog("The number of the physical slots reported " + numSlots 1320 + " is greater than the expectation " + mUiccSlots.length); 1321 numSlots = mUiccSlots.length; 1322 } 1323 1324 for (int i = 0; i < numSlots; i++) { 1325 IccSlotStatus iss = status.get(i); 1326 boolean isActive = hasActivePort(iss.mSimPortInfos); 1327 if (mUiccSlots[i] == null) { 1328 if (VDBG) { 1329 log("Creating mUiccSlot[" + i + "]; mUiccSlots.length = " + mUiccSlots.length); 1330 } 1331 mUiccSlots[i] = new UiccSlot(mContext, isActive); 1332 } 1333 1334 if (isActive) { // check isActive flag so that we don't have to iterate through all 1335 for (int j = 0; j < iss.mSimPortInfos.length; j++) { 1336 if (iss.mSimPortInfos[j].mPortActive) { 1337 int logicalSlotIndex = iss.mSimPortInfos[j].mLogicalSlotIndex; 1338 // Correctness check: logicalSlotIndex should be valid for an active slot 1339 if (!isValidPhoneIndex(logicalSlotIndex)) { 1340 Rlog.e(LOG_TAG, "Skipping slot " + i + " portIndex " + j + " as phone " 1341 + logicalSlotIndex 1342 + " is not available to communicate with this slot"); 1343 } else { 1344 mPhoneIdToSlotId[logicalSlotIndex] = i; 1345 } 1346 numActivePorts++; 1347 } 1348 } 1349 } 1350 1351 mUiccSlots[i].update(mCis, iss, i); 1352 1353 if (mUiccSlots[i].isEuicc()) { 1354 if (isActive) { 1355 anyEuiccIsActive = true; 1356 1357 if (isBuiltInEuiccSlot(i)) { 1358 mHasActiveBuiltInEuicc = true; 1359 } 1360 } 1361 String eid = iss.eid; 1362 if (TextUtils.isEmpty(eid)) { 1363 // iss.eid is not populated on HAL<1.4 1364 continue; 1365 } 1366 1367 addCardId(eid); 1368 1369 // whenever slot status is received, set default card to the non-removable eUICC 1370 // with the lowest slot index. 1371 if (!mUiccSlots[i].isRemovable() && !isDefaultEuiccCardIdSet) { 1372 isDefaultEuiccCardIdSet = true; 1373 mDefaultEuiccCardId = convertToPublicCardId(eid); 1374 logWithLocalLog("Using eid=" + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, eid) 1375 + " in slot=" + i + " to set mDefaultEuiccCardId=" 1376 + mDefaultEuiccCardId); 1377 } 1378 } 1379 } 1380 1381 if (!mHasActiveBuiltInEuicc && !isDefaultEuiccCardIdSet) { 1382 // if there are no active built-in eUICCs, then consider setting a removable eUICC to 1383 // the default. 1384 // Note that on HAL<1.2, it's possible that a built-in eUICC exists, but does not 1385 // correspond to any slot in mUiccSlots. This logic is still safe in that case because 1386 // SlotStatus is only for HAL >= 1.2 1387 for (int i = 0; i < numSlots; i++) { 1388 if (mUiccSlots[i].isEuicc()) { 1389 String eid = status.get(i).eid; 1390 if (!TextUtils.isEmpty(eid)) { 1391 isDefaultEuiccCardIdSet = true; 1392 mDefaultEuiccCardId = convertToPublicCardId(eid); 1393 logWithLocalLog("Using eid=" 1394 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, eid) 1395 + " from removable eUICC in slot=" + i 1396 + " to set mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1397 break; 1398 } 1399 } 1400 } 1401 } 1402 1403 if (mHasBuiltInEuicc && !anyEuiccIsActive && !isDefaultEuiccCardIdSet) { 1404 logWithLocalLog( 1405 "onGetSlotStatusDone: mDefaultEuiccCardId=TEMPORARILY_UNSUPPORTED_CARD_ID"); 1406 isDefaultEuiccCardIdSet = true; 1407 mDefaultEuiccCardId = TEMPORARILY_UNSUPPORTED_CARD_ID; 1408 } 1409 1410 1411 if (!isDefaultEuiccCardIdSet) { 1412 if (mDefaultEuiccCardId >= 0) { 1413 // if mDefaultEuiccCardId has already been set to an actual eUICC, 1414 // don't overwrite mDefaultEuiccCardId unless that eUICC is no longer inserted 1415 boolean defaultEuiccCardIdIsStillInserted = false; 1416 String cardString = mCardStrings.get(mDefaultEuiccCardId); 1417 for (UiccSlot slot : mUiccSlots) { 1418 if (slot.getUiccCard() == null) { 1419 continue; 1420 } 1421 if (cardString.equals( 1422 IccUtils.stripTrailingFs(slot.getUiccCard().getCardId()))) { 1423 defaultEuiccCardIdIsStillInserted = true; 1424 } 1425 } 1426 if (!defaultEuiccCardIdIsStillInserted) { 1427 logWithLocalLog("onGetSlotStatusDone: mDefaultEuiccCardId=" 1428 + mDefaultEuiccCardId 1429 + " is no longer inserted. Setting mDefaultEuiccCardId=UNINITIALIZED"); 1430 mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; 1431 } 1432 } else { 1433 // no known eUICCs at all (it's possible that an eUICC is inserted and we just don't 1434 // know it's EID) 1435 logWithLocalLog("onGetSlotStatusDone: mDefaultEuiccCardId=UNINITIALIZED"); 1436 mDefaultEuiccCardId = UNINITIALIZED_CARD_ID; 1437 } 1438 } 1439 1440 if (VDBG) logPhoneIdToSlotIdMapping(); 1441 1442 // Correctness check: number of active ports should be valid 1443 if (numActivePorts != mPhoneIdToSlotId.length) { 1444 Rlog.e(LOG_TAG, "Number of active ports " + numActivePorts 1445 + " does not match the number of Phones" + mPhoneIdToSlotId.length); 1446 } 1447 1448 // broadcast slot status changed 1449 final BroadcastOptions options = BroadcastOptions.makeBasic(); 1450 options.setBackgroundActivityStartsAllowed(true); 1451 Intent intent = new Intent(TelephonyManager.ACTION_SIM_SLOT_STATUS_CHANGED); 1452 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1453 mContext.sendBroadcast(intent, android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1454 options.toBundle()); 1455 } 1456 hasActivePort(IccSimPortInfo[] simPortInfos)1457 private boolean hasActivePort(IccSimPortInfo[] simPortInfos) { 1458 for (IccSimPortInfo simPortInfo : simPortInfos) { 1459 if (simPortInfo.mPortActive) { 1460 return true; 1461 } 1462 } 1463 return false; 1464 } 1465 1466 /** 1467 * Check if slot status has changed from the last received one 1468 */ 1469 @VisibleForTesting slotStatusChanged(ArrayList<IccSlotStatus> slotStatusList)1470 public boolean slotStatusChanged(ArrayList<IccSlotStatus> slotStatusList) { 1471 if (sLastSlotStatus == null || sLastSlotStatus.size() != slotStatusList.size()) { 1472 return true; 1473 } 1474 for (int i = 0; i < slotStatusList.size(); i++) { 1475 if (!sLastSlotStatus.get(i).equals(slotStatusList.get(i))) { 1476 return true; 1477 } 1478 } 1479 return false; 1480 } 1481 logPhoneIdToSlotIdMapping()1482 private void logPhoneIdToSlotIdMapping() { 1483 log("mPhoneIdToSlotId mapping:"); 1484 for (int i = 0; i < mPhoneIdToSlotId.length; i++) { 1485 log(" phoneId " + i + " slotId " + mPhoneIdToSlotId[i]); 1486 } 1487 } 1488 onSimRefresh(AsyncResult ar, Integer index)1489 private void onSimRefresh(AsyncResult ar, Integer index) { 1490 if (ar.exception != null) { 1491 Rlog.e(LOG_TAG, "onSimRefresh: Sim REFRESH with exception: " + ar.exception); 1492 return; 1493 } 1494 1495 if (!isValidPhoneIndex(index)) { 1496 Rlog.e(LOG_TAG,"onSimRefresh: invalid index : " + index); 1497 return; 1498 } 1499 1500 IccRefreshResponse resp = (IccRefreshResponse) ar.result; 1501 logWithLocalLog("onSimRefresh: index " + index + ", " + resp); 1502 1503 if (resp == null) { 1504 Rlog.e(LOG_TAG, "onSimRefresh: received without input"); 1505 return; 1506 } 1507 1508 UiccCard uiccCard = getUiccCardForPhone(index); 1509 if (uiccCard == null) { 1510 Rlog.e(LOG_TAG,"onSimRefresh: refresh on null card : " + index); 1511 return; 1512 } 1513 1514 UiccPort uiccPort = getUiccPortForPhone(index); 1515 if (uiccPort == null) { 1516 Rlog.e(LOG_TAG, "onSimRefresh: refresh on null port : " + index); 1517 return; 1518 } 1519 1520 boolean changed = false; 1521 switch(resp.refreshResult) { 1522 // Reset the required apps when we know about the refresh so that 1523 // anyone interested does not get stale state. 1524 case IccRefreshResponse.REFRESH_RESULT_RESET: 1525 changed = uiccPort.resetAppWithAid(resp.aid, true /* reset */); 1526 break; 1527 case IccRefreshResponse.REFRESH_RESULT_INIT: 1528 // don't dispose CatService on SIM REFRESH of type INIT 1529 changed = uiccPort.resetAppWithAid(resp.aid, false /* initialize */); 1530 break; 1531 default: 1532 return; 1533 } 1534 1535 if (changed && resp.refreshResult == IccRefreshResponse.REFRESH_RESULT_RESET) { 1536 // If there is any change on RESET, reset carrier config as well. From carrier config 1537 // perspective, this is treated the same as sim state unknown 1538 CarrierConfigManager configManager = (CarrierConfigManager) 1539 mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1540 configManager.updateConfigForPhoneId(index, IccCardConstants.INTENT_VALUE_ICC_UNKNOWN); 1541 } 1542 1543 // The card status could have changed. Get the latest state. 1544 mCis[index].getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, index)); 1545 } 1546 1547 // for HAL 1.2-1.3 we register for EID ready, set mCardStrings and mDefaultEuiccCardId here. 1548 // Note that if there are multiple eUICCs on HAL 1.2-1.3, the default eUICC is the one whose EID 1549 // is first loaded onEidReady(AsyncResult ar, Integer index)1550 private void onEidReady(AsyncResult ar, Integer index) { 1551 if (ar.exception != null) { 1552 Rlog.e(LOG_TAG, "onEidReady: exception: " + ar.exception); 1553 return; 1554 } 1555 1556 if (!isValidPhoneIndex(index)) { 1557 Rlog.e(LOG_TAG, "onEidReady: invalid index: " + index); 1558 return; 1559 } 1560 int slotId = mPhoneIdToSlotId[index]; 1561 EuiccCard card = (EuiccCard) mUiccSlots[slotId].getUiccCard(); 1562 if (card == null) { 1563 Rlog.e(LOG_TAG, "onEidReady: UiccCard in slot " + slotId + " is null"); 1564 return; 1565 } 1566 1567 // set mCardStrings and the defaultEuiccCardId using the now available EID 1568 String eid = card.getEid(); 1569 addCardId(eid); 1570 if (mDefaultEuiccCardId == UNINITIALIZED_CARD_ID 1571 || mDefaultEuiccCardId == TEMPORARILY_UNSUPPORTED_CARD_ID) { 1572 if (!mUiccSlots[slotId].isRemovable()) { 1573 mDefaultEuiccCardId = convertToPublicCardId(eid); 1574 logWithLocalLog("onEidReady: eid=" 1575 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, eid) 1576 + " slot=" + slotId + " mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1577 } else if (!mHasActiveBuiltInEuicc) { 1578 // we only set a removable eUICC to the default if there are no active non-removable 1579 // eUICCs 1580 mDefaultEuiccCardId = convertToPublicCardId(eid); 1581 logWithLocalLog("onEidReady: eid=" 1582 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, eid) 1583 + " from removable eUICC in slot=" + slotId + " mDefaultEuiccCardId=" 1584 + mDefaultEuiccCardId); 1585 } 1586 } 1587 card.unregisterForEidReady(this); 1588 } 1589 1590 // Return true if the device has at least one built in eUICC based on the resource overlay hasBuiltInEuicc()1591 private boolean hasBuiltInEuicc() { 1592 return mEuiccSlots != null && mEuiccSlots.length > 0; 1593 } 1594 isBuiltInEuiccSlot(int slotIndex)1595 private boolean isBuiltInEuiccSlot(int slotIndex) { 1596 if (!mHasBuiltInEuicc) { 1597 return false; 1598 } 1599 for (int slot : mEuiccSlots) { 1600 if (slot == slotIndex) { 1601 return true; 1602 } 1603 } 1604 return false; 1605 } 1606 1607 /** 1608 * static method to return whether CDMA is supported on the device 1609 * @param context object representative of the application that is calling this method 1610 * @return true if CDMA is supported by the device 1611 */ isCdmaSupported(Context context)1612 public static boolean isCdmaSupported(Context context) { 1613 PackageManager packageManager = context.getPackageManager(); 1614 boolean isCdmaSupported = 1615 packageManager.hasSystemFeature(PackageManager.FEATURE_TELEPHONY_CDMA); 1616 return isCdmaSupported; 1617 } 1618 isValidPhoneIndex(int index)1619 private boolean isValidPhoneIndex(int index) { 1620 return (index >= 0 && index < TelephonyManager.getDefault().getPhoneCount()); 1621 } 1622 isValidSlotIndex(int index)1623 private boolean isValidSlotIndex(int index) { 1624 return (index >= 0 && index < mUiccSlots.length); 1625 } 1626 isShuttingDown()1627 private boolean isShuttingDown() { 1628 for (int i = 0; i < TelephonyManager.getDefault().getActiveModemCount(); i++) { 1629 if (PhoneFactory.getPhone(i) != null && 1630 PhoneFactory.getPhone(i).isShuttingDown()) { 1631 return true; 1632 } 1633 } 1634 return false; 1635 } 1636 iccidMatches(String mvnoData, String iccId)1637 private static boolean iccidMatches(String mvnoData, String iccId) { 1638 String[] mvnoIccidList = mvnoData.split(","); 1639 for (String mvnoIccid : mvnoIccidList) { 1640 if (iccId.startsWith(mvnoIccid)) { 1641 Log.d(LOG_TAG, "mvno icc id match found"); 1642 return true; 1643 } 1644 } 1645 return false; 1646 } 1647 imsiMatches(String imsiDB, String imsiSIM)1648 private static boolean imsiMatches(String imsiDB, String imsiSIM) { 1649 // Note: imsiDB value has digit number or 'x' character for separating USIM information 1650 // for MVNO operator. And then digit number is matched at same order and 'x' character 1651 // could replace by any digit number. 1652 // ex) if imsiDB inserted '310260x10xxxxxx' for GG Operator, 1653 // that means first 6 digits, 8th and 9th digit 1654 // should be set in USIM for GG Operator. 1655 int len = imsiDB.length(); 1656 1657 if (len <= 0) return false; 1658 if (len > imsiSIM.length()) return false; 1659 1660 for (int idx = 0; idx < len; idx++) { 1661 char c = imsiDB.charAt(idx); 1662 if ((c == 'x') || (c == 'X') || (c == imsiSIM.charAt(idx))) { 1663 continue; 1664 } else { 1665 return false; 1666 } 1667 } 1668 return true; 1669 } 1670 1671 /** 1672 * Check if MVNO type and data match IccRecords. 1673 * 1674 * @param slotIndex SIM slot index. 1675 * @param mvnoType the MVNO type 1676 * @param mvnoMatchData the MVNO match data 1677 * @return {@code true} if MVNO type and data match IccRecords, {@code false} otherwise. 1678 */ mvnoMatches(int slotIndex, int mvnoType, String mvnoMatchData)1679 public boolean mvnoMatches(int slotIndex, int mvnoType, String mvnoMatchData) { 1680 IccRecords iccRecords = getIccRecords(slotIndex, UiccController.APP_FAM_3GPP); 1681 if (iccRecords == null) { 1682 Log.d(LOG_TAG, "isMvnoMatched# IccRecords is null"); 1683 return false; 1684 } 1685 if (mvnoType == ApnSetting.MVNO_TYPE_SPN) { 1686 String spn = iccRecords.getServiceProviderNameWithBrandOverride(); 1687 if ((spn != null) && spn.equalsIgnoreCase(mvnoMatchData)) { 1688 return true; 1689 } 1690 } else if (mvnoType == ApnSetting.MVNO_TYPE_IMSI) { 1691 String imsiSIM = iccRecords.getIMSI(); 1692 if ((imsiSIM != null) && imsiMatches(mvnoMatchData, imsiSIM)) { 1693 return true; 1694 } 1695 } else if (mvnoType == ApnSetting.MVNO_TYPE_GID) { 1696 String gid1 = iccRecords.getGid1(); 1697 int mvno_match_data_length = mvnoMatchData.length(); 1698 if ((gid1 != null) && (gid1.length() >= mvno_match_data_length) 1699 && gid1.substring(0, mvno_match_data_length).equalsIgnoreCase(mvnoMatchData)) { 1700 return true; 1701 } 1702 } else if (mvnoType == ApnSetting.MVNO_TYPE_ICCID) { 1703 String iccId = iccRecords.getIccId(); 1704 if ((iccId != null) && iccidMatches(mvnoMatchData, iccId)) { 1705 return true; 1706 } 1707 } 1708 1709 return false; 1710 } 1711 1712 /** 1713 * Set removable eSIM as default. 1714 * This API is added for test purpose to set removable eSIM as default eUICC. 1715 * @param isDefault Flag to set removable eSIM as default or not. 1716 */ setRemovableEsimAsDefaultEuicc(boolean isDefault)1717 public void setRemovableEsimAsDefaultEuicc(boolean isDefault) { 1718 mUseRemovableEsimAsDefault = isDefault; 1719 SharedPreferences.Editor editor = 1720 PreferenceManager.getDefaultSharedPreferences(mContext).edit(); 1721 editor.putBoolean(REMOVABLE_ESIM_AS_DEFAULT, isDefault); 1722 editor.apply(); 1723 Rlog.d(LOG_TAG, "setRemovableEsimAsDefaultEuicc isDefault: " + isDefault); 1724 } 1725 1726 /** 1727 * Returns whether the removable eSIM is default eUICC or not. 1728 * This API is added for test purpose to check whether removable eSIM is default eUICC or not. 1729 */ isRemovableEsimDefaultEuicc()1730 public boolean isRemovableEsimDefaultEuicc() { 1731 Rlog.d(LOG_TAG, "mUseRemovableEsimAsDefault: " + mUseRemovableEsimAsDefault); 1732 return mUseRemovableEsimAsDefault; 1733 } 1734 1735 /** 1736 * Returns the MEP mode supported by the UiccSlot associated with slotIndex. 1737 * @param slotIndex physical slot index 1738 * @return MultipleEnabledProfilesMode supported by the slot 1739 */ getSupportedMepMode(int slotIndex)1740 public IccSlotStatus.MultipleEnabledProfilesMode getSupportedMepMode(int slotIndex) { 1741 synchronized (mLock) { 1742 UiccSlot slot = getUiccSlot(slotIndex); 1743 return slot != null ? slot.getSupportedMepMode() 1744 : IccSlotStatus.MultipleEnabledProfilesMode.NONE; 1745 } 1746 } 1747 1748 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) log(String string)1749 private void log(String string) { 1750 Rlog.d(LOG_TAG, string); 1751 } 1752 logWithLocalLog(String string)1753 private void logWithLocalLog(String string) { 1754 Rlog.d(LOG_TAG, string); 1755 sLocalLog.log("UiccController: " + string); 1756 } 1757 logeWithLocalLog(String string)1758 private void logeWithLocalLog(String string) { 1759 Rlog.e(LOG_TAG, string); 1760 sLocalLog.log("UiccController: " + string); 1761 } 1762 1763 /** The supplied log should also indicate the caller to avoid ambiguity. */ addLocalLog(String data)1764 public static void addLocalLog(String data) { 1765 sLocalLog.log(data); 1766 } 1767 getPrintableCardStrings()1768 private List<String> getPrintableCardStrings() { 1769 if (!ArrayUtils.isEmpty(mCardStrings)) { 1770 return mCardStrings.stream().map(SubscriptionInfo::getPrintableId).collect( 1771 Collectors.toList()); 1772 } 1773 return mCardStrings; 1774 } 1775 dump(FileDescriptor fd, PrintWriter printWriter, String[] args)1776 public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) { 1777 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 1778 pw.println("mIsCdmaSupported=" + isCdmaSupported(mContext)); 1779 pw.println("mHasBuiltInEuicc=" + mHasBuiltInEuicc); 1780 pw.println("mHasActiveBuiltInEuicc=" + mHasActiveBuiltInEuicc); 1781 pw.println("mCardStrings=" + getPrintableCardStrings()); 1782 pw.println("mDefaultEuiccCardId=" + mDefaultEuiccCardId); 1783 pw.println("mPhoneIdToSlotId=" + Arrays.toString(mPhoneIdToSlotId)); 1784 pw.println("mUseRemovableEsimAsDefault=" + mUseRemovableEsimAsDefault); 1785 pw.println("mUiccSlots: size=" + mUiccSlots.length); 1786 pw.increaseIndent(); 1787 for (int i = 0; i < mUiccSlots.length; i++) { 1788 if (mUiccSlots[i] == null) { 1789 pw.println("mUiccSlots[" + i + "]=null"); 1790 } else { 1791 pw.println("mUiccSlots[" + i + "]:"); 1792 pw.increaseIndent(); 1793 mUiccSlots[i].dump(fd, pw, args); 1794 pw.decreaseIndent(); 1795 } 1796 } 1797 pw.decreaseIndent(); 1798 pw.println(); 1799 pw.println("sLocalLog= "); 1800 pw.increaseIndent(); 1801 mPinStorage.dump(fd, pw, args); 1802 sLocalLog.dump(fd, pw, args); 1803 } 1804 } 1805