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.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_CONGESTED; 20 import static android.net.NetworkPolicyManager.SUBSCRIPTION_OVERRIDE_UNMETERED; 21 22 import android.Manifest; 23 import android.annotation.CallbackExecutor; 24 import android.annotation.ColorInt; 25 import android.annotation.DurationMillisLong; 26 import android.annotation.IntDef; 27 import android.annotation.NonNull; 28 import android.annotation.Nullable; 29 import android.annotation.RequiresPermission; 30 import android.annotation.SdkConstant; 31 import android.annotation.SdkConstant.SdkConstantType; 32 import android.annotation.SuppressAutoDoc; 33 import android.annotation.SystemApi; 34 import android.annotation.SystemService; 35 import android.app.PendingIntent; 36 import android.app.PropertyInvalidatedCache; 37 import android.compat.annotation.UnsupportedAppUsage; 38 import android.content.Context; 39 import android.content.Intent; 40 import android.content.pm.PackageInfo; 41 import android.content.pm.PackageManager; 42 import android.content.res.Configuration; 43 import android.content.res.Resources; 44 import android.database.ContentObserver; 45 import android.net.NetworkCapabilities; 46 import android.net.NetworkPolicyManager; 47 import android.net.Uri; 48 import android.os.Binder; 49 import android.os.Build; 50 import android.os.Bundle; 51 import android.os.Handler; 52 import android.os.Looper; 53 import android.os.ParcelUuid; 54 import android.os.Process; 55 import android.os.RemoteException; 56 import android.provider.Telephony.SimInfo; 57 import android.telephony.euicc.EuiccManager; 58 import android.telephony.ims.ImsMmTelManager; 59 import android.util.Base64; 60 import android.util.Log; 61 import android.util.Pair; 62 63 import com.android.internal.telephony.ISetOpportunisticDataCallback; 64 import com.android.internal.telephony.ISub; 65 import com.android.internal.telephony.PhoneConstants; 66 import com.android.internal.telephony.util.HandlerExecutor; 67 import com.android.internal.util.FunctionalUtils; 68 import com.android.internal.util.Preconditions; 69 import com.android.telephony.Rlog; 70 71 import java.io.ByteArrayInputStream; 72 import java.io.ByteArrayOutputStream; 73 import java.io.IOException; 74 import java.io.ObjectInputStream; 75 import java.io.ObjectOutputStream; 76 import java.lang.annotation.Retention; 77 import java.lang.annotation.RetentionPolicy; 78 import java.util.ArrayList; 79 import java.util.Arrays; 80 import java.util.Collections; 81 import java.util.HashMap; 82 import java.util.List; 83 import java.util.Locale; 84 import java.util.Map; 85 import java.util.concurrent.ConcurrentHashMap; 86 import java.util.concurrent.Executor; 87 import java.util.function.Consumer; 88 import java.util.stream.Collectors; 89 90 /** 91 * SubscriptionManager is the application interface to SubscriptionController 92 * and provides information about the current Telephony Subscriptions. 93 */ 94 @SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) 95 public class SubscriptionManager { 96 private static final String LOG_TAG = "SubscriptionManager"; 97 private static final boolean DBG = false; 98 private static final boolean VDBG = false; 99 100 /** An invalid subscription identifier */ 101 public static final int INVALID_SUBSCRIPTION_ID = -1; 102 103 /** Base value for placeholder SUBSCRIPTION_ID's. */ 104 /** @hide */ 105 public static final int PLACEHOLDER_SUBSCRIPTION_ID_BASE = INVALID_SUBSCRIPTION_ID - 1; 106 107 /** An invalid phone identifier */ 108 /** @hide */ 109 public static final int INVALID_PHONE_INDEX = -1; 110 111 /** Indicates invalid sim slot. This can be returned by {@link #getSlotIndex(int)}. */ 112 public static final int INVALID_SIM_SLOT_INDEX = -1; 113 114 /** Indicates the default subscription ID in Telephony. */ 115 public static final int DEFAULT_SUBSCRIPTION_ID = Integer.MAX_VALUE; 116 117 /** 118 * Indicates the caller wants the default phone id. 119 * Used in SubscriptionController and Phone but do we really need it??? 120 * @hide 121 */ 122 public static final int DEFAULT_PHONE_INDEX = Integer.MAX_VALUE; 123 124 /** Indicates the caller wants the default slot id. NOT used remove? */ 125 /** @hide */ 126 public static final int DEFAULT_SIM_SLOT_INDEX = Integer.MAX_VALUE; 127 128 /** Minimum possible subid that represents a subscription */ 129 /** @hide */ 130 public static final int MIN_SUBSCRIPTION_ID_VALUE = 0; 131 132 /** Maximum possible subid that represents a subscription */ 133 /** @hide */ 134 public static final int MAX_SUBSCRIPTION_ID_VALUE = DEFAULT_SUBSCRIPTION_ID - 1; 135 136 /** @hide */ 137 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 138 public static final Uri CONTENT_URI = SimInfo.CONTENT_URI; 139 140 /** @hide */ 141 public static final String CACHE_KEY_DEFAULT_SUB_ID_PROPERTY = 142 "cache_key.telephony.get_default_sub_id"; 143 144 /** @hide */ 145 public static final String CACHE_KEY_DEFAULT_DATA_SUB_ID_PROPERTY = 146 "cache_key.telephony.get_default_data_sub_id"; 147 148 /** @hide */ 149 public static final String CACHE_KEY_DEFAULT_SMS_SUB_ID_PROPERTY = 150 "cache_key.telephony.get_default_sms_sub_id"; 151 152 /** @hide */ 153 public static final String CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY = 154 "cache_key.telephony.get_active_data_sub_id"; 155 156 /** @hide */ 157 public static final String CACHE_KEY_SLOT_INDEX_PROPERTY = 158 "cache_key.telephony.get_slot_index"; 159 160 /** @hide */ 161 public static final String GET_SIM_SPECIFIC_SETTINGS_METHOD_NAME = "getSimSpecificSettings"; 162 163 /** @hide */ 164 public static final String RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME = 165 "restoreSimSpecificSettings"; 166 167 /** 168 * Key to the backup & restore data byte array in the Bundle that is returned by {@link 169 * #getAllSimSpecificSettingsForBackup()} or to be pass in to {@link 170 * #restoreAllSimSpecificSettings()}. 171 * 172 * @hide 173 */ 174 public static final String KEY_SIM_SPECIFIC_SETTINGS_DATA = "KEY_SIM_SPECIFIC_SETTINGS_DATA"; 175 176 private static final int MAX_CACHE_SIZE = 4; 177 178 private static class VoidPropertyInvalidatedCache<T> 179 extends PropertyInvalidatedCache<Void, T> { 180 private final FunctionalUtils.ThrowingFunction<ISub, T> mInterfaceMethod; 181 private final String mCacheKeyProperty; 182 private final T mDefaultValue; 183 VoidPropertyInvalidatedCache( FunctionalUtils.ThrowingFunction<ISub, T> subscriptionInterfaceMethod, String cacheKeyProperty, T defaultValue)184 VoidPropertyInvalidatedCache( 185 FunctionalUtils.ThrowingFunction<ISub, T> subscriptionInterfaceMethod, 186 String cacheKeyProperty, 187 T defaultValue) { 188 super(MAX_CACHE_SIZE, cacheKeyProperty); 189 mInterfaceMethod = subscriptionInterfaceMethod; 190 mCacheKeyProperty = cacheKeyProperty; 191 mDefaultValue = defaultValue; 192 } 193 194 @Override recompute(Void aVoid)195 protected T recompute(Void aVoid) { 196 T result = mDefaultValue; 197 198 try { 199 ISub iSub = TelephonyManager.getSubscriptionService(); 200 if (iSub != null) { 201 result = mInterfaceMethod.applyOrThrow(iSub); 202 } 203 } catch (Exception ex) { 204 Rlog.w(LOG_TAG, "Failed to recompute cache key for " + mCacheKeyProperty); 205 } 206 207 if (VDBG) logd("recomputing " + mCacheKeyProperty + ", result = " + result); 208 return result; 209 } 210 } 211 212 private static class IntegerPropertyInvalidatedCache<T> 213 extends PropertyInvalidatedCache<Integer, T> { 214 private final FunctionalUtils.ThrowingBiFunction<ISub, Integer, T> mInterfaceMethod; 215 private final String mCacheKeyProperty; 216 private final T mDefaultValue; 217 IntegerPropertyInvalidatedCache( FunctionalUtils.ThrowingBiFunction<ISub, Integer, T> subscriptionInterfaceMethod, String cacheKeyProperty, T defaultValue)218 IntegerPropertyInvalidatedCache( 219 FunctionalUtils.ThrowingBiFunction<ISub, Integer, T> subscriptionInterfaceMethod, 220 String cacheKeyProperty, 221 T defaultValue) { 222 super(MAX_CACHE_SIZE, cacheKeyProperty); 223 mInterfaceMethod = subscriptionInterfaceMethod; 224 mCacheKeyProperty = cacheKeyProperty; 225 mDefaultValue = defaultValue; 226 } 227 228 @Override recompute(Integer query)229 protected T recompute(Integer query) { 230 T result = mDefaultValue; 231 232 try { 233 ISub iSub = TelephonyManager.getSubscriptionService(); 234 if (iSub != null) { 235 result = mInterfaceMethod.applyOrThrow(iSub, query); 236 } 237 } catch (Exception ex) { 238 Rlog.w(LOG_TAG, "Failed to recompute cache key for " + mCacheKeyProperty); 239 } 240 241 if (VDBG) logd("recomputing " + mCacheKeyProperty + ", result = " + result); 242 return result; 243 } 244 } 245 246 private static VoidPropertyInvalidatedCache<Integer> sDefaultSubIdCache = 247 new VoidPropertyInvalidatedCache<>(ISub::getDefaultSubId, 248 CACHE_KEY_DEFAULT_SUB_ID_PROPERTY, 249 INVALID_SUBSCRIPTION_ID); 250 251 private static VoidPropertyInvalidatedCache<Integer> sDefaultDataSubIdCache = 252 new VoidPropertyInvalidatedCache<>(ISub::getDefaultDataSubId, 253 CACHE_KEY_DEFAULT_DATA_SUB_ID_PROPERTY, 254 INVALID_SUBSCRIPTION_ID); 255 256 private static VoidPropertyInvalidatedCache<Integer> sDefaultSmsSubIdCache = 257 new VoidPropertyInvalidatedCache<>(ISub::getDefaultSmsSubId, 258 CACHE_KEY_DEFAULT_SMS_SUB_ID_PROPERTY, 259 INVALID_SUBSCRIPTION_ID); 260 261 private static VoidPropertyInvalidatedCache<Integer> sActiveDataSubIdCache = 262 new VoidPropertyInvalidatedCache<>(ISub::getActiveDataSubscriptionId, 263 CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY, 264 INVALID_SUBSCRIPTION_ID); 265 266 private static IntegerPropertyInvalidatedCache<Integer> sSlotIndexCache = 267 new IntegerPropertyInvalidatedCache<>(ISub::getSlotIndex, 268 CACHE_KEY_SLOT_INDEX_PROPERTY, 269 INVALID_SIM_SLOT_INDEX); 270 271 /** Cache depends on getDefaultSubId, so we use the defaultSubId cache key */ 272 private static IntegerPropertyInvalidatedCache<Integer> sPhoneIdCache = 273 new IntegerPropertyInvalidatedCache<>(ISub::getPhoneId, 274 CACHE_KEY_DEFAULT_SUB_ID_PROPERTY, 275 INVALID_PHONE_INDEX); 276 277 /** 278 * Generates a content {@link Uri} used to receive updates on simInfo change 279 * on the given subscriptionId 280 * @param subscriptionId the subscriptionId to receive updates on 281 * @return the Uri used to observe carrier identity changes 282 * @hide 283 */ getUriForSubscriptionId(int subscriptionId)284 public static Uri getUriForSubscriptionId(int subscriptionId) { 285 return Uri.withAppendedPath(CONTENT_URI, String.valueOf(subscriptionId)); 286 } 287 288 /** 289 * A content {@link Uri} used to receive updates on wfc enabled user setting. 290 * <p> 291 * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the 292 * subscription wfc enabled {@link ImsMmTelManager#isVoWiFiSettingEnabled()} 293 * while your app is running. You can also use a {@link android.app.job.JobService} 294 * to ensure your app 295 * is notified of changes to the {@link Uri} even when it is not running. 296 * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely 297 * delivery of updates to the {@link Uri}. 298 * To be notified of changes to a specific subId, append subId to the URI 299 * {@link Uri#withAppendedPath(Uri, String)}. 300 * @hide 301 */ 302 @NonNull 303 @SystemApi 304 public static final Uri WFC_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc"); 305 306 /** 307 * A content {@link Uri} used to receive updates on advanced calling user setting 308 * @see ImsMmTelManager#isAdvancedCallingSettingEnabled(). 309 * <p> 310 * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the 311 * subscription advanced calling enabled 312 * {@link ImsMmTelManager#isAdvancedCallingSettingEnabled()} while your app is running. 313 * You can also use a {@link android.app.job.JobService} to ensure your app is notified of 314 * changes to the {@link Uri} even when it is not running. 315 * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely 316 * delivery of updates to the {@link Uri}. 317 * To be notified of changes to a specific subId, append subId to the URI 318 * {@link Uri#withAppendedPath(Uri, String)}. 319 * @hide 320 */ 321 @NonNull 322 @SystemApi 323 public static final Uri ADVANCED_CALLING_ENABLED_CONTENT_URI = Uri.withAppendedPath( 324 CONTENT_URI, "advanced_calling"); 325 326 /** 327 * A content {@link Uri} used to receive updates on wfc mode setting. 328 * <p> 329 * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the 330 * subscription wfc mode {@link ImsMmTelManager#getVoWiFiModeSetting()} 331 * while your app is running. You can also use a {@link android.app.job.JobService} to ensure 332 * your app is notified of changes to the {@link Uri} even when it is not running. 333 * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely 334 * delivery of updates to the {@link Uri}. 335 * To be notified of changes to a specific subId, append subId to the URI 336 * {@link Uri#withAppendedPath(Uri, String)}. 337 * @hide 338 */ 339 @NonNull 340 @SystemApi 341 public static final Uri WFC_MODE_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, "wfc_mode"); 342 343 /** 344 * A content {@link Uri} used to receive updates on wfc roaming mode setting. 345 * <p> 346 * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the 347 * subscription wfc roaming mode {@link ImsMmTelManager#getVoWiFiRoamingModeSetting()} 348 * while your app is running. You can also use a {@link android.app.job.JobService} 349 * to ensure your app is notified of changes to the {@link Uri} even when it is not running. 350 * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely 351 * delivery of updates to the {@link Uri}. 352 * To be notified of changes to a specific subId, append subId to the URI 353 * {@link Uri#withAppendedPath(Uri, String)}. 354 * @hide 355 */ 356 @NonNull 357 @SystemApi 358 public static final Uri WFC_ROAMING_MODE_CONTENT_URI = Uri.withAppendedPath( 359 CONTENT_URI, "wfc_roaming_mode"); 360 361 /** 362 * A content {@link Uri} used to receive updates on vt(video telephony over IMS) enabled 363 * setting. 364 * <p> 365 * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the 366 * subscription vt enabled {@link ImsMmTelManager#isVtSettingEnabled()} 367 * while your app is running. You can also use a {@link android.app.job.JobService} to ensure 368 * your app is notified of changes to the {@link Uri} even when it is not running. 369 * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely 370 * delivery of updates to the {@link Uri}. 371 * To be notified of changes to a specific subId, append subId to the URI 372 * {@link Uri#withAppendedPath(Uri, String)}. 373 * @hide 374 */ 375 @NonNull 376 @SystemApi 377 public static final Uri VT_ENABLED_CONTENT_URI = Uri.withAppendedPath( 378 CONTENT_URI, "vt_enabled"); 379 380 /** 381 * A content {@link Uri} used to receive updates on wfc roaming enabled setting. 382 * <p> 383 * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the 384 * subscription wfc roaming enabled {@link ImsMmTelManager#isVoWiFiRoamingSettingEnabled()} 385 * while your app is running. You can also use a {@link android.app.job.JobService} to ensure 386 * your app is notified of changes to the {@link Uri} even when it is not running. 387 * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely 388 * delivery of updates to the {@link Uri}. 389 * To be notified of changes to a specific subId, append subId to the URI 390 * {@link Uri#withAppendedPath(Uri, String)}. 391 * @hide 392 */ 393 @NonNull 394 @SystemApi 395 public static final Uri WFC_ROAMING_ENABLED_CONTENT_URI = Uri.withAppendedPath( 396 CONTENT_URI, "wfc_roaming_enabled"); 397 398 399 /** 400 * A content {@link uri} used to call the appropriate backup or restore method for sim-specific 401 * settings 402 * <p> 403 * See {@link #GET_SIM_SPECIFIC_SETTINGS_METHOD_NAME} and {@link 404 * #RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME} for information on what method to call. 405 * @hide 406 */ 407 @NonNull 408 public static final Uri SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI = Uri.withAppendedPath( 409 CONTENT_URI, "backup_and_restore"); 410 411 /** 412 * A content {@link uri} used to notify contentobservers listening to siminfo restore during 413 * SuW. 414 * @hide 415 */ 416 @NonNull 417 public static final Uri SIM_INFO_SUW_RESTORE_CONTENT_URI = Uri.withAppendedPath( 418 SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, "suw_restore"); 419 420 /** 421 * A content {@link Uri} used to receive updates on cross sim enabled user setting. 422 * <p> 423 * Use this {@link Uri} with a {@link ContentObserver} to be notified of changes to the 424 * subscription cross sim calling enabled 425 * {@link ImsMmTelManager#isCrossSimCallingEnabled()} 426 * while your app is running. You can also use a {@link android.app.job.JobService} 427 * to ensure your app 428 * is notified of changes to the {@link Uri} even when it is not running. 429 * Note, however, that using a {@link android.app.job.JobService} does not guarantee timely 430 * delivery of updates to the {@link Uri}. 431 * To be notified of changes to a specific subId, append subId to the URI 432 * {@link Uri#withAppendedPath(Uri, String)}. 433 * @hide 434 */ 435 @NonNull 436 @SystemApi 437 public static final Uri CROSS_SIM_ENABLED_CONTENT_URI = Uri.withAppendedPath(CONTENT_URI, 438 SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED); 439 440 /** 441 * TelephonyProvider unique key column name is the subscription id. 442 * <P>Type: TEXT (String)</P> 443 */ 444 /** @hide */ 445 public static final String UNIQUE_KEY_SUBSCRIPTION_ID = 446 SimInfo.COLUMN_UNIQUE_KEY_SUBSCRIPTION_ID; 447 448 /** 449 * TelephonyProvider column name for a unique identifier for the subscription within the 450 * specific subscription type. For example, it contains SIM ICC Identifier subscriptions 451 * on Local SIMs. and Mac-address for Remote-SIM Subscriptions for Bluetooth devices. 452 * <P>Type: TEXT (String)</P> 453 */ 454 /** @hide */ 455 public static final String ICC_ID = SimInfo.COLUMN_ICC_ID; 456 457 /** 458 * TelephonyProvider column name for user SIM_SlOT_INDEX 459 * <P>Type: INTEGER (int)</P> 460 */ 461 /** @hide */ 462 public static final String SIM_SLOT_INDEX = SimInfo.COLUMN_SIM_SLOT_INDEX; 463 464 /** SIM is not inserted */ 465 /** @hide */ 466 public static final int SIM_NOT_INSERTED = SimInfo.SIM_NOT_INSERTED; 467 468 /** 469 * The slot-index for Bluetooth Remote-SIM subscriptions 470 * @hide 471 */ 472 public static final int SLOT_INDEX_FOR_REMOTE_SIM_SUB = INVALID_SIM_SLOT_INDEX; 473 474 /** 475 * TelephonyProvider column name Subscription-type. 476 * <P>Type: INTEGER (int)</P> {@link #SUBSCRIPTION_TYPE_LOCAL_SIM} for Local-SIM Subscriptions, 477 * {@link #SUBSCRIPTION_TYPE_REMOTE_SIM} for Remote-SIM Subscriptions. 478 * Default value is 0. 479 */ 480 /** @hide */ 481 public static final String SUBSCRIPTION_TYPE = SimInfo.COLUMN_SUBSCRIPTION_TYPE; 482 483 /** 484 * TelephonyProvider column name data_enabled_override_rules. 485 * It's a list of rules for overriding data enabled settings. The syntax is 486 * For example, "mms=nonDefault" indicates enabling data for mms in non-default subscription. 487 * "default=nonDefault&inVoiceCall" indicates enabling data for internet in non-default 488 * subscription and while is in voice call. 489 * 490 * Default value is empty string. 491 * 492 * @hide 493 */ 494 public static final String DATA_ENABLED_OVERRIDE_RULES = 495 SimInfo.COLUMN_DATA_ENABLED_OVERRIDE_RULES; 496 497 /** @hide */ 498 @Retention(RetentionPolicy.SOURCE) 499 @IntDef(prefix = {"SUBSCRIPTION_TYPE_"}, 500 value = { 501 SUBSCRIPTION_TYPE_LOCAL_SIM, 502 SUBSCRIPTION_TYPE_REMOTE_SIM}) 503 public @interface SubscriptionType {} 504 505 /** 506 * This constant is to designate a subscription as a Local-SIM Subscription. 507 * <p> A Local-SIM can be a physical SIM inserted into a sim-slot in the device, or eSIM on the 508 * device. 509 * </p> 510 */ 511 public static final int SUBSCRIPTION_TYPE_LOCAL_SIM = SimInfo.SUBSCRIPTION_TYPE_LOCAL_SIM; 512 513 /** 514 * This constant is to designate a subscription as a Remote-SIM Subscription. 515 * <p> 516 * A Remote-SIM subscription is for a SIM on a phone connected to this device via some 517 * connectivity mechanism, for example bluetooth. Similar to Local SIM, this subscription can 518 * be used for SMS, Voice and data by proxying data through the connected device. 519 * Certain data of the SIM, such as IMEI, are not accessible for Remote SIMs. 520 * </p> 521 * 522 * <p> 523 * A Remote-SIM is available only as long the phone stays connected to this device. 524 * When the phone disconnects, Remote-SIM subscription is removed from this device and is 525 * no longer known. All data associated with the subscription, such as stored SMS, call logs, 526 * contacts etc, are removed from this device. 527 * </p> 528 * 529 * <p> 530 * If the phone re-connects to this device, a new Remote-SIM subscription is created for 531 * the phone. The Subscription Id associated with the new subscription is different from 532 * the Subscription Id of the previous Remote-SIM subscription created (and removed) for the 533 * phone; i.e., new Remote-SIM subscription treats the reconnected phone as a Remote-SIM that 534 * was never seen before. 535 * </p> 536 */ 537 public static final int SUBSCRIPTION_TYPE_REMOTE_SIM = SimInfo.SUBSCRIPTION_TYPE_REMOTE_SIM; 538 539 /** 540 * TelephonyProvider column name for user displayed name. 541 * <P>Type: TEXT (String)</P> 542 */ 543 /** @hide */ 544 public static final String DISPLAY_NAME = SimInfo.COLUMN_DISPLAY_NAME; 545 546 /** 547 * TelephonyProvider column name for the service provider name for the SIM. 548 * <P>Type: TEXT (String)</P> 549 */ 550 /** @hide */ 551 public static final String CARRIER_NAME = SimInfo.COLUMN_CARRIER_NAME; 552 553 /** 554 * Default name resource 555 * @hide 556 */ 557 public static final int DEFAULT_NAME_RES = com.android.internal.R.string.unknownName; 558 559 /** 560 * TelephonyProvider column name for source of the user displayed name. 561 * <P>Type: INT (int)</P> with one of the NAME_SOURCE_XXXX values below 562 * 563 * @hide 564 */ 565 public static final String NAME_SOURCE = SimInfo.COLUMN_NAME_SOURCE; 566 567 /** 568 * The name_source is from the carrier id. 569 * @hide 570 */ 571 public static final int NAME_SOURCE_CARRIER_ID = SimInfo.NAME_SOURCE_CARRIER_ID; 572 573 /** 574 * The name_source is from SIM EF_SPN. 575 * @hide 576 */ 577 public static final int NAME_SOURCE_SIM_SPN = SimInfo.NAME_SOURCE_SIM_SPN; 578 579 /** 580 * The name_source is from user input 581 * @hide 582 */ 583 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) 584 public static final int NAME_SOURCE_USER_INPUT = SimInfo.NAME_SOURCE_USER_INPUT; 585 586 /** 587 * The name_source is carrier (carrier app, carrier config, etc.) 588 * @hide 589 */ 590 public static final int NAME_SOURCE_CARRIER = SimInfo.NAME_SOURCE_CARRIER; 591 592 /** 593 * The name_source is from SIM EF_PNN. 594 * @hide 595 */ 596 public static final int NAME_SOURCE_SIM_PNN = SimInfo.NAME_SOURCE_SIM_PNN; 597 598 /** @hide */ 599 @Retention(RetentionPolicy.SOURCE) 600 @IntDef(prefix = {"NAME_SOURCE_"}, 601 value = { 602 NAME_SOURCE_CARRIER_ID, 603 NAME_SOURCE_SIM_SPN, 604 NAME_SOURCE_USER_INPUT, 605 NAME_SOURCE_CARRIER, 606 NAME_SOURCE_SIM_PNN 607 }) 608 public @interface SimDisplayNameSource {} 609 610 /** 611 * Device status is not shared to a remote party. 612 */ 613 public static final int D2D_SHARING_DISABLED = 0; 614 615 /** 616 * Device status is shared with all numbers in the user's contacts. 617 */ 618 public static final int D2D_SHARING_ALL_CONTACTS = 1; 619 620 /** 621 * Device status is shared with all selected contacts. 622 */ 623 public static final int D2D_SHARING_SELECTED_CONTACTS = 2; 624 625 /** 626 * Device status is shared whenever possible. 627 */ 628 public static final int D2D_SHARING_ALL = 3; 629 630 /** @hide */ 631 @Retention(RetentionPolicy.SOURCE) 632 @IntDef(prefix = {"D2D_SHARING_"}, 633 value = { 634 D2D_SHARING_DISABLED, 635 D2D_SHARING_ALL_CONTACTS, 636 D2D_SHARING_SELECTED_CONTACTS, 637 D2D_SHARING_ALL 638 }) 639 public @interface DeviceToDeviceStatusSharingPreference {} 640 641 /** 642 * TelephonyProvider column name for device to device sharing status. 643 * <P>Type: INTEGER (int)</P> 644 */ 645 public static final String D2D_STATUS_SHARING = SimInfo.COLUMN_D2D_STATUS_SHARING; 646 647 /** 648 * TelephonyProvider column name for contacts information that allow device to device sharing. 649 * <P>Type: TEXT (String)</P> 650 */ 651 public static final String D2D_STATUS_SHARING_SELECTED_CONTACTS = 652 SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS; 653 654 /** 655 * TelephonyProvider column name for the color of a SIM. 656 * <P>Type: INTEGER (int)</P> 657 */ 658 /** @hide */ 659 public static final String HUE = SimInfo.COLUMN_COLOR; 660 661 /** 662 * TelephonyProvider column name for the phone number of a SIM. 663 * <P>Type: TEXT (String)</P> 664 */ 665 /** @hide */ 666 public static final String NUMBER = SimInfo.COLUMN_NUMBER; 667 668 /** 669 * TelephonyProvider column name for whether data roaming is enabled. 670 * <P>Type: INTEGER (int)</P> 671 */ 672 /** @hide */ 673 public static final String DATA_ROAMING = SimInfo.COLUMN_DATA_ROAMING; 674 675 /** Indicates that data roaming is enabled for a subscription */ 676 public static final int DATA_ROAMING_ENABLE = SimInfo.DATA_ROAMING_ENABLE; 677 678 /** Indicates that data roaming is disabled for a subscription */ 679 public static final int DATA_ROAMING_DISABLE = SimInfo.DATA_ROAMING_DISABLE; 680 681 /** 682 * TelephonyProvider column name for subscription carrier id. 683 * @see TelephonyManager#getSimCarrierId() 684 * <p>Type: INTEGER (int) </p> 685 * @hide 686 */ 687 public static final String CARRIER_ID = SimInfo.COLUMN_CARRIER_ID; 688 689 /** 690 * @hide A comma-separated list of EHPLMNs associated with the subscription 691 * <P>Type: TEXT (String)</P> 692 */ 693 public static final String EHPLMNS = SimInfo.COLUMN_EHPLMNS; 694 695 /** 696 * @hide A comma-separated list of HPLMNs associated with the subscription 697 * <P>Type: TEXT (String)</P> 698 */ 699 public static final String HPLMNS = SimInfo.COLUMN_HPLMNS; 700 701 /** 702 * TelephonyProvider column name for the MCC associated with a SIM, stored as a string. 703 * <P>Type: TEXT (String)</P> 704 * @hide 705 */ 706 public static final String MCC_STRING = SimInfo.COLUMN_MCC_STRING; 707 708 /** 709 * TelephonyProvider column name for the MNC associated with a SIM, stored as a string. 710 * <P>Type: TEXT (String)</P> 711 * @hide 712 */ 713 public static final String MNC_STRING = SimInfo.COLUMN_MNC_STRING; 714 715 /** 716 * TelephonyProvider column name for the MCC associated with a SIM. 717 * <P>Type: INTEGER (int)</P> 718 * @hide 719 */ 720 public static final String MCC = SimInfo.COLUMN_MCC; 721 722 /** 723 * TelephonyProvider column name for the MNC associated with a SIM. 724 * <P>Type: INTEGER (int)</P> 725 * @hide 726 */ 727 public static final String MNC = SimInfo.COLUMN_MNC; 728 729 /** 730 * TelephonyProvider column name for the iso country code associated with a SIM. 731 * <P>Type: TEXT (String)</P> 732 * @hide 733 */ 734 public static final String ISO_COUNTRY_CODE = SimInfo.COLUMN_ISO_COUNTRY_CODE; 735 736 /** 737 * TelephonyProvider column name for whether a subscription is embedded (that is, present on an 738 * eSIM). 739 * <p>Type: INTEGER (int), 1 for embedded or 0 for non-embedded. 740 * @hide 741 */ 742 public static final String IS_EMBEDDED = SimInfo.COLUMN_IS_EMBEDDED; 743 744 /** 745 * TelephonyProvider column name for SIM card identifier. For UICC card it is the ICCID of the 746 * current enabled profile on the card, while for eUICC card it is the EID of the card. 747 * <P>Type: TEXT (String)</P> 748 * @hide 749 */ 750 public static final String CARD_ID = SimInfo.COLUMN_CARD_ID; 751 752 /** 753 * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from 754 * {@link UiccAccessRule#encodeRules}. Only present if {@link #IS_EMBEDDED} is 1. 755 * <p>TYPE: BLOB 756 * @hide 757 */ 758 public static final String ACCESS_RULES = SimInfo.COLUMN_ACCESS_RULES; 759 760 /** 761 * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from 762 * {@link UiccAccessRule#encodeRules} but for the rules that come from CarrierConfigs. 763 * Only present if there are access rules in CarrierConfigs 764 * <p>TYPE: BLOB 765 * @hide 766 */ 767 public static final String ACCESS_RULES_FROM_CARRIER_CONFIGS = 768 SimInfo.COLUMN_ACCESS_RULES_FROM_CARRIER_CONFIGS; 769 770 /** 771 * TelephonyProvider column name identifying whether an embedded subscription is on a removable 772 * card. Such subscriptions are marked inaccessible as soon as the current card is removed. 773 * Otherwise, they will remain accessible unless explicitly deleted. Only present if 774 * {@link #IS_EMBEDDED} is 1. 775 * <p>TYPE: INTEGER (int), 1 for removable or 0 for non-removable. 776 * @hide 777 */ 778 public static final String IS_REMOVABLE = SimInfo.COLUMN_IS_REMOVABLE; 779 780 /** 781 * TelephonyProvider column name for extreme threat in CB settings 782 * @hide 783 */ 784 public static final String CB_EXTREME_THREAT_ALERT = 785 SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT; 786 787 /** 788 * TelephonyProvider column name for severe threat in CB settings 789 *@hide 790 */ 791 public static final String CB_SEVERE_THREAT_ALERT = SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT; 792 793 /** 794 * TelephonyProvider column name for amber alert in CB settings 795 *@hide 796 */ 797 public static final String CB_AMBER_ALERT = SimInfo.COLUMN_CB_AMBER_ALERT; 798 799 /** 800 * TelephonyProvider column name for emergency alert in CB settings 801 *@hide 802 */ 803 public static final String CB_EMERGENCY_ALERT = SimInfo.COLUMN_CB_EMERGENCY_ALERT; 804 805 /** 806 * TelephonyProvider column name for alert sound duration in CB settings 807 *@hide 808 */ 809 public static final String CB_ALERT_SOUND_DURATION = 810 SimInfo.COLUMN_CB_ALERT_SOUND_DURATION; 811 812 /** 813 * TelephonyProvider column name for alert reminder interval in CB settings 814 *@hide 815 */ 816 public static final String CB_ALERT_REMINDER_INTERVAL = 817 SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL; 818 819 /** 820 * TelephonyProvider column name for enabling vibrate in CB settings 821 *@hide 822 */ 823 public static final String CB_ALERT_VIBRATE = SimInfo.COLUMN_CB_ALERT_VIBRATE; 824 825 /** 826 * TelephonyProvider column name for enabling alert speech in CB settings 827 *@hide 828 */ 829 public static final String CB_ALERT_SPEECH = SimInfo.COLUMN_CB_ALERT_SPEECH; 830 831 /** 832 * TelephonyProvider column name for ETWS test alert in CB settings 833 *@hide 834 */ 835 public static final String CB_ETWS_TEST_ALERT = SimInfo.COLUMN_CB_ETWS_TEST_ALERT; 836 837 /** 838 * TelephonyProvider column name for enable channel50 alert in CB settings 839 *@hide 840 */ 841 public static final String CB_CHANNEL_50_ALERT = SimInfo.COLUMN_CB_CHANNEL_50_ALERT; 842 843 /** 844 * TelephonyProvider column name for CMAS test alert in CB settings 845 *@hide 846 */ 847 public static final String CB_CMAS_TEST_ALERT = SimInfo.COLUMN_CB_CMAS_TEST_ALERT; 848 849 /** 850 * TelephonyProvider column name for Opt out dialog in CB settings 851 *@hide 852 */ 853 public static final String CB_OPT_OUT_DIALOG = SimInfo.COLUMN_CB_OPT_OUT_DIALOG; 854 855 /** 856 * TelephonyProvider column name for enable Volte. 857 * 858 * If this setting is not initialized (set to -1) then we use the Carrier Config value 859 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}. 860 *@hide 861 */ 862 public static final String ENHANCED_4G_MODE_ENABLED = 863 SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED; 864 865 /** 866 * TelephonyProvider column name for enable VT (Video Telephony over IMS) 867 *@hide 868 */ 869 public static final String VT_IMS_ENABLED = SimInfo.COLUMN_VT_IMS_ENABLED; 870 871 /** 872 * TelephonyProvider column name for enable Wifi calling 873 *@hide 874 */ 875 public static final String WFC_IMS_ENABLED = SimInfo.COLUMN_WFC_IMS_ENABLED; 876 877 /** 878 * TelephonyProvider column name for Wifi calling mode 879 *@hide 880 */ 881 public static final String WFC_IMS_MODE = SimInfo.COLUMN_WFC_IMS_MODE; 882 883 /** 884 * TelephonyProvider column name for Wifi calling mode in roaming 885 *@hide 886 */ 887 public static final String WFC_IMS_ROAMING_MODE = SimInfo.COLUMN_WFC_IMS_ROAMING_MODE; 888 889 /** 890 * TelephonyProvider column name for enable Wifi calling in roaming 891 *@hide 892 */ 893 public static final String WFC_IMS_ROAMING_ENABLED = SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED; 894 895 /** 896 * Determines if the user has enabled IMS RCS User Capability Exchange (UCE) for this 897 * subscription. 898 * @hide 899 */ 900 public static final String IMS_RCS_UCE_ENABLED = SimInfo.COLUMN_IMS_RCS_UCE_ENABLED; 901 902 /** 903 * Determines if the user has enabled cross SIM calling for this subscription. 904 * 905 * @hide 906 */ 907 public static final String CROSS_SIM_CALLING_ENABLED = SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED; 908 909 /** 910 * TelephonyProvider column name for whether a subscription is opportunistic, that is, 911 * whether the network it connects to is limited in functionality or coverage. 912 * For example, CBRS. 913 * <p>Type: INTEGER (int), 1 for opportunistic or 0 for non-opportunistic. 914 * @hide 915 */ 916 public static final String IS_OPPORTUNISTIC = SimInfo.COLUMN_IS_OPPORTUNISTIC; 917 918 /** 919 * TelephonyProvider column name for group ID. Subscriptions with same group ID 920 * are considered bundled together, and should behave as a single subscription at 921 * certain scenarios. 922 * 923 * @hide 924 */ 925 public static final String GROUP_UUID = SimInfo.COLUMN_GROUP_UUID; 926 927 /** 928 * TelephonyProvider column name for group owner. It's the package name who created 929 * the subscription group. 930 * 931 * @hide 932 */ 933 public static final String GROUP_OWNER = SimInfo.COLUMN_GROUP_OWNER; 934 935 /** 936 * TelephonyProvider column name for the profile class of a subscription 937 * Only present if {@link #IS_EMBEDDED} is 1. 938 * <P>Type: INTEGER (int)</P> 939 * @hide 940 */ 941 public static final String PROFILE_CLASS = SimInfo.COLUMN_PROFILE_CLASS; 942 943 /** 944 * TelephonyProvider column name for VoIMS opt-in status. 945 * 946 * <P>Type: INTEGER (int)</P> 947 * @hide 948 */ 949 public static final String VOIMS_OPT_IN_STATUS = SimInfo.COLUMN_VOIMS_OPT_IN_STATUS; 950 951 /** 952 * Profile class of the subscription 953 * @hide 954 */ 955 @Retention(RetentionPolicy.SOURCE) 956 @IntDef(prefix = { "PROFILE_CLASS_" }, value = { 957 SimInfo.PROFILE_CLASS_TESTING, 958 SimInfo.PROFILE_CLASS_PROVISIONING, 959 SimInfo.PROFILE_CLASS_OPERATIONAL, 960 SimInfo.PROFILE_CLASS_UNSET, 961 }) 962 public @interface ProfileClass {} 963 964 /** 965 * A testing profile can be pre-loaded or downloaded onto 966 * the eUICC and provides connectivity to test equipment 967 * for the purpose of testing the device and the eUICC. It 968 * is not intended to store any operator credentials. 969 * @hide 970 */ 971 @SystemApi 972 public static final int PROFILE_CLASS_TESTING = SimInfo.PROFILE_CLASS_TESTING; 973 974 /** 975 * A provisioning profile is pre-loaded onto the eUICC and 976 * provides connectivity to a mobile network solely for the 977 * purpose of provisioning profiles. 978 * @hide 979 */ 980 @SystemApi 981 public static final int PROFILE_CLASS_PROVISIONING = SimInfo.PROFILE_CLASS_PROVISIONING; 982 983 /** 984 * An operational profile can be pre-loaded or downloaded 985 * onto the eUICC and provides services provided by the 986 * operator. 987 * @hide 988 */ 989 @SystemApi 990 public static final int PROFILE_CLASS_OPERATIONAL = SimInfo.PROFILE_CLASS_OPERATIONAL; 991 992 /** 993 * The profile class is unset. This occurs when profile class 994 * info is not available. The subscription either has no profile 995 * metadata or the profile metadata did not encode profile class. 996 * @hide 997 */ 998 @SystemApi 999 public static final int PROFILE_CLASS_UNSET = SimInfo.PROFILE_CLASS_UNSET; 1000 1001 /** 1002 * Default profile class 1003 * @hide 1004 */ 1005 @SystemApi 1006 @Deprecated 1007 public static final int PROFILE_CLASS_DEFAULT = SimInfo.PROFILE_CLASS_UNSET; 1008 1009 /** 1010 * IMSI (International Mobile Subscriber Identity). 1011 * <P>Type: TEXT </P> 1012 * @hide 1013 */ 1014 //TODO: add @SystemApi 1015 public static final String IMSI = SimInfo.COLUMN_IMSI; 1016 1017 /** 1018 * Whether uicc applications is set to be enabled or disabled. By default it's enabled. 1019 * @hide 1020 */ 1021 public static final String UICC_APPLICATIONS_ENABLED = SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED; 1022 1023 /** 1024 * Indicate which network type is allowed. By default it's enabled. 1025 * @hide 1026 */ 1027 public static final String ALLOWED_NETWORK_TYPES = 1028 SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS; 1029 1030 /** 1031 * Broadcast Action: The user has changed one of the default subs related to 1032 * data, phone calls, or sms</p> 1033 * 1034 * TODO: Change to a listener 1035 * @hide 1036 */ 1037 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1038 public static final String SUB_DEFAULT_CHANGED_ACTION = 1039 "android.intent.action.SUB_DEFAULT_CHANGED"; 1040 1041 /** 1042 * Broadcast Action: The default subscription has changed. This has the following 1043 * extra values:</p> 1044 * The {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default subscription index 1045 */ 1046 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1047 public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED 1048 = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED"; 1049 1050 /** 1051 * Broadcast Action: The default sms subscription has changed. This has the following 1052 * extra values:</p> 1053 * {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default sms 1054 * subscription index 1055 */ 1056 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1057 public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED 1058 = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED"; 1059 1060 /** 1061 * Activity Action: Display UI for managing the billing relationship plans 1062 * between a carrier and a specific subscriber. 1063 * <p> 1064 * Carrier apps are encouraged to implement this activity, and the OS will 1065 * provide an affordance to quickly enter this activity, typically via 1066 * Settings. This affordance will only be shown when the carrier app is 1067 * actively providing subscription plan information via 1068 * {@link #setSubscriptionPlans(int, List)}. 1069 * <p> 1070 * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription 1071 * the user is interested in. 1072 */ 1073 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1074 public static final String ACTION_MANAGE_SUBSCRIPTION_PLANS 1075 = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS"; 1076 1077 /** 1078 * Broadcast Action: Request a refresh of the billing relationship plans 1079 * between a carrier and a specific subscriber. 1080 * <p> 1081 * Carrier apps are encouraged to implement this receiver, and the OS will 1082 * provide an affordance to request a refresh. This affordance will only be 1083 * shown when the carrier app is actively providing subscription plan 1084 * information via {@link #setSubscriptionPlans(int, List)}. 1085 * <p> 1086 * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription 1087 * the user is interested in. 1088 * <p> 1089 * Receivers should protect themselves by checking that the sender holds the 1090 * {@code android.permission.MANAGE_SUBSCRIPTION_PLANS} permission. 1091 */ 1092 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1093 public static final String ACTION_REFRESH_SUBSCRIPTION_PLANS 1094 = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS"; 1095 1096 /** 1097 * Broadcast Action: The billing relationship plans between a carrier and a 1098 * specific subscriber has changed. 1099 * <p> 1100 * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription 1101 * changed. 1102 * @hide 1103 */ 1104 @SystemApi 1105 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1106 @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS) 1107 public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED 1108 = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED"; 1109 1110 /** 1111 * Integer extra used with {@link #ACTION_DEFAULT_SUBSCRIPTION_CHANGED} and 1112 * {@link #ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED} to indicate the subscription 1113 * which has changed. 1114 */ 1115 public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX"; 1116 1117 /** 1118 * Integer extra to specify SIM slot index. 1119 */ 1120 public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX"; 1121 1122 private final Context mContext; 1123 1124 // Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing 1125 // the Context and subId. 1126 private static final Map<Pair<Context, Integer>, Resources> sResourcesCache = 1127 new ConcurrentHashMap<>(); 1128 1129 /** 1130 * A listener class for monitoring changes to {@link SubscriptionInfo} records. 1131 * <p> 1132 * Override the onSubscriptionsChanged method in the object that extends this 1133 * class and pass it to {@link #addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)} 1134 * to register your listener and to unregister invoke 1135 * {@link #removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)} 1136 * <p> 1137 * Permissions android.Manifest.permission.READ_PHONE_STATE is required 1138 * for #onSubscriptionsChanged to be invoked. 1139 */ 1140 public static class OnSubscriptionsChangedListener { 1141 private class OnSubscriptionsChangedListenerHandler extends Handler { OnSubscriptionsChangedListenerHandler()1142 OnSubscriptionsChangedListenerHandler() { 1143 super(); 1144 } 1145 OnSubscriptionsChangedListenerHandler(Looper looper)1146 OnSubscriptionsChangedListenerHandler(Looper looper) { 1147 super(looper); 1148 } 1149 } 1150 1151 /** 1152 * Posted executor callback on the handler associated with a given looper. 1153 * The looper can be the calling thread's looper or the looper passed from the 1154 * constructor {@link #OnSubscriptionsChangedListener(Looper)}. 1155 */ 1156 private final HandlerExecutor mExecutor; 1157 1158 /** 1159 * @hide 1160 */ getHandlerExecutor()1161 public HandlerExecutor getHandlerExecutor() { 1162 return mExecutor; 1163 } 1164 OnSubscriptionsChangedListener()1165 public OnSubscriptionsChangedListener() { 1166 mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler()); 1167 } 1168 1169 /** 1170 * Allow a listener to be created with a custom looper 1171 * @param looper the looper that the underlining handler should run on 1172 * @hide 1173 */ OnSubscriptionsChangedListener(Looper looper)1174 public OnSubscriptionsChangedListener(Looper looper) { 1175 mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler(looper)); 1176 } 1177 1178 /** 1179 * Callback invoked when there is any change to any SubscriptionInfo, as well as once on 1180 * registering for changes with {@link #addOnSubscriptionsChangedListener}. Typically 1181 * this method would invoke {@link #getActiveSubscriptionInfoList} 1182 */ onSubscriptionsChanged()1183 public void onSubscriptionsChanged() { 1184 if (DBG) log("onSubscriptionsChanged: NOT OVERRIDDEN"); 1185 } 1186 1187 /** 1188 * Callback invoked when {@link SubscriptionManager#addOnSubscriptionsChangedListener( 1189 * Executor, OnSubscriptionsChangedListener)} or 1190 * {@link SubscriptionManager#addOnSubscriptionsChangedListener( 1191 * OnSubscriptionsChangedListener)} fails to complete due to the 1192 * {@link Context#TELEPHONY_REGISTRY_SERVICE} being unavailable. 1193 * @hide 1194 */ onAddListenerFailed()1195 public void onAddListenerFailed() { 1196 Rlog.w(LOG_TAG, "onAddListenerFailed not overridden"); 1197 } 1198 log(String s)1199 private void log(String s) { 1200 Rlog.d(LOG_TAG, s); 1201 } 1202 } 1203 1204 /** @hide */ 1205 @UnsupportedAppUsage SubscriptionManager(Context context)1206 public SubscriptionManager(Context context) { 1207 if (DBG) logd("SubscriptionManager created"); 1208 mContext = context; 1209 } 1210 getNetworkPolicyManager()1211 private NetworkPolicyManager getNetworkPolicyManager() { 1212 return (NetworkPolicyManager) mContext 1213 .getSystemService(Context.NETWORK_POLICY_SERVICE); 1214 } 1215 1216 /** 1217 * @deprecated developers should always obtain references directly from 1218 * {@link Context#getSystemService(Class)}. 1219 */ 1220 @Deprecated from(Context context)1221 public static SubscriptionManager from(Context context) { 1222 return (SubscriptionManager) context 1223 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); 1224 } 1225 1226 /** 1227 * Register for changes to the list of active {@link SubscriptionInfo} records or to the 1228 * individual records themselves. When a change occurs the onSubscriptionsChanged method of 1229 * the listener will be invoked immediately if there has been a notification. The 1230 * onSubscriptionChanged method will also be triggered once initially when calling this 1231 * function. The callback will be invoked on the looper specified in the listener's constructor. 1232 * 1233 * @param listener an instance of {@link OnSubscriptionsChangedListener} with 1234 * onSubscriptionsChanged overridden. 1235 * 1236 * @deprecated Will get exception if the parameter listener is not initialized with a Looper. 1237 * Use {@link #addOnSubscriptionsChangedListener(Executor, OnSubscriptionsChangedListener)}. 1238 */ 1239 @Deprecated addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener)1240 public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { 1241 if (listener == null) return; 1242 addOnSubscriptionsChangedListener(listener.mExecutor, listener); 1243 } 1244 1245 /** 1246 * Register for changes to the list of active {@link SubscriptionInfo} records or to the 1247 * individual records themselves. When a change occurs the onSubscriptionsChanged method of 1248 * the listener will be invoked immediately if there has been a notification. The 1249 * onSubscriptionChanged method will also be triggered once initially when calling this 1250 * function. 1251 * 1252 * @param listener an instance of {@link OnSubscriptionsChangedListener} with 1253 * onSubscriptionsChanged overridden. 1254 * @param executor the executor that will execute callbacks. 1255 */ addOnSubscriptionsChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnSubscriptionsChangedListener listener)1256 public void addOnSubscriptionsChangedListener( 1257 @NonNull @CallbackExecutor Executor executor, 1258 @NonNull OnSubscriptionsChangedListener listener) { 1259 String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 1260 if (DBG) { 1261 logd("register OnSubscriptionsChangedListener pkgName=" + pkgName 1262 + " listener=" + listener); 1263 } 1264 // We use the TelephonyRegistry as it runs in the system and thus is always 1265 // available. Where as SubscriptionController could crash and not be available 1266 TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) 1267 mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 1268 if (telephonyRegistryManager != null) { 1269 telephonyRegistryManager.addOnSubscriptionsChangedListener(listener, 1270 executor); 1271 } else { 1272 // If the telephony registry isn't available, we will inform the caller on their 1273 // listener that it failed so they can try to re-register. 1274 loge("addOnSubscriptionsChangedListener: pkgname=" + pkgName + " failed to be added " 1275 + " due to TELEPHONY_REGISTRY_SERVICE being unavailable."); 1276 executor.execute(() -> listener.onAddListenerFailed()); 1277 } 1278 } 1279 1280 /** 1281 * Unregister the {@link OnSubscriptionsChangedListener}. This is not strictly necessary 1282 * as the listener will automatically be unregistered if an attempt to invoke the listener 1283 * fails. 1284 * 1285 * @param listener that is to be unregistered. 1286 */ removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener)1287 public void removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { 1288 if (listener == null) return; 1289 String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 1290 if (DBG) { 1291 logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug 1292 + " listener=" + listener); 1293 } 1294 // We use the TelephonyRegistry as it runs in the system and thus is always 1295 // available where as SubscriptionController could crash and not be available 1296 TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) 1297 mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 1298 if (telephonyRegistryManager != null) { 1299 telephonyRegistryManager.removeOnSubscriptionsChangedListener(listener); 1300 } 1301 } 1302 1303 /** 1304 * A listener class for monitoring changes to {@link SubscriptionInfo} records of opportunistic 1305 * subscriptions. 1306 * <p> 1307 * Override the onOpportunisticSubscriptionsChanged method in the object that extends this 1308 * or {@link #addOnOpportunisticSubscriptionsChangedListener( 1309 * Executor, OnOpportunisticSubscriptionsChangedListener)} 1310 * to register your listener and to unregister invoke 1311 * {@link #removeOnOpportunisticSubscriptionsChangedListener( 1312 * OnOpportunisticSubscriptionsChangedListener)} 1313 * <p> 1314 * Permissions android.Manifest.permission.READ_PHONE_STATE is required 1315 * for #onOpportunisticSubscriptionsChanged to be invoked. 1316 */ 1317 public static class OnOpportunisticSubscriptionsChangedListener { 1318 /** 1319 * Callback invoked when there is any change to any SubscriptionInfo. Typically 1320 * this method would invoke {@link #getActiveSubscriptionInfoList} 1321 */ onOpportunisticSubscriptionsChanged()1322 public void onOpportunisticSubscriptionsChanged() { 1323 if (DBG) log("onOpportunisticSubscriptionsChanged: NOT OVERRIDDEN"); 1324 } 1325 log(String s)1326 private void log(String s) { 1327 Rlog.d(LOG_TAG, s); 1328 } 1329 } 1330 1331 /** 1332 * Register for changes to the list of opportunistic subscription records or to the 1333 * individual records themselves. When a change occurs the onOpportunisticSubscriptionsChanged 1334 * method of the listener will be invoked immediately if there has been a notification. 1335 * 1336 * @param listener an instance of {@link OnOpportunisticSubscriptionsChangedListener} with 1337 * onOpportunisticSubscriptionsChanged overridden. 1338 */ addOnOpportunisticSubscriptionsChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnOpportunisticSubscriptionsChangedListener listener)1339 public void addOnOpportunisticSubscriptionsChangedListener( 1340 @NonNull @CallbackExecutor Executor executor, 1341 @NonNull OnOpportunisticSubscriptionsChangedListener listener) { 1342 if (executor == null || listener == null) { 1343 return; 1344 } 1345 1346 String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 1347 if (DBG) { 1348 logd("register addOnOpportunisticSubscriptionsChangedListener pkgName=" + pkgName 1349 + " listener=" + listener); 1350 } 1351 1352 // We use the TelephonyRegistry as it runs in the system and thus is always 1353 // available where as SubscriptionController could crash and not be available 1354 TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) 1355 mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 1356 if (telephonyRegistryManager != null) { 1357 telephonyRegistryManager.addOnOpportunisticSubscriptionsChangedListener( 1358 listener, executor); 1359 } 1360 } 1361 1362 /** 1363 * Unregister the {@link OnOpportunisticSubscriptionsChangedListener} that is currently 1364 * listening opportunistic subscriptions change. This is not strictly necessary 1365 * as the listener will automatically be unregistered if an attempt to invoke the listener 1366 * fails. 1367 * 1368 * @param listener that is to be unregistered. 1369 */ removeOnOpportunisticSubscriptionsChangedListener( @onNull OnOpportunisticSubscriptionsChangedListener listener)1370 public void removeOnOpportunisticSubscriptionsChangedListener( 1371 @NonNull OnOpportunisticSubscriptionsChangedListener listener) { 1372 Preconditions.checkNotNull(listener, "listener cannot be null"); 1373 String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 1374 if (DBG) { 1375 logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug=" 1376 + pkgForDebug + " listener=" + listener); 1377 } 1378 TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) 1379 mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 1380 if (telephonyRegistryManager != null) { 1381 telephonyRegistryManager.removeOnOpportunisticSubscriptionsChangedListener(listener); 1382 } 1383 } 1384 1385 /** 1386 * Get the active SubscriptionInfo with the input subId. 1387 * 1388 * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 1389 * or that the calling app has carrier privileges (see 1390 * {@link TelephonyManager#hasCarrierPrivileges}). 1391 * 1392 * @param subId The unique SubscriptionInfo key in database. 1393 * @return SubscriptionInfo, maybe null if its not active. 1394 */ 1395 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 1396 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) getActiveSubscriptionInfo(int subId)1397 public SubscriptionInfo getActiveSubscriptionInfo(int subId) { 1398 if (VDBG) logd("[getActiveSubscriptionInfo]+ subId=" + subId); 1399 if (!isValidSubscriptionId(subId)) { 1400 if (DBG) { 1401 logd("[getActiveSubscriptionInfo]- invalid subId"); 1402 } 1403 return null; 1404 } 1405 1406 SubscriptionInfo subInfo = null; 1407 1408 try { 1409 ISub iSub = TelephonyManager.getSubscriptionService(); 1410 if (iSub != null) { 1411 subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName(), 1412 mContext.getAttributionTag()); 1413 } 1414 } catch (RemoteException ex) { 1415 // ignore it 1416 } 1417 1418 return subInfo; 1419 } 1420 1421 /** 1422 * Gets an active SubscriptionInfo {@link SubscriptionInfo} associated with the Sim IccId. 1423 * 1424 * @param iccId the IccId of SIM card 1425 * @return SubscriptionInfo, maybe null if its not active 1426 * 1427 * @hide 1428 */ 1429 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) 1430 @Nullable 1431 @SystemApi getActiveSubscriptionInfoForIcc(@onNull String iccId)1432 public SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String iccId) { 1433 if (VDBG) logd("[getActiveSubscriptionInfoForIccIndex]+ iccId=" + iccId); 1434 if (iccId == null) { 1435 logd("[getActiveSubscriptionInfoForIccIndex]- null iccid"); 1436 return null; 1437 } 1438 1439 SubscriptionInfo result = null; 1440 1441 try { 1442 ISub iSub = TelephonyManager.getSubscriptionService(); 1443 if (iSub != null) { 1444 result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName(), 1445 mContext.getAttributionTag()); 1446 } 1447 } catch (RemoteException ex) { 1448 // ignore it 1449 } 1450 1451 return result; 1452 } 1453 1454 /** 1455 * Get the active SubscriptionInfo associated with the slotIndex 1456 * 1457 * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 1458 * or that the calling app has carrier privileges (see 1459 * {@link TelephonyManager#hasCarrierPrivileges}). 1460 * 1461 * @param slotIndex the slot which the subscription is inserted 1462 * @return SubscriptionInfo, maybe null if its not active 1463 */ 1464 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 1465 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) getActiveSubscriptionInfoForSimSlotIndex(int slotIndex)1466 public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) { 1467 if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIndex=" + slotIndex); 1468 if (!isValidSlotIndex(slotIndex)) { 1469 logd("[getActiveSubscriptionInfoForSimSlotIndex]- invalid slotIndex"); 1470 return null; 1471 } 1472 1473 SubscriptionInfo result = null; 1474 1475 try { 1476 ISub iSub = TelephonyManager.getSubscriptionService(); 1477 if (iSub != null) { 1478 result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex, 1479 mContext.getOpPackageName(), mContext.getAttributionTag()); 1480 } 1481 } catch (RemoteException ex) { 1482 // ignore it 1483 } 1484 1485 return result; 1486 } 1487 1488 /** 1489 * @return List of all SubscriptionInfo records in database, 1490 * include those that were inserted before, maybe empty but not null. 1491 * @hide 1492 */ 1493 @NonNull 1494 @UnsupportedAppUsage getAllSubscriptionInfoList()1495 public List<SubscriptionInfo> getAllSubscriptionInfoList() { 1496 if (VDBG) logd("[getAllSubscriptionInfoList]+"); 1497 1498 List<SubscriptionInfo> result = null; 1499 1500 try { 1501 ISub iSub = TelephonyManager.getSubscriptionService(); 1502 if (iSub != null) { 1503 result = iSub.getAllSubInfoList(mContext.getOpPackageName(), 1504 mContext.getAttributionTag()); 1505 } 1506 } catch (RemoteException ex) { 1507 // ignore it 1508 } 1509 1510 if (result == null) { 1511 result = Collections.emptyList(); 1512 } 1513 return result; 1514 } 1515 1516 /** 1517 * Get the SubscriptionInfo(s) of the currently active SIM(s). The records will be sorted 1518 * by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}. 1519 * 1520 * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 1521 * or that the calling app has carrier privileges (see 1522 * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible 1523 * to the calling app are returned. 1524 * 1525 * @return Sorted list of the currently {@link SubscriptionInfo} records available on the device. 1526 * <ul> 1527 * <li> 1528 * If null is returned the current state is unknown but if a {@link OnSubscriptionsChangedListener} 1529 * has been registered {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be 1530 * invoked in the future. 1531 * </li> 1532 * <li> 1533 * If the list is empty then there are no {@link SubscriptionInfo} records currently available. 1534 * </li> 1535 * <li> 1536 * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} 1537 * then by {@link SubscriptionInfo#getSubscriptionId}. 1538 * </li> 1539 * </ul> 1540 */ 1541 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 1542 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) getActiveSubscriptionInfoList()1543 public List<SubscriptionInfo> getActiveSubscriptionInfoList() { 1544 return getActiveSubscriptionInfoList(/* userVisibleonly */true); 1545 } 1546 1547 /** 1548 * Get both hidden and visible SubscriptionInfo(s) of the currently active SIM(s). 1549 * The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} 1550 * then by {@link SubscriptionInfo#getSubscriptionId}. 1551 * 1552 * Hidden subscriptions refer to those are not meant visible to the users. 1553 * For example, an opportunistic subscription that is grouped with other 1554 * subscriptions should remain invisible to users as they are only functionally 1555 * supplementary to primary ones. 1556 * 1557 * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 1558 * or that the calling app has carrier privileges (see 1559 * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible 1560 * to the calling app are returned. 1561 * 1562 * @return Sorted list of the currently available {@link SubscriptionInfo} 1563 * records on the device. 1564 * This is similar to {@link #getActiveSubscriptionInfoList} except that it will return 1565 * both active and hidden SubscriptionInfos. 1566 * 1567 */ getCompleteActiveSubscriptionInfoList()1568 public @NonNull List<SubscriptionInfo> getCompleteActiveSubscriptionInfoList() { 1569 List<SubscriptionInfo> completeList = getActiveSubscriptionInfoList( 1570 /* userVisibleonly */false); 1571 if (completeList == null) { 1572 completeList = new ArrayList<>(); 1573 } 1574 return completeList; 1575 } 1576 1577 /** 1578 * This is similar to {@link #getActiveSubscriptionInfoList()}, but if userVisibleOnly 1579 * is true, it will filter out the hidden subscriptions. 1580 * 1581 * @hide 1582 */ getActiveSubscriptionInfoList(boolean userVisibleOnly)1583 public @Nullable List<SubscriptionInfo> getActiveSubscriptionInfoList(boolean userVisibleOnly) { 1584 List<SubscriptionInfo> activeList = null; 1585 1586 try { 1587 ISub iSub = TelephonyManager.getSubscriptionService(); 1588 if (iSub != null) { 1589 activeList = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName(), 1590 mContext.getAttributionTag()); 1591 } 1592 } catch (RemoteException ex) { 1593 // ignore it 1594 } 1595 1596 if (!userVisibleOnly || activeList == null) { 1597 return activeList; 1598 } else { 1599 return activeList.stream().filter(subInfo -> isSubscriptionVisible(subInfo)) 1600 .collect(Collectors.toList()); 1601 } 1602 } 1603 1604 /** 1605 * Gets the SubscriptionInfo(s) of all available subscriptions, if any. 1606 * 1607 * <p>Available subscriptions include active ones (those with a non-negative 1608 * {@link SubscriptionInfo#getSimSlotIndex()}) as well as inactive but installed embedded 1609 * subscriptions. 1610 * 1611 * <p>The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by 1612 * {@link SubscriptionInfo#getSubscriptionId}. 1613 * 1614 * @return Sorted list of the current {@link SubscriptionInfo} records available on the 1615 * device. 1616 * <ul> 1617 * <li> 1618 * If null is returned the current state is unknown but if a 1619 * {@link OnSubscriptionsChangedListener} has been registered 1620 * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be invoked in the future. 1621 * <li> 1622 * If the list is empty then there are no {@link SubscriptionInfo} records currently available. 1623 * <li> 1624 * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} 1625 * then by {@link SubscriptionInfo#getSubscriptionId}. 1626 * </ul> 1627 * 1628 * <p> 1629 * Permissions android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE is required 1630 * for #getAvailableSubscriptionInfoList to be invoked. 1631 * @hide 1632 */ 1633 @SystemApi getAvailableSubscriptionInfoList()1634 public List<SubscriptionInfo> getAvailableSubscriptionInfoList() { 1635 List<SubscriptionInfo> result = null; 1636 1637 try { 1638 ISub iSub = TelephonyManager.getSubscriptionService(); 1639 if (iSub != null) { 1640 result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName(), 1641 mContext.getAttributionTag()); 1642 } 1643 } catch (RemoteException ex) { 1644 // ignore it 1645 } 1646 return result; 1647 } 1648 1649 /** 1650 * Gets the SubscriptionInfo(s) of all embedded subscriptions accessible to the calling app, if 1651 * any. 1652 * 1653 * <p>Only those subscriptions for which the calling app has carrier privileges per the 1654 * subscription metadata, if any, will be included in the returned list. 1655 * 1656 * <p>The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by 1657 * {@link SubscriptionInfo#getSubscriptionId}. 1658 * 1659 * @return Sorted list of the current embedded {@link SubscriptionInfo} records available on the 1660 * device which are accessible to the caller. 1661 * <ul> 1662 * <li> 1663 * If null is returned the current state is unknown but if a 1664 * {@link OnSubscriptionsChangedListener} has been registered 1665 * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be invoked in the future. 1666 * <li> 1667 * If the list is empty then there are no {@link SubscriptionInfo} records currently available. 1668 * <li> 1669 * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} 1670 * then by {@link SubscriptionInfo#getSubscriptionId}. 1671 * </ul> 1672 */ getAccessibleSubscriptionInfoList()1673 public List<SubscriptionInfo> getAccessibleSubscriptionInfoList() { 1674 List<SubscriptionInfo> result = null; 1675 1676 try { 1677 ISub iSub = TelephonyManager.getSubscriptionService(); 1678 if (iSub != null) { 1679 result = iSub.getAccessibleSubscriptionInfoList(mContext.getOpPackageName()); 1680 } 1681 } catch (RemoteException ex) { 1682 // ignore it 1683 } 1684 return result; 1685 } 1686 1687 /** 1688 * Request a refresh of the platform cache of profile information for the eUICC which 1689 * corresponds to the card ID returned by {@link TelephonyManager#getCardIdForDefaultEuicc()}. 1690 * 1691 * <p>Should be called by the EuiccService implementation whenever this information changes due 1692 * to an operation done outside the scope of a request initiated by the platform to the 1693 * EuiccService. There is no need to refresh for downloads, deletes, or other operations that 1694 * were made through the EuiccService. 1695 * 1696 * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. 1697 * 1698 * @see {@link TelephonyManager#getCardIdForDefaultEuicc()} for more information on the card ID. 1699 * 1700 * @hide 1701 */ 1702 @SystemApi requestEmbeddedSubscriptionInfoListRefresh()1703 public void requestEmbeddedSubscriptionInfoListRefresh() { 1704 int cardId = TelephonyManager.from(mContext).getCardIdForDefaultEuicc(); 1705 try { 1706 ISub iSub = TelephonyManager.getSubscriptionService(); 1707 if (iSub != null) { 1708 iSub.requestEmbeddedSubscriptionInfoListRefresh(cardId); 1709 } 1710 } catch (RemoteException ex) { 1711 logd("requestEmbeddedSubscriptionInfoListFresh for card = " + cardId + " failed."); 1712 } 1713 } 1714 1715 /** 1716 * Request a refresh of the platform cache of profile information for the eUICC with the given 1717 * {@code cardId}. 1718 * 1719 * <p>Should be called by the EuiccService implementation whenever this information changes due 1720 * to an operation done outside the scope of a request initiated by the platform to the 1721 * EuiccService. There is no need to refresh for downloads, deletes, or other operations that 1722 * were made through the EuiccService. 1723 * 1724 * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. 1725 * 1726 * @param cardId the card ID of the eUICC. 1727 * 1728 * @see {@link TelephonyManager#getCardIdForDefaultEuicc()} for more information on the card ID. 1729 * 1730 * @hide 1731 */ 1732 @SystemApi requestEmbeddedSubscriptionInfoListRefresh(int cardId)1733 public void requestEmbeddedSubscriptionInfoListRefresh(int cardId) { 1734 try { 1735 ISub iSub = TelephonyManager.getSubscriptionService(); 1736 if (iSub != null) { 1737 iSub.requestEmbeddedSubscriptionInfoListRefresh(cardId); 1738 } 1739 } catch (RemoteException ex) { 1740 logd("requestEmbeddedSubscriptionInfoListFresh for card = " + cardId + " failed."); 1741 } 1742 } 1743 1744 /** 1745 * @return the count of all subscriptions in the database, this includes 1746 * all subscriptions that have been seen. 1747 * @hide 1748 */ 1749 @UnsupportedAppUsage getAllSubscriptionInfoCount()1750 public int getAllSubscriptionInfoCount() { 1751 if (VDBG) logd("[getAllSubscriptionInfoCount]+"); 1752 1753 int result = 0; 1754 1755 try { 1756 ISub iSub = TelephonyManager.getSubscriptionService(); 1757 if (iSub != null) { 1758 result = iSub.getAllSubInfoCount(mContext.getOpPackageName(), 1759 mContext.getAttributionTag()); 1760 } 1761 } catch (RemoteException ex) { 1762 // ignore it 1763 } 1764 1765 return result; 1766 } 1767 1768 /** 1769 * 1770 * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 1771 * or that the calling app has carrier privileges (see 1772 * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, the count will include 1773 * only those subscriptions accessible to the caller. 1774 * 1775 * @return the current number of active subscriptions. There is no guarantee the value 1776 * returned by this method will be the same as the length of the list returned by 1777 * {@link #getActiveSubscriptionInfoList}. 1778 */ 1779 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 1780 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) getActiveSubscriptionInfoCount()1781 public int getActiveSubscriptionInfoCount() { 1782 int result = 0; 1783 1784 try { 1785 ISub iSub = TelephonyManager.getSubscriptionService(); 1786 if (iSub != null) { 1787 result = iSub.getActiveSubInfoCount(mContext.getOpPackageName(), 1788 mContext.getAttributionTag()); 1789 } 1790 } catch (RemoteException ex) { 1791 // ignore it 1792 } 1793 1794 return result; 1795 } 1796 1797 /** 1798 * @return the maximum number of active subscriptions that will be returned by 1799 * {@link #getActiveSubscriptionInfoList} and the value returned by 1800 * {@link #getActiveSubscriptionInfoCount}. 1801 */ getActiveSubscriptionInfoCountMax()1802 public int getActiveSubscriptionInfoCountMax() { 1803 int result = 0; 1804 1805 try { 1806 ISub iSub = TelephonyManager.getSubscriptionService(); 1807 if (iSub != null) { 1808 result = iSub.getActiveSubInfoCountMax(); 1809 } 1810 } catch (RemoteException ex) { 1811 // ignore it 1812 } 1813 1814 return result; 1815 } 1816 1817 /** 1818 * Add a new SubscriptionInfo to SubscriptionInfo database if needed 1819 * @param iccId the IccId of the SIM card 1820 * @param slotIndex the slot which the SIM is inserted 1821 * @return the URL of the newly created row or the updated row 1822 * @hide 1823 */ addSubscriptionInfoRecord(String iccId, int slotIndex)1824 public Uri addSubscriptionInfoRecord(String iccId, int slotIndex) { 1825 if (VDBG) logd("[addSubscriptionInfoRecord]+ iccId:" + iccId + " slotIndex:" + slotIndex); 1826 if (iccId == null) { 1827 logd("[addSubscriptionInfoRecord]- null iccId"); 1828 } 1829 if (!isValidSlotIndex(slotIndex)) { 1830 logd("[addSubscriptionInfoRecord]- invalid slotIndex"); 1831 } 1832 1833 addSubscriptionInfoRecord(iccId, null, slotIndex, SUBSCRIPTION_TYPE_LOCAL_SIM); 1834 1835 // FIXME: Always returns null? 1836 return null; 1837 1838 } 1839 1840 /** 1841 * Add a new SubscriptionInfo to SubscriptionInfo database if needed 1842 * @param uniqueId This is the unique identifier for the subscription within the 1843 * specific subscription type. 1844 * @param displayName human-readable name of the device the subscription corresponds to. 1845 * @param slotIndex the slot assigned to this subscription. It is ignored for subscriptionType 1846 * of {@link #SUBSCRIPTION_TYPE_REMOTE_SIM}. 1847 * @param subscriptionType the {@link #SUBSCRIPTION_TYPE} 1848 * @hide 1849 */ addSubscriptionInfoRecord(String uniqueId, String displayName, int slotIndex, int subscriptionType)1850 public void addSubscriptionInfoRecord(String uniqueId, String displayName, int slotIndex, 1851 int subscriptionType) { 1852 if (VDBG) { 1853 logd("[addSubscriptionInfoRecord]+ uniqueId:" + uniqueId 1854 + ", displayName:" + displayName + ", slotIndex:" + slotIndex 1855 + ", subscriptionType: " + subscriptionType); 1856 } 1857 if (uniqueId == null) { 1858 Log.e(LOG_TAG, "[addSubscriptionInfoRecord]- uniqueId is null"); 1859 return; 1860 } 1861 1862 try { 1863 ISub iSub = TelephonyManager.getSubscriptionService(); 1864 if (iSub == null) { 1865 Log.e(LOG_TAG, "[addSubscriptionInfoRecord]- ISub service is null"); 1866 return; 1867 } 1868 int result = iSub.addSubInfo(uniqueId, displayName, slotIndex, subscriptionType); 1869 if (result < 0) { 1870 Log.e(LOG_TAG, "Adding of subscription didn't succeed: error = " + result); 1871 } else { 1872 logd("successfully added new subscription"); 1873 } 1874 } catch (RemoteException ex) { 1875 // ignore it 1876 } 1877 } 1878 1879 /** 1880 * Remove SubscriptionInfo record from the SubscriptionInfo database 1881 * @param uniqueId This is the unique identifier for the subscription within the specific 1882 * subscription type. 1883 * @param subscriptionType the {@link #SUBSCRIPTION_TYPE} 1884 * @hide 1885 */ removeSubscriptionInfoRecord(String uniqueId, int subscriptionType)1886 public void removeSubscriptionInfoRecord(String uniqueId, int subscriptionType) { 1887 if (VDBG) { 1888 logd("[removeSubscriptionInfoRecord]+ uniqueId:" + uniqueId 1889 + ", subscriptionType: " + subscriptionType); 1890 } 1891 if (uniqueId == null) { 1892 Log.e(LOG_TAG, "[addSubscriptionInfoRecord]- uniqueId is null"); 1893 return; 1894 } 1895 1896 try { 1897 ISub iSub = TelephonyManager.getSubscriptionService(); 1898 if (iSub == null) { 1899 Log.e(LOG_TAG, "[removeSubscriptionInfoRecord]- ISub service is null"); 1900 return; 1901 } 1902 int result = iSub.removeSubInfo(uniqueId, subscriptionType); 1903 if (result < 0) { 1904 Log.e(LOG_TAG, "Removal of subscription didn't succeed: error = " + result); 1905 } else { 1906 logd("successfully removed subscription"); 1907 } 1908 } catch (RemoteException ex) { 1909 // ignore it 1910 } 1911 } 1912 1913 /** 1914 * Set SIM icon tint color for subscription ID 1915 * @param tint the RGB value of icon tint color of the SIM 1916 * @param subId the unique Subscritpion ID in database 1917 * @return the number of records updated 1918 * @hide 1919 */ 1920 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setIconTint(@olorInt int tint, int subId)1921 public int setIconTint(@ColorInt int tint, int subId) { 1922 if (VDBG) logd("[setIconTint]+ tint:" + tint + " subId:" + subId); 1923 return setSubscriptionPropertyHelper(subId, "setIconTint", 1924 (iSub)-> iSub.setIconTint(tint, subId) 1925 ); 1926 } 1927 1928 /** 1929 * Set the display name for a subscription ID 1930 * @param displayName the display name of SIM card 1931 * @param subId the unique Subscritpion ID in database 1932 * @param nameSource SIM display name source 1933 * @return the number of records updated or < 0 if invalid subId 1934 * @hide 1935 */ 1936 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDisplayName(@ullable String displayName, int subId, @SimDisplayNameSource int nameSource)1937 public int setDisplayName(@Nullable String displayName, int subId, 1938 @SimDisplayNameSource int nameSource) { 1939 if (VDBG) { 1940 logd("[setDisplayName]+ displayName:" + displayName + " subId:" + subId 1941 + " nameSource:" + nameSource); 1942 } 1943 return setSubscriptionPropertyHelper(subId, "setDisplayName", 1944 (iSub)-> iSub.setDisplayNameUsingSrc(displayName, subId, nameSource) 1945 ); 1946 } 1947 1948 /** 1949 * Set phone number by subId 1950 * @param number the phone number of the SIM 1951 * @param subId the unique SubscriptionInfo index in database 1952 * @return the number of records updated 1953 * @hide 1954 */ 1955 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setDisplayNumber(String number, int subId)1956 public int setDisplayNumber(String number, int subId) { 1957 if (number == null) { 1958 logd("[setDisplayNumber]- fail"); 1959 return -1; 1960 } 1961 return setSubscriptionPropertyHelper(subId, "setDisplayNumber", 1962 (iSub)-> iSub.setDisplayNumber(number, subId) 1963 ); 1964 } 1965 1966 /** 1967 * Set data roaming by simInfo index 1968 * @param roaming 0:Don't allow data when roaming, 1:Allow data when roaming 1969 * @param subId the unique SubscriptionInfo index in database 1970 * @return the number of records updated 1971 * @hide 1972 */ 1973 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setDataRoaming(int roaming, int subId)1974 public int setDataRoaming(int roaming, int subId) { 1975 if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId); 1976 return setSubscriptionPropertyHelper(subId, "setDataRoaming", 1977 (iSub)->iSub.setDataRoaming(roaming, subId) 1978 ); 1979 } 1980 1981 /** 1982 * Get slotIndex associated with the subscription. 1983 * 1984 * @param subscriptionId the unique SubscriptionInfo index in database 1985 * @return slotIndex as a positive integer or {@link #INVALID_SIM_SLOT_INDEX} if the supplied 1986 * subscriptionId doesn't have an associated slot index. 1987 */ getSlotIndex(int subscriptionId)1988 public static int getSlotIndex(int subscriptionId) { 1989 return sSlotIndexCache.query(subscriptionId); 1990 } 1991 1992 /** 1993 * Get an array of Subscription Ids for specified slot Index. 1994 * @param slotIndex the slot index. 1995 * @return subscription Ids or null if the given slot Index is not valid or there are no active 1996 * subscriptions in the slot. 1997 */ 1998 @Nullable getSubscriptionIds(int slotIndex)1999 public int[] getSubscriptionIds(int slotIndex) { 2000 return getSubId(slotIndex); 2001 } 2002 2003 /** @hide */ 2004 @UnsupportedAppUsage getSubId(int slotIndex)2005 public static int[] getSubId(int slotIndex) { 2006 if (!isValidSlotIndex(slotIndex)) { 2007 logd("[getSubId]- fail"); 2008 return null; 2009 } 2010 2011 int[] subId = null; 2012 2013 try { 2014 ISub iSub = TelephonyManager.getSubscriptionService(); 2015 if (iSub != null) { 2016 subId = iSub.getSubId(slotIndex); 2017 } 2018 } catch (RemoteException ex) { 2019 // ignore it 2020 } 2021 2022 return subId; 2023 } 2024 2025 /** @hide */ 2026 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) getPhoneId(int subId)2027 public static int getPhoneId(int subId) { 2028 return sPhoneIdCache.query(subId); 2029 } 2030 logd(String msg)2031 private static void logd(String msg) { 2032 Rlog.d(LOG_TAG, msg); 2033 } 2034 loge(String msg)2035 private static void loge(String msg) { 2036 Rlog.e(LOG_TAG, msg); 2037 } 2038 2039 /** 2040 * Returns the system's default subscription id. 2041 * 2042 * For a voice capable device, it will return getDefaultVoiceSubscriptionId. 2043 * For a data only device, it will return the getDefaultDataSubscriptionId. 2044 * May return an INVALID_SUBSCRIPTION_ID on error. 2045 * 2046 * @return the "system" default subscription id. 2047 */ getDefaultSubscriptionId()2048 public static int getDefaultSubscriptionId() { 2049 return sDefaultSubIdCache.query(null); 2050 } 2051 2052 /** 2053 * Returns the system's default voice subscription id. 2054 * 2055 * On a data only device or on error, will return INVALID_SUBSCRIPTION_ID. 2056 * 2057 * @return the default voice subscription Id. 2058 */ getDefaultVoiceSubscriptionId()2059 public static int getDefaultVoiceSubscriptionId() { 2060 int subId = INVALID_SUBSCRIPTION_ID; 2061 2062 try { 2063 ISub iSub = TelephonyManager.getSubscriptionService(); 2064 if (iSub != null) { 2065 subId = iSub.getDefaultVoiceSubId(); 2066 } 2067 } catch (RemoteException ex) { 2068 // ignore it 2069 } 2070 2071 if (VDBG) logd("getDefaultVoiceSubscriptionId, sub id = " + subId); 2072 return subId; 2073 } 2074 2075 /** 2076 * Sets the system's default voice subscription id. 2077 * 2078 * On a data-only device, this is a no-op. 2079 * 2080 * May throw a {@link RuntimeException} if the provided subscription id is equal to 2081 * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} 2082 * 2083 * @param subscriptionId A valid subscription ID to set as the system default, or 2084 * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} 2085 * @hide 2086 */ 2087 @SystemApi 2088 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDefaultVoiceSubscriptionId(int subscriptionId)2089 public void setDefaultVoiceSubscriptionId(int subscriptionId) { 2090 if (VDBG) logd("setDefaultVoiceSubId sub id = " + subscriptionId); 2091 try { 2092 ISub iSub = TelephonyManager.getSubscriptionService(); 2093 if (iSub != null) { 2094 iSub.setDefaultVoiceSubId(subscriptionId); 2095 } 2096 } catch (RemoteException ex) { 2097 // ignore it 2098 } 2099 } 2100 2101 /** 2102 * Same as {@link #setDefaultVoiceSubscriptionId(int)}, but preserved for backwards 2103 * compatibility. 2104 * @hide 2105 */ setDefaultVoiceSubId(int subId)2106 public void setDefaultVoiceSubId(int subId) { 2107 setDefaultVoiceSubscriptionId(subId); 2108 } 2109 2110 /** 2111 * Return the SubscriptionInfo for default voice subscription. 2112 * 2113 * Will return null on data only devices, or on error. 2114 * 2115 * @return the SubscriptionInfo for the default voice subscription. 2116 * @hide 2117 */ 2118 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getDefaultVoiceSubscriptionInfo()2119 public SubscriptionInfo getDefaultVoiceSubscriptionInfo() { 2120 return getActiveSubscriptionInfo(getDefaultVoiceSubscriptionId()); 2121 } 2122 2123 /** @hide */ 2124 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getDefaultVoicePhoneId()2125 public static int getDefaultVoicePhoneId() { 2126 return getPhoneId(getDefaultVoiceSubscriptionId()); 2127 } 2128 2129 /** 2130 * Returns the system's default SMS subscription id. 2131 * 2132 * On a data only device or on error, will return INVALID_SUBSCRIPTION_ID. 2133 * 2134 * @return the default SMS subscription Id. 2135 */ getDefaultSmsSubscriptionId()2136 public static int getDefaultSmsSubscriptionId() { 2137 return sDefaultSmsSubIdCache.query(null); 2138 } 2139 2140 /** 2141 * Set the subscription which will be used by default for SMS, with the subscription which 2142 * the supplied subscription ID corresponds to; or throw a RuntimeException if the supplied 2143 * subscription ID is not usable (check with {@link #isUsableSubscriptionId(int)}). 2144 * 2145 * @param subscriptionId the supplied subscription ID 2146 * 2147 * @hide 2148 */ 2149 @SystemApi 2150 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) setDefaultSmsSubId(int subscriptionId)2151 public void setDefaultSmsSubId(int subscriptionId) { 2152 if (VDBG) logd("setDefaultSmsSubId sub id = " + subscriptionId); 2153 try { 2154 ISub iSub = TelephonyManager.getSubscriptionService(); 2155 if (iSub != null) { 2156 iSub.setDefaultSmsSubId(subscriptionId); 2157 } 2158 } catch (RemoteException ex) { 2159 ex.rethrowFromSystemServer(); 2160 } 2161 } 2162 2163 /** 2164 * Return the SubscriptionInfo for default voice subscription. 2165 * 2166 * Will return null on data only devices, or on error. 2167 * 2168 * @return the SubscriptionInfo for the default SMS subscription. 2169 * @hide 2170 */ getDefaultSmsSubscriptionInfo()2171 public SubscriptionInfo getDefaultSmsSubscriptionInfo() { 2172 return getActiveSubscriptionInfo(getDefaultSmsSubscriptionId()); 2173 } 2174 2175 /** @hide */ 2176 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getDefaultSmsPhoneId()2177 public int getDefaultSmsPhoneId() { 2178 return getPhoneId(getDefaultSmsSubscriptionId()); 2179 } 2180 2181 /** 2182 * Returns the system's default data subscription id. 2183 * 2184 * On a voice only device or on error, will return INVALID_SUBSCRIPTION_ID. 2185 * 2186 * @return the default data subscription Id. 2187 */ getDefaultDataSubscriptionId()2188 public static int getDefaultDataSubscriptionId() { 2189 return sDefaultDataSubIdCache.query(null); 2190 } 2191 2192 /** 2193 * Set the subscription which will be used by default for data, with the subscription which 2194 * the supplied subscription ID corresponds to; or throw a RuntimeException if the supplied 2195 * subscription ID is not usable (check with {@link #isUsableSubscriptionId(int)}). 2196 * 2197 * @param subscriptionId the supplied subscription ID 2198 * 2199 * @hide 2200 */ 2201 @SystemApi 2202 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) setDefaultDataSubId(int subscriptionId)2203 public void setDefaultDataSubId(int subscriptionId) { 2204 if (VDBG) logd("setDataSubscription sub id = " + subscriptionId); 2205 try { 2206 ISub iSub = TelephonyManager.getSubscriptionService(); 2207 if (iSub != null) { 2208 iSub.setDefaultDataSubId(subscriptionId); 2209 } 2210 } catch (RemoteException ex) { 2211 // ignore it 2212 } 2213 } 2214 2215 /** 2216 * Return the SubscriptionInfo for default data subscription. 2217 * 2218 * Will return null on voice only devices, or on error. 2219 * 2220 * @return the SubscriptionInfo for the default data subscription. 2221 * @hide 2222 */ 2223 @UnsupportedAppUsage getDefaultDataSubscriptionInfo()2224 public SubscriptionInfo getDefaultDataSubscriptionInfo() { 2225 return getActiveSubscriptionInfo(getDefaultDataSubscriptionId()); 2226 } 2227 2228 /** @hide */ 2229 @UnsupportedAppUsage getDefaultDataPhoneId()2230 public int getDefaultDataPhoneId() { 2231 return getPhoneId(getDefaultDataSubscriptionId()); 2232 } 2233 2234 /** @hide */ clearSubscriptionInfo()2235 public void clearSubscriptionInfo() { 2236 try { 2237 ISub iSub = TelephonyManager.getSubscriptionService(); 2238 if (iSub != null) { 2239 iSub.clearSubInfo(); 2240 } 2241 } catch (RemoteException ex) { 2242 // ignore it 2243 } 2244 2245 return; 2246 } 2247 2248 //FIXME this is vulnerable to race conditions 2249 /** @hide */ allDefaultsSelected()2250 public boolean allDefaultsSelected() { 2251 if (!isValidSubscriptionId(getDefaultDataSubscriptionId())) { 2252 return false; 2253 } 2254 if (!isValidSubscriptionId(getDefaultSmsSubscriptionId())) { 2255 return false; 2256 } 2257 if (!isValidSubscriptionId(getDefaultVoiceSubscriptionId())) { 2258 return false; 2259 } 2260 return true; 2261 } 2262 2263 /** 2264 * Check if the supplied subscription ID is valid. 2265 * 2266 * <p>A valid subscription ID is not necessarily an active subscription ID 2267 * (see {@link #isActiveSubscriptionId(int)}) or an usable subscription ID 2268 * (see {@link #isUsableSubscriptionId(int)}). Unless specifically noted, subscription 2269 * APIs work with a valid subscription ID. 2270 * 2271 * @param subscriptionId The subscription ID. 2272 * @return {@code true} if the supplied subscriptionId is valid; {@code false} otherwise. 2273 */ isValidSubscriptionId(int subscriptionId)2274 public static boolean isValidSubscriptionId(int subscriptionId) { 2275 return subscriptionId > INVALID_SUBSCRIPTION_ID; 2276 } 2277 2278 /** 2279 * Check if the supplied subscription ID is usable. 2280 * 2281 * <p>A usable subscription ID is a valid subscription ID, but not necessarily an active 2282 * subscription ID (see {@link #isActiveSubscriptionId(int)}). Some subscription APIs 2283 * require a usable subscription ID, and this is noted in their documentation; otherwise, a 2284 * subscription ID does not need to be usable for subscription functions, only valid. 2285 * 2286 * @param subscriptionId the subscription ID 2287 * @return {@code true} if the subscription ID is usable; {@code false} otherwise. 2288 */ isUsableSubscriptionId(int subscriptionId)2289 public static boolean isUsableSubscriptionId(int subscriptionId) { 2290 return isUsableSubIdValue(subscriptionId); 2291 } 2292 2293 /** 2294 * @return true if subId is an usable subId value else false. A 2295 * usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAULT_SUB_ID. 2296 * @hide 2297 */ 2298 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) isUsableSubIdValue(int subId)2299 public static boolean isUsableSubIdValue(int subId) { 2300 return subId >= MIN_SUBSCRIPTION_ID_VALUE && subId <= MAX_SUBSCRIPTION_ID_VALUE; 2301 } 2302 2303 /** @hide */ 2304 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) isValidSlotIndex(int slotIndex)2305 public static boolean isValidSlotIndex(int slotIndex) { 2306 return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getActiveModemCount(); 2307 } 2308 2309 /** @hide */ 2310 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isValidPhoneId(int phoneId)2311 public static boolean isValidPhoneId(int phoneId) { 2312 return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getActiveModemCount(); 2313 } 2314 2315 /** @hide */ 2316 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) putPhoneIdAndSubIdExtra(Intent intent, int phoneId)2317 public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) { 2318 int[] subIds = SubscriptionManager.getSubId(phoneId); 2319 if (subIds != null && subIds.length > 0) { 2320 putPhoneIdAndSubIdExtra(intent, phoneId, subIds[0]); 2321 } else { 2322 logd("putPhoneIdAndSubIdExtra: no valid subs"); 2323 intent.putExtra(PhoneConstants.PHONE_KEY, phoneId); 2324 intent.putExtra(EXTRA_SLOT_INDEX, phoneId); 2325 } 2326 } 2327 2328 /** @hide */ 2329 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId)2330 public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) { 2331 if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId); 2332 intent.putExtra(EXTRA_SLOT_INDEX, phoneId); 2333 intent.putExtra(PhoneConstants.PHONE_KEY, phoneId); 2334 putSubscriptionIdExtra(intent, subId); 2335 } 2336 2337 /** 2338 * Get visible subscription Id(s) of the currently active SIM(s). 2339 * 2340 * @return the list of subId's that are active, 2341 * is never null but the length may be 0. 2342 * @hide 2343 */ 2344 @SystemApi 2345 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getActiveSubscriptionIdList()2346 public @NonNull int[] getActiveSubscriptionIdList() { 2347 return getActiveSubscriptionIdList(/* visibleOnly */ true); 2348 } 2349 2350 /** 2351 * Get both hidden and visible subscription Id(s) of the currently active SIM(s). 2352 * 2353 * Hidden subscriptions refer to those are not meant visible to the users. 2354 * For example, an opportunistic subscription that is grouped with other 2355 * subscriptions should remain invisible to users as they are only functionally 2356 * supplementary to primary ones. 2357 * 2358 * @return the list of subId's that are active, 2359 * is never null but the length may be 0. 2360 * @hide 2361 */ 2362 @SystemApi 2363 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getCompleteActiveSubscriptionIdList()2364 public @NonNull int[] getCompleteActiveSubscriptionIdList() { 2365 return getActiveSubscriptionIdList(/* visibleOnly */false); 2366 } 2367 2368 /** 2369 * @return a non-null list of subId's that are active. 2370 * 2371 * @hide 2372 */ getActiveSubscriptionIdList(boolean visibleOnly)2373 public @NonNull int[] getActiveSubscriptionIdList(boolean visibleOnly) { 2374 try { 2375 ISub iSub = TelephonyManager.getSubscriptionService(); 2376 if (iSub != null) { 2377 int[] subId = iSub.getActiveSubIdList(visibleOnly); 2378 if (subId != null) return subId; 2379 } 2380 } catch (RemoteException ex) { 2381 // ignore it 2382 } 2383 2384 return new int[0]; 2385 } 2386 2387 /** 2388 * Returns true if the device is considered roaming on the current 2389 * network for a subscription. 2390 * <p> 2391 * Availability: Only when user registered to a network. 2392 * 2393 * @param subId The subscription ID 2394 * @return true if the network for the subscription is roaming, false otherwise 2395 */ isNetworkRoaming(int subId)2396 public boolean isNetworkRoaming(int subId) { 2397 final int phoneId = getPhoneId(subId); 2398 if (phoneId < 0) { 2399 // What else can we do? 2400 return false; 2401 } 2402 return TelephonyManager.getDefault().isNetworkRoaming(subId); 2403 } 2404 2405 /** 2406 * Returns a constant indicating the state of sim for the slot index. 2407 * 2408 * @param slotIndex 2409 * 2410 * {@See TelephonyManager#SIM_STATE_UNKNOWN} 2411 * {@See TelephonyManager#SIM_STATE_ABSENT} 2412 * {@See TelephonyManager#SIM_STATE_PIN_REQUIRED} 2413 * {@See TelephonyManager#SIM_STATE_PUK_REQUIRED} 2414 * {@See TelephonyManager#SIM_STATE_NETWORK_LOCKED} 2415 * {@See TelephonyManager#SIM_STATE_READY} 2416 * {@See TelephonyManager#SIM_STATE_NOT_READY} 2417 * {@See TelephonyManager#SIM_STATE_PERM_DISABLED} 2418 * {@See TelephonyManager#SIM_STATE_CARD_IO_ERROR} 2419 * 2420 * {@hide} 2421 */ getSimStateForSlotIndex(int slotIndex)2422 public static int getSimStateForSlotIndex(int slotIndex) { 2423 int simState = TelephonyManager.SIM_STATE_UNKNOWN; 2424 2425 try { 2426 ISub iSub = TelephonyManager.getSubscriptionService(); 2427 if (iSub != null) { 2428 simState = iSub.getSimStateForSlotIndex(slotIndex); 2429 } 2430 } catch (RemoteException ex) { 2431 } 2432 2433 return simState; 2434 } 2435 2436 /** 2437 * Store properties associated with SubscriptionInfo in database 2438 * @param subId Subscription Id of Subscription 2439 * @param propKey Column name in database associated with SubscriptionInfo 2440 * @param propValue Value to store in DB for particular subId & column name 2441 * @hide 2442 */ setSubscriptionProperty(int subId, String propKey, String propValue)2443 public static void setSubscriptionProperty(int subId, String propKey, String propValue) { 2444 try { 2445 ISub iSub = TelephonyManager.getSubscriptionService(); 2446 if (iSub != null) { 2447 iSub.setSubscriptionProperty(subId, propKey, propValue); 2448 } 2449 } catch (RemoteException ex) { 2450 // ignore it 2451 } 2452 } 2453 2454 /** 2455 * Serialize list of contacts uri to string 2456 * @hide 2457 */ serializeUriLists(List<Uri> uris)2458 public static String serializeUriLists(List<Uri> uris) { 2459 List<String> contacts = new ArrayList<>(); 2460 for (Uri uri : uris) { 2461 contacts.add(uri.toString()); 2462 } 2463 try { 2464 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 2465 ObjectOutputStream oos = new ObjectOutputStream(bos); 2466 oos.writeObject(contacts); 2467 oos.flush(); 2468 return Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT); 2469 } catch (IOException e) { 2470 logd("serializeUriLists IO exception"); 2471 } 2472 return ""; 2473 } 2474 2475 /** 2476 * Return list of contacts uri corresponding to query result. 2477 * @param subId Subscription Id of Subscription 2478 * @param propKey Column name in SubscriptionInfo database 2479 * @return list of contacts uri to be returned 2480 * @hide 2481 */ getContactsFromSubscriptionProperty(int subId, String propKey, Context context)2482 private static List<Uri> getContactsFromSubscriptionProperty(int subId, String propKey, 2483 Context context) { 2484 String result = getSubscriptionProperty(subId, propKey, context); 2485 if (result != null) { 2486 try { 2487 byte[] b = Base64.decode(result, Base64.DEFAULT); 2488 ByteArrayInputStream bis = new ByteArrayInputStream(b); 2489 ObjectInputStream ois = new ObjectInputStream(bis); 2490 List<String> contacts = ArrayList.class.cast(ois.readObject()); 2491 List<Uri> uris = new ArrayList<>(); 2492 for (String contact : contacts) { 2493 uris.add(Uri.parse(contact)); 2494 } 2495 return uris; 2496 } catch (IOException e) { 2497 logd("getContactsFromSubscriptionProperty IO exception"); 2498 } catch (ClassNotFoundException e) { 2499 logd("getContactsFromSubscriptionProperty ClassNotFound exception"); 2500 } 2501 } 2502 return new ArrayList<>(); 2503 } 2504 2505 /** 2506 * Store properties associated with SubscriptionInfo in database 2507 * @param subId Subscription Id of Subscription 2508 * @param propKey Column name in SubscriptionInfo database 2509 * @return Value associated with subId and propKey column in database 2510 * @hide 2511 */ getSubscriptionProperty(int subId, String propKey, Context context)2512 private static String getSubscriptionProperty(int subId, String propKey, 2513 Context context) { 2514 String resultValue = null; 2515 try { 2516 ISub iSub = TelephonyManager.getSubscriptionService(); 2517 if (iSub != null) { 2518 resultValue = iSub.getSubscriptionProperty(subId, propKey, 2519 context.getOpPackageName(), context.getAttributionTag()); 2520 } 2521 } catch (RemoteException ex) { 2522 // ignore it 2523 } 2524 return resultValue; 2525 } 2526 2527 /** 2528 * Returns boolean value corresponding to query result. 2529 * @param subId Subscription Id of Subscription 2530 * @param propKey Column name in SubscriptionInfo database 2531 * @param defValue Default boolean value to be returned 2532 * @return boolean result value to be returned 2533 * @hide 2534 */ getBooleanSubscriptionProperty(int subId, String propKey, boolean defValue, Context context)2535 public static boolean getBooleanSubscriptionProperty(int subId, String propKey, 2536 boolean defValue, Context context) { 2537 String result = getSubscriptionProperty(subId, propKey, context); 2538 if (result != null) { 2539 try { 2540 return Integer.parseInt(result) == 1; 2541 } catch (NumberFormatException err) { 2542 logd("getBooleanSubscriptionProperty NumberFormat exception"); 2543 } 2544 } 2545 return defValue; 2546 } 2547 2548 /** 2549 * Returns integer value corresponding to query result. 2550 * @param subId Subscription Id of Subscription 2551 * @param propKey Column name in SubscriptionInfo database 2552 * @param defValue Default integer value to be returned 2553 * @return integer result value to be returned 2554 * @hide 2555 */ getIntegerSubscriptionProperty(int subId, String propKey, int defValue, Context context)2556 public static int getIntegerSubscriptionProperty(int subId, String propKey, int defValue, 2557 Context context) { 2558 String result = getSubscriptionProperty(subId, propKey, context); 2559 if (result != null) { 2560 try { 2561 return Integer.parseInt(result); 2562 } catch (NumberFormatException err) { 2563 logd("getIntegerSubscriptionProperty NumberFormat exception"); 2564 } 2565 } 2566 return defValue; 2567 } 2568 2569 /** 2570 * Returns long value corresponding to query result. 2571 * @param subId Subscription Id of Subscription 2572 * @param propKey Column name in SubscriptionInfo database 2573 * @param defValue Default long value to be returned 2574 * @return long result value to be returned 2575 * @hide 2576 */ getLongSubscriptionProperty(int subId, String propKey, long defValue, Context context)2577 public static long getLongSubscriptionProperty(int subId, String propKey, long defValue, 2578 Context context) { 2579 String result = getSubscriptionProperty(subId, propKey, context); 2580 if (result != null) { 2581 try { 2582 return Long.parseLong(result); 2583 } catch (NumberFormatException err) { 2584 logd("getLongSubscriptionProperty NumberFormat exception"); 2585 } 2586 } 2587 return defValue; 2588 } 2589 2590 /** 2591 * Returns the {@link Resources} from the given {@link Context} for the MCC/MNC associated with 2592 * the subscription. If the subscription ID is invalid, the base resources are returned instead. 2593 * 2594 * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 2595 * 2596 * @param context Context object 2597 * @param subId Subscription Id of Subscription whose resources are required 2598 * @return Resources associated with Subscription. 2599 * @hide 2600 */ 2601 @NonNull 2602 @SystemApi getResourcesForSubId(@onNull Context context, int subId)2603 public static Resources getResourcesForSubId(@NonNull Context context, int subId) { 2604 return getResourcesForSubId(context, subId, false); 2605 } 2606 2607 /** 2608 * Returns the resources associated with Subscription. 2609 * @param context Context object 2610 * @param subId Subscription Id of Subscription who's resources are required 2611 * @param useRootLocale if root locale should be used. Localized locale is used if false. 2612 * @return Resources associated with Subscription. 2613 * @hide 2614 */ 2615 @NonNull getResourcesForSubId(Context context, int subId, boolean useRootLocale)2616 public static Resources getResourcesForSubId(Context context, int subId, 2617 boolean useRootLocale) { 2618 // Check if resources for this context and subId already exist in the resource cache. 2619 // Resources that use the root locale are not cached. 2620 Pair<Context, Integer> cacheKey = null; 2621 if (isValidSubscriptionId(subId) && !useRootLocale) { 2622 cacheKey = Pair.create(context, subId); 2623 if (sResourcesCache.containsKey(cacheKey)) { 2624 // Cache hit. Use cached Resources. 2625 return sResourcesCache.get(cacheKey); 2626 } 2627 } 2628 2629 final SubscriptionInfo subInfo = 2630 SubscriptionManager.from(context).getActiveSubscriptionInfo(subId); 2631 2632 Configuration overrideConfig = new Configuration(); 2633 if (subInfo != null) { 2634 overrideConfig.mcc = subInfo.getMcc(); 2635 overrideConfig.mnc = subInfo.getMnc(); 2636 if (overrideConfig.mnc == 0) { 2637 overrideConfig.mnc = Configuration.MNC_ZERO; 2638 cacheKey = null; 2639 } 2640 } 2641 2642 if (useRootLocale) { 2643 overrideConfig.setLocale(Locale.ROOT); 2644 } 2645 2646 // Create new context with new configuration so that we can avoid modifying the passed in 2647 // context. 2648 // Note that if the original context configuration changes, the resources here will also 2649 // change for all values except those overridden by newConfig (e.g. if the device has an 2650 // orientation change). 2651 Context newContext = context.createConfigurationContext(overrideConfig); 2652 Resources res = newContext.getResources(); 2653 2654 if (cacheKey != null) { 2655 // Save the newly created Resources in the resource cache. 2656 sResourcesCache.put(cacheKey, res); 2657 } 2658 return res; 2659 } 2660 2661 /** 2662 * Checks if the supplied subscription ID corresponds to a subscription which is actively in 2663 * use on the device. An active subscription ID is a valid and usable subscription ID. 2664 * 2665 * @param subscriptionId the subscription ID. 2666 * @return {@code true} if the supplied subscription ID corresponds to an active subscription; 2667 * {@code false} if it does not correspond to an active subscription; or throw a 2668 * SecurityException if the caller hasn't got the right permission. 2669 */ 2670 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) isActiveSubscriptionId(int subscriptionId)2671 public boolean isActiveSubscriptionId(int subscriptionId) { 2672 return isActiveSubId(subscriptionId); 2673 } 2674 2675 /** 2676 * @return true if the sub ID is active. i.e. The sub ID corresponds to a known subscription 2677 * and the SIM providing the subscription is present in a slot and in "LOADED" state. 2678 * @hide 2679 */ 2680 @UnsupportedAppUsage isActiveSubId(int subId)2681 public boolean isActiveSubId(int subId) { 2682 try { 2683 ISub iSub = TelephonyManager.getSubscriptionService(); 2684 if (iSub != null) { 2685 return iSub.isActiveSubId(subId, mContext.getOpPackageName(), 2686 mContext.getAttributionTag()); 2687 } 2688 } catch (RemoteException ex) { 2689 } 2690 return false; 2691 } 2692 2693 /** 2694 * Get the description of the billing relationship plan between a carrier 2695 * and a specific subscriber. 2696 * <p> 2697 * This method is only accessible to the following narrow set of apps: 2698 * <ul> 2699 * <li>The carrier app for this subscriberId, as determined by 2700 * {@link TelephonyManager#hasCarrierPrivileges()}. 2701 * <li>The carrier app explicitly delegated access through 2702 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 2703 * </ul> 2704 * 2705 * @param subId the subscriber this relationship applies to 2706 * @throws SecurityException if the caller doesn't meet the requirements 2707 * outlined above. 2708 */ getSubscriptionPlans(int subId)2709 public @NonNull List<SubscriptionPlan> getSubscriptionPlans(int subId) { 2710 SubscriptionPlan[] subscriptionPlans = 2711 getNetworkPolicyManager().getSubscriptionPlans(subId, mContext.getOpPackageName()); 2712 return subscriptionPlans == null 2713 ? Collections.emptyList() : Arrays.asList(subscriptionPlans); 2714 } 2715 2716 /** 2717 * Set the description of the billing relationship plan between a carrier 2718 * and a specific subscriber. 2719 * <p> 2720 * This method is only accessible to the following narrow set of apps: 2721 * <ul> 2722 * <li>The carrier app for this subscriberId, as determined by 2723 * {@link TelephonyManager#hasCarrierPrivileges()}. 2724 * <li>The carrier app explicitly delegated access through 2725 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 2726 * </ul> 2727 * 2728 * @param subId the subscriber this relationship applies to. An empty list 2729 * may be sent to clear any existing plans. 2730 * @param plans the list of plans. The first plan is always the primary and 2731 * most important plan. Any additional plans are secondary and 2732 * may not be displayed or used by decision making logic. 2733 * @throws SecurityException if the caller doesn't meet the requirements 2734 * outlined above. 2735 * @throws IllegalArgumentException if plans don't meet the requirements 2736 * defined in {@link SubscriptionPlan}. 2737 */ setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans)2738 public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) { 2739 getNetworkPolicyManager().setSubscriptionPlans(subId, 2740 plans.toArray(new SubscriptionPlan[plans.size()]), mContext.getOpPackageName()); 2741 } 2742 2743 /** 2744 * Temporarily override the billing relationship plan between a carrier and 2745 * a specific subscriber to be considered unmetered. This will be reflected 2746 * to apps via {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED}. 2747 * <p> 2748 * This method is only accessible to the following narrow set of apps: 2749 * <ul> 2750 * <li>The carrier app for this subscriberId, as determined by 2751 * {@link TelephonyManager#hasCarrierPrivileges()}. 2752 * <li>The carrier app explicitly delegated access through 2753 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 2754 * </ul> 2755 * 2756 * @param subId the subscriber this override applies to. 2757 * @param overrideUnmetered set if the billing relationship should be 2758 * considered unmetered. 2759 * @param timeoutMillis the timeout after which the requested override will 2760 * be automatically cleared, or {@code 0} to leave in the 2761 * requested state until explicitly cleared, or the next reboot, 2762 * whichever happens first. 2763 * @throws SecurityException if the caller doesn't meet the requirements 2764 * outlined above. 2765 */ setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered, @DurationMillisLong long timeoutMillis)2766 public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered, 2767 @DurationMillisLong long timeoutMillis) { 2768 setSubscriptionOverrideUnmetered(subId, overrideUnmetered, 2769 TelephonyManager.getAllNetworkTypes(), timeoutMillis); 2770 } 2771 2772 /** 2773 * Temporarily override the billing relationship plan between a carrier and 2774 * a specific subscriber to be considered unmetered. This will be reflected 2775 * to apps via {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED}. 2776 * <p> 2777 * This method is only accessible to the following narrow set of apps: 2778 * <ul> 2779 * <li>The carrier app for this subscriberId, as determined by 2780 * {@link TelephonyManager#hasCarrierPrivileges()}. 2781 * <li>The carrier app explicitly delegated access through 2782 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 2783 * </ul> 2784 * 2785 * @param subId the subscriber this override applies to. 2786 * @param overrideUnmetered set if the billing relationship should be 2787 * considered unmetered. 2788 * @param networkTypes the network types this override applies to. If no 2789 * network types are specified, override values will be ignored. 2790 * {@see TelephonyManager#getAllNetworkTypes()} 2791 * @param timeoutMillis the timeout after which the requested override will 2792 * be automatically cleared, or {@code 0} to leave in the 2793 * requested state until explicitly cleared, or the next reboot, 2794 * whichever happens first. 2795 * @throws SecurityException if the caller doesn't meet the requirements 2796 * outlined above. 2797 */ setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered, @NonNull @Annotation.NetworkType int[] networkTypes, @DurationMillisLong long timeoutMillis)2798 public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered, 2799 @NonNull @Annotation.NetworkType int[] networkTypes, 2800 @DurationMillisLong long timeoutMillis) { 2801 final int overrideValue = overrideUnmetered ? SUBSCRIPTION_OVERRIDE_UNMETERED : 0; 2802 getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_UNMETERED, 2803 overrideValue, networkTypes, timeoutMillis, mContext.getOpPackageName()); 2804 } 2805 2806 /** 2807 * Temporarily override the billing relationship plan between a carrier and 2808 * a specific subscriber to be considered congested. This will cause the 2809 * device to delay certain network requests when possible, such as developer 2810 * jobs that are willing to run in a flexible time window. 2811 * <p> 2812 * This method is only accessible to the following narrow set of apps: 2813 * <ul> 2814 * <li>The carrier app for this subscriberId, as determined by 2815 * {@link TelephonyManager#hasCarrierPrivileges()}. 2816 * <li>The carrier app explicitly delegated access through 2817 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 2818 * </ul> 2819 * 2820 * @param subId the subscriber this override applies to. 2821 * @param overrideCongested set if the subscription should be considered 2822 * congested. 2823 * @param timeoutMillis the timeout after which the requested override will 2824 * be automatically cleared, or {@code 0} to leave in the 2825 * requested state until explicitly cleared, or the next reboot, 2826 * whichever happens first. 2827 * @throws SecurityException if the caller doesn't meet the requirements 2828 * outlined above. 2829 */ setSubscriptionOverrideCongested(int subId, boolean overrideCongested, @DurationMillisLong long timeoutMillis)2830 public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested, 2831 @DurationMillisLong long timeoutMillis) { 2832 setSubscriptionOverrideCongested(subId, overrideCongested, 2833 TelephonyManager.getAllNetworkTypes(), timeoutMillis); 2834 } 2835 2836 /** 2837 * Temporarily override the billing relationship plan between a carrier and 2838 * a specific subscriber to be considered congested. This will cause the 2839 * device to delay certain network requests when possible, such as developer 2840 * jobs that are willing to run in a flexible time window. 2841 * <p> 2842 * This method is only accessible to the following narrow set of apps: 2843 * <ul> 2844 * <li>The carrier app for this subscriberId, as determined by 2845 * {@link TelephonyManager#hasCarrierPrivileges()}. 2846 * <li>The carrier app explicitly delegated access through 2847 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 2848 * </ul> 2849 * 2850 * @param subId the subscriber this override applies to. 2851 * @param overrideCongested set if the subscription should be considered 2852 * congested. 2853 * @param networkTypes the network types this override applies to. If no 2854 * network types are specified, override values will be ignored. 2855 * {@see TelephonyManager#getAllNetworkTypes()} 2856 * @param timeoutMillis the timeout after which the requested override will 2857 * be automatically cleared, or {@code 0} to leave in the 2858 * requested state until explicitly cleared, or the next reboot, 2859 * whichever happens first. 2860 * @throws SecurityException if the caller doesn't meet the requirements 2861 * outlined above. 2862 */ setSubscriptionOverrideCongested(int subId, boolean overrideCongested, @NonNull @Annotation.NetworkType int[] networkTypes, @DurationMillisLong long timeoutMillis)2863 public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested, 2864 @NonNull @Annotation.NetworkType int[] networkTypes, 2865 @DurationMillisLong long timeoutMillis) { 2866 final int overrideValue = overrideCongested ? SUBSCRIPTION_OVERRIDE_CONGESTED : 0; 2867 getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_CONGESTED, 2868 overrideValue, networkTypes, timeoutMillis, mContext.getOpPackageName()); 2869 } 2870 2871 /** 2872 * Checks whether the app with the given context is authorized to manage the given subscription 2873 * according to its metadata. 2874 * 2875 * Only supported for embedded subscriptions (if {@link SubscriptionInfo#isEmbedded} returns 2876 * true). To check for permissions for non-embedded subscription as well, 2877 * {@see android.telephony.TelephonyManager#hasCarrierPrivileges}. 2878 * 2879 * @param info The subscription to check. 2880 * @return whether the app is authorized to manage this subscription per its metadata. 2881 */ canManageSubscription(SubscriptionInfo info)2882 public boolean canManageSubscription(SubscriptionInfo info) { 2883 return canManageSubscription(info, mContext.getPackageName()); 2884 } 2885 2886 /** 2887 * Checks whether the given app is authorized to manage the given subscription. An app can only 2888 * be authorized if it is included in the {@link android.telephony.UiccAccessRule} of the 2889 * {@link android.telephony.SubscriptionInfo} with the access status. 2890 * 2891 * Only supported for embedded subscriptions (if {@link SubscriptionInfo#isEmbedded} returns 2892 * true). To check for permissions for non-embedded subscription as well, 2893 * {@see android.telephony.TelephonyManager#hasCarrierPrivileges}. 2894 * 2895 * @param info The subscription to check. 2896 * @param packageName Package name of the app to check. 2897 * @return whether the app is authorized to manage this subscription per its access rules. 2898 * @hide 2899 */ 2900 @SystemApi canManageSubscription(@onNull SubscriptionInfo info, @NonNull String packageName)2901 public boolean canManageSubscription(@NonNull SubscriptionInfo info, 2902 @NonNull String packageName) { 2903 if (info == null || info.getAllAccessRules() == null || packageName == null) { 2904 return false; 2905 } 2906 PackageManager packageManager = mContext.getPackageManager(); 2907 PackageInfo packageInfo; 2908 try { 2909 packageInfo = packageManager.getPackageInfo(packageName, 2910 PackageManager.GET_SIGNING_CERTIFICATES); 2911 } catch (PackageManager.NameNotFoundException e) { 2912 logd("Unknown package: " + packageName); 2913 return false; 2914 } 2915 for (UiccAccessRule rule : info.getAllAccessRules()) { 2916 if (rule.getCarrierPrivilegeStatus(packageInfo) 2917 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 2918 return true; 2919 } 2920 } 2921 return false; 2922 } 2923 2924 /** 2925 * Set which subscription is preferred for cellular data. 2926 * It's also usually the subscription we set up internet connection on. 2927 * 2928 * PreferredData overwrites user setting of default data subscription. And it's used 2929 * by AlternativeNetworkService or carrier apps to switch primary and CBRS 2930 * subscription dynamically in multi-SIM devices. 2931 * 2932 * @param subId which subscription is preferred to for cellular data. If it's 2933 * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}, it means 2934 * it's unset and {@link SubscriptionManager#getDefaultDataSubscriptionId()} 2935 * is used to determine which modem is preferred. 2936 * @param needValidation whether Telephony will wait until the network is validated by 2937 * connectivity service before switching data to it. More details see 2938 * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}. 2939 * @param executor The executor of where the callback will execute. 2940 * @param callback Callback will be triggered once it succeeds or failed. 2941 * Pass null if don't care about the result. 2942 * 2943 * @hide 2944 * 2945 */ 2946 @SystemApi 2947 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) setPreferredDataSubscriptionId(int subId, boolean needValidation, @Nullable @CallbackExecutor Executor executor, @Nullable @TelephonyManager.SetOpportunisticSubscriptionResult Consumer<Integer> callback)2948 public void setPreferredDataSubscriptionId(int subId, boolean needValidation, 2949 @Nullable @CallbackExecutor Executor executor, @Nullable 2950 @TelephonyManager.SetOpportunisticSubscriptionResult Consumer<Integer> callback) { 2951 if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId); 2952 try { 2953 ISub iSub = TelephonyManager.getSubscriptionService(); 2954 if (iSub == null) return; 2955 2956 ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() { 2957 @Override 2958 public void onComplete(int result) { 2959 if (executor == null || callback == null) { 2960 return; 2961 } 2962 final long identity = Binder.clearCallingIdentity(); 2963 try { 2964 executor.execute(() -> { 2965 callback.accept(result); 2966 }); 2967 } finally { 2968 Binder.restoreCallingIdentity(identity); 2969 } 2970 } 2971 }; 2972 iSub.setPreferredDataSubscriptionId(subId, needValidation, callbackStub); 2973 } catch (RemoteException ex) { 2974 // ignore it 2975 } 2976 } 2977 2978 /** 2979 * Get which subscription is preferred for cellular data. 2980 * It's also usually the subscription we set up internet connection on. 2981 * 2982 * PreferredData overwrites user setting of default data subscription. And it's used 2983 * by AlternativeNetworkService or carrier apps to switch primary and CBRS 2984 * subscription dynamically in multi-SIM devices. 2985 * 2986 * @return preferred subscription id for cellular data. {@link DEFAULT_SUBSCRIPTION_ID} if 2987 * there's no prefered subscription. 2988 * 2989 * @hide 2990 * 2991 */ 2992 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getPreferredDataSubscriptionId()2993 public int getPreferredDataSubscriptionId() { 2994 int preferredSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 2995 try { 2996 ISub iSub = TelephonyManager.getSubscriptionService(); 2997 if (iSub != null) { 2998 preferredSubId = iSub.getPreferredDataSubscriptionId(); 2999 } 3000 } catch (RemoteException ex) { 3001 // ignore it 3002 } 3003 3004 return preferredSubId; 3005 } 3006 3007 /** 3008 * Return opportunistic subscriptions that can be visible to the caller. 3009 * Opportunistic subscriptions are for opportunistic networks, which are cellular 3010 * networks with limited capabilities and coverage, for example, CBRS. 3011 * 3012 * <p>Requires Permission: 3013 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 3014 * or that the calling app has carrier privileges (see 3015 * {@link TelephonyManager#hasCarrierPrivileges}). 3016 * 3017 * @return the list of opportunistic subscription info. If none exists, an empty list. 3018 */ 3019 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 3020 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) getOpportunisticSubscriptions()3021 public @NonNull List<SubscriptionInfo> getOpportunisticSubscriptions() { 3022 String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 3023 String contextAttributionTag = mContext != null ? mContext.getAttributionTag() : null; 3024 List<SubscriptionInfo> subInfoList = null; 3025 3026 try { 3027 ISub iSub = TelephonyManager.getSubscriptionService(); 3028 if (iSub != null) { 3029 subInfoList = iSub.getOpportunisticSubscriptions(contextPkg, 3030 contextAttributionTag); 3031 } 3032 } catch (RemoteException ex) { 3033 // ignore it 3034 } 3035 3036 if (subInfoList == null) { 3037 subInfoList = new ArrayList<>(); 3038 } 3039 3040 return subInfoList; 3041 } 3042 3043 /** 3044 * Switch to a certain subscription 3045 * 3046 * @param subId sub id 3047 * @param callbackIntent pending intent that will be sent after operation is done. 3048 */ 3049 @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) switchToSubscription(int subId, @NonNull PendingIntent callbackIntent)3050 public void switchToSubscription(int subId, @NonNull PendingIntent callbackIntent) { 3051 Preconditions.checkNotNull(callbackIntent, "callbackIntent cannot be null"); 3052 EuiccManager euiccManager = new EuiccManager(mContext); 3053 euiccManager.switchToSubscription(subId, callbackIntent); 3054 } 3055 3056 /** 3057 * Set whether a subscription is opportunistic, that is, whether the network it connects 3058 * to has limited coverage. For example, CBRS. Setting a subscription opportunistic has 3059 * following impacts: 3060 * 1) Even if it's active, it will be dormant most of the time. The modem will not try 3061 * to scan or camp until it knows an available network is nearby to save power. 3062 * 2) Telephony relies on system app or carrier input to notify nearby available networks. 3063 * See {@link TelephonyManager#updateAvailableNetworks(List, Executor, Consumer)} 3064 * for more information. 3065 * 3) In multi-SIM devices, when the network is nearby and camped, system may automatically 3066 * switch internet data between it and default data subscription, based on carrier 3067 * recommendation and its signal strength and metered-ness, etc. 3068 * 3069 * 3070 * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier 3071 * privilege permission of the subscription. 3072 * 3073 * @param opportunistic whether it’s opportunistic subscription. 3074 * @param subId the unique SubscriptionInfo index in database 3075 * @return {@code true} if the operation is succeed, {@code false} otherwise. 3076 */ 3077 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 3078 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) setOpportunistic(boolean opportunistic, int subId)3079 public boolean setOpportunistic(boolean opportunistic, int subId) { 3080 if (VDBG) logd("[setOpportunistic]+ opportunistic:" + opportunistic + " subId:" + subId); 3081 return setSubscriptionPropertyHelper(subId, "setOpportunistic", 3082 (iSub)-> iSub.setOpportunistic( 3083 opportunistic, subId, mContext.getOpPackageName())) == 1; 3084 } 3085 3086 /** 3087 * Inform SubscriptionManager that subscriptions in the list are bundled 3088 * as a group. It can be multiple primary (non-opportunistic) subscriptions, 3089 * or one or more primary plus one or more opportunistic subscriptions. 3090 * 3091 * This API will always create a new immutable group and assign group UUID to all the 3092 * subscriptions, regardless whether they are in a group already or not. 3093 * 3094 * Grouped subscriptions will have below behaviors: 3095 * 1) They will share the same user settings. 3096 * 2) The opportunistic subscriptions in the group is considered invisible and will not 3097 * return from {@link #getActiveSubscriptionInfoList()}, unless caller has carrier 3098 * privilege permission of the subscriptions. 3099 * 3) The opportunistic subscriptions in the group can't be active by itself. If all other 3100 * non-opportunistic ones are deactivated (unplugged or disabled in Settings), 3101 * the opportunistic ones will be deactivated automatically. 3102 * 3103 * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} 3104 * permission or had carrier privilege permission on the subscriptions: 3105 * {@link TelephonyManager#hasCarrierPrivileges()} or 3106 * {@link #canManageSubscription(SubscriptionInfo)} 3107 * 3108 * @throws SecurityException if the caller doesn't meet the requirements 3109 * outlined above. 3110 * @throws IllegalArgumentException if any of the subscriptions in the list doesn't exist. 3111 * @throws IllegalStateException if Telephony service is in bad state. 3112 * 3113 * @param subIdList list of subId that will be in the same group 3114 * @return groupUUID a UUID assigned to the subscription group. 3115 * 3116 */ 3117 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 3118 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) createSubscriptionGroup(@onNull List<Integer> subIdList)3119 public @NonNull ParcelUuid createSubscriptionGroup(@NonNull List<Integer> subIdList) { 3120 Preconditions.checkNotNull(subIdList, "can't create group for null subId list"); 3121 String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 3122 if (VDBG) { 3123 logd("[createSubscriptionGroup]"); 3124 } 3125 3126 ParcelUuid groupUuid = null; 3127 int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray(); 3128 try { 3129 ISub iSub = TelephonyManager.getSubscriptionService(); 3130 if (iSub != null) { 3131 groupUuid = iSub.createSubscriptionGroup(subIdArray, pkgForDebug); 3132 } else { 3133 if (!isSystemProcess()) { 3134 throw new IllegalStateException("telephony service is null."); 3135 } 3136 } 3137 } catch (RemoteException ex) { 3138 loge("createSubscriptionGroup RemoteException " + ex); 3139 if (!isSystemProcess()) { 3140 ex.rethrowAsRuntimeException(); 3141 } 3142 } 3143 3144 return groupUuid; 3145 } 3146 3147 /** 3148 * Add a list of subscriptions into a group. 3149 * See {@link #createSubscriptionGroup(List)} for more details. 3150 * 3151 * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} 3152 * permission or had carrier privilege permission on the subscriptions: 3153 * {@link TelephonyManager#hasCarrierPrivileges()} or 3154 * {@link #canManageSubscription(SubscriptionInfo)} 3155 * 3156 * @throws SecurityException if the caller doesn't meet the requirements 3157 * outlined above. 3158 * @throws IllegalArgumentException if the some subscriptions in the list doesn't exist. 3159 * @throws IllegalStateException if Telephony service is in bad state. 3160 * 3161 * @param subIdList list of subId that need adding into the group 3162 * @param groupUuid the groupUuid the subscriptions are being added to. 3163 * 3164 */ 3165 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 3166 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) addSubscriptionsIntoGroup(@onNull List<Integer> subIdList, @NonNull ParcelUuid groupUuid)3167 public void addSubscriptionsIntoGroup(@NonNull List<Integer> subIdList, 3168 @NonNull ParcelUuid groupUuid) { 3169 Preconditions.checkNotNull(subIdList, "subIdList can't be null."); 3170 Preconditions.checkNotNull(groupUuid, "groupUuid can't be null."); 3171 String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 3172 if (VDBG) { 3173 logd("[addSubscriptionsIntoGroup]"); 3174 } 3175 3176 int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray(); 3177 3178 try { 3179 ISub iSub = TelephonyManager.getSubscriptionService(); 3180 if (iSub != null) { 3181 iSub.addSubscriptionsIntoGroup(subIdArray, groupUuid, pkgForDebug); 3182 } else { 3183 if (!isSystemProcess()) { 3184 throw new IllegalStateException("telephony service is null."); 3185 } 3186 } 3187 } catch (RemoteException ex) { 3188 loge("addSubscriptionsIntoGroup RemoteException " + ex); 3189 if (!isSystemProcess()) { 3190 ex.rethrowAsRuntimeException(); 3191 } 3192 } 3193 } 3194 isSystemProcess()3195 private boolean isSystemProcess() { 3196 return Process.myUid() == Process.SYSTEM_UID; 3197 } 3198 3199 /** 3200 * Remove a list of subscriptions from their subscription group. 3201 * See {@link #createSubscriptionGroup(List)} for more details. 3202 * 3203 * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} 3204 * permission or had carrier privilege permission on the subscriptions: 3205 * {@link TelephonyManager#hasCarrierPrivileges()} or 3206 * {@link #canManageSubscription(SubscriptionInfo)} 3207 * 3208 * @throws SecurityException if the caller doesn't meet the requirements 3209 * outlined above. 3210 * @throws IllegalArgumentException if the some subscriptions in the list doesn't belong 3211 * the specified group. 3212 * @throws IllegalStateException if Telephony service is in bad state. 3213 * 3214 * @param subIdList list of subId that need removing from their groups. 3215 * 3216 */ 3217 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 3218 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) removeSubscriptionsFromGroup(@onNull List<Integer> subIdList, @NonNull ParcelUuid groupUuid)3219 public void removeSubscriptionsFromGroup(@NonNull List<Integer> subIdList, 3220 @NonNull ParcelUuid groupUuid) { 3221 Preconditions.checkNotNull(subIdList, "subIdList can't be null."); 3222 Preconditions.checkNotNull(groupUuid, "groupUuid can't be null."); 3223 String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 3224 if (VDBG) { 3225 logd("[removeSubscriptionsFromGroup]"); 3226 } 3227 3228 int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray(); 3229 3230 try { 3231 ISub iSub = TelephonyManager.getSubscriptionService(); 3232 if (iSub != null) { 3233 iSub.removeSubscriptionsFromGroup(subIdArray, groupUuid, pkgForDebug); 3234 } else { 3235 if (!isSystemProcess()) { 3236 throw new IllegalStateException("telephony service is null."); 3237 } 3238 } 3239 } catch (RemoteException ex) { 3240 loge("removeSubscriptionsFromGroup RemoteException " + ex); 3241 if (!isSystemProcess()) { 3242 ex.rethrowAsRuntimeException(); 3243 } 3244 } 3245 } 3246 3247 /** 3248 * Get subscriptionInfo list of subscriptions that are in the same group of given subId. 3249 * See {@link #createSubscriptionGroup(List)} for more details. 3250 * 3251 * Caller will either have {@link android.Manifest.permission#READ_PHONE_STATE} 3252 * permission or had carrier privilege permission on the subscription. 3253 * {@link TelephonyManager#hasCarrierPrivileges()} 3254 * 3255 * @throws IllegalStateException if Telephony service is in bad state. 3256 * @throws SecurityException if the caller doesn't meet the requirements 3257 * outlined above. 3258 * 3259 * @param groupUuid of which list of subInfo will be returned. 3260 * @return list of subscriptionInfo that belong to the same group, including the given 3261 * subscription itself. It will return an empty list if no subscription belongs to the group. 3262 * 3263 */ 3264 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 3265 @RequiresPermission(Manifest.permission.READ_PHONE_STATE) getSubscriptionsInGroup(@onNull ParcelUuid groupUuid)3266 public @NonNull List<SubscriptionInfo> getSubscriptionsInGroup(@NonNull ParcelUuid groupUuid) { 3267 Preconditions.checkNotNull(groupUuid, "groupUuid can't be null"); 3268 String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 3269 String contextAttributionTag = mContext != null ? mContext.getAttributionTag() : null; 3270 if (VDBG) { 3271 logd("[getSubscriptionsInGroup]+ groupUuid:" + groupUuid); 3272 } 3273 3274 List<SubscriptionInfo> result = null; 3275 try { 3276 ISub iSub = TelephonyManager.getSubscriptionService(); 3277 if (iSub != null) { 3278 result = iSub.getSubscriptionsInGroup(groupUuid, contextPkg, 3279 contextAttributionTag); 3280 } else { 3281 if (!isSystemProcess()) { 3282 throw new IllegalStateException("telephony service is null."); 3283 } 3284 } 3285 } catch (RemoteException ex) { 3286 loge("removeSubscriptionsFromGroup RemoteException " + ex); 3287 if (!isSystemProcess()) { 3288 ex.rethrowAsRuntimeException(); 3289 } 3290 } 3291 3292 return result; 3293 } 3294 3295 /** 3296 * Whether a subscription is visible to API caller. If it's a bundled opportunistic 3297 * subscription, it should be hidden anywhere in Settings, dialer, status bar etc. 3298 * Exception is if caller owns carrier privilege, in which case they will 3299 * want to see their own hidden subscriptions. 3300 * 3301 * @param info the subscriptionInfo to check against. 3302 * @return true if this subscription should be visible to the API caller. 3303 * 3304 * @hide 3305 */ isSubscriptionVisible(SubscriptionInfo info)3306 public boolean isSubscriptionVisible(SubscriptionInfo info) { 3307 if (info == null) return false; 3308 // If subscription is NOT grouped opportunistic subscription, it's visible. 3309 if (info.getGroupUuid() == null || !info.isOpportunistic()) return true; 3310 3311 // If the caller is the carrier app and owns the subscription, it should be visible 3312 // to the caller. 3313 boolean hasCarrierPrivilegePermission = TelephonyManager.from(mContext) 3314 .hasCarrierPrivileges(info.getSubscriptionId()) 3315 || canManageSubscription(info); 3316 return hasCarrierPrivilegePermission; 3317 } 3318 3319 /** 3320 * Return a list of subscriptions that are available and visible to the user. 3321 * Used by Settings app to show a list of subscriptions for user to pick. 3322 * 3323 * <p> 3324 * Permissions android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE is required 3325 * for getSelectableSubscriptionInfoList to be invoked. 3326 * @return list of user selectable subscriptions. 3327 * 3328 * @hide 3329 */ getSelectableSubscriptionInfoList()3330 public @Nullable List<SubscriptionInfo> getSelectableSubscriptionInfoList() { 3331 List<SubscriptionInfo> availableList = getAvailableSubscriptionInfoList(); 3332 if (availableList == null) { 3333 return null; 3334 } else { 3335 // Multiple subscriptions in a group should only have one representative. 3336 // It should be the current active primary subscription if any, or any 3337 // primary subscription. 3338 List<SubscriptionInfo> selectableList = new ArrayList<>(); 3339 Map<ParcelUuid, SubscriptionInfo> groupMap = new HashMap<>(); 3340 3341 for (SubscriptionInfo info : availableList) { 3342 // Opportunistic subscriptions are considered invisible 3343 // to users so they should never be returned. 3344 if (!isSubscriptionVisible(info)) continue; 3345 3346 ParcelUuid groupUuid = info.getGroupUuid(); 3347 if (groupUuid == null) { 3348 // Doesn't belong to any group. Add in the list. 3349 selectableList.add(info); 3350 } else if (!groupMap.containsKey(groupUuid) 3351 || (groupMap.get(groupUuid).getSimSlotIndex() == INVALID_SIM_SLOT_INDEX 3352 && info.getSimSlotIndex() != INVALID_SIM_SLOT_INDEX)) { 3353 // If it belongs to a group that has never been recorded or it's the current 3354 // active subscription, add it in the list. 3355 selectableList.remove(groupMap.get(groupUuid)); 3356 selectableList.add(info); 3357 groupMap.put(groupUuid, info); 3358 } 3359 3360 } 3361 return selectableList; 3362 } 3363 } 3364 3365 /** 3366 * Enables or disables a subscription. This is currently used in the settings page. It will 3367 * fail and return false if operation is not supported or failed. 3368 * 3369 * To disable an active subscription on a physical (non-Euicc) SIM, 3370 * {@link #canDisablePhysicalSubscription} needs to be true. 3371 * 3372 * <p> 3373 * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required 3374 * 3375 * @param enable whether user is turning it on or off. 3376 * @param subscriptionId Subscription to be enabled or disabled. 3377 * It could be a eSIM or pSIM subscription. 3378 * 3379 * @return whether the operation is successful. 3380 * 3381 * @hide 3382 */ 3383 @SystemApi 3384 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) setSubscriptionEnabled(int subscriptionId, boolean enable)3385 public boolean setSubscriptionEnabled(int subscriptionId, boolean enable) { 3386 if (VDBG) { 3387 logd("setSubscriptionActivated subId= " + subscriptionId + " enable " + enable); 3388 } 3389 try { 3390 ISub iSub = TelephonyManager.getSubscriptionService(); 3391 if (iSub != null) { 3392 return iSub.setSubscriptionEnabled(enable, subscriptionId); 3393 } 3394 } catch (RemoteException ex) { 3395 // ignore it 3396 } 3397 3398 return false; 3399 } 3400 3401 /** 3402 * Set uicc applications being enabled or disabled. 3403 * The value will be remembered on the subscription and will be applied whenever it's present. 3404 * If the subscription in currently present, it will also apply the setting to modem 3405 * immediately (the setting in the modem will not change until the modem receives and responds 3406 * to the request, but typically this should only take a few seconds. The user visible setting 3407 * available from SubscriptionInfo.areUiccApplicationsEnabled() will be updated 3408 * immediately.) 3409 * 3410 * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required 3411 * 3412 * @param subscriptionId which subscription to operate on. 3413 * @param enabled whether uicc applications are enabled or disabled. 3414 * @hide 3415 */ 3416 @SystemApi 3417 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setUiccApplicationsEnabled(int subscriptionId, boolean enabled)3418 public void setUiccApplicationsEnabled(int subscriptionId, boolean enabled) { 3419 if (VDBG) { 3420 logd("setUiccApplicationsEnabled subId= " + subscriptionId + " enable " + enabled); 3421 } 3422 try { 3423 ISub iSub = ISub.Stub.asInterface( 3424 TelephonyFrameworkInitializer 3425 .getTelephonyServiceManager() 3426 .getSubscriptionServiceRegisterer() 3427 .get()); 3428 if (iSub != null) { 3429 iSub.setUiccApplicationsEnabled(enabled, subscriptionId); 3430 } 3431 } catch (RemoteException ex) { 3432 // ignore it 3433 } 3434 } 3435 3436 /** 3437 * Whether it's supported to disable / re-enable a subscription on a physical (non-euicc) SIM. 3438 * 3439 * Physical SIM refers non-euicc, or aka non-programmable SIM. 3440 * 3441 * It provides whether a physical SIM card can be disabled without taking it out, which is done 3442 * via {@link #setSubscriptionEnabled(int, boolean)} API. 3443 * 3444 * Requires Permission: READ_PRIVILEGED_PHONE_STATE. 3445 * 3446 * @return whether can disable subscriptions on physical SIMs. 3447 * 3448 * @hide 3449 */ 3450 @SystemApi 3451 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) canDisablePhysicalSubscription()3452 public boolean canDisablePhysicalSubscription() { 3453 if (VDBG) { 3454 logd("canDisablePhysicalSubscription"); 3455 } 3456 try { 3457 ISub iSub = ISub.Stub.asInterface( 3458 TelephonyFrameworkInitializer 3459 .getTelephonyServiceManager() 3460 .getSubscriptionServiceRegisterer() 3461 .get()); 3462 if (iSub != null) { 3463 return iSub.canDisablePhysicalSubscription(); 3464 } 3465 } catch (RemoteException ex) { 3466 // ignore it 3467 } 3468 3469 return false; 3470 } 3471 3472 /** 3473 * DO NOT USE. 3474 * This API is designed for features that are not finished at this point. Do not call this API. 3475 * @hide 3476 * TODO b/135547512: further clean up 3477 */ 3478 @SystemApi 3479 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) isSubscriptionEnabled(int subscriptionId)3480 public boolean isSubscriptionEnabled(int subscriptionId) { 3481 try { 3482 ISub iSub = TelephonyManager.getSubscriptionService(); 3483 if (iSub != null) { 3484 return iSub.isSubscriptionEnabled(subscriptionId); 3485 } 3486 } catch (RemoteException ex) { 3487 // ignore it 3488 } 3489 3490 return false; 3491 } 3492 3493 /** 3494 * Set the device to device status sharing user preference for a subscription ID. The setting 3495 * app uses this method to indicate with whom they wish to share device to device status 3496 * information. 3497 * @param sharing the status sharing preference 3498 * @param subscriptionId the unique Subscription ID in database 3499 */ 3500 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDeviceToDeviceStatusSharingPreference(int subscriptionId, @DeviceToDeviceStatusSharingPreference int sharing)3501 public void setDeviceToDeviceStatusSharingPreference(int subscriptionId, 3502 @DeviceToDeviceStatusSharingPreference int sharing) { 3503 if (VDBG) { 3504 logd("[setDeviceToDeviceStatusSharing] + sharing: " + sharing + " subId: " 3505 + subscriptionId); 3506 } 3507 setSubscriptionPropertyHelper(subscriptionId, "setDeviceToDeviceSharingStatus", 3508 (iSub)->iSub.setDeviceToDeviceStatusSharing(sharing, subscriptionId)); 3509 } 3510 3511 /** 3512 * Returns the user-chosen device to device status sharing preference 3513 * @param subscriptionId Subscription id of subscription 3514 * @return The device to device status sharing preference 3515 */ getDeviceToDeviceStatusSharingPreference( int subscriptionId)3516 public @DeviceToDeviceStatusSharingPreference int getDeviceToDeviceStatusSharingPreference( 3517 int subscriptionId) { 3518 if (VDBG) { 3519 logd("[getDeviceToDeviceStatusSharing] + subId: " + subscriptionId); 3520 } 3521 return getIntegerSubscriptionProperty(subscriptionId, D2D_STATUS_SHARING, 3522 D2D_SHARING_DISABLED, mContext); 3523 } 3524 3525 /** 3526 * Set the list of contacts that allow device to device status sharing for a subscription ID. 3527 * The setting app uses this method to indicate with whom they wish to share device to device 3528 * status information. 3529 * @param contacts The list of contacts that allow device to device status sharing 3530 * @param subscriptionId The unique Subscription ID in database 3531 */ 3532 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDeviceToDeviceStatusSharingContacts(int subscriptionId, @NonNull List<Uri> contacts)3533 public void setDeviceToDeviceStatusSharingContacts(int subscriptionId, 3534 @NonNull List<Uri> contacts) { 3535 String contactString = serializeUriLists(contacts); 3536 if (VDBG) { 3537 logd("[setDeviceToDeviceStatusSharingContacts] + contacts: " + contactString 3538 + " subId: " + subscriptionId); 3539 } 3540 setSubscriptionPropertyHelper(subscriptionId, "setDeviceToDeviceSharingStatus", 3541 (iSub)->iSub.setDeviceToDeviceStatusSharingContacts(serializeUriLists(contacts), 3542 subscriptionId)); 3543 } 3544 3545 /** 3546 * Returns the list of contacts that allow device to device status sharing. 3547 * @param subscriptionId Subscription id of subscription 3548 * @return The list of contacts that allow device to device status sharing 3549 */ getDeviceToDeviceStatusSharingContacts( int subscriptionId)3550 public @NonNull List<Uri> getDeviceToDeviceStatusSharingContacts( 3551 int subscriptionId) { 3552 if (VDBG) { 3553 logd("[getDeviceToDeviceStatusSharingContacts] + subId: " + subscriptionId); 3554 } 3555 return getContactsFromSubscriptionProperty(subscriptionId, 3556 D2D_STATUS_SHARING_SELECTED_CONTACTS, mContext); 3557 } 3558 3559 /** 3560 * DO NOT USE. 3561 * This API is designed for features that are not finished at this point. Do not call this API. 3562 * @hide 3563 * TODO b/135547512: further clean up 3564 */ 3565 @SystemApi 3566 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getEnabledSubscriptionId(int slotIndex)3567 public int getEnabledSubscriptionId(int slotIndex) { 3568 int subId = INVALID_SUBSCRIPTION_ID; 3569 3570 try { 3571 ISub iSub = TelephonyManager.getSubscriptionService(); 3572 if (iSub != null) { 3573 subId = iSub.getEnabledSubscriptionId(slotIndex); 3574 } 3575 } catch (RemoteException ex) { 3576 // ignore it 3577 } 3578 3579 if (VDBG) logd("getEnabledSubscriptionId, subId = " + subId); 3580 return subId; 3581 } 3582 3583 private interface CallISubMethodHelper { callMethod(ISub iSub)3584 int callMethod(ISub iSub) throws RemoteException; 3585 } 3586 setSubscriptionPropertyHelper(int subId, String methodName, CallISubMethodHelper helper)3587 private int setSubscriptionPropertyHelper(int subId, String methodName, 3588 CallISubMethodHelper helper) { 3589 if (!isValidSubscriptionId(subId)) { 3590 logd("[" + methodName + "]" + "- fail"); 3591 return -1; 3592 } 3593 3594 int result = 0; 3595 3596 try { 3597 ISub iSub = TelephonyManager.getSubscriptionService(); 3598 if (iSub != null) { 3599 result = helper.callMethod(iSub); 3600 } 3601 } catch (RemoteException ex) { 3602 // ignore it 3603 } 3604 3605 return result; 3606 } 3607 3608 /** 3609 * Get active data subscription id. Active data subscription refers to the subscription 3610 * currently chosen to provide cellular internet connection to the user. This may be 3611 * different from getDefaultDataSubscriptionId(). Eg. Opportunistics data 3612 * 3613 * See {@link PhoneStateListener#onActiveDataSubscriptionIdChanged(int)} for the details. 3614 * 3615 * @return Active data subscription id if any is chosen, or 3616 * SubscriptionManager.INVALID_SUBSCRIPTION_ID if not. 3617 */ getActiveDataSubscriptionId()3618 public static int getActiveDataSubscriptionId() { 3619 return sActiveDataSubIdCache.query(null); 3620 } 3621 3622 /** 3623 * Helper method that puts a subscription id on an intent with the constants: 3624 * PhoneConstant.SUBSCRIPTION_KEY and SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX. 3625 * Both constants are used to support backwards compatibility. Once we know we got all places, 3626 * we can remove PhoneConstants.SUBSCRIPTION_KEY. 3627 * @param intent Intent to put sub id on. 3628 * @param subId SubscriptionId to put on intent. 3629 * 3630 * @hide 3631 */ putSubscriptionIdExtra(Intent intent, int subId)3632 public static void putSubscriptionIdExtra(Intent intent, int subId) { 3633 intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId); 3634 intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId); 3635 } 3636 3637 /** @hide */ invalidateDefaultSubIdCaches()3638 public static void invalidateDefaultSubIdCaches() { 3639 PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DEFAULT_SUB_ID_PROPERTY); 3640 } 3641 3642 /** @hide */ invalidateDefaultDataSubIdCaches()3643 public static void invalidateDefaultDataSubIdCaches() { 3644 PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DEFAULT_DATA_SUB_ID_PROPERTY); 3645 } 3646 3647 /** @hide */ invalidateDefaultSmsSubIdCaches()3648 public static void invalidateDefaultSmsSubIdCaches() { 3649 PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DEFAULT_SMS_SUB_ID_PROPERTY); 3650 } 3651 3652 /** @hide */ invalidateActiveDataSubIdCaches()3653 public static void invalidateActiveDataSubIdCaches() { 3654 PropertyInvalidatedCache.invalidateCache(CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY); 3655 } 3656 3657 /** @hide */ invalidateSlotIndexCaches()3658 public static void invalidateSlotIndexCaches() { 3659 PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SLOT_INDEX_PROPERTY); 3660 } 3661 3662 /** 3663 * Allows a test process to disable client-side caching operations. 3664 * 3665 * @hide 3666 */ disableCaching()3667 public static void disableCaching() { 3668 sDefaultSubIdCache.disableLocal(); 3669 sDefaultDataSubIdCache.disableLocal(); 3670 sActiveDataSubIdCache.disableLocal(); 3671 sDefaultSmsSubIdCache.disableLocal(); 3672 sSlotIndexCache.disableLocal(); 3673 sPhoneIdCache.disableLocal(); 3674 } 3675 3676 /** 3677 * Clears all process-local binder caches. 3678 * 3679 * @hide */ clearCaches()3680 public static void clearCaches() { 3681 sDefaultSubIdCache.clear(); 3682 sDefaultDataSubIdCache.clear(); 3683 sActiveDataSubIdCache.clear(); 3684 sDefaultSmsSubIdCache.clear(); 3685 sSlotIndexCache.clear(); 3686 sPhoneIdCache.clear(); 3687 } 3688 3689 /** 3690 * Called to retrieve SIM-specific settings data to be backed up. 3691 * 3692 * @return data in byte[] to be backed up. 3693 * 3694 * @hide 3695 */ 3696 @NonNull 3697 @SystemApi 3698 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getAllSimSpecificSettingsForBackup()3699 public byte[] getAllSimSpecificSettingsForBackup() { 3700 Bundle bundle = mContext.getContentResolver().call( 3701 SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, 3702 GET_SIM_SPECIFIC_SETTINGS_METHOD_NAME, null, null); 3703 return bundle.getByteArray(SubscriptionManager.KEY_SIM_SPECIFIC_SETTINGS_DATA); 3704 } 3705 3706 /** 3707 * Called to attempt to restore the backed up sim-specific configs to device for specific sim. 3708 * This will try to restore the data that was stored internally when {@link 3709 * #restoreAllSimSpecificSettingsFromBackup(byte[] data)} was called during setup wizard. 3710 * End result is SimInfoDB is modified to match any backed up configs for the requested 3711 * inserted sim. 3712 * 3713 * <p> 3714 * The {@link Uri} {@link #SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is notified if any SimInfoDB 3715 * entry is updated as the result of this method call. 3716 * 3717 * @param iccId of the sim that a restore is requested for. 3718 * 3719 * @hide 3720 */ 3721 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) restoreSimSpecificSettingsForIccIdFromBackup(@onNull String iccId)3722 public void restoreSimSpecificSettingsForIccIdFromBackup(@NonNull String iccId) { 3723 mContext.getContentResolver().call( 3724 SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, 3725 RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, 3726 iccId, null); 3727 } 3728 3729 /** 3730 * Called during setup wizard restore flow to attempt to restore the backed up sim-specific 3731 * configs to device for all existing SIMs in SimInfoDB. Internally, it will store the backup 3732 * data in an internal file. This file will persist on device for device's lifetime and will be 3733 * used later on when a SIM is inserted to restore that specific SIM's settings by calling 3734 * {@link #restoreSimSpecificSettingsForIccIdFromBackup(String iccId)}. End result is 3735 * SimInfoDB is modified to match any backed up configs for the appropriate inserted SIMs. 3736 * 3737 * <p> 3738 * The {@link Uri} {@link #SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is notified if any SimInfoDB 3739 * entry is updated as the result of this method call. 3740 * 3741 * @param data with the sim specific configs to be backed up. 3742 * 3743 * @hide 3744 */ 3745 @SystemApi 3746 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) restoreAllSimSpecificSettingsFromBackup(@onNull byte[] data)3747 public void restoreAllSimSpecificSettingsFromBackup(@NonNull byte[] data) { 3748 Bundle bundle = new Bundle(); 3749 bundle.putByteArray(KEY_SIM_SPECIFIC_SETTINGS_DATA, data); 3750 mContext.getContentResolver().call( 3751 SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, 3752 RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, 3753 null, bundle); 3754 } 3755 } 3756