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