Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 826767b9 authored by Nate Myren's avatar Nate Myren
Browse files

Add command to allow setting of some permission flags from shell

Add the "pm set/clear-permission-flags" adb commands, which will allow a
developer to set the USER_SET, USER_FIXED, REVIEW_REQUIRED,
REVOKED_COMPAT, and REVOKE_WHEN_REQUESTED flags via adb.

Test: manual
Fixes: 229321394
Change-Id: I6a85466ce25ce24eececde936214cfc033fafac0
parent f1f03b8f
Loading
Loading
Loading
Loading
+72 −0
Original line number Diff line number Diff line
@@ -17,6 +17,11 @@
package com.android.server.pm;

import static android.content.pm.PackageInstaller.LOCATION_DATA_APP;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;

import android.accounts.IAccountManager;
import android.annotation.NonNull;
@@ -92,6 +97,7 @@ import android.system.ErrnoException;
import android.system.Os;
import android.text.TextUtils;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IntArray;
import android.util.PrintWriterPrinter;
@@ -150,6 +156,17 @@ class PackageManagerShellCommand extends ShellCommand {
            "--multi-package"
    );
    private static final Set<String> UNSUPPORTED_SESSION_CREATE_OPTS = Collections.emptySet();
    private static final Map<String, Integer> SUPPORTED_PERMISSION_FLAGS = new ArrayMap<>();
    private static final List<String> SUPPORTED_PERMISSION_FLAGS_LIST;
    static {
        SUPPORTED_PERMISSION_FLAGS.put("user-set", FLAG_PERMISSION_USER_SET);
        SUPPORTED_PERMISSION_FLAGS.put("user-fixed", FLAG_PERMISSION_USER_FIXED);
        SUPPORTED_PERMISSION_FLAGS.put("revoked-compat", FLAG_PERMISSION_REVOKED_COMPAT);
        SUPPORTED_PERMISSION_FLAGS.put("review-required", FLAG_PERMISSION_REVIEW_REQUIRED);
        SUPPORTED_PERMISSION_FLAGS.put("revoke-when-requested",
                FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
        SUPPORTED_PERMISSION_FLAGS_LIST = new ArrayList<>(SUPPORTED_PERMISSION_FLAGS.keySet());
    }

    final IPackageManager mInterface;
    final LegacyPermissionManagerInternal mLegacyPermissionManager;
@@ -276,6 +293,10 @@ class PackageManagerShellCommand extends ShellCommand {
                    return runGrantRevokePermission(false);
                case "reset-permissions":
                    return runResetPermissions();
                case "set-permission-flags":
                    return setOrClearPermissionFlags(true);
                case "clear-permission-flags":
                    return setOrClearPermissionFlags(false);
                case "set-permission-enforced":
                    return runSetPermissionEnforced();
                case "get-privapp-permissions":
@@ -2500,6 +2521,50 @@ class PackageManagerShellCommand extends ShellCommand {
        return 0;
    }

    private int setOrClearPermissionFlags(boolean setFlags) {
        int userId = UserHandle.USER_SYSTEM;

        String opt;
        while ((opt = getNextOption()) != null) {
            if (opt.equals("--user")) {
                userId = UserHandle.parseUserArg(getNextArgRequired());
            }
        }

        String pkg = getNextArg();
        if (pkg == null) {
            getErrPrintWriter().println("Error: no package specified");
            return 1;
        }
        String perm = getNextArg();
        if (perm == null) {
            getErrPrintWriter().println("Error: no permission specified");
            return 1;
        }

        int flagMask = 0;
        String flagName = getNextArg();
        if (flagName == null) {
            getErrPrintWriter().println("Error: no permission flags specified");
            return 1;
        }
        while (flagName != null) {
            if (!SUPPORTED_PERMISSION_FLAGS.containsKey(flagName)) {
                getErrPrintWriter().println("Error: specified flag " + flagName + " is not one of "
                        + SUPPORTED_PERMISSION_FLAGS_LIST);
                return 1;
            }
            flagMask |= SUPPORTED_PERMISSION_FLAGS.get(flagName);
            flagName = getNextArg();
        }

        final UserHandle translatedUser = UserHandle.of(translateUserId(userId,
                UserHandle.USER_NULL, "runGrantRevokePermission"));
        int flagSet = setFlags ? flagMask : 0;
        mPermissionManager.updatePermissionFlags(pkg, perm, flagMask, flagSet, translatedUser);
        return 0;
    }

    private int runSetPermissionEnforced() throws RemoteException {
        final String permission = getNextArg();
        if (permission == null) {
@@ -3997,6 +4062,13 @@ class PackageManagerShellCommand extends ShellCommand {
        pw.println("    must be declared as used in the app's manifest, be runtime permissions");
        pw.println("    (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
        pw.println("");
        pw.println("  set-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]");
        pw.println("  clear-permission-flags [--user USER_ID] PACKAGE PERMISSION [FLAGS..]");
        pw.println("    These commands either set or clear permission flags on apps.  The permissions");
        pw.println("    must be declared as used in the app's manifest, be runtime permissions");
        pw.println("    (protection level dangerous), and the app targeting SDK greater than Lollipop MR1.");
        pw.println("    The flags must be one or more of " + SUPPORTED_PERMISSION_FLAGS_LIST);
        pw.println("");
        pw.println("  reset-permissions");
        pw.println("    Revert all runtime permissions to their default state.");
        pw.println("");
+4 −2
Original line number Diff line number Diff line
@@ -761,8 +761,10 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
            flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
            flagValues &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
            flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
            // REVIEW_REQUIRED can only be set by non-system apps for for POST_NOTIFICATIONS
            if (!POST_NOTIFICATIONS.equals(permName)) {
            // REVIEW_REQUIRED can only be set by non-system apps for POST_NOTIFICATIONS, or by the
            // shell or root UID.
            if (!POST_NOTIFICATIONS.equals(permName) && callingUid != Process.SHELL_UID
                    && callingUid != Process.ROOT_UID) {
                flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
            }
        }