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

Commit 0f3bd201 authored by Hai Zhang's avatar Hai Zhang
Browse files

Second batch of permission in-process API refactoring.

- Refactored isPermissionReviewRequired(),
  grantRequestedRuntimePermissions(),
  setAllowlistedRestrictedPermissions(), and setAutoRevokeExempted(),

- Added javadoc for the methods, and refactor the parameter types to
  conform with API guidelines.

- The methods are taking an int array of user IDs because they
  are (mostly) used in handlePackagePostInstall, where the install can
  happen for multiple users at once, and allowing the API
  implementation to handle multiple users at once allows optimization,
  namely calling restorePermissionState() only once for all users.

- Fixed the bug that auto revoke exemption could only be set for the
  primary users post install, but not non-primary users.

- Renamed the methods to be inclusive, replacing the term with
  allowlist. However setAutoRevokeAllowlisted() is a bit confusing so
  I'm renaming it to setAutoRevokeExempted().

- Removed the callingUid parameter from the methods. Since the methods
  were called from handlePackagePostInstall(), which is called by a
  handler thread upon receiving the corresponding message, it is
  basically useless and for two methods we were already passing
  Process.myUid().

- Renamed/Created the API implementation methods, so that *Internal()
  methods perform no checks, whereas non-internal ones perform checks.

Bug: 158736025
Test: presubmit
Change-Id: I6965e2c715bc65ddb8e2aa51c03ccb1031c3a161
parent 65d46e9b
Loading
Loading
Loading
Loading
+19 −21
Original line number Diff line number Diff line
@@ -2214,14 +2214,15 @@ public class PackageManagerService extends IPackageManager.Stub
            // that the installer requested to be granted at install time.
            if (whitelistedRestrictedPermissions != null
                    && !whitelistedRestrictedPermissions.isEmpty()) {
                mPermissionManager.setWhitelistedRestrictedPermissions(
                        res.pkg, res.newUsers, whitelistedRestrictedPermissions,
                        Process.myUid(), FLAG_PERMISSION_WHITELIST_INSTALLER);
                mPermissionManager.setAllowlistedRestrictedPermissions(res.pkg,
                        whitelistedRestrictedPermissions, FLAG_PERMISSION_WHITELIST_INSTALLER,
                        res.newUsers);
            }
            if (autoRevokePermissionsMode == MODE_ALLOWED || autoRevokePermissionsMode == MODE_IGNORED) {
                mPermissionManager.setAutoRevokeWhitelisted(res.pkg.getPackageName(),
                        autoRevokePermissionsMode == MODE_IGNORED, UserHandle.myUserId());
            if (autoRevokePermissionsMode == MODE_ALLOWED
                    || autoRevokePermissionsMode == MODE_IGNORED) {
                mPermissionManager.setAutoRevokeExempted(res.pkg,
                        autoRevokePermissionsMode == MODE_IGNORED, res.newUsers);
            }
            // Now that we successfully installed the package, grant runtime
@@ -2231,8 +2232,9 @@ public class PackageManagerService extends IPackageManager.Stub
            // legacy apps.
            if (grantPermissions) {
                final int callingUid = Binder.getCallingUid();
                mPermissionManager.grantRequestedRuntimePermissions(
                        res.pkg, res.newUsers, grantedPermissions, callingUid);
                mPermissionManager.grantRequestedRuntimePermissions(res.pkg,
                        grantedPermissions != null ? Arrays.asList(grantedPermissions) : null,
                        res.newUsers);
            }
            final String installerPackageName =
@@ -13546,12 +13548,15 @@ public class PackageManagerService extends IPackageManager.Stub
            }
            if (installed) {
                if (pkgSetting.pkg != null) {
                    if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS)
                        != 0 && pkgSetting.pkg != null) {
                            != 0) {
                        whiteListedPermissions = pkgSetting.pkg.getRequestedPermissions();
                    }
                mPermissionManager.setWhitelistedRestrictedPermissions(packageName,
                        whiteListedPermissions, FLAG_PERMISSION_WHITELIST_INSTALLER, userId);
                    mPermissionManager.setAllowlistedRestrictedPermissions(pkgSetting.pkg,
                            whiteListedPermissions, FLAG_PERMISSION_WHITELIST_INSTALLER,
                            new int[] { userId });
                }
                if (pkgSetting.pkg != null) {
                    synchronized (mInstallLock) {
@@ -25023,14 +25028,7 @@ public class PackageManagerService extends IPackageManager.Stub
        @Override
        public boolean isPermissionsReviewRequired(String packageName, int userId) {
            synchronized (mLock) {
                final AndroidPackage pkg = mPackages.get(packageName);
                if (pkg == null) {
                    return false;
                }
                return mPermissionManager.isPermissionsReviewRequired(pkg, userId);
            }
            return mPermissionManager.isPermissionsReviewRequired(packageName, userId);
        }
        @Override
+74 −58
Original line number Diff line number Diff line
@@ -1293,7 +1293,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
    public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
            @NonNull String permName, @PermissionWhitelistFlags int flags,
            @UserIdInt int userId) {
        // Other argument checks are done in get/setWhitelistedRestrictedPermissions
        // Other argument checks are done in get/setAllowlistedRestrictedPermissions
        Objects.requireNonNull(permName);

        if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permName)) {
@@ -1307,7 +1307,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        }
        if (permissions.indexOf(permName) < 0) {
            permissions.add(permName);
            return setWhitelistedRestrictedPermissionsInternal(packageName, permissions,
            return setAllowlistedRestrictedPermissions(packageName, permissions,
                    flags, userId);
        }
        return false;
@@ -1338,7 +1338,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
    public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
            @NonNull String permName, @PermissionWhitelistFlags int flags,
            @UserIdInt int userId) {
        // Other argument checks are done in get/setWhitelistedRestrictedPermissions
        // Other argument checks are done in get/setAllowlistedRestrictedPermissions
        Objects.requireNonNull(permName);

        if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permName)) {
@@ -1348,13 +1348,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        final List<String> permissions =
                getWhitelistedRestrictedPermissions(packageName, flags, userId);
        if (permissions != null && permissions.remove(permName)) {
            return setWhitelistedRestrictedPermissionsInternal(packageName, permissions,
            return setAllowlistedRestrictedPermissions(packageName, permissions,
                    flags, userId);
        }
        return false;
    }

    private boolean setWhitelistedRestrictedPermissionsInternal(@NonNull String packageName,
    private boolean setAllowlistedRestrictedPermissions(@NonNull String packageName,
            @Nullable List<String> permissions, @PermissionWhitelistFlags int flags,
            @UserIdInt int userId) {
        Objects.requireNonNull(packageName);
@@ -1369,7 +1369,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        if (UserHandle.getCallingUserId() != userId) {
            mContext.enforceCallingOrSelfPermission(
                    Manifest.permission.INTERACT_ACROSS_USERS,
                    "setWhitelistedRestrictedPermissions for user " + userId);
                    "setAllowlistedRestrictedPermissions for user " + userId);
        }

        final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
@@ -1431,8 +1431,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {

        final long identity = Binder.clearCallingIdentity();
        try {
            setWhitelistedRestrictedPermissionsForUsers(pkg, new int[]{ userId }, permissions,
                    Process.myUid(), flags, mDefaultPermissionCallback);
            setAllowlistedRestrictedPermissionsInternal(pkg, permissions, flags,
                    new int[] { userId });
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
@@ -1447,25 +1447,34 @@ public class PermissionManagerService extends IPermissionManager.Stub {

        final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
        final int callingUid = Binder.getCallingUid();
        final int packageUid = UserHandle.getUid(userId, pkg.getUid());

        if (!checkAutoRevokeAccess(pkg, callingUid)) {
            return false;
        }

        if (mAppOpsManager
                .checkOpNoThrow(AppOpsManager.OP_AUTO_REVOKE_MANAGED_BY_INSTALLER,
                        packageUid, packageName)
                != MODE_ALLOWED) {
        return setAutoRevokeExemptedInternal(pkg, whitelisted, userId);
    }

    private void setAutoRevokeExemptedInternal(@NonNull AndroidPackage pkg, boolean exempted,
            @NonNull int[] userIds) {
        for (final int userId : userIds) {
            setAutoRevokeExemptedInternal(pkg, exempted, userId);
        }
    }

    private boolean setAutoRevokeExemptedInternal(@NonNull AndroidPackage pkg, boolean exempted,
            @UserIdInt int userId) {
        final int packageUid = UserHandle.getUid(userId, pkg.getUid());
        if (mAppOpsManager.checkOpNoThrow(AppOpsManager.OP_AUTO_REVOKE_MANAGED_BY_INSTALLER,
                packageUid, pkg.getPackageName()) != MODE_ALLOWED) {
            // Whitelist user set - don't override
            return false;
        }

        final long identity = Binder.clearCallingIdentity();
        try {
            mAppOpsManager.setMode(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED,
                    packageUid, packageName,
                    whitelisted ? MODE_IGNORED : MODE_ALLOWED);
            mAppOpsManager.setMode(AppOpsManager.OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED, packageUid,
                    pkg.getPackageName(), exempted ? MODE_IGNORED : MODE_ALLOWED);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
@@ -3741,8 +3750,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        return false;
    }

    private boolean isPermissionsReviewRequired(@NonNull AndroidPackage pkg,
    private boolean isPermissionsReviewRequiredInternal(@NonNull String packageName,
            @UserIdInt int userId) {
        final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);
        if (pkg == null) {
            return false;
        }

        // Permission review applies only to apps not supporting the new permission model.
        if (pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M) {
            return false;
@@ -3756,20 +3770,19 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                        + userId);
                return false;
            }
            return uidState.isPermissionReviewRequired();
            return uidState.isPermissionsReviewRequired();
        }
    }

    private void grantRequestedRuntimePermissions(AndroidPackage pkg, int[] userIds,
            String[] grantedPermissions, int callingUid, PermissionCallback callback) {
    private void grantRequestedRuntimePermissionsInternal(@NonNull AndroidPackage pkg,
            @Nullable List<String> permissions, @NonNull int[] userIds) {
        for (int userId : userIds) {
            grantRequestedRuntimePermissionsForUser(pkg, userId, grantedPermissions, callingUid,
                    callback);
            grantRequestedRuntimePermissionsForUser(pkg, permissions, userId);
        }
    }

    private void grantRequestedRuntimePermissionsForUser(AndroidPackage pkg, int userId,
            String[] grantedPermissions, int callingUid, PermissionCallback callback) {
    private void grantRequestedRuntimePermissionsForUser(@NonNull AndroidPackage pkg,
            @Nullable List<String> permissions, int userId) {
        final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
                | PackageManager.FLAG_PERMISSION_POLICY_FIXED;

@@ -3781,6 +3794,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {

        final boolean instantApp = mPackageManagerInt.isInstantApp(pkg.getPackageName(), userId);

        final int myUid = Process.myUid();

        for (String permission : pkg.getRequestedPermissions()) {
            final boolean shouldGrantPermission;
            synchronized (mLock) {
@@ -3788,36 +3803,36 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                shouldGrantPermission = bp != null && (bp.isRuntime() || bp.isDevelopment())
                        && (!instantApp || bp.isInstant())
                        && (supportsRuntimePermissions || !bp.isRuntimeOnly())
                        && (grantedPermissions == null
                                || ArrayUtils.contains(grantedPermissions, permission));
                        && (permissions == null || permissions.contains(permission));
            }
            if (shouldGrantPermission) {
                final int flags = getPermissionFlagsInternal(permission, pkg.getPackageName(),
                        callingUid, userId);
                        myUid, userId);
                if (supportsRuntimePermissions) {
                    // Installer cannot change immutable permissions.
                    if ((flags & immutableFlags) == 0) {
                        grantRuntimePermissionInternal(permission, pkg.getPackageName(), false,
                                callingUid, userId, callback);
                                myUid, userId, mDefaultPermissionCallback);
                    }
                } else {
                    // In permission review mode we clear the review flag and the revoked compat
                    // flag when we are asked to install the app with all permissions granted.
                    if ((flags & compatFlags) != 0) {
                        updatePermissionFlagsInternal(permission, pkg.getPackageName(), compatFlags,
                                0, callingUid, userId, false, callback);
                                0, myUid, userId, false, mDefaultPermissionCallback);
                    }
                }
            }
        }
    }

    private void setWhitelistedRestrictedPermissionsForUsers(@NonNull AndroidPackage pkg,
            @UserIdInt int[] userIds, @Nullable List<String> permissions, int callingUid,
            @PermissionWhitelistFlags int whitelistFlags, PermissionCallback callback) {
    private void setAllowlistedRestrictedPermissionsInternal(@NonNull AndroidPackage pkg,
            @Nullable List<String> permissions, @PermissionWhitelistFlags int allowlistFlags,
            @UserIdInt int[] userIds) {
        SparseArray<ArraySet<String>> oldGrantedRestrictedPermissions = new SparseArray<>();
        boolean updatePermissions = false;
        final int permissionCount = pkg.getRequestedPermissions().size();
        final int myUid = Process.myUid();

        for (int i = 0; i < userIds.length; i++) {
            int userId = userIds[i];
@@ -3849,11 +3864,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                }

                final int oldFlags = getPermissionFlagsInternal(permissionName,
                        pkg.getPackageName(), callingUid, userId);
                        pkg.getPackageName(), myUid, userId);

                int newFlags = oldFlags;
                int mask = 0;
                int whitelistFlagsCopy = whitelistFlags;
                int whitelistFlagsCopy = allowlistFlags;
                while (whitelistFlagsCopy != 0) {
                    final int flag = 1 << Integer.numberOfTrailingZeros(whitelistFlagsCopy);
                    whitelistFlagsCopy &= ~flag;
@@ -3928,13 +3943,13 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                }

                updatePermissionFlagsInternal(permissionName, pkg.getPackageName(), mask, newFlags,
                        callingUid, userId, false, null /*callback*/);
                        myUid, userId, false, null /*callback*/);
            }
        }

        if (updatePermissions) {
            // Update permission of this app to take into account the new whitelist state.
            restorePermissionState(pkg, false, pkg.getPackageName(), callback);
            restorePermissionState(pkg, false, pkg.getPackageName(), mDefaultPermissionCallback);

            // If this resulted in losing a permission we need to kill the app.
            for (int i = 0; i < userIds.length; i++) {
@@ -3959,7 +3974,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                        isGranted = uidState.isPermissionGranted(permissionName);
                    }
                    if (!isGranted) {
                        callback.onPermissionRevoked(pkg.getUid(), userId, null);
                        mDefaultPermissionCallback.onPermissionRevoked(pkg.getUid(), userId, null);
                        break;
                    }
                }
@@ -4987,10 +5002,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        public void systemReady() {
            PermissionManagerService.this.systemReady();
        }

        @Override
        public boolean isPermissionsReviewRequired(@NonNull AndroidPackage pkg,
        public boolean isPermissionsReviewRequired(@NonNull String packageName,
                @UserIdInt int userId) {
            return PermissionManagerService.this.isPermissionsReviewRequired(pkg, userId);
            Objects.requireNonNull(packageName, "packageName");
            // TODO(b/173235285): Some caller may pass USER_ALL as userId.
            //Preconditions.checkArgumentNonnegative(userId, "userId");
            return isPermissionsReviewRequiredInternal(packageName, userId);
        }

        @Override
@@ -5063,29 +5082,26 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            return PermissionManagerService.this.getAppOpPermissionPackagesInternal(permissionName);
        }
        @Override
        public void grantRequestedRuntimePermissions(AndroidPackage pkg, int[] userIds,
                String[] grantedPermissions, int callingUid) {
            PermissionManagerService.this.grantRequestedRuntimePermissions(
                    pkg, userIds, grantedPermissions, callingUid, mDefaultPermissionCallback);
        }
        @Override
        public void setWhitelistedRestrictedPermissions(@NonNull AndroidPackage pkg,
                @NonNull int[] userIds, @Nullable List<String> permissions, int callingUid,
                @PackageManager.PermissionWhitelistFlags int flags) {
            setWhitelistedRestrictedPermissionsForUsers(pkg, userIds, permissions,
                    callingUid, flags, mDefaultPermissionCallback);
        public void grantRequestedRuntimePermissions(@NonNull AndroidPackage pkg,
                @Nullable List<String> permissions, @NonNull int[] userIds) {
            Objects.requireNonNull(pkg, "pkg");
            Objects.requireNonNull(userIds, "userIds");
            grantRequestedRuntimePermissionsInternal(pkg, permissions, userIds);
        }
        @Override
        public void setWhitelistedRestrictedPermissions(String packageName,
                List<String> permissions, int flags, int userId) {
            PermissionManagerService.this.setWhitelistedRestrictedPermissionsInternal(
                    packageName, permissions, flags, userId);
        public void setAllowlistedRestrictedPermissions(@NonNull AndroidPackage pkg,
                @Nullable List<String> permissions, @PermissionWhitelistFlags int allowlistFlags,
                @NonNull int[] userIds) {
            Objects.requireNonNull(pkg, "pkg");
            Objects.requireNonNull(userIds, "userIds");
            setAllowlistedRestrictedPermissionsInternal(pkg, permissions, allowlistFlags, userIds);
        }
        @Override
        public void setAutoRevokeWhitelisted(
                @NonNull String packageName, boolean whitelisted, int userId) {
            PermissionManagerService.this.setAutoRevokeWhitelisted(
                    packageName, whitelisted, userId);
        public void setAutoRevokeExempted(@NonNull AndroidPackage pkg, boolean exempted,
                @NonNull int[] userIds) {
            Objects.requireNonNull(pkg, "pkg");
            Objects.requireNonNull(userIds, "userIds");
            setAutoRevokeExemptedInternal(pkg, exempted, userIds);
        }
        @Override
        public void updatePermissions(@NonNull String packageName, @Nullable AndroidPackage pkg) {
+44 −14
Original line number Diff line number Diff line
@@ -179,22 +179,52 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager

    public abstract void systemReady();

    public abstract boolean isPermissionsReviewRequired(@NonNull AndroidPackage pkg,
    /**
     * Get whether permission review is required for a package.
     *
     * @param packageName the name of the package
     * @param userId the user ID
     * @return whether permission review is required
     */
    //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
    public abstract boolean isPermissionsReviewRequired(@NonNull String packageName,
            @UserIdInt int userId);

    public abstract void grantRequestedRuntimePermissions(
            @NonNull AndroidPackage pkg, @NonNull int[] userIds,
            @NonNull String[] grantedPermissions, int callingUid);
    public abstract void setWhitelistedRestrictedPermissions(
            @NonNull AndroidPackage pkg, @NonNull int[] userIds,
            @NonNull List<String> permissions, int callingUid,
            @PackageManager.PermissionWhitelistFlags int whitelistFlags);
    /** Sets the allowlisted, restricted permissions for the given package. */
    public abstract void setWhitelistedRestrictedPermissions(
            @NonNull String packageName, @NonNull List<String> permissions,
            @PackageManager.PermissionWhitelistFlags int flags, int userId);
    public abstract void setAutoRevokeWhitelisted(
            @NonNull String packageName, boolean whitelisted, int userId);
    /**
     * Grant the requested runtime permissions for a package, or an explicit subset of them.
     *
     * @param pkg the package
     * @param permissions the names of the subset of permissions to be granted, or {@code null} for
     *                    granting all the requested permissions
     * @param userIds the user IDs
     */
    //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
    public abstract void grantRequestedRuntimePermissions(@NonNull AndroidPackage pkg,
            @Nullable List<String> permissions, @NonNull int[] userIds);

    /**
     * Set the allowlisted restricted permissions for a package, or an explicit subset of them.
     *
     * @param pkg the package
     * @param permissions the names of the subset of permissions to be allowlisted, or {@code null}
     *                    for allowlisting all the requested restricted permissions
     * @param userIds the user IDs
     */
    //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
    public abstract void setAllowlistedRestrictedPermissions(
            @NonNull AndroidPackage pkg, @Nullable List<String> permissions,
            @PackageManager.PermissionWhitelistFlags int allowlistFlags, @NonNull int[] userIds);

    /**
     * Set whether a package is exempted from auto revoke.
     *
     * @param pkg the package
     * @param exempted whether the package is exempted from auto revoke
     * @param userIds the user IDs
     */
    //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
    public abstract void setAutoRevokeExempted(@NonNull AndroidPackage pkg, boolean exempted,
            @NonNull int[] userIds);

    /**
     * Update permissions when a package changed.
+1 −1
Original line number Diff line number Diff line
@@ -308,7 +308,7 @@ public final class UidPermissionState {
        return anyChanged;
    }

    public boolean isPermissionReviewRequired() {
    public boolean isPermissionsReviewRequired() {
        if (mPermissions == null) {
            return false;
        }