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 android.telephony; 18 19 import static android.text.TextUtils.formatSimple; 20 21 import android.annotation.Nullable; 22 import android.annotation.SystemApi; 23 import android.compat.annotation.UnsupportedAppUsage; 24 import android.content.Context; 25 import android.content.pm.PackageInfo; 26 import android.content.pm.PackageManager; 27 import android.graphics.Bitmap; 28 import android.graphics.BitmapFactory; 29 import android.graphics.Canvas; 30 import android.graphics.Color; 31 import android.graphics.Paint; 32 import android.graphics.PorterDuff; 33 import android.graphics.PorterDuffColorFilter; 34 import android.graphics.Rect; 35 import android.graphics.Typeface; 36 import android.os.Build; 37 import android.os.Parcel; 38 import android.os.ParcelUuid; 39 import android.os.Parcelable; 40 import android.telephony.SubscriptionManager.UsageSetting; 41 import android.text.TextUtils; 42 import android.util.DisplayMetrics; 43 import android.util.Log; 44 45 import com.android.internal.telephony.util.TelephonyUtils; 46 import com.android.telephony.Rlog; 47 48 import java.util.ArrayList; 49 import java.util.Arrays; 50 import java.util.Collections; 51 import java.util.List; 52 import java.util.Objects; 53 54 /** 55 * A Parcelable class for Subscription Information. 56 */ 57 public class SubscriptionInfo implements Parcelable { 58 59 /** 60 * Size of text to render on the icon. 61 */ 62 private static final int TEXT_SIZE = 16; 63 64 /** 65 * Subscription Identifier, this is a device unique number 66 * and not an index into an array 67 */ 68 private int mId; 69 70 /** 71 * The GID for a SIM that maybe associated with this subscription, empty if unknown 72 */ 73 private String mIccId; 74 75 /** 76 * The index of the slot that currently contains the subscription 77 * and not necessarily unique and maybe INVALID_SLOT_ID if unknown 78 */ 79 private int mSimSlotIndex; 80 81 /** 82 * The name displayed to the user that identifies this subscription 83 */ 84 private CharSequence mDisplayName; 85 86 /** 87 * String that identifies SPN/PLMN 88 * TODO : Add a new field that identifies only SPN for a sim 89 */ 90 private CharSequence mCarrierName; 91 92 /** 93 * The subscription carrier id. 94 * @see TelephonyManager#getSimCarrierId() 95 */ 96 private int mCarrierId; 97 98 /** 99 * The source of the name, NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SPN, 100 * NAME_SOURCE_SIM_PNN, or NAME_SOURCE_USER_INPUT. 101 */ 102 private int mNameSource; 103 104 /** 105 * The color to be used for tinting the icon when displaying to the user 106 */ 107 private int mIconTint; 108 109 /** 110 * A number presented to the user identify this subscription 111 */ 112 private String mNumber; 113 114 /** 115 * Data roaming state, DATA_ROAMING_ENABLE, DATA_ROAMING_DISABLE 116 */ 117 private int mDataRoaming; 118 119 /** 120 * SIM icon bitmap cache 121 */ 122 @Nullable private Bitmap mIconBitmap; 123 124 /** 125 * Mobile Country Code 126 */ 127 private String mMcc; 128 129 /** 130 * Mobile Network Code 131 */ 132 private String mMnc; 133 134 /** 135 * EHPLMNs associated with the subscription 136 */ 137 private String[] mEhplmns; 138 139 /** 140 * HPLMNs associated with the subscription 141 */ 142 private String[] mHplmns; 143 144 /** 145 * ISO Country code for the subscription's provider 146 */ 147 private String mCountryIso; 148 149 /** 150 * Whether the subscription is an embedded one. 151 */ 152 private boolean mIsEmbedded; 153 154 /** 155 * The access rules for this subscription, if it is embedded and defines any. 156 * This does not include access rules for non-embedded subscriptions. 157 */ 158 @Nullable 159 private UiccAccessRule[] mNativeAccessRules; 160 161 /** 162 * The carrier certificates for this subscription that are saved in carrier configs. 163 * This does not include access rules from the Uicc, whether embedded or non-embedded. 164 */ 165 @Nullable 166 private UiccAccessRule[] mCarrierConfigAccessRules; 167 168 /** 169 * The string ID of the SIM card. It is the ICCID of the active profile for a UICC card and the 170 * EID for an eUICC card. 171 */ 172 private String mCardString; 173 174 /** 175 * The card ID of the SIM card. This maps uniquely to the card string. 176 */ 177 private int mCardId; 178 179 /** 180 * Whether the subscription is opportunistic. 181 */ 182 private boolean mIsOpportunistic; 183 184 /** 185 * A UUID assigned to the subscription group. It returns null if not assigned. 186 * Check {@link SubscriptionManager#createSubscriptionGroup(List)} for more details. 187 */ 188 @Nullable 189 private ParcelUuid mGroupUUID; 190 191 /** 192 * A package name that specifies who created the group. Null if mGroupUUID is null. 193 */ 194 private String mGroupOwner; 195 196 /** 197 * Whether group of the subscription is disabled. 198 * This is only useful if it's a grouped opportunistic subscription. In this case, if all 199 * primary (non-opportunistic) subscriptions in the group are deactivated (unplugged pSIM 200 * or deactivated eSIM profile), we should disable this opportunistic subscription. 201 */ 202 private boolean mIsGroupDisabled = false; 203 204 /** 205 * Profile class, PROFILE_CLASS_TESTING, PROFILE_CLASS_OPERATIONAL 206 * PROFILE_CLASS_PROVISIONING, or PROFILE_CLASS_UNSET. 207 * A profile on the eUICC can be defined as test, operational, provisioning, or unset. 208 * The profile class will be populated from the profile metadata if present. Otherwise, 209 * the profile class defaults to unset if there is no profile metadata or the subscription 210 * is not on an eUICC ({@link #isEmbedded} returns false). 211 */ 212 private int mProfileClass; 213 214 /** 215 * Type of subscription 216 */ 217 private int mSubscriptionType; 218 219 /** 220 * Whether uicc applications are configured to enable or disable. 221 * By default it's true. 222 */ 223 private boolean mAreUiccApplicationsEnabled = true; 224 225 /** 226 * The port index of the Uicc card. 227 */ 228 private final int mPortIndex; 229 230 /** 231 * Subscription's preferred usage setting. 232 */ 233 private @UsageSetting int mUsageSetting = SubscriptionManager.USAGE_SETTING_UNKNOWN; 234 235 /** 236 * Public copy constructor. 237 * @hide 238 */ SubscriptionInfo(SubscriptionInfo info)239 public SubscriptionInfo(SubscriptionInfo info) { 240 this(info.mId, info.mIccId, info.mSimSlotIndex, info.mDisplayName, info.mCarrierName, 241 info.mNameSource, info.mIconTint, info.mNumber, info.mDataRoaming, info.mIconBitmap, 242 info.mMcc, info.mMnc, info.mCountryIso, info.mIsEmbedded, info.mNativeAccessRules, 243 info.mCardString, info.mCardId, info.mIsOpportunistic, 244 info.mGroupUUID == null ? null : info.mGroupUUID.toString(), info.mIsGroupDisabled, 245 info.mCarrierId, info.mProfileClass, info.mSubscriptionType, info.mGroupOwner, 246 info.mCarrierConfigAccessRules, info.mAreUiccApplicationsEnabled); 247 } 248 249 /** 250 * @hide 251 */ SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded, @Nullable UiccAccessRule[] nativeAccessRules, String cardString)252 public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, 253 CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, 254 Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded, 255 @Nullable UiccAccessRule[] nativeAccessRules, String cardString) { 256 this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number, 257 roaming, icon, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, -1, 258 false, null, false, TelephonyManager.UNKNOWN_CARRIER_ID, 259 SubscriptionManager.PROFILE_CLASS_UNSET, 260 SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null, null, true); 261 } 262 263 /** 264 * @hide 265 */ SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded, @Nullable UiccAccessRule[] nativeAccessRules, String cardString, boolean isOpportunistic, @Nullable String groupUUID, int carrierId, int profileClass)266 public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, 267 CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, 268 Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded, 269 @Nullable UiccAccessRule[] nativeAccessRules, String cardString, 270 boolean isOpportunistic, @Nullable String groupUUID, int carrierId, int profileClass) { 271 this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number, 272 roaming, icon, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, -1, 273 isOpportunistic, groupUUID, false, carrierId, profileClass, 274 SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM, null, null, true); 275 } 276 277 /** 278 * @hide 279 */ SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded, @Nullable UiccAccessRule[] nativeAccessRules, String cardString, int cardId, boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled, int carrierId, int profileClass, int subType, @Nullable String groupOwner, @Nullable UiccAccessRule[] carrierConfigAccessRules, boolean areUiccApplicationsEnabled)280 public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, 281 CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, 282 Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded, 283 @Nullable UiccAccessRule[] nativeAccessRules, String cardString, int cardId, 284 boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled, 285 int carrierId, int profileClass, int subType, @Nullable String groupOwner, 286 @Nullable UiccAccessRule[] carrierConfigAccessRules, 287 boolean areUiccApplicationsEnabled) { 288 this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number, 289 roaming, icon, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, 290 cardId, isOpportunistic, groupUUID, isGroupDisabled, carrierId, profileClass, 291 subType, groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, 0); 292 } 293 294 /** 295 * @hide 296 */ SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded, @Nullable UiccAccessRule[] nativeAccessRules, String cardString, int cardId, boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled, int carrierId, int profileClass, int subType, @Nullable String groupOwner, @Nullable UiccAccessRule[] carrierConfigAccessRules, boolean areUiccApplicationsEnabled, int portIndex)297 public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, 298 CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, 299 Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded, 300 @Nullable UiccAccessRule[] nativeAccessRules, String cardString, int cardId, 301 boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled, 302 int carrierId, int profileClass, int subType, @Nullable String groupOwner, 303 @Nullable UiccAccessRule[] carrierConfigAccessRules, 304 boolean areUiccApplicationsEnabled, int portIndex) { 305 this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number, 306 roaming, icon, mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, 307 cardId, isOpportunistic, groupUUID, isGroupDisabled, carrierId, profileClass, 308 subType, groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, 309 portIndex, SubscriptionManager.USAGE_SETTING_DEFAULT); 310 } 311 312 /** 313 * @hide 314 */ SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded, @Nullable UiccAccessRule[] nativeAccessRules, String cardString, int cardId, boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled, int carrierId, int profileClass, int subType, @Nullable String groupOwner, @Nullable UiccAccessRule[] carrierConfigAccessRules, boolean areUiccApplicationsEnabled, int portIndex, @UsageSetting int usageSetting)315 public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, 316 CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, 317 Bitmap icon, String mcc, String mnc, String countryIso, boolean isEmbedded, 318 @Nullable UiccAccessRule[] nativeAccessRules, String cardString, int cardId, 319 boolean isOpportunistic, @Nullable String groupUUID, boolean isGroupDisabled, 320 int carrierId, int profileClass, int subType, @Nullable String groupOwner, 321 @Nullable UiccAccessRule[] carrierConfigAccessRules, 322 boolean areUiccApplicationsEnabled, int portIndex, @UsageSetting int usageSetting) { 323 this.mId = id; 324 this.mIccId = iccId; 325 this.mSimSlotIndex = simSlotIndex; 326 this.mDisplayName = displayName; 327 this.mCarrierName = carrierName; 328 this.mNameSource = nameSource; 329 this.mIconTint = iconTint; 330 this.mNumber = number; 331 this.mDataRoaming = roaming; 332 this.mIconBitmap = icon; 333 this.mMcc = mcc; 334 this.mMnc = mnc; 335 this.mCountryIso = countryIso; 336 this.mIsEmbedded = isEmbedded; 337 this.mNativeAccessRules = nativeAccessRules; 338 this.mCardString = cardString; 339 this.mCardId = cardId; 340 this.mIsOpportunistic = isOpportunistic; 341 this.mGroupUUID = groupUUID == null ? null : ParcelUuid.fromString(groupUUID); 342 this.mIsGroupDisabled = isGroupDisabled; 343 this.mCarrierId = carrierId; 344 this.mProfileClass = profileClass; 345 this.mSubscriptionType = subType; 346 this.mGroupOwner = groupOwner; 347 this.mCarrierConfigAccessRules = carrierConfigAccessRules; 348 this.mAreUiccApplicationsEnabled = areUiccApplicationsEnabled; 349 this.mPortIndex = portIndex; 350 this.mUsageSetting = usageSetting; 351 } 352 /** 353 * @return the subscription ID. 354 */ getSubscriptionId()355 public int getSubscriptionId() { 356 return this.mId; 357 } 358 359 /** 360 * Returns the ICC ID. 361 * 362 * Starting with API level 29 Security Patch 2021-04-05, returns the ICC ID if the calling app 363 * has been granted the READ_PRIVILEGED_PHONE_STATE permission, has carrier privileges (see 364 * {@link TelephonyManager#hasCarrierPrivileges}), or is a device owner or profile owner that 365 * has been granted the READ_PHONE_STATE permission. The profile owner is an app that owns a 366 * managed profile on the device; for more details see <a 367 * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile 368 * owner access is deprecated and will be removed in a future release. 369 * 370 * @return the ICC ID, or an empty string if one of these requirements is not met 371 */ getIccId()372 public String getIccId() { 373 return this.mIccId; 374 } 375 376 /** 377 * @hide 378 */ clearIccId()379 public void clearIccId() { 380 this.mIccId = ""; 381 } 382 383 /** 384 * @return the slot index of this Subscription's SIM card. 385 */ getSimSlotIndex()386 public int getSimSlotIndex() { 387 return this.mSimSlotIndex; 388 } 389 390 /** 391 * @return the carrier id of this Subscription carrier. 392 * @see TelephonyManager#getSimCarrierId() 393 */ getCarrierId()394 public int getCarrierId() { 395 return this.mCarrierId; 396 } 397 398 /** 399 * @return the name displayed to the user that identifies this subscription 400 */ getDisplayName()401 public CharSequence getDisplayName() { 402 return this.mDisplayName; 403 } 404 405 /** 406 * Sets the name displayed to the user that identifies this subscription 407 * @hide 408 */ 409 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setDisplayName(CharSequence name)410 public void setDisplayName(CharSequence name) { 411 this.mDisplayName = name; 412 } 413 414 /** 415 * @return the name displayed to the user that identifies Subscription provider name 416 */ getCarrierName()417 public CharSequence getCarrierName() { 418 return this.mCarrierName; 419 } 420 421 /** 422 * Sets the name displayed to the user that identifies Subscription provider name 423 * @hide 424 */ setCarrierName(CharSequence name)425 public void setCarrierName(CharSequence name) { 426 this.mCarrierName = name; 427 } 428 429 /** 430 * @return the source of the name, eg NAME_SOURCE_DEFAULT_SOURCE, NAME_SOURCE_SIM_SPN or 431 * NAME_SOURCE_USER_INPUT. 432 * @hide 433 */ 434 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getNameSource()435 public int getNameSource() { 436 return this.mNameSource; 437 } 438 439 /** 440 * @hide 441 */ setAssociatedPlmns(String[] ehplmns, String[] hplmns)442 public void setAssociatedPlmns(String[] ehplmns, String[] hplmns) { 443 mEhplmns = ehplmns; 444 mHplmns = hplmns; 445 } 446 447 /** 448 * Creates and returns an icon {@code Bitmap} to represent this {@code SubscriptionInfo} in a 449 * user interface. 450 * 451 * @param context A {@code Context} to get the {@code DisplayMetrics}s from. 452 * 453 * @return A bitmap icon for this {@code SubscriptionInfo}. 454 */ createIconBitmap(Context context)455 public Bitmap createIconBitmap(Context context) { 456 if (mIconBitmap == null) { 457 mIconBitmap = BitmapFactory.decodeResource(context.getResources(), 458 com.android.internal.R.drawable.ic_sim_card_multi_24px_clr); 459 } 460 int width = mIconBitmap.getWidth(); 461 int height = mIconBitmap.getHeight(); 462 DisplayMetrics metrics = context.getResources().getDisplayMetrics(); 463 464 // Create a new bitmap of the same size because it will be modified. 465 Bitmap workingBitmap = Bitmap.createBitmap(metrics, width, height, mIconBitmap.getConfig()); 466 467 Canvas canvas = new Canvas(workingBitmap); 468 Paint paint = new Paint(); 469 470 // Tint the icon with the color. 471 paint.setColorFilter(new PorterDuffColorFilter(mIconTint, PorterDuff.Mode.SRC_ATOP)); 472 canvas.drawBitmap(mIconBitmap, 0, 0, paint); 473 paint.setColorFilter(null); 474 475 // Write the sim slot index. 476 paint.setAntiAlias(true); 477 paint.setTypeface(Typeface.create("sans-serif", Typeface.NORMAL)); 478 paint.setColor(Color.WHITE); 479 // Set text size scaled by density 480 paint.setTextSize(TEXT_SIZE * metrics.density); 481 // Convert sim slot index to localized string 482 final String index = formatSimple("%d", mSimSlotIndex + 1); 483 final Rect textBound = new Rect(); 484 paint.getTextBounds(index, 0, 1, textBound); 485 final float xOffset = (width / 2.f) - textBound.centerX(); 486 final float yOffset = (height / 2.f) - textBound.centerY(); 487 canvas.drawText(index, xOffset, yOffset, paint); 488 489 return workingBitmap; 490 } 491 492 /** 493 * A highlight color to use in displaying information about this {@code PhoneAccount}. 494 * 495 * @return A hexadecimal color value. 496 */ getIconTint()497 public int getIconTint() { 498 return mIconTint; 499 } 500 501 /** 502 * Sets the color displayed to the user that identifies this subscription 503 * @hide 504 */ 505 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setIconTint(int iconTint)506 public void setIconTint(int iconTint) { 507 this.mIconTint = iconTint; 508 } 509 510 /** 511 * Returns the number of this subscription. 512 * 513 * Starting with API level 30, returns the number of this subscription if the calling app meets 514 * one of the following requirements: 515 * <ul> 516 * <li>If the calling app's target SDK is API level 29 or lower and the app has been granted 517 * the READ_PHONE_STATE permission. 518 * <li>If the calling app has been granted any of READ_PRIVILEGED_PHONE_STATE, 519 * READ_PHONE_NUMBERS, or READ_SMS. 520 * <li>If the calling app has carrier privileges (see {@link 521 * TelephonyManager#hasCarrierPrivileges}). 522 * <li>If the calling app is the default SMS role holder. 523 * </ul> 524 * 525 * @return the number of this subscription, or an empty string if one of these requirements is 526 * not met 527 * @deprecated use {@link SubscriptionManager#getPhoneNumber(int)} instead, which takes a 528 * {@link #getSubscriptionId() subscription ID}. 529 */ 530 @Deprecated getNumber()531 public String getNumber() { 532 return mNumber; 533 } 534 535 /** 536 * @hide 537 */ clearNumber()538 public void clearNumber() { 539 mNumber = ""; 540 } 541 542 /** 543 * @return the data roaming state for this subscription, either 544 * {@link SubscriptionManager#DATA_ROAMING_ENABLE} or {@link SubscriptionManager#DATA_ROAMING_DISABLE}. 545 */ getDataRoaming()546 public int getDataRoaming() { 547 return this.mDataRoaming; 548 } 549 550 /** 551 * @return the MCC. 552 * @deprecated Use {@link #getMccString()} instead. 553 */ 554 @Deprecated getMcc()555 public int getMcc() { 556 try { 557 return this.mMcc == null ? 0 : Integer.valueOf(this.mMcc); 558 } catch (NumberFormatException e) { 559 Log.w(SubscriptionInfo.class.getSimpleName(), "MCC string is not a number"); 560 return 0; 561 } 562 } 563 564 /** 565 * @return the MNC. 566 * @deprecated Use {@link #getMncString()} instead. 567 */ 568 @Deprecated getMnc()569 public int getMnc() { 570 try { 571 return this.mMnc == null ? 0 : Integer.valueOf(this.mMnc); 572 } catch (NumberFormatException e) { 573 Log.w(SubscriptionInfo.class.getSimpleName(), "MNC string is not a number"); 574 return 0; 575 } 576 } 577 578 /** 579 * @return The MCC, as a string. 580 */ getMccString()581 public @Nullable String getMccString() { 582 return this.mMcc; 583 } 584 585 /** 586 * @return The MNC, as a string. 587 */ getMncString()588 public @Nullable String getMncString() { 589 return this.mMnc; 590 } 591 592 /** 593 * @return the ISO country code 594 */ getCountryIso()595 public String getCountryIso() { 596 return this.mCountryIso; 597 } 598 599 /** @return whether the subscription is an eUICC one. */ isEmbedded()600 public boolean isEmbedded() { 601 return this.mIsEmbedded; 602 } 603 604 /** 605 * An opportunistic subscription connects to a network that is 606 * limited in functionality and / or coverage. 607 * 608 * @return whether subscription is opportunistic. 609 */ isOpportunistic()610 public boolean isOpportunistic() { 611 return mIsOpportunistic; 612 } 613 614 /** 615 * Used in scenarios where different subscriptions are bundled as a group. 616 * It's typically a primary and an opportunistic subscription. (see {@link #isOpportunistic()}) 617 * Such that those subscriptions will have some affiliated behaviors such as opportunistic 618 * subscription may be invisible to the user. 619 * 620 * @return group UUID a String of group UUID if it belongs to a group. Otherwise 621 * it will return null. 622 */ getGroupUuid()623 public @Nullable ParcelUuid getGroupUuid() { 624 return mGroupUUID; 625 } 626 627 /** 628 * @hide 629 */ clearGroupUuid()630 public void clearGroupUuid() { 631 this.mGroupUUID = null; 632 } 633 634 /** 635 * @hide 636 */ getEhplmns()637 public List<String> getEhplmns() { 638 return mEhplmns == null ? Collections.emptyList() : Arrays.asList(mEhplmns); 639 } 640 641 /** 642 * @hide 643 */ getHplmns()644 public List<String> getHplmns() { 645 return mHplmns == null ? Collections.emptyList() : Arrays.asList(mHplmns); 646 } 647 648 /** 649 * Return owner package of group the subscription belongs to. 650 * 651 * @hide 652 */ getGroupOwner()653 public @Nullable String getGroupOwner() { 654 return mGroupOwner; 655 } 656 657 /** 658 * @return the profile class of this subscription. 659 * @hide 660 */ 661 @SystemApi getProfileClass()662 public @SubscriptionManager.ProfileClass int getProfileClass() { 663 return this.mProfileClass; 664 } 665 666 /** 667 * This method returns the type of a subscription. It can be 668 * {@link SubscriptionManager#SUBSCRIPTION_TYPE_LOCAL_SIM} or 669 * {@link SubscriptionManager#SUBSCRIPTION_TYPE_REMOTE_SIM}. 670 * @return the type of subscription 671 */ getSubscriptionType()672 public @SubscriptionManager.SubscriptionType int getSubscriptionType() { 673 return mSubscriptionType; 674 } 675 676 /** 677 * Checks whether the app with the given context is authorized to manage this subscription 678 * according to its metadata. Only supported for embedded subscriptions (if {@link #isEmbedded} 679 * returns true). 680 * 681 * @param context Context of the application to check. 682 * @return whether the app is authorized to manage this subscription per its metadata. 683 * @hide 684 * @deprecated - Do not use. 685 */ 686 @Deprecated canManageSubscription(Context context)687 public boolean canManageSubscription(Context context) { 688 return canManageSubscription(context, context.getPackageName()); 689 } 690 691 /** 692 * Checks whether the given app is authorized to manage this subscription according to its 693 * metadata. Only supported for embedded subscriptions (if {@link #isEmbedded} returns true). 694 * 695 * @param context Any context. 696 * @param packageName Package name of the app to check. 697 * @return whether the app is authorized to manage this subscription per its metadata. 698 * @hide 699 * @deprecated - Do not use. 700 */ 701 @Deprecated canManageSubscription(Context context, String packageName)702 public boolean canManageSubscription(Context context, String packageName) { 703 List<UiccAccessRule> allAccessRules = getAllAccessRules(); 704 if (allAccessRules == null) { 705 return false; 706 } 707 PackageManager packageManager = context.getPackageManager(); 708 PackageInfo packageInfo; 709 try { 710 packageInfo = packageManager.getPackageInfo(packageName, 711 PackageManager.GET_SIGNING_CERTIFICATES); 712 } catch (PackageManager.NameNotFoundException e) { 713 Log.d("SubscriptionInfo", "canManageSubscription: Unknown package: " + packageName, e); 714 return false; 715 } 716 for (UiccAccessRule rule : allAccessRules) { 717 if (rule.getCarrierPrivilegeStatus(packageInfo) 718 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 719 return true; 720 } 721 } 722 return false; 723 } 724 725 /** 726 * @return the {@link UiccAccessRule}s that are stored in Uicc, dictating who 727 * is authorized to manage this subscription. 728 * TODO and fix it properly in R / master: either deprecate this and have 3 APIs 729 * native + carrier + all, or have this return all by default. 730 * @hide 731 */ 732 @SystemApi getAccessRules()733 public @Nullable List<UiccAccessRule> getAccessRules() { 734 if (mNativeAccessRules == null) return null; 735 return Arrays.asList(mNativeAccessRules); 736 } 737 738 /** 739 * @return the {@link UiccAccessRule}s that are both stored on Uicc and in carrierConfigs 740 * dictating who is authorized to manage this subscription. 741 * @hide 742 */ getAllAccessRules()743 public @Nullable List<UiccAccessRule> getAllAccessRules() { 744 List<UiccAccessRule> merged = new ArrayList<>(); 745 if (mNativeAccessRules != null) { 746 merged.addAll(getAccessRules()); 747 } 748 if (mCarrierConfigAccessRules != null) { 749 merged.addAll(Arrays.asList(mCarrierConfigAccessRules)); 750 } 751 return merged.isEmpty() ? null : merged; 752 } 753 754 /** 755 * Returns the card string of the SIM card which contains the subscription. 756 * 757 * Starting with API level 29 Security Patch 2021-04-05, returns the card string if the calling 758 * app has been granted the READ_PRIVILEGED_PHONE_STATE permission, has carrier privileges (see 759 * {@link TelephonyManager#hasCarrierPrivileges}), or is a device owner or profile owner that 760 * has been granted the READ_PHONE_STATE permission. The profile owner is an app that owns a 761 * managed profile on the device; for more details see <a 762 * href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile 763 * owner access is deprecated and will be removed in a future release. 764 * 765 * @return the card string of the SIM card which contains the subscription or an empty string 766 * if these requirements are not met. The card string is the ICCID for UICCs or the EID for 767 * eUICCs. 768 * @hide 769 * //TODO rename usages in LPA: UiccSlotUtil.java, UiccSlotsManager.java, UiccSlotInfoTest.java 770 */ getCardString()771 public String getCardString() { 772 return this.mCardString; 773 } 774 775 /** 776 * @hide 777 */ clearCardString()778 public void clearCardString() { 779 this.mCardString = ""; 780 } 781 782 /** 783 * Returns the card ID of the SIM card which contains the subscription (see 784 * {@link UiccCardInfo#getCardId()}. 785 * @return the cardId 786 */ getCardId()787 public int getCardId() { 788 return this.mCardId; 789 } 790 /** 791 * Returns the port index of the SIM card which contains the subscription. 792 * 793 * @return the portIndex 794 */ getPortIndex()795 public int getPortIndex() { 796 return this.mPortIndex; 797 } 798 799 /** 800 * Set whether the subscription's group is disabled. 801 * @hide 802 */ setGroupDisabled(boolean isGroupDisabled)803 public void setGroupDisabled(boolean isGroupDisabled) { 804 this.mIsGroupDisabled = isGroupDisabled; 805 } 806 807 /** 808 * Return whether the subscription's group is disabled. 809 * @hide 810 */ 811 @SystemApi isGroupDisabled()812 public boolean isGroupDisabled() { 813 return mIsGroupDisabled; 814 } 815 816 /** 817 * Return whether uicc applications are set to be enabled or disabled. 818 * @hide 819 */ 820 @SystemApi areUiccApplicationsEnabled()821 public boolean areUiccApplicationsEnabled() { 822 return mAreUiccApplicationsEnabled; 823 } 824 825 /** 826 * Get the usage setting for this subscription. 827 * 828 * @return the usage setting used for this subscription. 829 */ getUsageSetting()830 public @UsageSetting int getUsageSetting() { 831 return mUsageSetting; 832 } 833 834 public static final @android.annotation.NonNull 835 Parcelable.Creator<SubscriptionInfo> CREATOR = 836 new Parcelable.Creator<SubscriptionInfo>() { 837 @Override 838 public SubscriptionInfo createFromParcel(Parcel source) { 839 int id = source.readInt(); 840 String iccId = source.readString(); 841 int simSlotIndex = source.readInt(); 842 CharSequence displayName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); 843 CharSequence carrierName = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(source); 844 int nameSource = source.readInt(); 845 int iconTint = source.readInt(); 846 String number = source.readString(); 847 int dataRoaming = source.readInt(); 848 String mcc = source.readString(); 849 String mnc = source.readString(); 850 String countryIso = source.readString(); 851 boolean isEmbedded = source.readBoolean(); 852 UiccAccessRule[] nativeAccessRules = source.createTypedArray(UiccAccessRule.CREATOR); 853 String cardString = source.readString(); 854 int cardId = source.readInt(); 855 int portId = source.readInt(); 856 boolean isOpportunistic = source.readBoolean(); 857 String groupUUID = source.readString(); 858 boolean isGroupDisabled = source.readBoolean(); 859 int carrierid = source.readInt(); 860 int profileClass = source.readInt(); 861 int subType = source.readInt(); 862 String[] ehplmns = source.createStringArray(); 863 String[] hplmns = source.createStringArray(); 864 String groupOwner = source.readString(); 865 UiccAccessRule[] carrierConfigAccessRules = source.createTypedArray( 866 UiccAccessRule.CREATOR); 867 boolean areUiccApplicationsEnabled = source.readBoolean(); 868 int usageSetting = source.readInt(); 869 870 SubscriptionInfo info = new SubscriptionInfo(id, iccId, simSlotIndex, displayName, 871 carrierName, nameSource, iconTint, number, dataRoaming, /* icon= */ null, 872 mcc, mnc, countryIso, isEmbedded, nativeAccessRules, cardString, cardId, 873 isOpportunistic, groupUUID, isGroupDisabled, carrierid, profileClass, subType, 874 groupOwner, carrierConfigAccessRules, areUiccApplicationsEnabled, 875 portId, usageSetting); 876 info.setAssociatedPlmns(ehplmns, hplmns); 877 return info; 878 } 879 880 @Override 881 public SubscriptionInfo[] newArray(int size) { 882 return new SubscriptionInfo[size]; 883 } 884 }; 885 886 @Override writeToParcel(Parcel dest, int flags)887 public void writeToParcel(Parcel dest, int flags) { 888 dest.writeInt(mId); 889 dest.writeString(mIccId); 890 dest.writeInt(mSimSlotIndex); 891 TextUtils.writeToParcel(mDisplayName, dest, 0); 892 TextUtils.writeToParcel(mCarrierName, dest, 0); 893 dest.writeInt(mNameSource); 894 dest.writeInt(mIconTint); 895 dest.writeString(mNumber); 896 dest.writeInt(mDataRoaming); 897 dest.writeString(mMcc); 898 dest.writeString(mMnc); 899 dest.writeString(mCountryIso); 900 // Do not write mIconBitmap since it should be lazily loaded on first usage 901 dest.writeBoolean(mIsEmbedded); 902 dest.writeTypedArray(mNativeAccessRules, flags); 903 dest.writeString(mCardString); 904 dest.writeInt(mCardId); 905 dest.writeInt(mPortIndex); 906 dest.writeBoolean(mIsOpportunistic); 907 dest.writeString(mGroupUUID == null ? null : mGroupUUID.toString()); 908 dest.writeBoolean(mIsGroupDisabled); 909 dest.writeInt(mCarrierId); 910 dest.writeInt(mProfileClass); 911 dest.writeInt(mSubscriptionType); 912 dest.writeStringArray(mEhplmns); 913 dest.writeStringArray(mHplmns); 914 dest.writeString(mGroupOwner); 915 dest.writeTypedArray(mCarrierConfigAccessRules, flags); 916 dest.writeBoolean(mAreUiccApplicationsEnabled); 917 dest.writeInt(mUsageSetting); 918 } 919 920 @Override describeContents()921 public int describeContents() { 922 return 0; 923 } 924 925 /** 926 * @hide 927 */ givePrintableIccid(String iccId)928 public static String givePrintableIccid(String iccId) { 929 String iccIdToPrint = null; 930 if (iccId != null) { 931 if (iccId.length() > 9 && !TelephonyUtils.IS_DEBUGGABLE) { 932 iccIdToPrint = iccId.substring(0, 9) + Rlog.pii(false, iccId.substring(9)); 933 } else { 934 iccIdToPrint = iccId; 935 } 936 } 937 return iccIdToPrint; 938 } 939 940 @Override toString()941 public String toString() { 942 String iccIdToPrint = givePrintableIccid(mIccId); 943 String cardStringToPrint = givePrintableIccid(mCardString); 944 return "{id=" + mId + " iccId=" + iccIdToPrint + " simSlotIndex=" + mSimSlotIndex 945 + " carrierId=" + mCarrierId + " displayName=" + mDisplayName 946 + " carrierName=" + mCarrierName + " nameSource=" + mNameSource 947 + " iconTint=" + mIconTint 948 + " number=" + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, mNumber) 949 + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc=" + mMcc 950 + " mnc=" + mMnc + " countryIso=" + mCountryIso + " isEmbedded=" + mIsEmbedded 951 + " nativeAccessRules=" + Arrays.toString(mNativeAccessRules) 952 + " cardString=" + cardStringToPrint + " cardId=" + mCardId 953 + " portIndex=" + mPortIndex 954 + " isOpportunistic=" + mIsOpportunistic + " groupUUID=" + mGroupUUID 955 + " isGroupDisabled=" + mIsGroupDisabled 956 + " profileClass=" + mProfileClass 957 + " ehplmns=" + Arrays.toString(mEhplmns) 958 + " hplmns=" + Arrays.toString(mHplmns) 959 + " subscriptionType=" + mSubscriptionType 960 + " groupOwner=" + mGroupOwner 961 + " carrierConfigAccessRules=" + Arrays.toString(mCarrierConfigAccessRules) 962 + " areUiccApplicationsEnabled=" + mAreUiccApplicationsEnabled 963 + " usageSetting=" + mUsageSetting + "}"; 964 } 965 966 @Override hashCode()967 public int hashCode() { 968 return Objects.hash(mId, mSimSlotIndex, mNameSource, mIconTint, mDataRoaming, mIsEmbedded, 969 mIsOpportunistic, mGroupUUID, mIccId, mNumber, mMcc, mMnc, mCountryIso, mCardString, 970 mCardId, mDisplayName, mCarrierName, mNativeAccessRules, mIsGroupDisabled, 971 mCarrierId, mProfileClass, mGroupOwner, mAreUiccApplicationsEnabled, mPortIndex, 972 mUsageSetting); 973 } 974 975 @Override equals(Object obj)976 public boolean equals(Object obj) { 977 if (obj == null) return false; 978 if (obj == this) return true; 979 980 SubscriptionInfo toCompare; 981 try { 982 toCompare = (SubscriptionInfo) obj; 983 } catch (ClassCastException ex) { 984 return false; 985 } 986 987 return mId == toCompare.mId 988 && mSimSlotIndex == toCompare.mSimSlotIndex 989 && mNameSource == toCompare.mNameSource 990 && mIconTint == toCompare.mIconTint 991 && mDataRoaming == toCompare.mDataRoaming 992 && mIsEmbedded == toCompare.mIsEmbedded 993 && mIsOpportunistic == toCompare.mIsOpportunistic 994 && mIsGroupDisabled == toCompare.mIsGroupDisabled 995 && mAreUiccApplicationsEnabled == toCompare.mAreUiccApplicationsEnabled 996 && mCarrierId == toCompare.mCarrierId 997 && Objects.equals(mGroupUUID, toCompare.mGroupUUID) 998 && Objects.equals(mIccId, toCompare.mIccId) 999 && Objects.equals(mNumber, toCompare.mNumber) 1000 && Objects.equals(mMcc, toCompare.mMcc) 1001 && Objects.equals(mMnc, toCompare.mMnc) 1002 && Objects.equals(mCountryIso, toCompare.mCountryIso) 1003 && Objects.equals(mCardString, toCompare.mCardString) 1004 && Objects.equals(mCardId, toCompare.mCardId) 1005 && mPortIndex == toCompare.mPortIndex 1006 && Objects.equals(mGroupOwner, toCompare.mGroupOwner) 1007 && TextUtils.equals(mDisplayName, toCompare.mDisplayName) 1008 && TextUtils.equals(mCarrierName, toCompare.mCarrierName) 1009 && Arrays.equals(mNativeAccessRules, toCompare.mNativeAccessRules) 1010 && mProfileClass == toCompare.mProfileClass 1011 && Arrays.equals(mEhplmns, toCompare.mEhplmns) 1012 && Arrays.equals(mHplmns, toCompare.mHplmns) 1013 && mUsageSetting == toCompare.mUsageSetting; 1014 } 1015 } 1016