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