1 /* 2 * Copyright 2022 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 com.android.internal.telephony.subscription; 18 19 import static android.content.pm.PackageManager.FEATURE_TELEPHONY_SUBSCRIPTION; 20 import static android.telephony.TelephonyManager.ENABLE_FEATURE_MAPPING; 21 22 import android.Manifest; 23 import android.annotation.CallbackExecutor; 24 import android.annotation.ColorInt; 25 import android.annotation.EnforcePermission; 26 import android.annotation.NonNull; 27 import android.annotation.Nullable; 28 import android.annotation.RequiresPermission; 29 import android.annotation.UserIdInt; 30 import android.app.AppOpsManager; 31 import android.app.PendingIntent; 32 import android.app.compat.CompatChanges; 33 import android.compat.annotation.ChangeId; 34 import android.compat.annotation.EnabledSince; 35 import android.content.BroadcastReceiver; 36 import android.content.Context; 37 import android.content.Intent; 38 import android.content.IntentFilter; 39 import android.content.pm.PackageManager; 40 import android.content.res.Resources; 41 import android.net.Uri; 42 import android.os.Binder; 43 import android.os.Build; 44 import android.os.Bundle; 45 import android.os.CountDownTimer; 46 import android.os.Handler; 47 import android.os.HandlerThread; 48 import android.os.Looper; 49 import android.os.ParcelUuid; 50 import android.os.PersistableBundle; 51 import android.os.Process; 52 import android.os.RemoteException; 53 import android.os.SystemProperties; 54 import android.os.TelephonyServiceManager; 55 import android.os.UserHandle; 56 import android.os.UserManager; 57 import android.provider.DeviceConfig; 58 import android.provider.Settings; 59 import android.provider.Telephony.SimInfo; 60 import android.service.carrier.CarrierIdentifier; 61 import android.service.euicc.EuiccProfileInfo; 62 import android.service.euicc.EuiccService; 63 import android.service.euicc.GetEuiccProfileInfoListResult; 64 import android.telecom.PhoneAccountHandle; 65 import android.telecom.TelecomManager; 66 import android.telephony.AnomalyReporter; 67 import android.telephony.CarrierConfigManager; 68 import android.telephony.RadioAccessFamily; 69 import android.telephony.SubscriptionInfo; 70 import android.telephony.SubscriptionManager; 71 import android.telephony.SubscriptionManager.DataRoamingMode; 72 import android.telephony.SubscriptionManager.DeviceToDeviceStatusSharingPreference; 73 import android.telephony.SubscriptionManager.PhoneNumberSource; 74 import android.telephony.SubscriptionManager.SimDisplayNameSource; 75 import android.telephony.SubscriptionManager.SubscriptionType; 76 import android.telephony.SubscriptionManager.UsageSetting; 77 import android.telephony.TelephonyFrameworkInitializer; 78 import android.telephony.TelephonyManager; 79 import android.telephony.TelephonyManager.SimState; 80 import android.telephony.TelephonyRegistryManager; 81 import android.telephony.UiccAccessRule; 82 import android.telephony.euicc.EuiccManager; 83 import android.text.TextUtils; 84 import android.util.ArraySet; 85 import android.util.Base64; 86 import android.util.EventLog; 87 import android.util.IndentingPrintWriter; 88 import android.util.LocalLog; 89 90 import com.android.internal.R; 91 import com.android.internal.annotations.VisibleForTesting; 92 import com.android.internal.telephony.CarrierResolver; 93 import com.android.internal.telephony.ISetOpportunisticDataCallback; 94 import com.android.internal.telephony.ISub; 95 import com.android.internal.telephony.IccCard; 96 import com.android.internal.telephony.MccTable; 97 import com.android.internal.telephony.MultiSimSettingController; 98 import com.android.internal.telephony.Phone; 99 import com.android.internal.telephony.PhoneFactory; 100 import com.android.internal.telephony.ProxyController; 101 import com.android.internal.telephony.RILConstants; 102 import com.android.internal.telephony.TelephonyIntents; 103 import com.android.internal.telephony.TelephonyPermissions; 104 import com.android.internal.telephony.data.PhoneSwitcher; 105 import com.android.internal.telephony.euicc.EuiccController; 106 import com.android.internal.telephony.flags.FeatureFlags; 107 import com.android.internal.telephony.flags.Flags; 108 import com.android.internal.telephony.satellite.SatelliteController; 109 import com.android.internal.telephony.subscription.SubscriptionDatabaseManager.SubscriptionDatabaseManagerCallback; 110 import com.android.internal.telephony.uicc.IccRecords; 111 import com.android.internal.telephony.uicc.IccUtils; 112 import com.android.internal.telephony.uicc.UiccCard; 113 import com.android.internal.telephony.uicc.UiccController; 114 import com.android.internal.telephony.uicc.UiccPort; 115 import com.android.internal.telephony.uicc.UiccSlot; 116 import com.android.internal.telephony.util.ArrayUtils; 117 import com.android.internal.telephony.util.TelephonyUtils; 118 import com.android.telephony.Rlog; 119 120 import java.io.FileDescriptor; 121 import java.io.PrintWriter; 122 import java.util.ArrayList; 123 import java.util.Arrays; 124 import java.util.Collections; 125 import java.util.Comparator; 126 import java.util.List; 127 import java.util.Map; 128 import java.util.Objects; 129 import java.util.Optional; 130 import java.util.Random; 131 import java.util.Set; 132 import java.util.UUID; 133 import java.util.concurrent.ConcurrentHashMap; 134 import java.util.concurrent.Executor; 135 import java.util.stream.Collectors; 136 import java.util.stream.IntStream; 137 import java.util.stream.Stream; 138 139 /** 140 * The subscription manager service is the backend service of {@link SubscriptionManager}. 141 * The service handles all SIM subscription related requests from clients. 142 */ 143 public class SubscriptionManagerService extends ISub.Stub { 144 private static final String LOG_TAG = "SMSVC"; 145 private static final String ALLOW_MOCK_MODEM_PROPERTY = "persist.radio.allow_mock_modem"; 146 private static final String BOOT_ALLOW_MOCK_MODEM_PROPERTY = "ro.boot.radio.allow_mock_modem"; 147 148 private static final int CHECK_BOOTSTRAP_TIMER_IN_MS = 20 * 60 * 1000; // 20 minutes 149 private static CountDownTimer bootstrapProvisioningTimer; 150 151 /** Whether enabling verbose debugging message or not. */ 152 private static final boolean VDBG = false; 153 154 /** 155 * The columns in {@link SimInfo} table that can be directly accessed through 156 * {@link #getSubscriptionProperty(int, String, String, String)} or 157 * {@link #setSubscriptionProperty(int, String, String)}. Usually those fields are not 158 * sensitive. Mostly they are related to user settings, for example, wifi calling 159 * user settings, cross sim calling user settings, etc...Those fields are protected with 160 * {@link Manifest.permission#READ_PHONE_STATE} permission only. 161 * 162 * For sensitive fields, they usually requires special methods to access. For example, 163 * {@link #getSubscriptionUserHandle(int)} or {@link #getPhoneNumber(int, int, String, String)} 164 * that requires higher permission to access. 165 */ 166 private static final Set<String> DIRECT_ACCESS_SUBSCRIPTION_COLUMNS = Set.of( 167 SimInfo.COLUMN_CB_EXTREME_THREAT_ALERT, 168 SimInfo.COLUMN_CB_SEVERE_THREAT_ALERT, 169 SimInfo.COLUMN_CB_AMBER_ALERT, 170 SimInfo.COLUMN_CB_EMERGENCY_ALERT, 171 SimInfo.COLUMN_CB_ALERT_SOUND_DURATION, 172 SimInfo.COLUMN_CB_ALERT_REMINDER_INTERVAL, 173 SimInfo.COLUMN_CB_ALERT_VIBRATE, 174 SimInfo.COLUMN_CB_ALERT_SPEECH, 175 SimInfo.COLUMN_CB_ETWS_TEST_ALERT, 176 SimInfo.COLUMN_CB_CHANNEL_50_ALERT, 177 SimInfo.COLUMN_CB_CMAS_TEST_ALERT, 178 SimInfo.COLUMN_CB_OPT_OUT_DIALOG, 179 SimInfo.COLUMN_ENHANCED_4G_MODE_ENABLED, 180 SimInfo.COLUMN_VT_IMS_ENABLED, 181 SimInfo.COLUMN_WFC_IMS_ENABLED, 182 SimInfo.COLUMN_WFC_IMS_MODE, 183 SimInfo.COLUMN_WFC_IMS_ROAMING_MODE, 184 SimInfo.COLUMN_WFC_IMS_ROAMING_ENABLED, 185 SimInfo.COLUMN_ENABLED_MOBILE_DATA_POLICIES, 186 SimInfo.COLUMN_IMS_RCS_UCE_ENABLED, 187 SimInfo.COLUMN_CROSS_SIM_CALLING_ENABLED, 188 SimInfo.COLUMN_RCS_CONFIG, 189 SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS, 190 SimInfo.COLUMN_D2D_STATUS_SHARING, 191 SimInfo.COLUMN_VOIMS_OPT_IN_STATUS, 192 SimInfo.COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS, 193 SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED, 194 SimInfo.COLUMN_SATELLITE_ENABLED, 195 SimInfo.COLUMN_SATELLITE_ATTACH_ENABLED_FOR_CARRIER, 196 SimInfo.COLUMN_IS_NTN, 197 SimInfo.COLUMN_SATELLITE_ENTITLEMENT_STATUS, 198 SimInfo.COLUMN_SATELLITE_ENTITLEMENT_PLMNS 199 ); 200 201 /** 202 * Apps targeting on Android T and beyond will get exception if there is no access to device 203 * identifiers nor has carrier privileges when calling 204 * {@link SubscriptionManager#getSubscriptionsInGroup}. 205 */ 206 @ChangeId 207 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU) 208 public static final long REQUIRE_DEVICE_IDENTIFIERS_FOR_GROUP_UUID = 213902861L; 209 210 /** 211 * Apps targeting on Android V and beyond can only see subscriptions accessible by them 212 * according to its user Id. 213 */ 214 @ChangeId 215 @EnabledSince(targetSdkVersion = Build.VERSION_CODES.VANILLA_ICE_CREAM) 216 public static final long FILTER_ACCESSIBLE_SUBS_BY_USER = 296076674L; 217 218 /** Wrap Binder methods for testing. */ 219 @NonNull 220 private static final BinderWrapper BINDER_WRAPPER = new BinderWrapper(); 221 222 /** Instance of subscription manager service. */ 223 @NonNull 224 private static SubscriptionManagerService sInstance; 225 226 /** The context */ 227 @NonNull 228 private final Context mContext; 229 230 /** Feature flags */ 231 @NonNull 232 private final FeatureFlags mFeatureFlags; 233 234 /** App Ops manager instance. */ 235 @NonNull 236 private final AppOpsManager mAppOpsManager; 237 238 /** Telephony manager instance. */ 239 @NonNull 240 private final TelephonyManager mTelephonyManager; 241 242 /** Subscription manager instance. */ 243 @NonNull 244 private final SubscriptionManager mSubscriptionManager; 245 246 /** 247 * Euicc manager instance. Will be null if the device does not support 248 * {@link PackageManager#FEATURE_TELEPHONY_EUICC}. 249 */ 250 @Nullable 251 private final EuiccManager mEuiccManager; 252 253 /** Uicc controller instance. */ 254 @NonNull 255 private final UiccController mUiccController; 256 257 /** 258 * Euicc controller instance. Will be null if the device does not support 259 * {@link PackageManager#FEATURE_TELEPHONY_EUICC}. 260 */ 261 @Nullable 262 private EuiccController mEuiccController; 263 264 /** Package manager instance. */ 265 @NonNull 266 private final PackageManager mPackageManager; 267 268 /** 269 * The main handler of subscription manager service. This is running on phone process's main 270 * thread. 271 */ 272 @NonNull 273 private final Handler mHandler; 274 275 /** 276 * The background handler. This is running on a separate thread. 277 */ 278 @NonNull 279 private final Handler mBackgroundHandler; 280 281 /** Local log for most important debug messages. */ 282 @NonNull 283 private final LocalLog mLocalLog = new LocalLog(256); 284 285 /** The subscription database manager. */ 286 @NonNull 287 private final SubscriptionDatabaseManager mSubscriptionDatabaseManager; 288 289 /** The slot index subscription id map. Key is the slot index, and the value is sub id. */ 290 @NonNull 291 private final SubscriptionMap<Integer, Integer> mSlotIndexToSubId = new SubscriptionMap<>(); 292 293 /** Subscription manager service callbacks. */ 294 @NonNull 295 private final Set<SubscriptionManagerServiceCallback> mSubscriptionManagerServiceCallbacks = 296 new ArraySet<>(); 297 298 /** 299 * Default sub id. Derived from {@link #mDefaultVoiceSubId} and {@link #mDefaultDataSubId}, 300 * depending on device capability. 301 */ 302 @NonNull 303 private final WatchedInt mDefaultSubId; 304 305 /** Default voice subscription id. */ 306 @NonNull 307 private final WatchedInt mDefaultVoiceSubId; 308 309 /** Default data subscription id. */ 310 @NonNull 311 private final WatchedInt mDefaultDataSubId; 312 313 /** Default sms subscription id. */ 314 @NonNull 315 private final WatchedInt mDefaultSmsSubId; 316 317 /** Sim state per logical SIM slot index. */ 318 @NonNull 319 private final int[] mSimState; 320 321 /** Vendor API level from system property. */ 322 private final int mVendorApiLevel; 323 324 /** 325 * {@code true} if a user profile can only see the SIMs associated with it, unless it possesses 326 * no SIMs on the device. 327 */ 328 private Map<Integer, List<Integer>> mUserIdToAvailableSubs = new ConcurrentHashMap<>(); 329 330 /** 331 * Slot index/subscription map that automatically invalidate cache in 332 * {@link SubscriptionManager}. 333 * 334 * @param <K> The type of the key. 335 * @param <V> The type of the value. 336 */ 337 @VisibleForTesting 338 public static class SubscriptionMap<K, V> extends ConcurrentHashMap<K, V> { 339 @Override clear()340 public void clear() { 341 super.clear(); 342 SubscriptionManager.invalidateSubscriptionManagerServiceCaches(); 343 } 344 345 @Override put(K key, V value)346 public V put(K key, V value) { 347 V oldValue = super.put(key, value); 348 if (!Objects.equals(oldValue, value)) { 349 SubscriptionManager.invalidateSubscriptionManagerServiceCaches(); 350 } 351 return oldValue; 352 } 353 354 @Override remove(Object key)355 public V remove(Object key) { 356 V oldValue = super.remove(key); 357 if (oldValue != null) { 358 SubscriptionManager.invalidateSubscriptionManagerServiceCaches(); 359 } 360 return oldValue; 361 } 362 } 363 364 /** 365 * Watched integer. 366 */ 367 public static class WatchedInt { 368 protected int mValue; 369 370 /** 371 * Constructor. 372 * 373 * @param initialValue The initial value. 374 */ WatchedInt(int initialValue)375 public WatchedInt(int initialValue) { 376 mValue = initialValue; 377 } 378 379 /** 380 * @return The value. 381 */ get()382 public int get() { 383 return mValue; 384 } 385 386 /** 387 * Set the value. 388 * 389 * @param newValue The new value. 390 * 391 * @return {@code true} if {@code newValue} is different from the existing value. 392 */ set(int newValue)393 public boolean set(int newValue) { 394 if (mValue != newValue) { 395 mValue = newValue; 396 SubscriptionManager.invalidateSubscriptionManagerServiceCaches(); 397 return true; 398 } 399 return false; 400 } 401 } 402 403 /** Binder Wrapper for test mocking. */ 404 @VisibleForTesting 405 public static class BinderWrapper { getCallingUserHandle()406 @NonNull public UserHandle getCallingUserHandle() { 407 return Binder.getCallingUserHandle(); 408 } 409 } 410 411 /** 412 * This is the callback used for listening events from {@link SubscriptionManagerService}. 413 */ 414 public static class SubscriptionManagerServiceCallback { 415 /** The executor of the callback. */ 416 @NonNull 417 private final Executor mExecutor; 418 419 /** 420 * Constructor 421 * 422 * @param executor The executor of the callback. 423 */ SubscriptionManagerServiceCallback(@onNull @allbackExecutor Executor executor)424 public SubscriptionManagerServiceCallback(@NonNull @CallbackExecutor Executor executor) { 425 mExecutor = executor; 426 } 427 428 /** 429 * @return The executor of the callback. 430 */ 431 @NonNull 432 @VisibleForTesting getExecutor()433 public Executor getExecutor() { 434 return mExecutor; 435 } 436 437 /** 438 * Invoke the callback from executor. 439 * 440 * @param runnable The callback method to invoke. 441 */ invokeFromExecutor(@onNull Runnable runnable)442 public void invokeFromExecutor(@NonNull Runnable runnable) { 443 mExecutor.execute(runnable); 444 } 445 446 /** 447 * Called when subscription changed. 448 * 449 * @param subId The subscription id. 450 */ onSubscriptionChanged(int subId)451 public void onSubscriptionChanged(int subId) {} 452 453 /** 454 * Called when {@link SubscriptionInfoInternal#areUiccApplicationsEnabled()} changed. 455 * 456 * @param subId The subscription id. 457 */ onUiccApplicationsEnabledChanged(int subId)458 public void onUiccApplicationsEnabledChanged(int subId) {} 459 } 460 461 /** 462 * The constructor 463 * 464 * @param context The context 465 * @param looper The looper for the handler. 466 */ SubscriptionManagerService(@onNull Context context, @NonNull Looper looper, @NonNull FeatureFlags featureFlags)467 public SubscriptionManagerService(@NonNull Context context, @NonNull Looper looper, 468 @NonNull FeatureFlags featureFlags) { 469 logl("Created SubscriptionManagerService"); 470 sInstance = this; 471 mContext = context; 472 mFeatureFlags = featureFlags; 473 mTelephonyManager = context.getSystemService(TelephonyManager.class); 474 mSubscriptionManager = context.getSystemService(SubscriptionManager.class); 475 mEuiccManager = context.getSystemService(EuiccManager.class); 476 mAppOpsManager = context.getSystemService(AppOpsManager.class); 477 mPackageManager = context.getPackageManager(); 478 mVendorApiLevel = SystemProperties.getInt( 479 "ro.vendor.api_level", Build.VERSION.DEVICE_INITIAL_SDK_INT); 480 481 mUiccController = UiccController.getInstance(); 482 mHandler = new Handler(looper); 483 484 HandlerThread backgroundThread = new HandlerThread(LOG_TAG); 485 backgroundThread.start(); 486 487 mBackgroundHandler = new Handler(backgroundThread.getLooper()); 488 489 mDefaultVoiceSubId = new WatchedInt(Settings.Global.getInt(mContext.getContentResolver(), 490 Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION, 491 SubscriptionManager.INVALID_SUBSCRIPTION_ID)) { 492 @Override 493 public boolean set(int newValue) { 494 int oldValue = mValue; 495 if (super.set(newValue)) { 496 logl("Default voice subId changed from " + oldValue + " to " + newValue); 497 Settings.Global.putInt(mContext.getContentResolver(), 498 Settings.Global.MULTI_SIM_VOICE_CALL_SUBSCRIPTION, newValue); 499 return true; 500 } 501 return false; 502 } 503 }; 504 505 mDefaultDataSubId = new WatchedInt(Settings.Global.getInt(mContext.getContentResolver(), 506 Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION, 507 SubscriptionManager.INVALID_SUBSCRIPTION_ID)) { 508 @Override 509 public boolean set(int newValue) { 510 int oldValue = mValue; 511 if (super.set(newValue)) { 512 logl("Default data subId changed from " + oldValue + " to " + newValue); 513 Settings.Global.putInt(mContext.getContentResolver(), 514 Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION, newValue); 515 return true; 516 } 517 return false; 518 } 519 }; 520 521 mDefaultSmsSubId = new WatchedInt(Settings.Global.getInt(mContext.getContentResolver(), 522 Settings.Global.MULTI_SIM_SMS_SUBSCRIPTION, 523 SubscriptionManager.INVALID_SUBSCRIPTION_ID)) { 524 @Override 525 public boolean set(int newValue) { 526 int oldValue = mValue; 527 if (super.set(newValue)) { 528 logl("Default SMS subId changed from " + oldValue + " to " + newValue); 529 Settings.Global.putInt(mContext.getContentResolver(), 530 Settings.Global.MULTI_SIM_SMS_SUBSCRIPTION, newValue); 531 return true; 532 } 533 return false; 534 } 535 }; 536 537 mDefaultSubId = new WatchedInt(SubscriptionManager.INVALID_SUBSCRIPTION_ID); 538 539 mSimState = new int[mTelephonyManager.getSupportedModemCount()]; 540 Arrays.fill(mSimState, TelephonyManager.SIM_STATE_UNKNOWN); 541 542 // Create a separate thread for subscription database manager. The database will be updated 543 // from a different thread. 544 HandlerThread handlerThread = new HandlerThread(LOG_TAG); 545 handlerThread.start(); 546 mSubscriptionDatabaseManager = new SubscriptionDatabaseManager(context, 547 handlerThread.getLooper(), mFeatureFlags, 548 new SubscriptionDatabaseManagerCallback(mHandler::post) { 549 /** 550 * Called when database has been loaded into the cache. 551 */ 552 @Override 553 public void onInitialized() { 554 log("Subscription database has been initialized."); 555 for (int phoneId = 0; phoneId < mTelephonyManager.getSupportedModemCount() 556 ; phoneId++) { 557 markSubscriptionsInactive(phoneId); 558 } 559 } 560 561 /** 562 * Called when subscription changed. 563 * 564 * @param subId The subscription id. 565 */ 566 @Override 567 public void onSubscriptionChanged(int subId) { 568 updateUserIdToAvailableSubs(); 569 570 mSubscriptionManagerServiceCallbacks.forEach( 571 callback -> callback.invokeFromExecutor( 572 () -> callback.onSubscriptionChanged(subId))); 573 574 MultiSimSettingController.getInstance().notifySubscriptionInfoChanged(); 575 576 TelephonyRegistryManager telephonyRegistryManager = 577 mContext.getSystemService(TelephonyRegistryManager.class); 578 if (telephonyRegistryManager != null) { 579 telephonyRegistryManager.notifySubscriptionInfoChanged(); 580 } 581 582 SubscriptionInfoInternal subInfo = 583 mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subId); 584 if (subInfo != null && subInfo.isOpportunistic() 585 && telephonyRegistryManager != null) { 586 telephonyRegistryManager.notifyOpportunisticSubscriptionInfoChanged(); 587 } 588 } 589 }); 590 591 // Broadcast sub Id on service initialized. 592 broadcastSubId(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED, 593 getDefaultDataSubId()); 594 broadcastSubId(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED, 595 getDefaultVoiceSubId()); 596 broadcastSubId(SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED, 597 getDefaultSmsSubId()); 598 updateDefaultSubId(); 599 600 TelephonyServiceManager.ServiceRegisterer subscriptionServiceRegisterer = 601 TelephonyFrameworkInitializer 602 .getTelephonyServiceManager() 603 .getSubscriptionServiceRegisterer(); 604 if (subscriptionServiceRegisterer.get() == null) { 605 subscriptionServiceRegisterer.register(this); 606 } 607 608 mHandler.post(() -> { 609 // EuiccController is created after SubscriptionManagerService. So we need to get 610 // the instance later in the handler. 611 if (mContext.getPackageManager().hasSystemFeature( 612 PackageManager.FEATURE_TELEPHONY_EUICC)) { 613 mEuiccController = EuiccController.get(); 614 } 615 }); 616 617 SubscriptionManager.invalidateSubscriptionManagerServiceCaches(); 618 619 mContext.registerReceiver(new BroadcastReceiver() { 620 @Override 621 public void onReceive(Context context, Intent intent) { 622 updateEmbeddedSubscriptions(); 623 } 624 }, new IntentFilter(Intent.ACTION_USER_UNLOCKED)); 625 logl("Registered iSub service"); 626 } 627 628 /** 629 * @return The singleton instance of {@link SubscriptionManagerService}. 630 */ 631 @NonNull getInstance()632 public static SubscriptionManagerService getInstance() { 633 return sInstance; 634 } 635 636 /** 637 * Check if the calling package can manage the subscription group. 638 * 639 * @param groupUuid a UUID assigned to the subscription group. 640 * @param callingPackage the package making the IPC. 641 * 642 * @return {@code true} if calling package is the owner of or has carrier privileges for all 643 * subscriptions in the group. 644 */ canPackageManageGroup(@onNull ParcelUuid groupUuid, @NonNull String callingPackage)645 private boolean canPackageManageGroup(@NonNull ParcelUuid groupUuid, 646 @NonNull String callingPackage) { 647 if (groupUuid == null) { 648 throw new IllegalArgumentException("Invalid groupUuid"); 649 } 650 651 if (TextUtils.isEmpty(callingPackage)) { 652 throw new IllegalArgumentException("Empty callingPackage"); 653 } 654 655 List<SubscriptionInfo> infoList; 656 657 // Getting all subscriptions in the group. 658 infoList = mSubscriptionDatabaseManager.getAllSubscriptions().stream() 659 .filter(subInfo -> subInfo.getGroupUuid().equals(groupUuid.toString())) 660 .map(SubscriptionInfoInternal::toSubscriptionInfo) 661 .collect(Collectors.toList()); 662 663 // If the group does not exist, then by default the UUID is up for grabs so no need to 664 // restrict management of a group (that someone may be attempting to create). 665 if (ArrayUtils.isEmpty(infoList)) { 666 return true; 667 } 668 669 // If the calling package is the group owner, skip carrier permission check and return 670 // true as it was done before. 671 if (callingPackage.equals(infoList.get(0).getGroupOwner())) return true; 672 673 // Check carrier privilege for all subscriptions in the group. 674 return (checkCarrierPrivilegeOnSubList(infoList.stream() 675 .mapToInt(SubscriptionInfo::getSubscriptionId).toArray(), callingPackage)); 676 } 677 678 /** 679 * Helper function to check if the caller has carrier privilege permissions on a list of subId. 680 * The check can either be processed against access rules on currently active SIM cards, or 681 * the access rules we keep in our database for currently inactive SIMs. 682 * 683 * @param subIdList List of subscription ids. 684 * @param callingPackage The package making the call. 685 * 686 * @throws IllegalArgumentException if the some subId is invalid or doesn't exist. 687 * 688 * @return {@code true} if checking passes on all subId, {@code false} otherwise. 689 */ checkCarrierPrivilegeOnSubList(@onNull int[] subIdList, @NonNull String callingPackage)690 private boolean checkCarrierPrivilegeOnSubList(@NonNull int[] subIdList, 691 @NonNull String callingPackage) { 692 for (int subId : subIdList) { 693 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 694 .getSubscriptionInfoInternal(subId); 695 if (subInfo == null) { 696 loge("checkCarrierPrivilegeOnSubList: subId " + subId + " does not exist."); 697 return false; 698 } 699 700 if (subInfo.isActive()) { 701 if (!mTelephonyManager.hasCarrierPrivileges(subId)) { 702 loge("checkCarrierPrivilegeOnSubList: Does not have carrier privilege on sub " 703 + subId); 704 return false; 705 } 706 } else { 707 if (!mSubscriptionManager.canManageSubscription(subInfo.toSubscriptionInfo(), 708 callingPackage)) { 709 loge("checkCarrierPrivilegeOnSubList: cannot manage sub " + subId); 710 return false; 711 } 712 } 713 } 714 715 return true; 716 } 717 718 /** 719 * Sync the settings from specified subscription to all grouped subscriptions. 720 * 721 * @param subId The subscription id of the referenced subscription. 722 */ syncGroupedSetting(int subId)723 public void syncGroupedSetting(int subId) { 724 mHandler.post(() -> { 725 SubscriptionInfoInternal reference = mSubscriptionDatabaseManager 726 .getSubscriptionInfoInternal(subId); 727 if (reference == null) { 728 loge("syncSettings: Can't find subscription info for sub " + subId); 729 return; 730 } 731 732 mSubscriptionDatabaseManager.syncToGroup(subId); 733 }); 734 } 735 736 /** 737 * Check whether the {@code callingPackage} has access to the phone number on the specified 738 * {@code subId} or not. 739 * 740 * @param subId The subscription id. 741 * @param callingPackage The package making the call. 742 * @param callingFeatureId The feature in the package. 743 * @param message Message to include in the exception or NoteOp. 744 * 745 * @return {@code true} if the caller has phone number access. 746 */ hasPhoneNumberAccess(int subId, @NonNull String callingPackage, @Nullable String callingFeatureId, @Nullable String message)747 private boolean hasPhoneNumberAccess(int subId, @NonNull String callingPackage, 748 @Nullable String callingFeatureId, @Nullable String message) { 749 try { 750 return TelephonyPermissions.checkCallingOrSelfReadPhoneNumber(mContext, subId, 751 callingPackage, callingFeatureId, message); 752 } catch (SecurityException e) { 753 return false; 754 } 755 } 756 757 /** 758 * Check whether the {@code callingPackage} has access to subscriber identifiers on the 759 * specified {@code subId} or not. 760 * 761 * @param subId The subscription id. 762 * @param callingPackage The package making the call. 763 * @param callingFeatureId The feature in the package. 764 * @param message Message to include in the exception or NoteOp. 765 * @param reportFailure Indicates if failure should be reported. 766 * 767 * @return {@code true} if the caller has identifier access. 768 */ hasSubscriberIdentifierAccess(int subId, @NonNull String callingPackage, @Nullable String callingFeatureId, @Nullable String message, boolean reportFailure)769 private boolean hasSubscriberIdentifierAccess(int subId, @NonNull String callingPackage, 770 @Nullable String callingFeatureId, @Nullable String message, boolean reportFailure) { 771 try { 772 return TelephonyPermissions.checkCallingOrSelfReadSubscriberIdentifiers(mContext, subId, 773 callingPackage, callingFeatureId, message, reportFailure); 774 } catch (SecurityException e) { 775 // A SecurityException indicates that the calling package is targeting at least the 776 // minimum level that enforces identifier access restrictions and the new access 777 // requirements are not met. 778 return false; 779 } 780 } 781 782 /** 783 * Conditionally removes identifiers from the provided {@link SubscriptionInfo} if the {@code 784 * callingPackage} does not meet the access requirements for identifiers and returns the 785 * potentially modified object. 786 * 787 * <p> 788 * If the caller does not have {@link Manifest.permission#READ_PHONE_NUMBERS} permission, 789 * {@link SubscriptionInfo#getNumber()} will return empty string. 790 * If the caller does not have {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER}, 791 * {@link SubscriptionInfo#getIccId()} and {@link SubscriptionInfo#getCardString()} will return 792 * empty string, and {@link SubscriptionInfo#getGroupUuid()} will return {@code null}. 793 * 794 * @param subInfo The subscription info. 795 * @param callingPackage The package making the call. 796 * @param callingFeatureId The feature in the package. 797 * @param message Message to include in the exception or NoteOp. 798 * 799 * @return The modified {@link SubscriptionInfo} depending on caller's permission. 800 */ 801 @NonNull conditionallyRemoveIdentifiers(@onNull SubscriptionInfo subInfo, @NonNull String callingPackage, @Nullable String callingFeatureId, @Nullable String message)802 private SubscriptionInfo conditionallyRemoveIdentifiers(@NonNull SubscriptionInfo subInfo, 803 @NonNull String callingPackage, @Nullable String callingFeatureId, 804 @Nullable String message) { 805 int subId = subInfo.getSubscriptionId(); 806 boolean hasIdentifierAccess = hasSubscriberIdentifierAccess(subId, callingPackage, 807 callingFeatureId, message, true); 808 boolean hasPhoneNumberAccess = hasPhoneNumberAccess(subId, callingPackage, 809 callingFeatureId, message); 810 811 if (hasIdentifierAccess && hasPhoneNumberAccess) { 812 return subInfo; 813 } 814 815 SubscriptionInfo.Builder result = new SubscriptionInfo.Builder(subInfo); 816 if (!hasIdentifierAccess) { 817 result.setIccId(null); 818 result.setCardString(null); 819 result.setGroupUuid(null); 820 } 821 822 if (!hasPhoneNumberAccess) { 823 result.setNumber(null); 824 } 825 return result.build(); 826 } 827 828 /** 829 * @return The list of ICCIDs from the inserted physical SIMs. 830 */ 831 @NonNull getIccIdsOfInsertedPhysicalSims()832 private List<String> getIccIdsOfInsertedPhysicalSims() { 833 List<String> iccidList = new ArrayList<>(); 834 UiccSlot[] uiccSlots = mUiccController.getUiccSlots(); 835 if (uiccSlots == null) return iccidList; 836 837 for (UiccSlot uiccSlot : uiccSlots) { 838 if (uiccSlot != null && uiccSlot.getCardState() != null 839 && uiccSlot.getCardState().isCardPresent() && !uiccSlot.isEuicc()) { 840 // Non euicc slots will have single port, so use default port index. 841 String iccId = uiccSlot.getIccId(TelephonyManager.DEFAULT_PORT_INDEX); 842 if (!TextUtils.isEmpty(iccId)) { 843 iccidList.add(IccUtils.stripTrailingFs(iccId)); 844 } 845 } 846 } 847 848 return iccidList; 849 } 850 851 /** 852 * Set the subscription carrier id. 853 * 854 * @param subId Subscription id. 855 * @param carrierId The carrier id. 856 * 857 * @throws IllegalArgumentException if {@code subId} is invalid or the subscription does not 858 * exist. 859 * 860 * @see TelephonyManager#getSimCarrierId() 861 */ setCarrierId(int subId, int carrierId)862 public void setCarrierId(int subId, int carrierId) { 863 // This can throw IllegalArgumentException if the subscription does not exist. 864 try { 865 mSubscriptionDatabaseManager.setCarrierId(subId, carrierId); 866 } catch (IllegalArgumentException e) { 867 loge("setCarrierId: invalid subId=" + subId); 868 } 869 } 870 871 /** 872 * Set MCC/MNC by subscription id. 873 * 874 * @param mccMnc MCC/MNC associated with the subscription. 875 * @param subId The subscription id. 876 */ setMccMnc(int subId, @NonNull String mccMnc)877 public void setMccMnc(int subId, @NonNull String mccMnc) { 878 // This can throw IllegalArgumentException if the subscription does not exist. 879 try { 880 mSubscriptionDatabaseManager.setMcc(subId, mccMnc.substring(0, 3)); 881 mSubscriptionDatabaseManager.setMnc(subId, mccMnc.substring(3)); 882 } catch (IllegalArgumentException e) { 883 loge("setMccMnc: invalid subId=" + subId); 884 } 885 } 886 887 /** 888 * Set whether the subscription ID supports oem satellite or not. 889 * 890 * @param subId The subscription ID. 891 * @param isNtn {@code true} Requested subscription ID supports oem satellite service, 892 * {@code false} otherwise. 893 */ setNtn(int subId, boolean isNtn)894 public void setNtn(int subId, boolean isNtn) { 895 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 896 return; 897 } 898 899 // This can throw IllegalArgumentException if the subscription does not exist. 900 try { 901 mSubscriptionDatabaseManager.setNtn(subId, (isNtn ? 1 : 0)); 902 } catch (IllegalArgumentException e) { 903 loge("setOnlyNonTerrestrialNetwork: invalid subId=" + subId); 904 } 905 } 906 907 /** 908 * Set ISO country code by subscription id. 909 * 910 * @param iso ISO country code associated with the subscription. 911 * @param subId The subscription id. 912 */ setCountryIso(int subId, @NonNull String iso)913 public void setCountryIso(int subId, @NonNull String iso) { 914 // This can throw IllegalArgumentException if the subscription does not exist. 915 try { 916 mSubscriptionDatabaseManager.setCountryIso(subId, iso); 917 } catch (IllegalArgumentException e) { 918 loge("setCountryIso: invalid subId=" + subId); 919 } 920 } 921 922 /** 923 * Set the name displayed to the user that identifies subscription provider name. This name 924 * is the SPN displayed in status bar and many other places. Can't be renamed by the user. 925 * 926 * @param subId Subscription id. 927 * @param carrierName The carrier name. 928 */ setCarrierName(int subId, @NonNull String carrierName)929 public void setCarrierName(int subId, @NonNull String carrierName) { 930 // This can throw IllegalArgumentException if the subscription does not exist. 931 try { 932 mSubscriptionDatabaseManager.setCarrierName(subId, carrierName); 933 } catch (IllegalArgumentException e) { 934 loge("setCarrierName: invalid subId=" + subId); 935 } 936 } 937 938 /** 939 * Set the group owner on the subscription 940 * 941 * <p> Note: This only sets the group owner field and doesn't update other relevant fields. 942 * Prefer to call {@link #addSubscriptionsIntoGroup}. 943 * 944 * @param subId Subscription id. 945 * @param groupOwner The group owner to assign to the subscription 946 * 947 * @throws SecurityException if the caller does not have required permissions. 948 */ 949 @Override 950 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setGroupOwner(int subId, @NonNull String groupOwner)951 public void setGroupOwner(int subId, @NonNull String groupOwner) { 952 enforcePermissions("setGroupOwner", Manifest.permission.MODIFY_PHONE_STATE); 953 try { 954 mSubscriptionDatabaseManager.setGroupOwner( 955 subId, 956 groupOwner); 957 } catch (IllegalArgumentException e) { 958 loge("setManaged: invalid subId=" + subId); 959 } 960 } 961 962 /** 963 * Set last used TP message reference. 964 * 965 * @param subId Subscription id. 966 * @param lastUsedTPMessageReference Last used TP message reference. 967 */ setLastUsedTPMessageReference(int subId, int lastUsedTPMessageReference)968 public void setLastUsedTPMessageReference(int subId, int lastUsedTPMessageReference) { 969 // This can throw IllegalArgumentException if the subscription does not exist. 970 try { 971 mSubscriptionDatabaseManager.setLastUsedTPMessageReference( 972 subId, lastUsedTPMessageReference); 973 } catch (IllegalArgumentException e) { 974 loge("setLastUsedTPMessageReference: invalid subId=" + subId); 975 } 976 } 977 978 /** 979 * Set the enabled mobile data policies. 980 * 981 * @param subId Subscription id. 982 * @param enabledMobileDataPolicies The enabled mobile data policies. 983 */ setEnabledMobileDataPolicies(int subId, @NonNull String enabledMobileDataPolicies)984 public void setEnabledMobileDataPolicies(int subId, @NonNull String enabledMobileDataPolicies) { 985 // This can throw IllegalArgumentException if the subscription does not exist. 986 try { 987 mSubscriptionDatabaseManager.setEnabledMobileDataPolicies( 988 subId, enabledMobileDataPolicies); 989 } catch (IllegalArgumentException e) { 990 loge("setEnabledMobileDataPolicies: invalid subId=" + subId); 991 } 992 } 993 994 /** 995 * Set the phone number retrieved from IMS. 996 * 997 * @param subId Subscription id. 998 * @param numberFromIms The phone number retrieved from IMS. 999 */ setNumberFromIms(int subId, @NonNull String numberFromIms)1000 public void setNumberFromIms(int subId, @NonNull String numberFromIms) { 1001 // This can throw IllegalArgumentException if the subscription does not exist. 1002 try { 1003 mSubscriptionDatabaseManager.setNumberFromIms(subId, numberFromIms); 1004 } catch (IllegalArgumentException e) { 1005 loge("setNumberFromIms: invalid subId=" + subId); 1006 } 1007 } 1008 1009 /** 1010 * Mark all subscriptions on this SIM slot index inactive. 1011 * 1012 * @param simSlotIndex The logical SIM slot index (i.e. phone id). 1013 */ markSubscriptionsInactive(int simSlotIndex)1014 public void markSubscriptionsInactive(int simSlotIndex) { 1015 logl("markSubscriptionsInactive: slot " + simSlotIndex); 1016 mSlotIndexToSubId.remove(simSlotIndex); 1017 mSubscriptionDatabaseManager.getAllSubscriptions().stream() 1018 .filter(subInfo -> subInfo.getSimSlotIndex() == simSlotIndex) 1019 .forEach(subInfo -> { 1020 mSubscriptionDatabaseManager.setSimSlotIndex(subInfo.getSubscriptionId(), 1021 SubscriptionManager.INVALID_SIM_SLOT_INDEX); 1022 // Sometime even though slot-port is inactive, proper iccid will be present, 1023 // hence retry the port index from UiccSlot. (Pre-U behavior) 1024 mSubscriptionDatabaseManager.setPortIndex(subInfo.getSubscriptionId(), 1025 getPortIndex(subInfo.getIccId())); 1026 }); 1027 updateGroupDisabled(); 1028 logl("markSubscriptionsInactive: current mapping " + slotMappingToString()); 1029 } 1030 1031 /** 1032 * This is only for internal use and the returned priority is arbitrary. The idea is to give a 1033 * higher value to name source that has higher priority to override other name sources. 1034 * 1035 * @param nameSource Source of display name. 1036 * 1037 * @return The priority. Higher value means higher priority. 1038 */ getNameSourcePriority(@imDisplayNameSource int nameSource)1039 private static int getNameSourcePriority(@SimDisplayNameSource int nameSource) { 1040 int index = Arrays.asList( 1041 SubscriptionManager.NAME_SOURCE_UNKNOWN, 1042 SubscriptionManager.NAME_SOURCE_CARRIER_ID, 1043 SubscriptionManager.NAME_SOURCE_SIM_PNN, 1044 SubscriptionManager.NAME_SOURCE_SIM_SPN, 1045 SubscriptionManager.NAME_SOURCE_CARRIER, 1046 SubscriptionManager.NAME_SOURCE_USER_INPUT // user has highest priority. 1047 ).indexOf(nameSource); 1048 return Math.max(0, index); 1049 } 1050 1051 /** 1052 * Randomly pick a color from {@link R.array#sim_colors}. 1053 * 1054 * @return The selected color for the subscription. 1055 */ getColor()1056 private int getColor() { 1057 int[] colors = mContext.getResources().getIntArray(com.android.internal.R.array.sim_colors); 1058 if (colors.length == 0) return 0xFFFFFFFF; // white 1059 Random rand = new Random(); 1060 return colors[rand.nextInt(colors.length)]; 1061 } 1062 1063 /** 1064 * Get the port index by ICCID. 1065 * 1066 * @param iccId The ICCID. 1067 * @return The port index. 1068 */ getPortIndex(@onNull String iccId)1069 private int getPortIndex(@NonNull String iccId) { 1070 UiccSlot[] slots = mUiccController.getUiccSlots(); 1071 for (UiccSlot slot : slots) { 1072 if (slot != null) { 1073 int portIndex = slot.getPortIndexFromIccId(iccId); 1074 if (portIndex != TelephonyManager.INVALID_PORT_INDEX) { 1075 return portIndex; 1076 } 1077 } 1078 } 1079 return TelephonyManager.INVALID_PORT_INDEX; 1080 } 1081 1082 /** 1083 * Insert a new subscription into the database. 1084 * 1085 * @param iccId The ICCID. 1086 * @param slotIndex The logical SIM slot index (i.e. phone id). 1087 * @param displayName The display name. 1088 * @param subscriptionType The subscription type. 1089 * 1090 * @return The subscription id. 1091 */ insertSubscriptionInfo(@onNull String iccId, int slotIndex, @Nullable String displayName, @SubscriptionType int subscriptionType)1092 private int insertSubscriptionInfo(@NonNull String iccId, int slotIndex, 1093 @Nullable String displayName, @SubscriptionType int subscriptionType) { 1094 String defaultAllowNetworkTypes = Phone.convertAllowedNetworkTypeMapIndexToDbName( 1095 TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER) + "=" 1096 + RadioAccessFamily.getRafFromNetworkType(RILConstants.PREFERRED_NETWORK_MODE); 1097 SubscriptionInfoInternal.Builder builder = new SubscriptionInfoInternal.Builder() 1098 .setIccId(iccId) 1099 .setCardString(iccId) 1100 .setSimSlotIndex(slotIndex) 1101 .setType(subscriptionType) 1102 .setIconTint(getColor()) 1103 .setAllowedNetworkTypesForReasons(defaultAllowNetworkTypes); 1104 if (displayName != null) { 1105 builder.setDisplayName(displayName); 1106 } 1107 1108 int subId = mSubscriptionDatabaseManager.insertSubscriptionInfo(builder.build()); 1109 logl("insertSubscriptionInfo: Inserted a new subscription. subId=" + subId 1110 + ", slotIndex=" + slotIndex + ", iccId=" + SubscriptionInfo.getPrintableId(iccId) 1111 + ", displayName=" + displayName + ", type=" 1112 + SubscriptionManager.subscriptionTypeToString(subscriptionType)); 1113 return subId; 1114 } 1115 1116 /** 1117 * Pull the embedded subscription from {@link EuiccController} for the eUICC with the given list 1118 * of card IDs {@code cardIds}. 1119 * 1120 * @param cardIds The card ids of the embedded subscriptions. 1121 * @param callback Callback to be called upon completion. 1122 */ updateEmbeddedSubscriptions(@onNull List<Integer> cardIds, @Nullable Runnable callback)1123 public void updateEmbeddedSubscriptions(@NonNull List<Integer> cardIds, 1124 @Nullable Runnable callback) { 1125 // Run this on a background thread. 1126 mBackgroundHandler.post(() -> { 1127 // Do nothing if eUICCs are disabled. (Previous entries may remain in the cache, but 1128 // they are filtered out of list calls as long as EuiccManager.isEnabled returns false). 1129 if (mEuiccManager == null || !mEuiccManager.isEnabled() || mEuiccController == null) { 1130 loge("updateEmbeddedSubscriptions: eUICC not enabled"); 1131 if (callback != null) { 1132 callback.run(); 1133 } 1134 return; 1135 } 1136 1137 Set<Integer> embeddedSubs = new ArraySet<>(); 1138 log("updateEmbeddedSubscriptions: start to get euicc profiles."); 1139 1140 for (UiccSlot slot : mUiccController.getUiccSlots()) { 1141 if (slot != null) { 1142 log(" " + slot); 1143 } 1144 } 1145 1146 // The flag indicating getting successful result from EuiccController. 1147 boolean isProfileUpdateSuccessful = false; 1148 1149 for (int cardId : cardIds) { 1150 GetEuiccProfileInfoListResult result = mEuiccController 1151 .blockingGetEuiccProfileInfoList(cardId); 1152 logl("updateEmbeddedSubscriptions: cardId=" + cardId + ", result=" + result); 1153 if (result == null) { 1154 //TODO: Add back-off retry in the future if needed. 1155 loge("Failed to get euicc profiles."); 1156 continue; 1157 } 1158 1159 if (result.getResult() != EuiccService.RESULT_OK) { 1160 loge("Failed to get euicc profile info. result=" 1161 + EuiccService.resultToString(result.getResult())); 1162 continue; 1163 } 1164 1165 isProfileUpdateSuccessful = true; 1166 1167 if (result.getProfiles() == null || result.getProfiles().isEmpty()) { 1168 loge("No profiles returned."); 1169 continue; 1170 } 1171 1172 final boolean isRemovable = result.getIsRemovable(); 1173 1174 for (EuiccProfileInfo embeddedProfile : result.getProfiles()) { 1175 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 1176 .getSubscriptionInfoInternalByIccId(embeddedProfile.getIccid()); 1177 1178 // The subscription does not exist in the database. Insert a new one here. 1179 if (subInfo == null) { 1180 int subId = insertSubscriptionInfo(embeddedProfile.getIccid(), 1181 SubscriptionManager.INVALID_SIM_SLOT_INDEX, 1182 null, SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); 1183 mSubscriptionDatabaseManager.setDisplayName(subId, mContext.getResources() 1184 .getString(R.string.default_card_name, getCardNumber(subId))); 1185 subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subId); 1186 } 1187 1188 int nameSource = subInfo.getDisplayNameSource(); 1189 int carrierId = subInfo.getCarrierId(); 1190 1191 SubscriptionInfoInternal.Builder builder = new SubscriptionInfoInternal 1192 .Builder(subInfo); 1193 1194 builder.setEmbedded(1); 1195 1196 List<UiccAccessRule> ruleList = embeddedProfile.getUiccAccessRules(); 1197 if (ruleList != null && !ruleList.isEmpty()) { 1198 builder.setNativeAccessRules(embeddedProfile.getUiccAccessRules()); 1199 } 1200 builder.setRemovableEmbedded(isRemovable); 1201 1202 // override DISPLAY_NAME if the priority of existing nameSource is <= carrier 1203 String nickName = embeddedProfile.getNickname(); 1204 if (nickName != null 1205 && getNameSourcePriority(nameSource) <= getNameSourcePriority( 1206 SubscriptionManager.NAME_SOURCE_CARRIER)) { 1207 builder.setDisplayName(nickName); 1208 builder.setDisplayNameSource(SubscriptionManager.NAME_SOURCE_CARRIER); 1209 } 1210 1211 boolean isSatelliteSpn = false; 1212 if (mFeatureFlags.oemEnabledSatelliteFlag() ) { 1213 if (isSatelliteSpn(embeddedProfile.getServiceProviderName())) { 1214 isSatelliteSpn = true; 1215 builder.setOnlyNonTerrestrialNetwork(1); 1216 } 1217 } else { 1218 log("updateEmupdateEmbeddedSubscriptions: oemEnabledSatelliteFlag is " 1219 + "disabled"); 1220 } 1221 1222 if (android.os.Build.isDebuggable() && 1223 SystemProperties.getInt("telephony.test.bootstrap_cid", -2) 1224 == carrierId) { 1225 // Force set as provisioning profile for test purpose 1226 log("Hardcording as bootstrap subscription for cid=" + carrierId); 1227 builder.setProfileClass(SimInfo.PROFILE_CLASS_PROVISIONING); 1228 } else { 1229 builder.setProfileClass(embeddedProfile.getProfileClass()); 1230 } 1231 builder.setPortIndex(getPortIndex(embeddedProfile.getIccid())); 1232 1233 CarrierIdentifier cid = embeddedProfile.getCarrierIdentifier(); 1234 if (cid != null) { 1235 // Due to the limited subscription information, carrier id identified here 1236 // might not be accurate compared with CarrierResolver. Only update carrier 1237 // id if there is no valid carrier id present. 1238 if (carrierId == TelephonyManager.UNKNOWN_CARRIER_ID) { 1239 builder.setCarrierId(CarrierResolver 1240 .getCarrierIdFromIdentifier(mContext, cid)); 1241 } 1242 String mcc = cid.getMcc(); 1243 String mnc = cid.getMnc(); 1244 builder.setMcc(mcc); 1245 builder.setMnc(mnc); 1246 if (mFeatureFlags.oemEnabledSatelliteFlag() && !isSatelliteSpn) { 1247 builder.setOnlyNonTerrestrialNetwork( 1248 isSatellitePlmn(mcc + mnc) ? 1 : 0); 1249 } 1250 } 1251 // If cardId = unsupported or un-initialized, we have no reason to update DB. 1252 // Additionally, if the device does not support cardId for default eUICC, the 1253 // CARD_ID field should not contain the EID 1254 if (cardId >= 0 && mUiccController.getCardIdForDefaultEuicc() 1255 != TelephonyManager.UNSUPPORTED_CARD_ID) { 1256 builder.setCardId(cardId); 1257 builder.setCardString(mUiccController.convertToCardString(cardId)); 1258 } 1259 1260 if (mFeatureFlags.supportPsimToEsimConversion()) { 1261 builder.setTransferStatus(subInfo.getTransferStatus()); 1262 } 1263 embeddedSubs.add(subInfo.getSubscriptionId()); 1264 1265 subInfo = builder.build(); 1266 log("updateEmbeddedSubscriptions: update subscription " + subInfo); 1267 mSubscriptionDatabaseManager.updateSubscription(subInfo); 1268 } 1269 } 1270 1271 // Marked the previous embedded subscriptions non-embedded if the latest profiles do 1272 // not include them anymore. 1273 if (isProfileUpdateSuccessful) { 1274 // embeddedSubs contains all the existing embedded subs queried from EuiccManager, 1275 // including active or inactive. If there are any embedded subscription in the 1276 // database that is not in embeddedSubs, mark them as non-embedded. These were 1277 // deleted embedded subscriptions, so we treated them as non-embedded (pre-U 1278 // behavior) and they don't show up in Settings SIM page. 1279 mSubscriptionDatabaseManager.getAllSubscriptions().stream() 1280 .filter(SubscriptionInfoInternal::isEmbedded) 1281 .filter(subInfo -> !embeddedSubs.contains(subInfo.getSubscriptionId())) 1282 .forEach(subInfo -> { 1283 logl("updateEmbeddedSubscriptions: Mark the deleted sub " 1284 + subInfo.getSubscriptionId() + " as non-embedded."); 1285 mSubscriptionDatabaseManager.setEmbedded( 1286 subInfo.getSubscriptionId(), false); 1287 }); 1288 if (mSubscriptionDatabaseManager.getAllSubscriptions().stream() 1289 .anyMatch(subInfo -> subInfo.isEmbedded() 1290 && subInfo.isActive() 1291 && subInfo.getPortIndex() 1292 == TelephonyManager.INVALID_PORT_INDEX 1293 && mSimState[subInfo.getSimSlotIndex()] 1294 == TelephonyManager.SIM_STATE_LOADED)) { 1295 //Report Anomaly if invalid portIndex is updated in Active subscriptions 1296 AnomalyReporter.reportAnomaly( 1297 UUID.fromString("38fdf63c-3bd9-4fc2-ad33-a20246a32fa7"), 1298 "SubscriptionManagerService: Found Invalid portIndex" 1299 + " in active subscriptions"); 1300 } 1301 } else { 1302 loge("The eSIM profiles update was not successful."); 1303 } 1304 log("updateEmbeddedSubscriptions: Finished embedded subscription update."); 1305 // The runnable will be executed in the main thread. Pre Android-U behavior. 1306 mHandler.post(() -> { 1307 if (callback != null) { 1308 callback.run(); 1309 } 1310 }); 1311 }); 1312 } 1313 1314 /** 1315 * Update embedded subscriptions from {@link EuiccController}. 1316 */ updateEmbeddedSubscriptions()1317 private void updateEmbeddedSubscriptions() { 1318 UiccSlot[] uiccSlots = mUiccController.getUiccSlots(); 1319 if (uiccSlots != null) { 1320 List<Integer> cardIds = new ArrayList<>(); 1321 for (UiccSlot uiccSlot : uiccSlots) { 1322 if (uiccSlot != null && uiccSlot.isEuicc() && uiccSlot.getUiccCard() != null) { 1323 int cardId = mUiccController.convertToPublicCardId( 1324 uiccSlot.getUiccCard().getCardId()); 1325 cardIds.add(cardId); 1326 } 1327 } 1328 if (!cardIds.isEmpty()) { 1329 updateEmbeddedSubscriptions(cardIds, null); 1330 } 1331 } 1332 } 1333 1334 /** 1335 * Check if the SIM application is enabled on the card or not. 1336 * 1337 * @param phoneId The phone id. 1338 * 1339 * @return {@code true} if the application is enabled. 1340 */ areUiccAppsEnabledOnCard(int phoneId)1341 public boolean areUiccAppsEnabledOnCard(int phoneId) { 1342 // When uicc apps are disabled(supported in IRadio 1.5), we will still get IccId from 1343 // cardStatus (since IRadio 1.2). And upon cardStatus change we'll receive another 1344 // handleSimNotReady so this will be evaluated again. 1345 UiccSlot slot = mUiccController.getUiccSlotForPhone(phoneId); 1346 if (slot == null) return false; 1347 UiccPort port = mUiccController.getUiccPort(phoneId); 1348 String iccId = (port == null) ? null : port.getIccId(); 1349 if (iccId == null) { 1350 return false; 1351 } 1352 1353 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 1354 .getSubscriptionInfoInternalByIccId(IccUtils.stripTrailingFs(iccId)); 1355 return subInfo != null && subInfo.areUiccApplicationsEnabled(); 1356 } 1357 1358 /** 1359 * Get ICCID by phone id. 1360 * 1361 * @param phoneId The phone id (i.e. Logical SIM slot index.) 1362 * 1363 * @return The ICCID. Empty string if not available. 1364 */ 1365 @NonNull getIccId(int phoneId)1366 private String getIccId(int phoneId) { 1367 UiccPort port = mUiccController.getUiccPort(phoneId); 1368 return (port == null) ? "" : TextUtils.emptyIfNull( 1369 IccUtils.stripTrailingFs(port.getIccId())); 1370 } 1371 1372 /** 1373 * @return {@code true} if all the need-to-be-loaded subscriptions from SIM slots are already 1374 * loaded. {@code false} if more than one are still being loaded. 1375 */ areAllSubscriptionsLoaded()1376 private boolean areAllSubscriptionsLoaded() { 1377 for (int phoneId = 0; phoneId < mTelephonyManager.getActiveModemCount(); phoneId++) { 1378 UiccSlot slot = mUiccController.getUiccSlotForPhone(phoneId); 1379 if (slot == null) { 1380 log("areAllSubscriptionsLoaded: slot is null. phoneId=" + phoneId); 1381 return false; 1382 } 1383 if (!slot.isActive()) { 1384 log("areAllSubscriptionsLoaded: slot is inactive. phoneId=" + phoneId); 1385 return false; 1386 } 1387 if (slot.isEuicc() && mUiccController.getUiccPort(phoneId) == null) { 1388 log("Wait for port corresponding to phone " + phoneId + " to be active, portIndex " 1389 + "is " + slot.getPortIndexFromPhoneId(phoneId)); 1390 return false; 1391 } 1392 1393 if (mSimState[phoneId] == TelephonyManager.SIM_STATE_NOT_READY) { 1394 // Check if this is the final state. 1395 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); 1396 if (!iccCard.isEmptyProfile() && areUiccAppsEnabledOnCard(phoneId)) { 1397 log("areAllSubscriptionsLoaded: NOT_READY is not a final state."); 1398 return false; 1399 } 1400 } 1401 1402 if (mSimState[phoneId] == TelephonyManager.SIM_STATE_UNKNOWN) { 1403 log("areAllSubscriptionsLoaded: SIM " + phoneId + " state is still unknown."); 1404 return false; 1405 } 1406 } 1407 1408 return true; 1409 } 1410 1411 /** 1412 * Update the subscription on the logical SIM slot index (i.e. phone id). 1413 * 1414 * @param phoneId The phone id (i.e. Logical SIM slot index) 1415 */ updateSubscription(int phoneId)1416 private void updateSubscription(int phoneId) { 1417 int simState = mSimState[phoneId]; 1418 log("updateSubscription: phoneId=" + phoneId + ", simState=" 1419 + TelephonyManager.simStateToString(simState)); 1420 for (UiccSlot slot : mUiccController.getUiccSlots()) { 1421 if (slot != null) { 1422 log(" " + slot); 1423 } 1424 } 1425 1426 if (simState == TelephonyManager.SIM_STATE_ABSENT) { 1427 SatelliteController satelliteController = SatelliteController.getInstance(); 1428 boolean isSatelliteEnabledOrBeingEnabled = false; 1429 if (satelliteController != null) { 1430 isSatelliteEnabledOrBeingEnabled = satelliteController.isSatelliteEnabled() 1431 || satelliteController.isSatelliteBeingEnabled(); 1432 } 1433 1434 if (!isSatelliteEnabledOrBeingEnabled) { 1435 // Re-enable the pSIM when it's removed, so it will be in enabled state when it gets 1436 // re-inserted again. (pre-U behavior) 1437 List<String> iccIds = getIccIdsOfInsertedPhysicalSims(); 1438 mSubscriptionDatabaseManager.getAllSubscriptions().stream() 1439 .filter(subInfo -> !iccIds.contains(subInfo.getIccId()) 1440 && !subInfo.isEmbedded()) 1441 .forEach(subInfo -> { 1442 int subId = subInfo.getSubscriptionId(); 1443 log("updateSubscription: Re-enable Uicc application on sub " + subId); 1444 mSubscriptionDatabaseManager.setUiccApplicationsEnabled(subId, true); 1445 // When sim is absent, set the port index to invalid port index. 1446 // (pre-U behavior) 1447 mSubscriptionDatabaseManager.setPortIndex(subId, 1448 TelephonyManager.INVALID_PORT_INDEX); 1449 }); 1450 } 1451 1452 if (mSlotIndexToSubId.containsKey(phoneId)) { 1453 markSubscriptionsInactive(phoneId); 1454 } 1455 1456 if (Flags.clearCachedImsPhoneNumberWhenDeviceLostImsRegistration()) { 1457 // Clear the cached Ims phone number 1458 setNumberFromIms(getSubId(phoneId), new String("")); 1459 } 1460 } else if (simState == TelephonyManager.SIM_STATE_NOT_READY) { 1461 // Check if this is the final state. Only update the subscription if NOT_READY is a 1462 // final state. 1463 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); 1464 if (iccCard.isEmptyProfile()) log("updateSubscription: iccCard has empty profile."); 1465 if (!iccCard.isEmptyProfile() && areUiccAppsEnabledOnCard(phoneId)) { 1466 log("updateSubscription: SIM_STATE_NOT_READY is not a final state. Will update " 1467 + "subscription later."); 1468 return; 1469 } else { 1470 logl("updateSubscription: UICC app disabled on slot " + phoneId); 1471 markSubscriptionsInactive(phoneId); 1472 1473 if (Flags.clearCachedImsPhoneNumberWhenDeviceLostImsRegistration()) { 1474 // Clear the cached Ims phone number 1475 setNumberFromIms(getSubId(phoneId), new String("")); 1476 } 1477 } 1478 } else { 1479 String iccId = getIccId(phoneId); 1480 log("updateSubscription: Found iccId=" + SubscriptionInfo.getPrintableId(iccId) 1481 + " on phone " + phoneId); 1482 1483 // For eSIM switching, SIM absent will not happen. Below is to exam if we find ICCID 1484 // mismatch on the SIM slot. If that's the case, we need to mark all subscriptions on 1485 // that logical slot invalid first. The correct subscription will be assigned the 1486 // correct slot later. 1487 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getAllSubscriptions() 1488 .stream() 1489 .filter(sub -> sub.getSimSlotIndex() == phoneId && !iccId.equals( 1490 sub.getIccId())) 1491 .findFirst() 1492 .orElse(null); 1493 if (subInfo != null) { 1494 log("updateSubscription: Found previous active sub " + subInfo.getSubscriptionId() 1495 + " that doesn't match current iccid on slot " + phoneId + "."); 1496 markSubscriptionsInactive(phoneId); 1497 } 1498 1499 if (!TextUtils.isEmpty(iccId)) { 1500 // Check if the subscription already existed. 1501 subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternalByIccId(iccId); 1502 int subId; 1503 if (subInfo == null) { 1504 // This is a new SIM card. Insert a new record. 1505 subId = insertSubscriptionInfo(iccId, phoneId, null, 1506 SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); 1507 mSubscriptionDatabaseManager.setDisplayName(subId, 1508 mContext.getResources().getString(R.string.default_card_name, 1509 getCardNumber(subId))); 1510 } else { 1511 subId = subInfo.getSubscriptionId(); 1512 log("updateSubscription: Found existing subscription. subId= " + subId 1513 + ", phoneId=" + phoneId); 1514 } 1515 1516 subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subId); 1517 if (subInfo != null && subInfo.areUiccApplicationsEnabled()) { 1518 mSlotIndexToSubId.put(phoneId, subId); 1519 // Update the SIM slot index. This will make the subscription active. 1520 mSubscriptionDatabaseManager.setSimSlotIndex(subId, phoneId); 1521 logl("updateSubscription: current mapping " + slotMappingToString()); 1522 } 1523 1524 // Update the card id. 1525 UiccCard card = mUiccController.getUiccCardForPhone(phoneId); 1526 if (card != null) { 1527 String cardId = card.getCardId(); 1528 if (cardId != null) { 1529 mSubscriptionDatabaseManager.setCardString(subId, cardId); 1530 } 1531 } 1532 1533 // Update the port index. 1534 mSubscriptionDatabaseManager.setPortIndex(subId, getPortIndex(iccId)); 1535 1536 if (simState == TelephonyManager.SIM_STATE_LOADED) { 1537 String mccMnc = mTelephonyManager.getSimOperatorNumeric(subId); 1538 if (!TextUtils.isEmpty(mccMnc)) { 1539 if (subId == getDefaultSubId()) { 1540 MccTable.updateMccMncConfiguration(mContext, mccMnc); 1541 } 1542 setMccMnc(subId, mccMnc); 1543 } else { 1544 loge("updateSubscription: mcc/mnc is empty"); 1545 } 1546 1547 String iso = TelephonyManager.getSimCountryIsoForPhone(phoneId); 1548 1549 if (!TextUtils.isEmpty(iso)) { 1550 setCountryIso(subId, iso); 1551 } else { 1552 loge("updateSubscription: sim country iso is null"); 1553 } 1554 1555 String msisdn = PhoneFactory.getPhone(phoneId).getLine1Number(); 1556 if (!TextUtils.isEmpty(msisdn)) { 1557 setDisplayNumber(msisdn, subId); 1558 } 1559 1560 String imsi = mTelephonyManager.createForSubscriptionId( 1561 subId).getSubscriberId(); 1562 if (imsi != null) { 1563 mSubscriptionDatabaseManager.setImsi(subId, imsi); 1564 } 1565 1566 IccCard iccCard = PhoneFactory.getPhone(phoneId).getIccCard(); 1567 if (iccCard != null) { 1568 IccRecords records = iccCard.getIccRecords(); 1569 if (records != null) { 1570 String[] ehplmns = records.getEhplmns(); 1571 if (ehplmns != null) { 1572 mSubscriptionDatabaseManager.setEhplmns(subId, ehplmns); 1573 } 1574 String[] hplmns = records.getPlmnsFromHplmnActRecord(); 1575 if (hplmns != null) { 1576 mSubscriptionDatabaseManager.setHplmns(subId, hplmns); 1577 } 1578 } else { 1579 loge("updateSubscription: ICC records are not available."); 1580 } 1581 } else { 1582 loge("updateSubscription: ICC card is not available."); 1583 } 1584 1585 // Attempt to restore SIM specific settings when SIM is loaded. 1586 Bundle result = mContext.getContentResolver().call( 1587 SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, 1588 SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, 1589 iccId, null); 1590 if (result != null && result.getBoolean( 1591 SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_DATABASE_UPDATED)) { 1592 logl("Sim specific settings changed the database."); 1593 mSubscriptionDatabaseManager.reloadDatabaseSync(); 1594 if (mFeatureFlags.backupAndRestoreForEnable2g()) { 1595 PhoneFactory.getPhone(phoneId) 1596 .loadAllowedNetworksFromSubscriptionDatabase(); 1597 } 1598 } 1599 } 1600 1601 log("updateSubscription: " + mSubscriptionDatabaseManager 1602 .getSubscriptionInfoInternal(subId)); 1603 } else { 1604 log("updateSubscription: No ICCID available for phone " + phoneId); 1605 mSlotIndexToSubId.remove(phoneId); 1606 logl("updateSubscription: current mapping " + slotMappingToString()); 1607 } 1608 } 1609 1610 if (areAllSubscriptionsLoaded()) { 1611 log("Notify all subscriptions loaded."); 1612 MultiSimSettingController.getInstance().notifyAllSubscriptionLoaded(); 1613 } 1614 1615 updateGroupDisabled(); 1616 updateDefaultSubId(); 1617 1618 if (mSlotIndexToSubId.containsKey(phoneId) && 1619 isEsimBootStrapProvisioningActiveForSubId(mSlotIndexToSubId.get(phoneId))) { 1620 startEsimBootstrapTimer(); 1621 } else { 1622 cancelEsimBootstrapTimer(); 1623 } 1624 } 1625 cancelEsimBootstrapTimer()1626 private void cancelEsimBootstrapTimer() { 1627 if (bootstrapProvisioningTimer != null) { 1628 bootstrapProvisioningTimer.cancel(); 1629 bootstrapProvisioningTimer = null; 1630 log("bootstrapProvisioningTimer timer cancelled."); 1631 } 1632 } 1633 startEsimBootstrapTimer()1634 private void startEsimBootstrapTimer() { 1635 if (bootstrapProvisioningTimer == null) { 1636 bootstrapProvisioningTimer = new CountDownTimer(CHECK_BOOTSTRAP_TIMER_IN_MS, 1637 CHECK_BOOTSTRAP_TIMER_IN_MS) { 1638 @Override 1639 public void onTick(long millisUntilFinished) { 1640 // Do nothing 1641 } 1642 1643 @Override 1644 public void onFinish() { 1645 AnomalyReporter.reportAnomaly(UUID.fromString("40587b0f-27c9-4b39-b94d" 1646 + "-71fc9771f354"), "eSim bootstrap has been active for too " 1647 + "long."); 1648 log("bootstrapProvisioningTimer: timer finished esim was not disabled."); 1649 cancelEsimBootstrapTimer(); 1650 } 1651 }.start(); 1652 log("bootstrapProvisioningTimer timer started."); 1653 } 1654 } 1655 1656 /** 1657 * Calculate the usage setting based on the carrier request. 1658 * 1659 * @param currentUsageSetting the current setting in the subscription DB. 1660 * @param preferredUsageSetting provided by the carrier config. 1661 * 1662 * @return the calculated usage setting. 1663 */ 1664 @VisibleForTesting calculateUsageSetting(@sageSetting int currentUsageSetting, @UsageSetting int preferredUsageSetting)1665 @UsageSetting public int calculateUsageSetting(@UsageSetting int currentUsageSetting, 1666 @UsageSetting int preferredUsageSetting) { 1667 int[] supportedUsageSettings; 1668 1669 // Load the resources to provide the device capability 1670 try { 1671 supportedUsageSettings = mContext.getResources().getIntArray( 1672 com.android.internal.R.array.config_supported_cellular_usage_settings); 1673 // If usage settings are not supported, return the default setting, which is UNKNOWN. 1674 if (supportedUsageSettings == null 1675 || supportedUsageSettings.length < 1) return currentUsageSetting; 1676 } catch (Resources.NotFoundException nfe) { 1677 loge("calculateUsageSetting: Failed to load usage setting resources!"); 1678 return currentUsageSetting; 1679 } 1680 1681 // If the current setting is invalid, including the first time the value is set, 1682 // update it to default (this will trigger a change in the DB). 1683 if (currentUsageSetting < SubscriptionManager.USAGE_SETTING_DEFAULT 1684 || currentUsageSetting > SubscriptionManager.USAGE_SETTING_DATA_CENTRIC) { 1685 log("calculateUsageSetting: Updating usage setting for current subscription"); 1686 currentUsageSetting = SubscriptionManager.USAGE_SETTING_DEFAULT; 1687 } 1688 1689 // Range check the inputs, and on failure, make no changes 1690 if (preferredUsageSetting < SubscriptionManager.USAGE_SETTING_DEFAULT 1691 || preferredUsageSetting > SubscriptionManager.USAGE_SETTING_DATA_CENTRIC) { 1692 loge("calculateUsageSetting: Invalid usage setting!" + preferredUsageSetting); 1693 return currentUsageSetting; 1694 } 1695 1696 // Default is always allowed 1697 if (preferredUsageSetting == SubscriptionManager.USAGE_SETTING_DEFAULT) { 1698 return preferredUsageSetting; 1699 } 1700 1701 // Forced setting must be explicitly supported 1702 for (int supportedUsageSetting : supportedUsageSettings) { 1703 if (preferredUsageSetting == supportedUsageSetting) return preferredUsageSetting; 1704 } 1705 1706 // If the preferred setting is not possible, just keep the current setting. 1707 return currentUsageSetting; 1708 } 1709 1710 /** 1711 * Called by CarrierConfigLoader to update the subscription before sending a broadcast. 1712 */ updateSubscriptionByCarrierConfig(int phoneId, @NonNull String configPackageName, @NonNull PersistableBundle config, @NonNull Runnable callback)1713 public void updateSubscriptionByCarrierConfig(int phoneId, @NonNull String configPackageName, 1714 @NonNull PersistableBundle config, @NonNull Runnable callback) { 1715 mHandler.post(() -> { 1716 updateSubscriptionByCarrierConfigInternal(phoneId, configPackageName, config); 1717 callback.run(); 1718 }); 1719 } 1720 updateSubscriptionByCarrierConfigInternal(int phoneId, @NonNull String configPackageName, @NonNull PersistableBundle config)1721 private void updateSubscriptionByCarrierConfigInternal(int phoneId, 1722 @NonNull String configPackageName, @NonNull PersistableBundle config) { 1723 log("updateSubscriptionByCarrierConfig: phoneId=" + phoneId + ", configPackageName=" 1724 + configPackageName); 1725 if (!SubscriptionManager.isValidPhoneId(phoneId) 1726 || TextUtils.isEmpty(configPackageName) || config == null) { 1727 loge("updateSubscriptionByCarrierConfig: Failed to update the subscription. phoneId=" 1728 + phoneId + " configPackageName=" + configPackageName + " config=" 1729 + ((config == null) ? "null" : config.hashCode())); 1730 return; 1731 } 1732 1733 if (!mSlotIndexToSubId.containsKey(phoneId)) { 1734 log("updateSubscriptionByCarrierConfig: No subscription is active for phone being " 1735 + "updated."); 1736 return; 1737 } 1738 1739 int subId = mSlotIndexToSubId.get(phoneId); 1740 1741 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 1742 .getSubscriptionInfoInternal(subId); 1743 if (subInfo == null) { 1744 loge("updateSubscriptionByCarrierConfig: Couldn't retrieve subscription info for " 1745 + "current subscription. subId=" + subId); 1746 return; 1747 } 1748 1749 ParcelUuid groupUuid; 1750 1751 // carrier certificates are not subscription-specific, so we want to load them even if 1752 // this current package is not a CarrierServicePackage 1753 String[] certs = config.getStringArray( 1754 CarrierConfigManager.KEY_CARRIER_CERTIFICATE_STRING_ARRAY); 1755 UiccAccessRule[] carrierConfigAccessRules = UiccAccessRule.decodeRulesFromCarrierConfig( 1756 certs); 1757 if (carrierConfigAccessRules != null) { 1758 mSubscriptionDatabaseManager.setCarrierConfigAccessRules( 1759 subId, carrierConfigAccessRules); 1760 } 1761 1762 boolean isOpportunistic = config.getBoolean( 1763 CarrierConfigManager.KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL, 1764 subInfo.isOpportunistic()); 1765 mSubscriptionDatabaseManager.setOpportunistic(subId, isOpportunistic); 1766 1767 String groupUuidString = config.getString( 1768 CarrierConfigManager.KEY_SUBSCRIPTION_GROUP_UUID_STRING, ""); 1769 String oldGroupUuidString = subInfo.getGroupUuid(); 1770 if (!TextUtils.isEmpty(groupUuidString)) { 1771 try { 1772 // Update via a UUID Structure to ensure consistent formatting 1773 groupUuid = ParcelUuid.fromString(groupUuidString); 1774 if (groupUuidString.equals(CarrierConfigManager.REMOVE_GROUP_UUID_STRING)) { 1775 // Remove the group UUID. 1776 mSubscriptionDatabaseManager.setGroupUuid(subId, ""); 1777 } else if (canPackageManageGroup(groupUuid, configPackageName)) { 1778 mSubscriptionDatabaseManager.setGroupUuid(subId, groupUuidString); 1779 mSubscriptionDatabaseManager.setGroupOwner(subId, configPackageName); 1780 log("updateSubscriptionByCarrierConfig: Group added for sub " + subId); 1781 } else { 1782 loge("updateSubscriptionByCarrierConfig: configPackageName " 1783 + configPackageName + " doesn't own groupUuid " + groupUuid); 1784 } 1785 1786 if (!groupUuidString.equals(oldGroupUuidString)) { 1787 MultiSimSettingController.getInstance() 1788 .notifySubscriptionGroupChanged(groupUuid); 1789 } 1790 } catch (IllegalArgumentException e) { 1791 loge("updateSubscriptionByCarrierConfig: Invalid Group UUID=" 1792 + groupUuidString); 1793 } 1794 } 1795 1796 updateGroupDisabled(); 1797 1798 final int preferredUsageSetting = config.getInt( 1799 CarrierConfigManager.KEY_CELLULAR_USAGE_SETTING_INT, 1800 SubscriptionManager.USAGE_SETTING_UNKNOWN); 1801 1802 int newUsageSetting = calculateUsageSetting( 1803 subInfo.getUsageSetting(), preferredUsageSetting); 1804 1805 if (newUsageSetting != subInfo.getUsageSetting()) { 1806 mSubscriptionDatabaseManager.setUsageSetting(subId, newUsageSetting); 1807 log("updateSubscriptionByCarrierConfig: UsageSetting changed," 1808 + " oldSetting=" + SubscriptionManager.usageSettingToString( 1809 subInfo.getUsageSetting()) 1810 + " preferredSetting=" + SubscriptionManager.usageSettingToString( 1811 preferredUsageSetting) 1812 + " newSetting=" + SubscriptionManager.usageSettingToString(newUsageSetting)); 1813 } 1814 1815 if (mFeatureFlags.dataOnlyCellularService()) { 1816 final int[] servicesFromCarrierConfig = 1817 config.getIntArray( 1818 CarrierConfigManager.KEY_CELLULAR_SERVICE_CAPABILITIES_INT_ARRAY); 1819 int serviceBitmasks = 0; 1820 boolean allServicesAreValid = true; 1821 // Check if all services from carrier config are valid before setting to db 1822 if (servicesFromCarrierConfig == null) { 1823 allServicesAreValid = false; 1824 } else { 1825 for (int service : servicesFromCarrierConfig) { 1826 if (service < SubscriptionManager.SERVICE_CAPABILITY_VOICE 1827 || service > SubscriptionManager.SERVICE_CAPABILITY_MAX) { 1828 allServicesAreValid = false; 1829 break; 1830 } else { 1831 serviceBitmasks |= SubscriptionManager.serviceCapabilityToBitmask(service); 1832 } 1833 } 1834 } 1835 // In case we get invalid service override, fall back to default value. 1836 // DO NOT throw exception which will crash phone process. 1837 if (!allServicesAreValid) { 1838 serviceBitmasks = SubscriptionManager.getAllServiceCapabilityBitmasks(); 1839 } 1840 1841 if (serviceBitmasks != subInfo.getServiceCapabilities()) { 1842 log("updateSubscriptionByCarrierConfig: serviceCapabilities updated from " 1843 + subInfo.getServiceCapabilities() + " to " + serviceBitmasks); 1844 mSubscriptionDatabaseManager.setServiceCapabilities(subId, serviceBitmasks); 1845 } 1846 } 1847 } 1848 1849 /** 1850 * Get all subscription info records from SIMs visible to the calling user that are inserted now 1851 * or previously inserted. 1852 * 1853 * <p> 1854 * If the caller does not have {@link Manifest.permission#READ_PHONE_NUMBERS} permission, 1855 * {@link SubscriptionInfo#getNumber()} will return empty string. 1856 * If the caller does not have {@link Manifest.permission#USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER}, 1857 * {@link SubscriptionInfo#getIccId()} and {@link SubscriptionInfo#getCardString()} will return 1858 * empty string, and {@link SubscriptionInfo#getGroupUuid()} will return {@code null}. 1859 * 1860 * <p> 1861 * The carrier app will only get the list of subscriptions that it has carrier privilege on, 1862 * but will have non-stripped {@link SubscriptionInfo} in the list. 1863 * 1864 * @param callingPackage The package making the call. 1865 * @param callingFeatureId The feature in the package. 1866 * 1867 * @return List of all {@link SubscriptionInfo} records from SIMs that are inserted or 1868 * previously inserted. Sorted by {@link SubscriptionInfo#getSimSlotIndex()}, then 1869 * {@link SubscriptionInfo#getSubscriptionId()}. 1870 * 1871 * @throws SecurityException if callers do not hold the required permission. 1872 */ 1873 @Override 1874 @NonNull 1875 @RequiresPermission(anyOf = { 1876 Manifest.permission.READ_PHONE_STATE, 1877 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1878 "carrier privileges", 1879 }) getAllSubInfoList(@onNull String callingPackage, @Nullable String callingFeatureId)1880 public List<SubscriptionInfo> getAllSubInfoList(@NonNull String callingPackage, 1881 @Nullable String callingFeatureId) { 1882 // Check if the caller has READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or carrier 1883 // privilege on any active subscription. The carrier app will get full subscription infos 1884 // on the subs it has carrier privilege. 1885 if (!TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(mContext, 1886 Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, callingFeatureId, 1887 "getAllSubInfoList")) { 1888 throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or " 1889 + "carrier privilege"); 1890 } 1891 1892 enforceTelephonyFeatureWithException(callingPackage, "getAllSubInfoList"); 1893 1894 return getSubscriptionInfoStreamAsUser(BINDER_WRAPPER.getCallingUserHandle()) 1895 // callers have READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE can get a full 1896 // list. Carrier apps can only get the subscriptions they have privileged. 1897 .filter(subInfo -> TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow( 1898 mContext, subInfo.getSubscriptionId(), callingPackage, callingFeatureId, 1899 "getAllSubInfoList")) 1900 // Remove the identifier if the caller does not have sufficient permission. 1901 // carrier apps will get full subscription info on the subscriptions associated 1902 // to them. 1903 .map(subInfo -> conditionallyRemoveIdentifiers(subInfo.toSubscriptionInfo(), 1904 callingPackage, callingFeatureId, "getAllSubInfoList")) 1905 .sorted(Comparator.comparing(SubscriptionInfo::getSimSlotIndex) 1906 .thenComparing(SubscriptionInfo::getSubscriptionId)) 1907 .collect(Collectors.toList()); 1908 } 1909 1910 /** 1911 * Get the active {@link SubscriptionInfo} with the subscription id key. 1912 * 1913 * @param subId The unique {@link SubscriptionInfo} key in database 1914 * @param callingPackage The package making the call. 1915 * @param callingFeatureId The feature in the package. 1916 * 1917 * @return The subscription info. 1918 * 1919 * @throws SecurityException if the caller does not have required permissions. 1920 */ 1921 @Override 1922 @Nullable 1923 @RequiresPermission(anyOf = { 1924 Manifest.permission.READ_PHONE_STATE, 1925 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1926 "carrier privileges", 1927 }) getActiveSubscriptionInfo(int subId, @NonNull String callingPackage, @Nullable String callingFeatureId)1928 public SubscriptionInfo getActiveSubscriptionInfo(int subId, @NonNull String callingPackage, 1929 @Nullable String callingFeatureId) { 1930 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId, callingPackage, 1931 callingFeatureId, "getActiveSubscriptionInfo")) { 1932 throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or " 1933 + "carrier privilege"); 1934 } 1935 1936 enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfo"); 1937 1938 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 1939 .getSubscriptionInfoInternal(subId); 1940 if (subInfo != null && subInfo.isActive()) { 1941 return conditionallyRemoveIdentifiers(subInfo.toSubscriptionInfo(), callingPackage, 1942 callingFeatureId, "getActiveSubscriptionInfo"); 1943 } 1944 return null; 1945 } 1946 1947 /** 1948 * Get the active {@link SubscriptionInfo} associated with the iccId. 1949 * 1950 * @param iccId the IccId of SIM card 1951 * @param callingPackage The package making the call. 1952 * @param callingFeatureId The feature in the package. 1953 * 1954 * @return The subscription info. 1955 * 1956 * @throws SecurityException if the caller does not have required permissions. 1957 */ 1958 @Override 1959 @Nullable 1960 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getActiveSubscriptionInfoForIccId(@onNull String iccId, @NonNull String callingPackage, @Nullable String callingFeatureId)1961 public SubscriptionInfo getActiveSubscriptionInfoForIccId(@NonNull String iccId, 1962 @NonNull String callingPackage, @Nullable String callingFeatureId) { 1963 enforcePermissions("getActiveSubscriptionInfoForIccId", 1964 Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 1965 1966 enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfoForIccId"); 1967 1968 final long identity = Binder.clearCallingIdentity(); 1969 try { 1970 iccId = IccUtils.stripTrailingFs(iccId); 1971 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 1972 .getSubscriptionInfoInternalByIccId(iccId); 1973 1974 return (subInfo != null && subInfo.isActive()) ? subInfo.toSubscriptionInfo() : null; 1975 1976 } finally { 1977 Binder.restoreCallingIdentity(identity); 1978 } 1979 } 1980 1981 /** 1982 * Get the active {@link SubscriptionInfo} associated with the logical SIM slot index. 1983 * 1984 * @param slotIndex the logical SIM slot index which the subscription is inserted. 1985 * @param callingPackage The package making the call. 1986 * @param callingFeatureId The feature in the package. 1987 * 1988 * @return {@link SubscriptionInfo}, null for Remote-SIMs or non-active logical SIM slot index. 1989 * 1990 * @throws SecurityException if the caller does not have required permissions. 1991 */ 1992 @Override 1993 @Nullable 1994 @RequiresPermission(anyOf = { 1995 Manifest.permission.READ_PHONE_STATE, 1996 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 1997 "carrier privileges", 1998 }) getActiveSubscriptionInfoForSimSlotIndex(int slotIndex, @NonNull String callingPackage, @Nullable String callingFeatureId)1999 public SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int slotIndex, 2000 @NonNull String callingPackage, @Nullable String callingFeatureId) { 2001 int subId = mSlotIndexToSubId.getOrDefault(slotIndex, 2002 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 2003 2004 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId, 2005 callingPackage, callingFeatureId, 2006 "getActiveSubscriptionInfoForSimSlotIndex")) { 2007 throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or " 2008 + "carrier privilege"); 2009 2010 } 2011 2012 enforceTelephonyFeatureWithException(callingPackage, 2013 "getActiveSubscriptionInfoForSimSlotIndex"); 2014 2015 if (!SubscriptionManager.isValidSlotIndex(slotIndex)) { 2016 throw new IllegalArgumentException("Invalid slot index " + slotIndex); 2017 } 2018 2019 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 2020 .getSubscriptionInfoInternal(subId); 2021 if (subInfo != null && subInfo.isActive()) { 2022 return conditionallyRemoveIdentifiers(subInfo.toSubscriptionInfo(), callingPackage, 2023 callingFeatureId, "getActiveSubscriptionInfoForSimSlotIndex"); 2024 } 2025 2026 return null; 2027 } 2028 2029 /** 2030 * Get the SubscriptionInfo(s) of the active subscriptions for calling user. The records will be 2031 * sorted by {@link SubscriptionInfo#getSimSlotIndex} then by 2032 * {@link SubscriptionInfo#getSubscriptionId}. 2033 * 2034 * @param callingPackage The package making the call. 2035 * @param callingFeatureId The feature in the package. 2036 * @param isForAllProfiles whether the caller intends to see all subscriptions regardless 2037 * association. 2038 * 2039 * @return Sorted list of the currently {@link SubscriptionInfo} records available on the 2040 * device. 2041 */ 2042 @Override 2043 @NonNull 2044 @RequiresPermission(anyOf = { 2045 Manifest.permission.READ_PHONE_STATE, 2046 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 2047 "carrier privileges", 2048 }) getActiveSubscriptionInfoList(@onNull String callingPackage, @Nullable String callingFeatureId, boolean isForAllProfiles)2049 public List<SubscriptionInfo> getActiveSubscriptionInfoList(@NonNull String callingPackage, 2050 @Nullable String callingFeatureId, boolean isForAllProfiles) { 2051 // Check if the caller has READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or carrier 2052 // privilege on any active subscription. The carrier app will get full subscription infos 2053 // on the subs it has carrier privilege. 2054 if (!TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(mContext, 2055 Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, callingFeatureId, 2056 "getActiveSubscriptionInfoList")) { 2057 // Ideally we should avoid silent failure, but since this API has already been used by 2058 // many apps and they do not expect the security exception, we return an empty list 2059 // here so it's consistent with pre-U behavior. 2060 loge("getActiveSubscriptionInfoList: " + callingPackage + " does not have enough " 2061 + "permission. Returning empty list here."); 2062 return Collections.emptyList(); 2063 } 2064 2065 enforceTelephonyFeatureWithException(callingPackage, "getActiveSubscriptionInfoList"); 2066 2067 if (isForAllProfiles) { 2068 enforcePermissionAccessAllUserProfiles(); 2069 } 2070 return getSubscriptionInfoStreamAsUser(isForAllProfiles 2071 ? UserHandle.ALL : BINDER_WRAPPER.getCallingUserHandle()) 2072 .filter(SubscriptionInfoInternal::isActive) 2073 // Remove the identifier if the caller does not have sufficient permission. 2074 // carrier apps will get full subscription info on the subscriptions associated 2075 // to them. 2076 .map(subInfo -> conditionallyRemoveIdentifiers(subInfo.toSubscriptionInfo(), 2077 callingPackage, callingFeatureId, "getActiveSubscriptionInfoList")) 2078 .sorted(Comparator.comparing(SubscriptionInfo::getSimSlotIndex) 2079 .thenComparing(SubscriptionInfo::getSubscriptionId)) 2080 .collect(Collectors.toList()); 2081 } 2082 2083 /** 2084 * Get the number of active {@link SubscriptionInfo}. 2085 * 2086 * @param callingPackage The package making the call. 2087 * @param callingFeatureId The feature in the package. 2088 * @param isForAllProfiles whether the caller intends to see all subscriptions regardless 2089 * association. 2090 * 2091 * @return the number of active subscriptions. 2092 * 2093 * @throws SecurityException if the caller does not have required permissions. 2094 */ 2095 @Override 2096 @RequiresPermission(anyOf = { 2097 Manifest.permission.READ_PHONE_STATE, 2098 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 2099 "carrier privileges", 2100 }) getActiveSubInfoCount(@onNull String callingPackage, @Nullable String callingFeatureId, boolean isForAllProfiles)2101 public int getActiveSubInfoCount(@NonNull String callingPackage, 2102 @Nullable String callingFeatureId, boolean isForAllProfiles) { 2103 if (!TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(mContext, 2104 Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, callingFeatureId, 2105 "getAllSubInfoList")) { 2106 throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or " 2107 + "carrier privilege"); 2108 } 2109 if (isForAllProfiles) { 2110 enforcePermissionAccessAllUserProfiles(); 2111 } 2112 2113 enforceTelephonyFeatureWithException(callingPackage, "getActiveSubInfoCount"); 2114 2115 return getActiveSubIdListAsUser(false, isForAllProfiles 2116 ? UserHandle.ALL : BINDER_WRAPPER.getCallingUserHandle()).length; 2117 } 2118 2119 /** @throws SecurityException if caller doesn't have one of the requested permissions. */ enforcePermissionAccessAllUserProfiles()2120 private void enforcePermissionAccessAllUserProfiles() { 2121 if (!mFeatureFlags.enforceSubscriptionUserFilter()) return; 2122 enforcePermissions("To access across profiles", 2123 Manifest.permission.INTERACT_ACROSS_USERS, 2124 Manifest.permission.INTERACT_ACROSS_USERS_FULL, 2125 Manifest.permission.INTERACT_ACROSS_PROFILES); 2126 } 2127 2128 /** 2129 * @return the maximum number of subscriptions this device will support at any one time. 2130 */ 2131 @Override getActiveSubInfoCountMax()2132 public int getActiveSubInfoCountMax() { 2133 return mTelephonyManager.getActiveModemCount(); 2134 } 2135 2136 /** 2137 * Gets the SubscriptionInfo(s) of all available subscriptions, if any. 2138 * 2139 * Available subscriptions include active ones (those with a non-negative 2140 * {@link SubscriptionInfo#getSimSlotIndex()}) as well as inactive but installed embedded 2141 * subscriptions. 2142 * 2143 * @param callingPackage The package making the call. 2144 * @param callingFeatureId The feature in the package. 2145 * 2146 * @return The available subscription info. 2147 * 2148 * @throws SecurityException if the caller does not have required permissions. 2149 */ 2150 @Override 2151 @NonNull getAvailableSubscriptionInfoList(@onNull String callingPackage, @Nullable String callingFeatureId)2152 public List<SubscriptionInfo> getAvailableSubscriptionInfoList(@NonNull String callingPackage, 2153 @Nullable String callingFeatureId) { 2154 enforcePermissions("getAvailableSubscriptionInfoList", 2155 Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 2156 2157 enforceTelephonyFeatureWithException(callingPackage, "getAvailableSubscriptionInfoList"); 2158 2159 return getAvailableSubscriptionsInternalStream() 2160 .sorted(Comparator.comparing(SubscriptionInfoInternal::getSimSlotIndex) 2161 .thenComparing(SubscriptionInfoInternal::getSubscriptionId)) 2162 .map(SubscriptionInfoInternal::toSubscriptionInfo) 2163 .collect(Collectors.toList()); 2164 2165 } 2166 2167 /** 2168 * @return all the subscriptions visible to user on the device. 2169 */ getAvailableSubscriptionsInternalStream()2170 private Stream<SubscriptionInfoInternal> getAvailableSubscriptionsInternalStream() { 2171 // Available eSIM profiles are reported by EuiccManager. However for physical SIMs if 2172 // they are in inactive slot or programmatically disabled, they are still considered 2173 // available. In this case we get their iccid from slot info and include their 2174 // subscriptionInfos. 2175 List<String> iccIds = getIccIdsOfInsertedPhysicalSims(); 2176 2177 return mSubscriptionDatabaseManager.getAllSubscriptions().stream() 2178 .filter(subInfo -> subInfo.isActive() || iccIds.contains(subInfo.getIccId()) 2179 || (mEuiccManager != null && mEuiccManager.isEnabled() 2180 && subInfo.isEmbedded())); 2181 } 2182 2183 /** 2184 * Tracks for each user Id, a list of subscriptions associated with it. 2185 * A profile is barred from seeing unassociated subscriptions if it has its own subscription 2186 * which is available to choose from the device. 2187 */ updateUserIdToAvailableSubs()2188 private void updateUserIdToAvailableSubs() { 2189 mUserIdToAvailableSubs = getAvailableSubscriptionsInternalStream() 2190 .collect(Collectors.groupingBy( 2191 SubscriptionInfoInternal::getUserId, 2192 Collectors.mapping(SubscriptionInfoInternal::getSubscriptionId, 2193 Collectors.toList()))); 2194 log("updateUserIdToAvailableSubs: " + mUserIdToAvailableSubs); 2195 } 2196 2197 /** 2198 * Gets the SubscriptionInfo(s) of all embedded subscriptions accessible to the calling app, if 2199 * any. 2200 * 2201 * <p>Only those subscriptions for which the calling app has carrier privileges per the 2202 * subscription metadata, if any, will be included in the returned list. 2203 * 2204 * <p>The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by 2205 * {@link SubscriptionInfo#getSubscriptionId}. 2206 * 2207 * @return Sorted list of the current embedded {@link SubscriptionInfo} records available on the 2208 * device which are accessible to the caller. 2209 * <ul> 2210 * <li> 2211 * 2212 * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} 2213 * then by {@link SubscriptionInfo#getSubscriptionId}. 2214 * </ul> 2215 * 2216 * @param callingPackage The package making the call. 2217 * 2218 * @throws SecurityException if the caller does not have required permissions. 2219 */ 2220 @Override getAccessibleSubscriptionInfoList( @onNull String callingPackage)2221 public List<SubscriptionInfo> getAccessibleSubscriptionInfoList( 2222 @NonNull String callingPackage) { 2223 if (!mEuiccManager.isEnabled()) { 2224 return null; 2225 } 2226 2227 // Verify that the callingPackage belongs to the calling UID 2228 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 2229 return getSubscriptionInfoStreamAsUser(BINDER_WRAPPER.getCallingUserHandle()) 2230 .map(SubscriptionInfoInternal::toSubscriptionInfo) 2231 .filter(subInfo -> subInfo.isEmbedded() 2232 && mSubscriptionManager.canManageSubscription(subInfo, callingPackage)) 2233 .sorted(Comparator.comparing(SubscriptionInfo::getSimSlotIndex) 2234 .thenComparing(SubscriptionInfo::getSubscriptionId)) 2235 .collect(Collectors.toList()); 2236 } 2237 2238 /** 2239 * @see SubscriptionManager#requestEmbeddedSubscriptionInfoListRefresh 2240 */ 2241 @Override requestEmbeddedSubscriptionInfoListRefresh(int cardId)2242 public void requestEmbeddedSubscriptionInfoListRefresh(int cardId) { 2243 enforcePermissions("requestEmbeddedSubscriptionInfoListRefresh", 2244 Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS); 2245 updateEmbeddedSubscriptions(List.of(cardId), null); 2246 } 2247 2248 /** 2249 * Add a new subscription info record, if needed. This should be only used for remote SIM. 2250 * 2251 * @param iccId ICCID of the SIM card. 2252 * @param displayName human-readable name of the device the subscription corresponds to. 2253 * @param slotIndex the logical SIM slot index assigned to this device. 2254 * @param subscriptionType the type of subscription to be added 2255 * 2256 * @return 0 if success, < 0 on error 2257 * 2258 * @throws SecurityException if the caller does not have required permissions. 2259 * @throws IllegalArgumentException if {@code slotIndex} is invalid. 2260 */ 2261 @Override 2262 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) addSubInfo(@onNull String iccId, @NonNull String displayName, int slotIndex, @SubscriptionType int subscriptionType)2263 public int addSubInfo(@NonNull String iccId, @NonNull String displayName, int slotIndex, 2264 @SubscriptionType int subscriptionType) { 2265 enforcePermissions("addSubInfo", Manifest.permission.MODIFY_PHONE_STATE); 2266 logl("addSubInfo: iccId=" + SubscriptionInfo.getPrintableId(iccId) + ", slotIndex=" 2267 + slotIndex + ", displayName=" + displayName + ", type=" 2268 + SubscriptionManager.subscriptionTypeToString(subscriptionType) + ", " 2269 + getCallingPackage()); 2270 2271 enforceTelephonyFeatureWithException(getCurrentPackageName(), "addSubInfo"); 2272 2273 if (!SubscriptionManager.isValidSlotIndex(slotIndex) 2274 && slotIndex != SubscriptionManager.INVALID_SIM_SLOT_INDEX) { 2275 throw new IllegalArgumentException("Invalid slotIndex " + slotIndex); 2276 } 2277 2278 // Now that all security checks passes, perform the operation as ourselves. 2279 final long identity = Binder.clearCallingIdentity(); 2280 try { 2281 if (TextUtils.isEmpty(iccId)) { 2282 loge("addSubInfo: null or empty iccId"); 2283 return -1; 2284 } 2285 2286 iccId = IccUtils.stripTrailingFs(iccId); 2287 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 2288 .getSubscriptionInfoInternalByIccId(iccId); 2289 2290 // Check if the record exists or not. 2291 if (subInfo == null) { 2292 // Record does not exist. 2293 if (mSlotIndexToSubId.containsKey(slotIndex)) { 2294 loge("Already a subscription on slot " + slotIndex); 2295 return -1; 2296 } 2297 2298 int subId = insertSubscriptionInfo(iccId, slotIndex, displayName, subscriptionType); 2299 updateGroupDisabled(); 2300 mSlotIndexToSubId.put(slotIndex, subId); 2301 logl("addSubInfo: current mapping " + slotMappingToString()); 2302 } else { 2303 // Record already exists. 2304 loge("Subscription record already existed."); 2305 return -1; 2306 } 2307 } finally { 2308 Binder.restoreCallingIdentity(identity); 2309 } 2310 return 0; 2311 } 2312 2313 /** 2314 * Remove subscription info record from the subscription database. 2315 * 2316 * @param uniqueId This is the unique identifier for the subscription within the specific 2317 * subscription type. 2318 * @param subscriptionType the type of subscription to be removed. 2319 * 2320 * @return {@code true} if succeeded, otherwise {@code false}. 2321 * 2322 * @throws NullPointerException if {@code uniqueId} is {@code null}. 2323 * @throws SecurityException if callers do not hold the required permission. 2324 */ 2325 @Override 2326 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) removeSubInfo(@onNull String uniqueId, int subscriptionType)2327 public boolean removeSubInfo(@NonNull String uniqueId, int subscriptionType) { 2328 enforcePermissions("removeSubInfo", Manifest.permission.MODIFY_PHONE_STATE); 2329 2330 logl("removeSubInfo: uniqueId=" + SubscriptionInfo.getPrintableId(uniqueId) + ", " 2331 + SubscriptionManager.subscriptionTypeToString(subscriptionType) + ", " 2332 + getCallingPackage()); 2333 2334 enforceTelephonyFeatureWithException(getCurrentPackageName(), "removeSubInfo"); 2335 2336 final long identity = Binder.clearCallingIdentity(); 2337 try { 2338 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 2339 .getSubscriptionInfoInternalByIccId(uniqueId); 2340 if (subInfo == null) { 2341 loge("Cannot find subscription with uniqueId " + uniqueId); 2342 return false; 2343 } 2344 if (subInfo.getSubscriptionType() != subscriptionType) { 2345 loge("The subscription type does not match."); 2346 return false; 2347 } 2348 mSlotIndexToSubId.remove(subInfo.getSimSlotIndex()); 2349 mSubscriptionDatabaseManager.removeSubscriptionInfo(subInfo.getSubscriptionId()); 2350 return true; 2351 } finally { 2352 Binder.restoreCallingIdentity(identity); 2353 } 2354 } 2355 2356 /** 2357 * Set SIM icon tint color by simInfo index. 2358 * 2359 * @param subId the unique subscription index in database 2360 * @param tint the icon tint color of the SIM 2361 * 2362 * @return the number of records updated 2363 * 2364 * @throws IllegalArgumentException if {@code subId} is invalid or the subscription does not 2365 * exist. 2366 * @throws SecurityException if callers do not hold the required permission. 2367 */ 2368 @Override 2369 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setIconTint(int subId, @ColorInt int tint)2370 public int setIconTint(int subId, @ColorInt int tint) { 2371 enforcePermissions("setIconTint", Manifest.permission.MODIFY_PHONE_STATE); 2372 2373 final long identity = Binder.clearCallingIdentity(); 2374 try { 2375 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 2376 throw new IllegalArgumentException("Invalid sub id passed as parameter"); 2377 } 2378 2379 mSubscriptionDatabaseManager.setIconTint(subId, tint); 2380 return 1; 2381 } finally { 2382 Binder.restoreCallingIdentity(identity); 2383 } 2384 } 2385 2386 /** 2387 * Set display name of a subscription. 2388 * 2389 * @param displayName The display name of SIM card. 2390 * @param subId The subscription id. 2391 * @param nameSource The display name source. 2392 * 2393 * @return the number of records updated 2394 * 2395 * @throws IllegalArgumentException if {@code nameSource} is invalid, or {@code subId} is 2396 * invalid. 2397 * @throws NullPointerException if {@code displayName} is {@code null}. 2398 * @throws SecurityException if callers do not hold the required permission. 2399 */ 2400 @Override 2401 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDisplayNameUsingSrc(@onNull String displayName, int subId, @SimDisplayNameSource int nameSource)2402 public int setDisplayNameUsingSrc(@NonNull String displayName, int subId, 2403 @SimDisplayNameSource int nameSource) { 2404 enforcePermissions("setDisplayNameUsingSrc", Manifest.permission.MODIFY_PHONE_STATE); 2405 2406 String callingPackage = getCallingPackage(); 2407 final long identity = Binder.clearCallingIdentity(); 2408 try { 2409 Objects.requireNonNull(displayName, "setDisplayNameUsingSrc"); 2410 2411 if (nameSource < SubscriptionManager.NAME_SOURCE_CARRIER_ID 2412 || nameSource > SubscriptionManager.NAME_SOURCE_SIM_PNN) { 2413 throw new IllegalArgumentException("illegal name source " + nameSource); 2414 } 2415 2416 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 2417 .getSubscriptionInfoInternal(subId); 2418 2419 if (subInfo == null) { 2420 throw new IllegalArgumentException("Cannot find subscription info with sub id " 2421 + subId); 2422 } 2423 2424 if (getNameSourcePriority(subInfo.getDisplayNameSource()) 2425 > getNameSourcePriority(nameSource) 2426 || (getNameSourcePriority(subInfo.getDisplayNameSource()) 2427 == getNameSourcePriority(nameSource)) 2428 && (TextUtils.equals(displayName, subInfo.getDisplayName()))) { 2429 log("No need to update the display name. nameSource=" 2430 + SubscriptionManager.displayNameSourceToString(nameSource) 2431 + ", existing name=" + subInfo.getDisplayName() + ", source=" 2432 + SubscriptionManager.displayNameSourceToString( 2433 subInfo.getDisplayNameSource())); 2434 return 0; 2435 } 2436 2437 String nameToSet; 2438 if (TextUtils.isEmpty(displayName) || displayName.trim().length() == 0) { 2439 nameToSet = mTelephonyManager.getSimOperatorName(subId); 2440 if (TextUtils.isEmpty(nameToSet)) { 2441 if (nameSource == SubscriptionManager.NAME_SOURCE_USER_INPUT 2442 && SubscriptionManager.isValidSlotIndex(getSlotIndex(subId))) { 2443 Resources r = Resources.getSystem(); 2444 nameToSet = r.getString(R.string.default_card_name, 2445 (getSlotIndex(subId) + 1)); 2446 } else { 2447 nameToSet = mContext.getString(SubscriptionManager.DEFAULT_NAME_RES); 2448 } 2449 } 2450 } else { 2451 nameToSet = displayName; 2452 } 2453 2454 logl("setDisplayNameUsingSrc: subId=" + subId + ", name=" + nameToSet 2455 + ", nameSource=" + SubscriptionManager.displayNameSourceToString(nameSource) 2456 + ", calling package=" + callingPackage); 2457 mSubscriptionDatabaseManager.setDisplayName(subId, nameToSet); 2458 mSubscriptionDatabaseManager.setDisplayNameSource(subId, nameSource); 2459 2460 // Update the nickname on the eUICC chip if it's an embedded subscription. 2461 SubscriptionInfo sub = getSubscriptionInfo(subId); 2462 if (sub != null && sub.isEmbedded()) { 2463 int cardId = sub.getCardId(); 2464 log("Updating embedded sub nickname on cardId: " + cardId); 2465 mEuiccManager.updateSubscriptionNickname(subId, nameToSet, 2466 // This PendingIntent simply fulfills the requirement to pass in a callback; 2467 // we don't care about the result (hence 0 requestCode and no action 2468 // specified on the intent). 2469 PendingIntent.getService(mContext, 0 /* requestCode */, new Intent(), 2470 PendingIntent.FLAG_IMMUTABLE /* flags */)); 2471 } 2472 2473 return 1; 2474 } finally { 2475 Binder.restoreCallingIdentity(identity); 2476 } 2477 } 2478 2479 /** 2480 * Set phone number by subscription id. 2481 * 2482 * @param number the phone number of the SIM. 2483 * @param subId the unique SubscriptionInfo index in database. 2484 * 2485 * @return the number of records updated. 2486 * 2487 * @throws SecurityException if callers do not hold the required permission. 2488 * @throws NullPointerException if {@code number} is {@code null}. 2489 */ 2490 @Override 2491 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDisplayNumber(@onNull String number, int subId)2492 public int setDisplayNumber(@NonNull String number, int subId) { 2493 enforcePermissions("setDisplayNumber", Manifest.permission.MODIFY_PHONE_STATE); 2494 logl("setDisplayNumber: subId=" + subId + ", number=" 2495 + Rlog.pii(TelephonyUtils.IS_DEBUGGABLE, number) 2496 + ", calling package=" + getCallingPackage()); 2497 // Now that all security checks passes, perform the operation as ourselves. 2498 final long identity = Binder.clearCallingIdentity(); 2499 try { 2500 mSubscriptionDatabaseManager.setNumber(subId, number); 2501 return 1; 2502 } finally { 2503 Binder.restoreCallingIdentity(identity); 2504 } 2505 } 2506 2507 /** 2508 * Set data roaming by simInfo index 2509 * 2510 * @param roaming 0:Don't allow data when roaming, 1:Allow data when roaming 2511 * @param subId the unique SubscriptionInfo index in database 2512 * 2513 * @return the number of records updated 2514 * 2515 * @throws IllegalArgumentException if {@code subId} or {@code roaming} is not valid. 2516 * @throws SecurityException if callers do not hold the required permission. 2517 */ 2518 @Override 2519 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDataRoaming(@ataRoamingMode int roaming, int subId)2520 public int setDataRoaming(@DataRoamingMode int roaming, int subId) { 2521 enforcePermissions("setDataRoaming", Manifest.permission.MODIFY_PHONE_STATE); 2522 2523 // Now that all security checks passes, perform the operation as ourselves. 2524 final long identity = Binder.clearCallingIdentity(); 2525 try { 2526 if (roaming < 0) { 2527 throw new IllegalArgumentException("Invalid roaming value " + roaming); 2528 } 2529 2530 mSubscriptionDatabaseManager.setDataRoaming(subId, roaming); 2531 return 1; 2532 } finally { 2533 Binder.restoreCallingIdentity(identity); 2534 } 2535 } 2536 2537 /** 2538 * Switch to a certain subscription. 2539 * 2540 * @param opportunistic whether it’s opportunistic subscription 2541 * @param subId the unique SubscriptionInfo index in database 2542 * @param callingPackage The package making the call 2543 * 2544 * @return the number of records updated 2545 * 2546 * @throws IllegalArgumentException if {@code subId} is invalid. 2547 * @throws SecurityException if callers do not hold the required permission. 2548 */ 2549 @Override 2550 @RequiresPermission(anyOf = { 2551 Manifest.permission.MODIFY_PHONE_STATE, 2552 "carrier privileges", 2553 }) setOpportunistic(boolean opportunistic, int subId, @NonNull String callingPackage)2554 public int setOpportunistic(boolean opportunistic, int subId, @NonNull String callingPackage) { 2555 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges( 2556 mContext, subId, Binder.getCallingUid(), true, "setOpportunistic", 2557 Manifest.permission.MODIFY_PHONE_STATE); 2558 2559 enforceTelephonyFeatureWithException(callingPackage, "setOpportunistic"); 2560 2561 long token = Binder.clearCallingIdentity(); 2562 try { 2563 mSubscriptionDatabaseManager.setOpportunistic(subId, opportunistic); 2564 return 1; 2565 } finally { 2566 Binder.restoreCallingIdentity(token); 2567 } 2568 } 2569 2570 /** 2571 * Inform SubscriptionManager that subscriptions in the list are bundled as a group. Typically 2572 * it's a primary subscription and an opportunistic subscription. It should only affect 2573 * multi-SIM scenarios where primary and opportunistic subscriptions can be activated together. 2574 * 2575 * Being in the same group means they might be activated or deactivated together, some of them 2576 * may be invisible to the users, etc. 2577 * 2578 * Caller will either have {@link Manifest.permission#MODIFY_PHONE_STATE} permission or 2579 * can manage all subscriptions in the list, according to their access rules. 2580 * 2581 * @param subIdList list of subId that will be in the same group. 2582 * @param callingPackage The package making the call. 2583 * 2584 * @return groupUUID a UUID assigned to the subscription group. It returns null if fails. 2585 * 2586 * @throws IllegalArgumentException if {@code subId} is invalid. 2587 * @throws SecurityException if callers do not hold the required permission. 2588 */ 2589 @Override 2590 @RequiresPermission(anyOf = { 2591 Manifest.permission.MODIFY_PHONE_STATE, 2592 "carrier privileges", 2593 }) createSubscriptionGroup(@onNull int[] subIdList, @NonNull String callingPackage)2594 public ParcelUuid createSubscriptionGroup(@NonNull int[] subIdList, 2595 @NonNull String callingPackage) { 2596 // Verify that the callingPackage belongs to the calling UID 2597 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 2598 2599 Objects.requireNonNull(subIdList, "createSubscriptionGroup"); 2600 if (subIdList.length == 0) { 2601 throw new IllegalArgumentException("Invalid subIdList " + Arrays.toString(subIdList)); 2602 } 2603 2604 // If it doesn't have modify phone state permission, or carrier privilege permission, 2605 // a SecurityException will be thrown. 2606 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) 2607 != PackageManager.PERMISSION_GRANTED && !checkCarrierPrivilegeOnSubList( 2608 subIdList, callingPackage)) { 2609 throw new SecurityException("CreateSubscriptionGroup needs MODIFY_PHONE_STATE or" 2610 + " carrier privilege permission on all specified subscriptions"); 2611 } 2612 2613 enforceTelephonyFeatureWithException(callingPackage, "createSubscriptionGroup"); 2614 2615 long identity = Binder.clearCallingIdentity(); 2616 2617 try { 2618 // Generate a UUID. 2619 ParcelUuid groupUUID = new ParcelUuid(UUID.randomUUID()); 2620 String uuidString = groupUUID.toString(); 2621 2622 for (int subId : subIdList) { 2623 mSubscriptionDatabaseManager.setGroupUuid(subId, uuidString); 2624 mSubscriptionDatabaseManager.setGroupOwner(subId, callingPackage); 2625 } 2626 updateGroupDisabled(); 2627 2628 MultiSimSettingController.getInstance().notifySubscriptionGroupChanged(groupUUID); 2629 return groupUUID; 2630 } finally { 2631 Binder.restoreCallingIdentity(identity); 2632 } 2633 } 2634 2635 /** 2636 * Set which subscription is preferred for cellular data. It's designed to overwrite default 2637 * data subscription temporarily. 2638 * 2639 * @param subId which subscription is preferred to for cellular data 2640 * @param needValidation whether validation is needed before switching 2641 * @param callback callback upon request completion 2642 * 2643 * @throws SecurityException if callers do not hold the required permission. 2644 */ 2645 @Override 2646 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setPreferredDataSubscriptionId(int subId, boolean needValidation, @Nullable ISetOpportunisticDataCallback callback)2647 public void setPreferredDataSubscriptionId(int subId, boolean needValidation, 2648 @Nullable ISetOpportunisticDataCallback callback) { 2649 enforcePermissions("setPreferredDataSubscriptionId", 2650 Manifest.permission.MODIFY_PHONE_STATE); 2651 2652 enforceTelephonyFeatureWithException(getCurrentPackageName(), 2653 "setPreferredDataSubscriptionId"); 2654 2655 final long token = Binder.clearCallingIdentity(); 2656 2657 try { 2658 PhoneSwitcher phoneSwitcher = PhoneSwitcher.getInstance(); 2659 if (phoneSwitcher == null) { 2660 loge("Set preferred data sub: phoneSwitcher is null."); 2661 if (callback != null) { 2662 try { 2663 callback.onComplete( 2664 TelephonyManager.SET_OPPORTUNISTIC_SUB_REMOTE_SERVICE_EXCEPTION); 2665 } catch (RemoteException exception) { 2666 loge("RemoteException " + exception); 2667 } 2668 } 2669 return; 2670 } 2671 2672 phoneSwitcher.trySetOpportunisticDataSubscription(subId, needValidation, callback); 2673 } finally { 2674 Binder.restoreCallingIdentity(token); 2675 } 2676 } 2677 2678 /** 2679 * @return The subscription id of preferred subscription for cellular data. This reflects 2680 * the active modem which can serve large amount of cellular data. 2681 * 2682 * @throws SecurityException if callers do not hold the required permission. 2683 */ 2684 @Override 2685 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getPreferredDataSubscriptionId()2686 public int getPreferredDataSubscriptionId() { 2687 enforcePermissions("getPreferredDataSubscriptionId", 2688 Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 2689 final long token = Binder.clearCallingIdentity(); 2690 2691 try { 2692 PhoneSwitcher phoneSwitcher = PhoneSwitcher.getInstance(); 2693 if (phoneSwitcher == null) { 2694 loge("getPreferredDataSubscriptionId: PhoneSwitcher not available. Return the " 2695 + "default data sub " + getDefaultDataSubId()); 2696 return getDefaultDataSubId(); 2697 } 2698 2699 return phoneSwitcher.getAutoSelectedDataSubId(); 2700 } finally { 2701 Binder.restoreCallingIdentity(token); 2702 } 2703 } 2704 2705 /** 2706 * Get the opportunistic subscriptions. 2707 * 2708 * Callers with {@link Manifest.permission#READ_PHONE_STATE} or 2709 * {@link Manifest.permission#READ_PRIVILEGED_PHONE_STATE} will have a full list of 2710 * opportunistic subscriptions. Subscriptions that the carrier app has no privilege will be 2711 * excluded from the list. 2712 * 2713 * @param callingPackage The package making the call. 2714 * @param callingFeatureId The feature in the package. 2715 * 2716 * @return The list of opportunistic subscription info that can be accessed by the callers. 2717 */ 2718 @Override 2719 @NonNull 2720 @RequiresPermission(anyOf = { 2721 Manifest.permission.READ_PHONE_STATE, 2722 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 2723 "carrier privileges", 2724 }) getOpportunisticSubscriptions(@onNull String callingPackage, @Nullable String callingFeatureId)2725 public List<SubscriptionInfo> getOpportunisticSubscriptions(@NonNull String callingPackage, 2726 @Nullable String callingFeatureId) { 2727 // Check if the caller has READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or carrier 2728 // privilege on any active subscription. The carrier app will get full subscription infos 2729 // on the subs it has carrier privilege. 2730 if (!TelephonyPermissions.checkReadPhoneStateOnAnyActiveSub(mContext, 2731 Binder.getCallingPid(), Binder.getCallingUid(), callingPackage, callingFeatureId, 2732 "getOpportunisticSubscriptions")) { 2733 // Ideally we should avoid silent failure, but since this API has already been used by 2734 // many apps and they do not expect the security exception, we return an empty list 2735 // here so it's consistent with pre-U behavior. 2736 loge("getOpportunisticSubscriptions: " + callingPackage + " does not have enough " 2737 + "permission. Returning empty list here."); 2738 return Collections.emptyList(); 2739 } 2740 2741 enforceTelephonyFeatureWithException(callingPackage, "getOpportunisticSubscriptions"); 2742 2743 return mSubscriptionDatabaseManager.getAllSubscriptions().stream() 2744 // callers have READ_PHONE_STATE or READ_PRIVILEGED_PHONE_STATE can get a full 2745 // list. Carrier apps can only get the subscriptions they have privileged. 2746 .filter(subInfo -> subInfo.isOpportunistic() 2747 && TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow( 2748 mContext, subInfo.getSubscriptionId(), callingPackage, 2749 callingFeatureId, "getOpportunisticSubscriptions")) 2750 // Remove the identifier if the caller does not have sufficient permission. 2751 // carrier apps will get full subscription info on the subscriptions associated 2752 // to them. 2753 .map(subInfo -> conditionallyRemoveIdentifiers(subInfo.toSubscriptionInfo(), 2754 callingPackage, callingFeatureId, "getOpportunisticSubscriptions")) 2755 .sorted(Comparator.comparing(SubscriptionInfo::getSimSlotIndex) 2756 .thenComparing(SubscriptionInfo::getSubscriptionId)) 2757 .collect(Collectors.toList()); 2758 } 2759 2760 /** 2761 * Remove a list of subscriptions from their subscription group. 2762 * 2763 * @param subIdList list of subId that need removing from their groups. 2764 * @param groupUuid The UUID of the subscription group. 2765 * @param callingPackage The package making the call. 2766 * 2767 * @throws SecurityException if the caller doesn't meet the requirements outlined above. 2768 * @throws IllegalArgumentException if the some subscriptions in the list doesn't belong the 2769 * specified group. 2770 * 2771 * @see SubscriptionManager#createSubscriptionGroup(List) 2772 */ 2773 @Override 2774 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) removeSubscriptionsFromGroup(@onNull int[] subIdList, @NonNull ParcelUuid groupUuid, @NonNull String callingPackage)2775 public void removeSubscriptionsFromGroup(@NonNull int[] subIdList, 2776 @NonNull ParcelUuid groupUuid, @NonNull String callingPackage) { 2777 // If it doesn't have modify phone state permission, or carrier privilege permission, 2778 // a SecurityException will be thrown. If it's due to invalid parameter or internal state, 2779 // it will return null. 2780 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) 2781 != PackageManager.PERMISSION_GRANTED 2782 && !(checkCarrierPrivilegeOnSubList(subIdList, callingPackage) 2783 && canPackageManageGroup(groupUuid, callingPackage))) { 2784 throw new SecurityException("removeSubscriptionsFromGroup needs MODIFY_PHONE_STATE or" 2785 + " carrier privilege permission on all specified subscriptions."); 2786 } 2787 2788 Objects.requireNonNull(subIdList); 2789 Objects.requireNonNull(groupUuid); 2790 2791 if (subIdList.length == 0) { 2792 throw new IllegalArgumentException("subIdList is empty."); 2793 } 2794 2795 enforceTelephonyFeatureWithException(callingPackage, "removeSubscriptionsFromGroup"); 2796 2797 long identity = Binder.clearCallingIdentity(); 2798 2799 try { 2800 for (int subId : subIdList) { 2801 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 2802 .getSubscriptionInfoInternal(subId); 2803 if (subInfo == null) { 2804 throw new IllegalArgumentException("The provided sub id " + subId 2805 + " is not valid."); 2806 } 2807 if (!groupUuid.toString().equals(subInfo.getGroupUuid())) { 2808 throw new IllegalArgumentException("Subscription " + subInfo.getSubscriptionId() 2809 + " doesn't belong to group " + groupUuid); 2810 } 2811 } 2812 2813 for (SubscriptionInfoInternal subInfo : 2814 mSubscriptionDatabaseManager.getAllSubscriptions()) { 2815 if (IntStream.of(subIdList).anyMatch( 2816 subId -> subId == subInfo.getSubscriptionId())) { 2817 mSubscriptionDatabaseManager.setGroupUuid(subInfo.getSubscriptionId(), ""); 2818 mSubscriptionDatabaseManager.setGroupOwner(subInfo.getSubscriptionId(), ""); 2819 } else if (subInfo.getGroupUuid().equals(groupUuid.toString())) { 2820 // Pre-T behavior. If there are still subscriptions having the same UUID, update 2821 // to the new owner. 2822 mSubscriptionDatabaseManager.setGroupOwner( 2823 subInfo.getSubscriptionId(), callingPackage); 2824 } 2825 } 2826 2827 updateGroupDisabled(); 2828 } finally { 2829 Binder.restoreCallingIdentity(identity); 2830 } 2831 } 2832 2833 /** 2834 * Add a list of subscriptions into a group. 2835 * 2836 * Caller should either have {@link android.Manifest.permission#MODIFY_PHONE_STATE} 2837 * permission or had carrier privilege permission on the subscriptions. 2838 * 2839 * @param subIdList list of subId that need adding into the group 2840 * @param groupUuid the groupUuid the subscriptions are being added to. 2841 * @param callingPackage The package making the call. 2842 * 2843 * @throws SecurityException if the caller doesn't meet the requirements outlined above. 2844 * @throws IllegalArgumentException if the some subscriptions in the list doesn't exist. 2845 * 2846 * @see SubscriptionManager#createSubscriptionGroup(List) 2847 */ 2848 @Override 2849 @RequiresPermission(anyOf = { 2850 Manifest.permission.MODIFY_PHONE_STATE, 2851 "carrier privileges", 2852 }) addSubscriptionsIntoGroup(@onNull int[] subIdList, @NonNull ParcelUuid groupUuid, @NonNull String callingPackage)2853 public void addSubscriptionsIntoGroup(@NonNull int[] subIdList, @NonNull ParcelUuid groupUuid, 2854 @NonNull String callingPackage) { 2855 Objects.requireNonNull(subIdList, "subIdList"); 2856 if (subIdList.length == 0) { 2857 throw new IllegalArgumentException("Invalid subId list"); 2858 } 2859 2860 Objects.requireNonNull(groupUuid, "groupUuid"); 2861 String groupUuidString = groupUuid.toString(); 2862 if (groupUuidString.equals(CarrierConfigManager.REMOVE_GROUP_UUID_STRING)) { 2863 throw new IllegalArgumentException("Invalid groupUuid"); 2864 } 2865 2866 // Verify that the callingPackage belongs to the calling UID 2867 mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackage); 2868 2869 // If it doesn't have modify phone state permission, or carrier privilege permission, 2870 // a SecurityException will be thrown. 2871 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.MODIFY_PHONE_STATE) 2872 != PackageManager.PERMISSION_GRANTED 2873 && !(checkCarrierPrivilegeOnSubList(subIdList, callingPackage) 2874 && canPackageManageGroup(groupUuid, callingPackage))) { 2875 throw new SecurityException("Requires MODIFY_PHONE_STATE or carrier privilege" 2876 + " permissions on subscriptions and the group."); 2877 } 2878 2879 enforceTelephonyFeatureWithException(callingPackage, "addSubscriptionsIntoGroup"); 2880 2881 long identity = Binder.clearCallingIdentity(); 2882 2883 try { 2884 for (int subId : subIdList) { 2885 mSubscriptionDatabaseManager.setGroupUuid(subId, groupUuidString); 2886 mSubscriptionDatabaseManager.setGroupOwner(subId, callingPackage); 2887 } 2888 2889 updateGroupDisabled(); 2890 MultiSimSettingController.getInstance().notifySubscriptionGroupChanged(groupUuid); 2891 logl("addSubscriptionsIntoGroup: add subs " + Arrays.toString(subIdList) 2892 + " to the group."); 2893 } finally { 2894 Binder.restoreCallingIdentity(identity); 2895 } 2896 } 2897 2898 /** 2899 * Get subscriptionInfo list of subscriptions that are in the same group of given subId. 2900 * See {@link #createSubscriptionGroup(int[], String)} for more details. 2901 * 2902 * Caller must have {@link android.Manifest.permission#READ_PHONE_STATE} 2903 * or carrier privilege permission on the subscription. 2904 * 2905 * <p>Starting with API level 33, the caller also needs permission to access device identifiers 2906 * to get the list of subscriptions associated with a group UUID. 2907 * This method can be invoked if one of the following requirements is met: 2908 * <ul> 2909 * <li>If the app has carrier privilege permission. 2910 * {@link TelephonyManager#hasCarrierPrivileges()} 2911 * <li>If the app has {@link android.Manifest.permission#READ_PHONE_STATE} permission and 2912 * access to device identifiers. 2913 * </ul> 2914 * 2915 * @param groupUuid of which list of subInfo will be returned. 2916 * @param callingPackage The package making the call. 2917 * @param callingFeatureId The feature in the package. 2918 * 2919 * @return List of {@link SubscriptionInfo} that belong to the same group, including the given 2920 * subscription itself. It will return an empty list if no subscription belongs to the group. 2921 * 2922 * @throws SecurityException if the caller doesn't meet the requirements outlined above. 2923 */ 2924 @Override 2925 @NonNull 2926 @RequiresPermission(anyOf = { 2927 Manifest.permission.READ_PHONE_STATE, 2928 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 2929 "carrier privileges", 2930 }) getSubscriptionsInGroup(@onNull ParcelUuid groupUuid, @NonNull String callingPackage, @Nullable String callingFeatureId)2931 public List<SubscriptionInfo> getSubscriptionsInGroup(@NonNull ParcelUuid groupUuid, 2932 @NonNull String callingPackage, @Nullable String callingFeatureId) { 2933 // If the calling app neither has carrier privileges nor READ_PHONE_STATE and access to 2934 // device identifiers, it will throw a SecurityException. 2935 if (CompatChanges.isChangeEnabled(REQUIRE_DEVICE_IDENTIFIERS_FOR_GROUP_UUID, 2936 Binder.getCallingUid())) { 2937 try { 2938 if (!TelephonyPermissions.checkCallingOrSelfReadDeviceIdentifiers(mContext, 2939 callingPackage, callingFeatureId, "getSubscriptionsInGroup")) { 2940 EventLog.writeEvent(0x534e4554, "213902861", Binder.getCallingUid()); 2941 throw new SecurityException("Need to have carrier privileges or access to " 2942 + "device identifiers to call getSubscriptionsInGroup"); 2943 } 2944 } catch (SecurityException e) { 2945 EventLog.writeEvent(0x534e4554, "213902861", Binder.getCallingUid()); 2946 throw e; 2947 } 2948 } 2949 2950 enforceTelephonyFeatureWithException(callingPackage, "getSubscriptionsInGroup"); 2951 2952 return mSubscriptionDatabaseManager.getAllSubscriptions().stream() 2953 .map(SubscriptionInfoInternal::toSubscriptionInfo) 2954 .filter(info -> groupUuid.equals(info.getGroupUuid()) 2955 && (mSubscriptionManager.canManageSubscription(info, callingPackage) 2956 || TelephonyPermissions.checkCallingOrSelfReadPhoneStateNoThrow( 2957 mContext, info.getSubscriptionId(), callingPackage, 2958 callingFeatureId, "getSubscriptionsInGroup"))) 2959 .map(subscriptionInfo -> conditionallyRemoveIdentifiers(subscriptionInfo, 2960 callingPackage, callingFeatureId, "getSubscriptionsInGroup")) 2961 .collect(Collectors.toList()); 2962 } 2963 2964 /** 2965 * Get slot index associated with the subscription. 2966 * 2967 * @param subId The subscription id. 2968 * 2969 * @return Logical slot index (i.e. phone id) as a positive integer or 2970 * {@link SubscriptionManager#INVALID_SIM_SLOT_INDEX} if the supplied {@code subId} doesn't have 2971 * an associated slot index. 2972 */ 2973 @Override getSlotIndex(int subId)2974 public int getSlotIndex(int subId) { 2975 if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { 2976 subId = getDefaultSubId(); 2977 } 2978 2979 for (Map.Entry<Integer, Integer> entry : mSlotIndexToSubId.entrySet()) { 2980 if (entry.getValue() == subId) return entry.getKey(); 2981 } 2982 2983 return SubscriptionManager.INVALID_SIM_SLOT_INDEX; 2984 } 2985 2986 /** 2987 * Get the subscription id for specified slot index. 2988 * 2989 * @param slotIndex Logical SIM slot index. 2990 * @return The subscription id. {@link SubscriptionManager#INVALID_SUBSCRIPTION_ID} if SIM is 2991 * absent. 2992 */ 2993 @Override getSubId(int slotIndex)2994 public int getSubId(int slotIndex) { 2995 if (slotIndex == SubscriptionManager.DEFAULT_SIM_SLOT_INDEX) { 2996 slotIndex = getSlotIndex(getDefaultSubId()); 2997 } 2998 2999 // Check that we have a valid slotIndex or the slotIndex is for a remote SIM (remote SIM 3000 // uses special slot index that may be invalid otherwise) 3001 if (!SubscriptionManager.isValidSlotIndex(slotIndex) 3002 && slotIndex != SubscriptionManager.SLOT_INDEX_FOR_REMOTE_SIM_SUB) { 3003 return SubscriptionManager.INVALID_SUBSCRIPTION_ID; 3004 } 3005 3006 return mSlotIndexToSubId.getOrDefault(slotIndex, 3007 SubscriptionManager.INVALID_SUBSCRIPTION_ID); 3008 } 3009 3010 /** 3011 * Update default sub id. 3012 */ updateDefaultSubId()3013 private void updateDefaultSubId() { 3014 int subId; 3015 boolean isVoiceCapable = mTelephonyManager.isVoiceCapable(); 3016 3017 if (isVoiceCapable) { 3018 subId = getDefaultVoiceSubId(); 3019 } else { 3020 subId = getDefaultDataSubId(); 3021 } 3022 3023 // If the subId is not active, use the fist active subscription's subId. 3024 if (!mSlotIndexToSubId.containsValue(subId)) { 3025 int[] activeSubIds = getActiveSubIdList(true); 3026 if (activeSubIds.length > 0) { 3027 subId = activeSubIds[0]; 3028 log("updateDefaultSubId: First available active sub = " + subId); 3029 } else { 3030 subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID; 3031 } 3032 } 3033 3034 if (mDefaultSubId.get() != subId) { 3035 int phoneId = getPhoneId(subId); 3036 logl("updateDefaultSubId: Default sub id updated from " + mDefaultSubId.get() + " to " 3037 + subId + ", phoneId=" + phoneId); 3038 mDefaultSubId.set(subId); 3039 3040 Intent intent = new Intent(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED); 3041 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 3042 SubscriptionManager.putPhoneIdAndSubIdExtra(intent, phoneId, subId); 3043 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 3044 } 3045 } 3046 3047 /** 3048 * @return The default subscription id. 3049 * @deprecated Use {@link #getDefaultSubIdAsUser}. 3050 */ 3051 @Override getDefaultSubId()3052 public int getDefaultSubId() { 3053 return getDefaultSubIdAsUser(BINDER_WRAPPER.getCallingUserHandle().getIdentifier()); 3054 } 3055 3056 /** 3057 * @param userId The given user Id to check. 3058 * @return The default subscription id. 3059 */ 3060 @Override getDefaultSubIdAsUser(@serIdInt int userId)3061 public int getDefaultSubIdAsUser(@UserIdInt int userId) { 3062 enforceTelephonyFeatureWithException(getCurrentPackageName(), 3063 "getDefaultVoiceSubIdAsUser"); 3064 3065 return getDefaultAsUser(userId, mDefaultSubId.get()); 3066 } 3067 3068 /** 3069 * Get the default subscription visible to the caller. 3070 * @param userId The calling user Id. 3071 * @param defaultValue Useful if the user owns more than one subscription. 3072 * @return The subscription Id default to use. 3073 */ getDefaultAsUser(@serIdInt int userId, int defaultValue)3074 private int getDefaultAsUser(@UserIdInt int userId, int defaultValue) { 3075 // TODO: Not using mFlags.enforceSubscriptionUserFilter because this affects U CTS. 3076 if (mFeatureFlags.workProfileApiSplit()) { 3077 List<SubscriptionInfoInternal> subInfos = 3078 getSubscriptionInfoStreamAsUser(UserHandle.of(userId)) 3079 .filter(SubscriptionInfoInternal::isActive) 3080 .toList(); 3081 if (subInfos.size() == 1) { 3082 return subInfos.get(0).getSubscriptionId(); 3083 } 3084 } 3085 return defaultValue; 3086 } 3087 3088 /** 3089 * Get phone id from the subscription id. In the implementation, the logical SIM slot index 3090 * is equivalent to phone id. So this method is same as {@link #getSlotIndex(int)}. 3091 * 3092 * @param subId The subscription id. 3093 * 3094 * @return The phone id. 3095 */ 3096 @Override getPhoneId(int subId)3097 public int getPhoneId(int subId) { 3098 if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { 3099 subId = getDefaultSubId(); 3100 } 3101 3102 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 3103 return SubscriptionManager.INVALID_PHONE_INDEX; 3104 } 3105 3106 // slot index and phone id are equivalent in the current implementation. 3107 int slotIndex = getSlotIndex(subId); 3108 if (SubscriptionManager.isValidSlotIndex(slotIndex)) { 3109 return slotIndex; 3110 } 3111 3112 return SubscriptionManager.DEFAULT_PHONE_INDEX; 3113 } 3114 3115 /** 3116 * @return Subscription id of the default cellular data. This reflects the user's default data 3117 * choice, which might be a little bit different than the active one returned by 3118 * {@link #getPreferredDataSubscriptionId()}. 3119 */ 3120 @Override getDefaultDataSubId()3121 public int getDefaultDataSubId() { 3122 return mDefaultDataSubId.get(); 3123 } 3124 3125 /** 3126 * Set the default data subscription id. 3127 * 3128 * @param subId The default data subscription id. 3129 * 3130 * @throws SecurityException if callers do not hold the required permission. 3131 */ 3132 @Override 3133 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDefaultDataSubId(int subId)3134 public void setDefaultDataSubId(int subId) { 3135 enforcePermissions("setDefaultDataSubId", Manifest.permission.MODIFY_PHONE_STATE); 3136 3137 if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { 3138 throw new RuntimeException("setDefaultDataSubId called with DEFAULT_SUBSCRIPTION_ID"); 3139 } 3140 3141 enforceTelephonyFeatureWithException(getCurrentPackageName(), "setDefaultDataSubId"); 3142 3143 final long token = Binder.clearCallingIdentity(); 3144 try { 3145 if (mDefaultDataSubId.set(subId)) { 3146 remapRafIfApplicable(); 3147 3148 MultiSimSettingController.getInstance().notifyDefaultDataSubChanged(); 3149 3150 broadcastSubId(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED, 3151 subId); 3152 3153 updateDefaultSubId(); 3154 } 3155 } finally { 3156 Binder.restoreCallingIdentity(token); 3157 } 3158 } 3159 3160 /** 3161 * Remap Radio Access Family if needed. 3162 */ remapRafIfApplicable()3163 private void remapRafIfApplicable() { 3164 boolean applicable = mSlotIndexToSubId.containsValue(getDefaultDataSubId()); 3165 if (!applicable) return; 3166 ProxyController proxyController = ProxyController.getInstance(); 3167 RadioAccessFamily[] rafs = new RadioAccessFamily[mTelephonyManager.getActiveModemCount()]; 3168 for (int phoneId = 0; phoneId < rafs.length; phoneId++) { 3169 int raf = mSlotIndexToSubId.getOrDefault(phoneId, 3170 SubscriptionManager.INVALID_SUBSCRIPTION_ID) == getDefaultDataSubId() 3171 ? proxyController.getMaxRafSupported() : proxyController.getMinRafSupported(); 3172 rafs[phoneId] = new RadioAccessFamily(phoneId, raf); 3173 } 3174 proxyController.setRadioCapability(rafs); 3175 } 3176 3177 /** 3178 * @return The default subscription id for voice. 3179 * @deprecated Use {@link #getDefaultVoiceSubIdAsUser}. 3180 */ 3181 @Override getDefaultVoiceSubId()3182 public int getDefaultVoiceSubId() { 3183 return getDefaultVoiceSubIdAsUser(BINDER_WRAPPER.getCallingUserHandle().getIdentifier()); 3184 } 3185 3186 /** 3187 * @param userId The calling user Id. 3188 * @return The default voice subscription id. 3189 */ 3190 @Override getDefaultVoiceSubIdAsUser(@serIdInt int userId)3191 public int getDefaultVoiceSubIdAsUser(@UserIdInt int userId) { 3192 return getDefaultAsUser(userId, mDefaultVoiceSubId.get()); 3193 } 3194 3195 /** 3196 * Set the default voice subscription id. 3197 * 3198 * @param subId The default SMS subscription id. 3199 * 3200 * @throws SecurityException if callers do not hold the required permission. 3201 */ 3202 @Override 3203 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDefaultVoiceSubId(int subId)3204 public void setDefaultVoiceSubId(int subId) { 3205 enforcePermissions("setDefaultVoiceSubId", Manifest.permission.MODIFY_PHONE_STATE); 3206 3207 if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { 3208 throw new RuntimeException("setDefaultVoiceSubId called with DEFAULT_SUB_ID"); 3209 } 3210 3211 enforceTelephonyFeatureWithException(getCurrentPackageName(), "setDefaultVoiceSubId"); 3212 3213 final long token = Binder.clearCallingIdentity(); 3214 try { 3215 if (mDefaultVoiceSubId.set(subId)) { 3216 broadcastSubId(TelephonyIntents.ACTION_DEFAULT_VOICE_SUBSCRIPTION_CHANGED, 3217 subId); 3218 3219 PhoneAccountHandle newHandle = subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID 3220 ? null : mTelephonyManager.getPhoneAccountHandleForSubscriptionId(subId); 3221 3222 TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class); 3223 if (telecomManager != null) { 3224 telecomManager.setUserSelectedOutgoingPhoneAccount(newHandle); 3225 } 3226 3227 updateDefaultSubId(); 3228 } 3229 3230 } finally { 3231 Binder.restoreCallingIdentity(token); 3232 } 3233 } 3234 3235 /** 3236 * @return The default subscription id for SMS. 3237 * @deprecated Use {@link #getDefaultSmsSubIdAsUser}. 3238 */ 3239 @Override getDefaultSmsSubId()3240 public int getDefaultSmsSubId() { 3241 return getDefaultSmsSubIdAsUser(BINDER_WRAPPER.getCallingUserHandle().getIdentifier()); 3242 } 3243 3244 /** 3245 * Get the default sms subscription id associated with the user. When a subscription is 3246 * associated with personal profile or work profile, the default sms subscription id will be 3247 * always the subscription it is associated with. 3248 * 3249 * @param userId The given user Id to check. 3250 * @return The default voice id. 3251 */ 3252 @Override getDefaultSmsSubIdAsUser(@serIdInt int userId)3253 public int getDefaultSmsSubIdAsUser(@UserIdInt int userId) { 3254 return getDefaultAsUser(userId, mDefaultSmsSubId.get()); 3255 } 3256 3257 /** 3258 * Set the default SMS subscription id. 3259 * 3260 * @param subId The default SMS subscription id. 3261 * 3262 * @throws SecurityException if callers do not hold the required permission. 3263 */ 3264 @Override 3265 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDefaultSmsSubId(int subId)3266 public void setDefaultSmsSubId(int subId) { 3267 enforcePermissions("setDefaultSmsSubId", Manifest.permission.MODIFY_PHONE_STATE); 3268 3269 if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { 3270 throw new RuntimeException("setDefaultSmsSubId called with DEFAULT_SUB_ID"); 3271 } 3272 3273 enforceTelephonyFeatureWithException(getCurrentPackageName(), "setDefaultSmsSubId"); 3274 3275 final long token = Binder.clearCallingIdentity(); 3276 try { 3277 if (mDefaultSmsSubId.set(subId)) { 3278 broadcastSubId(SubscriptionManager.ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED, 3279 subId); 3280 } 3281 3282 } finally { 3283 Binder.restoreCallingIdentity(token); 3284 } 3285 } 3286 3287 /** 3288 * Broadcast a sub Id with the given action. 3289 * @param action The intent action. 3290 * @param newSubId The sub Id to broadcast. 3291 */ broadcastSubId(@onNull String action, int newSubId)3292 private void broadcastSubId(@NonNull String action, int newSubId) { 3293 Intent intent = new Intent(action); 3294 intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); 3295 SubscriptionManager.putSubscriptionIdExtra(intent, newSubId); 3296 mContext.sendBroadcastAsUser(intent, UserHandle.ALL); 3297 log("broadcastSubId action: " + action + " subId= " + newSubId); 3298 } 3299 3300 /** 3301 * Get the active subscription id list. 3302 * 3303 * @param visibleOnly {@code true} if only includes user visible subscription's sub id. 3304 * 3305 * @return List of the active subscription id. 3306 * 3307 * @throws SecurityException if callers do not hold the required permission. 3308 */ 3309 @Override 3310 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getActiveSubIdList(boolean visibleOnly)3311 public int[] getActiveSubIdList(boolean visibleOnly) { 3312 enforcePermissions("getActiveSubIdList", Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 3313 3314 enforceTelephonyFeatureWithException(getCurrentPackageName(), "getActiveSubIdList"); 3315 3316 // UserHandle.ALL because this API is exposed as system API. 3317 return getActiveSubIdListAsUser(visibleOnly, UserHandle.ALL); 3318 } 3319 3320 /** 3321 * Get the active subscription id list as user. 3322 * Must be used before clear Binder identity. 3323 * 3324 * @param visibleOnly {@code true} if only includes user visible subscription's sub id. 3325 * @param user If {@code null}, uses the calling user handle to judge which subscriptions are 3326 * accessible to the caller. 3327 * @return List of the active subscription id. 3328 */ getActiveSubIdListAsUser(boolean visibleOnly, @NonNull final UserHandle user)3329 private int[] getActiveSubIdListAsUser(boolean visibleOnly, @NonNull final UserHandle user) { 3330 return mSlotIndexToSubId.values().stream() 3331 .filter(subId -> { 3332 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 3333 .getSubscriptionInfoInternal(subId); 3334 return subInfo != null && (!visibleOnly || subInfo.isVisible()) 3335 && isSubscriptionAssociatedWithUserInternal( 3336 subInfo, user.getIdentifier()); 3337 }) 3338 .mapToInt(x -> x) 3339 .toArray(); 3340 } 3341 3342 /** 3343 * Set a field in the subscription database. Note not all fields are supported. 3344 * 3345 * @param subId Subscription Id of Subscription. 3346 * @param columnName Column name in the database. Note not all fields are supported. 3347 * @param value Value to store in the database. 3348 * 3349 * @throws IllegalArgumentException if {@code subscriptionId} is invalid, or the field is not 3350 * exposed. 3351 * @throws SecurityException if callers do not hold the required permission. 3352 * 3353 * @see #getSubscriptionProperty(int, String, String, String) 3354 * @see SimInfo for all the columns. 3355 */ 3356 @Override 3357 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setSubscriptionProperty(int subId, @NonNull String columnName, @NonNull String value)3358 public void setSubscriptionProperty(int subId, @NonNull String columnName, 3359 @NonNull String value) { 3360 enforcePermissions("setSubscriptionProperty", Manifest.permission.MODIFY_PHONE_STATE); 3361 3362 final long token = Binder.clearCallingIdentity(); 3363 try { 3364 logl("setSubscriptionProperty: subId=" + subId + ", columnName=" + columnName 3365 + ", value=" + value + ", calling package=" + getCallingPackage()); 3366 3367 if (!SimInfo.getAllColumns().contains(columnName)) { 3368 throw new IllegalArgumentException("Invalid column name " + columnName); 3369 } 3370 3371 // Check if the columns are allowed to be accessed through the generic 3372 // getSubscriptionProperty method. 3373 if (!DIRECT_ACCESS_SUBSCRIPTION_COLUMNS.contains(columnName)) { 3374 throw new SecurityException("Column " + columnName + " is not allowed be directly " 3375 + "accessed through setSubscriptionProperty."); 3376 } 3377 3378 mSubscriptionDatabaseManager.setSubscriptionProperty(subId, columnName, value); 3379 } finally { 3380 Binder.restoreCallingIdentity(token); 3381 } 3382 } 3383 3384 /** 3385 * Get specific field in string format from the subscription info database. 3386 * 3387 * @param subId Subscription id of the subscription. 3388 * @param columnName Column name in subscription database. 3389 * 3390 * @return Value in string format associated with {@code subscriptionId} and {@code columnName} 3391 * from the database. {@code null} if the {@code subscriptionId} is invalid (for backward 3392 * compatible). 3393 * 3394 * @throws IllegalArgumentException if the field is not exposed. 3395 * @throws SecurityException if callers do not hold the required permission. 3396 * 3397 * @see SimInfo for all the columns. 3398 */ 3399 @Override 3400 @Nullable 3401 @RequiresPermission(anyOf = { 3402 Manifest.permission.READ_PHONE_STATE, 3403 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 3404 "carrier privileges", 3405 }) getSubscriptionProperty(int subId, @NonNull String columnName, @NonNull String callingPackage, @Nullable String callingFeatureId)3406 public String getSubscriptionProperty(int subId, @NonNull String columnName, 3407 @NonNull String callingPackage, @Nullable String callingFeatureId) { 3408 Objects.requireNonNull(columnName); 3409 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId, 3410 callingPackage, callingFeatureId, 3411 "getSubscriptionProperty")) { 3412 throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or " 3413 + "carrier privilege"); 3414 } 3415 3416 if (!SimInfo.getAllColumns().contains(columnName)) { 3417 throw new IllegalArgumentException("Invalid column name " + columnName); 3418 } 3419 3420 // Check if the columns are allowed to be accessed through the generic 3421 // getSubscriptionProperty method. 3422 if (!DIRECT_ACCESS_SUBSCRIPTION_COLUMNS.contains(columnName)) { 3423 throw new SecurityException("Column " + columnName + " is not allowed be directly " 3424 + "accessed through getSubscriptionProperty."); 3425 } 3426 3427 enforceTelephonyFeatureWithException(callingPackage, "getSubscriptionProperty"); 3428 3429 final long token = Binder.clearCallingIdentity(); 3430 try { 3431 Object value = mSubscriptionDatabaseManager.getSubscriptionProperty(subId, columnName); 3432 // The raw types of subscription database should only have 3 different types. 3433 if (value instanceof Integer) { 3434 return String.valueOf(value); 3435 } else if (value instanceof String) { 3436 return (String) value; 3437 } else if (value instanceof byte[]) { 3438 return Base64.encodeToString((byte[]) value, Base64.DEFAULT); 3439 } else { 3440 // This should not happen unless SubscriptionDatabaseManager.getSubscriptionProperty 3441 // did not implement correctly. 3442 throw new RuntimeException("Unexpected type " + value.getClass().getTypeName() 3443 + " was returned from SubscriptionDatabaseManager for column " 3444 + columnName); 3445 } 3446 } catch (IllegalArgumentException e) { 3447 loge("getSubscriptionProperty: Invalid subId " + subId + ", columnName=" + columnName); 3448 return null; 3449 } finally { 3450 Binder.restoreCallingIdentity(token); 3451 } 3452 } 3453 3454 /** 3455 * Check if a subscription is active. 3456 * 3457 * @param subId The subscription id to check. 3458 * 3459 * @return {@code true} if the subscription is active. 3460 * 3461 * @throws IllegalArgumentException if the provided slot index is invalid. 3462 * @throws SecurityException if callers do not hold the required permission. 3463 */ 3464 @Override 3465 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) isSubscriptionEnabled(int subId)3466 public boolean isSubscriptionEnabled(int subId) { 3467 enforcePermissions("isSubscriptionEnabled", 3468 Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 3469 if (!SubscriptionManager.isValidSubscriptionId(subId)) { 3470 throw new IllegalArgumentException("Invalid subscription id " + subId); 3471 } 3472 3473 enforceTelephonyFeatureWithException(getCurrentPackageName(), "isSubscriptionEnabled"); 3474 3475 final long identity = Binder.clearCallingIdentity(); 3476 try { 3477 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 3478 .getSubscriptionInfoInternal(subId); 3479 return subInfo != null && subInfo.isActive(); 3480 } finally { 3481 Binder.restoreCallingIdentity(identity); 3482 } 3483 } 3484 3485 /** 3486 * Get the active subscription id by logical SIM slot index. 3487 * 3488 * @param slotIndex The logical SIM slot index. 3489 * @return The active subscription id. 3490 * 3491 * @throws IllegalArgumentException if the provided slot index is invalid. 3492 * @throws SecurityException if callers do not hold the required permission. 3493 */ 3494 @Override 3495 @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) getEnabledSubscriptionId(int slotIndex)3496 public int getEnabledSubscriptionId(int slotIndex) { 3497 enforcePermissions("getEnabledSubscriptionId", 3498 Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 3499 3500 if (!SubscriptionManager.isValidSlotIndex(slotIndex)) { 3501 throw new IllegalArgumentException("Invalid slot index " + slotIndex); 3502 } 3503 3504 enforceTelephonyFeatureWithException(getCurrentPackageName(), "getEnabledSubscriptionId"); 3505 3506 final long identity = Binder.clearCallingIdentity(); 3507 try { 3508 return mSubscriptionDatabaseManager.getAllSubscriptions().stream() 3509 .filter(subInfo -> subInfo.isActive() && subInfo.getSimSlotIndex() == slotIndex) 3510 .mapToInt(SubscriptionInfoInternal::getSubscriptionId) 3511 .findFirst() 3512 .orElse(SubscriptionManager.INVALID_SUBSCRIPTION_ID); 3513 } finally { 3514 Binder.restoreCallingIdentity(identity); 3515 } 3516 } 3517 3518 /** 3519 * Check if a subscription is active. 3520 * 3521 * @param subId The subscription id. 3522 * @param callingPackage The package making the call. 3523 * @param callingFeatureId The feature in the package. 3524 * 3525 * @return {@code true} if the subscription is active. 3526 * 3527 * @throws SecurityException if callers do not hold the required permission. 3528 */ 3529 @Override 3530 @RequiresPermission(anyOf = { 3531 Manifest.permission.READ_PHONE_STATE, 3532 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 3533 "carrier privileges", 3534 }) isActiveSubId(int subId, @NonNull String callingPackage, @Nullable String callingFeatureId)3535 public boolean isActiveSubId(int subId, @NonNull String callingPackage, 3536 @Nullable String callingFeatureId) { 3537 if (!TelephonyPermissions.checkCallingOrSelfReadPhoneState(mContext, subId, callingPackage, 3538 callingFeatureId, "isActiveSubId")) { 3539 throw new SecurityException("Need READ_PHONE_STATE, READ_PRIVILEGED_PHONE_STATE, or " 3540 + "carrier privilege"); 3541 } 3542 3543 enforceTelephonyFeatureWithException(callingPackage, "isActiveSubId"); 3544 3545 final long identity = Binder.clearCallingIdentity(); 3546 try { 3547 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 3548 .getSubscriptionInfoInternal(subId); 3549 return subInfo != null && subInfo.isActive(); 3550 } finally { 3551 Binder.restoreCallingIdentity(identity); 3552 } 3553 } 3554 3555 /** 3556 * Get active data subscription id. Active data subscription refers to the subscription 3557 * currently chosen to provide cellular internet connection to the user. This may be 3558 * different from getDefaultDataSubscriptionId(). 3559 * 3560 * @return Active data subscription id if any is chosen, or 3561 * SubscriptionManager.INVALID_SUBSCRIPTION_ID if not. 3562 * 3563 * @see android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener 3564 */ 3565 @Override getActiveDataSubscriptionId()3566 public int getActiveDataSubscriptionId() { 3567 final long token = Binder.clearCallingIdentity(); 3568 try { 3569 PhoneSwitcher phoneSwitcher = PhoneSwitcher.getInstance(); 3570 if (phoneSwitcher != null) { 3571 int activeDataSubId = phoneSwitcher.getActiveDataSubId(); 3572 if (SubscriptionManager.isUsableSubscriptionId(activeDataSubId)) { 3573 return activeDataSubId; 3574 } 3575 } 3576 // If phone switcher isn't ready, or active data sub id is not available, use default 3577 // sub id from settings. 3578 return getDefaultDataSubId(); 3579 } finally { 3580 Binder.restoreCallingIdentity(token); 3581 } 3582 } 3583 3584 /** 3585 * Whether it's supported to disable / re-enable a subscription on a physical (non-euicc) SIM. 3586 * 3587 * Physical SIM refers non-euicc, or aka non-programmable SIM. 3588 * 3589 * It provides whether a physical SIM card can be disabled without taking it out, which is done 3590 * via {@link SubscriptionManager#setSubscriptionEnabled(int, boolean)} API. 3591 * 3592 * @return whether can disable subscriptions on physical SIMs. 3593 * 3594 * @throws SecurityException if callers do not hold the required permission. 3595 */ 3596 @Override 3597 @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) canDisablePhysicalSubscription()3598 public boolean canDisablePhysicalSubscription() { 3599 enforcePermissions("canDisablePhysicalSubscription", 3600 Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 3601 3602 enforceTelephonyFeatureWithException(getCurrentPackageName(), 3603 "canDisablePhysicalSubscription"); 3604 3605 final long identity = Binder.clearCallingIdentity(); 3606 try { 3607 Phone phone = PhoneFactory.getDefaultPhone(); 3608 return phone != null && phone.canDisablePhysicalSubscription(); 3609 } finally { 3610 Binder.restoreCallingIdentity(identity); 3611 } 3612 } 3613 3614 /** 3615 * Set uicc applications being enabled or disabled. 3616 * 3617 * The value will be remembered on the subscription and will be applied whenever it's present. 3618 * If the subscription in currently present, it will also apply the setting to modem 3619 * immediately (the setting in the modem will not change until the modem receives and responds 3620 * to the request, but typically this should only take a few seconds. The user visible setting 3621 * available from {@link SubscriptionInfo#areUiccApplicationsEnabled()} will be updated 3622 * immediately.) 3623 * 3624 * @param enabled whether uicc applications are enabled or disabled. 3625 * @param subId which subscription to operate on. 3626 * 3627 * @throws IllegalArgumentException if the subscription does not exist. 3628 * @throws SecurityException if callers do not hold the required permission. 3629 */ 3630 @Override 3631 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setUiccApplicationsEnabled(boolean enabled, int subId)3632 public void setUiccApplicationsEnabled(boolean enabled, int subId) { 3633 enforcePermissions("setUiccApplicationsEnabled", 3634 Manifest.permission.MODIFY_PHONE_STATE); 3635 logl("setUiccApplicationsEnabled: subId=" + subId + ", enabled=" + enabled 3636 + ", calling package=" + getCallingPackage()); 3637 3638 enforceTelephonyFeatureWithException(getCurrentPackageName(), 3639 "setUiccApplicationsEnabled"); 3640 3641 final long identity = Binder.clearCallingIdentity(); 3642 try { 3643 3644 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 3645 .getSubscriptionInfoInternal(subId); 3646 if (subInfo == null) { 3647 throw new IllegalArgumentException("setUiccApplicationsEnabled: Subscription " 3648 + "doesn't exist. subId=" + subId); 3649 } 3650 3651 if (subInfo.areUiccApplicationsEnabled() != enabled) { 3652 mSubscriptionDatabaseManager.setUiccApplicationsEnabled(subId, enabled); 3653 mSubscriptionManagerServiceCallbacks.forEach( 3654 callback -> callback.invokeFromExecutor( 3655 () -> callback.onUiccApplicationsEnabledChanged(subId))); 3656 } 3657 } finally { 3658 Binder.restoreCallingIdentity(identity); 3659 } 3660 } 3661 3662 /** 3663 * Set the device to device status sharing user preference for a subscription ID. The setting 3664 * app uses this method to indicate with whom they wish to share device to device status 3665 * information. 3666 * 3667 * @param sharing the status sharing preference. 3668 * @param subId the unique Subscription ID in database. 3669 * 3670 * @return the number of records updated. 3671 * 3672 * @throws IllegalArgumentException if the subscription does not exist, or the sharing 3673 * preference is invalid. 3674 * @throws SecurityException if callers do not hold the required permission. 3675 */ 3676 @Override 3677 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDeviceToDeviceStatusSharing(@eviceToDeviceStatusSharingPreference int sharing, int subId)3678 public int setDeviceToDeviceStatusSharing(@DeviceToDeviceStatusSharingPreference int sharing, 3679 int subId) { 3680 enforcePermissions("setDeviceToDeviceStatusSharing", 3681 Manifest.permission.MODIFY_PHONE_STATE); 3682 3683 enforceTelephonyFeatureWithException(getCurrentPackageName(), 3684 "setDeviceToDeviceStatusSharing"); 3685 3686 final long identity = Binder.clearCallingIdentity(); 3687 try { 3688 if (sharing < SubscriptionManager.D2D_SHARING_DISABLED 3689 || sharing > SubscriptionManager.D2D_SHARING_ALL) { 3690 throw new IllegalArgumentException("invalid sharing " + sharing); 3691 } 3692 3693 mSubscriptionDatabaseManager.setDeviceToDeviceStatusSharingPreference(subId, sharing); 3694 return 1; 3695 } finally { 3696 Binder.restoreCallingIdentity(identity); 3697 } 3698 } 3699 3700 /** 3701 * Set the list of contacts that allow device to device status sharing for a subscription ID. 3702 * The setting app uses this method to indicate with whom they wish to share device to device 3703 * status information. 3704 * 3705 * @param contacts The list of contacts that allow device to device status sharing 3706 * @param subId The unique Subscription ID in database. 3707 * 3708 * @throws IllegalArgumentException if {@code subId} is invalid. 3709 * @throws NullPointerException if {@code contacts} is {@code null}. 3710 * @throws SecurityException if callers do not hold the required permission. 3711 */ 3712 @Override 3713 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) setDeviceToDeviceStatusSharingContacts(@onNull String contacts, int subId)3714 public int setDeviceToDeviceStatusSharingContacts(@NonNull String contacts, int subId) { 3715 enforcePermissions("setDeviceToDeviceStatusSharingContacts", 3716 Manifest.permission.MODIFY_PHONE_STATE); 3717 3718 enforceTelephonyFeatureWithException(getCurrentPackageName(), 3719 "setDeviceToDeviceStatusSharingContacts"); 3720 3721 final long identity = Binder.clearCallingIdentity(); 3722 try { 3723 Objects.requireNonNull(contacts, "contacts"); 3724 mSubscriptionDatabaseManager.setDeviceToDeviceStatusSharingContacts(subId, contacts); 3725 return 1; 3726 } finally { 3727 Binder.restoreCallingIdentity(identity); 3728 } 3729 } 3730 3731 /** 3732 * Returns the phone number for the given {@code subscriptionId} and {@code source}, 3733 * or an empty string if not available. 3734 * 3735 * <p>General apps that need to know the phone number should use 3736 * {@link SubscriptionManager#getPhoneNumber(int)} instead. This API may be suitable specific 3737 * apps that needs to know the phone number from a specific source. For example, a carrier app 3738 * needs to know exactly what's on {@link SubscriptionManager#PHONE_NUMBER_SOURCE_UICC UICC} and 3739 * decide if the previously set phone number of source 3740 * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_CARRIER carrier} should be updated. 3741 * 3742 * <p>The API provides no guarantees of what format the number is in: the format can vary 3743 * depending on the {@code source} and the network etc. Programmatic parsing should be done 3744 * cautiously, for example, after formatting the number to a consistent format with 3745 * {@link android.telephony.PhoneNumberUtils#formatNumberToE164(String, String)}. 3746 * 3747 * <p>Note the assumption is that one subscription (which usually means one SIM) has 3748 * only one phone number. The multiple sources backup each other so hopefully at least one 3749 * is available. For example, for a carrier that doesn't typically set phone numbers 3750 * on {@link SubscriptionManager#PHONE_NUMBER_SOURCE_UICC UICC}, the source 3751 * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_IMS IMS} may provide one. Or, a carrier may 3752 * decide to provide the phone number via source 3753 * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_CARRIER carrier} if neither source UICC nor 3754 * IMS is available. 3755 * 3756 * <p>The availability and correctness of the phone number depends on the underlying source 3757 * and the network etc. Additional verification is needed to use this number for 3758 * security-related or other sensitive scenarios. 3759 * 3760 * @param subId The subscription ID. 3761 * @param source The source of the phone number. 3762 * @param callingPackage The package making the call. 3763 * @param callingFeatureId The feature in the package. 3764 * 3765 * @return The phone number, or an empty string if not available. 3766 * 3767 * @throws IllegalArgumentException if {@code source} is invalid. 3768 * @throws SecurityException if the caller doesn't have permissions required. 3769 * 3770 * @see SubscriptionManager#PHONE_NUMBER_SOURCE_UICC 3771 * @see SubscriptionManager#PHONE_NUMBER_SOURCE_CARRIER 3772 * @see SubscriptionManager#PHONE_NUMBER_SOURCE_IMS 3773 */ 3774 @Override 3775 @NonNull 3776 @RequiresPermission(anyOf = { 3777 Manifest.permission.READ_PHONE_NUMBERS, 3778 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 3779 "carrier privileges", 3780 }) getPhoneNumber(int subId, @PhoneNumberSource int source, @NonNull String callingPackage, @Nullable String callingFeatureId )3781 public String getPhoneNumber(int subId, @PhoneNumberSource int source, 3782 @NonNull String callingPackage, @Nullable String callingFeatureId /* unused */) { 3783 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges( 3784 mContext, subId, Binder.getCallingUid(), "getPhoneNumber", 3785 Manifest.permission.READ_PHONE_NUMBERS, 3786 Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 3787 enforceTelephonyFeatureWithException(callingPackage, "getPhoneNumber"); 3788 3789 if (mFeatureFlags.saferGetPhoneNumber()) { 3790 checkPhoneNumberSource(source); 3791 subId = checkAndGetSubId(subId); 3792 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return ""; 3793 3794 final long identity = Binder.clearCallingIdentity(); 3795 try { 3796 return getPhoneNumberFromSourceInternal(subId, source); 3797 } finally { 3798 Binder.restoreCallingIdentity(identity); 3799 } 3800 } else { 3801 final long identity = Binder.clearCallingIdentity(); 3802 try { 3803 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 3804 .getSubscriptionInfoInternal(subId); 3805 3806 if (subInfo == null) { 3807 loge("Invalid sub id " + subId + ", callingPackage=" + callingPackage); 3808 return ""; 3809 } 3810 3811 switch(source) { 3812 case SubscriptionManager.PHONE_NUMBER_SOURCE_UICC: 3813 Phone phone = PhoneFactory.getPhone(getSlotIndex(subId)); 3814 if (phone != null) { 3815 return TextUtils.emptyIfNull(phone.getLine1Number()); 3816 } else { 3817 return subInfo.getNumber(); 3818 } 3819 case SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER: 3820 return subInfo.getNumberFromCarrier(); 3821 case SubscriptionManager.PHONE_NUMBER_SOURCE_IMS: 3822 return subInfo.getNumberFromIms(); 3823 default: 3824 throw new IllegalArgumentException("Invalid number source " + source); 3825 } 3826 } finally { 3827 Binder.restoreCallingIdentity(identity); 3828 } 3829 } 3830 } 3831 3832 /** 3833 * Get a resolved subId based on what the user passed in. 3834 * 3835 * Only use this before clearing the calling binder. Used for compatibility (only). 3836 * Do not use this behavior for new methods. 3837 * 3838 * @param subId the subId passed in by the user. 3839 */ checkAndGetSubId(int subId)3840 private int checkAndGetSubId(int subId) { 3841 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 3842 // for historical reasons, INVALID_SUB_ID fails gracefully 3843 return subId; 3844 } else if (subId == SubscriptionManager.DEFAULT_SUBSCRIPTION_ID) { 3845 return getDefaultSubId(); 3846 } else if (!SubscriptionManager.isValidSubscriptionId(subId)) { 3847 throw new IllegalArgumentException("Invalid SubId=" + subId); 3848 } else { 3849 return subId; 3850 } 3851 } 3852 checkPhoneNumberSource(int source)3853 private void checkPhoneNumberSource(int source) { 3854 if (source == SubscriptionManager.PHONE_NUMBER_SOURCE_UICC 3855 || source == SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER 3856 || source == SubscriptionManager.PHONE_NUMBER_SOURCE_IMS) { 3857 return; 3858 } 3859 3860 throw new IllegalArgumentException("Invalid number source " + source); 3861 } 3862 getPhoneNumberFromSourceInternal( int subId, @PhoneNumberSource int source)3863 private @NonNull String getPhoneNumberFromSourceInternal( 3864 int subId, 3865 @PhoneNumberSource int source) { 3866 3867 final SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 3868 .getSubscriptionInfoInternal(subId); 3869 3870 if (subInfo == null) { 3871 loge("No SubscriptionInfo found for subId=" + subId); 3872 return ""; 3873 } 3874 3875 switch(source) { 3876 case SubscriptionManager.PHONE_NUMBER_SOURCE_UICC: 3877 final Phone phone = PhoneFactory.getPhone(getSlotIndex(subId)); 3878 if (phone != null) { 3879 return TextUtils.emptyIfNull(phone.getLine1Number()); 3880 } else { 3881 return subInfo.getNumber(); 3882 } 3883 case SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER: 3884 return subInfo.getNumberFromCarrier(); 3885 case SubscriptionManager.PHONE_NUMBER_SOURCE_IMS: 3886 return subInfo.getNumberFromIms(); 3887 default: 3888 loge("No SubscriptionInfo found for subId=" + subId); 3889 return ""; 3890 } 3891 } 3892 3893 /** 3894 * Get phone number from first available source. The order would be 3895 * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_CARRIER}, 3896 * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_UICC}, then 3897 * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_IMS}. 3898 * 3899 * @param subId The subscription ID. 3900 * @param callingPackage The package making the call. 3901 * @param callingFeatureId The feature in the package. 3902 * 3903 * @return The phone number from the first available source. 3904 * 3905 * @throws IllegalArgumentException if {@code subId} is invalid. 3906 * @throws SecurityException if callers do not hold the required permission. 3907 */ 3908 @Override 3909 @NonNull 3910 @RequiresPermission(anyOf = { 3911 Manifest.permission.READ_PHONE_NUMBERS, 3912 Manifest.permission.READ_PRIVILEGED_PHONE_STATE, 3913 "carrier privileges", 3914 }) getPhoneNumberFromFirstAvailableSource(int subId, @NonNull String callingPackage, @Nullable String callingFeatureId)3915 public String getPhoneNumberFromFirstAvailableSource(int subId, 3916 @NonNull String callingPackage, @Nullable String callingFeatureId) { 3917 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges( 3918 mContext, subId, Binder.getCallingUid(), "getPhoneNumberFromFirstAvailableSource", 3919 Manifest.permission.READ_PHONE_NUMBERS, 3920 Manifest.permission.READ_PRIVILEGED_PHONE_STATE); 3921 3922 enforceTelephonyFeatureWithException(callingPackage, 3923 "getPhoneNumberFromFirstAvailableSource"); 3924 3925 if (mFeatureFlags.saferGetPhoneNumber()) { 3926 subId = checkAndGetSubId(subId); 3927 if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) return ""; 3928 3929 final long identity = Binder.clearCallingIdentity(); 3930 try { 3931 String number; 3932 number = getPhoneNumberFromSourceInternal( 3933 subId, 3934 SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER); 3935 if (!TextUtils.isEmpty(number)) return number; 3936 3937 number = getPhoneNumberFromSourceInternal( 3938 subId, 3939 SubscriptionManager.PHONE_NUMBER_SOURCE_UICC); 3940 if (!TextUtils.isEmpty(number)) return number; 3941 3942 number = getPhoneNumberFromSourceInternal( 3943 subId, 3944 SubscriptionManager.PHONE_NUMBER_SOURCE_IMS); 3945 return TextUtils.emptyIfNull(number); 3946 } finally { 3947 Binder.restoreCallingIdentity(identity); 3948 } 3949 } else { 3950 String numberFromCarrier = getPhoneNumber(subId, 3951 SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER, callingPackage, 3952 callingFeatureId); 3953 if (!TextUtils.isEmpty(numberFromCarrier)) { 3954 return numberFromCarrier; 3955 } 3956 String numberFromUicc = getPhoneNumber( 3957 subId, SubscriptionManager.PHONE_NUMBER_SOURCE_UICC, callingPackage, 3958 callingFeatureId); 3959 if (!TextUtils.isEmpty(numberFromUicc)) { 3960 return numberFromUicc; 3961 } 3962 String numberFromIms = getPhoneNumber( 3963 subId, SubscriptionManager.PHONE_NUMBER_SOURCE_IMS, callingPackage, 3964 callingFeatureId); 3965 if (!TextUtils.isEmpty(numberFromIms)) { 3966 return numberFromIms; 3967 } 3968 return ""; 3969 } 3970 } 3971 3972 /** 3973 * Set the phone number of the subscription. 3974 * 3975 * @param subId The subscription id. 3976 * @param source The phone number source. 3977 * @param number The phone number. 3978 * @param callingPackage The package making the call. 3979 * @param callingFeatureId The feature in the package. 3980 * 3981 * @throws IllegalArgumentException {@code subId} is invalid, or {@code source} is not 3982 * {@link SubscriptionManager#PHONE_NUMBER_SOURCE_CARRIER}. 3983 * @throws NullPointerException if {@code number} is {@code null}. 3984 */ 3985 @Override 3986 @RequiresPermission("carrier privileges") setPhoneNumber(int subId, @PhoneNumberSource int source, @NonNull String number, @NonNull String callingPackage, @Nullable String callingFeatureId)3987 public void setPhoneNumber(int subId, @PhoneNumberSource int source, @NonNull String number, 3988 @NonNull String callingPackage, @Nullable String callingFeatureId) { 3989 if (!TelephonyPermissions.checkCarrierPrivilegeForSubId(mContext, subId)) { 3990 throw new SecurityException("setPhoneNumber for CARRIER needs carrier privilege."); 3991 } 3992 3993 if (source != SubscriptionManager.PHONE_NUMBER_SOURCE_CARRIER) { 3994 throw new IllegalArgumentException("setPhoneNumber doesn't accept source " 3995 + SubscriptionManager.phoneNumberSourceToString(source)); 3996 } 3997 3998 enforceTelephonyFeatureWithException(callingPackage, "setPhoneNumber"); 3999 4000 Objects.requireNonNull(number, "number"); 4001 4002 final long identity = Binder.clearCallingIdentity(); 4003 try { 4004 mSubscriptionDatabaseManager.setNumberFromCarrier(subId, number); 4005 } finally { 4006 Binder.restoreCallingIdentity(identity); 4007 } 4008 } 4009 4010 /** 4011 * Set the Usage Setting for this subscription. 4012 * 4013 * @param usageSetting the usage setting for this subscription 4014 * @param subId the unique SubscriptionInfo index in database 4015 * @param callingPackage The package making the IPC. 4016 * 4017 * @throws IllegalArgumentException if the subscription does not exist, or {@code usageSetting} 4018 * is invalid. 4019 * @throws SecurityException if doesn't have MODIFY_PHONE_STATE or Carrier Privileges 4020 */ 4021 @Override 4022 @RequiresPermission(anyOf = { 4023 Manifest.permission.MODIFY_PHONE_STATE, 4024 "carrier privileges", 4025 }) setUsageSetting(@sageSetting int usageSetting, int subId, @NonNull String callingPackage)4026 public int setUsageSetting(@UsageSetting int usageSetting, int subId, 4027 @NonNull String callingPackage) { 4028 TelephonyPermissions.enforceAnyPermissionGrantedOrCarrierPrivileges( 4029 mContext, Binder.getCallingUid(), subId, true, "setUsageSetting", 4030 Manifest.permission.MODIFY_PHONE_STATE); 4031 4032 if (usageSetting < SubscriptionManager.USAGE_SETTING_DEFAULT 4033 || usageSetting > SubscriptionManager.USAGE_SETTING_DATA_CENTRIC) { 4034 throw new IllegalArgumentException("setUsageSetting: Invalid usage setting: " 4035 + usageSetting); 4036 } 4037 4038 final long token = Binder.clearCallingIdentity(); 4039 try { 4040 mSubscriptionDatabaseManager.setUsageSetting(subId, usageSetting); 4041 return 1; 4042 } finally { 4043 Binder.restoreCallingIdentity(token); 4044 } 4045 } 4046 4047 /** 4048 * Set UserHandle for this subscription. 4049 * 4050 * @param userHandle the userHandle associated with the subscription 4051 * Pass {@code null} user handle to clear the association 4052 * @param subId the unique SubscriptionInfo index in database 4053 * @return the number of records updated. 4054 * 4055 * @throws SecurityException if callers do not hold the required permission. 4056 * @throws IllegalArgumentException if {@code subId} is invalid. 4057 */ 4058 @Override 4059 @RequiresPermission(Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION) setSubscriptionUserHandle(@ullable UserHandle userHandle, int subId)4060 public int setSubscriptionUserHandle(@Nullable UserHandle userHandle, int subId) { 4061 enforcePermissions("setSubscriptionUserHandle", 4062 Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION); 4063 4064 if (userHandle == null) { 4065 userHandle = UserHandle.of(UserHandle.USER_NULL); 4066 } 4067 4068 long token = Binder.clearCallingIdentity(); 4069 try { 4070 // This can throw IllegalArgumentException if the subscription does not exist. 4071 mSubscriptionDatabaseManager.setUserId(subId, userHandle.getIdentifier()); 4072 return 1; 4073 } finally { 4074 Binder.restoreCallingIdentity(token); 4075 } 4076 } 4077 4078 /** 4079 * Get UserHandle of this subscription. 4080 * 4081 * @param subId the unique SubscriptionInfo index in database 4082 * @return userHandle associated with this subscription 4083 * or {@code null} if subscription is not associated with any user 4084 * or {code null} if subscripiton is not available on the device. 4085 * 4086 * @throws SecurityException if doesn't have required permission. 4087 */ 4088 @Override 4089 @Nullable 4090 @RequiresPermission(Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION) getSubscriptionUserHandle(int subId)4091 public UserHandle getSubscriptionUserHandle(int subId) { 4092 enforcePermissions("getSubscriptionUserHandle", 4093 Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION); 4094 long token = Binder.clearCallingIdentity(); 4095 try { 4096 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 4097 .getSubscriptionInfoInternal(subId); 4098 if (subInfo == null) { 4099 return null; 4100 } 4101 4102 UserHandle userHandle = UserHandle.of(subInfo.getUserId()); 4103 if (userHandle.getIdentifier() == UserHandle.USER_NULL) { 4104 return null; 4105 } 4106 return userHandle; 4107 } finally { 4108 Binder.restoreCallingIdentity(token); 4109 } 4110 } 4111 4112 /** 4113 * Returns whether the given subscription is associated with the calling user. 4114 * 4115 * @param subscriptionId the subscription ID of the subscription 4116 * @return {@code true} if the subscription is associated with the user that the calling process 4117 * is running in; {@code false} otherwise. 4118 * 4119 * @throws IllegalArgumentException if subscription doesn't exist. 4120 * @throws SecurityException if the caller doesn't have permissions required. 4121 */ 4122 @Override isSubscriptionAssociatedWithCallingUser(int subscriptionId)4123 public boolean isSubscriptionAssociatedWithCallingUser(int subscriptionId) { 4124 enforcePermissions("isSubscriptionAssociatedWithCallingUser", 4125 Manifest.permission.READ_PHONE_STATE); 4126 4127 UserHandle myUserHandle = UserHandle.of(UserHandle.getCallingUserId()); 4128 return mFeatureFlags.subscriptionUserAssociationQuery() 4129 && isSubscriptionAssociatedWithUserNoCheck(subscriptionId, myUserHandle); 4130 } 4131 4132 /** 4133 * Check if subscription and user are associated with each other. 4134 * 4135 * @param subscriptionId the subId of the subscription 4136 * @param userHandle user handle of the user 4137 * @return {@code true} if subscription is associated with user 4138 * else {@code false} if subscription is not associated with user. 4139 * 4140 * @throws SecurityException if the caller doesn't have permissions required. 4141 * @throws IllegalArgumentException if the subscription has no records on device. 4142 */ 4143 @Override isSubscriptionAssociatedWithUser(int subscriptionId, @NonNull UserHandle userHandle)4144 public boolean isSubscriptionAssociatedWithUser(int subscriptionId, 4145 @NonNull UserHandle userHandle) { 4146 enforcePermissions("isSubscriptionAssociatedWithUser", 4147 Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION); 4148 4149 return isSubscriptionAssociatedWithUserNoCheck(subscriptionId, userHandle); 4150 } 4151 isSubscriptionAssociatedWithUserNoCheck(int subscriptionId, @NonNull UserHandle userHandle)4152 private boolean isSubscriptionAssociatedWithUserNoCheck(int subscriptionId, 4153 @NonNull UserHandle userHandle) { 4154 SubscriptionInfoInternal subInfoInternal = mSubscriptionDatabaseManager 4155 .getSubscriptionInfoInternal(subscriptionId); 4156 // Throw IAE if no record of the sub's association state. 4157 if (subInfoInternal == null) { 4158 throw new IllegalArgumentException( 4159 "[isSubscriptionAssociatedWithUser]: Subscription doesn't exist: " 4160 + subscriptionId); 4161 } 4162 4163 if (mFeatureFlags.enforceSubscriptionUserFilter()) { 4164 return isSubscriptionAssociatedWithUserInternal( 4165 subInfoInternal, userHandle.getIdentifier()); 4166 } 4167 4168 long token = Binder.clearCallingIdentity(); 4169 try { 4170 // Get list of subscriptions associated with this user. 4171 List<SubscriptionInfo> associatedSubscriptionsList = 4172 getSubscriptionInfoListAssociatedWithUser(userHandle); 4173 // Return true if required subscription is present in associated subscriptions list. 4174 for (SubscriptionInfo subInfo: associatedSubscriptionsList) { 4175 if (subInfo.getSubscriptionId() == subscriptionId) { 4176 return true; 4177 } 4178 } 4179 return false; 4180 } finally { 4181 Binder.restoreCallingIdentity(token); 4182 } 4183 } 4184 4185 /** 4186 * @param subInfo The subscription info to check. 4187 * @param userId The caller user Id. 4188 * @return {@code true} if the given user Id is allowed to access to the given subscription. 4189 */ isSubscriptionAssociatedWithUserInternal( @onNull SubscriptionInfoInternal subInfo, @UserIdInt int userId)4190 private boolean isSubscriptionAssociatedWithUserInternal( 4191 @NonNull SubscriptionInfoInternal subInfo, @UserIdInt int userId) { 4192 if (!mFeatureFlags.enforceSubscriptionUserFilter() 4193 || !CompatChanges.isChangeEnabled(FILTER_ACCESSIBLE_SUBS_BY_USER, 4194 Binder.getCallingUid())) { 4195 return true; 4196 } 4197 // Can access the unassociated sub if the user doesn't have its own. 4198 return (subInfo.getUserId() == UserHandle.USER_NULL 4199 && mUserIdToAvailableSubs.get(userId) == null) 4200 || userId == subInfo.getUserId() 4201 || userId == UserHandle.USER_ALL; 4202 } 4203 4204 /** 4205 * Get list of subscriptions associated with user. 4206 * 4207 * If user handle is associated with some subscriptions, return subscriptionsAssociatedWithUser 4208 * else return all the subscriptions which are not associated with any user. 4209 * 4210 * @param userHandle user handle of the user 4211 * @return list of subscriptionInfo associated with the user. 4212 * 4213 * @throws SecurityException if the caller doesn't have permissions required. 4214 * 4215 */ 4216 @Override 4217 @NonNull getSubscriptionInfoListAssociatedWithUser( @onNull UserHandle userHandle)4218 public List<SubscriptionInfo> getSubscriptionInfoListAssociatedWithUser( 4219 @NonNull UserHandle userHandle) { 4220 enforcePermissions("getSubscriptionInfoListAssociatedWithUser", 4221 Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION); 4222 4223 if (mFeatureFlags.enforceSubscriptionUserFilter()) { 4224 return getSubscriptionInfoStreamAsUser(userHandle) 4225 .map(SubscriptionInfoInternal::toSubscriptionInfo) 4226 .collect(Collectors.toList()); 4227 } 4228 4229 long token = Binder.clearCallingIdentity(); 4230 try { 4231 List<SubscriptionInfoInternal> subInfoList = mSubscriptionDatabaseManager 4232 .getAllSubscriptions(); 4233 if (subInfoList.isEmpty()) { 4234 return new ArrayList<>(); 4235 } 4236 4237 List<SubscriptionInfo> subscriptionsAssociatedWithUser = new ArrayList<>(); 4238 List<SubscriptionInfo> subscriptionsWithNoAssociation = new ArrayList<>(); 4239 for (SubscriptionInfoInternal subInfo : subInfoList) { 4240 if (subInfo.getUserId() == userHandle.getIdentifier()) { 4241 // Store subscriptions whose user handle matches with required user handle. 4242 subscriptionsAssociatedWithUser.add(subInfo.toSubscriptionInfo()); 4243 } else if (subInfo.getUserId() == UserHandle.USER_NULL) { 4244 // Store subscriptions whose user handle is set to null. 4245 subscriptionsWithNoAssociation.add(subInfo.toSubscriptionInfo()); 4246 } 4247 } 4248 4249 UserManager userManager = mContext.getSystemService(UserManager.class); 4250 if ((userManager != null) 4251 && (userManager.isManagedProfile(userHandle.getIdentifier()))) { 4252 // For work profile, return subscriptions associated only with work profile even 4253 // if it's empty. 4254 return subscriptionsAssociatedWithUser; 4255 } 4256 4257 // For all other profiles, if subscriptionsAssociatedWithUser is empty return all 4258 // the subscriptionsWithNoAssociation. 4259 return subscriptionsAssociatedWithUser.isEmpty() 4260 ? subscriptionsWithNoAssociation : subscriptionsAssociatedWithUser; 4261 } finally { 4262 Binder.restoreCallingIdentity(token); 4263 } 4264 } 4265 4266 /** 4267 * Get subscriptions accessible to the caller user. 4268 * 4269 * @param user The user to check. 4270 * @return a stream of accessible internal subscriptions. 4271 */ 4272 @NonNull getSubscriptionInfoStreamAsUser( @onNull final UserHandle user)4273 private Stream<SubscriptionInfoInternal> getSubscriptionInfoStreamAsUser( 4274 @NonNull final UserHandle user) { 4275 return mSubscriptionDatabaseManager.getAllSubscriptions().stream() 4276 .filter(info -> isSubscriptionAssociatedWithUserInternal( 4277 info, user.getIdentifier())); 4278 } 4279 4280 /** 4281 * Called during setup wizard restore flow to attempt to restore the backed up sim-specific 4282 * configs to device for all existing SIMs in the subscription database {@link SimInfo}. 4283 * Internally, it will store the backup data in an internal file. This file will persist on 4284 * device for device's lifetime and will be used later on when a SIM is inserted to restore that 4285 * specific SIM's settings. End result is subscription database is modified to match any backed 4286 * up configs for the appropriate inserted SIMs. 4287 * 4288 * <p> 4289 * The {@link Uri} {@link SubscriptionManager#SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI} is 4290 * notified if any {@link SimInfo} entry is updated as the result of this method call. 4291 * 4292 * @param data with the sim specific configs to be backed up. 4293 */ 4294 @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) 4295 @Override restoreAllSimSpecificSettingsFromBackup(@onNull byte[] data)4296 public void restoreAllSimSpecificSettingsFromBackup(@NonNull byte[] data) { 4297 enforcePermissions("restoreAllSimSpecificSettingsFromBackup", 4298 Manifest.permission.MODIFY_PHONE_STATE); 4299 4300 enforceTelephonyFeatureWithException(getCurrentPackageName(), 4301 "restoreAllSimSpecificSettingsFromBackup"); 4302 4303 long token = Binder.clearCallingIdentity(); 4304 try { 4305 Bundle bundle = new Bundle(); 4306 bundle.putByteArray(SubscriptionManager.KEY_SIM_SPECIFIC_SETTINGS_DATA, data); 4307 logl("restoreAllSimSpecificSettingsFromBackup"); 4308 Bundle result = mContext.getContentResolver().call( 4309 SubscriptionManager.SIM_INFO_BACKUP_AND_RESTORE_CONTENT_URI, 4310 SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_METHOD_NAME, 4311 null, bundle); 4312 4313 if (result != null && result.getBoolean( 4314 SubscriptionManager.RESTORE_SIM_SPECIFIC_SETTINGS_DATABASE_UPDATED)) { 4315 logl("Sim specific settings changed the database."); 4316 mSubscriptionDatabaseManager.reloadDatabaseSync(); 4317 if (mFeatureFlags.backupAndRestoreForEnable2g()) { 4318 Arrays.stream(PhoneFactory.getPhones()) 4319 .forEach(Phone::loadAllowedNetworksFromSubscriptionDatabase); 4320 } 4321 } 4322 } finally { 4323 Binder.restoreCallingIdentity(token); 4324 } 4325 } 4326 4327 /** 4328 * Register the callback for receiving information from {@link SubscriptionManagerService}. 4329 * 4330 * @param callback The callback. 4331 */ registerCallback(@onNull SubscriptionManagerServiceCallback callback)4332 public void registerCallback(@NonNull SubscriptionManagerServiceCallback callback) { 4333 mSubscriptionManagerServiceCallbacks.add(callback); 4334 } 4335 4336 /** 4337 * Unregister the previously registered {@link SubscriptionManagerServiceCallback}. 4338 * 4339 * @param callback The callback to unregister. 4340 */ unregisterCallback(@onNull SubscriptionManagerServiceCallback callback)4341 public void unregisterCallback(@NonNull SubscriptionManagerServiceCallback callback) { 4342 mSubscriptionManagerServiceCallbacks.remove(callback); 4343 } 4344 4345 /** 4346 * Enforce callers have any of the provided permissions. 4347 * 4348 * @param message Message to include in the exception. 4349 * @param permissions The permissions to enforce. 4350 * 4351 * @throws SecurityException if the caller does not have any permissions. 4352 */ enforcePermissions(@ullable String message, @NonNull String ...permissions)4353 private void enforcePermissions(@Nullable String message, @NonNull String ...permissions) { 4354 if (!hasPermissions(permissions)) { 4355 throw new SecurityException( 4356 message + ". Does not have any of the following permissions. " 4357 + Arrays.toString(permissions)); 4358 } 4359 } 4360 4361 /** 4362 * Check have any of the permissions 4363 * @param permissions The permissions to check. 4364 * @return {@code true} if the caller has one of the given permissions. 4365 */ hasPermissions(@onNull String ....permissions)4366 private boolean hasPermissions(@NonNull String ...permissions) { 4367 for (String permission : permissions) { 4368 if (mContext.checkCallingOrSelfPermission(permission) 4369 == PackageManager.PERMISSION_GRANTED) { 4370 return true; 4371 } 4372 } 4373 return false; 4374 } 4375 4376 /** 4377 * Get the {@link SubscriptionInfoInternal} by subscription id. 4378 * 4379 * @param subId The subscription id. 4380 * 4381 * @return The subscription info. {@code null} if not found. 4382 */ 4383 @Nullable getSubscriptionInfoInternal(int subId)4384 public SubscriptionInfoInternal getSubscriptionInfoInternal(int subId) { 4385 return mSubscriptionDatabaseManager.getSubscriptionInfoInternal(subId); 4386 } 4387 4388 /** 4389 * Get the {@link SubscriptionInfo} by subscription id. 4390 * 4391 * @param subId The subscription id. 4392 * 4393 * @return The subscription info. {@code null} if not found. 4394 */ 4395 @Nullable getSubscriptionInfo(int subId)4396 public SubscriptionInfo getSubscriptionInfo(int subId) { 4397 SubscriptionInfoInternal infoInternal = getSubscriptionInfoInternal(subId); 4398 return infoInternal != null ? infoInternal.toSubscriptionInfo() : null; 4399 } 4400 4401 /** 4402 * Called when SIM becomes inactive. 4403 * 4404 * @param slotIndex The logical SIM slot index. 4405 * @param iccId iccId of the SIM in inactivate slot. 4406 */ updateSimStateForInactivePort(int slotIndex, @NonNull String iccId)4407 public void updateSimStateForInactivePort(int slotIndex, @NonNull String iccId) { 4408 mHandler.post(() -> { 4409 logl("updateSimStateForInactivePort: slotIndex=" + slotIndex + ", iccId=" 4410 + SubscriptionInfo.getPrintableId(iccId)); 4411 if (mSlotIndexToSubId.containsKey(slotIndex)) { 4412 // Re-enable the UICC application , so it will be in enabled state when it becomes 4413 // active again. (Pre-U behavior) 4414 mSubscriptionDatabaseManager.setUiccApplicationsEnabled( 4415 mSlotIndexToSubId.get(slotIndex), true); 4416 updateSubscription(slotIndex); 4417 } 4418 if (!TextUtils.isEmpty(iccId)) { 4419 // When port is inactive, sometimes valid iccid is present in the slot status, 4420 // hence update the portIndex. (Pre-U behavior) 4421 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager 4422 .getSubscriptionInfoInternalByIccId(IccUtils.stripTrailingFs(iccId)); 4423 int subId; 4424 if (subInfo != null) { 4425 subId = subInfo.getSubscriptionId(); 4426 log("updateSimStateForInactivePort: Found existing subscription. subId=" 4427 + subId); 4428 } else { 4429 // If iccId is new, add a subscription record in the database so it can be 4430 // activated later. (Pre-U behavior) 4431 subId = insertSubscriptionInfo(IccUtils.stripTrailingFs(iccId), 4432 SubscriptionManager.INVALID_SIM_SLOT_INDEX, "", 4433 SubscriptionManager.SUBSCRIPTION_TYPE_LOCAL_SIM); 4434 mSubscriptionDatabaseManager.setDisplayName(subId, 4435 mContext.getResources().getString(R.string.default_card_name, subId)); 4436 log("updateSimStateForInactivePort: Insert a new subscription for inactive SIM." 4437 + " subId=" + subId); 4438 } 4439 if (SubscriptionManager.isValidSubscriptionId(subId)) { 4440 mSubscriptionDatabaseManager.setPortIndex(subId, getPortIndex(iccId)); 4441 } 4442 } 4443 }); 4444 } 4445 4446 /** 4447 * Update SIM state. This method is supposed to be called by {@link UiccController} only. 4448 * 4449 * @param slotIndex The logical SIM slot index. 4450 * @param simState SIM state. 4451 * @param executor The executor to execute the callback. 4452 * @param updateCompleteCallback The callback to call when subscription manager service 4453 * completes subscription update. SIM state changed event will be broadcasted by 4454 * {@link UiccController} upon receiving callback. 4455 */ updateSimState(int slotIndex, @SimState int simState, @Nullable @CallbackExecutor Executor executor, @Nullable Runnable updateCompleteCallback)4456 public void updateSimState(int slotIndex, @SimState int simState, 4457 @Nullable @CallbackExecutor Executor executor, 4458 @Nullable Runnable updateCompleteCallback) { 4459 mHandler.post(() -> { 4460 mSimState[slotIndex] = simState; 4461 logl("updateSimState: slot " + slotIndex + " " 4462 + TelephonyManager.simStateToString(simState)); 4463 switch (simState) { 4464 case TelephonyManager.SIM_STATE_ABSENT: 4465 case TelephonyManager.SIM_STATE_PIN_REQUIRED: 4466 case TelephonyManager.SIM_STATE_PUK_REQUIRED: 4467 case TelephonyManager.SIM_STATE_NETWORK_LOCKED: 4468 case TelephonyManager.SIM_STATE_PERM_DISABLED: 4469 case TelephonyManager.SIM_STATE_CARD_IO_ERROR: 4470 case TelephonyManager.SIM_STATE_LOADED: 4471 updateSubscription(slotIndex); 4472 break; 4473 case TelephonyManager.SIM_STATE_NOT_READY: 4474 case TelephonyManager.SIM_STATE_READY: 4475 updateEmbeddedSubscriptions(); 4476 updateSubscription(slotIndex); 4477 break; 4478 case TelephonyManager.SIM_STATE_CARD_RESTRICTED: 4479 default: 4480 // No specific things needed to be done. Just return and broadcast the SIM 4481 // states. 4482 break; 4483 } 4484 if (executor != null && updateCompleteCallback != null) { 4485 executor.execute(updateCompleteCallback); 4486 } 4487 }); 4488 } 4489 4490 /** 4491 * Get the calling package(s). 4492 * 4493 * @return The calling package(s). 4494 */ 4495 @NonNull getCallingPackage()4496 private String getCallingPackage() { 4497 if (Binder.getCallingUid() == Process.PHONE_UID) { 4498 // Too many packages running with phone uid. Just return one here. 4499 return "com.android.phone"; 4500 } 4501 return Arrays.toString(mContext.getPackageManager().getPackagesForUid( 4502 Binder.getCallingUid())); 4503 } 4504 4505 /** 4506 * Update the {@link SubscriptionInfo#isGroupDisabled()} bit for the opportunistic 4507 * subscriptions. 4508 * 4509 * If all primary (non-opportunistic) subscriptions in the group are deactivated 4510 * (unplugged pSIM or deactivated eSIM profile), we should disable this opportunistic 4511 * subscriptions. 4512 */ 4513 @VisibleForTesting updateGroupDisabled()4514 public void updateGroupDisabled() { 4515 List<SubscriptionInfo> activeSubscriptions = mSubscriptionDatabaseManager 4516 .getAllSubscriptions().stream() 4517 .filter(SubscriptionInfoInternal::isActive) 4518 .map(SubscriptionInfoInternal::toSubscriptionInfo) 4519 .collect(Collectors.toList()); 4520 for (SubscriptionInfo oppSubInfo : getOpportunisticSubscriptions( 4521 mContext.getOpPackageName(), mContext.getFeatureId())) { 4522 boolean groupDisabled = activeSubscriptions.stream() 4523 .noneMatch(subInfo -> !subInfo.isOpportunistic() 4524 && Objects.equals(oppSubInfo.getGroupUuid(), subInfo.getGroupUuid())); 4525 mSubscriptionDatabaseManager.setGroupDisabled( 4526 oppSubInfo.getSubscriptionId(), groupDisabled); 4527 } 4528 } 4529 4530 4531 4532 /** 4533 * Set the transfer status of the subscriptionInfo that corresponds to subId. 4534 * @param subId The unique SubscriptionInfo key in database. 4535 * @param status The transfer status to change. This value must be one of the following. 4536 * {@link SubscriptionManager#TRANSFER_STATUS_NONE}, 4537 * {@link SubscriptionManager#TRANSFER_STATUS_TRANSFERRED_OUT} or 4538 * {@link SubscriptionManager#TRANSFER_STATUS_CONVERTED} 4539 * 4540 */ 4541 @Override 4542 @EnforcePermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) setTransferStatus(int subId, int status)4543 public void setTransferStatus(int subId, int status) { 4544 setTransferStatus_enforcePermission(); 4545 if (mContext.checkCallingOrSelfPermission( 4546 Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS) 4547 != PackageManager.PERMISSION_GRANTED) { 4548 throw new SecurityException("Must have WRITE_EMBEDDED_SUBSCRIPTIONS to" 4549 + "setTransferStatus"); 4550 } 4551 long token = Binder.clearCallingIdentity(); 4552 try { 4553 mSubscriptionDatabaseManager.setTransferStatus(subId, status); 4554 } finally { 4555 Binder.restoreCallingIdentity(token); 4556 } 4557 } 4558 4559 /** 4560 * Set the satellite entitlement plmn list value in the subscription database. 4561 * 4562 * @param subId subscription id. 4563 * @param satelliteEntitlementPlmnList satellite entitlement plmn list 4564 */ setSatelliteEntitlementPlmnList(int subId, @NonNull List<String> satelliteEntitlementPlmnList)4565 public void setSatelliteEntitlementPlmnList(int subId, 4566 @NonNull List<String> satelliteEntitlementPlmnList) { 4567 try { 4568 mSubscriptionDatabaseManager.setSatelliteEntitlementPlmnList( 4569 subId, satelliteEntitlementPlmnList); 4570 } catch (IllegalArgumentException e) { 4571 loge("setSatelliteEntitlementPlmnList: invalid subId=" + subId); 4572 } 4573 } 4574 4575 /** 4576 * Get the satellite entitlement plmn list value from the subscription database. 4577 * 4578 * @param subId subscription id. 4579 * @return satellite entitlement plmn list 4580 */ 4581 @NonNull getSatelliteEntitlementPlmnList(int subId)4582 public List<String> getSatelliteEntitlementPlmnList(int subId) { 4583 SubscriptionInfoInternal subInfo = mSubscriptionDatabaseManager.getSubscriptionInfoInternal( 4584 subId); 4585 4586 return Optional.ofNullable(subInfo) 4587 .map(SubscriptionInfoInternal::getSatelliteEntitlementPlmns) 4588 .filter(s -> !s.isEmpty()) 4589 .map(s -> Arrays.stream(s.split(",")).collect(Collectors.toList())) 4590 .orElse(new ArrayList<>()); 4591 } 4592 4593 /** 4594 * checks whether esim bootstrap is activated for any of the available active subscription info 4595 * list. 4596 * 4597 * @return {@code true} if esim bootstrap is activated for any of the active subscription, 4598 * else {@code false} 4599 * 4600 */ isEsimBootStrapProvisioningActivated()4601 public boolean isEsimBootStrapProvisioningActivated() { 4602 if (!mFeatureFlags.esimBootstrapProvisioningFlag()) { 4603 return false; 4604 } 4605 4606 List<SubscriptionInfo> activeSubInfos = 4607 getActiveSubscriptionInfoList(mContext.getOpPackageName(), 4608 mContext.getAttributionTag(), true/*isForAllProfile*/); 4609 4610 return activeSubInfos.stream().anyMatch(subInfo -> subInfo != null 4611 && subInfo.getProfileClass() == SubscriptionManager.PROFILE_CLASS_PROVISIONING); 4612 } 4613 4614 /** 4615 * checks whether esim bootstrap is activated for the subscription. 4616 * 4617 * @return {@code true} if esim bootstrap is activated for sub id else {@code false} 4618 * 4619 */ isEsimBootStrapProvisioningActiveForSubId(int subId)4620 public boolean isEsimBootStrapProvisioningActiveForSubId(int subId) { 4621 if (!mFeatureFlags.esimBootstrapProvisioningFlag()) { 4622 return false; 4623 } 4624 4625 SubscriptionInfoInternal subInfo = getSubscriptionInfoInternal(subId); 4626 return subInfo != null 4627 && subInfo.getProfileClass() == SubscriptionManager.PROFILE_CLASS_PROVISIONING; 4628 } 4629 4630 /** 4631 * Get the current calling package name. 4632 * @return the current calling package name 4633 */ 4634 @Nullable getCurrentPackageName()4635 private String getCurrentPackageName() { 4636 if (mPackageManager == null) return null; 4637 String[] callingUids = mPackageManager.getPackagesForUid(Binder.getCallingUid()); 4638 return (callingUids == null) ? null : callingUids[0]; 4639 } 4640 4641 /** 4642 * Make sure the device has required telephony feature 4643 * 4644 * @throws UnsupportedOperationException if the device does not have required telephony feature 4645 */ enforceTelephonyFeatureWithException(@ullable String callingPackage, @NonNull String methodName)4646 private void enforceTelephonyFeatureWithException(@Nullable String callingPackage, 4647 @NonNull String methodName) { 4648 if (callingPackage == null || mPackageManager == null) { 4649 return; 4650 } 4651 4652 if (!mFeatureFlags.enforceTelephonyFeatureMappingForPublicApis() 4653 || !CompatChanges.isChangeEnabled(ENABLE_FEATURE_MAPPING, callingPackage, 4654 Binder.getCallingUserHandle()) 4655 || mVendorApiLevel < Build.VERSION_CODES.VANILLA_ICE_CREAM) { 4656 // Skip to check associated telephony feature, 4657 // if compatibility change is not enabled for the current process or 4658 // the SDK version of vendor partition is less than Android V. 4659 return; 4660 } 4661 4662 if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY_SUBSCRIPTION)) { 4663 throw new UnsupportedOperationException( 4664 methodName + " is unsupported without " + FEATURE_TELEPHONY_SUBSCRIPTION); 4665 } 4666 } 4667 4668 /** 4669 * @return The logical SIM slot/sub mapping to string. 4670 */ 4671 @NonNull slotMappingToString()4672 private String slotMappingToString() { 4673 return "[" + mSlotIndexToSubId.entrySet().stream() 4674 .map(e -> "slot " + e.getKey() + ": subId=" + e.getValue()) 4675 .collect(Collectors.joining(", ")) + "]"; 4676 } 4677 4678 /** 4679 * @param mccMnc MccMnc value to check whether it supports non-terrestrial network or not. 4680 * @return {@code true} if MCC/MNC is matched with in the device overlay key 4681 * "config_satellite_sim_plmn_identifier", {@code false} otherwise. 4682 */ isSatellitePlmn(@onNull String mccMnc)4683 private boolean isSatellitePlmn(@NonNull String mccMnc) { 4684 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 4685 log("isSatellitePlmn: oemEnabledSatelliteFlag is disabled"); 4686 return false; 4687 } 4688 4689 final int id = R.string.config_satellite_sim_plmn_identifier; 4690 String overlayMccMnc = null; 4691 try { 4692 overlayMccMnc = mContext.getResources().getString(id); 4693 } catch (Resources.NotFoundException ex) { 4694 loge("isSatellitePlmn: id= " + id + ", ex=" + ex); 4695 } 4696 if (TextUtils.isEmpty(overlayMccMnc) && isMockModemAllowed()) { 4697 log("isSatellitePlmn: Read config_satellite_sim_plmn_identifier from device config"); 4698 overlayMccMnc = DeviceConfig.getString(DeviceConfig.NAMESPACE_TELEPHONY, 4699 "config_satellite_sim_plmn_identifier", ""); 4700 } 4701 log("isSatellitePlmn: overlayMccMnc=" + overlayMccMnc + ", mccMnc=" + mccMnc); 4702 return TextUtils.equals(mccMnc, overlayMccMnc); 4703 } 4704 4705 /** 4706 * Checks and matches the service provider name (spn) with the device overlay config to 4707 * determine whether non-terrestrial networks are supported. 4708 * @param spn service provider name of the profile. 4709 * @return {@code true} if the given spn is matched with the overlay key. 4710 * "config_satellite_sim_spn_identifier", {@code false} otherwise. 4711 */ isSatelliteSpn(@onNull String spn)4712 private boolean isSatelliteSpn(@NonNull String spn) { 4713 if (!mFeatureFlags.oemEnabledSatelliteFlag()) { 4714 log("isSatelliteSpn: oemEnabledSatelliteFlag is disabled"); 4715 return false; 4716 } 4717 4718 final int id = R.string.config_satellite_sim_spn_identifier; 4719 String overlaySpn = null; 4720 try { 4721 overlaySpn = mContext.getResources().getString(id); 4722 } catch (Resources.NotFoundException ex) { 4723 loge("isSatelliteSpn: id= " + id + ", ex=" + ex); 4724 } 4725 if (TextUtils.isEmpty(overlaySpn) && isMockModemAllowed()) { 4726 log("isSatelliteSpn: Read config_satellite_sim_spn_identifier from device config"); 4727 overlaySpn = DeviceConfig.getString(DeviceConfig.NAMESPACE_TELEPHONY, 4728 "config_satellite_sim_spn_identifier", ""); 4729 } 4730 log("isSatelliteSpn: overlaySpn=" + overlaySpn + ", spn=" + spn); 4731 4732 if (TextUtils.isEmpty(spn) || TextUtils.isEmpty(overlaySpn)) { 4733 return false; 4734 } 4735 4736 return TextUtils.equals(spn, overlaySpn); 4737 } 4738 isMockModemAllowed()4739 private boolean isMockModemAllowed() { 4740 boolean isAllowed = SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false); 4741 return (SystemProperties.getBoolean(ALLOW_MOCK_MODEM_PROPERTY, false) 4742 || SystemProperties.getBoolean(BOOT_ALLOW_MOCK_MODEM_PROPERTY, false)); 4743 } 4744 4745 /** 4746 * Iterates through previously subscribed SIMs to excludes subscriptions that are not visible 4747 * to the users to provide a more appropriate number to describe the current SIM. 4748 * @param subId current subscription id. 4749 * @return cardNumber subId excluding invisible subscriptions. 4750 */ getCardNumber(int subId)4751 private int getCardNumber(int subId) { 4752 int cardNumber = subId; // Initialize with the potential card number 4753 for (int i = subId - 1; i > 0; i--) { 4754 SubscriptionInfoInternal subInfo = getSubscriptionInfoInternal(i); 4755 if (subInfo != null && !subInfo.isVisible()) { 4756 cardNumber--; 4757 } 4758 } 4759 4760 return cardNumber; 4761 } 4762 4763 /** 4764 * Log debug messages. 4765 * 4766 * @param s debug messages 4767 */ log(@onNull String s)4768 private void log(@NonNull String s) { 4769 Rlog.d(LOG_TAG, s); 4770 } 4771 4772 /** 4773 * Log error messages. 4774 * 4775 * @param s error messages 4776 */ loge(@onNull String s)4777 private void loge(@NonNull String s) { 4778 Rlog.e(LOG_TAG, s); 4779 } 4780 4781 /** 4782 * Log debug messages and also log into the local log. 4783 * 4784 * @param s debug messages 4785 */ logl(@onNull String s)4786 private void logl(@NonNull String s) { 4787 log(s); 4788 mLocalLog.log(s); 4789 } 4790 4791 /** 4792 * Dump the state of {@link SubscriptionManagerService}. 4793 * 4794 * @param fd File descriptor 4795 * @param printWriter Print writer 4796 * @param args Arguments 4797 */ dump(@onNull FileDescriptor fd, @NonNull PrintWriter printWriter, @NonNull String[] args)4798 public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter printWriter, 4799 @NonNull String[] args) { 4800 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DUMP, 4801 "Requires android.Manifest.permission.DUMP"); 4802 final long token = Binder.clearCallingIdentity(); 4803 try { 4804 IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, " "); 4805 pw.println(SubscriptionManagerService.class.getSimpleName() + ":"); 4806 pw.println("Active modem count=" + mTelephonyManager.getActiveModemCount()); 4807 pw.println("Logical SIM slot sub id mapping:"); 4808 pw.increaseIndent(); 4809 mSlotIndexToSubId.forEach((slotIndex, subId) 4810 -> pw.println("Logical SIM slot " + slotIndex + ": subId=" + subId)); 4811 pw.decreaseIndent(); 4812 pw.println("ICCID:"); 4813 pw.increaseIndent(); 4814 for (int i = 0; i < mTelephonyManager.getActiveModemCount(); i++) { 4815 pw.println("slot " + i + ": " + SubscriptionInfo.getPrintableId(getIccId(i))); 4816 } 4817 pw.decreaseIndent(); 4818 pw.println(); 4819 pw.println("defaultSubId=" + getDefaultSubId()); 4820 pw.println("defaultVoiceSubId=" + getDefaultVoiceSubId()); 4821 pw.println("defaultDataSubId=" + getDefaultDataSubId()); 4822 pw.println("activeDataSubId=" + getActiveDataSubscriptionId()); 4823 pw.println("defaultSmsSubId=" + getDefaultSmsSubId()); 4824 pw.println("areAllSubscriptionsLoaded=" + areAllSubscriptionsLoaded()); 4825 pw.println("mUserIdToAvailableSubs=" + mUserIdToAvailableSubs); 4826 pw.println(); 4827 for (int i = 0; i < mSimState.length; i++) { 4828 pw.println("mSimState[" + i + "]=" 4829 + TelephonyManager.simStateToString(mSimState[i])); 4830 } 4831 4832 pw.println(); 4833 pw.println("Active subscriptions:"); 4834 pw.increaseIndent(); 4835 mSubscriptionDatabaseManager.getAllSubscriptions().stream() 4836 .filter(SubscriptionInfoInternal::isActive).forEach(pw::println); 4837 pw.decreaseIndent(); 4838 4839 pw.println(); 4840 pw.println("All subscriptions:"); 4841 pw.increaseIndent(); 4842 mSubscriptionDatabaseManager.getAllSubscriptions().forEach(pw::println); 4843 pw.decreaseIndent(); 4844 pw.println(); 4845 4846 pw.print("Embedded subscriptions: ["); 4847 pw.println(mSubscriptionDatabaseManager.getAllSubscriptions().stream() 4848 .filter(SubscriptionInfoInternal::isEmbedded) 4849 .map(subInfo -> String.valueOf(subInfo.getSubscriptionId())) 4850 .collect(Collectors.joining(", ")) + "]"); 4851 4852 pw.print("Opportunistic subscriptions: ["); 4853 pw.println(mSubscriptionDatabaseManager.getAllSubscriptions().stream() 4854 .filter(SubscriptionInfoInternal::isOpportunistic) 4855 .map(subInfo -> String.valueOf(subInfo.getSubscriptionId())) 4856 .collect(Collectors.joining(", ")) + "]"); 4857 4858 pw.print("getAvailableSubscriptionInfoList: ["); 4859 pw.println(getAvailableSubscriptionInfoList( 4860 mContext.getOpPackageName(), mContext.getFeatureId()).stream() 4861 .map(subInfo -> String.valueOf(subInfo.getSubscriptionId())) 4862 .collect(Collectors.joining(", ")) + "]"); 4863 4864 pw.print("getSelectableSubscriptionInfoList: ["); 4865 pw.println(mSubscriptionManager.getSelectableSubscriptionInfoList().stream() 4866 .map(subInfo -> String.valueOf(subInfo.getSubscriptionId())) 4867 .collect(Collectors.joining(", ")) + "]"); 4868 4869 if (mEuiccManager != null) { 4870 pw.println("Euicc enabled=" + mEuiccManager.isEnabled()); 4871 } 4872 pw.println(); 4873 pw.println("Local log:"); 4874 pw.increaseIndent(); 4875 mLocalLog.dump(fd, pw, args); 4876 pw.decreaseIndent(); 4877 pw.decreaseIndent(); 4878 pw.println(); 4879 mSubscriptionDatabaseManager.dump(fd, pw, args); 4880 } finally { 4881 Binder.restoreCallingIdentity(token); 4882 } 4883 } 4884 } 4885