Add a Method to Revoke DefaultGrant Permissions

Runtime permissions grants for system-bound
services should be revoked when no longer needed.
This ensures that in cases where say, a package
is needed while a user is using a certain cellular
provider, that package will lose its privileges
if the user changes providers.

Bug: 66955045
Test: compilation (still WIP)
Change-Id: I8dc2dd719f3b4af83ebb2b2f4a128f267b26fd91
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 83fe1c9..6f1a83e 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -1082,6 +1082,51 @@
         grantRuntimePermissions(pkg, permissions, systemFixed, false, userId);
     }
 
+    private void revokeRuntimePermissions(PackageParser.Package pkg, Set<String> permissions,
+            boolean systemFixed, int userId) {
+        if (pkg.requestedPermissions.isEmpty()) {
+            return;
+        }
+        Set<String> revokablePermissions = new ArraySet<>(pkg.requestedPermissions);
+
+        for (String permission : permissions) {
+            // We can't revoke what wasn't requested.
+            if (!revokablePermissions.contains(permission)) {
+                continue;
+            }
+
+            final int flags = mServiceInternal.getPermissionFlagsTEMP(
+                    permission, pkg.packageName, userId);
+
+            // We didn't get this through the default grant policy. Move along.
+            if ((flags & PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT) == 0) {
+                continue;
+            }
+            // We aren't going to clobber device policy with a DefaultGrant.
+            if ((flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
+                continue;
+            }
+            // Do not revoke system fixed permissions unless caller set them that way;
+            // there is no refcount for the number of sources of this, so there
+            // should be at most one grantor doing SYSTEM_FIXED for any given package.
+            if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0 && !systemFixed) {
+                continue;
+            }
+            mServiceInternal.revokeRuntimePermission(pkg.packageName, permission, userId, false);
+
+            if (DEBUG) {
+                Log.i(TAG, "revoked " + (systemFixed ? "fixed " : "not fixed ")
+                        + permission + " to " + pkg.packageName);
+            }
+
+            // Remove the GRANTED_BY_DEFAULT flag without touching the others.
+            // Note that we do not revoke FLAG_PERMISSION_SYSTEM_FIXED. That bit remains
+            // sticky once set.
+            mServiceInternal.updatePermissionFlagsTEMP(permission, pkg.packageName,
+                    PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT, 0, userId);
+        }
+    }
+
     private void grantRuntimePermissions(PackageParser.Package pkg, Set<String> permissions,
             boolean systemFixed, boolean ignoreSystemPackage, int userId) {
         if (pkg.requestedPermissions.isEmpty()) {
@@ -1132,10 +1177,10 @@
                 // to make sure we can grant the needed permission to the default
                 // sms and phone apps after the user chooses this in the UI.
                 if (flags == 0 || ignoreSystemPackage) {
-                    // Never clobber policy or system.
-                    final int fixedFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
-                            | PackageManager.FLAG_PERMISSION_POLICY_FIXED;
-                    if ((flags & fixedFlags) != 0) {
+                    // Never clobber policy fixed permissions.
+                    // We must allow the grant of a system-fixed permission because
+                    // system-fixed is sticky, but the permission itself may be revoked.
+                    if ((flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
                         continue;
                     }