1 /* 2 * Copyright (C) 2014 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; 18 19 import android.Manifest; 20 import android.annotation.Nullable; 21 import android.app.ActivityManager; 22 import android.compat.annotation.UnsupportedAppUsage; 23 import android.content.BroadcastReceiver; 24 import android.content.ContentResolver; 25 import android.content.ContentValues; 26 import android.content.Context; 27 import android.content.Intent; 28 import android.content.IntentFilter; 29 import android.content.SharedPreferences; 30 import android.os.AsyncResult; 31 import android.os.Build; 32 import android.os.Handler; 33 import android.os.Looper; 34 import android.os.Message; 35 import android.os.ParcelUuid; 36 import android.os.PersistableBundle; 37 import android.os.UserHandle; 38 import android.preference.PreferenceManager; 39 import android.service.carrier.CarrierIdentifier; 40 import android.service.carrier.CarrierService; 41 import android.service.euicc.EuiccProfileInfo; 42 import android.service.euicc.EuiccService; 43 import android.service.euicc.GetEuiccProfileInfoListResult; 44 import android.telephony.CarrierConfigManager; 45 import android.telephony.SubscriptionInfo; 46 import android.telephony.SubscriptionManager; 47 import android.telephony.TelephonyManager; 48 import android.telephony.TelephonyManager.SimState; 49 import android.telephony.UiccAccessRule; 50 import android.telephony.euicc.EuiccManager; 51 import android.text.TextUtils; 52 import android.util.Pair; 53 54 import com.android.internal.annotations.VisibleForTesting; 55 import com.android.internal.telephony.euicc.EuiccController; 56 import com.android.internal.telephony.metrics.TelephonyMetrics; 57 import com.android.internal.telephony.uicc.IccRecords; 58 import com.android.internal.telephony.uicc.IccUtils; 59 import com.android.internal.telephony.uicc.UiccCard; 60 import com.android.internal.telephony.uicc.UiccController; 61 import com.android.internal.telephony.uicc.UiccSlot; 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.List; 68 69 /** 70 *@hide 71 */ 72 public class SubscriptionInfoUpdater extends Handler { 73 private static final String LOG_TAG = "SubscriptionInfoUpdater"; 74 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 75 private static final int SUPPORTED_MODEM_COUNT = TelephonyManager.getDefault() 76 .getSupportedModemCount(); 77 78 private static final boolean DBG = true; 79 80 private static final int EVENT_INVALID = -1; 81 private static final int EVENT_GET_NETWORK_SELECTION_MODE_DONE = 2; 82 private static final int EVENT_SIM_LOADED = 3; 83 private static final int EVENT_SIM_ABSENT = 4; 84 private static final int EVENT_SIM_LOCKED = 5; 85 private static final int EVENT_SIM_IO_ERROR = 6; 86 private static final int EVENT_SIM_UNKNOWN = 7; 87 private static final int EVENT_SIM_RESTRICTED = 8; 88 private static final int EVENT_SIM_NOT_READY = 9; 89 private static final int EVENT_SIM_READY = 10; 90 private static final int EVENT_SIM_IMSI = 11; 91 private static final int EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS = 12; 92 private static final int EVENT_MULTI_SIM_CONFIG_CHANGED = 13; 93 private static final int EVENT_INACTIVE_SLOT_ICC_STATE_CHANGED = 14; 94 95 private static final String ICCID_STRING_FOR_NO_SIM = ""; 96 97 private static final ParcelUuid REMOVE_GROUP_UUID = 98 ParcelUuid.fromString(CarrierConfigManager.REMOVE_GROUP_UUID_STRING); 99 100 // Key used to read/write the current IMSI. Updated on SIM_STATE_CHANGED - LOADED. 101 public static final String CURR_SUBID = "curr_subid"; 102 103 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 104 private static Context sContext = null; 105 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 106 107 protected static String[] sIccId = new String[SUPPORTED_MODEM_COUNT]; 108 protected SubscriptionController mSubscriptionController = null; 109 private static String[] sInactiveIccIds = new String[SUPPORTED_MODEM_COUNT]; 110 private static int[] sSimCardState = new int[SUPPORTED_MODEM_COUNT]; 111 private static int[] sSimApplicationState = new int[SUPPORTED_MODEM_COUNT]; 112 private static boolean sIsSubInfoInitialized = false; 113 private SubscriptionManager mSubscriptionManager = null; 114 private EuiccManager mEuiccManager; 115 private Handler mBackgroundHandler; 116 117 // The current foreground user ID. 118 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 119 private int mCurrentlyActiveUserId; 120 private CarrierServiceBindHelper mCarrierServiceBindHelper; 121 122 /** 123 * Runnable with a boolean parameter. This is used in 124 * updateEmbeddedSubscriptions(List<Integer> cardIds, @Nullable UpdateEmbeddedSubsCallback). 125 */ 126 protected interface UpdateEmbeddedSubsCallback { 127 /** 128 * Callback of the Runnable. 129 * @param hasChanges Whether there is any subscription info change. If yes, we need to 130 * notify the listeners. 131 */ run(boolean hasChanges)132 void run(boolean hasChanges); 133 } 134 135 @VisibleForTesting SubscriptionInfoUpdater(Looper looper, Context context, SubscriptionController sc)136 public SubscriptionInfoUpdater(Looper looper, Context context, SubscriptionController sc) { 137 logd("Constructor invoked"); 138 mBackgroundHandler = new Handler(looper); 139 140 sContext = context; 141 mSubscriptionController = sc; 142 mSubscriptionManager = SubscriptionManager.from(sContext); 143 mEuiccManager = (EuiccManager) sContext.getSystemService(Context.EUICC_SERVICE); 144 145 mCarrierServiceBindHelper = new CarrierServiceBindHelper(sContext); 146 initializeCarrierApps(); 147 148 PhoneConfigurationManager.registerForMultiSimConfigChange( 149 this, EVENT_MULTI_SIM_CONFIG_CHANGED, null); 150 } 151 initializeCarrierApps()152 private void initializeCarrierApps() { 153 // Initialize carrier apps: 154 // -Now (on system startup) 155 // -Whenever new carrier privilege rules might change (new SIM is loaded) 156 // -Whenever we switch to a new user 157 mCurrentlyActiveUserId = 0; 158 sContext.registerReceiverForAllUsers(new BroadcastReceiver() { 159 @Override 160 public void onReceive(Context context, Intent intent) { 161 // Remove this line after testing 162 if (Intent.ACTION_USER_FOREGROUND.equals(intent.getAction())) { 163 UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER); 164 // If couldn't get current user ID, guess it's 0. 165 mCurrentlyActiveUserId = userHandle != null ? userHandle.getIdentifier() : 0; 166 CarrierAppUtils.disableCarrierAppsUntilPrivileged(sContext.getOpPackageName(), 167 TelephonyManager.getDefault(), mCurrentlyActiveUserId, sContext); 168 } 169 } 170 }, new IntentFilter(Intent.ACTION_USER_FOREGROUND), null, null); 171 ActivityManager am = (ActivityManager) sContext.getSystemService(Context.ACTIVITY_SERVICE); 172 mCurrentlyActiveUserId = am.getCurrentUser(); 173 CarrierAppUtils.disableCarrierAppsUntilPrivileged(sContext.getOpPackageName(), 174 TelephonyManager.getDefault(), mCurrentlyActiveUserId, sContext); 175 } 176 177 /** 178 * Update subscriptions when given a new ICC state. 179 */ updateInternalIccState(String simStatus, String reason, int phoneId)180 public void updateInternalIccState(String simStatus, String reason, int phoneId) { 181 logd("updateInternalIccState to simStatus " + simStatus + " reason " + reason 182 + " phoneId " + phoneId); 183 int message = internalIccStateToMessage(simStatus); 184 if (message != EVENT_INVALID) { 185 sendMessage(obtainMessage(message, phoneId, 0, reason)); 186 } 187 } 188 189 /** 190 * Update subscriptions if needed when there's a change in inactive slot. 191 * @param prevActivePhoneId is the corresponding phoneId of the slot if slot was previously 192 * active. It could be INVALID if it was already inactive. 193 * @param iccId iccId in that slot, if any. 194 */ updateInternalIccStateForInactiveSlot(int prevActivePhoneId, String iccId)195 public void updateInternalIccStateForInactiveSlot(int prevActivePhoneId, String iccId) { 196 sendMessage(obtainMessage(EVENT_INACTIVE_SLOT_ICC_STATE_CHANGED, prevActivePhoneId, 197 0, iccId)); 198 } 199 internalIccStateToMessage(String simStatus)200 private int internalIccStateToMessage(String simStatus) { 201 switch(simStatus) { 202 case IccCardConstants.INTENT_VALUE_ICC_ABSENT: return EVENT_SIM_ABSENT; 203 case IccCardConstants.INTENT_VALUE_ICC_UNKNOWN: return EVENT_SIM_UNKNOWN; 204 case IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR: return EVENT_SIM_IO_ERROR; 205 case IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED: return EVENT_SIM_RESTRICTED; 206 case IccCardConstants.INTENT_VALUE_ICC_NOT_READY: return EVENT_SIM_NOT_READY; 207 case IccCardConstants.INTENT_VALUE_ICC_LOCKED: return EVENT_SIM_LOCKED; 208 case IccCardConstants.INTENT_VALUE_ICC_LOADED: return EVENT_SIM_LOADED; 209 case IccCardConstants.INTENT_VALUE_ICC_READY: return EVENT_SIM_READY; 210 case IccCardConstants.INTENT_VALUE_ICC_IMSI: return EVENT_SIM_IMSI; 211 default: 212 logd("Ignoring simStatus: " + simStatus); 213 return EVENT_INVALID; 214 } 215 } 216 217 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isAllIccIdQueryDone()218 protected boolean isAllIccIdQueryDone() { 219 for (int i = 0; i < TelephonyManager.getDefault().getActiveModemCount(); i++) { 220 UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(i); 221 int slotId = UiccController.getInstance().getSlotIdFromPhoneId(i); 222 if (sIccId[i] == null || slot == null || !slot.isActive()) { 223 if (sIccId[i] == null) { 224 logd("Wait for SIM " + i + " Iccid"); 225 } else { 226 logd(String.format("Wait for slot corresponding to phone %d to be active, " 227 + "slotId is %d", i, slotId)); 228 } 229 return false; 230 } 231 } 232 logd("All IccIds query complete"); 233 234 return true; 235 } 236 237 @Override handleMessage(Message msg)238 public void handleMessage(Message msg) { 239 List<Integer> cardIds = new ArrayList<>(); 240 switch (msg.what) { 241 case EVENT_GET_NETWORK_SELECTION_MODE_DONE: { 242 AsyncResult ar = (AsyncResult)msg.obj; 243 Integer slotId = (Integer)ar.userObj; 244 if (ar.exception == null && ar.result != null) { 245 int[] modes = (int[])ar.result; 246 if (modes[0] == 1) { // Manual mode. 247 PhoneFactory.getPhone(slotId).setNetworkSelectionModeAutomatic(null); 248 } 249 } else { 250 logd("EVENT_GET_NETWORK_SELECTION_MODE_DONE: error getting network mode."); 251 } 252 break; 253 } 254 255 case EVENT_SIM_LOADED: 256 handleSimLoaded(msg.arg1); 257 break; 258 259 case EVENT_SIM_ABSENT: 260 handleSimAbsent(msg.arg1); 261 break; 262 263 case EVENT_INACTIVE_SLOT_ICC_STATE_CHANGED: 264 handleInactiveSlotIccStateChange(msg.arg1, (String) msg.obj); 265 break; 266 267 case EVENT_SIM_LOCKED: 268 handleSimLocked(msg.arg1, (String) msg.obj); 269 break; 270 271 case EVENT_SIM_UNKNOWN: 272 broadcastSimStateChanged(msg.arg1, IccCardConstants.INTENT_VALUE_ICC_UNKNOWN, null); 273 broadcastSimCardStateChanged(msg.arg1, TelephonyManager.SIM_STATE_UNKNOWN); 274 broadcastSimApplicationStateChanged(msg.arg1, TelephonyManager.SIM_STATE_UNKNOWN); 275 updateSubscriptionCarrierId(msg.arg1, IccCardConstants.INTENT_VALUE_ICC_UNKNOWN); 276 updateCarrierServices(msg.arg1, IccCardConstants.INTENT_VALUE_ICC_UNKNOWN); 277 break; 278 279 case EVENT_SIM_IO_ERROR: 280 handleSimError(msg.arg1); 281 break; 282 283 case EVENT_SIM_RESTRICTED: 284 broadcastSimStateChanged(msg.arg1, 285 IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED, 286 IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED); 287 broadcastSimCardStateChanged(msg.arg1, TelephonyManager.SIM_STATE_CARD_RESTRICTED); 288 broadcastSimApplicationStateChanged(msg.arg1, TelephonyManager.SIM_STATE_NOT_READY); 289 updateSubscriptionCarrierId(msg.arg1, 290 IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED); 291 updateCarrierServices(msg.arg1, IccCardConstants.INTENT_VALUE_ICC_CARD_RESTRICTED); 292 break; 293 294 case EVENT_SIM_READY: 295 handleSimReady(msg.arg1); 296 break; 297 298 case EVENT_SIM_IMSI: 299 broadcastSimStateChanged(msg.arg1, IccCardConstants.INTENT_VALUE_ICC_IMSI, null); 300 break; 301 302 case EVENT_SIM_NOT_READY: 303 // an eUICC with no active subscriptions never becomes ready, so we need to trigger 304 // the embedded subscriptions update here 305 cardIds.add(getCardIdFromPhoneId(msg.arg1)); 306 updateEmbeddedSubscriptions(cardIds, (hasChanges) -> { 307 if (hasChanges) { 308 mSubscriptionController.notifySubscriptionInfoChanged(); 309 } 310 }); 311 handleSimNotReady(msg.arg1); 312 break; 313 314 case EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS: 315 cardIds.add(msg.arg1); 316 Runnable r = (Runnable) msg.obj; 317 updateEmbeddedSubscriptions(cardIds, (hasChanges) -> { 318 if (hasChanges) { 319 mSubscriptionController.notifySubscriptionInfoChanged(); 320 } 321 if (r != null) { 322 r.run(); 323 } 324 }); 325 break; 326 327 case EVENT_MULTI_SIM_CONFIG_CHANGED: 328 onMultiSimConfigChanged(); 329 break; 330 331 default: 332 logd("Unknown msg:" + msg.what); 333 } 334 } 335 onMultiSimConfigChanged()336 private void onMultiSimConfigChanged() { 337 int activeModemCount = ((TelephonyManager) sContext.getSystemService( 338 Context.TELEPHONY_SERVICE)).getActiveModemCount(); 339 // For inactive modems, reset its states. 340 for (int phoneId = activeModemCount; phoneId < SUPPORTED_MODEM_COUNT; phoneId++) { 341 sIccId[phoneId] = null; 342 sSimCardState[phoneId] = TelephonyManager.SIM_STATE_UNKNOWN; 343 sSimApplicationState[phoneId] = TelephonyManager.SIM_STATE_UNKNOWN; 344 } 345 } 346 getCardIdFromPhoneId(int phoneId)347 protected int getCardIdFromPhoneId(int phoneId) { 348 UiccController uiccController = UiccController.getInstance(); 349 UiccCard card = uiccController.getUiccCardForPhone(phoneId); 350 if (card != null) { 351 return uiccController.convertToPublicCardId(card.getCardId()); 352 } 353 return TelephonyManager.UNINITIALIZED_CARD_ID; 354 } 355 requestEmbeddedSubscriptionInfoListRefresh(int cardId, @Nullable Runnable callback)356 void requestEmbeddedSubscriptionInfoListRefresh(int cardId, @Nullable Runnable callback) { 357 sendMessage(obtainMessage( 358 EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS, cardId, 0 /* arg2 */, callback)); 359 } 360 handleSimLocked(int phoneId, String reason)361 protected void handleSimLocked(int phoneId, String reason) { 362 if (sIccId[phoneId] != null && sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) { 363 logd("SIM" + (phoneId + 1) + " hot plug in"); 364 sIccId[phoneId] = null; 365 } 366 367 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); 368 if (iccCard == null) { 369 logd("handleSimLocked: IccCard null"); 370 return; 371 } 372 IccRecords records = iccCard.getIccRecords(); 373 if (records == null) { 374 logd("handleSimLocked: IccRecords null"); 375 return; 376 } 377 if (IccUtils.stripTrailingFs(records.getFullIccId()) == null) { 378 logd("handleSimLocked: IccID null"); 379 return; 380 } 381 sIccId[phoneId] = IccUtils.stripTrailingFs(records.getFullIccId()); 382 383 updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */); 384 385 broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOCKED, reason); 386 broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT); 387 broadcastSimApplicationStateChanged(phoneId, getSimStateFromLockedReason(reason)); 388 updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOCKED); 389 updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOCKED); 390 } 391 getSimStateFromLockedReason(String lockedReason)392 private static int getSimStateFromLockedReason(String lockedReason) { 393 switch (lockedReason) { 394 case IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN: 395 return TelephonyManager.SIM_STATE_PIN_REQUIRED; 396 case IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK: 397 return TelephonyManager.SIM_STATE_PUK_REQUIRED; 398 case IccCardConstants.INTENT_VALUE_LOCKED_NETWORK: 399 return TelephonyManager.SIM_STATE_NETWORK_LOCKED; 400 case IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED: 401 return TelephonyManager.SIM_STATE_PERM_DISABLED; 402 default: 403 Rlog.e(LOG_TAG, "Unexpected SIM locked reason " + lockedReason); 404 return TelephonyManager.SIM_STATE_UNKNOWN; 405 } 406 } 407 handleSimReady(int phoneId)408 protected void handleSimReady(int phoneId) { 409 List<Integer> cardIds = new ArrayList<>(); 410 logd("handleSimReady: phoneId: " + phoneId); 411 412 if (sIccId[phoneId] != null && sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) { 413 logd(" SIM" + (phoneId + 1) + " hot plug in"); 414 sIccId[phoneId] = null; 415 } 416 417 // ICCID is not available in IccRecords by the time SIM Ready event received 418 // hence get ICCID from UiccSlot. 419 UiccSlot uiccSlot = UiccController.getInstance().getUiccSlotForPhone(phoneId); 420 String iccId = (uiccSlot != null) ? IccUtils.stripTrailingFs(uiccSlot.getIccId()) : null; 421 if (!TextUtils.isEmpty(iccId)) { 422 sIccId[phoneId] = iccId; 423 updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */); 424 } 425 426 cardIds.add(getCardIdFromPhoneId(phoneId)); 427 updateEmbeddedSubscriptions(cardIds, (hasChanges) -> { 428 if (hasChanges) { 429 mSubscriptionController.notifySubscriptionInfoChanged(); 430 } 431 }); 432 broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_READY, null); 433 broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT); 434 broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY); 435 } 436 handleSimNotReady(int phoneId)437 protected void handleSimNotReady(int phoneId) { 438 logd("handleSimNotReady: phoneId: " + phoneId); 439 boolean isFinalState = false; 440 441 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); 442 boolean uiccAppsDisabled = areUiccAppsDisabledOnCard(phoneId); 443 if (iccCard.isEmptyProfile() || uiccAppsDisabled) { 444 if (uiccAppsDisabled) { 445 UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId); 446 sInactiveIccIds[phoneId] = IccUtils.stripTrailingFs(slot.getIccId()); 447 } 448 isFinalState = true; 449 // ICC_NOT_READY is a terminal state for 450 // 1) It's an empty profile as there's no uicc applications. Or 451 // 2) Its uicc applications are set to be disabled. 452 // At this phase, the subscription list is accessible. Treating NOT_READY 453 // as equivalent to ABSENT, once the rest of the system can handle it. 454 sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM; 455 updateSubscriptionInfoByIccId(phoneId, false /* updateEmbeddedSubs */); 456 } else { 457 sIccId[phoneId] = null; 458 } 459 460 broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_NOT_READY, 461 null); 462 broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT); 463 broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY); 464 if (isFinalState) { 465 updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_NOT_READY); 466 } 467 } 468 areUiccAppsDisabledOnCard(int phoneId)469 private boolean areUiccAppsDisabledOnCard(int phoneId) { 470 // When uicc apps are disabled(supported in IRadio 1.5), we will still get IccId from 471 // cardStatus (since IRadio 1.2). Amd upon cardStatus change we'll receive another 472 // handleSimNotReady so this will be evaluated again. 473 UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId); 474 if (slot == null || slot.getIccId() == null) return false; 475 SubscriptionInfo info = 476 mSubscriptionController.getSubInfoForIccId( 477 IccUtils.stripTrailingFs(slot.getIccId())); 478 return info != null && !info.areUiccApplicationsEnabled(); 479 } 480 handleSimLoaded(int phoneId)481 protected void handleSimLoaded(int phoneId) { 482 logd("handleSimLoaded: phoneId: " + phoneId); 483 484 // The SIM should be loaded at this state, but it is possible in cases such as SIM being 485 // removed or a refresh RESET that the IccRecords could be null. The right behavior is to 486 // not broadcast the SIM loaded. 487 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); 488 if (iccCard == null) { // Possibly a race condition. 489 logd("handleSimLoaded: IccCard null"); 490 return; 491 } 492 IccRecords records = iccCard.getIccRecords(); 493 if (records == null) { // Possibly a race condition. 494 logd("handleSimLoaded: IccRecords null"); 495 return; 496 } 497 if (IccUtils.stripTrailingFs(records.getFullIccId()) == null) { 498 logd("handleSimLoaded: IccID null"); 499 return; 500 } 501 502 // Call updateSubscriptionInfoByIccId() only if was not done earlier from SIM READY event 503 if (sIccId[phoneId] == null) { 504 sIccId[phoneId] = IccUtils.stripTrailingFs(records.getFullIccId()); 505 506 updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */); 507 } 508 509 List<SubscriptionInfo> subscriptionInfos = 510 mSubscriptionController.getSubInfoUsingSlotIndexPrivileged(phoneId); 511 if (subscriptionInfos == null || subscriptionInfos.isEmpty()) { 512 loge("empty subinfo for phoneId: " + phoneId + "could not update ContentResolver"); 513 } else { 514 for (SubscriptionInfo sub : subscriptionInfos) { 515 int subId = sub.getSubscriptionId(); 516 TelephonyManager tm = (TelephonyManager) 517 sContext.getSystemService(Context.TELEPHONY_SERVICE); 518 String operator = tm.getSimOperatorNumeric(subId); 519 520 if (!TextUtils.isEmpty(operator)) { 521 if (subId == mSubscriptionController.getDefaultSubId()) { 522 MccTable.updateMccMncConfiguration(sContext, operator); 523 } 524 mSubscriptionController.setMccMnc(operator, subId); 525 } else { 526 logd("EVENT_RECORDS_LOADED Operator name is null"); 527 } 528 529 String iso = tm.getSimCountryIsoForPhone(phoneId); 530 531 if (!TextUtils.isEmpty(iso)) { 532 mSubscriptionController.setCountryIso(iso, subId); 533 } else { 534 logd("EVENT_RECORDS_LOADED sim country iso is null"); 535 } 536 537 String msisdn = tm.getLine1Number(subId); 538 if (msisdn != null) { 539 mSubscriptionController.setDisplayNumber(msisdn, subId); 540 } 541 542 String imsi = tm.createForSubscriptionId(subId).getSubscriberId(); 543 if (imsi != null) { 544 mSubscriptionController.setImsi(imsi, subId); 545 } 546 547 String[] ehplmns = records.getEhplmns(); 548 String[] hplmns = records.getPlmnsFromHplmnActRecord(); 549 if (ehplmns != null || hplmns != null) { 550 mSubscriptionController.setAssociatedPlmns(ehplmns, hplmns, subId); 551 } 552 553 /* Update preferred network type and network selection mode on SIM change. 554 * Storing last subId in SharedPreference for now to detect SIM change. 555 */ 556 SharedPreferences sp = 557 PreferenceManager.getDefaultSharedPreferences(sContext); 558 int storedSubId = sp.getInt(CURR_SUBID + phoneId, -1); 559 560 if (storedSubId != subId) { 561 // Only support automatic selection mode on SIM change. 562 PhoneFactory.getPhone(phoneId).getNetworkSelectionMode( 563 obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE, 564 new Integer(phoneId))); 565 // Update stored subId 566 SharedPreferences.Editor editor = sp.edit(); 567 editor.putInt(CURR_SUBID + phoneId, subId); 568 editor.apply(); 569 } 570 } 571 } 572 573 /** 574 * The sim loading sequence will be 575 * 1. ACTION_SUBINFO_CONTENT_CHANGE happens through updateSubscriptionInfoByIccId() above. 576 * 2. ACTION_SIM_STATE_CHANGED/ACTION_SIM_CARD_STATE_CHANGED 577 * /ACTION_SIM_APPLICATION_STATE_CHANGED 578 * 3. ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED 579 * 4. restore sim-specific settings 580 * 5. ACTION_CARRIER_CONFIG_CHANGED 581 */ 582 broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED, null); 583 broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT); 584 broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_LOADED); 585 updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED); 586 /* Sim-specific settings restore depends on knowing both the mccmnc and the carrierId of the 587 sim which is why it must be done after #updateSubscriptionCarrierId(). It is done before 588 carrier config update to avoid any race conditions with user settings that depend on 589 carrier config*/ 590 restoreSimSpecificSettingsForPhone(phoneId); 591 updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED); 592 } 593 restoreSimSpecificSettingsForPhone(int phoneId)594 private void restoreSimSpecificSettingsForPhone(int phoneId) { 595 SubscriptionManager subManager = SubscriptionManager.from(sContext); 596 subManager.restoreSimSpecificSettingsForIccIdFromBackup(sIccId[phoneId]); 597 } 598 updateCarrierServices(int phoneId, String simState)599 private void updateCarrierServices(int phoneId, String simState) { 600 CarrierConfigManager configManager = 601 (CarrierConfigManager) sContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 602 configManager.updateConfigForPhoneId(phoneId, simState); 603 mCarrierServiceBindHelper.updateForPhoneId(phoneId, simState); 604 } 605 updateSubscriptionCarrierId(int phoneId, String simState)606 private void updateSubscriptionCarrierId(int phoneId, String simState) { 607 if (PhoneFactory.getPhone(phoneId) != null) { 608 PhoneFactory.getPhone(phoneId).resolveSubscriptionCarrierId(simState); 609 } 610 } 611 612 /** 613 * PhoneId is the corresponding phoneId of the slot if slot was previously active. 614 * It could be INVALID if it was already inactive. 615 */ handleInactiveSlotIccStateChange(int phoneId, String iccId)616 private void handleInactiveSlotIccStateChange(int phoneId, String iccId) { 617 if (SubscriptionManager.isValidPhoneId(phoneId)) { 618 // If phoneId is valid, it means the physical slot was previously active in that 619 // phoneId. In this case, found the subId and set its phoneId to invalid. 620 if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) { 621 logd("Slot of SIM" + (phoneId + 1) + " becomes inactive"); 622 } 623 cleanSubscriptionInPhone(phoneId, false); 624 } 625 if (!TextUtils.isEmpty(iccId)) { 626 // If iccId is new, add a subscription record in the db. 627 String strippedIccId = IccUtils.stripTrailingFs(iccId); 628 if (mSubscriptionController.getSubInfoForIccId(strippedIccId) == null) { 629 mSubscriptionController.insertEmptySubInfoRecord( 630 strippedIccId, "CARD", SubscriptionManager.INVALID_PHONE_INDEX, 631 SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); 632 } 633 } 634 } 635 636 /** 637 * Clean subscription info when sim state becomes ABSENT. There are 2 scenarios for this: 638 * 1. SIM is actually removed 639 * 2. Slot becomes inactive, which results in SIM being treated as ABSENT, but SIM may not 640 * have been removed. 641 * @param phoneId phoneId for which the cleanup needs to be done 642 * @param isSimAbsent boolean to indicate if the SIM is actually ABSENT (case 1 above) 643 */ cleanSubscriptionInPhone(int phoneId, boolean isSimAbsent)644 private void cleanSubscriptionInPhone(int phoneId, boolean isSimAbsent) { 645 if (sInactiveIccIds[phoneId] != null || (isSimAbsent && sIccId[phoneId] != null 646 && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM))) { 647 // When a SIM is unplugged, mark uicc applications enabled. This is to make sure when 648 // user unplugs and re-inserts the SIM card, we re-enable it. 649 // In certain cases this can happen before sInactiveIccIds is updated, which is why we 650 // check for sIccId as well (in case of isSimAbsent). The scenario is: after SIM 651 // deactivate request is sent to RIL, SIM is removed before SIM state is updated to 652 // NOT_READY. We do not need to check if this exact scenario is hit, because marking 653 // uicc applications enabled when SIM is removed should be okay to do regardless. 654 logd("cleanSubscriptionInPhone: " + phoneId + ", inactive iccid " 655 + sInactiveIccIds[phoneId]); 656 if (sInactiveIccIds[phoneId] == null) { 657 logd("cleanSubscriptionInPhone: " + phoneId + ", isSimAbsent=" + isSimAbsent 658 + ", iccid=" + sIccId[phoneId]); 659 } 660 String iccId = sInactiveIccIds[phoneId] != null 661 ? sInactiveIccIds[phoneId] : sIccId[phoneId]; 662 ContentValues value = new ContentValues(1); 663 value.put(SubscriptionManager.UICC_APPLICATIONS_ENABLED, true); 664 sContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value, 665 SubscriptionManager.ICC_ID + "=\'" + iccId + "\'", null); 666 sInactiveIccIds[phoneId] = null; 667 } 668 sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM; 669 updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */); 670 } 671 handleSimAbsent(int phoneId)672 protected void handleSimAbsent(int phoneId) { 673 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 674 logd("handleSimAbsent on invalid phoneId"); 675 return; 676 } 677 if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) { 678 logd("SIM" + (phoneId + 1) + " hot plug out"); 679 } 680 cleanSubscriptionInPhone(phoneId, true); 681 682 broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT, null); 683 broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_ABSENT); 684 broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_UNKNOWN); 685 updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT); 686 updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT); 687 } 688 handleSimError(int phoneId)689 protected void handleSimError(int phoneId) { 690 if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) { 691 logd("SIM" + (phoneId + 1) + " Error "); 692 } 693 sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM; 694 updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */); 695 broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR, 696 IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR); 697 broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_CARD_IO_ERROR); 698 broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY); 699 updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR); 700 updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR); 701 } 702 updateSubscriptionInfoByIccId(int phoneId, boolean updateEmbeddedSubs)703 protected synchronized void updateSubscriptionInfoByIccId(int phoneId, 704 boolean updateEmbeddedSubs) { 705 logd("updateSubscriptionInfoByIccId:+ Start - phoneId: " + phoneId); 706 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 707 loge("[updateSubscriptionInfoByIccId]- invalid phoneId=" + phoneId); 708 return; 709 } 710 logd("updateSubscriptionInfoByIccId: removing subscription info record: phoneId " 711 + phoneId); 712 // Clear phoneId only when sim absent is not enough. It's possible to switch SIM profile 713 // within the same slot. Need to clear the slot index of the previous sub. Thus always clear 714 // for the changing slot first. 715 mSubscriptionController.clearSubInfoRecord(phoneId); 716 717 // If SIM is not absent, insert new record or update existing record. 718 if (!ICCID_STRING_FOR_NO_SIM.equals(sIccId[phoneId]) && sIccId[phoneId] != null) { 719 logd("updateSubscriptionInfoByIccId: adding subscription info record: iccid: " 720 + sIccId[phoneId] + ", phoneId:" + phoneId); 721 mSubscriptionManager.addSubscriptionInfoRecord(sIccId[phoneId], phoneId); 722 } 723 724 List<SubscriptionInfo> subInfos = 725 mSubscriptionController.getSubInfoUsingSlotIndexPrivileged(phoneId); 726 if (subInfos != null) { 727 boolean changed = false; 728 for (int i = 0; i < subInfos.size(); i++) { 729 SubscriptionInfo temp = subInfos.get(i); 730 ContentValues value = new ContentValues(1); 731 732 String msisdn = TelephonyManager.getDefault().getLine1Number( 733 temp.getSubscriptionId()); 734 735 if (!TextUtils.equals(msisdn, temp.getNumber())) { 736 value.put(SubscriptionManager.NUMBER, msisdn); 737 sContext.getContentResolver().update(SubscriptionManager 738 .getUriForSubscriptionId(temp.getSubscriptionId()), value, null, null); 739 changed = true; 740 } 741 } 742 if (changed) { 743 // refresh Cached Active Subscription Info List 744 mSubscriptionController.refreshCachedActiveSubscriptionInfoList(); 745 } 746 } 747 748 // TODO investigate if we can update for each slot separately. 749 if (isAllIccIdQueryDone()) { 750 // Ensure the modems are mapped correctly 751 if (mSubscriptionManager.isActiveSubId( 752 mSubscriptionManager.getDefaultDataSubscriptionId())) { 753 mSubscriptionManager.setDefaultDataSubId( 754 mSubscriptionManager.getDefaultDataSubscriptionId()); 755 } else { 756 logd("bypass reset default data sub if inactive"); 757 } 758 setSubInfoInitialized(); 759 } 760 761 UiccController uiccController = UiccController.getInstance(); 762 UiccSlot[] uiccSlots = uiccController.getUiccSlots(); 763 if (uiccSlots != null && updateEmbeddedSubs) { 764 List<Integer> cardIds = new ArrayList<>(); 765 for (UiccSlot uiccSlot : uiccSlots) { 766 if (uiccSlot != null && uiccSlot.getUiccCard() != null) { 767 int cardId = uiccController.convertToPublicCardId( 768 uiccSlot.getUiccCard().getCardId()); 769 cardIds.add(cardId); 770 } 771 } 772 updateEmbeddedSubscriptions(cardIds, (hasChanges) -> { 773 if (hasChanges) { 774 mSubscriptionController.notifySubscriptionInfoChanged(); 775 } 776 if (DBG) logd("updateSubscriptionInfoByIccId: SubscriptionInfo update complete"); 777 }); 778 } 779 780 mSubscriptionController.notifySubscriptionInfoChanged(); 781 if (DBG) logd("updateSubscriptionInfoByIccId: SubscriptionInfo update complete"); 782 } 783 setSubInfoInitialized()784 private void setSubInfoInitialized() { 785 // Should only be triggered once. 786 if (!sIsSubInfoInitialized) { 787 if (DBG) logd("SubInfo Initialized"); 788 sIsSubInfoInitialized = true; 789 mSubscriptionController.notifySubInfoReady(); 790 } 791 MultiSimSettingController.getInstance().notifyAllSubscriptionLoaded(); 792 } 793 794 /** 795 * Whether subscriptions of all SIMs are initialized. 796 */ isSubInfoInitialized()797 public static boolean isSubInfoInitialized() { 798 return sIsSubInfoInitialized; 799 } 800 801 /** 802 * Updates the cached list of embedded subscription for the eUICC with the given list of card 803 * IDs {@code cardIds}. The step of reading the embedded subscription list from eUICC card is 804 * executed in background thread. The callback {@code callback} is executed after the cache is 805 * refreshed. The callback is executed in main thread. 806 */ 807 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) updateEmbeddedSubscriptions(List<Integer> cardIds, @Nullable UpdateEmbeddedSubsCallback callback)808 public void updateEmbeddedSubscriptions(List<Integer> cardIds, 809 @Nullable UpdateEmbeddedSubsCallback callback) { 810 // Do nothing if eUICCs are disabled. (Previous entries may remain in the cache, but they 811 // are filtered out of list calls as long as EuiccManager.isEnabled returns false). 812 if (!mEuiccManager.isEnabled()) { 813 callback.run(false /* hasChanges */); 814 return; 815 } 816 817 mBackgroundHandler.post(() -> { 818 List<Pair<Integer, GetEuiccProfileInfoListResult>> results = new ArrayList<>(); 819 for (int cardId : cardIds) { 820 GetEuiccProfileInfoListResult result = 821 EuiccController.get().blockingGetEuiccProfileInfoList(cardId); 822 if (DBG) logd("blockingGetEuiccProfileInfoList cardId " + cardId); 823 results.add(Pair.create(cardId, result)); 824 } 825 826 // The runnable will be executed in the main thread. 827 this.post(() -> { 828 boolean hasChanges = false; 829 for (Pair<Integer, GetEuiccProfileInfoListResult> cardIdAndResult : results) { 830 if (updateEmbeddedSubscriptionsCache(cardIdAndResult.first, 831 cardIdAndResult.second)) { 832 hasChanges = true; 833 } 834 } 835 // The latest state in the main thread may be changed when the callback is 836 // triggered. 837 if (callback != null) { 838 callback.run(hasChanges); 839 } 840 }); 841 }); 842 } 843 844 /** 845 * Update the cached list of embedded subscription based on the passed in 846 * GetEuiccProfileInfoListResult {@code result}. 847 * 848 * @return true if changes may have been made. This is not a guarantee that changes were made, 849 * but notifications about subscription changes may be skipped if this returns false as an 850 * optimization to avoid spurious notifications. 851 */ updateEmbeddedSubscriptionsCache(int cardId, GetEuiccProfileInfoListResult result)852 private boolean updateEmbeddedSubscriptionsCache(int cardId, 853 GetEuiccProfileInfoListResult result) { 854 if (DBG) logd("updateEmbeddedSubscriptionsCache"); 855 856 if (result == null) { 857 // IPC to the eUICC controller failed. 858 return false; 859 } 860 861 // If the returned result is not RESULT_OK or the profile list is null, don't update cache. 862 // Otherwise, update the cache. 863 final EuiccProfileInfo[] embeddedProfiles; 864 List<EuiccProfileInfo> list = result.getProfiles(); 865 if (result.getResult() == EuiccService.RESULT_OK && list != null) { 866 embeddedProfiles = list.toArray(new EuiccProfileInfo[list.size()]); 867 if (DBG) { 868 logd("blockingGetEuiccProfileInfoList: got " + result.getProfiles().size() 869 + " profiles"); 870 } 871 } else { 872 if (DBG) { 873 logd("blockingGetEuiccProfileInfoList returns an error. " 874 + "Result code=" + result.getResult() 875 + ". Null profile list=" + (result.getProfiles() == null)); 876 } 877 return false; 878 } 879 880 final boolean isRemovable = result.getIsRemovable(); 881 882 final String[] embeddedIccids = new String[embeddedProfiles.length]; 883 for (int i = 0; i < embeddedProfiles.length; i++) { 884 embeddedIccids[i] = embeddedProfiles[i].getIccid(); 885 } 886 887 if (DBG) logd("Get eUICC profile list of size " + embeddedProfiles.length); 888 889 // Note that this only tracks whether we make any writes to the DB. It's possible this will 890 // be set to true for an update even when the row contents remain exactly unchanged from 891 // before, since we don't compare against the previous value. Since this is only intended to 892 // avoid some spurious broadcasts (particularly for users who don't use eSIM at all), this 893 // is fine. 894 boolean hasChanges = false; 895 896 // Update or insert records for all embedded subscriptions (except non-removable ones if the 897 // current eUICC is non-removable, since we assume these are still accessible though not 898 // returned by the eUICC controller). 899 List<SubscriptionInfo> existingSubscriptions = 900 mSubscriptionController.getSubscriptionInfoListForEmbeddedSubscriptionUpdate( 901 embeddedIccids, isRemovable); 902 ContentResolver contentResolver = sContext.getContentResolver(); 903 for (EuiccProfileInfo embeddedProfile : embeddedProfiles) { 904 int index = 905 findSubscriptionInfoForIccid(existingSubscriptions, embeddedProfile.getIccid()); 906 int prevCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; 907 int nameSource = SubscriptionManager.NAME_SOURCE_CARRIER_ID; 908 if (index < 0) { 909 // No existing entry for this ICCID; create an empty one. 910 mSubscriptionController.insertEmptySubInfoRecord( 911 embeddedProfile.getIccid(), SubscriptionManager.SIM_NOT_INSERTED); 912 } else { 913 nameSource = existingSubscriptions.get(index).getNameSource(); 914 prevCarrierId = existingSubscriptions.get(index).getCarrierId(); 915 existingSubscriptions.remove(index); 916 } 917 918 if (DBG) { 919 logd("embeddedProfile " + embeddedProfile + " existing record " 920 + (index < 0 ? "not found" : "found")); 921 } 922 923 ContentValues values = new ContentValues(); 924 values.put(SubscriptionManager.IS_EMBEDDED, 1); 925 List<UiccAccessRule> ruleList = embeddedProfile.getUiccAccessRules(); 926 boolean isRuleListEmpty = false; 927 if (ruleList == null || ruleList.size() == 0) { 928 isRuleListEmpty = true; 929 } 930 values.put(SubscriptionManager.ACCESS_RULES, 931 isRuleListEmpty ? null : UiccAccessRule.encodeRules( 932 ruleList.toArray(new UiccAccessRule[ruleList.size()]))); 933 values.put(SubscriptionManager.IS_REMOVABLE, isRemovable); 934 // override DISPLAY_NAME if the priority of existing nameSource is <= carrier 935 if (SubscriptionController.getNameSourcePriority(nameSource) 936 <= SubscriptionController.getNameSourcePriority( 937 SubscriptionManager.NAME_SOURCE_CARRIER)) { 938 values.put(SubscriptionManager.DISPLAY_NAME, embeddedProfile.getNickname()); 939 values.put(SubscriptionManager.NAME_SOURCE, 940 SubscriptionManager.NAME_SOURCE_CARRIER); 941 } 942 values.put(SubscriptionManager.PROFILE_CLASS, embeddedProfile.getProfileClass()); 943 CarrierIdentifier cid = embeddedProfile.getCarrierIdentifier(); 944 if (cid != null) { 945 // Due to the limited subscription information, carrier id identified here might 946 // not be accurate compared with CarrierResolver. Only update carrier id if there 947 // is no valid carrier id present. 948 if (prevCarrierId == TelephonyManager.UNKNOWN_CARRIER_ID) { 949 values.put(SubscriptionManager.CARRIER_ID, 950 CarrierResolver.getCarrierIdFromIdentifier(sContext, cid)); 951 } 952 String mcc = cid.getMcc(); 953 String mnc = cid.getMnc(); 954 values.put(SubscriptionManager.MCC_STRING, mcc); 955 values.put(SubscriptionManager.MCC, mcc); 956 values.put(SubscriptionManager.MNC_STRING, mnc); 957 values.put(SubscriptionManager.MNC, mnc); 958 } 959 // If cardId = unsupported or unitialized, we have no reason to update DB. 960 // Additionally, if the device does not support cardId for default eUICC, the CARD_ID 961 // field should not contain the EID 962 UiccController uiccController = UiccController.getInstance(); 963 if (cardId >= 0 && uiccController.getCardIdForDefaultEuicc() 964 != TelephonyManager.UNSUPPORTED_CARD_ID) { 965 values.put(SubscriptionManager.CARD_ID, uiccController.convertToCardString(cardId)); 966 } 967 hasChanges = true; 968 contentResolver.update(SubscriptionManager.CONTENT_URI, values, 969 SubscriptionManager.ICC_ID + "=\"" + embeddedProfile.getIccid() + "\"", null); 970 971 // refresh Cached Active Subscription Info List 972 mSubscriptionController.refreshCachedActiveSubscriptionInfoList(); 973 } 974 975 // Remove all remaining subscriptions which have embedded = true. We set embedded to false 976 // to ensure they are not returned in the list of embedded subscriptions (but keep them 977 // around in case the subscription is added back later, which is equivalent to a removable 978 // SIM being removed and reinserted). 979 if (!existingSubscriptions.isEmpty()) { 980 if (DBG) { 981 logd("Removing existing embedded subscriptions of size" 982 + existingSubscriptions.size()); 983 } 984 List<String> iccidsToRemove = new ArrayList<>(); 985 for (int i = 0; i < existingSubscriptions.size(); i++) { 986 SubscriptionInfo info = existingSubscriptions.get(i); 987 if (info.isEmbedded()) { 988 if (DBG) logd("Removing embedded subscription of IccId " + info.getIccId()); 989 iccidsToRemove.add("\"" + info.getIccId() + "\""); 990 } 991 } 992 String whereClause = SubscriptionManager.ICC_ID + " IN (" 993 + TextUtils.join(",", iccidsToRemove) + ")"; 994 ContentValues values = new ContentValues(); 995 values.put(SubscriptionManager.IS_EMBEDDED, 0); 996 hasChanges = true; 997 contentResolver.update(SubscriptionManager.CONTENT_URI, values, whereClause, null); 998 999 // refresh Cached Active Subscription Info List 1000 mSubscriptionController.refreshCachedActiveSubscriptionInfoList(); 1001 } 1002 1003 if (DBG) logd("updateEmbeddedSubscriptions done hasChanges=" + hasChanges); 1004 return hasChanges; 1005 } 1006 1007 /** 1008 * Called by CarrierConfigLoader to update the subscription before sending a broadcast. 1009 */ updateSubscriptionByCarrierConfigAndNotifyComplete(int phoneId, String configPackageName, PersistableBundle config, Message onComplete)1010 public void updateSubscriptionByCarrierConfigAndNotifyComplete(int phoneId, 1011 String configPackageName, PersistableBundle config, Message onComplete) { 1012 post(() -> { 1013 updateSubscriptionByCarrierConfig(phoneId, configPackageName, config); 1014 onComplete.sendToTarget(); 1015 }); 1016 } 1017 getDefaultCarrierServicePackageName()1018 private String getDefaultCarrierServicePackageName() { 1019 CarrierConfigManager configManager = 1020 (CarrierConfigManager) sContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 1021 return configManager.getDefaultCarrierServicePackageName(); 1022 } 1023 isCarrierServicePackage(int phoneId, String pkgName)1024 private boolean isCarrierServicePackage(int phoneId, String pkgName) { 1025 if (pkgName.equals(getDefaultCarrierServicePackageName())) return false; 1026 1027 List<String> carrierPackageNames = TelephonyManager.from(sContext) 1028 .getCarrierPackageNamesForIntentAndPhone( 1029 new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), phoneId); 1030 if (DBG) logd("Carrier Packages For Subscription = " + carrierPackageNames); 1031 return carrierPackageNames != null && carrierPackageNames.contains(pkgName); 1032 } 1033 1034 /** 1035 * Update the currently active Subscription based on information from CarrierConfig 1036 */ 1037 @VisibleForTesting updateSubscriptionByCarrierConfig( int phoneId, String configPackageName, PersistableBundle config)1038 public void updateSubscriptionByCarrierConfig( 1039 int phoneId, String configPackageName, PersistableBundle config) { 1040 if (!SubscriptionManager.isValidPhoneId(phoneId) 1041 || TextUtils.isEmpty(configPackageName) || config == null) { 1042 if (DBG) { 1043 logd("In updateSubscriptionByCarrierConfig(): phoneId=" + phoneId 1044 + " configPackageName=" + configPackageName + " config=" 1045 + ((config == null) ? "null" : config.hashCode())); 1046 } 1047 return; 1048 } 1049 1050 int currentSubId = mSubscriptionController.getSubIdUsingPhoneId(phoneId); 1051 if (!SubscriptionManager.isValidSubscriptionId(currentSubId) 1052 || currentSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { 1053 if (DBG) logd("No subscription is active for phone being updated"); 1054 return; 1055 } 1056 1057 SubscriptionInfo currentSubInfo = mSubscriptionController.getSubscriptionInfo(currentSubId); 1058 if (currentSubInfo == null) { 1059 loge("Couldn't retrieve subscription info for current subscription"); 1060 return; 1061 } 1062 1063 ContentValues cv = new ContentValues(); 1064 ParcelUuid groupUuid = null; 1065 1066 // carrier certificates are not subscription-specific, so we want to load them even if 1067 // this current package is not a CarrierServicePackage 1068 String[] certs = config.getStringArray( 1069 CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY); 1070 UiccAccessRule[] carrierConfigAccessRules = UiccAccessRule.decodeRulesFromCarrierConfig( 1071 certs); 1072 cv.put(SubscriptionManager.ACCESS_RULES_FROM_CARRIER_CONFIGS, 1073 UiccAccessRule.encodeRules(carrierConfigAccessRules)); 1074 1075 if (!isCarrierServicePackage(phoneId, configPackageName)) { 1076 loge("Cannot manage subId=" + currentSubId + ", carrierPackage=" + configPackageName); 1077 } else { 1078 boolean isOpportunistic = config.getBoolean( 1079 CarrierConfigManager.KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL, false); 1080 if (currentSubInfo.isOpportunistic() != isOpportunistic) { 1081 if (DBG) logd("Set SubId=" + currentSubId + " isOpportunistic=" + isOpportunistic); 1082 cv.put(SubscriptionManager.IS_OPPORTUNISTIC, isOpportunistic ? "1" : "0"); 1083 } 1084 1085 String groupUuidString = 1086 config.getString(CarrierConfigManager.KEY_SUBSCRIPTION_GROUP_UUID_STRING, ""); 1087 if (!TextUtils.isEmpty(groupUuidString)) { 1088 try { 1089 // Update via a UUID Structure to ensure consistent formatting 1090 groupUuid = ParcelUuid.fromString(groupUuidString); 1091 if (groupUuid.equals(REMOVE_GROUP_UUID) 1092 && currentSubInfo.getGroupUuid() != null) { 1093 cv.put(SubscriptionManager.GROUP_UUID, (String) null); 1094 if (DBG) logd("Group Removed for" + currentSubId); 1095 } else if (mSubscriptionController.canPackageManageGroup( 1096 groupUuid, configPackageName)) { 1097 cv.put(SubscriptionManager.GROUP_UUID, groupUuid.toString()); 1098 cv.put(SubscriptionManager.GROUP_OWNER, configPackageName); 1099 if (DBG) logd("Group Added for" + currentSubId); 1100 } else { 1101 loge("configPackageName " + configPackageName + " doesn't own grouUuid " 1102 + groupUuid); 1103 } 1104 } catch (IllegalArgumentException e) { 1105 loge("Invalid Group UUID=" + groupUuidString); 1106 } 1107 } 1108 } 1109 if (cv.size() > 0 && sContext.getContentResolver().update(SubscriptionManager 1110 .getUriForSubscriptionId(currentSubId), cv, null, null) > 0) { 1111 mSubscriptionController.refreshCachedActiveSubscriptionInfoList(); 1112 mSubscriptionController.notifySubscriptionInfoChanged(); 1113 MultiSimSettingController.getInstance().notifySubscriptionGroupChanged(groupUuid); 1114 } 1115 } 1116 findSubscriptionInfoForIccid(List<SubscriptionInfo> list, String iccid)1117 private static int findSubscriptionInfoForIccid(List<SubscriptionInfo> list, String iccid) { 1118 for (int i = 0; i < list.size(); i++) { 1119 if (TextUtils.equals(iccid, list.get(i).getIccId())) { 1120 return i; 1121 } 1122 } 1123 return -1; 1124 } 1125 1126 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) broadcastSimStateChanged(int phoneId, String state, String reason)1127 protected void broadcastSimStateChanged(int phoneId, String state, String reason) { 1128 // Note: This intent is way deprecated and is only being kept around because there's no 1129 // graceful way to deprecate a sticky broadcast that has a lot of listeners. 1130 // DO NOT add any new extras to this broadcast -- it is not protected by any permissions. 1131 Intent i = new Intent(TelephonyIntents.ACTION_SIM_STATE_CHANGED); 1132 i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1133 i.putExtra(PhoneConstants.PHONE_NAME_KEY, "Phone"); 1134 i.putExtra(IccCardConstants.INTENT_KEY_ICC_STATE, state); 1135 i.putExtra(IccCardConstants.INTENT_KEY_LOCKED_REASON, reason); 1136 SubscriptionManager.putPhoneIdAndSubIdExtra(i, phoneId); 1137 logd("Broadcasting intent ACTION_SIM_STATE_CHANGED " + state + " reason " + reason + 1138 " for phone: " + phoneId); 1139 IntentBroadcaster.getInstance().broadcastStickyIntent(sContext, i, phoneId); 1140 } 1141 broadcastSimCardStateChanged(int phoneId, int state)1142 protected void broadcastSimCardStateChanged(int phoneId, int state) { 1143 if (state != sSimCardState[phoneId]) { 1144 sSimCardState[phoneId] = state; 1145 Intent i = new Intent(TelephonyManager.ACTION_SIM_CARD_STATE_CHANGED); 1146 i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1147 i.putExtra(TelephonyManager.EXTRA_SIM_STATE, state); 1148 SubscriptionManager.putPhoneIdAndSubIdExtra(i, phoneId); 1149 // TODO(b/130664115) we manually populate this intent with the slotId. In the future we 1150 // should do a review of whether to make this public 1151 int slotId = UiccController.getInstance().getSlotIdFromPhoneId(phoneId); 1152 i.putExtra(PhoneConstants.SLOT_KEY, slotId); 1153 logd("Broadcasting intent ACTION_SIM_CARD_STATE_CHANGED " + simStateString(state) 1154 + " for phone: " + phoneId + " slot: " + slotId); 1155 sContext.sendBroadcast(i, Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 1156 TelephonyMetrics.getInstance().updateSimState(phoneId, state); 1157 } 1158 } 1159 broadcastSimApplicationStateChanged(int phoneId, int state)1160 protected void broadcastSimApplicationStateChanged(int phoneId, int state) { 1161 // Broadcast if the state has changed, except if old state was UNKNOWN and new is NOT_READY, 1162 // because that's the initial state and a broadcast should be sent only on a transition 1163 // after SIM is PRESENT. The only exception is eSIM boot profile, where NOT_READY is the 1164 // terminal state. 1165 boolean isUnknownToNotReady = 1166 (sSimApplicationState[phoneId] == TelephonyManager.SIM_STATE_UNKNOWN 1167 && state == TelephonyManager.SIM_STATE_NOT_READY); 1168 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); 1169 boolean emptyProfile = iccCard != null && iccCard.isEmptyProfile(); 1170 if (state != sSimApplicationState[phoneId] && (!isUnknownToNotReady || emptyProfile)) { 1171 sSimApplicationState[phoneId] = state; 1172 Intent i = new Intent(TelephonyManager.ACTION_SIM_APPLICATION_STATE_CHANGED); 1173 i.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 1174 i.putExtra(TelephonyManager.EXTRA_SIM_STATE, state); 1175 SubscriptionManager.putPhoneIdAndSubIdExtra(i, phoneId); 1176 // TODO(b/130664115) we populate this intent with the actual slotId. In the future we 1177 // should do a review of whether to make this public 1178 int slotId = UiccController.getInstance().getSlotIdFromPhoneId(phoneId); 1179 i.putExtra(PhoneConstants.SLOT_KEY, slotId); 1180 logd("Broadcasting intent ACTION_SIM_APPLICATION_STATE_CHANGED " + simStateString(state) 1181 + " for phone: " + phoneId + " slot: " + slotId); 1182 sContext.sendBroadcast(i, Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 1183 TelephonyMetrics.getInstance().updateSimState(phoneId, state); 1184 } 1185 } 1186 1187 /** 1188 * Convert SIM state into string 1189 * 1190 * @param state SIM state 1191 * @return SIM state in string format 1192 */ simStateString(@imState int state)1193 public static String simStateString(@SimState int state) { 1194 switch (state) { 1195 case TelephonyManager.SIM_STATE_UNKNOWN: 1196 return "UNKNOWN"; 1197 case TelephonyManager.SIM_STATE_ABSENT: 1198 return "ABSENT"; 1199 case TelephonyManager.SIM_STATE_PIN_REQUIRED: 1200 return "PIN_REQUIRED"; 1201 case TelephonyManager.SIM_STATE_PUK_REQUIRED: 1202 return "PUK_REQUIRED"; 1203 case TelephonyManager.SIM_STATE_NETWORK_LOCKED: 1204 return "NETWORK_LOCKED"; 1205 case TelephonyManager.SIM_STATE_READY: 1206 return "READY"; 1207 case TelephonyManager.SIM_STATE_NOT_READY: 1208 return "NOT_READY"; 1209 case TelephonyManager.SIM_STATE_PERM_DISABLED: 1210 return "PERM_DISABLED"; 1211 case TelephonyManager.SIM_STATE_CARD_IO_ERROR: 1212 return "CARD_IO_ERROR"; 1213 case TelephonyManager.SIM_STATE_CARD_RESTRICTED: 1214 return "CARD_RESTRICTED"; 1215 case TelephonyManager.SIM_STATE_LOADED: 1216 return "LOADED"; 1217 case TelephonyManager.SIM_STATE_PRESENT: 1218 return "PRESENT"; 1219 default: 1220 return "INVALID"; 1221 } 1222 } 1223 1224 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) logd(String message)1225 private static void logd(String message) { 1226 Rlog.d(LOG_TAG, message); 1227 } 1228 loge(String message)1229 private static void loge(String message) { 1230 Rlog.e(LOG_TAG, message); 1231 } 1232 dump(FileDescriptor fd, PrintWriter pw, String[] args)1233 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1234 pw.println("SubscriptionInfoUpdater:"); 1235 mCarrierServiceBindHelper.dump(fd, pw, args); 1236 } 1237 } 1238