From 1cc9277e4bd58ca75b5dbaa9f6980de2dd89dedb Mon Sep 17 00:00:00 2001 From: Nathan Harold Date: Tue, 24 Oct 2023 18:05:16 -0700 Subject: Replace Null Returns with EmptyList in SubscriptionManager Fix some call sites where a null might have been returned in the specific edge case that the phone process is not available and SubscriptionManager swallows the RemoteException. This will also guard against any issues where the implementation of SubscriptionManagerService erroneously returns a null when an empty list could have been returned. Bug: 245818227 Test: atest FrameworksTelephonyTest # (no functional change) Test: Functional test (voice, messaging, data) Change-Id: I2046567edbceaf9fef5f754a368b9aff8f18e6e8 --- core/api/current.txt | 4 +- core/api/system-current.txt | 2 +- .../android/telephony/SubscriptionManager.java | 56 +++++++++------------- 3 files changed, 26 insertions(+), 36 deletions(-) diff --git a/core/api/current.txt b/core/api/current.txt index b17e3343666e..cb8aa55deb51 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -45157,13 +45157,13 @@ package android.telephony { method @FlaggedApi("com.android.internal.telephony.flags.enforce_subscription_user_filter") @NonNull @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_PROFILES) public android.telephony.SubscriptionManager createForAllUserProfiles(); method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public android.os.ParcelUuid createSubscriptionGroup(@NonNull java.util.List); method @Deprecated public static android.telephony.SubscriptionManager from(android.content.Context); - method public java.util.List getAccessibleSubscriptionInfoList(); + method @Nullable public java.util.List getAccessibleSubscriptionInfoList(); method public static int getActiveDataSubscriptionId(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfo(int); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getActiveSubscriptionInfoCount(); method public int getActiveSubscriptionInfoCountMax(); method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForSimSlotIndex(int); - method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List getActiveSubscriptionInfoList(); + method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public java.util.List getActiveSubscriptionInfoList(); method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.READ_PHONE_STATE, "carrier privileges"}) public java.util.List getAllSubscriptionInfoList(); method @NonNull public java.util.List getCompleteActiveSubscriptionInfoList(); method public static int getDefaultDataSubscriptionId(); diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 01f54ade9acc..35f7c213b66f 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -14581,7 +14581,7 @@ package android.telephony { method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getActiveSubscriptionIdList(); method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public android.telephony.SubscriptionInfo getActiveSubscriptionInfoForIcc(@NonNull String); method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public byte[] getAllSimSpecificSettingsForBackup(); - method public java.util.List getAvailableSubscriptionInfoList(); + method @Nullable public java.util.List getAvailableSubscriptionInfoList(); method @NonNull @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int[] getCompleteActiveSubscriptionIdList(); method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getEnabledSubscriptionId(int); method @NonNull public static android.content.res.Resources getResourcesForSubId(@NonNull android.content.Context, int); diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index eb7e67dccfd5..174954542b94 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -1927,34 +1927,25 @@ public class SubscriptionManager { * Then for SDK 35+, if the caller identity is personal profile, then this will return * subscription 1 only and vice versa. * - *

The records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by - * {@link SubscriptionInfo#getSubscriptionId}. + *

Returned records will be sorted by {@link SubscriptionInfo#getSimSlotIndex} then by + * {@link SubscriptionInfo#getSubscriptionId}. Beginning with Android SDK 35, this method will + * never return null. * *

Requires Permission: {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} * or that the calling app has carrier privileges (see * {@link TelephonyManager#hasCarrierPrivileges}). * - * @return Sorted list of the currently {@link SubscriptionInfo} records available on the device. - *

    - *
  • - * If null is returned the current state is unknown but if a {@link OnSubscriptionsChangedListener} - * has been registered {@link OnSubscriptionsChangedListener#onSubscriptionsChanged} will be - * invoked in the future. - *
  • - *
  • - * If the list is empty then there are no {@link SubscriptionInfo} records currently available. - *
  • - *
  • - * if the list is non-empty the list is sorted by {@link SubscriptionInfo#getSimSlotIndex} - * then by {@link SubscriptionInfo#getSubscriptionId}. - *
  • - *
+ * @return a list of the active {@link SubscriptionInfo} that is visible to the caller. If + * an empty list or null is returned, then there are no active subscriptions that + * are visible to the caller. If the number of active subscriptions available to + * any caller changes, then this change will be indicated by + * {@link OnSubscriptionsChangedListener#onSubscriptionsChanged}. * * @throws UnsupportedOperationException If the device does not have - * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}. + * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}. */ @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) - public List getActiveSubscriptionInfoList() { + public @Nullable List getActiveSubscriptionInfoList() { List activeList = null; try { @@ -1970,6 +1961,8 @@ public class SubscriptionManager { if (activeList != null) { activeList = activeList.stream().filter(subInfo -> isSubscriptionVisible(subInfo)) .collect(Collectors.toList()); + } else { + activeList = Collections.emptyList(); } return activeList; } @@ -1998,12 +1991,7 @@ public class SubscriptionManager { * {@link PackageManager#FEATURE_TELEPHONY_SUBSCRIPTION}. */ public @NonNull List getCompleteActiveSubscriptionInfoList() { - List completeList = getActiveSubscriptionInfoList( - /* userVisibleonly */false); - if (completeList == null) { - completeList = new ArrayList<>(); - } - return completeList; + return getActiveSubscriptionInfoList(/* userVisibleonly */ false); } /** @@ -2032,7 +2020,7 @@ public class SubscriptionManager { * * @hide */ - public @Nullable List getActiveSubscriptionInfoList(boolean userVisibleOnly) { + public @NonNull List getActiveSubscriptionInfoList(boolean userVisibleOnly) { List activeList = null; try { @@ -2045,11 +2033,13 @@ public class SubscriptionManager { // ignore it } - if (!userVisibleOnly || activeList == null) { - return activeList; - } else { + if (activeList == null || activeList.isEmpty()) { + return Collections.emptyList(); + } else if (userVisibleOnly) { return activeList.stream().filter(subInfo -> isSubscriptionVisible(subInfo)) .collect(Collectors.toList()); + } else { + return activeList; } } @@ -2086,7 +2076,7 @@ public class SubscriptionManager { * @hide */ @SystemApi - public List getAvailableSubscriptionInfoList() { + public @Nullable List getAvailableSubscriptionInfoList() { List result = null; try { @@ -2098,7 +2088,7 @@ public class SubscriptionManager { } catch (RemoteException ex) { // ignore it } - return result; + return (result == null) ? Collections.emptyList() : result; } /** @@ -2128,7 +2118,7 @@ public class SubscriptionManager { * @throws UnsupportedOperationException If the device does not have * {@link PackageManager#FEATURE_TELEPHONY_EUICC}. */ - public List getAccessibleSubscriptionInfoList() { + public @Nullable List getAccessibleSubscriptionInfoList() { List result = null; try { @@ -2139,7 +2129,7 @@ public class SubscriptionManager { } catch (RemoteException ex) { // ignore it } - return result; + return (result == null) ? Collections.emptyList() : result; } /** -- cgit v1.2.3-59-g8ed1b