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