Use internal SubManagerService
Use internal subscriptionmanager service to gain access to all active subscriptions regardless its associated profile, then filter by caller profile.
And gate user handle filtering activity with a new feature flag so
that it can be advanced independent from enterprise feature. It should
cause no behavior change because currently no client can assign a SIM to
a profile.
Bug: 296076674
Test: data browsing + voice call + sending sms
Change-Id: Ie851f2c6ed12a70fa67797baa35c7ce62bedbeb7
diff --git a/flags/subscription.aconfig b/flags/subscription.aconfig
index 0521cb9..dece11a 100644
--- a/flags/subscription.aconfig
+++ b/flags/subscription.aconfig
@@ -5,4 +5,11 @@
namespace: "telephony"
description: "To support separation between personal and work from TelephonyManager and SubscriptionManager API perspective."
bug: "296076674"
+}
+
+flag {
+ name: "enforce_subscription_user_filter"
+ namespace: "telephony"
+ description: "Enabled flag means subscriptions enforce filtering result base on calling user handle. It marks the telephony completion of user filtering."
+ bug: "296076674"
}
\ No newline at end of file
diff --git a/src/java/com/android/internal/telephony/SmsController.java b/src/java/com/android/internal/telephony/SmsController.java
index 251a1fd..9d88a0d 100644
--- a/src/java/com/android/internal/telephony/SmsController.java
+++ b/src/java/com/android/internal/telephony/SmsController.java
@@ -36,6 +36,7 @@
import android.os.Build;
import android.os.Bundle;
import android.os.TelephonyServiceManager.ServiceRegisterer;
+import android.os.UserHandle;
import android.provider.Telephony.Sms.Intents;
import android.telephony.CarrierConfigManager;
import android.telephony.SmsManager;
@@ -54,6 +55,7 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
import java.util.List;
import java.util.Locale;
@@ -64,7 +66,7 @@
static final String LOG_TAG = "SmsController";
private final Context mContext;
- private final FeatureFlags mFlags;
+ @NonNull private final FeatureFlags mFlags;
@VisibleForTesting
public SmsController(Context context, @NonNull FeatureFlags flags) {
mContext = context;
@@ -558,32 +560,55 @@
}
TelephonyManager telephonyManager =
(TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
- List<SubscriptionInfo> subInfoList;
- final long identity = Binder.clearCallingIdentity();
- try {
- subInfoList = SubscriptionManager.from(context).getActiveSubscriptionInfoList();
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ if (mFlags.enforceSubscriptionUserFilter()) {
+ int[] activeSubIds;
+ final UserHandle user = Binder.getCallingUserHandle();
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ activeSubIds = Arrays.stream(SubscriptionManagerService.getInstance()
+ .getActiveSubIdList(true /*visibleOnly*/))
+ .filter(sub -> SubscriptionManagerService.getInstance()
+ .isSubscriptionAssociatedWithUser(sub, user))
+ .toArray();
+ for (int activeSubId : activeSubIds) {
+ // Check if the subId is associated with the caller user profile.
+ if (activeSubId == subId) {
+ return false;
+ }
+ }
- if (subInfoList != null) {
- final int subInfoLength = subInfoList.size();
+ // If reached here and multiple SIMs and subs present, need sms sim pick activity.
+ return activeSubIds.length > 1 && telephonyManager.getSimCount() > 1;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ } else {
+ List<SubscriptionInfo> subInfoList;
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ subInfoList = SubscriptionManager.from(context).getActiveSubscriptionInfoList();
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
- for (int i = 0; i < subInfoLength; ++i) {
- final SubscriptionInfo sir = subInfoList.get(i);
- if (sir != null && sir.getSubscriptionId() == subId) {
- // The subscription id is valid, sms sim pick activity not needed
- return false;
+ if (subInfoList != null) {
+ final int subInfoLength = subInfoList.size();
+
+ for (int i = 0; i < subInfoLength; ++i) {
+ final SubscriptionInfo sir = subInfoList.get(i);
+ if (sir != null && sir.getSubscriptionId() == subId) {
+ // The subscription id is valid, sms sim pick activity not needed
+ return false;
+ }
+ }
+
+ // If reached here and multiple SIMs and subs present, need sms sim pick activity
+ if (subInfoLength > 1 && telephonyManager.getSimCount() > 1) {
+ return true;
}
}
-
- // If reached here and multiple SIMs and subs present, sms sim pick activity is needed
- if (subInfoLength > 1 && telephonyManager.getSimCount() > 1) {
- return true;
- }
+ return false;
}
-
- return false;
}
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
diff --git a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
index a8d05a3..3dc5cab 100644
--- a/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
+++ b/src/java/com/android/internal/telephony/subscription/SubscriptionManagerService.java
@@ -2879,6 +2879,7 @@
* @return The subscription Id default to use.
*/
private int getDefaultAsUser(@UserIdInt int userId, int defaultValue) {
+ // TODO: Not using mFlags.enforceSubscriptionUserFilter because this affects U CTS.
if (mFeatureFlags.workProfileApiSplit()) {
List<SubscriptionInfoInternal> subInfos =
getSubscriptionInfoStreamAsUser(UserHandle.of(userId))
@@ -3806,7 +3807,7 @@
+ subscriptionId);
}
- if (mFeatureFlags.workProfileApiSplit()) {
+ if (mFeatureFlags.enforceSubscriptionUserFilter()) {
return isSubscriptionAssociatedWithUserInternal(
subInfoInternal, userHandle.getIdentifier());
}
@@ -3835,15 +3836,15 @@
*/
private boolean isSubscriptionAssociatedWithUserInternal(
@NonNull SubscriptionInfoInternal subInfo, @UserIdInt int userId) {
- if (!mFeatureFlags.workProfileApiSplit()
+ if (!mFeatureFlags.enforceSubscriptionUserFilter()
|| !CompatChanges.isChangeEnabled(FILTER_ACCESSIBLE_SUBS_BY_USER,
Binder.getCallingUid())) {
return true;
}
- return subInfo.getUserId() == userId
- // Can access the unassociated sub if the user doesn't have its own.
- || (subInfo.getUserId() == UserHandle.USER_NULL
+ // Can access the unassociated sub if the user doesn't have its own.
+ return (subInfo.getUserId() == UserHandle.USER_NULL
&& mUserIdToAvailableSubs.get(userId) == null)
+ || userId == subInfo.getUserId()
|| userId == UserHandle.USER_ALL;
}
@@ -3866,7 +3867,7 @@
enforcePermissions("getSubscriptionInfoListAssociatedWithUser",
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
- if (mFeatureFlags.workProfileApiSplit()) {
+ if (mFeatureFlags.enforceSubscriptionUserFilter()) {
return getSubscriptionInfoStreamAsUser(userHandle)
.map(SubscriptionInfoInternal::toSubscriptionInfo)
.collect(Collectors.toList());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
index eecaf90..9ef25e4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/subscription/SubscriptionManagerServiceTest.java
@@ -1161,6 +1161,7 @@
SubscriptionManagerService.FILTER_ACCESSIBLE_SUBS_BY_USER})
public void testIsSubscriptionAssociatedWithUserMultiSubs() {
doReturn(true).when(mFlags).workProfileApiSplit();
+ doReturn(true).when(mFlags).enforceSubscriptionUserFilter();
mContextFixture.addCallingOrSelfPermission(
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
insertSubscription(FAKE_SUBSCRIPTION_INFO1);
@@ -1222,6 +1223,7 @@
public void testSubscriptionAssociationWorkProfileCallerVisibility() {
// Split mode is defined as when a profile owns a dedicated sub, it loses the visibility to
// the unassociated sub.
+ doReturn(true).when(mFlags).enforceSubscriptionUserFilter();
doReturn(true).when(mFlags).workProfileApiSplit();
mContextFixture.addCallingOrSelfPermission(
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);
@@ -1339,6 +1341,7 @@
public void testSubscriptionAssociationPersonalCallerVisibility() {
// Split mode is defined as when a profile owns a dedicated sub, it loses the visibility to
// the unassociated sub.
+ doReturn(true).when(mFlags).enforceSubscriptionUserFilter();
doReturn(true).when(mFlags).workProfileApiSplit();
mContextFixture.addCallingOrSelfPermission(
Manifest.permission.MANAGE_SUBSCRIPTION_USER_ASSOCIATION);