Prevent loop in PermissionPolicyService

The AppOpsModeChangeWatchers call back even if the mode was set to
already set mode. PermissionPolicyService listens to the same app-ops it
changes. I.e. it used to change the mode to default, which then causes a
call-back which made set it to default again, etc...

This exhausts a thread until the app-op is finally set to non-default.
The fix is to prevent the loop by checking if the app-op is already the
correct mode before setting it.

Fixes: 135674928
Test: atest IncidentReportListenerTest CollectorHostsideLibTest on
          cuttlefish and crosshatch
Change-Id: Ic65945e814957ac59495b3da221fabb0f3d42b66
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 68feb4a..3a78aa2 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -365,7 +365,7 @@
          *
          * @see #syncPackages
          */
-        private final @NonNull ArrayList<OpToRestrict> mOpsToDefault = new ArrayList<>();
+        private final @NonNull ArrayList<OpToChange> mOpsToDefault = new ArrayList<>();
 
         /**
          * All ops that need to be flipped to allow if default.
@@ -374,14 +374,14 @@
          *
          * @see #syncPackages
          */
-        private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllowIfDefault = new ArrayList<>();
+        private final @NonNull ArrayList<OpToChange> mOpsToAllowIfDefault = new ArrayList<>();
 
         /**
          * All ops that need to be flipped to allow.
          *
          * @see #syncPackages
          */
-        private final @NonNull ArrayList<OpToUnrestrict> mOpsToAllow = new ArrayList<>();
+        private final @NonNull ArrayList<OpToChange> mOpsToAllow = new ArrayList<>();
 
         /**
          * All ops that need to be flipped to ignore if default.
@@ -390,14 +390,14 @@
          *
          * @see #syncPackages
          */
-        private final @NonNull ArrayList<OpToUnrestrict> mOpsToIgnoreIfDefault = new ArrayList<>();
+        private final @NonNull ArrayList<OpToChange> mOpsToIgnoreIfDefault = new ArrayList<>();
 
         /**
          * All ops that need to be flipped to ignore.
          *
          * @see #syncPackages
          */
-        private final @NonNull ArrayList<OpToUnrestrict> mOpsToIgnore = new ArrayList<>();
+        private final @NonNull ArrayList<OpToChange> mOpsToIgnore = new ArrayList<>();
 
         /**
          * All ops that need to be flipped to foreground.
@@ -406,7 +406,7 @@
          *
          * @see #syncPackages
          */
-        private final @NonNull ArrayList<OpToUnrestrict> mOpsToForeground = new ArrayList<>();
+        private final @NonNull ArrayList<OpToChange> mOpsToForeground = new ArrayList<>();
 
         /**
          * All ops that need to be flipped to foreground if allow.
@@ -415,7 +415,7 @@
          *
          * @see #syncPackages
          */
-        private final @NonNull ArrayList<OpToUnrestrict> mOpsToForegroundIfAllow =
+        private final @NonNull ArrayList<OpToChange> mOpsToForegroundIfAllow =
                 new ArrayList<>();
 
         PermissionToOpSynchroniser(@NonNull Context context) {
@@ -432,38 +432,38 @@
         private void syncPackages() {
             final int allowCount = mOpsToAllow.size();
             for (int i = 0; i < allowCount; i++) {
-                final OpToUnrestrict op = mOpsToAllow.get(i);
+                final OpToChange op = mOpsToAllow.get(i);
                 setUidModeAllowed(op.code, op.uid, op.packageName);
             }
             final int allowIfDefaultCount = mOpsToAllowIfDefault.size();
             for (int i = 0; i < allowIfDefaultCount; i++) {
-                final OpToUnrestrict op = mOpsToAllowIfDefault.get(i);
+                final OpToChange op = mOpsToAllowIfDefault.get(i);
                 setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
             }
             final int foregroundCount = mOpsToForegroundIfAllow.size();
             for (int i = 0; i < foregroundCount; i++) {
-                final OpToUnrestrict op = mOpsToForegroundIfAllow.get(i);
+                final OpToChange op = mOpsToForegroundIfAllow.get(i);
                 setUidModeForegroundIfAllow(op.code, op.uid, op.packageName);
             }
             final int foregroundIfAllowCount = mOpsToForeground.size();
             for (int i = 0; i < foregroundIfAllowCount; i++) {
-                final OpToUnrestrict op = mOpsToForeground.get(i);
+                final OpToChange op = mOpsToForeground.get(i);
                 setUidModeForeground(op.code, op.uid, op.packageName);
             }
             final int ignoreCount = mOpsToIgnore.size();
             for (int i = 0; i < ignoreCount; i++) {
-                final OpToUnrestrict op = mOpsToIgnore.get(i);
+                final OpToChange op = mOpsToIgnore.get(i);
                 setUidModeIgnored(op.code, op.uid, op.packageName);
             }
             final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
             for (int i = 0; i < ignoreIfDefaultCount; i++) {
-                final OpToUnrestrict op = mOpsToIgnoreIfDefault.get(i);
+                final OpToChange op = mOpsToIgnoreIfDefault.get(i);
                 setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
             }
             final int defaultCount = mOpsToDefault.size();
             for (int i = 0; i < defaultCount; i++) {
-                final OpToRestrict op = mOpsToDefault.get(i);
-                setUidModeDefault(op.code, op.uid);
+                final OpToChange op = mOpsToDefault.get(i);
+                setUidModeDefault(op.code, op.uid, op.packageName);
             }
         }
 
@@ -493,9 +493,9 @@
             if (permissionInfo.isHardRestricted()) {
                 if (opCode != OP_NONE) {
                     if (applyRestriction) {
-                        mOpsToDefault.add(new OpToRestrict(uid, opCode));
+                        mOpsToDefault.add(new OpToChange(uid, pkg.packageName, opCode));
                     } else {
-                        mOpsToAllowIfDefault.add(new OpToUnrestrict(uid, pkg.packageName, opCode));
+                        mOpsToAllowIfDefault.add(new OpToChange(uid, pkg.packageName, opCode));
                     }
                 }
             } else if (permissionInfo.isSoftRestricted()) {
@@ -505,9 +505,9 @@
 
                 if (opCode != OP_NONE) {
                     if (policy.canBeGranted()) {
-                        mOpsToAllowIfDefault.add(new OpToUnrestrict(uid, pkg.packageName, opCode));
+                        mOpsToAllowIfDefault.add(new OpToChange(uid, pkg.packageName, opCode));
                     } else {
-                        mOpsToDefault.add(new OpToRestrict(uid, opCode));
+                        mOpsToDefault.add(new OpToChange(uid, pkg.packageName, opCode));
                     }
                 }
 
@@ -515,15 +515,14 @@
                 if (op != OP_NONE) {
                     switch (policy.getDesiredOpMode()) {
                         case MODE_DEFAULT:
-                            mOpsToDefault.add(new OpToRestrict(uid, op));
+                            mOpsToDefault.add(new OpToChange(uid, pkg.packageName, op));
                             break;
                         case MODE_ALLOWED:
                             if (policy.shouldSetAppOpIfNotDefault()) {
-                                mOpsToAllow.add(new OpToUnrestrict(uid, pkg.packageName, op));
+                                mOpsToAllow.add(new OpToChange(uid, pkg.packageName, op));
                             } else {
                                 mOpsToAllowIfDefault.add(
-                                        new OpToUnrestrict(uid, pkg.packageName,
-                                                op));
+                                        new OpToChange(uid, pkg.packageName, op));
                             }
                             break;
                         case MODE_FOREGROUND:
@@ -532,10 +531,10 @@
                             break;
                         case MODE_IGNORED:
                             if (policy.shouldSetAppOpIfNotDefault()) {
-                                mOpsToIgnore.add(new OpToUnrestrict(uid, pkg.packageName, op));
+                                mOpsToIgnore.add(new OpToChange(uid, pkg.packageName, op));
                             } else {
                                 mOpsToIgnoreIfDefault.add(
-                                        new OpToUnrestrict(uid, pkg.packageName,
+                                        new OpToChange(uid, pkg.packageName,
                                                 op));
                             }
                             break;
@@ -597,7 +596,7 @@
 
                 if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) == 0
                         && isBgPermRestricted(pkgName, bgPermissionName, uid)) {
-                    mOpsToForegroundIfAllow.add(new OpToUnrestrict(uid, pkgName, opCode));
+                    mOpsToForegroundIfAllow.add(new OpToChange(uid, pkgName, opCode));
                 }
 
                 return;
@@ -611,12 +610,12 @@
                         pkgName) == PackageManager.PERMISSION_GRANTED;
 
                 if (!isBgHardRestricted && isBgPermGranted) {
-                    mOpsToAllow.add(new OpToUnrestrict(uid, pkgName, opCode));
+                    mOpsToAllow.add(new OpToChange(uid, pkgName, opCode));
                 } else {
-                    mOpsToForeground.add(new OpToUnrestrict(uid, pkgName, opCode));
+                    mOpsToForeground.add(new OpToChange(uid, pkgName, opCode));
                 }
             } else {
-                mOpsToIgnore.add(new OpToUnrestrict(uid, pkgName, opCode));
+                mOpsToIgnore.add(new OpToChange(uid, pkgName, opCode));
             }
         }
 
@@ -703,26 +702,16 @@
             }
         }
 
-        private void setUidModeDefault(int opCode, int uid) {
-            mAppOpsManager.setUidMode(opCode, uid, MODE_DEFAULT);
+        private void setUidModeDefault(int opCode, int uid, String packageName) {
+            setUidMode(opCode, uid, MODE_DEFAULT, packageName);
         }
 
-        private class OpToRestrict {
-            final int uid;
-            final int code;
-
-            OpToRestrict(int uid, int code) {
-                this.uid = uid;
-                this.code = code;
-            }
-        }
-
-        private class OpToUnrestrict {
+        private class OpToChange {
             final int uid;
             final @NonNull String packageName;
             final int code;
 
-            OpToUnrestrict(int uid, @NonNull String packageName, int code) {
+            OpToChange(int uid, @NonNull String packageName, int code) {
                 this.uid = uid;
                 this.packageName = packageName;
                 this.code = code;