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