• 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.content.Context;
21 import android.content.pm.PackageInfo;
22 import android.content.pm.PackageManager;
23 import android.graphics.Bitmap;
24 import android.graphics.Canvas;
25 import android.graphics.Color;
26 import android.graphics.Paint;
27 import android.graphics.PorterDuff;
28 import android.graphics.PorterDuffColorFilter;
29 import android.graphics.Rect;
30 import android.graphics.Typeface;
31 import android.os.Build;
32 import android.os.Parcel;
33 import android.os.Parcelable;
34 import android.util.DisplayMetrics;
35 
36 import java.util.Arrays;
37 
38 /**
39  * A Parcelable class for Subscription Information.
40  */
41 public class SubscriptionInfo implements Parcelable {
42 
43     /**
44      * Size of text to render on the icon.
45      */
46     private static final int TEXT_SIZE = 16;
47 
48     /**
49      * Subscription Identifier, this is a device unique number
50      * and not an index into an array
51      */
52     private int mId;
53 
54     /**
55      * The GID for a SIM that maybe associated with this subscription, empty if unknown
56      */
57     private String mIccId;
58 
59     /**
60      * The index of the slot that currently contains the subscription
61      * and not necessarily unique and maybe INVALID_SLOT_ID if unknown
62      */
63     private int mSimSlotIndex;
64 
65     /**
66      * The name displayed to the user that identifies this subscription
67      */
68     private CharSequence mDisplayName;
69 
70     /**
71      * String that identifies SPN/PLMN
72      * TODO : Add a new field that identifies only SPN for a sim
73      */
74     private CharSequence mCarrierName;
75 
76     /**
77      * The source of the name, NAME_SOURCE_UNDEFINED, NAME_SOURCE_DEFAULT_SOURCE,
78      * NAME_SOURCE_SIM_SOURCE or NAME_SOURCE_USER_INPUT.
79      */
80     private int mNameSource;
81 
82     /**
83      * The color to be used for tinting the icon when displaying to the user
84      */
85     private int mIconTint;
86 
87     /**
88      * A number presented to the user identify this subscription
89      */
90     private String mNumber;
91 
92     /**
93      * Data roaming state, DATA_RAOMING_ENABLE, DATA_RAOMING_DISABLE
94      */
95     private int mDataRoaming;
96 
97     /**
98      * SIM Icon bitmap
99      */
100     private Bitmap mIconBitmap;
101 
102     /**
103      * Mobile Country Code
104      */
105     private int mMcc;
106 
107     /**
108      * Mobile Network Code
109      */
110     private int mMnc;
111 
112     /**
113      * ISO Country code for the subscription's provider
114      */
115     private String mCountryIso;
116 
117     /**
118      * Whether the subscription is an embedded one.
119      */
120     private boolean mIsEmbedded;
121 
122     /**
123      * The access rules for this subscription, if it is embedded and defines any.
124      */
125     @Nullable
126     private UiccAccessRule[] mAccessRules;
127 
128     /**
129      * @hide
130      */
SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, Bitmap icon, int mcc, int mnc, String countryIso)131     public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
132             CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
133             Bitmap icon, int mcc, int mnc, String countryIso) {
134         this(id, iccId, simSlotIndex, displayName, carrierName, nameSource, iconTint, number,
135                 roaming, icon, mcc, mnc, countryIso, false /* isEmbedded */,
136                 null /* accessRules */);
137     }
138 
139     /**
140      * @hide
141      */
SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName, CharSequence carrierName, int nameSource, int iconTint, String number, int roaming, Bitmap icon, int mcc, int mnc, String countryIso, boolean isEmbedded, @Nullable UiccAccessRule[] accessRules)142     public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
143             CharSequence carrierName, int nameSource, int iconTint, String number, int roaming,
144             Bitmap icon, int mcc, int mnc, String countryIso, boolean isEmbedded,
145             @Nullable UiccAccessRule[] accessRules) {
146         this.mId = id;
147         this.mIccId = iccId;
148         this.mSimSlotIndex = simSlotIndex;
149         this.mDisplayName = displayName;
150         this.mCarrierName = carrierName;
151         this.mNameSource = nameSource;
152         this.mIconTint = iconTint;
153         this.mNumber = number;
154         this.mDataRoaming = roaming;
155         this.mIconBitmap = icon;
156         this.mMcc = mcc;
157         this.mMnc = mnc;
158         this.mCountryIso = countryIso;
159         this.mIsEmbedded = isEmbedded;
160         this.mAccessRules = accessRules;
161     }
162 
163     /**
164      * @return the subscription ID.
165      */
getSubscriptionId()166     public int getSubscriptionId() {
167         return this.mId;
168     }
169 
170     /**
171      * @return the ICC ID.
172      */
getIccId()173     public String getIccId() {
174         return this.mIccId;
175     }
176 
177     /**
178      * @return the slot index of this Subscription's SIM card.
179      */
getSimSlotIndex()180     public int getSimSlotIndex() {
181         return this.mSimSlotIndex;
182     }
183 
184     /**
185      * @return the name displayed to the user that identifies this subscription
186      */
getDisplayName()187     public CharSequence getDisplayName() {
188         return this.mDisplayName;
189     }
190 
191     /**
192      * Sets the name displayed to the user that identifies this subscription
193      * @hide
194      */
setDisplayName(CharSequence name)195     public void setDisplayName(CharSequence name) {
196         this.mDisplayName = name;
197     }
198 
199     /**
200      * @return the name displayed to the user that identifies Subscription provider name
201      */
getCarrierName()202     public CharSequence getCarrierName() {
203         return this.mCarrierName;
204     }
205 
206     /**
207      * Sets the name displayed to the user that identifies Subscription provider name
208      * @hide
209      */
setCarrierName(CharSequence name)210     public void setCarrierName(CharSequence name) {
211         this.mCarrierName = name;
212     }
213 
214     /**
215      * @return the source of the name, eg NAME_SOURCE_UNDEFINED, NAME_SOURCE_DEFAULT_SOURCE,
216      * NAME_SOURCE_SIM_SOURCE or NAME_SOURCE_USER_INPUT.
217      * @hide
218      */
getNameSource()219     public int getNameSource() {
220         return this.mNameSource;
221     }
222 
223     /**
224      * Creates and returns an icon {@code Bitmap} to represent this {@code SubscriptionInfo} in a user
225      * interface.
226      *
227      * @param context A {@code Context} to get the {@code DisplayMetrics}s from.
228      *
229      * @return A bitmap icon for this {@code SubscriptionInfo}.
230      */
createIconBitmap(Context context)231     public Bitmap createIconBitmap(Context context) {
232         int width = mIconBitmap.getWidth();
233         int height = mIconBitmap.getHeight();
234         DisplayMetrics metrics = context.getResources().getDisplayMetrics();
235 
236         // Create a new bitmap of the same size because it will be modified.
237         Bitmap workingBitmap = Bitmap.createBitmap(metrics, width, height, mIconBitmap.getConfig());
238 
239         Canvas canvas = new Canvas(workingBitmap);
240         Paint paint = new Paint();
241 
242         // Tint the icon with the color.
243         paint.setColorFilter(new PorterDuffColorFilter(mIconTint, PorterDuff.Mode.SRC_ATOP));
244         canvas.drawBitmap(mIconBitmap, 0, 0, paint);
245         paint.setColorFilter(null);
246 
247         // Write the sim slot index.
248         paint.setAntiAlias(true);
249         paint.setTypeface(Typeface.create("sans-serif", Typeface.NORMAL));
250         paint.setColor(Color.WHITE);
251         // Set text size scaled by density
252         paint.setTextSize(TEXT_SIZE * metrics.density);
253         // Convert sim slot index to localized string
254         final String index = String.format("%d", mSimSlotIndex + 1);
255         final Rect textBound = new Rect();
256         paint.getTextBounds(index, 0, 1, textBound);
257         final float xOffset = (width / 2.f) - textBound.centerX();
258         final float yOffset = (height / 2.f) - textBound.centerY();
259         canvas.drawText(index, xOffset, yOffset, paint);
260 
261         return workingBitmap;
262     }
263 
264     /**
265      * A highlight color to use in displaying information about this {@code PhoneAccount}.
266      *
267      * @return A hexadecimal color value.
268      */
getIconTint()269     public int getIconTint() {
270         return mIconTint;
271     }
272 
273     /**
274      * Sets the color displayed to the user that identifies this subscription
275      * @hide
276      */
setIconTint(int iconTint)277     public void setIconTint(int iconTint) {
278         this.mIconTint = iconTint;
279     }
280 
281     /**
282      * @return the number of this subscription.
283      */
getNumber()284     public String getNumber() {
285         return mNumber;
286     }
287 
288     /**
289      * @return the data roaming state for this subscription, either
290      * {@link SubscriptionManager#DATA_ROAMING_ENABLE} or {@link SubscriptionManager#DATA_ROAMING_DISABLE}.
291      */
getDataRoaming()292     public int getDataRoaming() {
293         return this.mDataRoaming;
294     }
295 
296     /**
297      * @return the MCC.
298      */
getMcc()299     public int getMcc() {
300         return this.mMcc;
301     }
302 
303     /**
304      * @return the MNC.
305      */
getMnc()306     public int getMnc() {
307         return this.mMnc;
308     }
309 
310     /**
311      * @return the ISO country code
312      */
getCountryIso()313     public String getCountryIso() {
314         return this.mCountryIso;
315     }
316 
317     /**
318      * @return whether the subscription is an embedded one.
319      * @hide
320      *
321      * TODO(b/35851809): Make this public.
322      */
isEmbedded()323     public boolean isEmbedded() {
324         return this.mIsEmbedded;
325     }
326 
327     /**
328      * Checks whether the app with the given context is authorized to manage this subscription
329      * according to its metadata. Only supported for embedded subscriptions (if {@link #isEmbedded}
330      * returns true).
331      *
332      * @param context Context of the application to check.
333      * @return whether the app is authorized to manage this subscription per its metadata.
334      * @throws UnsupportedOperationException if this subscription is not embedded.
335      * @hide
336      *
337      * TODO(b/35851809): Make this public.
338      */
canManageSubscription(Context context)339     public boolean canManageSubscription(Context context) {
340         return canManageSubscription(context, context.getPackageName());
341     }
342 
343     /**
344      * Checks whether the given app is authorized to manage this subscription according to its
345      * metadata. Only supported for embedded subscriptions (if {@link #isEmbedded} returns true).
346      *
347      * @param context Any context.
348      * @param packageName Package name of the app to check.
349      * @return whether the app is authorized to manage this subscription per its metadata.
350      * @throws UnsupportedOperationException if this subscription is not embedded.
351      * @hide
352      */
canManageSubscription(Context context, String packageName)353     public boolean canManageSubscription(Context context, String packageName) {
354         if (!isEmbedded()) {
355             throw new UnsupportedOperationException("Not an embedded subscription");
356         }
357         if (mAccessRules == null) {
358             return false;
359         }
360         PackageManager packageManager = context.getPackageManager();
361         PackageInfo packageInfo;
362         try {
363             packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES);
364         } catch (PackageManager.NameNotFoundException e) {
365             throw new IllegalArgumentException("Unknown package: " + packageName, e);
366         }
367         for (UiccAccessRule rule : mAccessRules) {
368             if (rule.getCarrierPrivilegeStatus(packageInfo)
369                     == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
370                 return true;
371             }
372         }
373         return false;
374     }
375 
376     /**
377      * @return the {@link UiccAccessRule}s dictating who is authorized to manage this subscription.
378      * @throws UnsupportedOperationException if this subscription is not embedded.
379      * @hide
380      *
381      * TODO(b/35851809): Make this a SystemApi.
382      */
getAccessRules()383     public @Nullable UiccAccessRule[] getAccessRules() {
384         if (!isEmbedded()) {
385             throw new UnsupportedOperationException("Not an embedded subscription");
386         }
387         return mAccessRules;
388     }
389 
390     public static final Parcelable.Creator<SubscriptionInfo> CREATOR = new Parcelable.Creator<SubscriptionInfo>() {
391         @Override
392         public SubscriptionInfo createFromParcel(Parcel source) {
393             int id = source.readInt();
394             String iccId = source.readString();
395             int simSlotIndex = source.readInt();
396             CharSequence displayName = source.readCharSequence();
397             CharSequence carrierName = source.readCharSequence();
398             int nameSource = source.readInt();
399             int iconTint = source.readInt();
400             String number = source.readString();
401             int dataRoaming = source.readInt();
402             int mcc = source.readInt();
403             int mnc = source.readInt();
404             String countryIso = source.readString();
405             Bitmap iconBitmap = Bitmap.CREATOR.createFromParcel(source);
406             boolean isEmbedded = source.readBoolean();
407             UiccAccessRule[] accessRules = source.createTypedArray(UiccAccessRule.CREATOR);
408 
409             return new SubscriptionInfo(id, iccId, simSlotIndex, displayName, carrierName,
410                     nameSource, iconTint, number, dataRoaming, iconBitmap, mcc, mnc, countryIso,
411                     isEmbedded, accessRules);
412         }
413 
414         @Override
415         public SubscriptionInfo[] newArray(int size) {
416             return new SubscriptionInfo[size];
417         }
418     };
419 
420     @Override
writeToParcel(Parcel dest, int flags)421     public void writeToParcel(Parcel dest, int flags) {
422         dest.writeInt(mId);
423         dest.writeString(mIccId);
424         dest.writeInt(mSimSlotIndex);
425         dest.writeCharSequence(mDisplayName);
426         dest.writeCharSequence(mCarrierName);
427         dest.writeInt(mNameSource);
428         dest.writeInt(mIconTint);
429         dest.writeString(mNumber);
430         dest.writeInt(mDataRoaming);
431         dest.writeInt(mMcc);
432         dest.writeInt(mMnc);
433         dest.writeString(mCountryIso);
434         mIconBitmap.writeToParcel(dest, flags);
435         dest.writeBoolean(mIsEmbedded);
436         dest.writeTypedArray(mAccessRules, flags);
437     }
438 
439     @Override
describeContents()440     public int describeContents() {
441         return 0;
442     }
443 
444     /**
445      * @hide
446      */
givePrintableIccid(String iccId)447     public static String givePrintableIccid(String iccId) {
448         String iccIdToPrint = null;
449         if (iccId != null) {
450             if (iccId.length() > 9 && !Build.IS_DEBUGGABLE) {
451                 iccIdToPrint = iccId.substring(0, 9) + Rlog.pii(false, iccId.substring(9));
452             } else {
453                 iccIdToPrint = iccId;
454             }
455         }
456         return iccIdToPrint;
457     }
458 
459     @Override
toString()460     public String toString() {
461         String iccIdToPrint = givePrintableIccid(mIccId);
462         return "{id=" + mId + ", iccId=" + iccIdToPrint + " simSlotIndex=" + mSimSlotIndex
463                 + " displayName=" + mDisplayName + " carrierName=" + mCarrierName
464                 + " nameSource=" + mNameSource + " iconTint=" + mIconTint
465                 + " dataRoaming=" + mDataRoaming + " iconBitmap=" + mIconBitmap + " mcc " + mMcc
466                 + " mnc " + mMnc + " isEmbedded " + mIsEmbedded
467                 + " accessRules " + Arrays.toString(mAccessRules) + "}";
468     }
469 }
470