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