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.annotation.DurationMillisLong; 23 import android.annotation.NonNull; 24 import android.annotation.Nullable; 25 import android.annotation.RequiresPermission; 26 import android.annotation.SdkConstant; 27 import android.annotation.SdkConstant.SdkConstantType; 28 import android.annotation.SuppressAutoDoc; 29 import android.annotation.SystemApi; 30 import android.annotation.SystemService; 31 import android.app.BroadcastOptions; 32 import android.content.Context; 33 import android.content.Intent; 34 import android.content.pm.PackageInfo; 35 import android.content.pm.PackageManager; 36 import android.content.res.Configuration; 37 import android.content.res.Resources; 38 import android.net.INetworkPolicyManager; 39 import android.net.NetworkCapabilities; 40 import android.net.Uri; 41 import android.os.Handler; 42 import android.os.Looper; 43 import android.os.Message; 44 import android.os.RemoteException; 45 import android.os.ServiceManager; 46 import android.util.DisplayMetrics; 47 48 import com.android.internal.telephony.IOnSubscriptionsChangedListener; 49 import com.android.internal.telephony.ISub; 50 import com.android.internal.telephony.ITelephonyRegistry; 51 import com.android.internal.telephony.PhoneConstants; 52 53 import java.util.ArrayList; 54 import java.util.Arrays; 55 import java.util.Collections; 56 import java.util.List; 57 import java.util.concurrent.TimeUnit; 58 59 /** 60 * SubscriptionManager is the application interface to SubscriptionController 61 * and provides information about the current Telephony Subscriptions. 62 */ 63 @SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) 64 public class SubscriptionManager { 65 private static final String LOG_TAG = "SubscriptionManager"; 66 private static final boolean DBG = false; 67 private static final boolean VDBG = false; 68 69 /** An invalid subscription identifier */ 70 public static final int INVALID_SUBSCRIPTION_ID = -1; 71 72 /** Base value for Dummy SUBSCRIPTION_ID's. */ 73 /** FIXME: Remove DummySubId's, but for now have them map just below INVALID_SUBSCRIPTION_ID 74 /** @hide */ 75 public static final int DUMMY_SUBSCRIPTION_ID_BASE = INVALID_SUBSCRIPTION_ID - 1; 76 77 /** An invalid phone identifier */ 78 /** @hide */ 79 public static final int INVALID_PHONE_INDEX = -1; 80 81 /** An invalid slot identifier */ 82 /** @hide */ 83 public static final int INVALID_SIM_SLOT_INDEX = -1; 84 85 /** Indicates the caller wants the default sub id. */ 86 /** @hide */ 87 public static final int DEFAULT_SUBSCRIPTION_ID = Integer.MAX_VALUE; 88 89 /** 90 * Indicates the caller wants the default phone id. 91 * Used in SubscriptionController and Phone but do we really need it??? 92 * @hide 93 */ 94 public static final int DEFAULT_PHONE_INDEX = Integer.MAX_VALUE; 95 96 /** Indicates the caller wants the default slot id. NOT used remove? */ 97 /** @hide */ 98 public static final int DEFAULT_SIM_SLOT_INDEX = Integer.MAX_VALUE; 99 100 /** Minimum possible subid that represents a subscription */ 101 /** @hide */ 102 public static final int MIN_SUBSCRIPTION_ID_VALUE = 0; 103 104 /** Maximum possible subid that represents a subscription */ 105 /** @hide */ 106 public static final int MAX_SUBSCRIPTION_ID_VALUE = DEFAULT_SUBSCRIPTION_ID - 1; 107 108 /** @hide */ 109 public static final Uri CONTENT_URI = Uri.parse("content://telephony/siminfo"); 110 111 /** 112 * TelephonyProvider unique key column name is the subscription id. 113 * <P>Type: TEXT (String)</P> 114 */ 115 /** @hide */ 116 public static final String UNIQUE_KEY_SUBSCRIPTION_ID = "_id"; 117 118 /** 119 * TelephonyProvider column name for SIM ICC Identifier 120 * <P>Type: TEXT (String)</P> 121 */ 122 /** @hide */ 123 public static final String ICC_ID = "icc_id"; 124 125 /** 126 * TelephonyProvider column name for user SIM_SlOT_INDEX 127 * <P>Type: INTEGER (int)</P> 128 */ 129 /** @hide */ 130 public static final String SIM_SLOT_INDEX = "sim_id"; 131 132 /** SIM is not inserted */ 133 /** @hide */ 134 public static final int SIM_NOT_INSERTED = -1; 135 136 /** 137 * TelephonyProvider column name for user displayed name. 138 * <P>Type: TEXT (String)</P> 139 */ 140 /** @hide */ 141 public static final String DISPLAY_NAME = "display_name"; 142 143 /** 144 * TelephonyProvider column name for the service provider name for the SIM. 145 * <P>Type: TEXT (String)</P> 146 */ 147 /** @hide */ 148 public static final String CARRIER_NAME = "carrier_name"; 149 150 /** 151 * Default name resource 152 * @hide 153 */ 154 public static final int DEFAULT_NAME_RES = com.android.internal.R.string.unknownName; 155 156 /** 157 * TelephonyProvider column name for source of the user displayed name. 158 * <P>Type: INT (int)</P> with one of the NAME_SOURCE_XXXX values below 159 * 160 * @hide 161 */ 162 public static final String NAME_SOURCE = "name_source"; 163 164 /** 165 * The name_source is undefined 166 * @hide 167 */ 168 public static final int NAME_SOURCE_UNDEFINDED = -1; 169 170 /** 171 * The name_source is the default 172 * @hide 173 */ 174 public static final int NAME_SOURCE_DEFAULT_SOURCE = 0; 175 176 /** 177 * The name_source is from the SIM 178 * @hide 179 */ 180 public static final int NAME_SOURCE_SIM_SOURCE = 1; 181 182 /** 183 * The name_source is from the user 184 * @hide 185 */ 186 public static final int NAME_SOURCE_USER_INPUT = 2; 187 188 /** 189 * TelephonyProvider column name for the color of a SIM. 190 * <P>Type: INTEGER (int)</P> 191 */ 192 /** @hide */ 193 public static final String COLOR = "color"; 194 195 /** @hide */ 196 public static final int COLOR_1 = 0; 197 198 /** @hide */ 199 public static final int COLOR_2 = 1; 200 201 /** @hide */ 202 public static final int COLOR_3 = 2; 203 204 /** @hide */ 205 public static final int COLOR_4 = 3; 206 207 /** @hide */ 208 public static final int COLOR_DEFAULT = COLOR_1; 209 210 /** 211 * TelephonyProvider column name for the phone number of a SIM. 212 * <P>Type: TEXT (String)</P> 213 */ 214 /** @hide */ 215 public static final String NUMBER = "number"; 216 217 /** 218 * TelephonyProvider column name for the number display format of a SIM. 219 * <P>Type: INTEGER (int)</P> 220 */ 221 /** @hide */ 222 public static final String DISPLAY_NUMBER_FORMAT = "display_number_format"; 223 224 /** @hide */ 225 public static final int DISPLAY_NUMBER_NONE = 0; 226 227 /** @hide */ 228 public static final int DISPLAY_NUMBER_FIRST = 1; 229 230 /** @hide */ 231 public static final int DISPLAY_NUMBER_LAST = 2; 232 233 /** @hide */ 234 public static final int DISPLAY_NUMBER_DEFAULT = DISPLAY_NUMBER_FIRST; 235 236 /** 237 * TelephonyProvider column name for permission for data roaming of a SIM. 238 * <P>Type: INTEGER (int)</P> 239 */ 240 /** @hide */ 241 public static final String DATA_ROAMING = "data_roaming"; 242 243 /** Indicates that data roaming is enabled for a subscription */ 244 public static final int DATA_ROAMING_ENABLE = 1; 245 246 /** Indicates that data roaming is disabled for a subscription */ 247 public static final int DATA_ROAMING_DISABLE = 0; 248 249 /** @hide */ 250 public static final int DATA_ROAMING_DEFAULT = DATA_ROAMING_DISABLE; 251 252 /** @hide */ 253 public static final int SIM_PROVISIONED = 0; 254 255 /** 256 * TelephonyProvider column name for the MCC associated with a SIM. 257 * <P>Type: INTEGER (int)</P> 258 * @hide 259 */ 260 public static final String MCC = "mcc"; 261 262 /** 263 * TelephonyProvider column name for the MNC associated with a SIM. 264 * <P>Type: INTEGER (int)</P> 265 * @hide 266 */ 267 public static final String MNC = "mnc"; 268 269 /** 270 * TelephonyProvider column name for the sim provisioning status associated with a SIM. 271 * <P>Type: INTEGER (int)</P> 272 * @hide 273 */ 274 public static final String SIM_PROVISIONING_STATUS = "sim_provisioning_status"; 275 276 /** 277 * TelephonyProvider column name for whether a subscription is embedded (that is, present on an 278 * eSIM). 279 * <p>Type: INTEGER (int), 1 for embedded or 0 for non-embedded. 280 * @hide 281 */ 282 public static final String IS_EMBEDDED = "is_embedded"; 283 284 /** 285 * TelephonyProvider column name for SIM card identifier. For UICC card it is the ICCID of the 286 * current enabled profile on the card, while for eUICC card it is the EID of the card. 287 * <P>Type: TEXT (String)</P> 288 * @hide 289 */ 290 public static final String CARD_ID = "card_id"; 291 292 /** 293 * TelephonyProvider column name for the encoded {@link UiccAccessRule}s from 294 * {@link UiccAccessRule#encodeRules}. Only present if {@link #IS_EMBEDDED} is 1. 295 * <p>TYPE: BLOB 296 * @hide 297 */ 298 public static final String ACCESS_RULES = "access_rules"; 299 300 /** 301 * TelephonyProvider column name identifying whether an embedded subscription is on a removable 302 * card. Such subscriptions are marked inaccessible as soon as the current card is removed. 303 * Otherwise, they will remain accessible unless explicitly deleted. Only present if 304 * {@link #IS_EMBEDDED} is 1. 305 * <p>TYPE: INTEGER (int), 1 for removable or 0 for non-removable. 306 * @hide 307 */ 308 public static final String IS_REMOVABLE = "is_removable"; 309 310 /** 311 * TelephonyProvider column name for extreme threat in CB settings 312 * @hide 313 */ 314 public static final String CB_EXTREME_THREAT_ALERT = "enable_cmas_extreme_threat_alerts"; 315 316 /** 317 * TelephonyProvider column name for severe threat in CB settings 318 *@hide 319 */ 320 public static final String CB_SEVERE_THREAT_ALERT = "enable_cmas_severe_threat_alerts"; 321 322 /** 323 * TelephonyProvider column name for amber alert in CB settings 324 *@hide 325 */ 326 public static final String CB_AMBER_ALERT = "enable_cmas_amber_alerts"; 327 328 /** 329 * TelephonyProvider column name for emergency alert in CB settings 330 *@hide 331 */ 332 public static final String CB_EMERGENCY_ALERT = "enable_emergency_alerts"; 333 334 /** 335 * TelephonyProvider column name for alert sound duration in CB settings 336 *@hide 337 */ 338 public static final String CB_ALERT_SOUND_DURATION = "alert_sound_duration"; 339 340 /** 341 * TelephonyProvider column name for alert reminder interval in CB settings 342 *@hide 343 */ 344 public static final String CB_ALERT_REMINDER_INTERVAL = "alert_reminder_interval"; 345 346 /** 347 * TelephonyProvider column name for enabling vibrate in CB settings 348 *@hide 349 */ 350 public static final String CB_ALERT_VIBRATE = "enable_alert_vibrate"; 351 352 /** 353 * TelephonyProvider column name for enabling alert speech in CB settings 354 *@hide 355 */ 356 public static final String CB_ALERT_SPEECH = "enable_alert_speech"; 357 358 /** 359 * TelephonyProvider column name for ETWS test alert in CB settings 360 *@hide 361 */ 362 public static final String CB_ETWS_TEST_ALERT = "enable_etws_test_alerts"; 363 364 /** 365 * TelephonyProvider column name for enable channel50 alert in CB settings 366 *@hide 367 */ 368 public static final String CB_CHANNEL_50_ALERT = "enable_channel_50_alerts"; 369 370 /** 371 * TelephonyProvider column name for CMAS test alert in CB settings 372 *@hide 373 */ 374 public static final String CB_CMAS_TEST_ALERT= "enable_cmas_test_alerts"; 375 376 /** 377 * TelephonyProvider column name for Opt out dialog in CB settings 378 *@hide 379 */ 380 public static final String CB_OPT_OUT_DIALOG = "show_cmas_opt_out_dialog"; 381 382 /** 383 * TelephonyProvider column name for enable Volte. 384 * 385 * If this setting is not initialized (set to -1) then we use the Carrier Config value 386 * {@link CarrierConfigManager#KEY_ENHANCED_4G_LTE_ON_BY_DEFAULT_BOOL}. 387 *@hide 388 */ 389 public static final String ENHANCED_4G_MODE_ENABLED = "volte_vt_enabled"; 390 391 /** 392 * TelephonyProvider column name for enable VT (Video Telephony over IMS) 393 *@hide 394 */ 395 public static final String VT_IMS_ENABLED = "vt_ims_enabled"; 396 397 /** 398 * TelephonyProvider column name for enable Wifi calling 399 *@hide 400 */ 401 public static final String WFC_IMS_ENABLED = "wfc_ims_enabled"; 402 403 /** 404 * TelephonyProvider column name for Wifi calling mode 405 *@hide 406 */ 407 public static final String WFC_IMS_MODE = "wfc_ims_mode"; 408 409 /** 410 * TelephonyProvider column name for Wifi calling mode in roaming 411 *@hide 412 */ 413 public static final String WFC_IMS_ROAMING_MODE = "wfc_ims_roaming_mode"; 414 415 /** 416 * TelephonyProvider column name for enable Wifi calling in roaming 417 *@hide 418 */ 419 public static final String WFC_IMS_ROAMING_ENABLED = "wfc_ims_roaming_enabled"; 420 421 /** 422 * Broadcast Action: The user has changed one of the default subs related to 423 * data, phone calls, or sms</p> 424 * 425 * TODO: Change to a listener 426 * @hide 427 */ 428 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 429 public static final String SUB_DEFAULT_CHANGED_ACTION = 430 "android.intent.action.SUB_DEFAULT_CHANGED"; 431 432 /** 433 * Broadcast Action: The default subscription has changed. This has the following 434 * extra values:</p> 435 * The {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default subscription index 436 */ 437 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 438 public static final String ACTION_DEFAULT_SUBSCRIPTION_CHANGED 439 = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED"; 440 441 /** 442 * Broadcast Action: The default sms subscription has changed. This has the following 443 * extra values:</p> 444 * {@link #EXTRA_SUBSCRIPTION_INDEX} extra indicates the current default sms 445 * subscription index 446 */ 447 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 448 public static final String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED 449 = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED"; 450 451 /** 452 * Activity Action: Display UI for managing the billing relationship plans 453 * between a carrier and a specific subscriber. 454 * <p> 455 * Carrier apps are encouraged to implement this activity, and the OS will 456 * provide an affordance to quickly enter this activity, typically via 457 * Settings. This affordance will only be shown when the carrier app is 458 * actively providing subscription plan information via 459 * {@link #setSubscriptionPlans(int, List)}. 460 * <p> 461 * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription 462 * the user is interested in. 463 */ 464 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 465 @SystemApi 466 public static final String ACTION_MANAGE_SUBSCRIPTION_PLANS 467 = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS"; 468 469 /** 470 * Broadcast Action: Request a refresh of the billing relationship plans 471 * between a carrier and a specific subscriber. 472 * <p> 473 * Carrier apps are encouraged to implement this receiver, and the OS will 474 * provide an affordance to request a refresh. This affordance will only be 475 * shown when the carrier app is actively providing subscription plan 476 * information via {@link #setSubscriptionPlans(int, List)}. 477 * <p> 478 * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription 479 * the user is interested in. 480 * <p> 481 * Receivers should protect themselves by checking that the sender holds the 482 * {@code android.permission.MANAGE_SUBSCRIPTION_PLANS} permission. 483 */ 484 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 485 @SystemApi 486 public static final String ACTION_REFRESH_SUBSCRIPTION_PLANS 487 = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS"; 488 489 /** 490 * Broadcast Action: The billing relationship plans between a carrier and a 491 * specific subscriber has changed. 492 * <p> 493 * Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription 494 * changed. 495 * 496 * @hide 497 */ 498 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 499 @RequiresPermission(android.Manifest.permission.MANAGE_SUBSCRIPTION_PLANS) 500 public static final String ACTION_SUBSCRIPTION_PLANS_CHANGED 501 = "android.telephony.action.SUBSCRIPTION_PLANS_CHANGED"; 502 503 /** 504 * Integer extra used with {@link #ACTION_DEFAULT_SUBSCRIPTION_CHANGED} and 505 * {@link #ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED} to indicate the subscription 506 * which has changed. 507 */ 508 public static final String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX"; 509 510 private final Context mContext; 511 private volatile INetworkPolicyManager mNetworkPolicy; 512 513 /** 514 * A listener class for monitoring changes to {@link SubscriptionInfo} records. 515 * <p> 516 * Override the onSubscriptionsChanged method in the object that extends this 517 * class and pass it to {@link #addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)} 518 * to register your listener and to unregister invoke 519 * {@link #removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener)} 520 * <p> 521 * Permissions android.Manifest.permission.READ_PHONE_STATE is required 522 * for #onSubscriptionsChanged to be invoked. 523 */ 524 public static class OnSubscriptionsChangedListener { 525 private class OnSubscriptionsChangedListenerHandler extends Handler { 526 OnSubscriptionsChangedListenerHandler() { 527 super(); 528 } 529 530 OnSubscriptionsChangedListenerHandler(Looper looper) { 531 super(looper); 532 } 533 534 @Override 535 public void handleMessage(Message msg) { 536 if (DBG) { 537 log("handleMessage: invoke the overriden onSubscriptionsChanged()"); 538 } 539 OnSubscriptionsChangedListener.this.onSubscriptionsChanged(); 540 } 541 } 542 543 private final Handler mHandler; 544 545 public OnSubscriptionsChangedListener() { 546 mHandler = new OnSubscriptionsChangedListenerHandler(); 547 } 548 549 /** 550 * Allow a listener to be created with a custom looper 551 * @param looper the looper that the underlining handler should run on 552 * @hide 553 */ 554 public OnSubscriptionsChangedListener(Looper looper) { 555 mHandler = new OnSubscriptionsChangedListenerHandler(looper); 556 } 557 558 /** 559 * Callback invoked when there is any change to any SubscriptionInfo. Typically 560 * this method would invoke {@link #getActiveSubscriptionInfoList} 561 */ 562 public void onSubscriptionsChanged() { 563 if (DBG) log("onSubscriptionsChanged: NOT OVERRIDDEN"); 564 } 565 566 /** 567 * The callback methods need to be called on the handler thread where 568 * this object was created. If the binder did that for us it'd be nice. 569 */ 570 IOnSubscriptionsChangedListener callback = new IOnSubscriptionsChangedListener.Stub() { 571 @Override 572 public void onSubscriptionsChanged() { 573 if (DBG) log("callback: received, sendEmptyMessage(0) to handler"); 574 mHandler.sendEmptyMessage(0); 575 } 576 }; 577 578 private void log(String s) { 579 Rlog.d(LOG_TAG, s); 580 } 581 } 582 583 /** @hide */ 584 public SubscriptionManager(Context context) { 585 if (DBG) logd("SubscriptionManager created"); 586 mContext = context; 587 } 588 589 /** 590 * @deprecated developers should always obtain references directly from 591 * {@link Context#getSystemService(Class)}. 592 */ 593 @Deprecated 594 public static SubscriptionManager from(Context context) { 595 return (SubscriptionManager) context 596 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE); 597 } 598 599 private final INetworkPolicyManager getNetworkPolicy() { 600 if (mNetworkPolicy == null) { 601 mNetworkPolicy = INetworkPolicyManager.Stub 602 .asInterface(ServiceManager.getService(Context.NETWORK_POLICY_SERVICE)); 603 } 604 return mNetworkPolicy; 605 } 606 607 /** 608 * Register for changes to the list of active {@link SubscriptionInfo} records or to the 609 * individual records themselves. When a change occurs the onSubscriptionsChanged method of 610 * the listener will be invoked immediately if there has been a notification. 611 * 612 * @param listener an instance of {@link OnSubscriptionsChangedListener} with 613 * onSubscriptionsChanged overridden. 614 */ 615 public void addOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { 616 String pkgName = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 617 if (DBG) { 618 logd("register OnSubscriptionsChangedListener pkgName=" + pkgName 619 + " listener=" + listener); 620 } 621 try { 622 // We use the TelephonyRegistry as it runs in the system and thus is always 623 // available. Where as SubscriptionController could crash and not be available 624 ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( 625 "telephony.registry")); 626 if (tr != null) { 627 tr.addOnSubscriptionsChangedListener(pkgName, listener.callback); 628 } 629 } catch (RemoteException ex) { 630 // Should not happen 631 } 632 } 633 634 /** 635 * Unregister the {@link OnSubscriptionsChangedListener}. This is not strictly necessary 636 * as the listener will automatically be unregistered if an attempt to invoke the listener 637 * fails. 638 * 639 * @param listener that is to be unregistered. 640 */ 641 public void removeOnSubscriptionsChangedListener(OnSubscriptionsChangedListener listener) { 642 String pkgForDebug = mContext != null ? mContext.getOpPackageName() : "<unknown>"; 643 if (DBG) { 644 logd("unregister OnSubscriptionsChangedListener pkgForDebug=" + pkgForDebug 645 + " listener=" + listener); 646 } 647 try { 648 // We use the TelephonyRegistry as its runs in the system and thus is always 649 // available where as SubscriptionController could crash and not be available 650 ITelephonyRegistry tr = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( 651 "telephony.registry")); 652 if (tr != null) { 653 tr.removeOnSubscriptionsChangedListener(pkgForDebug, listener.callback); 654 } 655 } catch (RemoteException ex) { 656 // Should not happen 657 } 658 } 659 660 /** 661 * Get the active SubscriptionInfo with the input subId. 662 * 663 * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 664 * or that the calling app has carrier privileges (see 665 * {@link TelephonyManager#hasCarrierPrivileges}). 666 * 667 * @param subId The unique SubscriptionInfo key in database. 668 * @return SubscriptionInfo, maybe null if its not active. 669 */ 670 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 671 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) 672 public SubscriptionInfo getActiveSubscriptionInfo(int subId) { 673 if (VDBG) logd("[getActiveSubscriptionInfo]+ subId=" + subId); 674 if (!isValidSubscriptionId(subId)) { 675 if (DBG) { 676 logd("[getActiveSubscriptionInfo]- invalid subId"); 677 } 678 return null; 679 } 680 681 SubscriptionInfo subInfo = null; 682 683 try { 684 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 685 if (iSub != null) { 686 subInfo = iSub.getActiveSubscriptionInfo(subId, mContext.getOpPackageName()); 687 } 688 } catch (RemoteException ex) { 689 // ignore it 690 } 691 692 return subInfo; 693 694 } 695 696 /** 697 * Get the active SubscriptionInfo associated with the iccId 698 * @param iccId the IccId of SIM card 699 * @return SubscriptionInfo, maybe null if its not active 700 * @hide 701 */ 702 public SubscriptionInfo getActiveSubscriptionInfoForIccIndex(String iccId) { 703 if (VDBG) logd("[getActiveSubscriptionInfoForIccIndex]+ iccId=" + iccId); 704 if (iccId == null) { 705 logd("[getActiveSubscriptionInfoForIccIndex]- null iccid"); 706 return null; 707 } 708 709 SubscriptionInfo result = null; 710 711 try { 712 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 713 if (iSub != null) { 714 result = iSub.getActiveSubscriptionInfoForIccId(iccId, mContext.getOpPackageName()); 715 } 716 } catch (RemoteException ex) { 717 // ignore it 718 } 719 720 return result; 721 } 722 723 /** 724 * Get the active SubscriptionInfo associated with the slotIndex 725 * 726 * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 727 * or that the calling app has carrier privileges (see 728 * {@link TelephonyManager#hasCarrierPrivileges}). 729 * 730 * @param slotIndex the slot which the subscription is inserted 731 * @return SubscriptionInfo, maybe null if its not active 732 */ 733 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 734 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) 735 public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex) { 736 if (VDBG) logd("[getActiveSubscriptionInfoForSimSlotIndex]+ slotIndex=" + slotIndex); 737 if (!isValidSlotIndex(slotIndex)) { 738 logd("[getActiveSubscriptionInfoForSimSlotIndex]- invalid slotIndex"); 739 return null; 740 } 741 742 SubscriptionInfo result = null; 743 744 try { 745 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 746 if (iSub != null) { 747 result = iSub.getActiveSubscriptionInfoForSimSlotIndex(slotIndex, 748 mContext.getOpPackageName()); 749 } 750 } catch (RemoteException ex) { 751 // ignore it 752 } 753 754 return result; 755 } 756 757 /** 758 * @return List of all SubscriptionInfo records in database, 759 * include those that were inserted before, maybe empty but not null. 760 * @hide 761 */ 762 public List<SubscriptionInfo> getAllSubscriptionInfoList() { 763 if (VDBG) logd("[getAllSubscriptionInfoList]+"); 764 765 List<SubscriptionInfo> result = null; 766 767 try { 768 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 769 if (iSub != null) { 770 result = iSub.getAllSubInfoList(mContext.getOpPackageName()); 771 } 772 } catch (RemoteException ex) { 773 // ignore it 774 } 775 776 if (result == null) { 777 result = new ArrayList<>(); 778 } 779 return result; 780 } 781 782 /** 783 * Get the SubscriptionInfo(s) of the currently inserted SIM(s). The records will be sorted 784 * by {@link SubscriptionInfo#getSimSlotIndex} then by {@link SubscriptionInfo#getSubscriptionId}. 785 * 786 * <p>Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 787 * or that the calling app has carrier privileges (see 788 * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, only records accessible 789 * to the calling app are returned. 790 * 791 * @return Sorted list of the currently {@link SubscriptionInfo} records available on the device. 792 * <ul> 793 * <li> 794 * If null is returned the current state is unknown but if a {@link OnSubscriptionsChangedListener} 795 * has been registered {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be 796 * invoked in the future. 797 * </li> 798 * <li> 799 * If the list is empty then there are no {@link SubscriptionInfo} records currently available. 800 * </li> 801 * <li> 802 * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} 803 * then by {@link SubscriptionInfo#getSubscriptionId}. 804 * </li> 805 * </ul> 806 */ 807 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 808 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) 809 public List<SubscriptionInfo> getActiveSubscriptionInfoList() { 810 List<SubscriptionInfo> result = null; 811 812 try { 813 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 814 if (iSub != null) { 815 result = iSub.getActiveSubscriptionInfoList(mContext.getOpPackageName()); 816 } 817 } catch (RemoteException ex) { 818 // ignore it 819 } 820 return result; 821 } 822 823 /** 824 * Gets the SubscriptionInfo(s) of all available subscriptions, if any. 825 * 826 * <p>Available subscriptions include active ones (those with a non-negative 827 * {@link SubscriptionInfo#getSimSlotIndex()}) as well as inactive but installed embedded 828 * subscriptions. 829 * 830 * <p>The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by 831 * {@link SubscriptionInfo#getSubscriptionId}. 832 * 833 * @return Sorted list of the current {@link SubscriptionInfo} records available on the 834 * device. 835 * <ul> 836 * <li> 837 * If null is returned the current state is unknown but if a 838 * {@link OnSubscriptionsChangedListener} has been registered 839 * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be invoked in the future. 840 * <li> 841 * If the list is empty then there are no {@link SubscriptionInfo} records currently available. 842 * <li> 843 * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} 844 * then by {@link SubscriptionInfo#getSubscriptionId}. 845 * </ul> 846 * 847 * <p> 848 * Permissions android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE is required 849 * for #getAvailableSubscriptionInfoList to be invoked. 850 * @hide 851 */ 852 @SystemApi 853 public List<SubscriptionInfo> getAvailableSubscriptionInfoList() { 854 List<SubscriptionInfo> result = null; 855 856 try { 857 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 858 if (iSub != null) { 859 result = iSub.getAvailableSubscriptionInfoList(mContext.getOpPackageName()); 860 } 861 } catch (RemoteException ex) { 862 // ignore it 863 } 864 return result; 865 } 866 867 /** 868 * Gets the SubscriptionInfo(s) of all embedded subscriptions accessible to the calling app, if 869 * any. 870 * 871 * <p>Only those subscriptions for which the calling app has carrier privileges per the 872 * subscription metadata, if any, will be included in the returned list. 873 * 874 * <p>The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by 875 * {@link SubscriptionInfo#getSubscriptionId}. 876 * 877 * @return Sorted list of the current embedded {@link SubscriptionInfo} records available on the 878 * device which are accessible to the caller. 879 * <ul> 880 * <li> 881 * If null is returned the current state is unknown but if a 882 * {@link OnSubscriptionsChangedListener} has been registered 883 * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be invoked in the future. 884 * <li> 885 * If the list is empty then there are no {@link SubscriptionInfo} records currently available. 886 * <li> 887 * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} 888 * then by {@link SubscriptionInfo#getSubscriptionId}. 889 * </ul> 890 */ 891 public List<SubscriptionInfo> getAccessibleSubscriptionInfoList() { 892 List<SubscriptionInfo> result = null; 893 894 try { 895 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 896 if (iSub != null) { 897 result = iSub.getAccessibleSubscriptionInfoList(mContext.getOpPackageName()); 898 } 899 } catch (RemoteException ex) { 900 // ignore it 901 } 902 return result; 903 } 904 905 /** 906 * Request a refresh of the platform cache of profile information. 907 * 908 * <p>Should be called by the EuiccService implementation whenever this information changes due 909 * to an operation done outside the scope of a request initiated by the platform to the 910 * EuiccService. There is no need to refresh for downloads, deletes, or other operations that 911 * were made through the EuiccService. 912 * 913 * <p>Requires the {@link android.Manifest.permission#WRITE_EMBEDDED_SUBSCRIPTIONS} permission. 914 * @hide 915 */ 916 @SystemApi 917 public void requestEmbeddedSubscriptionInfoListRefresh() { 918 try { 919 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 920 if (iSub != null) { 921 iSub.requestEmbeddedSubscriptionInfoListRefresh(); 922 } 923 } catch (RemoteException ex) { 924 // ignore it 925 } 926 } 927 928 /** 929 * @return the count of all subscriptions in the database, this includes 930 * all subscriptions that have been seen. 931 * @hide 932 */ 933 public int getAllSubscriptionInfoCount() { 934 if (VDBG) logd("[getAllSubscriptionInfoCount]+"); 935 936 int result = 0; 937 938 try { 939 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 940 if (iSub != null) { 941 result = iSub.getAllSubInfoCount(mContext.getOpPackageName()); 942 } 943 } catch (RemoteException ex) { 944 // ignore it 945 } 946 947 return result; 948 } 949 950 /** 951 * 952 * Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} 953 * or that the calling app has carrier privileges (see 954 * {@link TelephonyManager#hasCarrierPrivileges}). In the latter case, the count will include 955 * only those subscriptions accessible to the caller. 956 * 957 * @return the current number of active subscriptions. There is no guarantee the value 958 * returned by this method will be the same as the length of the list returned by 959 * {@link #getActiveSubscriptionInfoList}. 960 */ 961 @SuppressAutoDoc // Blocked by b/72967236 - no support for carrier privileges 962 @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) 963 public int getActiveSubscriptionInfoCount() { 964 int result = 0; 965 966 try { 967 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 968 if (iSub != null) { 969 result = iSub.getActiveSubInfoCount(mContext.getOpPackageName()); 970 } 971 } catch (RemoteException ex) { 972 // ignore it 973 } 974 975 return result; 976 } 977 978 /** 979 * @return the maximum number of active subscriptions that will be returned by 980 * {@link #getActiveSubscriptionInfoList} and the value returned by 981 * {@link #getActiveSubscriptionInfoCount}. 982 */ 983 public int getActiveSubscriptionInfoCountMax() { 984 int result = 0; 985 986 try { 987 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 988 if (iSub != null) { 989 result = iSub.getActiveSubInfoCountMax(); 990 } 991 } catch (RemoteException ex) { 992 // ignore it 993 } 994 995 return result; 996 } 997 998 /** 999 * Add a new SubscriptionInfo to SubscriptionInfo database if needed 1000 * @param iccId the IccId of the SIM card 1001 * @param slotIndex the slot which the SIM is inserted 1002 * @return the URL of the newly created row or the updated row 1003 * @hide 1004 */ 1005 public Uri addSubscriptionInfoRecord(String iccId, int slotIndex) { 1006 if (VDBG) logd("[addSubscriptionInfoRecord]+ iccId:" + iccId + " slotIndex:" + slotIndex); 1007 if (iccId == null) { 1008 logd("[addSubscriptionInfoRecord]- null iccId"); 1009 } 1010 if (!isValidSlotIndex(slotIndex)) { 1011 logd("[addSubscriptionInfoRecord]- invalid slotIndex"); 1012 } 1013 1014 try { 1015 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1016 if (iSub != null) { 1017 // FIXME: This returns 1 on success, 0 on error should should we return it? 1018 iSub.addSubInfoRecord(iccId, slotIndex); 1019 } else { 1020 logd("[addSubscriptionInfoRecord]- ISub service is null"); 1021 } 1022 } catch (RemoteException ex) { 1023 // ignore it 1024 } 1025 1026 // FIXME: Always returns null? 1027 return null; 1028 1029 } 1030 1031 /** 1032 * Set SIM icon tint color by simInfo index 1033 * @param tint the RGB value of icon tint color of the SIM 1034 * @param subId the unique SubInfoRecord index in database 1035 * @return the number of records updated 1036 * @hide 1037 */ 1038 public int setIconTint(int tint, int subId) { 1039 if (VDBG) logd("[setIconTint]+ tint:" + tint + " subId:" + subId); 1040 if (!isValidSubscriptionId(subId)) { 1041 logd("[setIconTint]- fail"); 1042 return -1; 1043 } 1044 1045 int result = 0; 1046 1047 try { 1048 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1049 if (iSub != null) { 1050 result = iSub.setIconTint(tint, subId); 1051 } 1052 } catch (RemoteException ex) { 1053 // ignore it 1054 } 1055 1056 return result; 1057 1058 } 1059 1060 /** 1061 * Set display name by simInfo index 1062 * @param displayName the display name of SIM card 1063 * @param subId the unique SubscriptionInfo index in database 1064 * @return the number of records updated 1065 * @hide 1066 */ 1067 public int setDisplayName(String displayName, int subId) { 1068 return setDisplayName(displayName, subId, NAME_SOURCE_UNDEFINDED); 1069 } 1070 1071 /** 1072 * Set display name by simInfo index with name source 1073 * @param displayName the display name of SIM card 1074 * @param subId the unique SubscriptionInfo index in database 1075 * @param nameSource 0: NAME_SOURCE_DEFAULT_SOURCE, 1: NAME_SOURCE_SIM_SOURCE, 1076 * 2: NAME_SOURCE_USER_INPUT, -1 NAME_SOURCE_UNDEFINED 1077 * @return the number of records updated or < 0 if invalid subId 1078 * @hide 1079 */ 1080 public int setDisplayName(String displayName, int subId, long nameSource) { 1081 if (VDBG) { 1082 logd("[setDisplayName]+ displayName:" + displayName + " subId:" + subId 1083 + " nameSource:" + nameSource); 1084 } 1085 if (!isValidSubscriptionId(subId)) { 1086 logd("[setDisplayName]- fail"); 1087 return -1; 1088 } 1089 1090 int result = 0; 1091 1092 try { 1093 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1094 if (iSub != null) { 1095 result = iSub.setDisplayNameUsingSrc(displayName, subId, nameSource); 1096 } 1097 } catch (RemoteException ex) { 1098 // ignore it 1099 } 1100 1101 return result; 1102 1103 } 1104 1105 /** 1106 * Set phone number by subId 1107 * @param number the phone number of the SIM 1108 * @param subId the unique SubscriptionInfo index in database 1109 * @return the number of records updated 1110 * @hide 1111 */ 1112 public int setDisplayNumber(String number, int subId) { 1113 if (number == null || !isValidSubscriptionId(subId)) { 1114 logd("[setDisplayNumber]- fail"); 1115 return -1; 1116 } 1117 1118 int result = 0; 1119 1120 try { 1121 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1122 if (iSub != null) { 1123 result = iSub.setDisplayNumber(number, subId); 1124 } 1125 } catch (RemoteException ex) { 1126 // ignore it 1127 } 1128 1129 return result; 1130 1131 } 1132 1133 /** 1134 * Set data roaming by simInfo index 1135 * @param roaming 0:Don't allow data when roaming, 1:Allow data when roaming 1136 * @param subId the unique SubscriptionInfo index in database 1137 * @return the number of records updated 1138 * @hide 1139 */ 1140 public int setDataRoaming(int roaming, int subId) { 1141 if (VDBG) logd("[setDataRoaming]+ roaming:" + roaming + " subId:" + subId); 1142 if (roaming < 0 || !isValidSubscriptionId(subId)) { 1143 logd("[setDataRoaming]- fail"); 1144 return -1; 1145 } 1146 1147 int result = 0; 1148 1149 try { 1150 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1151 if (iSub != null) { 1152 result = iSub.setDataRoaming(roaming, subId); 1153 } 1154 } catch (RemoteException ex) { 1155 // ignore it 1156 } 1157 1158 return result; 1159 } 1160 1161 /** 1162 * Get slotIndex associated with the subscription. 1163 * @return slotIndex as a positive integer or a negative value if an error either 1164 * SIM_NOT_INSERTED or < 0 if an invalid slot index 1165 * @hide 1166 */ 1167 public static int getSlotIndex(int subId) { 1168 if (!isValidSubscriptionId(subId)) { 1169 if (DBG) { 1170 logd("[getSlotIndex]- fail"); 1171 } 1172 } 1173 1174 int result = INVALID_SIM_SLOT_INDEX; 1175 1176 try { 1177 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1178 if (iSub != null) { 1179 result = iSub.getSlotIndex(subId); 1180 } 1181 } catch (RemoteException ex) { 1182 // ignore it 1183 } 1184 1185 return result; 1186 1187 } 1188 1189 /** @hide */ 1190 public static int[] getSubId(int slotIndex) { 1191 if (!isValidSlotIndex(slotIndex)) { 1192 logd("[getSubId]- fail"); 1193 return null; 1194 } 1195 1196 int[] subId = null; 1197 1198 try { 1199 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1200 if (iSub != null) { 1201 subId = iSub.getSubId(slotIndex); 1202 } 1203 } catch (RemoteException ex) { 1204 // ignore it 1205 } 1206 1207 return subId; 1208 } 1209 1210 /** @hide */ 1211 public static int getPhoneId(int subId) { 1212 if (!isValidSubscriptionId(subId)) { 1213 if (DBG) { 1214 logd("[getPhoneId]- fail"); 1215 } 1216 return INVALID_PHONE_INDEX; 1217 } 1218 1219 int result = INVALID_PHONE_INDEX; 1220 1221 try { 1222 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1223 if (iSub != null) { 1224 result = iSub.getPhoneId(subId); 1225 } 1226 } catch (RemoteException ex) { 1227 // ignore it 1228 } 1229 1230 if (VDBG) logd("[getPhoneId]- phoneId=" + result); 1231 return result; 1232 1233 } 1234 1235 private static void logd(String msg) { 1236 Rlog.d(LOG_TAG, msg); 1237 } 1238 1239 /** 1240 * Returns the system's default subscription id. 1241 * 1242 * For a voice capable device, it will return getDefaultVoiceSubscriptionId. 1243 * For a data only device, it will return the getDefaultDataSubscriptionId. 1244 * May return an INVALID_SUBSCRIPTION_ID on error. 1245 * 1246 * @return the "system" default subscription id. 1247 */ 1248 public static int getDefaultSubscriptionId() { 1249 int subId = INVALID_SUBSCRIPTION_ID; 1250 1251 try { 1252 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1253 if (iSub != null) { 1254 subId = iSub.getDefaultSubId(); 1255 } 1256 } catch (RemoteException ex) { 1257 // ignore it 1258 } 1259 1260 if (VDBG) logd("getDefaultSubId=" + subId); 1261 return subId; 1262 } 1263 1264 /** 1265 * Returns the system's default voice subscription id. 1266 * 1267 * On a data only device or on error, will return INVALID_SUBSCRIPTION_ID. 1268 * 1269 * @return the default voice subscription Id. 1270 */ 1271 public static int getDefaultVoiceSubscriptionId() { 1272 int subId = INVALID_SUBSCRIPTION_ID; 1273 1274 try { 1275 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1276 if (iSub != null) { 1277 subId = iSub.getDefaultVoiceSubId(); 1278 } 1279 } catch (RemoteException ex) { 1280 // ignore it 1281 } 1282 1283 if (VDBG) logd("getDefaultVoiceSubscriptionId, sub id = " + subId); 1284 return subId; 1285 } 1286 1287 /** @hide */ 1288 public void setDefaultVoiceSubId(int subId) { 1289 if (VDBG) logd("setDefaultVoiceSubId sub id = " + subId); 1290 try { 1291 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1292 if (iSub != null) { 1293 iSub.setDefaultVoiceSubId(subId); 1294 } 1295 } catch (RemoteException ex) { 1296 // ignore it 1297 } 1298 } 1299 1300 /** 1301 * Return the SubscriptionInfo for default voice subscription. 1302 * 1303 * Will return null on data only devices, or on error. 1304 * 1305 * @return the SubscriptionInfo for the default voice subscription. 1306 * @hide 1307 */ 1308 public SubscriptionInfo getDefaultVoiceSubscriptionInfo() { 1309 return getActiveSubscriptionInfo(getDefaultVoiceSubscriptionId()); 1310 } 1311 1312 /** @hide */ 1313 public static int getDefaultVoicePhoneId() { 1314 return getPhoneId(getDefaultVoiceSubscriptionId()); 1315 } 1316 1317 /** 1318 * Returns the system's default SMS subscription id. 1319 * 1320 * On a data only device or on error, will return INVALID_SUBSCRIPTION_ID. 1321 * 1322 * @return the default SMS subscription Id. 1323 */ 1324 public static int getDefaultSmsSubscriptionId() { 1325 int subId = INVALID_SUBSCRIPTION_ID; 1326 1327 try { 1328 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1329 if (iSub != null) { 1330 subId = iSub.getDefaultSmsSubId(); 1331 } 1332 } catch (RemoteException ex) { 1333 // ignore it 1334 } 1335 1336 if (VDBG) logd("getDefaultSmsSubscriptionId, sub id = " + subId); 1337 return subId; 1338 } 1339 1340 /** @hide */ 1341 public void setDefaultSmsSubId(int subId) { 1342 if (VDBG) logd("setDefaultSmsSubId sub id = " + subId); 1343 try { 1344 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1345 if (iSub != null) { 1346 iSub.setDefaultSmsSubId(subId); 1347 } 1348 } catch (RemoteException ex) { 1349 // ignore it 1350 } 1351 } 1352 1353 /** 1354 * Return the SubscriptionInfo for default voice subscription. 1355 * 1356 * Will return null on data only devices, or on error. 1357 * 1358 * @return the SubscriptionInfo for the default SMS subscription. 1359 * @hide 1360 */ 1361 public SubscriptionInfo getDefaultSmsSubscriptionInfo() { 1362 return getActiveSubscriptionInfo(getDefaultSmsSubscriptionId()); 1363 } 1364 1365 /** @hide */ 1366 public int getDefaultSmsPhoneId() { 1367 return getPhoneId(getDefaultSmsSubscriptionId()); 1368 } 1369 1370 /** 1371 * Returns the system's default data subscription id. 1372 * 1373 * On a voice only device or on error, will return INVALID_SUBSCRIPTION_ID. 1374 * 1375 * @return the default data subscription Id. 1376 */ 1377 public static int getDefaultDataSubscriptionId() { 1378 int subId = INVALID_SUBSCRIPTION_ID; 1379 1380 try { 1381 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1382 if (iSub != null) { 1383 subId = iSub.getDefaultDataSubId(); 1384 } 1385 } catch (RemoteException ex) { 1386 // ignore it 1387 } 1388 1389 if (VDBG) logd("getDefaultDataSubscriptionId, sub id = " + subId); 1390 return subId; 1391 } 1392 1393 /** @hide */ 1394 public void setDefaultDataSubId(int subId) { 1395 if (VDBG) logd("setDataSubscription sub id = " + subId); 1396 try { 1397 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1398 if (iSub != null) { 1399 iSub.setDefaultDataSubId(subId); 1400 } 1401 } catch (RemoteException ex) { 1402 // ignore it 1403 } 1404 } 1405 1406 /** 1407 * Return the SubscriptionInfo for default data subscription. 1408 * 1409 * Will return null on voice only devices, or on error. 1410 * 1411 * @return the SubscriptionInfo for the default data subscription. 1412 * @hide 1413 */ 1414 public SubscriptionInfo getDefaultDataSubscriptionInfo() { 1415 return getActiveSubscriptionInfo(getDefaultDataSubscriptionId()); 1416 } 1417 1418 /** @hide */ 1419 public int getDefaultDataPhoneId() { 1420 return getPhoneId(getDefaultDataSubscriptionId()); 1421 } 1422 1423 /** @hide */ 1424 public void clearSubscriptionInfo() { 1425 try { 1426 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1427 if (iSub != null) { 1428 iSub.clearSubInfo(); 1429 } 1430 } catch (RemoteException ex) { 1431 // ignore it 1432 } 1433 1434 return; 1435 } 1436 1437 //FIXME this is vulnerable to race conditions 1438 /** @hide */ 1439 public boolean allDefaultsSelected() { 1440 if (!isValidSubscriptionId(getDefaultDataSubscriptionId())) { 1441 return false; 1442 } 1443 if (!isValidSubscriptionId(getDefaultSmsSubscriptionId())) { 1444 return false; 1445 } 1446 if (!isValidSubscriptionId(getDefaultVoiceSubscriptionId())) { 1447 return false; 1448 } 1449 return true; 1450 } 1451 1452 /** 1453 * If a default is set to subscription which is not active, this will reset that default back to 1454 * an invalid subscription id, i.e. < 0. 1455 * @hide 1456 */ 1457 public void clearDefaultsForInactiveSubIds() { 1458 if (VDBG) logd("clearDefaultsForInactiveSubIds"); 1459 try { 1460 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1461 if (iSub != null) { 1462 iSub.clearDefaultsForInactiveSubIds(); 1463 } 1464 } catch (RemoteException ex) { 1465 // ignore it 1466 } 1467 } 1468 1469 /** 1470 * @return true if a valid subId else false 1471 * @hide 1472 */ 1473 public static boolean isValidSubscriptionId(int subId) { 1474 return subId > INVALID_SUBSCRIPTION_ID ; 1475 } 1476 1477 /** 1478 * @return true if subId is an usable subId value else false. A 1479 * usable subId means its neither a INVALID_SUBSCRIPTION_ID nor a DEFAULT_SUB_ID. 1480 * @hide 1481 */ 1482 public static boolean isUsableSubIdValue(int subId) { 1483 return subId >= MIN_SUBSCRIPTION_ID_VALUE && subId <= MAX_SUBSCRIPTION_ID_VALUE; 1484 } 1485 1486 /** @hide */ 1487 public static boolean isValidSlotIndex(int slotIndex) { 1488 return slotIndex >= 0 && slotIndex < TelephonyManager.getDefault().getSimCount(); 1489 } 1490 1491 /** @hide */ 1492 public static boolean isValidPhoneId(int phoneId) { 1493 return phoneId >= 0 && phoneId < TelephonyManager.getDefault().getPhoneCount(); 1494 } 1495 1496 /** @hide */ 1497 public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId) { 1498 int[] subIds = SubscriptionManager.getSubId(phoneId); 1499 if (subIds != null && subIds.length > 0) { 1500 putPhoneIdAndSubIdExtra(intent, phoneId, subIds[0]); 1501 } else { 1502 logd("putPhoneIdAndSubIdExtra: no valid subs"); 1503 } 1504 } 1505 1506 /** @hide */ 1507 public static void putPhoneIdAndSubIdExtra(Intent intent, int phoneId, int subId) { 1508 if (VDBG) logd("putPhoneIdAndSubIdExtra: phoneId=" + phoneId + " subId=" + subId); 1509 intent.putExtra(PhoneConstants.SUBSCRIPTION_KEY, subId); 1510 intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId); 1511 intent.putExtra(PhoneConstants.PHONE_KEY, phoneId); 1512 //FIXME this is using phoneId and slotIndex interchangeably 1513 //Eventually, this should be removed as it is not the slot id 1514 intent.putExtra(PhoneConstants.SLOT_KEY, phoneId); 1515 } 1516 1517 /** 1518 * @return the list of subId's that are active, 1519 * is never null but the length maybe 0. 1520 * @hide 1521 */ 1522 public @NonNull int[] getActiveSubscriptionIdList() { 1523 int[] subId = null; 1524 1525 try { 1526 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1527 if (iSub != null) { 1528 subId = iSub.getActiveSubIdList(); 1529 } 1530 } catch (RemoteException ex) { 1531 // ignore it 1532 } 1533 1534 if (subId == null) { 1535 subId = new int[0]; 1536 } 1537 1538 return subId; 1539 1540 } 1541 1542 /** 1543 * Returns true if the device is considered roaming on the current 1544 * network for a subscription. 1545 * <p> 1546 * Availability: Only when user registered to a network. 1547 * 1548 * @param subId The subscription ID 1549 * @return true if the network for the subscription is roaming, false otherwise 1550 */ 1551 public boolean isNetworkRoaming(int subId) { 1552 final int phoneId = getPhoneId(subId); 1553 if (phoneId < 0) { 1554 // What else can we do? 1555 return false; 1556 } 1557 return TelephonyManager.getDefault().isNetworkRoaming(subId); 1558 } 1559 1560 /** 1561 * Returns a constant indicating the state of sim for the slot index. 1562 * 1563 * @param slotIndex 1564 * 1565 * {@See TelephonyManager#SIM_STATE_UNKNOWN} 1566 * {@See TelephonyManager#SIM_STATE_ABSENT} 1567 * {@See TelephonyManager#SIM_STATE_PIN_REQUIRED} 1568 * {@See TelephonyManager#SIM_STATE_PUK_REQUIRED} 1569 * {@See TelephonyManager#SIM_STATE_NETWORK_LOCKED} 1570 * {@See TelephonyManager#SIM_STATE_READY} 1571 * {@See TelephonyManager#SIM_STATE_NOT_READY} 1572 * {@See TelephonyManager#SIM_STATE_PERM_DISABLED} 1573 * {@See TelephonyManager#SIM_STATE_CARD_IO_ERROR} 1574 * 1575 * {@hide} 1576 */ 1577 public static int getSimStateForSlotIndex(int slotIndex) { 1578 int simState = TelephonyManager.SIM_STATE_UNKNOWN; 1579 1580 try { 1581 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1582 if (iSub != null) { 1583 simState = iSub.getSimStateForSlotIndex(slotIndex); 1584 } 1585 } catch (RemoteException ex) { 1586 } 1587 1588 return simState; 1589 } 1590 1591 /** 1592 * Store properties associated with SubscriptionInfo in database 1593 * @param subId Subscription Id of Subscription 1594 * @param propKey Column name in database associated with SubscriptionInfo 1595 * @param propValue Value to store in DB for particular subId & column name 1596 * @hide 1597 */ 1598 public static void setSubscriptionProperty(int subId, String propKey, String propValue) { 1599 try { 1600 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1601 if (iSub != null) { 1602 iSub.setSubscriptionProperty(subId, propKey, propValue); 1603 } 1604 } catch (RemoteException ex) { 1605 // ignore it 1606 } 1607 } 1608 1609 /** 1610 * Store properties associated with SubscriptionInfo in database 1611 * @param subId Subscription Id of Subscription 1612 * @param propKey Column name in SubscriptionInfo database 1613 * @return Value associated with subId and propKey column in database 1614 * @hide 1615 */ 1616 private static String getSubscriptionProperty(int subId, String propKey, 1617 Context context) { 1618 String resultValue = null; 1619 try { 1620 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1621 if (iSub != null) { 1622 resultValue = iSub.getSubscriptionProperty(subId, propKey, 1623 context.getOpPackageName()); 1624 } 1625 } catch (RemoteException ex) { 1626 // ignore it 1627 } 1628 return resultValue; 1629 } 1630 1631 /** 1632 * Returns boolean value corresponding to query result. 1633 * @param subId Subscription Id of Subscription 1634 * @param propKey Column name in SubscriptionInfo database 1635 * @param defValue Default boolean value to be returned 1636 * @return boolean result value to be returned 1637 * @hide 1638 */ 1639 public static boolean getBooleanSubscriptionProperty(int subId, String propKey, 1640 boolean defValue, Context context) { 1641 String result = getSubscriptionProperty(subId, propKey, context); 1642 if (result != null) { 1643 try { 1644 return Integer.parseInt(result) == 1; 1645 } catch (NumberFormatException err) { 1646 logd("getBooleanSubscriptionProperty NumberFormat exception"); 1647 } 1648 } 1649 return defValue; 1650 } 1651 1652 /** 1653 * Returns integer value corresponding to query result. 1654 * @param subId Subscription Id of Subscription 1655 * @param propKey Column name in SubscriptionInfo database 1656 * @param defValue Default integer value to be returned 1657 * @return integer result value to be returned 1658 * @hide 1659 */ 1660 public static int getIntegerSubscriptionProperty(int subId, String propKey, int defValue, 1661 Context context) { 1662 String result = getSubscriptionProperty(subId, propKey, context); 1663 if (result != null) { 1664 try { 1665 return Integer.parseInt(result); 1666 } catch (NumberFormatException err) { 1667 logd("getBooleanSubscriptionProperty NumberFormat exception"); 1668 } 1669 } 1670 return defValue; 1671 } 1672 1673 /** 1674 * Returns the resources associated with Subscription. 1675 * @param context Context object 1676 * @param subId Subscription Id of Subscription who's resources are required 1677 * @return Resources associated with Subscription. 1678 * @hide 1679 */ 1680 public static Resources getResourcesForSubId(Context context, int subId) { 1681 final SubscriptionInfo subInfo = 1682 SubscriptionManager.from(context).getActiveSubscriptionInfo(subId); 1683 1684 Configuration config = context.getResources().getConfiguration(); 1685 Configuration newConfig = new Configuration(); 1686 newConfig.setTo(config); 1687 if (subInfo != null) { 1688 newConfig.mcc = subInfo.getMcc(); 1689 newConfig.mnc = subInfo.getMnc(); 1690 if (newConfig.mnc == 0) newConfig.mnc = Configuration.MNC_ZERO; 1691 } 1692 DisplayMetrics metrics = context.getResources().getDisplayMetrics(); 1693 DisplayMetrics newMetrics = new DisplayMetrics(); 1694 newMetrics.setTo(metrics); 1695 return new Resources(context.getResources().getAssets(), newMetrics, newConfig); 1696 } 1697 1698 /** 1699 * @return true if the sub ID is active. i.e. The sub ID corresponds to a known subscription 1700 * and the SIM providing the subscription is present in a slot and in "LOADED" state. 1701 * @hide 1702 */ 1703 public boolean isActiveSubId(int subId) { 1704 try { 1705 ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub")); 1706 if (iSub != null) { 1707 return iSub.isActiveSubId(subId); 1708 } 1709 } catch (RemoteException ex) { 1710 } 1711 return false; 1712 } 1713 1714 /** 1715 * Get the description of the billing relationship plan between a carrier 1716 * and a specific subscriber. 1717 * <p> 1718 * This method is only accessible to the following narrow set of apps: 1719 * <ul> 1720 * <li>The carrier app for this subscriberId, as determined by 1721 * {@link TelephonyManager#hasCarrierPrivileges()}. 1722 * <li>The carrier app explicitly delegated access through 1723 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 1724 * </ul> 1725 * 1726 * @param subId the subscriber this relationship applies to 1727 * @throws SecurityException if the caller doesn't meet the requirements 1728 * outlined above. 1729 */ 1730 @SystemApi 1731 public @NonNull List<SubscriptionPlan> getSubscriptionPlans(int subId) { 1732 try { 1733 SubscriptionPlan[] subscriptionPlans = 1734 getNetworkPolicy().getSubscriptionPlans(subId, mContext.getOpPackageName()); 1735 return subscriptionPlans == null 1736 ? Collections.emptyList() : Arrays.asList(subscriptionPlans); 1737 } catch (RemoteException e) { 1738 throw e.rethrowFromSystemServer(); 1739 } 1740 } 1741 1742 /** 1743 * Set the description of the billing relationship plan between a carrier 1744 * and a specific subscriber. 1745 * <p> 1746 * This method is only accessible to the following narrow set of apps: 1747 * <ul> 1748 * <li>The carrier app for this subscriberId, as determined by 1749 * {@link TelephonyManager#hasCarrierPrivileges()}. 1750 * <li>The carrier app explicitly delegated access through 1751 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 1752 * </ul> 1753 * 1754 * @param subId the subscriber this relationship applies to. An empty list 1755 * may be sent to clear any existing plans. 1756 * @param plans the list of plans. The first plan is always the primary and 1757 * most important plan. Any additional plans are secondary and 1758 * may not be displayed or used by decision making logic. 1759 * @throws SecurityException if the caller doesn't meet the requirements 1760 * outlined above. 1761 */ 1762 @SystemApi 1763 public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) { 1764 try { 1765 getNetworkPolicy().setSubscriptionPlans(subId, 1766 plans.toArray(new SubscriptionPlan[plans.size()]), mContext.getOpPackageName()); 1767 } catch (RemoteException e) { 1768 throw e.rethrowFromSystemServer(); 1769 } 1770 } 1771 1772 /** @hide */ 1773 private String getSubscriptionPlansOwner(int subId) { 1774 try { 1775 return getNetworkPolicy().getSubscriptionPlansOwner(subId); 1776 } catch (RemoteException e) { 1777 throw e.rethrowFromSystemServer(); 1778 } 1779 } 1780 1781 /** 1782 * Temporarily override the billing relationship plan between a carrier and 1783 * a specific subscriber to be considered unmetered. This will be reflected 1784 * to apps via {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED}. 1785 * <p> 1786 * This method is only accessible to the following narrow set of apps: 1787 * <ul> 1788 * <li>The carrier app for this subscriberId, as determined by 1789 * {@link TelephonyManager#hasCarrierPrivileges()}. 1790 * <li>The carrier app explicitly delegated access through 1791 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 1792 * </ul> 1793 * 1794 * @param subId the subscriber this override applies to. 1795 * @param overrideUnmetered set if the billing relationship should be 1796 * considered unmetered. 1797 * @param timeoutMillis the timeout after which the requested override will 1798 * be automatically cleared, or {@code 0} to leave in the 1799 * requested state until explicitly cleared, or the next reboot, 1800 * whichever happens first. 1801 * @throws SecurityException if the caller doesn't meet the requirements 1802 * outlined above. 1803 */ 1804 @SystemApi 1805 public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered, 1806 @DurationMillisLong long timeoutMillis) { 1807 try { 1808 final int overrideValue = overrideUnmetered ? OVERRIDE_UNMETERED : 0; 1809 getNetworkPolicy().setSubscriptionOverride(subId, OVERRIDE_UNMETERED, overrideValue, 1810 timeoutMillis, mContext.getOpPackageName()); 1811 } catch (RemoteException e) { 1812 throw e.rethrowFromSystemServer(); 1813 } 1814 } 1815 1816 /** 1817 * Temporarily override the billing relationship plan between a carrier and 1818 * a specific subscriber to be considered congested. This will cause the 1819 * device to delay certain network requests when possible, such as developer 1820 * jobs that are willing to run in a flexible time window. 1821 * <p> 1822 * This method is only accessible to the following narrow set of apps: 1823 * <ul> 1824 * <li>The carrier app for this subscriberId, as determined by 1825 * {@link TelephonyManager#hasCarrierPrivileges()}. 1826 * <li>The carrier app explicitly delegated access through 1827 * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}. 1828 * </ul> 1829 * 1830 * @param subId the subscriber this override applies to. 1831 * @param overrideCongested set if the subscription should be considered 1832 * congested. 1833 * @param timeoutMillis the timeout after which the requested override will 1834 * be automatically cleared, or {@code 0} to leave in the 1835 * requested state until explicitly cleared, or the next reboot, 1836 * whichever happens first. 1837 * @throws SecurityException if the caller doesn't meet the requirements 1838 * outlined above. 1839 */ 1840 @SystemApi 1841 public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested, 1842 @DurationMillisLong long timeoutMillis) { 1843 try { 1844 final int overrideValue = overrideCongested ? OVERRIDE_CONGESTED : 0; 1845 getNetworkPolicy().setSubscriptionOverride(subId, OVERRIDE_CONGESTED, overrideValue, 1846 timeoutMillis, mContext.getOpPackageName()); 1847 } catch (RemoteException e) { 1848 throw e.rethrowFromSystemServer(); 1849 } 1850 } 1851 1852 /** 1853 * Create an {@link Intent} that can be launched towards the carrier app 1854 * that is currently defining the billing relationship plan through 1855 * {@link #setSubscriptionPlans(int, List)}. 1856 * 1857 * @return ready to launch Intent targeted towards the carrier app, or 1858 * {@code null} if no carrier app is defined, or if the defined 1859 * carrier app provides no management activity. 1860 * @hide 1861 */ 1862 public @Nullable Intent createManageSubscriptionIntent(int subId) { 1863 // Bail if no owner 1864 final String owner = getSubscriptionPlansOwner(subId); 1865 if (owner == null) return null; 1866 1867 // Bail if no plans 1868 final List<SubscriptionPlan> plans = getSubscriptionPlans(subId); 1869 if (plans.isEmpty()) return null; 1870 1871 final Intent intent = new Intent(ACTION_MANAGE_SUBSCRIPTION_PLANS); 1872 intent.setPackage(owner); 1873 intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId); 1874 1875 // Bail if not implemented 1876 if (mContext.getPackageManager().queryIntentActivities(intent, 1877 PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) { 1878 return null; 1879 } 1880 1881 return intent; 1882 } 1883 1884 /** @hide */ 1885 private @Nullable Intent createRefreshSubscriptionIntent(int subId) { 1886 // Bail if no owner 1887 final String owner = getSubscriptionPlansOwner(subId); 1888 if (owner == null) return null; 1889 1890 // Bail if no plans 1891 final List<SubscriptionPlan> plans = getSubscriptionPlans(subId); 1892 if (plans.isEmpty()) return null; 1893 1894 final Intent intent = new Intent(ACTION_REFRESH_SUBSCRIPTION_PLANS); 1895 intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); 1896 intent.setPackage(owner); 1897 intent.putExtra(EXTRA_SUBSCRIPTION_INDEX, subId); 1898 1899 // Bail if not implemented 1900 if (mContext.getPackageManager().queryBroadcastReceivers(intent, 0).isEmpty()) { 1901 return null; 1902 } 1903 1904 return intent; 1905 } 1906 1907 /** 1908 * Check if there is a carrier app that is currently defining the billing 1909 * relationship plan through {@link #setSubscriptionPlans(int, List)} that 1910 * supports refreshing of subscription plans. 1911 * 1912 * @hide 1913 */ 1914 public boolean isSubscriptionPlansRefreshSupported(int subId) { 1915 return createRefreshSubscriptionIntent(subId) != null; 1916 } 1917 1918 /** 1919 * Request that the carrier app that is currently defining the billing 1920 * relationship plan through {@link #setSubscriptionPlans(int, List)} 1921 * refresh its subscription plans. 1922 * <p> 1923 * If the app is able to successfully update the plans, you'll expect to 1924 * receive the {@link #ACTION_SUBSCRIPTION_PLANS_CHANGED} broadcast. 1925 * 1926 * @hide 1927 */ 1928 public void requestSubscriptionPlansRefresh(int subId) { 1929 final Intent intent = createRefreshSubscriptionIntent(subId); 1930 final BroadcastOptions options = BroadcastOptions.makeBasic(); 1931 options.setTemporaryAppWhitelistDuration(TimeUnit.MINUTES.toMillis(1)); 1932 mContext.sendBroadcast(intent, null, options.toBundle()); 1933 } 1934 1935 /** 1936 * Checks whether the app with the given context is authorized to manage the given subscription 1937 * according to its metadata. Only supported for embedded subscriptions (if 1938 * {@code SubscriptionInfo#isEmbedded} returns true). 1939 * 1940 * @param info The subscription to check. 1941 * @return whether the app is authorized to manage this subscription per its metadata. 1942 * @throws IllegalArgumentException if this subscription is not embedded. 1943 */ 1944 public boolean canManageSubscription(SubscriptionInfo info) { 1945 return canManageSubscription(info, mContext.getPackageName()); 1946 } 1947 1948 /** 1949 * Checks whether the given app is authorized to manage the given subscription. An app can only 1950 * be authorized if it is included in the {@link android.telephony.UiccAccessRule} of the 1951 * {@link android.telephony.SubscriptionInfo} with the access status. 1952 * Only supported for embedded subscriptions (if {@link SubscriptionInfo#isEmbedded} 1953 * returns true). 1954 * 1955 * @param info The subscription to check. 1956 * @param packageName Package name of the app to check. 1957 * @return whether the app is authorized to manage this subscription per its access rules. 1958 * @throws IllegalArgumentException if this subscription is not embedded. 1959 * @hide 1960 */ 1961 public boolean canManageSubscription(SubscriptionInfo info, String packageName) { 1962 if (!info.isEmbedded()) { 1963 throw new IllegalArgumentException("Not an embedded subscription"); 1964 } 1965 if (info.getAccessRules() == null) { 1966 return false; 1967 } 1968 PackageManager packageManager = mContext.getPackageManager(); 1969 PackageInfo packageInfo; 1970 try { 1971 packageInfo = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES); 1972 } catch (PackageManager.NameNotFoundException e) { 1973 throw new IllegalArgumentException("Unknown package: " + packageName, e); 1974 } 1975 for (UiccAccessRule rule : info.getAccessRules()) { 1976 if (rule.getCarrierPrivilegeStatus(packageInfo) 1977 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) { 1978 return true; 1979 } 1980 } 1981 return false; 1982 } 1983 } 1984