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