Update mobile data preference getter/setter

To satisfy OEM's requests, setting mobile data preference
should be by uid. Thus, update the getter/setter to
return/accept set of uids that need to apply mobile data
preference.

Bug: 171872461
Test: atest FrameworksNetTests
Change-Id: Id44efd2a6d820867f4405426c91e65b9ef155898
diff --git a/framework/api/module-lib-current.txt b/framework/api/module-lib-current.txt
index 524db18..b219375 100644
--- a/framework/api/module-lib-current.txt
+++ b/framework/api/module-lib-current.txt
@@ -57,7 +57,7 @@
     method @Nullable public static android.net.ProxyInfo getGlobalProxy(@NonNull android.content.Context);
     method @NonNull public static java.time.Duration getMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
     method public static boolean getMobileDataAlwaysOn(@NonNull android.content.Context, boolean);
-    method @Nullable public static String getMobileDataPreferredApps(@NonNull android.content.Context);
+    method @NonNull public static java.util.Set<java.lang.Integer> getMobileDataPreferredUids(@NonNull android.content.Context);
     method public static int getNetworkAvoidBadWifi(@NonNull android.content.Context);
     method @Nullable public static String getNetworkMeteredMultipathPreference(@NonNull android.content.Context);
     method public static int getNetworkSwitchNotificationMaximumDailyCount(@NonNull android.content.Context, int);
@@ -77,7 +77,7 @@
     method public static void setGlobalProxy(@NonNull android.content.Context, @NonNull android.net.ProxyInfo);
     method public static void setMobileDataActivityTimeout(@NonNull android.content.Context, @NonNull java.time.Duration);
     method public static void setMobileDataAlwaysOn(@NonNull android.content.Context, boolean);
-    method public static void setMobileDataPreferredApps(@NonNull android.content.Context, @Nullable String);
+    method public static void setMobileDataPreferredUids(@NonNull android.content.Context, @NonNull java.util.Set<java.lang.Integer>);
     method public static void setNetworkAvoidBadWifi(@NonNull android.content.Context, int);
     method public static void setNetworkMeteredMultipathPreference(@NonNull android.content.Context, @NonNull String);
     method public static void setNetworkSwitchNotificationMaximumDailyCount(@NonNull android.content.Context, @IntRange(from=0) int);
diff --git a/framework/src/android/net/ConnectivitySettingsManager.java b/framework/src/android/net/ConnectivitySettingsManager.java
index c4bb2d3..07754e4 100644
--- a/framework/src/android/net/ConnectivitySettingsManager.java
+++ b/framework/src/android/net/ConnectivitySettingsManager.java
@@ -28,6 +28,8 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.net.ConnectivityManager.MultipathPreference;
+import android.os.Process;
+import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.ArraySet;
@@ -334,12 +336,12 @@
             "network_metered_multipath_preference";
 
     /**
-     * A list of apps that should go on cellular networks in preference even when higher-priority
+     * A list of uids that should go on cellular networks in preference even when higher-priority
      * networks are connected.
      *
      * @hide
      */
-    public static final String MOBILE_DATA_PREFERRED_APPS = "mobile_data_preferred_apps";
+    public static final String MOBILE_DATA_PREFERRED_UIDS = "mobile_data_preferred_uids";
 
     /**
      * One of the private DNS modes that indicates the private DNS mode is off.
@@ -1002,28 +1004,46 @@
     }
 
     /**
-     * Get the list of apps(from {@link Settings}) that should go on cellular networks in preference
+     * Get the list of uids(from {@link Settings}) that should go on cellular networks in preference
      * even when higher-priority networks are connected.
      *
      * @param context The {@link Context} to query the setting.
-     * @return A list of apps that should go on cellular networks in preference even when
+     * @return A list of uids that should go on cellular networks in preference even when
      *         higher-priority networks are connected or null if no setting value.
      */
-    @Nullable
-    public static String getMobileDataPreferredApps(@NonNull Context context) {
-        return Settings.Secure.getString(context.getContentResolver(), MOBILE_DATA_PREFERRED_APPS);
+    @NonNull
+    public static Set<Integer> getMobileDataPreferredUids(@NonNull Context context) {
+        final String uidList = Settings.Secure.getString(
+                context.getContentResolver(), MOBILE_DATA_PREFERRED_UIDS);
+        final Set<Integer> uids = new ArraySet<>();
+        if (TextUtils.isEmpty(uidList)) {
+            return uids;
+        }
+        for (String uid : uidList.split(";")) {
+            uids.add(Integer.valueOf(uid));
+        }
+        return uids;
     }
 
     /**
-     * Set the list of apps(to {@link Settings}) that should go on cellular networks in preference
+     * Set the list of uids(to {@link Settings}) that should go on cellular networks in preference
      * even when higher-priority networks are connected.
      *
      * @param context The {@link Context} to set the setting.
-     * @param list A list of apps that should go on cellular networks in preference even when
+     * @param uidList A list of uids that should go on cellular networks in preference even when
      *             higher-priority networks are connected.
      */
-    public static void setMobileDataPreferredApps(@NonNull Context context, @Nullable String list) {
-        Settings.Secure.putString(context.getContentResolver(), MOBILE_DATA_PREFERRED_APPS, list);
+    public static void setMobileDataPreferredUids(@NonNull Context context,
+            @NonNull Set<Integer> uidList) {
+        final StringJoiner joiner = new StringJoiner(";");
+        for (Integer uid : uidList) {
+            if (uid < 0 || UserHandle.getAppId(uid) > Process.LAST_APPLICATION_UID) {
+                throw new IllegalArgumentException("Invalid uid");
+            }
+            joiner.add(uid.toString());
+        }
+        Settings.Secure.putString(
+                context.getContentResolver(), MOBILE_DATA_PREFERRED_UIDS, joiner.toString());
     }
 
     /**