Merge "Don't allow the shell to change admin-locked app permissions."
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index f5bcf64..da4eb2d 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -168,4 +168,25 @@
      * @return Whether was launched.
      */
     public abstract boolean wasPackageEverLaunched(String packageName, int userId);
+
+    /**
+     * Grants a runtime permission
+     * @param packageName The package name.
+     * @param name The name of the permission.
+     * @param userId The userId for which to grant the permission.
+     * @param overridePolicy If true, grant this permission even if it is fixed by policy.
+     */
+    public abstract void grantRuntimePermission(String packageName, String name, int userId,
+            boolean overridePolicy);
+
+    /**
+     * Revokes a runtime permission
+     * @param packageName The package name.
+     * @param name The name of the permission.
+     * @param userId The userId for which to revoke the permission.
+     * @param overridePolicy If true, revoke this permission even if it is fixed by policy.
+     */
+    public abstract void revokeRuntimePermission(String packageName, String name, int userId,
+            boolean overridePolicy);
+
 }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index df02b86..c70963f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -4013,6 +4013,11 @@
 
     @Override
     public void grantRuntimePermission(String packageName, String name, final int userId) {
+        grantRuntimePermission(packageName, name, userId, false /* Only if not fixed by policy */);
+    }
+
+    private void grantRuntimePermission(String packageName, String name, final int userId,
+            boolean overridePolicy) {
         if (!sUserManager.exists(userId)) {
             Log.e(TAG, "No such user:" + userId);
             return;
@@ -4065,6 +4070,10 @@
                 throw new SecurityException("Cannot grant system fixed permission "
                         + name + " for package " + packageName);
             }
+            if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
+                throw new SecurityException("Cannot grant policy fixed permission "
+                        + name + " for package " + packageName);
+            }
 
             if (bp.isDevelopment()) {
                 // Development permissions must be handled specially, since they are not
@@ -4125,6 +4134,11 @@
 
     @Override
     public void revokeRuntimePermission(String packageName, String name, int userId) {
+        revokeRuntimePermission(packageName, name, userId, false /* Only if not fixed by policy */);
+    }
+
+    private void revokeRuntimePermission(String packageName, String name, int userId,
+            boolean overridePolicy) {
         if (!sUserManager.exists(userId)) {
             Log.e(TAG, "No such user:" + userId);
             return;
@@ -4175,6 +4189,10 @@
                 throw new SecurityException("Cannot revoke system fixed permission "
                         + name + " for package " + packageName);
             }
+            if (!overridePolicy && (flags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) {
+                throw new SecurityException("Cannot revoke policy fixed permission "
+                        + name + " for package " + packageName);
+            }
 
             if (bp.isDevelopment()) {
                 // Development permissions must be handled specially, since they are not
@@ -21141,6 +21159,20 @@
                 return mSettings.wasPackageEverLaunchedLPr(packageName, userId);
             }
         }
+
+        @Override
+        public void grantRuntimePermission(String packageName, String name, int userId,
+                boolean overridePolicy) {
+            PackageManagerService.this.grantRuntimePermission(packageName, name, userId,
+                    overridePolicy);
+        }
+
+        @Override
+        public void revokeRuntimePermission(String packageName, String name, int userId,
+                boolean overridePolicy) {
+            PackageManagerService.this.revokeRuntimePermission(packageName, name, userId,
+                    overridePolicy);
+        }
     }
 
     @Override
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 0c57179..e7772f3 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8540,15 +8540,16 @@
                 final PackageManager packageManager = mContext.getPackageManager();
                 switch (grantState) {
                     case DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED: {
-                        packageManager.grantRuntimePermission(packageName, permission, user);
+                        mInjector.getPackageManagerInternal().grantRuntimePermission(packageName,
+                                permission, user.getIdentifier(), true /* override policy */);
                         packageManager.updatePermissionFlags(permission, packageName,
                                 PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                                 PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);
                     } break;
 
                     case DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED: {
-                        packageManager.revokeRuntimePermission(packageName,
-                                permission, user);
+                        mInjector.getPackageManagerInternal().revokeRuntimePermission(packageName,
+                                permission, user.getIdentifier(), true /* override policy */);
                         packageManager.updatePermissionFlags(permission, packageName,
                                 PackageManager.FLAG_PERMISSION_POLICY_FIXED,
                                 PackageManager.FLAG_PERMISSION_POLICY_FIXED, user);