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 * TelephonyProvider column name for NR Advanced calling 953 * Determines if the user has enabled VoNR settings for this subscription. 954 * 955 * @hide 956 */ 957 public static final String NR_ADVANCED_CALLING_ENABLED = 958 SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED; 959 960 /** 961 * Profile class of the subscription 962 * @hide 963 */ 964 @Retention(RetentionPolicy.SOURCE) 965 @IntDef(prefix = { "PROFILE_CLASS_" }, value = { 966 SimInfo.PROFILE_CLASS_TESTING, 967 SimInfo.PROFILE_CLASS_PROVISIONING, 968 SimInfo.PROFILE_CLASS_OPERATIONAL, 969 SimInfo.PROFILE_CLASS_UNSET, 970 }) 971 public @interface ProfileClass {} 972 973 /** 974 * A testing profile can be pre-loaded or downloaded onto 975 * the eUICC and provides connectivity to test equipment 976 * for the purpose of testing the device and the eUICC. It 977 * is not intended to store any operator credentials. 978 * @hide 979 */ 980 @SystemApi 981 public static final int PROFILE_CLASS_TESTING = SimInfo.PROFILE_CLASS_TESTING; 982 983 /** 984 * A provisioning profile is pre-loaded onto the eUICC and 985 * provides connectivity to a mobile network solely for the 986 * purpose of provisioning profiles. 987 * @hide 988 */ 989 @SystemApi 990 public static final int PROFILE_CLASS_PROVISIONING = SimInfo.PROFILE_CLASS_PROVISIONING; 991 992 /** 993 * An operational profile can be pre-loaded or downloaded 994 * onto the eUICC and provides services provided by the 995 * operator. 996 * @hide 997 */ 998 @SystemApi 999 public static final int PROFILE_CLASS_OPERATIONAL = SimInfo.PROFILE_CLASS_OPERATIONAL; 1000 1001 /** 1002 * The profile class is unset. This occurs when profile class 1003 * info is not available. The subscription either has no profile 1004 * metadata or the profile metadata did not encode profile class. 1005 * @hide 1006 */ 1007 @SystemApi 1008 public static final int PROFILE_CLASS_UNSET = SimInfo.PROFILE_CLASS_UNSET; 1009 1010 /** 1011 * Default profile class 1012 * @hide 1013 */ 1014 @SystemApi 1015 @Deprecated 1016 public static final int PROFILE_CLASS_DEFAULT = SimInfo.PROFILE_CLASS_UNSET; 1017 1018 /** 1019 * IMSI (International Mobile Subscriber Identity). 1020 * <P>Type: TEXT </P> 1021 * @hide 1022 */ 1023 //TODO: add @SystemApi 1024 public static final String IMSI = SimInfo.COLUMN_IMSI; 1025 1026 /** 1027 * Whether uicc applications is set to be enabled or disabled. By default it's enabled. 1028 * @hide 1029 */ 1030 public static final String UICC_APPLICATIONS_ENABLED = SimInfo.COLUMN_UICC_APPLICATIONS_ENABLED; 1031 1032 /** 1033 * Indicate which network type is allowed. By default it's enabled. 1034 * @hide 1035 */ 1036 public static final String ALLOWED_NETWORK_TYPES = 1037 SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS; 1038 1039 /** 1040 * Broadcast Action: The user has changed one of the default subs related to 1041 * data, phone calls, or sms</p> 1042 * 1043 * TODO: Change to a listener 1044 * @hide 1045 */ 1046 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1047 public static final String SUB_DEFAULT_CHANGED_ACTION = 1048 "android.intent.action.SUB_DEFAULT_CHANGED"; 1049 1050 /** 1051 * Broadcast Action: The default subscription has changed. This has the following 1052 * extra values:</p> 1053 * The {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default subscription index 1054 */ 1055 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1056 public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED 1057 = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED"; 1058 1059 /** 1060 * Broadcast Action: The default sms subscription has changed. This has the following 1061 * extra values:</p> 1062 * {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default sms 1063 * subscription index 1064 */ 1065 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1066 public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED 1067 = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED"; 1068 1069 /** 1070 * Activity Action: Display UI for managing the billing relationship plans 1071 * between a carrier and a specific subscriber. 1072 * <p> 1073 * Carrier apps are encouraged to implement this activity, and the OS will 1074 * provide an affordance to quickly enter this activity, typically via 1075 * Settings. This affordance will only be shown when the carrier app is 1076 * actively providing subscription plan information via 1077 * {@link #setSubscriptionPlans(int, List)}. 1078 * <p> 1079 * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription 1080 * the user is interested in. 1081 */ 1082 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 1083 public static final String ACTION_MANAGE_SUBSCRIPTION_PLANS 1084 = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS"; 1085 1086 /** 1087 * Broadcast Action: Request a refresh of the billing relationship plans 1088 * between a carrier and a specific subscriber. 1089 * <p> 1090 * Carrier apps are encouraged to implement this receiver, and the OS will 1091 * provide an affordance to request a refresh. This affordance will only be 1092 * shown when the carrier app is actively providing subscription plan 1093 * information via {@link #setSubscriptionPlans(int, List)}. 1094 * <p> 1095 * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription 1096 * the user is interested in. 1097 * <p> 1098 * Receivers should protect themselves by checking that the sender holds the 1099 * {@code android.permission.MANAGE_SUBSCRIPTION_PLANS} permission. 1100 */ 1101 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1102 public static final String ACTION_REFRESH_SUBSCRIPTION_PLANS 1103 = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS"; 1104 1105 /** 1106 * Broadcast Action: The billing relationship plans between a carrier and a 1107 * specific subscriber has changed. 1108 * <p> 1109 * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription 1110 * changed. 1111 * @hide 1112 */ 1113 @SystemApi 1114 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 1115 @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS) 1116 public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED 1117 = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED"; 1118 1119 /** 1120 * Integer extra used with {@link #ACTION_DEFAULT_SUBSCRIPTION_CHANGED} and 1121 * {@link #ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED} to indicate the subscription 1122 * which has changed. 1123 */ 1124 public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX"; 1125 1126 /** 1127 * Integer extra to specify SIM slot index. 1128 */ 1129 public static final String EXTRA_SLOT_INDEX = "android.telephony.extra.SLOT_INDEX"; 1130 1131 private final Context mContext; 1132 1133 // Cache of Resource that has been created in getResourcesForSubId. Key is a Pair containing 1134 // the Context and subId. 1135 private static final Map<Pair<Context, Integer>, Resources> sResourcesCache = 1136 new ConcurrentHashMap<>(); 1137 1138 /** 1139 * A listener class for monitoring changes to {@link SubscriptionInfo} records. 1140 * <p> 1141 * Override the onSubscriptionsChanged method in the object that extends this 1142 * class and pass it to {@link #addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)} 1143 * to register your listener and to unregister invoke 1144 * {@link #removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)} 1145 * <p> 1146 * Permissions android.Manifest.permission.READ_PHONE_STATE is required 1147 * for #onSubscriptionsChanged to be invoked. 1148 */ 1149 public static class OnSubscriptionsChangedListener { 1150 private class OnSubscriptionsChangedListenerHandler extends Handler { OnSubscriptionsChangedListenerHandler()1151 OnSubscriptionsChangedListenerHandler() { 1152 super(); 1153 } 1154 OnSubscriptionsChangedListenerHandler(Looper looper)1155 OnSubscriptionsChangedListenerHandler(Looper looper) { 1156 super(looper); 1157 } 1158 } 1159 1160 /** 1161 * Posted executor callback on the handler associated with a given looper. 1162 * The looper can be the calling thread's looper or the looper passed from the 1163 * constructor {@link #OnSubscriptionsChangedListener(Looper)}. 1164 */ 1165 private final HandlerExecutor mExecutor; 1166 1167 /** 1168 * @hide 1169 */ getHandlerExecutor()1170 public HandlerExecutor getHandlerExecutor() { 1171 return mExecutor; 1172 } 1173 OnSubscriptionsChangedListener()1174 public OnSubscriptionsChangedListener() { 1175 mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler()); 1176 } 1177 1178 /** 1179 * Allow a listener to be created with a custom looper 1180 * @param looper the looper that the underlining handler should run on 1181 * @hide 1182 */ OnSubscriptionsChangedListener(Looper looper)1183 public OnSubscriptionsChangedListener(Looper looper) { 1184 mExecutor = new HandlerExecutor(new OnSubscriptionsChangedListenerHandler(looper)); 1185 } 1186 1187 /** 1188 * Callback invoked when there is any change to any SubscriptionInfo, as well as once on 1189 * registering for changes with {@link #addOnSubscriptionsChangedListener}. Typically 1190 * this method would invoke {@link #getActiveSubscriptionInfoList} 1191 */ onSubscriptionsChanged()1192 public void onSubscriptionsChanged() { 1193 if (DBG) log("onSubscriptionsChanged: NOT OVERRIDDEN"); 1194 } 1195 1196 /** 1197 * Callback invoked when {@link SubscriptionManager#addOnSubscriptionsChangedListener( 1198 * Executor, OnSubscriptionsChangedListener)} or 1199 * {@link SubscriptionManager#addOnSubscriptionsChangedListener( 1200 * OnSubscriptionsChangedListener)} fails to complete due to the 1201 * {@link Context#TELEPHONY_REGISTRY_SERVICE} being unavailable. 1202 * @hide 1203 */ onAddListenerFailed()1204 public void onAddListenerFailed() { 1205 Rlog.w(LOG_TAG, "onAddListenerFailed not overridden"); 1206 } 1207 log(String s)1208 private void log(String s) { 1209 Rlog.d(LOG_TAG, s); 1210 } 1211 } 1212 1213 /** @hide */ 1214 @UnsupportedAppUsage SubscriptionManager(Context context)1215 public SubscriptionManager(Context context) { 1216 if (DBG) logd("SubscriptionManager created"); 1217 mContext = context; 1218 } 1219 getNetworkPolicyManager()1220 private NetworkPolicyManager getNetworkPolicyManager() { 1221 return (NetworkPolicyManager) mContext 1222 .getSystemService(Context.NETWORK_POLICY_SERVICE); 1223 } 1224 1225 /** 1226 * @deprecated developers should always obtain references directly from 1227 * {@link Context#getSystemService(Class)}. 1228 */ 1229 @Deprecated from(Context context)1230 public static SubscriptionManager from(Context context) { 1231 return (SubscriptionManager) context 1232 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); 1233 } 1234 1235 /** 1236 * Register for changes to the list of active {@link SubscriptionInfo} records or to the 1237 * individual records themselves. When a change occurs the onSubscriptionsChanged method of 1238 * the listener will be invoked immediately if there has been a notification. The 1239 * onSubscriptionChanged method will also be triggered once initially when calling this 1240 * function. The callback will be invoked on the looper specified in the listener's constructor. 1241 * 1242 * @param listener an instance of {@link OnSubscriptionsChangedListener} with 1243 * onSubscriptionsChanged overridden. 1244 * 1245 * @deprecated Will get exception if the parameter listener is not initialized with a Looper. 1246 * Use {@link #addOnSubscriptionsChangedListener(Executor, OnSubscriptionsChangedListener)}. 1247 */ 1248 @Deprecated addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener)1249 public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { 1250 if (listener == null) return; 1251 addOnSubscriptionsChangedListener(listener.mExecutor, listener); 1252 } 1253 1254 /** 1255 * Register for changes to the list of active {@link SubscriptionInfo} records or to the 1256 * individual records themselves. When a change occurs the onSubscriptionsChanged method of 1257 * the listener will be invoked immediately if there has been a notification. The 1258 * onSubscriptionChanged method will also be triggered once initially when calling this 1259 * function. 1260 * 1261 * @param listener an instance of {@link OnSubscriptionsChangedListener} with 1262 * onSubscriptionsChanged overridden. 1263 * @param executor the executor that will execute callbacks. 1264 */ addOnSubscriptionsChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnSubscriptionsChangedListener listener)1265 public void addOnSubscriptionsChangedListener( 1266 @NonNull @CallbackExecutor Executor executor, 1267 @NonNull OnSubscriptionsChangedListener listener) { 1268 String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 1269 if (DBG) { 1270 logd("register OnSubscriptionsChangedListener pkgName=" + pkgName 1271 + " listener=" + listener); 1272 } 1273 // We use the TelephonyRegistry as it runs in the system and thus is always 1274 // available. Where as SubscriptionController could crash and not be available 1275 TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) 1276 mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 1277 if (telephonyRegistryManager != null) { 1278 telephonyRegistryManager.addOnSubscriptionsChangedListener(listener, 1279 executor); 1280 } else { 1281 // If the telephony registry isn't available, we will inform the caller on their 1282 // listener that it failed so they can try to re-register. 1283 loge("addOnSubscriptionsChangedListener: pkgname=" + pkgName + " failed to be added " 1284 + " due to TELEPHONY_REGISTRY_SERVICE being unavailable."); 1285 executor.execute(() -> listener.onAddListenerFailed()); 1286 } 1287 } 1288 1289 /** 1290 * Unregister the {@link OnSubscriptionsChangedListener}. This is not strictly necessary 1291 * as the listener will automatically be unregistered if an attempt to invoke the listener 1292 * fails. 1293 * 1294 * @param listener that is to be unregistered. 1295 */ removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener)1296 public void removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { 1297 if (listener == null) return; 1298 String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 1299 if (DBG) { 1300 logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug 1301 + " listener=" + listener); 1302 } 1303 // We use the TelephonyRegistry as it runs in the system and thus is always 1304 // available where as SubscriptionController could crash and not be available 1305 TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) 1306 mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 1307 if (telephonyRegistryManager != null) { 1308 telephonyRegistryManager.removeOnSubscriptionsChangedListener(listener); 1309 } 1310 } 1311 1312 /** 1313 * A listener class for monitoring changes to {@link SubscriptionInfo} records of opportunistic 1314 * subscriptions. 1315 * <p> 1316 * Override the onOpportunisticSubscriptionsChanged method in the object that extends this 1317 * or {@link #addOnOpportunisticSubscriptionsChangedListener( 1318 * Executor, OnOpportunisticSubscriptionsChangedListener)} 1319 * to register your listener and to unregister invoke 1320 * {@link #removeOnOpportunisticSubscriptionsChangedListener( 1321 * OnOpportunisticSubscriptionsChangedListener)} 1322 * <p> 1323 * Permissions android.Manifest.permission.READ_PHONE_STATE is required 1324 * for #onOpportunisticSubscriptionsChanged to be invoked. 1325 */ 1326 public static class OnOpportunisticSubscriptionsChangedListener { 1327 /** 1328 * Callback invoked when there is any change to any SubscriptionInfo. Typically 1329 * this method would invoke {@link #getActiveSubscriptionInfoList} 1330 */ onOpportunisticSubscriptionsChanged()1331 public void onOpportunisticSubscriptionsChanged() { 1332 if (DBG) log("onOpportunisticSubscriptionsChanged: NOT OVERRIDDEN"); 1333 } 1334 log(String s)1335 private void log(String s) { 1336 Rlog.d(LOG_TAG, s); 1337 } 1338 } 1339 1340 /** 1341 * Register for changes to the list of opportunistic subscription records or to the 1342 * individual records themselves. When a change occurs the onOpportunisticSubscriptionsChanged 1343 * method of the listener will be invoked immediately if there has been a notification. 1344 * 1345 * @param listener an instance of {@link OnOpportunisticSubscriptionsChangedListener} with 1346 * onOpportunisticSubscriptionsChanged overridden. 1347 */ addOnOpportunisticSubscriptionsChangedListener( @onNull @allbackExecutor Executor executor, @NonNull OnOpportunisticSubscriptionsChangedListener listener)1348 public void addOnOpportunisticSubscriptionsChangedListener( 1349 @NonNull @CallbackExecutor Executor executor, 1350 @NonNull OnOpportunisticSubscriptionsChangedListener listener) { 1351 if (executor == null || listener == null) { 1352 return; 1353 } 1354 1355 String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 1356 if (DBG) { 1357 logd("register addOnOpportunisticSubscriptionsChangedListener pkgName=" + pkgName 1358 + " listener=" + listener); 1359 } 1360 1361 // We use the TelephonyRegistry as it runs in the system and thus is always 1362 // available where as SubscriptionController could crash and not be available 1363 TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) 1364 mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 1365 if (telephonyRegistryManager != null) { 1366 telephonyRegistryManager.addOnOpportunisticSubscriptionsChangedListener( 1367 listener, executor); 1368 } 1369 } 1370 1371 /** 1372 * Unregister the {@link OnOpportunisticSubscriptionsChangedListener} that is currently 1373 * listening opportunistic subscriptions change. This is not strictly necessary 1374 * as the listener will automatically be unregistered if an attempt to invoke the listener 1375 * fails. 1376 * 1377 * @param listener that is to be unregistered. 1378 */ removeOnOpportunisticSubscriptionsChangedListener( @onNull OnOpportunisticSubscriptionsChangedListener listener)1379 public void removeOnOpportunisticSubscriptionsChangedListener( 1380 @NonNull OnOpportunisticSubscriptionsChangedListener listener) { 1381 Preconditions.checkNotNull(listener, "listener cannot be null"); 1382 String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 1383 if (DBG) { 1384 logd("unregister OnOpportunisticSubscriptionsChangedListener pkgForDebug=" 1385 + pkgForDebug + " listener=" + listener); 1386 } 1387 TelephonyRegistryManager telephonyRegistryManager = (TelephonyRegistryManager) 1388 mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); 1389 if (telephonyRegistryManager != null) { 1390 telephonyRegistryManager.removeOnOpportunisticSubscriptionsChangedListener(listener); 1391 } 1392 } 1393 1394 /** 1395 * Get the active SubscriptionInfo with the input subId. 1396 * 1397 * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 1398 * or that the calling app has carrier privileges (see 1399 * {@link TelephonyManager#hasCarrierPrivileges}). 1400 * 1401 * @param subId The unique SubscriptionInfo key in database. 1402 * @return SubscriptionInfo, maybe null if its not active. 1403 */ 1404 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 1405 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) getActiveSubscriptionInfo(int subId)1406 public SubscriptionInfo getActiveSubscriptionInfo(int subId) { 1407 if (VDBG) logd("[getActiveSubscriptionInfo]+ subId=" + subId); 1408 if (!isValidSubscriptionId(subId)) { 1409 if (DBG) { 1410 logd("[getActiveSubscriptionInfo]- invalid subId"); 1411 } 1412 return null; 1413 } 1414 1415 SubscriptionInfo subInfo = null; 1416 1417 try { 1418 ISub iSub = TelephonyManager.getSubscriptionService(); 1419 if (iSub != null) { 1420 subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName(), 1421 mContext.getAttributionTag()); 1422 } 1423 } catch (RemoteException ex) { 1424 // ignore it 1425 } 1426 1427 return subInfo; 1428 } 1429 1430 /** 1431 * Gets an active SubscriptionInfo {@link SubscriptionInfo} associated with the Sim IccId. 1432 * 1433 * @param iccId the IccId of SIM card 1434 * @return SubscriptionInfo, maybe null if its not active 1435 * 1436 * @hide 1437 */ 1438 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) 1439 @Nullable 1440 @SystemApi getActiveSubscriptionInfoForIcc(@onNull String iccId)1441 public SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String iccId) { 1442 if (VDBG) logd("[getActiveSubscriptionInfoForIccIndex]+ iccId=" + iccId); 1443 if (iccId == null) { 1444 logd("[getActiveSubscriptionInfoForIccIndex]- null iccid"); 1445 return null; 1446 } 1447 1448 SubscriptionInfo result = null; 1449 1450 try { 1451 ISub iSub = TelephonyManager.getSubscriptionService(); 1452 if (iSub != null) { 1453 result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName(), 1454 mContext.getAttributionTag()); 1455 } 1456 } catch (RemoteException ex) { 1457 // ignore it 1458 } 1459 1460 return result; 1461 } 1462 1463 /** 1464 * Get the active SubscriptionInfo associated with the slotIndex 1465 * 1466 * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 1467 * or that the calling app has carrier privileges (see 1468 * {@link TelephonyManager#hasCarrierPrivileges}). 1469 * 1470 * @param slotIndex the slot which the subscription is inserted 1471 * @return SubscriptionInfo, maybe null if its not active 1472 */ 1473 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 1474 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) getActiveSubscriptionInfoForSimSlotIndex(int slotIndex)1475 public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) { 1476 if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIndex=" + slotIndex); 1477 if (!isValidSlotIndex(slotIndex)) { 1478 logd("[getActiveSubscriptionInfoForSimSlotIndex]- invalid slotIndex"); 1479 return null; 1480 } 1481 1482 SubscriptionInfo result = null; 1483 1484 try { 1485 ISub iSub = TelephonyManager.getSubscriptionService(); 1486 if (iSub != null) { 1487 result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex, 1488 mContext.getOpPackageName(), mContext.getAttributionTag()); 1489 } 1490 } catch (RemoteException ex) { 1491 // ignore it 1492 } 1493 1494 return result; 1495 } 1496 1497 /** 1498 * @return List of all SubscriptionInfo records in database, 1499 * include those that were inserted before, maybe empty but not null. 1500 * @hide 1501 */ 1502 @NonNull 1503 @UnsupportedAppUsage getAllSubscriptionInfoList()1504 public List<SubscriptionInfo> getAllSubscriptionInfoList() { 1505 if (VDBG) logd("[getAllSubscriptionInfoList]+"); 1506 1507 List<SubscriptionInfo> result = null; 1508 1509 try { 1510 ISub iSub = TelephonyManager.getSubscriptionService(); 1511 if (iSub != null) { 1512 result = iSub.getAllSubInfoList(mContext.getOpPackageName(), 1513 mContext.getAttributionTag()); 1514 } 1515 } catch (RemoteException ex) { 1516 // ignore it 1517 } 1518 1519 if (result == null) { 1520 result = Collections.emptyList(); 1521 } 1522 return result; 1523 } 1524 1525 /** 1526 * Get the SubscriptionInfo(s) of the currently active SIM(s). The records will be sorted 1527 * by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}. 1528 * 1529 * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 1530 * or that the calling app has carrier privileges (see 1531 * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible 1532 * to the calling app are returned. 1533 * 1534 * @return Sorted list of the currently {@link SubscriptionInfo} records available on the device. 1535 * <ul> 1536 * <li> 1537 * If null is returned the current state is unknown but if a {@link OnSubscriptionsChangedListener} 1538 * has been registered {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be 1539 * invoked in the future. 1540 * </li> 1541 * <li> 1542 * If the list is empty then there are no {@link SubscriptionInfo} records currently available. 1543 * </li> 1544 * <li> 1545 * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} 1546 * then by {@link SubscriptionInfo#getSubscriptionId}. 1547 * </li> 1548 * </ul> 1549 */ 1550 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 1551 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) getActiveSubscriptionInfoList()1552 public List<SubscriptionInfo> getActiveSubscriptionInfoList() { 1553 return getActiveSubscriptionInfoList(/* userVisibleonly */true); 1554 } 1555 1556 /** 1557 * Get both hidden and visible SubscriptionInfo(s) of the currently active SIM(s). 1558 * The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} 1559 * then by {@link SubscriptionInfo#getSubscriptionId}. 1560 * 1561 * Hidden subscriptions refer to those are not meant visible to the users. 1562 * For example, an opportunistic subscription that is grouped with other 1563 * subscriptions should remain invisible to users as they are only functionally 1564 * supplementary to primary ones. 1565 * 1566 * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 1567 * or that the calling app has carrier privileges (see 1568 * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible 1569 * to the calling app are returned. 1570 * 1571 * @return Sorted list of the currently available {@link SubscriptionInfo} 1572 * records on the device. 1573 * This is similar to {@link #getActiveSubscriptionInfoList} except that it will return 1574 * both active and hidden SubscriptionInfos. 1575 * 1576 */ getCompleteActiveSubscriptionInfoList()1577 public @NonNull List<SubscriptionInfo> getCompleteActiveSubscriptionInfoList() { 1578 List<SubscriptionInfo> completeList = getActiveSubscriptionInfoList( 1579 /* userVisibleonly */false); 1580 if (completeList == null) { 1581 completeList = new ArrayList<>(); 1582 } 1583 return completeList; 1584 } 1585 1586 /** 1587 * This is similar to {@link #getActiveSubscriptionInfoList()}, but if userVisibleOnly 1588 * is true, it will filter out the hidden subscriptions. 1589 * 1590 * @hide 1591 */ getActiveSubscriptionInfoList(boolean userVisibleOnly)1592 public @Nullable List<SubscriptionInfo> getActiveSubscriptionInfoList(boolean userVisibleOnly) { 1593 List<SubscriptionInfo> activeList = null; 1594 1595 try { 1596 ISub iSub = TelephonyManager.getSubscriptionService(); 1597 if (iSub != null) { 1598 activeList = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName(), 1599 mContext.getAttributionTag()); 1600 } 1601 } catch (RemoteException ex) { 1602 // ignore it 1603 } 1604 1605 if (!userVisibleOnly || activeList == null) { 1606 return activeList; 1607 } else { 1608 return activeList.stream().filter(subInfo -> isSubscriptionVisible(subInfo)) 1609 .collect(Collectors.toList()); 1610 } 1611 } 1612 1613 /** 1614 * Gets the SubscriptionInfo(s) of all available subscriptions, if any. 1615 * 1616 * <p>Available subscriptions include active ones (those with a non-negative 1617 * {@link SubscriptionInfo#getSimSlotIndex()}) as well as inactive but installed embedded 1618 * subscriptions. 1619 * 1620 * <p>The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by 1621 * {@link SubscriptionInfo#getSubscriptionId}. 1622 * 1623 * @return Sorted list of the current {@link SubscriptionInfo} records available on the 1624 * device. 1625 * <ul> 1626 * <li> 1627 * If null is returned the current state is unknown but if a 1628 * {@link OnSubscriptionsChangedListener} has been registered 1629 * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be invoked in the future. 1630 * <li> 1631 * If the list is empty then there are no {@link SubscriptionInfo} records currently available. 1632 * <li> 1633 * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} 1634 * then by {@link SubscriptionInfo#getSubscriptionId}. 1635 * </ul> 1636 * 1637 * <p> 1638 * Permissions android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE is required 1639 * for #getAvailableSubscriptionInfoList to be invoked. 1640 * @hide 1641 */ 1642 @SystemApi getAvailableSubscriptionInfoList()1643 public List<SubscriptionInfo> getAvailableSubscriptionInfoList() { 1644 List<SubscriptionInfo> result = null; 1645 1646 try { 1647 ISub iSub = TelephonyManager.getSubscriptionService(); 1648 if (iSub != null) { 1649 result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName(), 1650 mContext.getAttributionTag()); 1651 } 1652 } catch (RemoteException ex) { 1653 // ignore it 1654 } 1655 return result; 1656 } 1657 1658 /** 1659 * Gets the SubscriptionInfo(s) of all embedded subscriptions accessible to the calling app, if 1660 * any. 1661 * 1662 * <p>Only those subscriptions for which the calling app has carrier privileges per the 1663 * subscription metadata, if any, will be included in the returned list. 1664 * 1665 * <p>The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by 1666 * {@link SubscriptionInfo#getSubscriptionId}. 1667 * 1668 * @return Sorted list of the current embedded {@link SubscriptionInfo} records available on the 1669 * device which are accessible to the caller. 1670 * <ul> 1671 * <li> 1672 * If null is returned the current state is unknown but if a 1673 * {@link OnSubscriptionsChangedListener} has been registered 1674 * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be invoked in the future. 1675 * <li> 1676 * If the list is empty then there are no {@link SubscriptionInfo} records currently available. 1677 * <li> 1678 * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} 1679 * then by {@link SubscriptionInfo#getSubscriptionId}. 1680 * </ul> 1681 */ getAccessibleSubscriptionInfoList()1682 public List<SubscriptionInfo> getAccessibleSubscriptionInfoList() { 1683 List<SubscriptionInfo> result = null; 1684 1685 try { 1686 ISub iSub = TelephonyManager.getSubscriptionService(); 1687 if (iSub != null) { 1688 result = iSub.getAccessibleSubscriptionInfoList(mContext.getOpPackageName()); 1689 } 1690 } catch (RemoteException ex) { 1691 // ignore it 1692 } 1693 return result; 1694 } 1695 1696 /** 1697 * Request a refresh of the platform cache of profile information for the eUICC which 1698 * corresponds to the card ID returned by {@link TelephonyManager#getCardIdForDefaultEuicc()}. 1699 * 1700 * <p>Should be called by the EuiccService implementation whenever this information changes due 1701 * to an operation done outside the scope of a request initiated by the platform to the 1702 * EuiccService. There is no need to refresh for downloads, deletes, or other operations that 1703 * were made through the EuiccService. 1704 * 1705 * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. 1706 * 1707 * @see {@link TelephonyManager#getCardIdForDefaultEuicc()} for more information on the card ID. 1708 * 1709 * @hide 1710 */ 1711 @SystemApi requestEmbeddedSubscriptionInfoListRefresh()1712 public void requestEmbeddedSubscriptionInfoListRefresh() { 1713 int cardId = TelephonyManager.from(mContext).getCardIdForDefaultEuicc(); 1714 try { 1715 ISub iSub = TelephonyManager.getSubscriptionService(); 1716 if (iSub != null) { 1717 iSub.requestEmbeddedSubscriptionInfoListRefresh(cardId); 1718 } 1719 } catch (RemoteException ex) { 1720 logd("requestEmbeddedSubscriptionInfoListFresh for card = " + cardId + " failed."); 1721 } 1722 } 1723 1724 /** 1725 * Request a refresh of the platform cache of profile information for the eUICC with the given 1726 * {@code cardId}. 1727 * 1728 * <p>Should be called by the EuiccService implementation whenever this information changes due 1729 * to an operation done outside the scope of a request initiated by the platform to the 1730 * EuiccService. There is no need to refresh for downloads, deletes, or other operations that 1731 * were made through the EuiccService. 1732 * 1733 * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. 1734 * 1735 * @param cardId the card ID of the eUICC. 1736 * 1737 * @see {@link TelephonyManager#getCardIdForDefaultEuicc()} for more information on the card ID. 1738 * 1739 * @hide 1740 */ 1741 @SystemApi requestEmbeddedSubscriptionInfoListRefresh(int cardId)1742 public void requestEmbeddedSubscriptionInfoListRefresh(int cardId) { 1743 try { 1744 ISub iSub = TelephonyManager.getSubscriptionService(); 1745 if (iSub != null) { 1746 iSub.requestEmbeddedSubscriptionInfoListRefresh(cardId); 1747 } 1748 } catch (RemoteException ex) { 1749 logd("requestEmbeddedSubscriptionInfoListFresh for card = " + cardId + " failed."); 1750 } 1751 } 1752 1753 /** 1754 * @return the count of all subscriptions in the database, this includes 1755 * all subscriptions that have been seen. 1756 * @hide 1757 */ 1758 @UnsupportedAppUsage getAllSubscriptionInfoCount()1759 public int getAllSubscriptionInfoCount() { 1760 if (VDBG) logd("[getAllSubscriptionInfoCount]+"); 1761 1762 int result = 0; 1763 1764 try { 1765 ISub iSub = TelephonyManager.getSubscriptionService(); 1766 if (iSub != null) { 1767 result = iSub.getAllSubInfoCount(mContext.getOpPackageName(), 1768 mContext.getAttributionTag()); 1769 } 1770 } catch (RemoteException ex) { 1771 // ignore it 1772 } 1773 1774 return result; 1775 } 1776 1777 /** 1778 * 1779 * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 1780 * or that the calling app has carrier privileges (see 1781 * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, the count will include 1782 * only those subscriptions accessible to the caller. 1783 * 1784 * @return the current number of active subscriptions. There is no guarantee the value 1785 * returned by this method will be the same as the length of the list returned by 1786 * {@link #getActiveSubscriptionInfoList}. 1787 */ 1788 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 1789 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) getActiveSubscriptionInfoCount()1790 public int getActiveSubscriptionInfoCount() { 1791 int result = 0; 1792 1793 try { 1794 ISub iSub = TelephonyManager.getSubscriptionService(); 1795 if (iSub != null) { 1796 result = iSub.getActiveSubInfoCount(mContext.getOpPackageName(), 1797 mContext.getAttributionTag()); 1798 } 1799 } catch (RemoteException ex) { 1800 // ignore it 1801 } 1802 1803 return result; 1804 } 1805 1806 /** 1807 * @return the maximum number of active subscriptions that will be returned by 1808 * {@link #getActiveSubscriptionInfoList} and the value returned by 1809 * {@link #getActiveSubscriptionInfoCount}. 1810 */ getActiveSubscriptionInfoCountMax()1811 public int getActiveSubscriptionInfoCountMax() { 1812 int result = 0; 1813 1814 try { 1815 ISub iSub = TelephonyManager.getSubscriptionService(); 1816 if (iSub != null) { 1817 result = iSub.getActiveSubInfoCountMax(); 1818 } 1819 } catch (RemoteException ex) { 1820 // ignore it 1821 } 1822 1823 return result; 1824 } 1825 1826 /** 1827 * Add a new SubscriptionInfo to SubscriptionInfo database if needed 1828 * @param iccId the IccId of the SIM card 1829 * @param slotIndex the slot which the SIM is inserted 1830 * @return the URL of the newly created row or the updated row 1831 * @hide 1832 */ addSubscriptionInfoRecord(String iccId, int slotIndex)1833 public Uri addSubscriptionInfoRecord(String iccId, int slotIndex) { 1834 if (VDBG) logd("[addSubscriptionInfoRecord]+ iccId:" + iccId + " slotIndex:" + slotIndex); 1835 if (iccId == null) { 1836 logd("[addSubscriptionInfoRecord]- null iccId"); 1837 } 1838 if (!isValidSlotIndex(slotIndex)) { 1839 logd("[addSubscriptionInfoRecord]- invalid slotIndex"); 1840 } 1841 1842 addSubscriptionInfoRecord(iccId, null, slotIndex, SUBSCRIPTION_TYPE_LOCAL_SIM); 1843 1844 // FIXME: Always returns null? 1845 return null; 1846 1847 } 1848 1849 /** 1850 * Add a new SubscriptionInfo to SubscriptionInfo database if needed 1851 * @param uniqueId This is the unique identifier for the subscription within the 1852 * specific subscription type. 1853 * @param displayName human-readable name of the device the subscription corresponds to. 1854 * @param slotIndex the slot assigned to this subscription. It is ignored for subscriptionType 1855 * of {@link #SUBSCRIPTION_TYPE_REMOTE_SIM}. 1856 * @param subscriptionType the {@link #SUBSCRIPTION_TYPE} 1857 * @hide 1858 */ addSubscriptionInfoRecord(String uniqueId, String displayName, int slotIndex, int subscriptionType)1859 public void addSubscriptionInfoRecord(String uniqueId, String displayName, int slotIndex, 1860 int subscriptionType) { 1861 if (VDBG) { 1862 logd("[addSubscriptionInfoRecord]+ uniqueId:" + uniqueId 1863 + ", displayName:" + displayName + ", slotIndex:" + slotIndex 1864 + ", subscriptionType: " + subscriptionType); 1865 } 1866 if (uniqueId == null) { 1867 Log.e(LOG_TAG, "[addSubscriptionInfoRecord]- uniqueId is null"); 1868 return; 1869 } 1870 1871 try { 1872 ISub iSub = TelephonyManager.getSubscriptionService(); 1873 if (iSub == null) { 1874 Log.e(LOG_TAG, "[addSubscriptionInfoRecord]- ISub service is null"); 1875 return; 1876 } 1877 int result = iSub.addSubInfo(uniqueId, displayName, slotIndex, subscriptionType); 1878 if (result < 0) { 1879 Log.e(LOG_TAG, "Adding of subscription didn't succeed: error = " + result); 1880 } else { 1881 logd("successfully added new subscription"); 1882 } 1883 } catch (RemoteException ex) { 1884 // ignore it 1885 } 1886 } 1887 1888 /** 1889 * Remove SubscriptionInfo record from the SubscriptionInfo database 1890 * @param uniqueId This is the unique identifier for the subscription within the specific 1891 * subscription type. 1892 * @param subscriptionType the {@link #SUBSCRIPTION_TYPE} 1893 * @hide 1894 */ removeSubscriptionInfoRecord(String uniqueId, int subscriptionType)1895 public void removeSubscriptionInfoRecord(String uniqueId, int subscriptionType) { 1896 if (VDBG) { 1897 logd("[removeSubscriptionInfoRecord]+ uniqueId:" + uniqueId 1898 + ", subscriptionType: " + subscriptionType); 1899 } 1900 if (uniqueId == null) { 1901 Log.e(LOG_TAG, "[addSubscriptionInfoRecord]- uniqueId is null"); 1902 return; 1903 } 1904 1905 try { 1906 ISub iSub = TelephonyManager.getSubscriptionService(); 1907 if (iSub == null) { 1908 Log.e(LOG_TAG, "[removeSubscriptionInfoRecord]- ISub service is null"); 1909 return; 1910 } 1911 int result = iSub.removeSubInfo(uniqueId, subscriptionType); 1912 if (result < 0) { 1913 Log.e(LOG_TAG, "Removal of subscription didn't succeed: error = " + result); 1914 } else { 1915 logd("successfully removed subscription"); 1916 } 1917 } catch (RemoteException ex) { 1918 // ignore it 1919 } 1920 } 1921 1922 /** 1923 * Set SIM icon tint color for subscription ID 1924 * @param tint the RGB value of icon tint color of the SIM 1925 * @param subId the unique Subscritpion ID in database 1926 * @return the number of records updated 1927 * @hide 1928 */ 1929 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setIconTint(@olorInt int tint, int subId)1930 public int setIconTint(@ColorInt int tint, int subId) { 1931 if (VDBG) logd("[setIconTint]+ tint:" + tint + " subId:" + subId); 1932 return setSubscriptionPropertyHelper(subId, "setIconTint", 1933 (iSub)-> iSub.setIconTint(tint, subId) 1934 ); 1935 } 1936 1937 /** 1938 * Set the display name for a subscription ID 1939 * @param displayName the display name of SIM card 1940 * @param subId the unique Subscritpion ID in database 1941 * @param nameSource SIM display name source 1942 * @return the number of records updated or < 0 if invalid subId 1943 * @hide 1944 */ 1945 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDisplayName(@ullable String displayName, int subId, @SimDisplayNameSource int nameSource)1946 public int setDisplayName(@Nullable String displayName, int subId, 1947 @SimDisplayNameSource int nameSource) { 1948 if (VDBG) { 1949 logd("[setDisplayName]+ displayName:" + displayName + " subId:" + subId 1950 + " nameSource:" + nameSource); 1951 } 1952 return setSubscriptionPropertyHelper(subId, "setDisplayName", 1953 (iSub)-> iSub.setDisplayNameUsingSrc(displayName, subId, nameSource) 1954 ); 1955 } 1956 1957 /** 1958 * Set phone number by subId 1959 * @param number the phone number of the SIM 1960 * @param subId the unique SubscriptionInfo index in database 1961 * @return the number of records updated 1962 * @hide 1963 */ 1964 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setDisplayNumber(String number, int subId)1965 public int setDisplayNumber(String number, int subId) { 1966 if (number == null) { 1967 logd("[setDisplayNumber]- fail"); 1968 return -1; 1969 } 1970 return setSubscriptionPropertyHelper(subId, "setDisplayNumber", 1971 (iSub)-> iSub.setDisplayNumber(number, subId) 1972 ); 1973 } 1974 1975 /** 1976 * Set data roaming by simInfo index 1977 * @param roaming 0:Don't allow data when roaming, 1:Allow data when roaming 1978 * @param subId the unique SubscriptionInfo index in database 1979 * @return the number of records updated 1980 * @hide 1981 */ 1982 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) setDataRoaming(int roaming, int subId)1983 public int setDataRoaming(int roaming, int subId) { 1984 if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId); 1985 return setSubscriptionPropertyHelper(subId, "setDataRoaming", 1986 (iSub)->iSub.setDataRoaming(roaming, subId) 1987 ); 1988 } 1989 1990 /** 1991 * Get slotIndex associated with the subscription. 1992 * 1993 * @param subscriptionId the unique SubscriptionInfo index in database 1994 * @return slotIndex as a positive integer or {@link #INVALID_SIM_SLOT_INDEX} if the supplied 1995 * subscriptionId doesn't have an associated slot index. 1996 */ getSlotIndex(int subscriptionId)1997 public static int getSlotIndex(int subscriptionId) { 1998 return sSlotIndexCache.query(subscriptionId); 1999 } 2000 2001 /** 2002 * Get an array of Subscription Ids for specified slot Index. 2003 * @param slotIndex the slot index. 2004 * @return subscription Ids or null if the given slot Index is not valid or there are no active 2005 * subscriptions in the slot. 2006 */ 2007 @Nullable getSubscriptionIds(int slotIndex)2008 public int[] getSubscriptionIds(int slotIndex) { 2009 return getSubId(slotIndex); 2010 } 2011 2012 /** @hide */ 2013 @UnsupportedAppUsage getSubId(int slotIndex)2014 public static int[] getSubId(int slotIndex) { 2015 if (!isValidSlotIndex(slotIndex)) { 2016 logd("[getSubId]- fail"); 2017 return null; 2018 } 2019 2020 int[] subId = null; 2021 2022 try { 2023 ISub iSub = TelephonyManager.getSubscriptionService(); 2024 if (iSub != null) { 2025 subId = iSub.getSubId(slotIndex); 2026 } 2027 } catch (RemoteException ex) { 2028 // ignore it 2029 } 2030 2031 return subId; 2032 } 2033 2034 /** @hide */ 2035 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) getPhoneId(int subId)2036 public static int getPhoneId(int subId) { 2037 return sPhoneIdCache.query(subId); 2038 } 2039 logd(String msg)2040 private static void logd(String msg) { 2041 Rlog.d(LOG_TAG, msg); 2042 } 2043 loge(String msg)2044 private static void loge(String msg) { 2045 Rlog.e(LOG_TAG, msg); 2046 } 2047 2048 /** 2049 * Returns the system's default subscription id. 2050 * 2051 * For a voice capable device, it will return getDefaultVoiceSubscriptionId. 2052 * For a data only device, it will return the getDefaultDataSubscriptionId. 2053 * May return an INVALID_SUBSCRIPTION_ID on error. 2054 * 2055 * @return the "system" default subscription id. 2056 */ getDefaultSubscriptionId()2057 public static int getDefaultSubscriptionId() { 2058 return sDefaultSubIdCache.query(null); 2059 } 2060 2061 /** 2062 * Returns the system's default voice subscription id. 2063 * 2064 * On a data only device or on error, will return INVALID_SUBSCRIPTION_ID. 2065 * 2066 * @return the default voice subscription Id. 2067 */ getDefaultVoiceSubscriptionId()2068 public static int getDefaultVoiceSubscriptionId() { 2069 int subId = INVALID_SUBSCRIPTION_ID; 2070 2071 try { 2072 ISub iSub = TelephonyManager.getSubscriptionService(); 2073 if (iSub != null) { 2074 subId = iSub.getDefaultVoiceSubId(); 2075 } 2076 } catch (RemoteException ex) { 2077 // ignore it 2078 } 2079 2080 if (VDBG) logd("getDefaultVoiceSubscriptionId, sub id = " + subId); 2081 return subId; 2082 } 2083 2084 /** 2085 * Sets the system's default voice subscription id. 2086 * 2087 * On a data-only device, this is a no-op. 2088 * 2089 * May throw a {@link RuntimeException} if the provided subscription id is equal to 2090 * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID} 2091 * 2092 * @param subscriptionId A valid subscription ID to set as the system default, or 2093 * {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} 2094 * @hide 2095 */ 2096 @SystemApi 2097 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDefaultVoiceSubscriptionId(int subscriptionId)2098 public void setDefaultVoiceSubscriptionId(int subscriptionId) { 2099 if (VDBG) logd("setDefaultVoiceSubId sub id = " + subscriptionId); 2100 try { 2101 ISub iSub = TelephonyManager.getSubscriptionService(); 2102 if (iSub != null) { 2103 iSub.setDefaultVoiceSubId(subscriptionId); 2104 } 2105 } catch (RemoteException ex) { 2106 // ignore it 2107 } 2108 } 2109 2110 /** 2111 * Same as {@link #setDefaultVoiceSubscriptionId(int)}, but preserved for backwards 2112 * compatibility. 2113 * @hide 2114 */ setDefaultVoiceSubId(int subId)2115 public void setDefaultVoiceSubId(int subId) { 2116 setDefaultVoiceSubscriptionId(subId); 2117 } 2118 2119 /** 2120 * Return the SubscriptionInfo for default voice subscription. 2121 * 2122 * Will return null on data only devices, or on error. 2123 * 2124 * @return the SubscriptionInfo for the default voice subscription. 2125 * @hide 2126 */ 2127 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getDefaultVoiceSubscriptionInfo()2128 public SubscriptionInfo getDefaultVoiceSubscriptionInfo() { 2129 return getActiveSubscriptionInfo(getDefaultVoiceSubscriptionId()); 2130 } 2131 2132 /** @hide */ 2133 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getDefaultVoicePhoneId()2134 public static int getDefaultVoicePhoneId() { 2135 return getPhoneId(getDefaultVoiceSubscriptionId()); 2136 } 2137 2138 /** 2139 * Returns the system's default SMS subscription id. 2140 * 2141 * On a data only device or on error, will return INVALID_SUBSCRIPTION_ID. 2142 * 2143 * @return the default SMS subscription Id. 2144 */ getDefaultSmsSubscriptionId()2145 public static int getDefaultSmsSubscriptionId() { 2146 return sDefaultSmsSubIdCache.query(null); 2147 } 2148 2149 /** 2150 * Set the subscription which will be used by default for SMS, with the subscription which 2151 * the supplied subscription ID corresponds to; or throw a RuntimeException if the supplied 2152 * subscription ID is not usable (check with {@link #isUsableSubscriptionId(int)}). 2153 * 2154 * @param subscriptionId the supplied subscription ID 2155 * 2156 * @hide 2157 */ 2158 @SystemApi 2159 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) setDefaultSmsSubId(int subscriptionId)2160 public void setDefaultSmsSubId(int subscriptionId) { 2161 if (VDBG) logd("setDefaultSmsSubId sub id = " + subscriptionId); 2162 try { 2163 ISub iSub = TelephonyManager.getSubscriptionService(); 2164 if (iSub != null) { 2165 iSub.setDefaultSmsSubId(subscriptionId); 2166 } 2167 } catch (RemoteException ex) { 2168 ex.rethrowFromSystemServer(); 2169 } 2170 } 2171 2172 /** 2173 * Return the SubscriptionInfo for default voice subscription. 2174 * 2175 * Will return null on data only devices, or on error. 2176 * 2177 * @return the SubscriptionInfo for the default SMS subscription. 2178 * @hide 2179 */ getDefaultSmsSubscriptionInfo()2180 public SubscriptionInfo getDefaultSmsSubscriptionInfo() { 2181 return getActiveSubscriptionInfo(getDefaultSmsSubscriptionId()); 2182 } 2183 2184 /** @hide */ 2185 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) getDefaultSmsPhoneId()2186 public int getDefaultSmsPhoneId() { 2187 return getPhoneId(getDefaultSmsSubscriptionId()); 2188 } 2189 2190 /** 2191 * Returns the system's default data subscription id. 2192 * 2193 * On a voice only device or on error, will return INVALID_SUBSCRIPTION_ID. 2194 * 2195 * @return the default data subscription Id. 2196 */ getDefaultDataSubscriptionId()2197 public static int getDefaultDataSubscriptionId() { 2198 return sDefaultDataSubIdCache.query(null); 2199 } 2200 2201 /** 2202 * Set the subscription which will be used by default for data, with the subscription which 2203 * the supplied subscription ID corresponds to; or throw a RuntimeException if the supplied 2204 * subscription ID is not usable (check with {@link #isUsableSubscriptionId(int)}). 2205 * 2206 * @param subscriptionId the supplied subscription ID 2207 * 2208 * @hide 2209 */ 2210 @SystemApi 2211 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) setDefaultDataSubId(int subscriptionId)2212 public void setDefaultDataSubId(int subscriptionId) { 2213 if (VDBG) logd("setDataSubscription sub id = " + subscriptionId); 2214 try { 2215 ISub iSub = TelephonyManager.getSubscriptionService(); 2216 if (iSub != null) { 2217 iSub.setDefaultDataSubId(subscriptionId); 2218 } 2219 } catch (RemoteException ex) { 2220 // ignore it 2221 } 2222 } 2223 2224 /** 2225 * Return the SubscriptionInfo for default data subscription. 2226 * 2227 * Will return null on voice only devices, or on error. 2228 * 2229 * @return the SubscriptionInfo for the default data subscription. 2230 * @hide 2231 */ 2232 @UnsupportedAppUsage getDefaultDataSubscriptionInfo()2233 public SubscriptionInfo getDefaultDataSubscriptionInfo() { 2234 return getActiveSubscriptionInfo(getDefaultDataSubscriptionId()); 2235 } 2236 2237 /** @hide */ 2238 @UnsupportedAppUsage getDefaultDataPhoneId()2239 public int getDefaultDataPhoneId() { 2240 return getPhoneId(getDefaultDataSubscriptionId()); 2241 } 2242 2243 /** @hide */ clearSubscriptionInfo()2244 public void clearSubscriptionInfo() { 2245 try { 2246 ISub iSub = TelephonyManager.getSubscriptionService(); 2247 if (iSub != null) { 2248 iSub.clearSubInfo(); 2249 } 2250 } catch (RemoteException ex) { 2251 // ignore it 2252 } 2253 2254 return; 2255 } 2256 2257 //FIXME this is vulnerable to race conditions 2258 /** @hide */ allDefaultsSelected()2259 public boolean allDefaultsSelected() { 2260 if (!isValidSubscriptionId(getDefaultDataSubscriptionId())) { 2261 return false; 2262 } 2263 if (!isValidSubscriptionId(getDefaultSmsSubscriptionId())) { 2264 return false; 2265 } 2266 if (!isValidSubscriptionId(getDefaultVoiceSubscriptionId())) { 2267 return false; 2268 } 2269 return true; 2270 } 2271 2272 /** 2273 * Check if the supplied subscription ID is valid. 2274 * 2275 * <p>A valid subscription ID is not necessarily an active subscription ID 2276 * (see {@link #isActiveSubscriptionId(int)}) or an usable subscription ID 2277 * (see {@link #isUsableSubscriptionId(int)}). Unless specifically noted, subscription 2278 * APIs work with a valid subscription ID. 2279 * 2280 * @param subscriptionId The subscription ID. 2281 * @return {@code true} if the supplied subscriptionId is valid; {@code false} otherwise. 2282 */ isValidSubscriptionId(int subscriptionId)2283 public static boolean isValidSubscriptionId(int subscriptionId) { 2284 return subscriptionId > INVALID_SUBSCRIPTION_ID; 2285 } 2286 2287 /** 2288 * Check if the supplied subscription ID is usable. 2289 * 2290 * <p>A usable subscription ID is a valid subscription ID, but not necessarily an active 2291 * subscription ID (see {@link #isActiveSubscriptionId(int)}). Some subscription APIs 2292 * require a usable subscription ID, and this is noted in their documentation; otherwise, a 2293 * subscription ID does not need to be usable for subscription functions, only valid. 2294 * 2295 * @param subscriptionId the subscription ID 2296 * @return {@code true} if the subscription ID is usable; {@code false} otherwise. 2297 */ isUsableSubscriptionId(int subscriptionId)2298 public static boolean isUsableSubscriptionId(int subscriptionId) { 2299 return isUsableSubIdValue(subscriptionId); 2300 } 2301 2302 /** 2303 * @return true if subId is an usable subId value else false. A 2304 * usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAULT_SUB_ID. 2305 * @hide 2306 */ 2307 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) isUsableSubIdValue(int subId)2308 public static boolean isUsableSubIdValue(int subId) { 2309 return subId >= MIN_SUBSCRIPTION_ID_VALUE && subId <= MAX_SUBSCRIPTION_ID_VALUE; 2310 } 2311 2312 /** @hide */ 2313 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) isValidSlotIndex(int slotIndex)2314 public static boolean isValidSlotIndex(int slotIndex) { 2315 return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getActiveModemCount(); 2316 } 2317 2318 /** @hide */ 2319 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) isValidPhoneId(int phoneId)2320 public static boolean isValidPhoneId(int phoneId) { 2321 return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getActiveModemCount(); 2322 } 2323 2324 /** @hide */ 2325 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P) putPhoneIdAndSubIdExtra(Intent intent, int phoneId)2326 public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) { 2327 int[] subIds = SubscriptionManager.getSubId(phoneId); 2328 if (subIds != null && subIds.length > 0) { 2329 putPhoneIdAndSubIdExtra(intent, phoneId, subIds[0]); 2330 } else { 2331 logd("putPhoneIdAndSubIdExtra: no valid subs"); 2332 intent.putExtra(PhoneConstants.PHONE_KEY, phoneId); 2333 intent.putExtra(EXTRA_SLOT_INDEX, phoneId); 2334 } 2335 } 2336 2337 /** @hide */ 2338 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId)2339 public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) { 2340 if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId); 2341 intent.putExtra(EXTRA_SLOT_INDEX, phoneId); 2342 intent.putExtra(PhoneConstants.PHONE_KEY, phoneId); 2343 putSubscriptionIdExtra(intent, subId); 2344 } 2345 2346 /** 2347 * Get visible subscription Id(s) of the currently active SIM(s). 2348 * 2349 * @return the list of subId's that are active, 2350 * is never null but the length may be 0. 2351 * @hide 2352 */ 2353 @SystemApi 2354 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getActiveSubscriptionIdList()2355 public @NonNull int[] getActiveSubscriptionIdList() { 2356 return getActiveSubscriptionIdList(/* visibleOnly */ true); 2357 } 2358 2359 /** 2360 * Get both hidden and visible subscription Id(s) of the currently active SIM(s). 2361 * 2362 * Hidden subscriptions refer to those are not meant visible to the users. 2363 * For example, an opportunistic subscription that is grouped with other 2364 * subscriptions should remain invisible to users as they are only functionally 2365 * supplementary to primary ones. 2366 * 2367 * @return the list of subId's that are active, 2368 * is never null but the length may be 0. 2369 * @hide 2370 */ 2371 @SystemApi 2372 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getCompleteActiveSubscriptionIdList()2373 public @NonNull int[] getCompleteActiveSubscriptionIdList() { 2374 return getActiveSubscriptionIdList(/* visibleOnly */false); 2375 } 2376 2377 /** 2378 * @return a non-null list of subId's that are active. 2379 * 2380 * @hide 2381 */ getActiveSubscriptionIdList(boolean visibleOnly)2382 public @NonNull int[] getActiveSubscriptionIdList(boolean visibleOnly) { 2383 try { 2384 ISub iSub = TelephonyManager.getSubscriptionService(); 2385 if (iSub != null) { 2386 int[] subId = iSub.getActiveSubIdList(visibleOnly); 2387 if (subId != null) return subId; 2388 } 2389 } catch (RemoteException ex) { 2390 // ignore it 2391 } 2392 2393 return new int[0]; 2394 } 2395 2396 /** 2397 * Returns true if the device is considered roaming on the current 2398 * network for a subscription. 2399 * <p> 2400 * Availability: Only when user registered to a network. 2401 * 2402 * @param subId The subscription ID 2403 * @return true if the network for the subscription is roaming, false otherwise 2404 */ isNetworkRoaming(int subId)2405 public boolean isNetworkRoaming(int subId) { 2406 final int phoneId = getPhoneId(subId); 2407 if (phoneId < 0) { 2408 // What else can we do? 2409 return false; 2410 } 2411 return TelephonyManager.getDefault().isNetworkRoaming(subId); 2412 } 2413 2414 /** 2415 * Returns a constant indicating the state of sim for the slot index. 2416 * 2417 * @param slotIndex 2418 * 2419 * {@See TelephonyManager#SIM_STATE_UNKNOWN} 2420 * {@See TelephonyManager#SIM_STATE_ABSENT} 2421 * {@See TelephonyManager#SIM_STATE_PIN_REQUIRED} 2422 * {@See TelephonyManager#SIM_STATE_PUK_REQUIRED} 2423 * {@See TelephonyManager#SIM_STATE_NETWORK_LOCKED} 2424 * {@See TelephonyManager#SIM_STATE_READY} 2425 * {@See TelephonyManager#SIM_STATE_NOT_READY} 2426 * {@See TelephonyManager#SIM_STATE_PERM_DISABLED} 2427 * {@See TelephonyManager#SIM_STATE_CARD_IO_ERROR} 2428 * 2429 * {@hide} 2430 */ getSimStateForSlotIndex(int slotIndex)2431 public static int getSimStateForSlotIndex(int slotIndex) { 2432 int simState = TelephonyManager.SIM_STATE_UNKNOWN; 2433 2434 try { 2435 ISub iSub = TelephonyManager.getSubscriptionService(); 2436 if (iSub != null) { 2437 simState = iSub.getSimStateForSlotIndex(slotIndex); 2438 } 2439 } catch (RemoteException ex) { 2440 } 2441 2442 return simState; 2443 } 2444 2445 /** 2446 * Store properties associated with SubscriptionInfo in database 2447 * @param subId Subscription Id of Subscription 2448 * @param propKey Column name in database associated with SubscriptionInfo 2449 * @param propValue Value to store in DB for particular subId & column name 2450 * @hide 2451 */ setSubscriptionProperty(int subId, String propKey, String propValue)2452 public static void setSubscriptionProperty(int subId, String propKey, String propValue) { 2453 try { 2454 ISub iSub = TelephonyManager.getSubscriptionService(); 2455 if (iSub != null) { 2456 iSub.setSubscriptionProperty(subId, propKey, propValue); 2457 } 2458 } catch (RemoteException ex) { 2459 // ignore it 2460 } 2461 } 2462 2463 /** 2464 * Serialize list of contacts uri to string 2465 * @hide 2466 */ serializeUriLists(List<Uri> uris)2467 public static String serializeUriLists(List<Uri> uris) { 2468 List<String> contacts = new ArrayList<>(); 2469 for (Uri uri : uris) { 2470 contacts.add(uri.toString()); 2471 } 2472 try { 2473 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 2474 ObjectOutputStream oos = new ObjectOutputStream(bos); 2475 oos.writeObject(contacts); 2476 oos.flush(); 2477 return Base64.encodeToString(bos.toByteArray(), Base64.DEFAULT); 2478 } catch (IOException e) { 2479 logd("serializeUriLists IO exception"); 2480 } 2481 return ""; 2482 } 2483 2484 /** 2485 * Return list of contacts uri corresponding to query result. 2486 * @param subId Subscription Id of Subscription 2487 * @param propKey Column name in SubscriptionInfo database 2488 * @return list of contacts uri to be returned 2489 * @hide 2490 */ getContactsFromSubscriptionProperty(int subId, String propKey, Context context)2491 private static List<Uri> getContactsFromSubscriptionProperty(int subId, String propKey, 2492 Context context) { 2493 String result = getSubscriptionProperty(subId, propKey, context); 2494 if (result != null) { 2495 try { 2496 byte[] b = Base64.decode(result, Base64.DEFAULT); 2497 ByteArrayInputStream bis = new ByteArrayInputStream(b); 2498 ObjectInputStream ois = new ObjectInputStream(bis); 2499 List<String> contacts = ArrayList.class.cast(ois.readObject()); 2500 List<Uri> uris = new ArrayList<>(); 2501 for (String contact : contacts) { 2502 uris.add(Uri.parse(contact)); 2503 } 2504 return uris; 2505 } catch (IOException e) { 2506 logd("getContactsFromSubscriptionProperty IO exception"); 2507 } catch (ClassNotFoundException e) { 2508 logd("getContactsFromSubscriptionProperty ClassNotFound exception"); 2509 } 2510 } 2511 return new ArrayList<>(); 2512 } 2513 2514 /** 2515 * Store properties associated with SubscriptionInfo in database 2516 * @param subId Subscription Id of Subscription 2517 * @param propKey Column name in SubscriptionInfo database 2518 * @return Value associated with subId and propKey column in database 2519 * @hide 2520 */ getSubscriptionProperty(int subId, String propKey, Context context)2521 private static String getSubscriptionProperty(int subId, String propKey, 2522 Context context) { 2523 String resultValue = null; 2524 try { 2525 ISub iSub = TelephonyManager.getSubscriptionService(); 2526 if (iSub != null) { 2527 resultValue = iSub.getSubscriptionProperty(subId, propKey, 2528 context.getOpPackageName(), context.getAttributionTag()); 2529 } 2530 } catch (RemoteException ex) { 2531 // ignore it 2532 } 2533 return resultValue; 2534 } 2535 2536 /** 2537 * Returns boolean value corresponding to query result. 2538 * @param subId Subscription Id of Subscription 2539 * @param propKey Column name in SubscriptionInfo database 2540 * @param defValue Default boolean value to be returned 2541 * @return boolean result value to be returned 2542 * @hide 2543 */ getBooleanSubscriptionProperty(int subId, String propKey, boolean defValue, Context context)2544 public static boolean getBooleanSubscriptionProperty(int subId, String propKey, 2545 boolean defValue, Context context) { 2546 String result = getSubscriptionProperty(subId, propKey, context); 2547 if (result != null) { 2548 try { 2549 return Integer.parseInt(result) == 1; 2550 } catch (NumberFormatException err) { 2551 logd("getBooleanSubscriptionProperty NumberFormat exception"); 2552 } 2553 } 2554 return defValue; 2555 } 2556 2557 /** 2558 * Returns integer value corresponding to query result. 2559 * @param subId Subscription Id of Subscription 2560 * @param propKey Column name in SubscriptionInfo database 2561 * @param defValue Default integer value to be returned 2562 * @return integer result value to be returned 2563 * @hide 2564 */ getIntegerSubscriptionProperty(int subId, String propKey, int defValue, Context context)2565 public static int getIntegerSubscriptionProperty(int subId, String propKey, int defValue, 2566 Context context) { 2567 String result = getSubscriptionProperty(subId, propKey, context); 2568 if (result != null) { 2569 try { 2570 return Integer.parseInt(result); 2571 } catch (NumberFormatException err) { 2572 logd("getIntegerSubscriptionProperty NumberFormat exception"); 2573 } 2574 } 2575 return defValue; 2576 } 2577 2578 /** 2579 * Returns long value corresponding to query result. 2580 * @param subId Subscription Id of Subscription 2581 * @param propKey Column name in SubscriptionInfo database 2582 * @param defValue Default long value to be returned 2583 * @return long result value to be returned 2584 * @hide 2585 */ getLongSubscriptionProperty(int subId, String propKey, long defValue, Context context)2586 public static long getLongSubscriptionProperty(int subId, String propKey, long defValue, 2587 Context context) { 2588 String result = getSubscriptionProperty(subId, propKey, context); 2589 if (result != null) { 2590 try { 2591 return Long.parseLong(result); 2592 } catch (NumberFormatException err) { 2593 logd("getLongSubscriptionProperty NumberFormat exception"); 2594 } 2595 } 2596 return defValue; 2597 } 2598 2599 /** 2600 * Returns the {@link Resources} from the given {@link Context} for the MCC/MNC associated with 2601 * the subscription. If the subscription ID is invalid, the base resources are returned instead. 2602 * 2603 * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 2604 * 2605 * @param context Context object 2606 * @param subId Subscription Id of Subscription whose resources are required 2607 * @return Resources associated with Subscription. 2608 * @hide 2609 */ 2610 @NonNull 2611 @SystemApi getResourcesForSubId(@onNull Context context, int subId)2612 public static Resources getResourcesForSubId(@NonNull Context context, int subId) { 2613 return getResourcesForSubId(context, subId, false); 2614 } 2615 2616 /** 2617 * Returns the resources associated with Subscription. 2618 * @param context Context object 2619 * @param subId Subscription Id of Subscription who's resources are required 2620 * @param useRootLocale if root locale should be used. Localized locale is used if false. 2621 * @return Resources associated with Subscription. 2622 * @hide 2623 */ 2624 @NonNull getResourcesForSubId(Context context, int subId, boolean useRootLocale)2625 public static Resources getResourcesForSubId(Context context, int subId, 2626 boolean useRootLocale) { 2627 // Check if resources for this context and subId already exist in the resource cache. 2628 // Resources that use the root locale are not cached. 2629 Pair<Context, Integer> cacheKey = null; 2630 if (isValidSubscriptionId(subId) && !useRootLocale) { 2631 cacheKey = Pair.create(context, subId); 2632 if (sResourcesCache.containsKey(cacheKey)) { 2633 // Cache hit. Use cached Resources. 2634 return sResourcesCache.get(cacheKey); 2635 } 2636 } 2637 2638 final SubscriptionInfo subInfo = 2639 SubscriptionManager.from(context).getActiveSubscriptionInfo(subId); 2640 2641 Configuration overrideConfig = new Configuration(); 2642 if (subInfo != null) { 2643 overrideConfig.mcc = subInfo.getMcc(); 2644 overrideConfig.mnc = subInfo.getMnc(); 2645 if (overrideConfig.mnc == 0) { 2646 overrideConfig.mnc = Configuration.MNC_ZERO; 2647 cacheKey = null; 2648 } 2649 } 2650 2651 if (useRootLocale) { 2652 overrideConfig.setLocale(Locale.ROOT); 2653 } 2654 2655 // Create new context with new configuration so that we can avoid modifying the passed in 2656 // context. 2657 // Note that if the original context configuration changes, the resources here will also 2658 // change for all values except those overridden by newConfig (e.g. if the device has an 2659 // orientation change). 2660 Context newContext = context.createConfigurationContext(overrideConfig); 2661 Resources res = newContext.getResources(); 2662 2663 if (cacheKey != null) { 2664 // Save the newly created Resources in the resource cache. 2665 sResourcesCache.put(cacheKey, res); 2666 } 2667 return res; 2668 } 2669 2670 /** 2671 * Checks if the supplied subscription ID corresponds to a subscription which is actively in 2672 * use on the device. An active subscription ID is a valid and usable subscription ID. 2673 * 2674 * @param subscriptionId the subscription ID. 2675 * @return {@code true} if the supplied subscription ID corresponds to an active subscription; 2676 * {@code false} if it does not correspond to an active subscription; or throw a 2677 * SecurityException if the caller hasn't got the right permission. 2678 */ 2679 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) isActiveSubscriptionId(int subscriptionId)2680 public boolean isActiveSubscriptionId(int subscriptionId) { 2681 return isActiveSubId(subscriptionId); 2682 } 2683 2684 /** 2685 * @return true if the sub ID is active. i.e. The sub ID corresponds to a known subscription 2686 * and the SIM providing the subscription is present in a slot and in "LOADED" state. 2687 * @hide 2688 */ 2689 @UnsupportedAppUsage isActiveSubId(int subId)2690 public boolean isActiveSubId(int subId) { 2691 try { 2692 ISub iSub = TelephonyManager.getSubscriptionService(); 2693 if (iSub != null) { 2694 return iSub.isActiveSubId(subId, mContext.getOpPackageName(), 2695 mContext.getAttributionTag()); 2696 } 2697 } catch (RemoteException ex) { 2698 } 2699 return false; 2700 } 2701 2702 /** 2703 * Get the description of the billing relationship plan between a carrier 2704 * and a specific subscriber. 2705 * <p> 2706 * This method is only accessible to the following narrow set of apps: 2707 * <ul> 2708 * <li>The carrier app for this subscriberId, as determined by 2709 * {@link TelephonyManager#hasCarrierPrivileges()}. 2710 * <li>The carrier app explicitly delegated access through 2711 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 2712 * </ul> 2713 * 2714 * @param subId the subscriber this relationship applies to 2715 * @throws SecurityException if the caller doesn't meet the requirements 2716 * outlined above. 2717 */ getSubscriptionPlans(int subId)2718 public @NonNull List<SubscriptionPlan> getSubscriptionPlans(int subId) { 2719 SubscriptionPlan[] subscriptionPlans = 2720 getNetworkPolicyManager().getSubscriptionPlans(subId, mContext.getOpPackageName()); 2721 return subscriptionPlans == null 2722 ? Collections.emptyList() : Arrays.asList(subscriptionPlans); 2723 } 2724 2725 /** 2726 * Set the description of the billing relationship plan between a carrier 2727 * and a specific subscriber. 2728 * <p> 2729 * This method is only accessible to the following narrow set of apps: 2730 * <ul> 2731 * <li>The carrier app for this subscriberId, as determined by 2732 * {@link TelephonyManager#hasCarrierPrivileges()}. 2733 * <li>The carrier app explicitly delegated access through 2734 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 2735 * </ul> 2736 * 2737 * @param subId the subscriber this relationship applies to. An empty list 2738 * may be sent to clear any existing plans. 2739 * @param plans the list of plans. The first plan is always the primary and 2740 * most important plan. Any additional plans are secondary and 2741 * may not be displayed or used by decision making logic. 2742 * @throws SecurityException if the caller doesn't meet the requirements 2743 * outlined above. 2744 * @throws IllegalArgumentException if plans don't meet the requirements 2745 * defined in {@link SubscriptionPlan}. 2746 */ setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans)2747 public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) { 2748 getNetworkPolicyManager().setSubscriptionPlans(subId, 2749 plans.toArray(new SubscriptionPlan[plans.size()]), mContext.getOpPackageName()); 2750 } 2751 2752 /** 2753 * Temporarily override the billing relationship plan between a carrier and 2754 * a specific subscriber to be considered unmetered. This will be reflected 2755 * to apps via {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED}. 2756 * <p> 2757 * This method is only accessible to the following narrow set of apps: 2758 * <ul> 2759 * <li>The carrier app for this subscriberId, as determined by 2760 * {@link TelephonyManager#hasCarrierPrivileges()}. 2761 * <li>The carrier app explicitly delegated access through 2762 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 2763 * </ul> 2764 * 2765 * @param subId the subscriber this override applies to. 2766 * @param overrideUnmetered set if the billing relationship should be 2767 * considered unmetered. 2768 * @param timeoutMillis the timeout after which the requested override will 2769 * be automatically cleared, or {@code 0} to leave in the 2770 * requested state until explicitly cleared, or the next reboot, 2771 * whichever happens first. 2772 * @throws SecurityException if the caller doesn't meet the requirements 2773 * outlined above. 2774 */ setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered, @DurationMillisLong long timeoutMillis)2775 public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered, 2776 @DurationMillisLong long timeoutMillis) { 2777 setSubscriptionOverrideUnmetered(subId, overrideUnmetered, 2778 TelephonyManager.getAllNetworkTypes(), timeoutMillis); 2779 } 2780 2781 /** 2782 * Temporarily override the billing relationship plan between a carrier and 2783 * a specific subscriber to be considered unmetered. This will be reflected 2784 * to apps via {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED}. 2785 * <p> 2786 * This method is only accessible to the following narrow set of apps: 2787 * <ul> 2788 * <li>The carrier app for this subscriberId, as determined by 2789 * {@link TelephonyManager#hasCarrierPrivileges()}. 2790 * <li>The carrier app explicitly delegated access through 2791 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 2792 * </ul> 2793 * 2794 * @param subId the subscriber this override applies to. 2795 * @param overrideUnmetered set if the billing relationship should be 2796 * considered unmetered. 2797 * @param networkTypes the network types this override applies to. If no 2798 * network types are specified, override values will be ignored. 2799 * {@see TelephonyManager#getAllNetworkTypes()} 2800 * @param timeoutMillis the timeout after which the requested override will 2801 * be automatically cleared, or {@code 0} to leave in the 2802 * requested state until explicitly cleared, or the next reboot, 2803 * whichever happens first. 2804 * @throws SecurityException if the caller doesn't meet the requirements 2805 * outlined above. 2806 */ setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered, @NonNull @Annotation.NetworkType int[] networkTypes, @DurationMillisLong long timeoutMillis)2807 public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered, 2808 @NonNull @Annotation.NetworkType int[] networkTypes, 2809 @DurationMillisLong long timeoutMillis) { 2810 final int overrideValue = overrideUnmetered ? SUBSCRIPTION_OVERRIDE_UNMETERED : 0; 2811 getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_UNMETERED, 2812 overrideValue, networkTypes, timeoutMillis, mContext.getOpPackageName()); 2813 } 2814 2815 /** 2816 * Temporarily override the billing relationship plan between a carrier and 2817 * a specific subscriber to be considered congested. This will cause the 2818 * device to delay certain network requests when possible, such as developer 2819 * jobs that are willing to run in a flexible time window. 2820 * <p> 2821 * This method is only accessible to the following narrow set of apps: 2822 * <ul> 2823 * <li>The carrier app for this subscriberId, as determined by 2824 * {@link TelephonyManager#hasCarrierPrivileges()}. 2825 * <li>The carrier app explicitly delegated access through 2826 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 2827 * </ul> 2828 * 2829 * @param subId the subscriber this override applies to. 2830 * @param overrideCongested set if the subscription should be considered 2831 * congested. 2832 * @param timeoutMillis the timeout after which the requested override will 2833 * be automatically cleared, or {@code 0} to leave in the 2834 * requested state until explicitly cleared, or the next reboot, 2835 * whichever happens first. 2836 * @throws SecurityException if the caller doesn't meet the requirements 2837 * outlined above. 2838 */ setSubscriptionOverrideCongested(int subId, boolean overrideCongested, @DurationMillisLong long timeoutMillis)2839 public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested, 2840 @DurationMillisLong long timeoutMillis) { 2841 setSubscriptionOverrideCongested(subId, overrideCongested, 2842 TelephonyManager.getAllNetworkTypes(), timeoutMillis); 2843 } 2844 2845 /** 2846 * Temporarily override the billing relationship plan between a carrier and 2847 * a specific subscriber to be considered congested. This will cause the 2848 * device to delay certain network requests when possible, such as developer 2849 * jobs that are willing to run in a flexible time window. 2850 * <p> 2851 * This method is only accessible to the following narrow set of apps: 2852 * <ul> 2853 * <li>The carrier app for this subscriberId, as determined by 2854 * {@link TelephonyManager#hasCarrierPrivileges()}. 2855 * <li>The carrier app explicitly delegated access through 2856 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 2857 * </ul> 2858 * 2859 * @param subId the subscriber this override applies to. 2860 * @param overrideCongested set if the subscription should be considered 2861 * congested. 2862 * @param networkTypes the network types this override applies to. If no 2863 * network types are specified, override values will be ignored. 2864 * {@see TelephonyManager#getAllNetworkTypes()} 2865 * @param timeoutMillis the timeout after which the requested override will 2866 * be automatically cleared, or {@code 0} to leave in the 2867 * requested state until explicitly cleared, or the next reboot, 2868 * whichever happens first. 2869 * @throws SecurityException if the caller doesn't meet the requirements 2870 * outlined above. 2871 */ setSubscriptionOverrideCongested(int subId, boolean overrideCongested, @NonNull @Annotation.NetworkType int[] networkTypes, @DurationMillisLong long timeoutMillis)2872 public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested, 2873 @NonNull @Annotation.NetworkType int[] networkTypes, 2874 @DurationMillisLong long timeoutMillis) { 2875 final int overrideValue = overrideCongested ? SUBSCRIPTION_OVERRIDE_CONGESTED : 0; 2876 getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_CONGESTED, 2877 overrideValue, networkTypes, timeoutMillis, mContext.getOpPackageName()); 2878 } 2879 2880 /** 2881 * Checks whether the app with the given context is authorized to manage the given subscription 2882 * according to its metadata. 2883 * 2884 * Only supported for embedded subscriptions (if {@link SubscriptionInfo#isEmbedded} returns 2885 * true). To check for permissions for non-embedded subscription as well, 2886 * {@see android.telephony.TelephonyManager#hasCarrierPrivileges}. 2887 * 2888 * @param info The subscription to check. 2889 * @return whether the app is authorized to manage this subscription per its metadata. 2890 */ canManageSubscription(SubscriptionInfo info)2891 public boolean canManageSubscription(SubscriptionInfo info) { 2892 return canManageSubscription(info, mContext.getPackageName()); 2893 } 2894 2895 /** 2896 * Checks whether the given app is authorized to manage the given subscription. An app can only 2897 * be authorized if it is included in the {@link android.telephony.UiccAccessRule} of the 2898 * {@link android.telephony.SubscriptionInfo} with the access status. 2899 * 2900 * Only supported for embedded subscriptions (if {@link SubscriptionInfo#isEmbedded} returns 2901 * true). To check for permissions for non-embedded subscription as well, 2902 * {@see android.telephony.TelephonyManager#hasCarrierPrivileges}. 2903 * 2904 * @param info The subscription to check. 2905 * @param packageName Package name of the app to check. 2906 * @return whether the app is authorized to manage this subscription per its access rules. 2907 * @hide 2908 */ 2909 @SystemApi canManageSubscription(@onNull SubscriptionInfo info, @NonNull String packageName)2910 public boolean canManageSubscription(@NonNull SubscriptionInfo info, 2911 @NonNull String packageName) { 2912 if (info == null || info.getAllAccessRules() == null || packageName == null) { 2913 return false; 2914 } 2915 PackageManager packageManager = mContext.getPackageManager(); 2916 PackageInfo packageInfo; 2917 try { 2918 packageInfo = packageManager.getPackageInfo(packageName, 2919 PackageManager.GET_SIGNING_CERTIFICATES); 2920 } catch (PackageManager.NameNotFoundException e) { 2921 logd("Unknown package: " + packageName); 2922 return false; 2923 } 2924 for (UiccAccessRule rule : info.getAllAccessRules()) { 2925 if (rule.getCarrierPrivilegeStatus(packageInfo) 2926 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 2927 return true; 2928 } 2929 } 2930 return false; 2931 } 2932 2933 /** 2934 * Set which subscription is preferred for cellular data. 2935 * It's also usually the subscription we set up internet connection on. 2936 * 2937 * PreferredData overwrites user setting of default data subscription. And it's used 2938 * by AlternativeNetworkService or carrier apps to switch primary and CBRS 2939 * subscription dynamically in multi-SIM devices. 2940 * 2941 * @param subId which subscription is preferred to for cellular data. If it's 2942 * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}, it means 2943 * it's unset and {@link SubscriptionManager#getDefaultDataSubscriptionId()} 2944 * is used to determine which modem is preferred. 2945 * @param needValidation whether Telephony will wait until the network is validated by 2946 * connectivity service before switching data to it. More details see 2947 * {@link NetworkCapabilities#NET_CAPABILITY_VALIDATED}. 2948 * @param executor The executor of where the callback will execute. 2949 * @param callback Callback will be triggered once it succeeds or failed. 2950 * Pass null if don't care about the result. 2951 * 2952 * @hide 2953 * 2954 */ 2955 @SystemApi 2956 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) setPreferredDataSubscriptionId(int subId, boolean needValidation, @Nullable @CallbackExecutor Executor executor, @Nullable @TelephonyManager.SetOpportunisticSubscriptionResult Consumer<Integer> callback)2957 public void setPreferredDataSubscriptionId(int subId, boolean needValidation, 2958 @Nullable @CallbackExecutor Executor executor, @Nullable 2959 @TelephonyManager.SetOpportunisticSubscriptionResult Consumer<Integer> callback) { 2960 if (VDBG) logd("[setPreferredDataSubscriptionId]+ subId:" + subId); 2961 try { 2962 ISub iSub = TelephonyManager.getSubscriptionService(); 2963 if (iSub == null) return; 2964 2965 ISetOpportunisticDataCallback callbackStub = new ISetOpportunisticDataCallback.Stub() { 2966 @Override 2967 public void onComplete(int result) { 2968 if (executor == null || callback == null) { 2969 return; 2970 } 2971 final long identity = Binder.clearCallingIdentity(); 2972 try { 2973 executor.execute(() -> { 2974 callback.accept(result); 2975 }); 2976 } finally { 2977 Binder.restoreCallingIdentity(identity); 2978 } 2979 } 2980 }; 2981 iSub.setPreferredDataSubscriptionId(subId, needValidation, callbackStub); 2982 } catch (RemoteException ex) { 2983 // ignore it 2984 } 2985 } 2986 2987 /** 2988 * Get which subscription is preferred for cellular data. 2989 * It's also usually the subscription we set up internet connection on. 2990 * 2991 * PreferredData overwrites user setting of default data subscription. And it's used 2992 * by AlternativeNetworkService or carrier apps to switch primary and CBRS 2993 * subscription dynamically in multi-SIM devices. 2994 * 2995 * @return preferred subscription id for cellular data. {@link DEFAULT_SUBSCRIPTION_ID} if 2996 * there's no prefered subscription. 2997 * 2998 * @hide 2999 * 3000 */ 3001 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getPreferredDataSubscriptionId()3002 public int getPreferredDataSubscriptionId() { 3003 int preferredSubId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID; 3004 try { 3005 ISub iSub = TelephonyManager.getSubscriptionService(); 3006 if (iSub != null) { 3007 preferredSubId = iSub.getPreferredDataSubscriptionId(); 3008 } 3009 } catch (RemoteException ex) { 3010 // ignore it 3011 } 3012 3013 return preferredSubId; 3014 } 3015 3016 /** 3017 * Return opportunistic subscriptions that can be visible to the caller. 3018 * Opportunistic subscriptions are for opportunistic networks, which are cellular 3019 * networks with limited capabilities and coverage, for example, CBRS. 3020 * 3021 * <p>Requires Permission: 3022 * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 3023 * or that the calling app has carrier privileges (see 3024 * {@link TelephonyManager#hasCarrierPrivileges}). 3025 * 3026 * @return the list of opportunistic subscription info. If none exists, an empty list. 3027 */ 3028 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 3029 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) getOpportunisticSubscriptions()3030 public @NonNull List<SubscriptionInfo> getOpportunisticSubscriptions() { 3031 String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 3032 String contextAttributionTag = mContext != null ? mContext.getAttributionTag() : null; 3033 List<SubscriptionInfo> subInfoList = null; 3034 3035 try { 3036 ISub iSub = TelephonyManager.getSubscriptionService(); 3037 if (iSub != null) { 3038 subInfoList = iSub.getOpportunisticSubscriptions(contextPkg, 3039 contextAttributionTag); 3040 } 3041 } catch (RemoteException ex) { 3042 // ignore it 3043 } 3044 3045 if (subInfoList == null) { 3046 subInfoList = new ArrayList<>(); 3047 } 3048 3049 return subInfoList; 3050 } 3051 3052 /** 3053 * Switch to a certain subscription 3054 * 3055 * @param subId sub id 3056 * @param callbackIntent pending intent that will be sent after operation is done. 3057 */ 3058 @RequiresPermission(android.Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) switchToSubscription(int subId, @NonNull PendingIntent callbackIntent)3059 public void switchToSubscription(int subId, @NonNull PendingIntent callbackIntent) { 3060 Preconditions.checkNotNull(callbackIntent, "callbackIntent cannot be null"); 3061 EuiccManager euiccManager = new EuiccManager(mContext); 3062 euiccManager.switchToSubscription(subId, callbackIntent); 3063 } 3064 3065 /** 3066 * Set whether a subscription is opportunistic, that is, whether the network it connects 3067 * to has limited coverage. For example, CBRS. Setting a subscription opportunistic has 3068 * following impacts: 3069 * 1) Even if it's active, it will be dormant most of the time. The modem will not try 3070 * to scan or camp until it knows an available network is nearby to save power. 3071 * 2) Telephony relies on system app or carrier input to notify nearby available networks. 3072 * See {@link TelephonyManager#updateAvailableNetworks(List, Executor, Consumer)} 3073 * for more information. 3074 * 3) In multi-SIM devices, when the network is nearby and camped, system may automatically 3075 * switch internet data between it and default data subscription, based on carrier 3076 * recommendation and its signal strength and metered-ness, etc. 3077 * 3078 * 3079 * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} or carrier 3080 * privilege permission of the subscription. 3081 * 3082 * @param opportunistic whether it’s opportunistic subscription. 3083 * @param subId the unique SubscriptionInfo index in database 3084 * @return {@code true} if the operation is succeed, {@code false} otherwise. 3085 */ 3086 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 3087 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) setOpportunistic(boolean opportunistic, int subId)3088 public boolean setOpportunistic(boolean opportunistic, int subId) { 3089 if (VDBG) logd("[setOpportunistic]+ opportunistic:" + opportunistic + " subId:" + subId); 3090 return setSubscriptionPropertyHelper(subId, "setOpportunistic", 3091 (iSub)-> iSub.setOpportunistic( 3092 opportunistic, subId, mContext.getOpPackageName())) == 1; 3093 } 3094 3095 /** 3096 * Inform SubscriptionManager that subscriptions in the list are bundled 3097 * as a group. It can be multiple primary (non-opportunistic) subscriptions, 3098 * or one or more primary plus one or more opportunistic subscriptions. 3099 * 3100 * This API will always create a new immutable group and assign group UUID to all the 3101 * subscriptions, regardless whether they are in a group already or not. 3102 * 3103 * Grouped subscriptions will have below behaviors: 3104 * 1) They will share the same user settings. 3105 * 2) The opportunistic subscriptions in the group is considered invisible and will not 3106 * return from {@link #getActiveSubscriptionInfoList()}, unless caller has carrier 3107 * privilege permission of the subscriptions. 3108 * 3) The opportunistic subscriptions in the group can't be active by itself. If all other 3109 * non-opportunistic ones are deactivated (unplugged or disabled in Settings), 3110 * the opportunistic ones will be deactivated automatically. 3111 * 3112 * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} 3113 * permission or had carrier privilege permission on the subscriptions: 3114 * {@link TelephonyManager#hasCarrierPrivileges()} or 3115 * {@link #canManageSubscription(SubscriptionInfo)} 3116 * 3117 * @throws SecurityException if the caller doesn't meet the requirements 3118 * outlined above. 3119 * @throws IllegalArgumentException if any of the subscriptions in the list doesn't exist. 3120 * @throws IllegalStateException if Telephony service is in bad state. 3121 * 3122 * @param subIdList list of subId that will be in the same group 3123 * @return groupUUID a UUID assigned to the subscription group. 3124 * 3125 */ 3126 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 3127 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) createSubscriptionGroup(@onNull List<Integer> subIdList)3128 public @NonNull ParcelUuid createSubscriptionGroup(@NonNull List<Integer> subIdList) { 3129 Preconditions.checkNotNull(subIdList, "can't create group for null subId list"); 3130 String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 3131 if (VDBG) { 3132 logd("[createSubscriptionGroup]"); 3133 } 3134 3135 ParcelUuid groupUuid = null; 3136 int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray(); 3137 try { 3138 ISub iSub = TelephonyManager.getSubscriptionService(); 3139 if (iSub != null) { 3140 groupUuid = iSub.createSubscriptionGroup(subIdArray, pkgForDebug); 3141 } else { 3142 if (!isSystemProcess()) { 3143 throw new IllegalStateException("telephony service is null."); 3144 } 3145 } 3146 } catch (RemoteException ex) { 3147 loge("createSubscriptionGroup RemoteException " + ex); 3148 if (!isSystemProcess()) { 3149 ex.rethrowAsRuntimeException(); 3150 } 3151 } 3152 3153 return groupUuid; 3154 } 3155 3156 /** 3157 * Add a list of subscriptions into a group. 3158 * See {@link #createSubscriptionGroup(List)} for more details. 3159 * 3160 * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} 3161 * permission or had carrier privilege permission on the subscriptions: 3162 * {@link TelephonyManager#hasCarrierPrivileges()} or 3163 * {@link #canManageSubscription(SubscriptionInfo)} 3164 * 3165 * @throws SecurityException if the caller doesn't meet the requirements 3166 * outlined above. 3167 * @throws IllegalArgumentException if the some subscriptions in the list doesn't exist. 3168 * @throws IllegalStateException if Telephony service is in bad state. 3169 * 3170 * @param subIdList list of subId that need adding into the group 3171 * @param groupUuid the groupUuid the subscriptions are being added to. 3172 * 3173 */ 3174 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 3175 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) addSubscriptionsIntoGroup(@onNull List<Integer> subIdList, @NonNull ParcelUuid groupUuid)3176 public void addSubscriptionsIntoGroup(@NonNull List<Integer> subIdList, 3177 @NonNull ParcelUuid groupUuid) { 3178 Preconditions.checkNotNull(subIdList, "subIdList can't be null."); 3179 Preconditions.checkNotNull(groupUuid, "groupUuid can't be null."); 3180 String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 3181 if (VDBG) { 3182 logd("[addSubscriptionsIntoGroup]"); 3183 } 3184 3185 int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray(); 3186 3187 try { 3188 ISub iSub = TelephonyManager.getSubscriptionService(); 3189 if (iSub != null) { 3190 iSub.addSubscriptionsIntoGroup(subIdArray, groupUuid, pkgForDebug); 3191 } else { 3192 if (!isSystemProcess()) { 3193 throw new IllegalStateException("telephony service is null."); 3194 } 3195 } 3196 } catch (RemoteException ex) { 3197 loge("addSubscriptionsIntoGroup RemoteException " + ex); 3198 if (!isSystemProcess()) { 3199 ex.rethrowAsRuntimeException(); 3200 } 3201 } 3202 } 3203 isSystemProcess()3204 private boolean isSystemProcess() { 3205 return Process.myUid() == Process.SYSTEM_UID; 3206 } 3207 3208 /** 3209 * Remove a list of subscriptions from their subscription group. 3210 * See {@link #createSubscriptionGroup(List)} for more details. 3211 * 3212 * Caller will either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} 3213 * permission or had carrier privilege permission on the subscriptions: 3214 * {@link TelephonyManager#hasCarrierPrivileges()} or 3215 * {@link #canManageSubscription(SubscriptionInfo)} 3216 * 3217 * @throws SecurityException if the caller doesn't meet the requirements 3218 * outlined above. 3219 * @throws IllegalArgumentException if the some subscriptions in the list doesn't belong 3220 * the specified group. 3221 * @throws IllegalStateException if Telephony service is in bad state. 3222 * 3223 * @param subIdList list of subId that need removing from their groups. 3224 * 3225 */ 3226 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 3227 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) removeSubscriptionsFromGroup(@onNull List<Integer> subIdList, @NonNull ParcelUuid groupUuid)3228 public void removeSubscriptionsFromGroup(@NonNull List<Integer> subIdList, 3229 @NonNull ParcelUuid groupUuid) { 3230 Preconditions.checkNotNull(subIdList, "subIdList can't be null."); 3231 Preconditions.checkNotNull(groupUuid, "groupUuid can't be null."); 3232 String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 3233 if (VDBG) { 3234 logd("[removeSubscriptionsFromGroup]"); 3235 } 3236 3237 int[] subIdArray = subIdList.stream().mapToInt(i->i).toArray(); 3238 3239 try { 3240 ISub iSub = TelephonyManager.getSubscriptionService(); 3241 if (iSub != null) { 3242 iSub.removeSubscriptionsFromGroup(subIdArray, groupUuid, pkgForDebug); 3243 } else { 3244 if (!isSystemProcess()) { 3245 throw new IllegalStateException("telephony service is null."); 3246 } 3247 } 3248 } catch (RemoteException ex) { 3249 loge("removeSubscriptionsFromGroup RemoteException " + ex); 3250 if (!isSystemProcess()) { 3251 ex.rethrowAsRuntimeException(); 3252 } 3253 } 3254 } 3255 3256 /** 3257 * Get subscriptionInfo list of subscriptions that are in the same group of given subId. 3258 * See {@link #createSubscriptionGroup(List)} for more details. 3259 * 3260 * Caller will either have {@link android.Manifest.permission#READ_PHONE_STATE} 3261 * permission or had carrier privilege permission on the subscription. 3262 * {@link TelephonyManager#hasCarrierPrivileges()} 3263 * 3264 * @throws IllegalStateException if Telephony service is in bad state. 3265 * @throws SecurityException if the caller doesn't meet the requirements 3266 * outlined above. 3267 * 3268 * @param groupUuid of which list of subInfo will be returned. 3269 * @return list of subscriptionInfo that belong to the same group, including the given 3270 * subscription itself. It will return an empty list if no subscription belongs to the group. 3271 * 3272 */ 3273 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 3274 @RequiresPermission(Manifest.permission.READ_PHONE_STATE) getSubscriptionsInGroup(@onNull ParcelUuid groupUuid)3275 public @NonNull List<SubscriptionInfo> getSubscriptionsInGroup(@NonNull ParcelUuid groupUuid) { 3276 Preconditions.checkNotNull(groupUuid, "groupUuid can't be null"); 3277 String contextPkg = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 3278 String contextAttributionTag = mContext != null ? mContext.getAttributionTag() : null; 3279 if (VDBG) { 3280 logd("[getSubscriptionsInGroup]+ groupUuid:" + groupUuid); 3281 } 3282 3283 List<SubscriptionInfo> result = null; 3284 try { 3285 ISub iSub = TelephonyManager.getSubscriptionService(); 3286 if (iSub != null) { 3287 result = iSub.getSubscriptionsInGroup(groupUuid, contextPkg, 3288 contextAttributionTag); 3289 } else { 3290 if (!isSystemProcess()) { 3291 throw new IllegalStateException("telephony service is null."); 3292 } 3293 } 3294 } catch (RemoteException ex) { 3295 loge("removeSubscriptionsFromGroup RemoteException " + ex); 3296 if (!isSystemProcess()) { 3297 ex.rethrowAsRuntimeException(); 3298 } 3299 } 3300 3301 return result; 3302 } 3303 3304 /** 3305 * Whether a subscription is visible to API caller. If it's a bundled opportunistic 3306 * subscription, it should be hidden anywhere in Settings, dialer, status bar etc. 3307 * Exception is if caller owns carrier privilege, in which case they will 3308 * want to see their own hidden subscriptions. 3309 * 3310 * @param info the subscriptionInfo to check against. 3311 * @return true if this subscription should be visible to the API caller. 3312 * 3313 * @hide 3314 */ isSubscriptionVisible(SubscriptionInfo info)3315 public boolean isSubscriptionVisible(SubscriptionInfo info) { 3316 if (info == null) return false; 3317 // If subscription is NOT grouped opportunistic subscription, it's visible. 3318 if (info.getGroupUuid() == null || !info.isOpportunistic()) return true; 3319 3320 // If the caller is the carrier app and owns the subscription, it should be visible 3321 // to the caller. 3322 boolean hasCarrierPrivilegePermission = TelephonyManager.from(mContext) 3323 .hasCarrierPrivileges(info.getSubscriptionId()) 3324 || canManageSubscription(info); 3325 return hasCarrierPrivilegePermission; 3326 } 3327 3328 /** 3329 * Return a list of subscriptions that are available and visible to the user. 3330 * Used by Settings app to show a list of subscriptions for user to pick. 3331 * 3332 * <p> 3333 * Permissions android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE is required 3334 * for getSelectableSubscriptionInfoList to be invoked. 3335 * @return list of user selectable subscriptions. 3336 * 3337 * @hide 3338 */ getSelectableSubscriptionInfoList()3339 public @Nullable List<SubscriptionInfo> getSelectableSubscriptionInfoList() { 3340 List<SubscriptionInfo> availableList = getAvailableSubscriptionInfoList(); 3341 if (availableList == null) { 3342 return null; 3343 } else { 3344 // Multiple subscriptions in a group should only have one representative. 3345 // It should be the current active primary subscription if any, or any 3346 // primary subscription. 3347 List<SubscriptionInfo> selectableList = new ArrayList<>(); 3348 Map<ParcelUuid, SubscriptionInfo> groupMap = new HashMap<>(); 3349 3350 for (SubscriptionInfo info : availableList) { 3351 // Opportunistic subscriptions are considered invisible 3352 // to users so they should never be returned. 3353 if (!isSubscriptionVisible(info)) continue; 3354 3355 ParcelUuid groupUuid = info.getGroupUuid(); 3356 if (groupUuid == null) { 3357 // Doesn't belong to any group. Add in the list. 3358 selectableList.add(info); 3359 } else if (!groupMap.containsKey(groupUuid) 3360 || (groupMap.get(groupUuid).getSimSlotIndex() == INVALID_SIM_SLOT_INDEX 3361 && info.getSimSlotIndex() != INVALID_SIM_SLOT_INDEX)) { 3362 // If it belongs to a group that has never been recorded or it's the current 3363 // active subscription, add it in the list. 3364 selectableList.remove(groupMap.get(groupUuid)); 3365 selectableList.add(info); 3366 groupMap.put(groupUuid, info); 3367 } 3368 3369 } 3370 return selectableList; 3371 } 3372 } 3373 3374 /** 3375 * Enables or disables a subscription. This is currently used in the settings page. It will 3376 * fail and return false if operation is not supported or failed. 3377 * 3378 * To disable an active subscription on a physical (non-Euicc) SIM, 3379 * {@link #canDisablePhysicalSubscription} needs to be true. 3380 * 3381 * <p> 3382 * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required 3383 * 3384 * @param enable whether user is turning it on or off. 3385 * @param subscriptionId Subscription to be enabled or disabled. 3386 * It could be a eSIM or pSIM subscription. 3387 * 3388 * @return whether the operation is successful. 3389 * 3390 * @hide 3391 */ 3392 @SystemApi 3393 @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) setSubscriptionEnabled(int subscriptionId, boolean enable)3394 public boolean setSubscriptionEnabled(int subscriptionId, boolean enable) { 3395 if (VDBG) { 3396 logd("setSubscriptionActivated subId= " + subscriptionId + " enable " + enable); 3397 } 3398 try { 3399 ISub iSub = TelephonyManager.getSubscriptionService(); 3400 if (iSub != null) { 3401 return iSub.setSubscriptionEnabled(enable, subscriptionId); 3402 } 3403 } catch (RemoteException ex) { 3404 // ignore it 3405 } 3406 3407 return false; 3408 } 3409 3410 /** 3411 * Set uicc applications being enabled or disabled. 3412 * The value will be remembered on the subscription and will be applied whenever it's present. 3413 * If the subscription in currently present, it will also apply the setting to modem 3414 * immediately (the setting in the modem will not change until the modem receives and responds 3415 * to the request, but typically this should only take a few seconds. The user visible setting 3416 * available from SubscriptionInfo.areUiccApplicationsEnabled() will be updated 3417 * immediately.) 3418 * 3419 * Permissions android.Manifest.permission.MODIFY_PHONE_STATE is required 3420 * 3421 * @param subscriptionId which subscription to operate on. 3422 * @param enabled whether uicc applications are enabled or disabled. 3423 * @hide 3424 */ 3425 @SystemApi 3426 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setUiccApplicationsEnabled(int subscriptionId, boolean enabled)3427 public void setUiccApplicationsEnabled(int subscriptionId, boolean enabled) { 3428 if (VDBG) { 3429 logd("setUiccApplicationsEnabled subId= " + subscriptionId + " enable " + enabled); 3430 } 3431 try { 3432 ISub iSub = ISub.Stub.asInterface( 3433 TelephonyFrameworkInitializer 3434 .getTelephonyServiceManager() 3435 .getSubscriptionServiceRegisterer() 3436 .get()); 3437 if (iSub != null) { 3438 iSub.setUiccApplicationsEnabled(enabled, subscriptionId); 3439 } 3440 } catch (RemoteException ex) { 3441 // ignore it 3442 } 3443 } 3444 3445 /** 3446 * Whether it's supported to disable / re-enable a subscription on a physical (non-euicc) SIM. 3447 * 3448 * Physical SIM refers non-euicc, or aka non-programmable SIM. 3449 * 3450 * It provides whether a physical SIM card can be disabled without taking it out, which is done 3451 * via {@link #setSubscriptionEnabled(int, boolean)} API. 3452 * 3453 * Requires Permission: READ_PRIVILEGED_PHONE_STATE. 3454 * 3455 * @return whether can disable subscriptions on physical SIMs. 3456 * 3457 * @hide 3458 */ 3459 @SystemApi 3460 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) canDisablePhysicalSubscription()3461 public boolean canDisablePhysicalSubscription() { 3462 if (VDBG) { 3463 logd("canDisablePhysicalSubscription"); 3464 } 3465 try { 3466 ISub iSub = ISub.Stub.asInterface( 3467 TelephonyFrameworkInitializer 3468 .getTelephonyServiceManager() 3469 .getSubscriptionServiceRegisterer() 3470 .get()); 3471 if (iSub != null) { 3472 return iSub.canDisablePhysicalSubscription(); 3473 } 3474 } catch (RemoteException ex) { 3475 // ignore it 3476 } 3477 3478 return false; 3479 } 3480 3481 /** 3482 * DO NOT USE. 3483 * This API is designed for features that are not finished at this point. Do not call this API. 3484 * @hide 3485 * TODO b/135547512: further clean up 3486 */ 3487 @SystemApi 3488 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) isSubscriptionEnabled(int subscriptionId)3489 public boolean isSubscriptionEnabled(int subscriptionId) { 3490 try { 3491 ISub iSub = TelephonyManager.getSubscriptionService(); 3492 if (iSub != null) { 3493 return iSub.isSubscriptionEnabled(subscriptionId); 3494 } 3495 } catch (RemoteException ex) { 3496 // ignore it 3497 } 3498 3499 return false; 3500 } 3501 3502 /** 3503 * Set the device to device status sharing user preference for a subscription ID. The setting 3504 * app uses this method to indicate with whom they wish to share device to device status 3505 * information. 3506 * @param sharing the status sharing preference 3507 * @param subscriptionId the unique Subscription ID in database 3508 */ 3509 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDeviceToDeviceStatusSharingPreference(int subscriptionId, @DeviceToDeviceStatusSharingPreference int sharing)3510 public void setDeviceToDeviceStatusSharingPreference(int subscriptionId, 3511 @DeviceToDeviceStatusSharingPreference int sharing) { 3512 if (VDBG) { 3513 logd("[setDeviceToDeviceStatusSharing] + sharing: " + sharing + " subId: " 3514 + subscriptionId); 3515 } 3516 setSubscriptionPropertyHelper(subscriptionId, "setDeviceToDeviceSharingStatus", 3517 (iSub)->iSub.setDeviceToDeviceStatusSharing(sharing, subscriptionId)); 3518 } 3519 3520 /** 3521 * Returns the user-chosen device to device status sharing preference 3522 * @param subscriptionId Subscription id of subscription 3523 * @return The device to device status sharing preference 3524 */ getDeviceToDeviceStatusSharingPreference( int subscriptionId)3525 public @DeviceToDeviceStatusSharingPreference int getDeviceToDeviceStatusSharingPreference( 3526 int subscriptionId) { 3527 if (VDBG) { 3528 logd("[getDeviceToDeviceStatusSharing] + subId: " + subscriptionId); 3529 } 3530 return getIntegerSubscriptionProperty(subscriptionId, D2D_STATUS_SHARING, 3531 D2D_SHARING_DISABLED, mContext); 3532 } 3533 3534 /** 3535 * Set the list of contacts that allow device to device status sharing for a subscription ID. 3536 * The setting app uses this method to indicate with whom they wish to share device to device 3537 * status information. 3538 * @param contacts The list of contacts that allow device to device status sharing 3539 * @param subscriptionId The unique Subscription ID in database 3540 */ 3541 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDeviceToDeviceStatusSharingContacts(int subscriptionId, @NonNull List<Uri> contacts)3542 public void setDeviceToDeviceStatusSharingContacts(int subscriptionId, 3543 @NonNull List<Uri> contacts) { 3544 String contactString = serializeUriLists(contacts); 3545 if (VDBG) { 3546 logd("[setDeviceToDeviceStatusSharingContacts] + contacts: " + contactString 3547 + " subId: " + subscriptionId); 3548 } 3549 setSubscriptionPropertyHelper(subscriptionId, "setDeviceToDeviceSharingStatus", 3550 (iSub)->iSub.setDeviceToDeviceStatusSharingContacts(serializeUriLists(contacts), 3551 subscriptionId)); 3552 } 3553 3554 /** 3555 * Returns the list of contacts that allow device to device status sharing. 3556 * @param subscriptionId Subscription id of subscription 3557 * @return The list of contacts that allow device to device status sharing 3558 */ getDeviceToDeviceStatusSharingContacts( int subscriptionId)3559 public @NonNull List<Uri> getDeviceToDeviceStatusSharingContacts( 3560 int subscriptionId) { 3561 if (VDBG) { 3562 logd("[getDeviceToDeviceStatusSharingContacts] + subId: " + subscriptionId); 3563 } 3564 return getContactsFromSubscriptionProperty(subscriptionId, 3565 D2D_STATUS_SHARING_SELECTED_CONTACTS, mContext); 3566 } 3567 3568 /** 3569 * DO NOT USE. 3570 * This API is designed for features that are not finished at this point. Do not call this API. 3571 * @hide 3572 * TODO b/135547512: further clean up 3573 */ 3574 @SystemApi 3575 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getEnabledSubscriptionId(int slotIndex)3576 public int getEnabledSubscriptionId(int slotIndex) { 3577 int subId = INVALID_SUBSCRIPTION_ID; 3578 3579 try { 3580 ISub iSub = TelephonyManager.getSubscriptionService(); 3581 if (iSub != null) { 3582 subId = iSub.getEnabledSubscriptionId(slotIndex); 3583 } 3584 } catch (RemoteException ex) { 3585 // ignore it 3586 } 3587 3588 if (VDBG) logd("getEnabledSubscriptionId, subId = " + subId); 3589 return subId; 3590 } 3591 3592 private interface CallISubMethodHelper { callMethod(ISub iSub)3593 int callMethod(ISub iSub) throws RemoteException; 3594 } 3595 setSubscriptionPropertyHelper(int subId, String methodName, CallISubMethodHelper helper)3596 private int setSubscriptionPropertyHelper(int subId, String methodName, 3597 CallISubMethodHelper helper) { 3598 if (!isValidSubscriptionId(subId)) { 3599 logd("[" + methodName + "]" + "- fail"); 3600 return -1; 3601 } 3602 3603 int result = 0; 3604 3605 try { 3606 ISub iSub = TelephonyManager.getSubscriptionService(); 3607 if (iSub != null) { 3608 result = helper.callMethod(iSub); 3609 } 3610 } catch (RemoteException ex) { 3611 // ignore it 3612 } 3613 3614 return result; 3615 } 3616 3617 /** 3618 * Get active data subscription id. Active data subscription refers to the subscription 3619 * currently chosen to provide cellular internet connection to the user. This may be 3620 * different from getDefaultDataSubscriptionId(). Eg. Opportunistics data 3621 * 3622 * See {@link PhoneStateListener#onActiveDataSubscriptionIdChanged(int)} for the details. 3623 * 3624 * @return Active data subscription id if any is chosen, or 3625 * SubscriptionManager.INVALID_SUBSCRIPTION_ID if not. 3626 */ getActiveDataSubscriptionId()3627 public static int getActiveDataSubscriptionId() { 3628 return sActiveDataSubIdCache.query(null); 3629 } 3630 3631 /** 3632 * Helper method that puts a subscription id on an intent with the constants: 3633 * PhoneConstant.SUBSCRIPTION_KEY and SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX. 3634 * Both constants are used to support backwards compatibility. Once we know we got all places, 3635 * we can remove PhoneConstants.SUBSCRIPTION_KEY. 3636 * @param intent Intent to put sub id on. 3637 * @param subId SubscriptionId to put on intent. 3638 * 3639 * @hide 3640 */ putSubscriptionIdExtra(Intent intent, int subId)3641 public static void putSubscriptionIdExtra(Intent intent, int subId) { 3642 intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, subId); 3643 intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId); 3644 } 3645 3646 /** @hide */ invalidateDefaultSubIdCaches()3647 public static void invalidateDefaultSubIdCaches() { 3648 PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DEFAULT_SUB_ID_PROPERTY); 3649 } 3650 3651 /** @hide */ invalidateDefaultDataSubIdCaches()3652 public static void invalidateDefaultDataSubIdCaches() { 3653 PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DEFAULT_DATA_SUB_ID_PROPERTY); 3654 } 3655 3656 /** @hide */ invalidateDefaultSmsSubIdCaches()3657 public static void invalidateDefaultSmsSubIdCaches() { 3658 PropertyInvalidatedCache.invalidateCache(CACHE_KEY_DEFAULT_SMS_SUB_ID_PROPERTY); 3659 } 3660 3661 /** @hide */ invalidateActiveDataSubIdCaches()3662 public static void invalidateActiveDataSubIdCaches() { 3663 PropertyInvalidatedCache.invalidateCache(CACHE_KEY_ACTIVE_DATA_SUB_ID_PROPERTY); 3664 } 3665 3666 /** @hide */ invalidateSlotIndexCaches()3667 public static void invalidateSlotIndexCaches() { 3668 PropertyInvalidatedCache.invalidateCache(CACHE_KEY_SLOT_INDEX_PROPERTY); 3669 } 3670 3671 /** 3672 * Allows a test process to disable client-side caching operations. 3673 * 3674 * @hide 3675 */ disableCaching()3676 public static void disableCaching() { 3677 sDefaultSubIdCache.disableLocal(); 3678 sDefaultDataSubIdCache.disableLocal(); 3679 sActiveDataSubIdCache.disableLocal(); 3680 sDefaultSmsSubIdCache.disableLocal(); 3681 sSlotIndexCache.disableLocal(); 3682 sPhoneIdCache.disableLocal(); 3683 } 3684 3685 /** 3686 * Clears all process-local binder caches. 3687 * 3688 * @hide */ clearCaches()3689 public static void clearCaches() { 3690 sDefaultSubIdCache.clear(); 3691 sDefaultDataSubIdCache.clear(); 3692 sActiveDataSubIdCache.clear(); 3693 sDefaultSmsSubIdCache.clear(); 3694 sSlotIndexCache.clear(); 3695 sPhoneIdCache.clear(); 3696 } 3697 3698 /** 3699 * Called to retrieve SIM-specific settings data to be backed up. 3700 * 3701 * @return data in byte[] to be backed up. 3702 * 3703 * @hide 3704 */ 3705 @NonNull 3706 @SystemApi 3707 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getAllSimSpecificSettingsForBackup()3708 public byte[] getAllSimSpecificSettingsForBackup() { 3709 Bundle bundle = mContext.getContentResolver().call( 3710 SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, 3711 GET_SIM_SPECIFIC_SETTINGS_METHOD_NAME, null, null); 3712 return bundle.getByteArray(SubscriptionManager.KEY_SIM_SPECIFIC_SETTINGS_DATA); 3713 } 3714 3715 /** 3716 * Called to attempt to restore the backed up sim-specific configs to device for specific sim. 3717 * This will try to restore the data that was stored internally when {@link 3718 * #restoreAllSimSpecificSettingsFromBackup(byte[] data)} was called during setup wizard. 3719 * End result is SimInfoDB is modified to match any backed up configs for the requested 3720 * inserted sim. 3721 * 3722 * <p> 3723 * The {@link Uri} {@link #SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is notified if any SimInfoDB 3724 * entry is updated as the result of this method call. 3725 * 3726 * @param iccId of the sim that a restore is requested for. 3727 * 3728 * @hide 3729 */ 3730 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) restoreSimSpecificSettingsForIccIdFromBackup(@onNull String iccId)3731 public void restoreSimSpecificSettingsForIccIdFromBackup(@NonNull String iccId) { 3732 mContext.getContentResolver().call( 3733 SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, 3734 RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, 3735 iccId, null); 3736 } 3737 3738 /** 3739 * Called during setup wizard restore flow to attempt to restore the backed up sim-specific 3740 * configs to device for all existing SIMs in SimInfoDB. Internally, it will store the backup 3741 * data in an internal file. This file will persist on device for device's lifetime and will be 3742 * used later on when a SIM is inserted to restore that specific SIM's settings by calling 3743 * {@link #restoreSimSpecificSettingsForIccIdFromBackup(String iccId)}. End result is 3744 * SimInfoDB is modified to match any backed up configs for the appropriate inserted SIMs. 3745 * 3746 * <p> 3747 * The {@link Uri} {@link #SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is notified if any SimInfoDB 3748 * entry is updated as the result of this method call. 3749 * 3750 * @param data with the sim specific configs to be backed up. 3751 * 3752 * @hide 3753 */ 3754 @SystemApi 3755 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) restoreAllSimSpecificSettingsFromBackup(@onNull byte[] data)3756 public void restoreAllSimSpecificSettingsFromBackup(@NonNull byte[] data) { 3757 Bundle bundle = new Bundle(); 3758 bundle.putByteArray(KEY_SIM_SPECIFIC_SETTINGS_DATA, data); 3759 mContext.getContentResolver().call( 3760 SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, 3761 RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, 3762 null, bundle); 3763 } 3764 } 3765