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