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