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