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 SubscriptionController.getInstance().clearSubInfoRecord(phoneId); 344 sIccId[phoneId] = null; 345 sSimCardState[phoneId] = TelephonyManager.SIM_STATE_UNKNOWN; 346 sSimApplicationState[phoneId] = TelephonyManager.SIM_STATE_UNKNOWN; 347 } 348 } 349 getCardIdFromPhoneId(int phoneId)350 protected int getCardIdFromPhoneId(int phoneId) { 351 UiccController uiccController = UiccController.getInstance(); 352 UiccCard card = uiccController.getUiccCardForPhone(phoneId); 353 if (card != null) { 354 return uiccController.convertToPublicCardId(card.getCardId()); 355 } 356 return TelephonyManager.UNINITIALIZED_CARD_ID; 357 } 358 requestEmbeddedSubscriptionInfoListRefresh(int cardId, @Nullable Runnable callback)359 void requestEmbeddedSubscriptionInfoListRefresh(int cardId, @Nullable Runnable callback) { 360 sendMessage(obtainMessage( 361 EVENT_REFRESH_EMBEDDED_SUBSCRIPTIONS, cardId, 0 /* arg2 */, callback)); 362 } 363 handleSimLocked(int phoneId, String reason)364 protected void handleSimLocked(int phoneId, String reason) { 365 if (sIccId[phoneId] != null && sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) { 366 logd("SIM" + (phoneId + 1) + " hot plug in"); 367 sIccId[phoneId] = null; 368 } 369 370 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); 371 if (iccCard == null) { 372 logd("handleSimLocked: IccCard null"); 373 return; 374 } 375 IccRecords records = iccCard.getIccRecords(); 376 if (records == null) { 377 logd("handleSimLocked: IccRecords null"); 378 return; 379 } 380 if (IccUtils.stripTrailingFs(records.getFullIccId()) == null) { 381 logd("handleSimLocked: IccID null"); 382 return; 383 } 384 sIccId[phoneId] = IccUtils.stripTrailingFs(records.getFullIccId()); 385 386 updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */); 387 388 broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOCKED, reason); 389 broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT); 390 broadcastSimApplicationStateChanged(phoneId, getSimStateFromLockedReason(reason)); 391 updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOCKED); 392 updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOCKED); 393 } 394 getSimStateFromLockedReason(String lockedReason)395 private static int getSimStateFromLockedReason(String lockedReason) { 396 switch (lockedReason) { 397 case IccCardConstants.INTENT_VALUE_LOCKED_ON_PIN: 398 return TelephonyManager.SIM_STATE_PIN_REQUIRED; 399 case IccCardConstants.INTENT_VALUE_LOCKED_ON_PUK: 400 return TelephonyManager.SIM_STATE_PUK_REQUIRED; 401 case IccCardConstants.INTENT_VALUE_LOCKED_NETWORK: 402 return TelephonyManager.SIM_STATE_NETWORK_LOCKED; 403 case IccCardConstants.INTENT_VALUE_ABSENT_ON_PERM_DISABLED: 404 return TelephonyManager.SIM_STATE_PERM_DISABLED; 405 default: 406 Rlog.e(LOG_TAG, "Unexpected SIM locked reason " + lockedReason); 407 return TelephonyManager.SIM_STATE_UNKNOWN; 408 } 409 } 410 handleSimReady(int phoneId)411 protected void handleSimReady(int phoneId) { 412 List<Integer> cardIds = new ArrayList<>(); 413 414 cardIds.add(getCardIdFromPhoneId(phoneId)); 415 updateEmbeddedSubscriptions(cardIds, (hasChanges) -> { 416 if (hasChanges) { 417 SubscriptionController.getInstance().notifySubscriptionInfoChanged(); 418 } 419 }); 420 broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_READY, null); 421 broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT); 422 broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY); 423 } 424 425 handleSimNotReady(int phoneId)426 protected void handleSimNotReady(int phoneId) { 427 logd("handleSimNotReady: phoneId: " + phoneId); 428 boolean isFinalState = false; 429 430 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); 431 boolean uiccAppsDisabled = areUiccAppsDisabledOnCard(phoneId); 432 if (iccCard.isEmptyProfile() || uiccAppsDisabled) { 433 if (uiccAppsDisabled) { 434 UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId); 435 sInactiveIccIds[phoneId] = IccUtils.stripTrailingFs(slot.getIccId()); 436 } 437 isFinalState = true; 438 // ICC_NOT_READY is a terminal state for 439 // 1) It's an empty profile as there's no uicc applications. Or 440 // 2) Its uicc applications are set to be disabled. 441 // At this phase, the subscription list is accessible. Treating NOT_READY 442 // as equivalent to ABSENT, once the rest of the system can handle it. 443 sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM; 444 updateSubscriptionInfoByIccId(phoneId, false /* updateEmbeddedSubs */); 445 } 446 447 broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_NOT_READY, 448 null); 449 broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT); 450 broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY); 451 if (isFinalState) { 452 updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_NOT_READY); 453 } 454 } 455 areUiccAppsDisabledOnCard(int phoneId)456 private boolean areUiccAppsDisabledOnCard(int phoneId) { 457 // When uicc apps are disabled(supported in IRadio 1.5), we will still get IccId from 458 // cardStatus (since IRadio 1.2). Amd upon cardStatus change we'll receive another 459 // handleSimNotReady so this will be evaluated again. 460 UiccSlot slot = UiccController.getInstance().getUiccSlotForPhone(phoneId); 461 if (slot == null || slot.getIccId() == null) return false; 462 SubscriptionInfo info = SubscriptionController.getInstance() 463 .getSubInfoForIccId(IccUtils.stripTrailingFs(slot.getIccId())); 464 return info != null && !info.areUiccApplicationsEnabled(); 465 } 466 handleSimLoaded(int phoneId)467 protected void handleSimLoaded(int phoneId) { 468 logd("handleSimLoaded: phoneId: " + phoneId); 469 470 // The SIM should be loaded at this state, but it is possible in cases such as SIM being 471 // removed or a refresh RESET that the IccRecords could be null. The right behavior is to 472 // not broadcast the SIM loaded. 473 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); 474 if (iccCard == null) { // Possibly a race condition. 475 logd("handleSimLoaded: IccCard null"); 476 return; 477 } 478 IccRecords records = iccCard.getIccRecords(); 479 if (records == null) { // Possibly a race condition. 480 logd("handleSimLoaded: IccRecords null"); 481 return; 482 } 483 if (IccUtils.stripTrailingFs(records.getFullIccId()) == null) { 484 logd("handleSimLoaded: IccID null"); 485 return; 486 } 487 sIccId[phoneId] = IccUtils.stripTrailingFs(records.getFullIccId()); 488 489 updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */); 490 List<SubscriptionInfo> subscriptionInfos = SubscriptionController.getInstance() 491 .getSubInfoUsingSlotIndexPrivileged(phoneId); 492 if (subscriptionInfos == null || subscriptionInfos.isEmpty()) { 493 loge("empty subinfo for phoneId: " + phoneId + "could not update ContentResolver"); 494 } else { 495 for (SubscriptionInfo sub : subscriptionInfos) { 496 int subId = sub.getSubscriptionId(); 497 TelephonyManager tm = (TelephonyManager) 498 sContext.getSystemService(Context.TELEPHONY_SERVICE); 499 String operator = tm.getSimOperatorNumeric(subId); 500 501 if (!TextUtils.isEmpty(operator)) { 502 if (subId == SubscriptionController.getInstance().getDefaultSubId()) { 503 MccTable.updateMccMncConfiguration(sContext, operator); 504 } 505 SubscriptionController.getInstance().setMccMnc(operator, subId); 506 } else { 507 logd("EVENT_RECORDS_LOADED Operator name is null"); 508 } 509 510 String iso = tm.getSimCountryIsoForPhone(phoneId); 511 512 if (!TextUtils.isEmpty(iso)) { 513 SubscriptionController.getInstance().setCountryIso(iso, subId); 514 } else { 515 logd("EVENT_RECORDS_LOADED sim country iso is null"); 516 } 517 518 String msisdn = tm.getLine1Number(subId); 519 if (msisdn != null) { 520 SubscriptionController.getInstance().setDisplayNumber(msisdn, subId); 521 } 522 523 String imsi = tm.createForSubscriptionId(subId).getSubscriberId(); 524 if (imsi != null) { 525 SubscriptionController.getInstance().setImsi(imsi, subId); 526 } 527 528 String[] ehplmns = records.getEhplmns(); 529 String[] hplmns = records.getPlmnsFromHplmnActRecord(); 530 if (ehplmns != null || hplmns != null) { 531 SubscriptionController.getInstance().setAssociatedPlmns(ehplmns, hplmns, subId); 532 } 533 534 /* Update preferred network type and network selection mode on SIM change. 535 * Storing last subId in SharedPreference for now to detect SIM change. 536 */ 537 SharedPreferences sp = 538 PreferenceManager.getDefaultSharedPreferences(sContext); 539 int storedSubId = sp.getInt(CURR_SUBID + phoneId, -1); 540 541 if (storedSubId != subId) { 542 int networkType = Settings.Global.getInt( 543 PhoneFactory.getPhone(phoneId).getContext().getContentResolver(), 544 Settings.Global.PREFERRED_NETWORK_MODE + subId, 545 -1 /* invalid network mode */); 546 547 if (networkType == -1) { 548 networkType = RILConstants.PREFERRED_NETWORK_MODE; 549 try { 550 networkType = TelephonyManager.getIntAtIndex( 551 sContext.getContentResolver(), 552 Settings.Global.PREFERRED_NETWORK_MODE, phoneId); 553 } catch (SettingNotFoundException retrySnfe) { 554 Rlog.e(LOG_TAG, "Settings Exception Reading Value At Index for " 555 + "Settings.Global.PREFERRED_NETWORK_MODE"); 556 } 557 Settings.Global.putInt( 558 PhoneFactory.getPhone(phoneId).getContext().getContentResolver(), 559 Global.PREFERRED_NETWORK_MODE + subId, 560 networkType); 561 } 562 563 // Set the modem network mode 564 PhoneFactory.getPhone(phoneId).setPreferredNetworkType(networkType, null); 565 566 // Only support automatic selection mode on SIM change. 567 PhoneFactory.getPhone(phoneId).getNetworkSelectionMode( 568 obtainMessage(EVENT_GET_NETWORK_SELECTION_MODE_DONE, 569 new Integer(phoneId))); 570 571 // Update stored subId 572 SharedPreferences.Editor editor = sp.edit(); 573 editor.putInt(CURR_SUBID + phoneId, subId); 574 editor.apply(); 575 } 576 } 577 } 578 579 // Update set of enabled carrier apps now that the privilege rules may have changed. 580 CarrierAppUtils.disableCarrierAppsUntilPrivileged(sContext.getOpPackageName(), 581 TelephonyManager.getDefault(), mCurrentlyActiveUserId, sContext); 582 583 /** 584 * The sim loading sequence will be 585 * 1. ACTION_SUBINFO_CONTENT_CHANGE happens through updateSubscriptionInfoByIccId() above. 586 * 2. ACTION_SIM_STATE_CHANGED/ACTION_SIM_CARD_STATE_CHANGED 587 * /ACTION_SIM_APPLICATION_STATE_CHANGED 588 * 3. ACTION_SUBSCRIPTION_CARRIER_IDENTITY_CHANGED 589 * 4. ACTION_CARRIER_CONFIG_CHANGED 590 */ 591 broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED, null); 592 broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_PRESENT); 593 broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_LOADED); 594 updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED); 595 updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_LOADED); 596 } 597 updateCarrierServices(int phoneId, String simState)598 private void updateCarrierServices(int phoneId, String simState) { 599 CarrierConfigManager configManager = 600 (CarrierConfigManager) sContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 601 configManager.updateConfigForPhoneId(phoneId, simState); 602 mCarrierServiceBindHelper.updateForPhoneId(phoneId, simState); 603 } 604 updateSubscriptionCarrierId(int phoneId, String simState)605 private void updateSubscriptionCarrierId(int phoneId, String simState) { 606 if (PhoneFactory.getPhone(phoneId) != null) { 607 PhoneFactory.getPhone(phoneId).resolveSubscriptionCarrierId(simState); 608 } 609 } 610 611 /** 612 * PhoneId is the corresponding phoneId of the slot if slot was previously active. 613 * It could be INVALID if it was already inactive. 614 */ handleInactiveSlotIccStateChange(int phoneId, String iccId)615 private void handleInactiveSlotIccStateChange(int phoneId, String iccId) { 616 if (SubscriptionManager.isValidPhoneId(phoneId)) { 617 // If phoneId is valid, it means the physical slot was previously active in that 618 // phoneId. In this case, found the subId and set its phoneId to invalid. 619 if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) { 620 logd("Slot of SIM" + (phoneId + 1) + " becomes inactive"); 621 } 622 cleanSubscriptionInPhone(phoneId); 623 } 624 if (!TextUtils.isEmpty(iccId)) { 625 // If iccId is new, add a subscription record in the db. 626 String strippedIccId = IccUtils.stripTrailingFs(iccId); 627 if (SubscriptionController.getInstance().getSubInfoForIccId(strippedIccId) == null) { 628 SubscriptionController.getInstance().insertEmptySubInfoRecord( 629 strippedIccId, "CARD", SubscriptionManager.INVALID_PHONE_INDEX, 630 SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); 631 } 632 } 633 } 634 cleanSubscriptionInPhone(int phoneId)635 private void cleanSubscriptionInPhone(int phoneId) { 636 sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM; 637 if (sInactiveIccIds[phoneId] != null) { 638 // When a SIM is unplugged, mark uicc applications enabled. This is to make sure when 639 // user unplugs and re-inserts the SIM card, we re-enable it. 640 logd("cleanSubscriptionInPhone " + phoneId + " inactive iccid " 641 + sInactiveIccIds[phoneId]); 642 ContentValues value = new ContentValues(1); 643 value.put(SubscriptionManager.UICC_APPLICATIONS_ENABLED, true); 644 sContext.getContentResolver().update(SubscriptionManager.CONTENT_URI, value, 645 SubscriptionManager.ICC_ID + "=\'" + sInactiveIccIds[phoneId] + "\'", null); 646 sInactiveIccIds[phoneId] = null; 647 } 648 updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */); 649 } 650 handleSimAbsent(int phoneId)651 protected void handleSimAbsent(int phoneId) { 652 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 653 logd("handleSimAbsent on invalid phoneId"); 654 return; 655 } 656 if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) { 657 logd("SIM" + (phoneId + 1) + " hot plug out"); 658 } 659 cleanSubscriptionInPhone(phoneId); 660 661 broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT, null); 662 broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_ABSENT); 663 broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_UNKNOWN); 664 updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT); 665 updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_ABSENT); 666 } 667 handleSimError(int phoneId)668 protected void handleSimError(int phoneId) { 669 if (sIccId[phoneId] != null && !sIccId[phoneId].equals(ICCID_STRING_FOR_NO_SIM)) { 670 logd("SIM" + (phoneId + 1) + " Error "); 671 } 672 sIccId[phoneId] = ICCID_STRING_FOR_NO_SIM; 673 updateSubscriptionInfoByIccId(phoneId, true /* updateEmbeddedSubs */); 674 broadcastSimStateChanged(phoneId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR, 675 IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR); 676 broadcastSimCardStateChanged(phoneId, TelephonyManager.SIM_STATE_CARD_IO_ERROR); 677 broadcastSimApplicationStateChanged(phoneId, TelephonyManager.SIM_STATE_NOT_READY); 678 updateSubscriptionCarrierId(phoneId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR); 679 updateCarrierServices(phoneId, IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR); 680 } 681 updateSubscriptionInfoByIccId(int phoneId, boolean updateEmbeddedSubs)682 protected synchronized void updateSubscriptionInfoByIccId(int phoneId, 683 boolean updateEmbeddedSubs) { 684 logd("updateSubscriptionInfoByIccId:+ Start - phoneId: " + phoneId); 685 if (!SubscriptionManager.isValidPhoneId(phoneId)) { 686 loge("[updateSubscriptionInfoByIccId]- invalid phoneId=" + phoneId); 687 return; 688 } 689 logd("updateSubscriptionInfoByIccId: removing subscription info record: phoneId " 690 + phoneId); 691 // Clear phoneId only when sim absent is not enough. It's possible to switch SIM profile 692 // within the same slot. Need to clear the slot index of the previous sub. Thus always clear 693 // for the changing slot first. 694 SubscriptionController.getInstance().clearSubInfoRecord(phoneId); 695 696 // If SIM is not absent, insert new record or update existing record. 697 if (!ICCID_STRING_FOR_NO_SIM.equals(sIccId[phoneId])) { 698 logd("updateSubscriptionInfoByIccId: adding subscription info record: iccid: " 699 + sIccId[phoneId] + ", phoneId:" + phoneId); 700 mSubscriptionManager.addSubscriptionInfoRecord(sIccId[phoneId], phoneId); 701 } 702 703 List<SubscriptionInfo> subInfos = SubscriptionController.getInstance() 704 .getSubInfoUsingSlotIndexPrivileged(phoneId); 705 if (subInfos != null) { 706 boolean changed = false; 707 for (int i = 0; i < subInfos.size(); i++) { 708 SubscriptionInfo temp = subInfos.get(i); 709 ContentValues value = new ContentValues(1); 710 711 String msisdn = TelephonyManager.getDefault().getLine1Number( 712 temp.getSubscriptionId()); 713 714 if (!TextUtils.equals(msisdn, temp.getNumber())) { 715 value.put(SubscriptionManager.NUMBER, msisdn); 716 sContext.getContentResolver().update(SubscriptionManager 717 .getUriForSubscriptionId(temp.getSubscriptionId()), value, null, null); 718 changed = true; 719 } 720 } 721 if (changed) { 722 // refresh Cached Active Subscription Info List 723 SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList(); 724 } 725 } 726 727 // TODO investigate if we can update for each slot separately. 728 if (isAllIccIdQueryDone()) { 729 // Ensure the modems are mapped correctly 730 if (mSubscriptionManager.isActiveSubId( 731 mSubscriptionManager.getDefaultDataSubscriptionId())) { 732 mSubscriptionManager.setDefaultDataSubId( 733 mSubscriptionManager.getDefaultDataSubscriptionId()); 734 } else { 735 logd("bypass reset default data sub if inactive"); 736 } 737 setSubInfoInitialized(); 738 } 739 740 UiccController uiccController = UiccController.getInstance(); 741 UiccSlot[] uiccSlots = uiccController.getUiccSlots(); 742 if (uiccSlots != null && updateEmbeddedSubs) { 743 List<Integer> cardIds = new ArrayList<>(); 744 for (UiccSlot uiccSlot : uiccSlots) { 745 if (uiccSlot != null && uiccSlot.getUiccCard() != null) { 746 int cardId = uiccController.convertToPublicCardId( 747 uiccSlot.getUiccCard().getCardId()); 748 cardIds.add(cardId); 749 } 750 } 751 updateEmbeddedSubscriptions(cardIds, (hasChanges) -> { 752 if (hasChanges) { 753 SubscriptionController.getInstance().notifySubscriptionInfoChanged(); 754 } 755 if (DBG) logd("updateSubscriptionInfoByIccId: SubscriptionInfo update complete"); 756 }); 757 } 758 759 SubscriptionController.getInstance().notifySubscriptionInfoChanged(); 760 if (DBG) logd("updateSubscriptionInfoByIccId: SubscriptionInfo update complete"); 761 } 762 setSubInfoInitialized()763 private static void setSubInfoInitialized() { 764 // Should only be triggered once. 765 if (!sIsSubInfoInitialized) { 766 if (DBG) logd("SubInfo Initialized"); 767 sIsSubInfoInitialized = true; 768 SubscriptionController.getInstance().notifySubInfoReady(); 769 MultiSimSettingController.getInstance().notifyAllSubscriptionLoaded(); 770 } 771 } 772 773 /** 774 * Whether subscriptions of all SIMs are initialized. 775 */ isSubInfoInitialized()776 public static boolean isSubInfoInitialized() { 777 return sIsSubInfoInitialized; 778 } 779 780 /** 781 * Updates the cached list of embedded subscription for the eUICC with the given list of card 782 * IDs {@code cardIds}. The step of reading the embedded subscription list from eUICC card is 783 * executed in background thread. The callback {@code callback} is executed after the cache is 784 * refreshed. The callback is executed in main thread. 785 */ 786 @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE) updateEmbeddedSubscriptions(List<Integer> cardIds, @Nullable UpdateEmbeddedSubsCallback callback)787 public void updateEmbeddedSubscriptions(List<Integer> cardIds, 788 @Nullable UpdateEmbeddedSubsCallback callback) { 789 // Do nothing if eUICCs are disabled. (Previous entries may remain in the cache, but they 790 // are filtered out of list calls as long as EuiccManager.isEnabled returns false). 791 if (!mEuiccManager.isEnabled()) { 792 callback.run(false /* hasChanges */); 793 return; 794 } 795 796 mBackgroundHandler.post(() -> { 797 List<Pair<Integer, GetEuiccProfileInfoListResult>> results = new ArrayList<>(); 798 for (int cardId : cardIds) { 799 GetEuiccProfileInfoListResult result = 800 EuiccController.get().blockingGetEuiccProfileInfoList(cardId); 801 if (DBG) logd("blockingGetEuiccProfileInfoList cardId " + cardId); 802 results.add(Pair.create(cardId, result)); 803 } 804 805 // The runnable will be executed in the main thread. 806 this.post(() -> { 807 boolean hasChanges = false; 808 for (Pair<Integer, GetEuiccProfileInfoListResult> cardIdAndResult : results) { 809 if (updateEmbeddedSubscriptionsCache(cardIdAndResult.first, 810 cardIdAndResult.second)) { 811 hasChanges = true; 812 } 813 } 814 // The latest state in the main thread may be changed when the callback is 815 // triggered. 816 if (callback != null) { 817 callback.run(hasChanges); 818 } 819 }); 820 }); 821 } 822 823 /** 824 * Update the cached list of embedded subscription based on the passed in 825 * GetEuiccProfileInfoListResult {@code result}. 826 * 827 * @return true if changes may have been made. This is not a guarantee that changes were made, 828 * but notifications about subscription changes may be skipped if this returns false as an 829 * optimization to avoid spurious notifications. 830 */ updateEmbeddedSubscriptionsCache(int cardId, GetEuiccProfileInfoListResult result)831 private boolean updateEmbeddedSubscriptionsCache(int cardId, 832 GetEuiccProfileInfoListResult result) { 833 if (DBG) logd("updateEmbeddedSubscriptionsCache"); 834 835 if (result == null) { 836 // IPC to the eUICC controller failed. 837 return false; 838 } 839 840 // If the returned result is not RESULT_OK or the profile list is null, don't update cache. 841 // Otherwise, update the cache. 842 final EuiccProfileInfo[] embeddedProfiles; 843 List<EuiccProfileInfo> list = result.getProfiles(); 844 if (result.getResult() == EuiccService.RESULT_OK && list != null) { 845 embeddedProfiles = list.toArray(new EuiccProfileInfo[list.size()]); 846 if (DBG) { 847 logd("blockingGetEuiccProfileInfoList: got " + result.getProfiles().size() 848 + " profiles"); 849 } 850 } else { 851 if (DBG) { 852 logd("blockingGetEuiccProfileInfoList returns an error. " 853 + "Result code=" + result.getResult() 854 + ". Null profile list=" + (result.getProfiles() == null)); 855 } 856 return false; 857 } 858 859 final boolean isRemovable = result.getIsRemovable(); 860 861 final String[] embeddedIccids = new String[embeddedProfiles.length]; 862 for (int i = 0; i < embeddedProfiles.length; i++) { 863 embeddedIccids[i] = embeddedProfiles[i].getIccid(); 864 } 865 866 if (DBG) logd("Get eUICC profile list of size " + embeddedProfiles.length); 867 868 // Note that this only tracks whether we make any writes to the DB. It's possible this will 869 // be set to true for an update even when the row contents remain exactly unchanged from 870 // before, since we don't compare against the previous value. Since this is only intended to 871 // avoid some spurious broadcasts (particularly for users who don't use eSIM at all), this 872 // is fine. 873 boolean hasChanges = false; 874 875 // Update or insert records for all embedded subscriptions (except non-removable ones if the 876 // current eUICC is non-removable, since we assume these are still accessible though not 877 // returned by the eUICC controller). 878 List<SubscriptionInfo> existingSubscriptions = SubscriptionController.getInstance() 879 .getSubscriptionInfoListForEmbeddedSubscriptionUpdate(embeddedIccids, isRemovable); 880 ContentResolver contentResolver = sContext.getContentResolver(); 881 for (EuiccProfileInfo embeddedProfile : embeddedProfiles) { 882 int index = 883 findSubscriptionInfoForIccid(existingSubscriptions, embeddedProfile.getIccid()); 884 int prevCarrierId = TelephonyManager.UNKNOWN_CARRIER_ID; 885 int nameSource = SubscriptionManager.NAME_SOURCE_CARRIER_ID; 886 if (index < 0) { 887 // No existing entry for this ICCID; create an empty one. 888 SubscriptionController.getInstance().insertEmptySubInfoRecord( 889 embeddedProfile.getIccid(), SubscriptionManager.SIM_NOT_INSERTED); 890 } else { 891 nameSource = existingSubscriptions.get(index).getNameSource(); 892 prevCarrierId = existingSubscriptions.get(index).getCarrierId(); 893 existingSubscriptions.remove(index); 894 } 895 896 if (DBG) { 897 logd("embeddedProfile " + embeddedProfile + " existing record " 898 + (index < 0 ? "not found" : "found")); 899 } 900 901 ContentValues values = new ContentValues(); 902 values.put(SubscriptionManager.IS_EMBEDDED, 1); 903 List<UiccAccessRule> ruleList = embeddedProfile.getUiccAccessRules(); 904 boolean isRuleListEmpty = false; 905 if (ruleList == null || ruleList.size() == 0) { 906 isRuleListEmpty = true; 907 } 908 values.put(SubscriptionManager.ACCESS_RULES, 909 isRuleListEmpty ? null : UiccAccessRule.encodeRules( 910 ruleList.toArray(new UiccAccessRule[ruleList.size()]))); 911 values.put(SubscriptionManager.IS_REMOVABLE, isRemovable); 912 // override DISPLAY_NAME if the priority of existing nameSource is <= carrier 913 if (SubscriptionController.getNameSourcePriority(nameSource) 914 <= SubscriptionController.getNameSourcePriority( 915 SubscriptionManager.NAME_SOURCE_CARRIER)) { 916 values.put(SubscriptionManager.DISPLAY_NAME, embeddedProfile.getNickname()); 917 values.put(SubscriptionManager.NAME_SOURCE, 918 SubscriptionManager.NAME_SOURCE_CARRIER); 919 } 920 values.put(SubscriptionManager.PROFILE_CLASS, embeddedProfile.getProfileClass()); 921 CarrierIdentifier cid = embeddedProfile.getCarrierIdentifier(); 922 if (cid != null) { 923 // Due to the limited subscription information, carrier id identified here might 924 // not be accurate compared with CarrierResolver. Only update carrier id if there 925 // is no valid carrier id present. 926 if (prevCarrierId == TelephonyManager.UNKNOWN_CARRIER_ID) { 927 values.put(SubscriptionManager.CARRIER_ID, 928 CarrierResolver.getCarrierIdFromIdentifier(sContext, cid)); 929 } 930 String mcc = cid.getMcc(); 931 String mnc = cid.getMnc(); 932 values.put(SubscriptionManager.MCC_STRING, mcc); 933 values.put(SubscriptionManager.MCC, mcc); 934 values.put(SubscriptionManager.MNC_STRING, mnc); 935 values.put(SubscriptionManager.MNC, mnc); 936 } 937 // If cardId = unsupported or unitialized, we have no reason to update DB. 938 // Additionally, if the device does not support cardId for default eUICC, the CARD_ID 939 // field should not contain the EID 940 UiccController uiccController = UiccController.getInstance(); 941 if (cardId >= 0 && uiccController.getCardIdForDefaultEuicc() 942 != TelephonyManager.UNSUPPORTED_CARD_ID) { 943 values.put(SubscriptionManager.CARD_ID, uiccController.convertToCardString(cardId)); 944 } 945 hasChanges = true; 946 contentResolver.update(SubscriptionManager.CONTENT_URI, values, 947 SubscriptionManager.ICC_ID + "=\"" + embeddedProfile.getIccid() + "\"", null); 948 949 // refresh Cached Active Subscription Info List 950 SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList(); 951 } 952 953 // Remove all remaining subscriptions which have embedded = true. We set embedded to false 954 // to ensure they are not returned in the list of embedded subscriptions (but keep them 955 // around in case the subscription is added back later, which is equivalent to a removable 956 // SIM being removed and reinserted). 957 if (!existingSubscriptions.isEmpty()) { 958 if (DBG) { 959 logd("Removing existing embedded subscriptions of size" 960 + existingSubscriptions.size()); 961 } 962 List<String> iccidsToRemove = new ArrayList<>(); 963 for (int i = 0; i < existingSubscriptions.size(); i++) { 964 SubscriptionInfo info = existingSubscriptions.get(i); 965 if (info.isEmbedded()) { 966 if (DBG) logd("Removing embedded subscription of IccId " + info.getIccId()); 967 iccidsToRemove.add("\"" + info.getIccId() + "\""); 968 } 969 } 970 String whereClause = SubscriptionManager.ICC_ID + " IN (" 971 + TextUtils.join(",", iccidsToRemove) + ")"; 972 ContentValues values = new ContentValues(); 973 values.put(SubscriptionManager.IS_EMBEDDED, 0); 974 hasChanges = true; 975 contentResolver.update(SubscriptionManager.CONTENT_URI, values, whereClause, null); 976 977 // refresh Cached Active Subscription Info List 978 SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList(); 979 } 980 981 if (DBG) logd("updateEmbeddedSubscriptions done hasChanges=" + hasChanges); 982 return hasChanges; 983 } 984 985 /** 986 * Called by CarrierConfigLoader to update the subscription before sending a broadcast. 987 */ updateSubscriptionByCarrierConfigAndNotifyComplete(int phoneId, String configPackageName, PersistableBundle config, Message onComplete)988 public void updateSubscriptionByCarrierConfigAndNotifyComplete(int phoneId, 989 String configPackageName, PersistableBundle config, Message onComplete) { 990 post(() -> { 991 updateSubscriptionByCarrierConfig(phoneId, configPackageName, config); 992 onComplete.sendToTarget(); 993 }); 994 } 995 getDefaultCarrierServicePackageName()996 private String getDefaultCarrierServicePackageName() { 997 CarrierConfigManager configManager = 998 (CarrierConfigManager) sContext.getSystemService(Context.CARRIER_CONFIG_SERVICE); 999 return configManager.getDefaultCarrierServicePackageName(); 1000 } 1001 isCarrierServicePackage(int phoneId, String pkgName)1002 private boolean isCarrierServicePackage(int phoneId, String pkgName) { 1003 if (pkgName.equals(getDefaultCarrierServicePackageName())) return false; 1004 1005 List<String> carrierPackageNames = TelephonyManager.from(sContext) 1006 .getCarrierPackageNamesForIntentAndPhone( 1007 new Intent(CarrierService.CARRIER_SERVICE_INTERFACE), phoneId); 1008 if (DBG) logd("Carrier Packages For Subscription = " + carrierPackageNames); 1009 return carrierPackageNames != null && carrierPackageNames.contains(pkgName); 1010 } 1011 1012 /** 1013 * Update the currently active Subscription based on information from CarrierConfig 1014 */ 1015 @VisibleForTesting updateSubscriptionByCarrierConfig( int phoneId, String configPackageName, PersistableBundle config)1016 public void updateSubscriptionByCarrierConfig( 1017 int phoneId, String configPackageName, PersistableBundle config) { 1018 if (!SubscriptionManager.isValidPhoneId(phoneId) 1019 || TextUtils.isEmpty(configPackageName) || config == null) { 1020 if (DBG) { 1021 logd("In updateSubscriptionByCarrierConfig(): phoneId=" + phoneId 1022 + " configPackageName=" + configPackageName + " config=" 1023 + ((config == null) ? "null" : config.hashCode())); 1024 } 1025 return; 1026 } 1027 1028 SubscriptionController sc = SubscriptionController.getInstance(); 1029 if (sc == null) { 1030 loge("SubscriptionController was null"); 1031 return; 1032 } 1033 1034 int currentSubId = sc.getSubIdUsingPhoneId(phoneId); 1035 if (!SubscriptionManager.isValidSubscriptionId(currentSubId) 1036 || currentSubId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { 1037 if (DBG) logd("No subscription is active for phone being updated"); 1038 return; 1039 } 1040 1041 SubscriptionInfo currentSubInfo = sc.getSubscriptionInfo(currentSubId); 1042 if (currentSubInfo == null) { 1043 loge("Couldn't retrieve subscription info for current subscription"); 1044 return; 1045 } 1046 1047 ContentValues cv = new ContentValues(); 1048 ParcelUuid groupUuid = null; 1049 1050 // carrier certificates are not subscription-specific, so we want to load them even if 1051 // this current package is not a CarrierServicePackage 1052 String[] certs = config.getStringArray( 1053 CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY); 1054 if (certs != null) { 1055 UiccAccessRule[] 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 cv.put(SubscriptionManager.ACCESS_RULES_FROM_CARRIER_CONFIGS, 1061 UiccAccessRule.encodeRules(carrierConfigAccessRules)); 1062 } 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