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