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