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

Commit 6b086884 authored by Hai Zhang's avatar Hai Zhang
Browse files

Revert "Revert "Replace permissions API with onPackageInstalled().""

This reverts commit 84ee067a.

Reason for revert: Fixed the issue where allowlisted restricted
permissions were removed upon package update due to the original
CL. This was caused by the fact that previously the allowlisted
permissions passed in by installer are used to replace the set of
existing allowlisted permissions, and this is inconsistent with the
granted permissions passed in by installer where we simply grant the
specified permissions instead of revoking permissions that weren't in
the list passed in. So I believe making the allowlisted permissions an
addition instead of replacement makes more sense and also solves the
issue.

The other change is that onPackageInstalled() is now called on a
per-user basis, because permission allowlist addition has to be done
per-user unlike the previous replacement. This also gives us a cleaner
API.

Bug: 158736025
Test: RestrictedStoragePermissionTest

Change-Id: I7a47afebf88406dc16f64942db6dcaff4e18ab75
parent d2ff4867
Loading
Loading
Loading
Loading
+23 −32
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import static android.Manifest.permission.MANAGE_DEVICE_ADMINS;
import static android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS;
import static android.Manifest.permission.REQUEST_DELETE_PACKAGES;
import static android.Manifest.permission.SET_HARMFUL_APP_WARNINGS;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.MODE_IGNORED;
import static android.content.Intent.ACTION_MAIN;
@@ -44,7 +43,6 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKED_COMPAT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER;
import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
import static android.content.pm.PackageManager.INSTALL_FAILED_BAD_PERMISSION_GROUP;
import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
@@ -2172,7 +2170,7 @@ public class PackageManagerService extends IPackageManager.Stub
    private void handlePackagePostInstall(PackageInstalledInfo res, boolean grantPermissions,
            boolean killApp, boolean virtualPreload,
            String[] grantedPermissions, List<String> whitelistedRestrictedPermissions,
            String[] grantedPermissions, List<String> allowlistedRestrictedPermissions,
            int autoRevokePermissionsMode,
            boolean launchedForRestore, String installerPackage,
            IPackageInstallObserver2 installObserver, int dataLoaderType) {
@@ -2205,31 +2203,22 @@ public class PackageManagerService extends IPackageManager.Stub
                res.removedInfo.sendPackageRemovedBroadcasts(killApp, false /*removedBySystem*/);
            }
            // Allowlist any restricted permissions first as some may be runtime
            // that the installer requested to be granted at install time.
            if (whitelistedRestrictedPermissions != null
                    && !whitelistedRestrictedPermissions.isEmpty()) {
                mPermissionManager.setAllowlistedRestrictedPermissions(res.pkg,
                        whitelistedRestrictedPermissions, FLAG_PERMISSION_WHITELIST_INSTALLER,
                        res.newUsers);
            final List<String> grantedPermissionsList;
            if (grantPermissions) {
                if (grantedPermissions != null) {
                    grantedPermissionsList = Arrays.asList(grantedPermissions);
                } else {
                    grantedPermissionsList = res.pkg.getRequestedPermissions();
                }
            if (autoRevokePermissionsMode == MODE_ALLOWED
                    || autoRevokePermissionsMode == MODE_IGNORED) {
                mPermissionManager.setAutoRevokeExempted(res.pkg,
                        autoRevokePermissionsMode == MODE_IGNORED, res.newUsers);
            } else {
                grantedPermissionsList = Collections.emptyList();
            }
            // Now that we successfully installed the package, grant runtime
            // permissions if requested before broadcasting the install. Also
            // for legacy apps in permission review mode we clear the permission
            // review flag which is used to emulate runtime permissions for
            // legacy apps.
            if (grantPermissions) {
                final int callingUid = Binder.getCallingUid();
                mPermissionManager.grantRequestedRuntimePermissions(res.pkg,
                        grantedPermissions != null ? Arrays.asList(grantedPermissions) : null,
                        res.newUsers);
            if (allowlistedRestrictedPermissions == null) {
                allowlistedRestrictedPermissions = Collections.emptyList();
            }
            for (final int userId : res.newUsers) {
                mPermissionManager.onPackageInstalled(res.pkg, grantedPermissionsList,
                        allowlistedRestrictedPermissions, autoRevokePermissionsMode, userId);
            }
            final String installerPackageName =
@@ -13609,11 +13598,12 @@ public class PackageManagerService extends IPackageManager.Stub
    int installExistingPackageAsUser(@Nullable String packageName, @UserIdInt int userId,
            @PackageManager.InstallFlags int installFlags,
            @PackageManager.InstallReason int installReason,
            @Nullable List<String> whiteListedPermissions, @Nullable IntentSender intentSender) {
            @Nullable List<String> allowlistedRestrictedPermissions,
            @Nullable IntentSender intentSender) {
        if (DEBUG_INSTALL) {
            Log.v(TAG, "installExistingPackageAsUser package=" + packageName + " userId=" + userId
                    + " installFlags=" + installFlags + " installReason=" + installReason
                    + " whiteListedPermissions=" + whiteListedPermissions);
                    + " allowlistedRestrictedPermissions=" + allowlistedRestrictedPermissions);
        }
        final int callingUid = Binder.getCallingUid();
@@ -13679,11 +13669,12 @@ public class PackageManagerService extends IPackageManager.Stub
                if (pkgSetting.pkg != null) {
                    if ((installFlags & PackageManager.INSTALL_ALL_WHITELIST_RESTRICTED_PERMISSIONS)
                            != 0) {
                        whiteListedPermissions = pkgSetting.pkg.getRequestedPermissions();
                        allowlistedRestrictedPermissions = pkgSetting.pkg.getRequestedPermissions();
                    } else if (allowlistedRestrictedPermissions == null) {
                        allowlistedRestrictedPermissions = Collections.emptyList();
                    }
                    mPermissionManager.setAllowlistedRestrictedPermissions(pkgSetting.pkg,
                            whiteListedPermissions, FLAG_PERMISSION_WHITELIST_INSTALLER,
                            new int[] { userId });
                    mPermissionManager.onPackageInstalled(pkgSetting.pkg, Collections.emptyList(),
                            allowlistedRestrictedPermissions, MODE_DEFAULT, userId);
                }
                if (pkgSetting.pkg != null) {
+195 −192
Original line number Diff line number Diff line
@@ -1243,10 +1243,19 @@ public class PermissionManagerService extends IPermissionManager.Stub {

        final long identity = Binder.clearCallingIdentity();
        try {
            return getAllowlistedRestrictedPermissionsInternal(pkg, flags, userId);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
    }

    @Nullable
    private List<String> getAllowlistedRestrictedPermissionsInternal(@NonNull AndroidPackage pkg,
            @PermissionWhitelistFlags int flags, @UserIdInt int userId) {
        synchronized (mLock) {
            final UidPermissionState uidState = getUidStateLocked(pkg, userId);
            if (uidState == null) {
                    Slog.e(TAG, "Missing permissions state for " + packageName + " and user "
                Slog.e(TAG, "Missing permissions state for " + pkg.getPackageName() + " and user "
                        + userId);
                return null;
            }
@@ -1265,7 +1274,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                queryFlags |=  FLAG_PERMISSION_RESTRICTION_ROLE_EXEMPT;
            }

                ArrayList<String> whitelistedPermissions = null;
            ArrayList<String> allowlistedPermissions = null;

            final int permissionCount = ArrayUtils.size(pkg.getRequestedPermissions());
            for (int i = 0; i < permissionCount; i++) {
@@ -1273,17 +1282,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                final int currentFlags =
                        uidState.getPermissionFlags(permissionName);
                if ((currentFlags & queryFlags) != 0) {
                        if (whitelistedPermissions == null) {
                            whitelistedPermissions = new ArrayList<>();
                    if (allowlistedPermissions == null) {
                        allowlistedPermissions = new ArrayList<>();
                    }
                        whitelistedPermissions.add(permissionName);
                    allowlistedPermissions.add(permissionName);
                }
            }

                return whitelistedPermissions;
            }
        } finally {
            Binder.restoreCallingIdentity(identity);
            return allowlistedPermissions;
        }
    }

@@ -1429,8 +1435,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {

        final long identity = Binder.clearCallingIdentity();
        try {
            setAllowlistedRestrictedPermissionsInternal(pkg, permissions, flags,
                    new int[] { userId });
            setAllowlistedRestrictedPermissionsInternal(pkg, permissions, flags, userId);
        } finally {
            Binder.restoreCallingIdentity(identity);
        }
@@ -1453,13 +1458,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        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());
@@ -3775,13 +3773,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
    }

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

    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;
@@ -3828,15 +3819,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {

    private void setAllowlistedRestrictedPermissionsInternal(@NonNull AndroidPackage pkg,
            @Nullable List<String> permissions, @PermissionWhitelistFlags int allowlistFlags,
            @UserIdInt int[] userIds) {
        SparseArray<ArraySet<String>> oldGrantedRestrictedPermissions = new SparseArray<>();
            @UserIdInt int userId) {
        ArraySet<String> oldGrantedRestrictedPermissions = null;
        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];

        for (int j = 0; j < permissionCount; j++) {
            final String permissionName = pkg.getRequestedPermissions().get(j);

@@ -3857,10 +3845,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            }

            if (isGranted) {
                    if (oldGrantedRestrictedPermissions.get(userId) == null) {
                        oldGrantedRestrictedPermissions.put(userId, new ArraySet<>());
                if (oldGrantedRestrictedPermissions == null) {
                    oldGrantedRestrictedPermissions = new ArraySet<>();
                }
                    oldGrantedRestrictedPermissions.get(userId).add(permissionName);
                oldGrantedRestrictedPermissions.add(permissionName);
            }

            final int oldFlags = getPermissionFlagsInternal(permissionName,
@@ -3945,23 +3933,19 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            updatePermissionFlagsInternal(permissionName, pkg.getPackageName(), mask, newFlags,
                    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(), mDefaultPermissionCallback);

            // If this resulted in losing a permission we need to kill the app.
            for (int i = 0; i < userIds.length; i++) {
                int userId = userIds[i];
                ArraySet<String> oldPermsForUser = oldGrantedRestrictedPermissions.get(userId);
                if (oldPermsForUser == null) {
                    continue;
            if (oldGrantedRestrictedPermissions == null) {
                return;
            }

                final int oldGrantedCount = oldPermsForUser.size();
            final int oldGrantedCount = oldGrantedRestrictedPermissions.size();
            for (int j = 0; j < oldGrantedCount; j++) {
                    final String permissionName = oldPermsForUser.valueAt(j);
                final String permissionName = oldGrantedRestrictedPermissions.valueAt(j);
                // Sometimes we create a new permission state instance during update.
                final boolean isGranted;
                synchronized (mLock) {
@@ -3980,7 +3964,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            }
        }
    }
    }

    @UserIdInt
    private int revokeSharedUserPermissionsForDeletedPackageInternal(
@@ -4914,6 +4897,34 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        return true;
    }

    private void onPackageInstalledInternal(@NonNull AndroidPackage pkg,
            @NonNull List<String> grantedPermissions,
            @NonNull List<String> allowlistedRestrictedPermissions, int autoRevokePermissionsMode,
            @UserIdInt int userId) {
        addAllowlistedRestrictedPermissionsInternal(pkg, allowlistedRestrictedPermissions,
                FLAG_PERMISSION_WHITELIST_INSTALLER, userId);
        if (autoRevokePermissionsMode == AppOpsManager.MODE_ALLOWED
                || autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED) {
            setAutoRevokeExemptedInternal(pkg,
                    autoRevokePermissionsMode == AppOpsManager.MODE_IGNORED, userId);
        }
        grantRequestedRuntimePermissionsInternal(pkg, grantedPermissions, userId);
    }

    private void addAllowlistedRestrictedPermissionsInternal(@NonNull AndroidPackage pkg,
            @NonNull List<String> allowlistedRestrictedPermissions,
            @PermissionWhitelistFlags int flags, @UserIdInt int userId) {
        List<String> permissions = getAllowlistedRestrictedPermissionsInternal(pkg, flags, userId);
        if (permissions != null) {
            ArraySet<String> permissionSet = new ArraySet<>(permissions);
            permissionSet.addAll(allowlistedRestrictedPermissions);
            permissions = new ArrayList<>(permissionSet);
        } else {
            permissions = allowlistedRestrictedPermissions;
        }
        setAllowlistedRestrictedPermissionsInternal(pkg, permissions, flags, userId);
    }

    private void onPackageRemovedInternal(@NonNull AndroidPackage pkg) {
        removeAllPermissionsInternal(pkg);
    }
@@ -5080,28 +5091,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            return PermissionManagerService.this.getAppOpPermissionPackagesInternal(permissionName);
        }
        @Override
        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 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 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) {
            PermissionManagerService.this
                    .updatePermissions(packageName, pkg, mDefaultPermissionCallback);
@@ -5371,6 +5360,20 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            onPackageAddedInternal(pkg, isInstantApp, oldPkg);
        }

        @Override
        public void onPackageInstalled(@NonNull AndroidPackage pkg,
                @NonNull List<String> grantedPermissions,
                @NonNull List<String> allowlistedRestrictedPermissions,
                int autoRevokePermissionsMode, @UserIdInt int userId) {
            Objects.requireNonNull(pkg, "pkg");
            Objects.requireNonNull(grantedPermissions, "grantedPermissions");
            Objects.requireNonNull(allowlistedRestrictedPermissions,
                    "allowlistedRestrictedPermissions");
            Preconditions.checkArgumentNonNegative(userId, "userId");
            onPackageInstalledInternal(pkg, grantedPermissions, allowlistedRestrictedPermissions,
                    autoRevokePermissionsMode, userId);
        }

        @Override
        public void onPackageRemoved(@NonNull AndroidPackage pkg) {
            Objects.requireNonNull(pkg);
+15 −37
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@ import android.annotation.AppIdInt;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.pm.PackageManager;
import android.content.pm.PermissionInfo;
import android.permission.PermissionManagerInternal;

@@ -189,42 +188,6 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
    public abstract boolean isPermissionsReviewRequired(@NonNull String packageName,
            @UserIdInt 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.
     *
@@ -525,6 +488,21 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
    public abstract void onPackageAdded(@NonNull AndroidPackage pkg, boolean isInstantApp,
            @Nullable AndroidPackage oldPkg);

    /**
     * Callback when a package has been installed for certain users.
     *
     * @param pkg the installed package
     * @param grantedPermissions the permissions to be granted
     * @param allowlistedRestrictedPermissions the restricted permissions to be allowlisted
     * @param autoRevokePermissionsMode the auto revoke permissions mode for this package
     * @param userId the user ID this package is installed for
     */
    //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
    public abstract void onPackageInstalled(@NonNull AndroidPackage pkg,
            @NonNull List<String> grantedPermissions,
            @NonNull List<String> allowlistedRestrictedPermissions,
            int autoRevokePermissionsMode, @UserIdInt int userId);

    /**
     * Callback when a package has been removed.
     *