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 */ 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)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 */ 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)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 */ 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, String cardId)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 */ getSubscriptionId()187 public int getSubscriptionId() { 188 return this.mId; 189 } 190 191 /** 192 * @return the ICC ID. 193 */ getIccId()194 public String getIccId() { 195 return this.mIccId; 196 } 197 198 /** 199 * @return the slot index of this Subscription's SIM card. 200 */ getSimSlotIndex()201 public int getSimSlotIndex() { 202 return this.mSimSlotIndex; 203 } 204 205 /** 206 * @return the name displayed to the user that identifies this subscription 207 */ getDisplayName()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 */ setDisplayName(CharSequence name)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 */ getCarrierName()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 */ setCarrierName(CharSequence name)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 */ getNameSource()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 */ createIconBitmap(Context context)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 */ getIconTint()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 */ setIconTint(int iconTint)298 public void setIconTint(int iconTint) { 299 this.mIconTint = iconTint; 300 } 301 302 /** 303 * @return the number of this subscription. 304 */ getNumber()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 */ getDataRoaming()313 public int getDataRoaming() { 314 return this.mDataRoaming; 315 } 316 317 /** 318 * @return the MCC. 319 */ getMcc()320 public int getMcc() { 321 return this.mMcc; 322 } 323 324 /** 325 * @return the MNC. 326 */ getMnc()327 public int getMnc() { 328 return this.mMnc; 329 } 330 331 /** 332 * @return the ISO country code 333 */ getCountryIso()334 public String getCountryIso() { 335 return this.mCountryIso; 336 } 337 338 /** @return whether the subscription is an eUICC one. */ isEmbedded()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 canManageSubscription(Context context)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 canManageSubscription(Context context, String packageName)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 getAccessRules()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 */ getCardId()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 writeToParcel(Parcel dest, int flags)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 describeContents()468 public int describeContents() { 469 return 0; 470 } 471 472 /** 473 * @hide 474 */ givePrintableIccid(String iccId)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 toString()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