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