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