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);