Use ParceledListSlice to paginate response from getPackagesForOpsForDevice binder API

In a previous similar security bug fix ag/31434165 we imposed a
threshold on the number of attributed op entries returned for a single
package. But in this bug, the POC app created attributed op entries for
hundreds of packages which caused TransactionTooLargeException in getPackagesForOpsForDevice binder API.
So the fix is to add pagination in the binder response by using
ParceledListSlice.

Bug: 416490321
Test: Use the POC app in the bug report, verified after the fix there
was no more crashes from SystemUi and the device could boot
successfully.
Flag: EXEMPT security bug fix
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:2c637955ab388773c234268ceb108372eaab2200)
Cherrypick-From: https://googleplex-android-review.googlesource.com/q/commit:bd1eff349d514a53838df08ae097380d21c08c67
Merged-In: If4590160d1d743f58c1aed3f923d3668a8936c57
Change-Id: If4590160d1d743f58c1aed3f923d3668a8936c57
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 5214d2c..fa7e164 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -7860,13 +7860,13 @@
         } else {
             opCodes = null;
         }
-        final List<AppOpsManager.PackageOps> result;
         try {
-            result = mService.getPackagesForOpsForDevice(opCodes, persistentDeviceId);
+            ParceledListSlice<PackageOps> packageOps = mService.getPackagesForOpsForDevice(opCodes,
+                    persistentDeviceId);
+            return packageOps == null ? Collections.emptyList() : packageOps.getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
-        return (result != null) ? result : Collections.emptyList();
     }
 
     /**
@@ -7885,8 +7885,9 @@
     @UnsupportedAppUsage
     public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
         try {
-            return mService.getPackagesForOpsForDevice(ops,
+            ParceledListSlice<PackageOps> packageOps = mService.getPackagesForOpsForDevice(ops,
                     VirtualDeviceManager.PERSISTENT_DEVICE_ID_DEFAULT);
+            return packageOps == null ? null : packageOps.getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/com/android/internal/app/IAppOpsService.aidl b/core/java/com/android/internal/app/IAppOpsService.aidl
index 3ec7064..151a08e 100644
--- a/core/java/com/android/internal/app/IAppOpsService.aidl
+++ b/core/java/com/android/internal/app/IAppOpsService.aidl
@@ -162,5 +162,5 @@
             int attributionFlags, int attributionChainId);
     void finishOperationForDevice(IBinder clientId, int code, int uid, String packageName,
             @nullable String attributionTag, int virtualDeviceId);
-   List<AppOpsManager.PackageOps> getPackagesForOpsForDevice(in int[] ops, String persistentDeviceId);
+   ParceledListSlice<AppOpsManager.PackageOps> getPackagesForOpsForDevice(in int[] ops, String persistentDeviceId);
 }
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 8d01cd7..da55675 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -104,6 +104,7 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionInfo;
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
@@ -194,6 +195,7 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.io.StringWriter;
 import java.text.SimpleDateFormat;
 import java.time.Instant;
 import java.time.temporal.ChronoUnit;
@@ -1753,11 +1755,13 @@
 
     @Override
     public List<AppOpsManager.PackageOps> getPackagesForOps(int[] ops) {
-        return getPackagesForOpsForDevice(ops, PERSISTENT_DEVICE_ID_DEFAULT);
+        ParceledListSlice<AppOpsManager.PackageOps> packageOps = getPackagesForOpsForDevice(ops,
+                PERSISTENT_DEVICE_ID_DEFAULT);
+        return packageOps == null ? null : packageOps.getList();
     }
 
     @Override
-    public List<AppOpsManager.PackageOps> getPackagesForOpsForDevice(int[] ops,
+    public ParceledListSlice<AppOpsManager.PackageOps> getPackagesForOpsForDevice(int[] ops,
             @NonNull String persistentDeviceId) {
         final int callingUid = Binder.getCallingUid();
         final boolean hasAllPackageAccess = mContext.checkPermission(
@@ -1794,7 +1798,7 @@
                 }
             }
         }
-        return res;
+        return res == null ? null : new ParceledListSlice<>(res);
     }
 
     @Override