Check for fixed permissions when restoring notification permissions

Ensure that REVIEW_REQUIRED is not set on system or policy fixed
permissions, or on GRANTED_BY_DEFAULT and GRANTED_BY_ROLE permissions.
Also removes Droidfooder-only state

Fixes: 218593876
Test: PermissionHelperTest
Change-Id: Ia830aa0fe4e60292d5808f29f126392e52883596
diff --git a/services/core/java/com/android/server/notification/PermissionHelper.java b/services/core/java/com/android/server/notification/PermissionHelper.java
index 86ac7c1..d80d9f3 100644
--- a/services/core/java/com/android/server/notification/PermissionHelper.java
+++ b/services/core/java/com/android/server/notification/PermissionHelper.java
@@ -178,6 +178,12 @@
             boolean userSet, boolean reviewRequired) {
         assertFlag();
         final long callingId = Binder.clearCallingIdentity();
+        // Do not change fixed permissions, and do not change non-user set permissions that are
+        // granted by default, or granted by role.
+        if (isPermissionFixed(packageName, userId)
+                || (isPermissionGrantedByDefaultOrRole(packageName, userId) && !userSet)) {
+            return;
+        }
         try {
             if (grant && !reviewRequired) {
                 mPermManager.grantRuntimePermission(packageName, NOTIFICATION_PERMISSION, userId);
@@ -252,6 +258,24 @@
         }
     }
 
+    boolean isPermissionGrantedByDefaultOrRole(String packageName, @UserIdInt int userId) {
+        assertFlag();
+        final long callingId = Binder.clearCallingIdentity();
+        try {
+            try {
+                int flags = mPermManager.getPermissionFlags(packageName, NOTIFICATION_PERMISSION,
+                        userId);
+                return (flags & (PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT
+                        | PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE)) != 0;
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Could not reach system server", e);
+            }
+            return false;
+        } finally {
+            Binder.restoreCallingIdentity(callingId);
+        }
+    }
+
     private void assertFlag() {
         if (!mMigrationEnabled) {
             throw new IllegalStateException("Method called without checking flag value");
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index e9074c4..8c3466e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -3170,44 +3170,12 @@
                     inheritPermissionStateToNewImplicitPermissionLocked(sourcePerms, newPerm, ps,
                             pkg);
                 }
-            } else if (NOTIFICATION_PERMISSIONS.contains(newPerm)) {
-                //&& (origPs.getPermissionState(newPerm) == null) {
-                // TODO(b/205888750): add back line about origPs once all TODO sections below are
-                //  propagated through droidfood
-                Permission bp = mRegistry.getPermission(newPerm);
-                if (bp == null) {
-                    throw new IllegalStateException("Unknown new permission " + newPerm);
-                }
-                if (!isUserSetOrPregrantedOrFixed(ps.getPermissionFlags(newPerm))) {
-                    updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
-                    int setFlag = ps.isPermissionGranted(newPerm)
-                            ? 0 : FLAG_PERMISSION_REVIEW_REQUIRED;
-                    ps.updatePermissionFlags(bp, FLAG_PERMISSION_REVIEW_REQUIRED, setFlag);
-                    // TODO(b/205888750): remove if/else block once propagated through droidfood
-                    if (ps.isPermissionGranted(newPerm)
-                            && pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M) {
-                        ps.revokePermission(bp);
-                    } else if (!ps.isPermissionGranted(newPerm)
-                            && pkg.getTargetSdkVersion() < Build.VERSION_CODES.M) {
-                        ps.grantPermission(bp);
-                    }
-                } else {
-                    // TODO(b/205888750): remove once propagated through droidfood
-                    ps.updatePermissionFlags(bp, FLAG_PERMISSION_REVOKE_WHEN_REQUESTED
-                            | FLAG_PERMISSION_REVIEW_REQUIRED, 0);
-                }
             }
         }
 
         return updatedUserIds;
     }
 
-    private boolean isUserSetOrPregrantedOrFixed(int flags) {
-        return (flags & (FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_USER_FIXED
-                | FLAG_PERMISSION_POLICY_FIXED | FLAG_PERMISSION_SYSTEM_FIXED
-                | FLAG_PERMISSION_GRANTED_BY_DEFAULT | FLAG_PERMISSION_GRANTED_BY_ROLE)) != 0;
-    }
-
     @NonNull
     @Override
     public List<SplitPermissionInfoParcelable> getSplitPermissions() {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
index a3440b4..b71323b4 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PermissionHelperTest.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.notification;
 
+import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
 import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
@@ -252,6 +253,39 @@
     }
 
     @Test
+    public void testSetNotificationPermission_pkgPerm_notUserSet_grantedByDefaultPermNotSet()
+            throws Exception {
+        when(mPermManager.getPermissionFlags(anyString(),
+                eq(Manifest.permission.POST_NOTIFICATIONS),
+                anyInt())).thenReturn(FLAG_PERMISSION_GRANTED_BY_DEFAULT);
+        PermissionHelper.PackagePermission pkgPerm = new PermissionHelper.PackagePermission(
+                "pkg", 10, true, false);
+
+        mPermissionHelper.setNotificationPermission(pkgPerm);
+        verify(mPermManager, never()).revokeRuntimePermission(
+                anyString(), anyString(), anyInt(), anyString());
+        verify(mPermManager, never()).updatePermissionFlags(
+                anyString(), anyString(), anyInt(), anyInt(), anyBoolean(), anyInt());
+    }
+
+    @Test
+    public void testSetNotificationPermission_pkgPerm_userSet_grantedByDefaultPermSet()
+            throws Exception {
+        when(mPermManager.getPermissionFlags(anyString(),
+                eq(Manifest.permission.POST_NOTIFICATIONS),
+                anyInt())).thenReturn(FLAG_PERMISSION_GRANTED_BY_DEFAULT);
+        PermissionHelper.PackagePermission pkgPerm = new PermissionHelper.PackagePermission(
+                "pkg", 10, true, true);
+
+        mPermissionHelper.setNotificationPermission(pkgPerm);
+        verify(mPermManager).grantRuntimePermission(
+                "pkg", Manifest.permission.POST_NOTIFICATIONS, 10);
+        verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
+                FLAG_PERMISSION_USER_SET | FLAG_PERMISSION_REVIEW_REQUIRED,
+                FLAG_PERMISSION_USER_SET, true, 10);
+    }
+
+    @Test
     public void testSetNotificationPermission_revokeUserSet() throws Exception {
         mPermissionHelper.setNotificationPermission("pkg", 10, false, true);
 
@@ -283,6 +317,32 @@
     }
 
     @Test
+    public void testSetNotificationPermission_SystemFixedPermNotSet() throws Exception {
+        when(mPermManager.getPermissionFlags(anyString(),
+                eq(Manifest.permission.POST_NOTIFICATIONS),
+                anyInt())).thenReturn(FLAG_PERMISSION_SYSTEM_FIXED);
+
+        mPermissionHelper.setNotificationPermission("pkg", 10, false, true);
+        verify(mPermManager, never()).revokeRuntimePermission(
+                anyString(), anyString(), anyInt(), anyString());
+        verify(mPermManager, never()).updatePermissionFlags(
+                anyString(), anyString(), anyInt(), anyInt(), anyBoolean(), anyInt());
+    }
+
+    @Test
+    public void testSetNotificationPermission_PolicyFixedPermNotSet() throws Exception {
+        when(mPermManager.getPermissionFlags(anyString(),
+                eq(Manifest.permission.POST_NOTIFICATIONS),
+                anyInt())).thenReturn(FLAG_PERMISSION_POLICY_FIXED);
+
+        mPermissionHelper.setNotificationPermission("pkg", 10, false, true);
+        verify(mPermManager, never()).revokeRuntimePermission(
+                anyString(), anyString(), anyInt(), anyString());
+        verify(mPermManager, never()).updatePermissionFlags(
+                anyString(), anyString(), anyInt(), anyInt(), anyBoolean(), anyInt());
+    }
+
+    @Test
     public void testIsPermissionFixed() throws Exception {
         when(mPermManager.getPermissionFlags(anyString(),
                 eq(Manifest.permission.POST_NOTIFICATIONS),