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