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

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

Remove isRuntime for permissions state.

The distinction for whether a permission was granted as an install
permission or a runtime permission can actually be eliminated since
we are storing all permissions state as per-user now.

This is important for the persistence data scheme before we actually
make the migration.

The different between GRANT_RUNTIME and GRANT_UPGRADE is that the
latter clears the install permission state that was stored under
USER_ALL, but since that is no longer relevant in our new
implementation, we can simply remove GRANT_UPGRADE. A side effect of
the removal is that we are no longer revoking the non-platform pre-Q
activity recognition permission, which is an install permission and
shouldn't be revoked anyway.

Another small behavior change is that since we are not keep track of
whether a permission was granted as install or runtime despite its
current permission definition, we are no longer removing permission
flags when a permission definition is changed from runtime to
install. This shouldn't matter anyway because we are not downgrading
platform runtime permissions to install ones, and permission flags
isn't meaningful for app-defined install permissions anyway.

Bug: 158736025
Test: atest CtsPermissionTestCases
Test: atest CtsPermission3TestCases
Test: atest ActivityRecognitionPermissionTest
Change-Id: I515f2067ec7a961dda87f41bd76e84b32d8fc642
parent 1050e5b0
Loading
Loading
Loading
Loading
+45 −187
Original line number Original line Diff line number Diff line
@@ -183,8 +183,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
    private static final int GRANT_INSTALL = 2;
    private static final int GRANT_INSTALL = 2;
    /** Permission grant: grant the permission as a runtime one. */
    /** Permission grant: grant the permission as a runtime one. */
    private static final int GRANT_RUNTIME = 3;
    private static final int GRANT_RUNTIME = 3;
    /** Permission grant: grant as runtime a permission that was granted as an install time one. */
    private static final int GRANT_UPGRADE = 4;


    private static final long BACKUP_TIMEOUT_MILLIS = SECONDS.toMillis(60);
    private static final long BACKUP_TIMEOUT_MILLIS = SECONDS.toMillis(60);


@@ -2687,7 +2685,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                            SplitPermissionInfoParcelable sp = permissionList.get(splitPermNum);
                            SplitPermissionInfoParcelable sp = permissionList.get(splitPermNum);
                            String splitPermName = sp.getSplitPermission();
                            String splitPermName = sp.getSplitPermission();
                            if (sp.getNewPermissions().contains(permName)
                            if (sp.getNewPermissions().contains(permName)
                                    && origState.hasInstallPermission(splitPermName)) {
                                    && origState.hasPermission(splitPermName)) {
                                upgradedActivityRecognitionPermission = splitPermName;
                                upgradedActivityRecognitionPermission = splitPermName;
                                newImplicitPermissions.add(permName);
                                newImplicitPermissions.add(permName);


@@ -2733,15 +2731,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                    // For all apps normal permissions are install time ones.
                    // For all apps normal permissions are install time ones.
                    grant = GRANT_INSTALL;
                    grant = GRANT_INSTALL;
                } else if (bp.isRuntime()) {
                } else if (bp.isRuntime()) {
                    if (origState.hasInstallPermission(bp.getName())
                            || upgradedActivityRecognitionPermission != null) {
                        // Before Q we represented some runtime permissions as install permissions,
                        // in Q we cannot do this anymore. Hence upgrade them all.
                        grant = GRANT_UPGRADE;
                    } else {
                    // For modern apps keep runtime permissions unchanged.
                    // For modern apps keep runtime permissions unchanged.
                    grant = GRANT_RUNTIME;
                    grant = GRANT_RUNTIME;
                    }
                } else if (bp.isSignature()) {
                } else if (bp.isSignature()) {
                    // For all apps signature permissions are install time ones.
                    // For all apps signature permissions are install time ones.
                    allowedSig = shouldGrantSignaturePermission(perm, pkg, ps, bp, origState);
                    allowedSig = shouldGrantSignaturePermission(perm, pkg, ps, bp, origState);
@@ -2750,13 +2741,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                    }
                    }
                }
                }


                if (grant != GRANT_DENIED) {
                if (grant == GRANT_INSTALL && !allowedSig && !origState.hasPermission(perm)) {
                    if (!ps.isSystem() && userState.areInstallPermissionsFixed(ps.name)
                            && !bp.isRuntime()) {
                    // If this is an existing, non-system package, then
                    // If this is an existing, non-system package, then
                    // we can't add any new permissions to it. Runtime
                    // we can't add any new permissions to it. Runtime
                        // permissions can be added any time - they ad dynamic.
                    // permissions can be added any time - they are dynamic.
                        if (!allowedSig && !origState.hasInstallPermission(perm)) {
                    if (!ps.isSystem() && userState.areInstallPermissionsFixed(ps.name)) {
                        // Except...  if this is a permission that was added
                        // Except...  if this is a permission that was added
                        // to the platform (note: need to only do this when
                        // to the platform (note: need to only do this when
                        // updating the platform).
                        // updating the platform).
@@ -2765,7 +2754,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                        }
                        }
                    }
                    }
                }
                }
                }


                if (DEBUG_PERMISSIONS) {
                if (DEBUG_PERMISSIONS) {
                    Slog.i(TAG, "Considering granting permission " + perm + " to package "
                    Slog.i(TAG, "Considering granting permission " + perm + " to package "
@@ -2776,22 +2764,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                    if (grant != GRANT_DENIED) {
                    if (grant != GRANT_DENIED) {
                        switch (grant) {
                        switch (grant) {
                            case GRANT_INSTALL: {
                            case GRANT_INSTALL: {
                                // Revoke this as runtime permission to handle the case of
                                // a runtime permission being downgraded to an install one.
                                // Also in permission review mode we keep dangerous permissions
                                // for legacy apps
                                final PermissionState origPermissionState =
                                        origState.getPermissionState(perm);
                                if (origPermissionState != null
                                        && origPermissionState.isRuntime()) {
                                    // Revoke the runtime permission and clear the flags.
                                    origState.revokePermission(bp);
                                    origState.updatePermissionFlags(bp,
                                            PackageManager.MASK_PERMISSION_FLAGS_ALL, 0);
                                    // If we revoked a permission permission, we have to write.
                                    updatedUserIds = ArrayUtils.appendInt(
                                            updatedUserIds, userId);
                                }
                                // Grant an install permission.
                                // Grant an install permission.
                                if (uidState.grantPermission(bp) != PERMISSION_OPERATION_FAILURE) {
                                if (uidState.grantPermission(bp) != PERMISSION_OPERATION_FAILURE) {
                                    changedInstallPermission = true;
                                    changedInstallPermission = true;
@@ -2856,7 +2828,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                                    // Hard restricted permissions cannot be held.
                                    // Hard restricted permissions cannot be held.
                                    } else if (!permissionPolicyInitialized
                                    } else if (!permissionPolicyInitialized
                                            || (!hardRestricted || restrictionExempt)) {
                                            || (!hardRestricted || restrictionExempt)) {
                                        if (origPermState != null && origPermState.isGranted()) {
                                        if ((origPermState != null && origPermState.isGranted())
                                                || upgradedActivityRecognitionPermission != null) {
                                            if (uidState.grantPermission(bp)
                                            if (uidState.grantPermission(bp)
                                                    == PERMISSION_OPERATION_FAILURE) {
                                                    == PERMISSION_OPERATION_FAILURE) {
                                                wasChanged = true;
                                                wasChanged = true;
@@ -2914,124 +2887,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                                        flags);
                                        flags);
                            } break;
                            } break;


                            case GRANT_UPGRADE: {
                                // Upgrade from Pre-Q to Q permission model. Make all permissions
                                // runtime
                                PermissionState origPermState = origState.getPermissionState(perm);
                                int flags = (origPermState != null) ? origPermState.getFlags() : 0;

                                BasePermission bpToRevoke =
                                        upgradedActivityRecognitionPermission == null
                                        ? bp : mSettings.getPermissionLocked(
                                                upgradedActivityRecognitionPermission);
                                // Remove install permission
                                if (origState.revokePermission(bpToRevoke)
                                        != PERMISSION_OPERATION_FAILURE) {
                                    origState.updatePermissionFlags(bpToRevoke,
                                            (MASK_PERMISSION_FLAGS_ALL
                                                    & ~FLAG_PERMISSION_APPLY_RESTRICTION), 0);
                                    changedInstallPermission = true;
                                }

                                boolean hardRestricted = bp.isHardRestricted();
                                boolean softRestricted = bp.isSoftRestricted();

                                // If permission policy is not ready we don't deal with restricted
                                // permissions as the policy may whitelist some permissions. Once
                                // the policy is initialized we would re-evaluate permissions.
                                final boolean permissionPolicyInitialized =
                                        mPermissionPolicyInternal != null
                                                && mPermissionPolicyInternal.isInitialized(userId);

                                boolean wasChanged = false;

                                boolean restrictionExempt =
                                        (origState.getPermissionFlags(bp.name)
                                                & FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT) != 0;
                                boolean restrictionApplied = (origState.getPermissionFlags(
                                        bp.name) & FLAG_PERMISSION_APPLY_RESTRICTION) != 0;

                                if (appSupportsRuntimePermissions) {
                                    // If hard restricted we don't allow holding it
                                    if (permissionPolicyInitialized && hardRestricted) {
                                        if (!restrictionExempt) {
                                            if (origPermState != null && origPermState.isGranted()
                                                    && uidState.revokePermission(
                                                    bp) != PERMISSION_OPERATION_FAILURE) {
                                                wasChanged = true;
                                            }
                                            if (!restrictionApplied) {
                                                flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
                                                wasChanged = true;
                                            }
                                        }
                                    // If soft restricted we allow holding in a restricted form
                                    } else if (permissionPolicyInitialized && softRestricted) {
                                        // Regardless if granted set the  restriction flag as it
                                        // may affect app treatment based on this permission.
                                        if (!restrictionExempt && !restrictionApplied) {
                                            flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
                                            wasChanged = true;
                                        }
                                    }

                                    // Remove review flag as it is not necessary anymore
                                    if ((flags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
                                        flags &= ~FLAG_PERMISSION_REVIEW_REQUIRED;
                                        wasChanged = true;
                                    }

                                    if ((flags & FLAG_PERMISSION_REVOKED_COMPAT) != 0) {
                                        flags &= ~FLAG_PERMISSION_REVOKED_COMPAT;
                                        wasChanged = true;
                                    // Hard restricted permissions cannot be held.
                                    } else if (!permissionPolicyInitialized ||
                                            (!hardRestricted || restrictionExempt)) {
                                        if (uidState.grantPermission(bp)
                                                != PERMISSION_OPERATION_FAILURE) {
                                             wasChanged = true;
                                        }
                                    }
                                } else {
                                    if (!uidState.hasPermission(bp.name)
                                            && uidState.grantPermission(bp)
                                                    != PERMISSION_OPERATION_FAILURE) {
                                        flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
                                        wasChanged = true;
                                    }

                                    // If legacy app always grant the permission but if restricted
                                    // and not exempt take a note a restriction should be applied.
                                    if (permissionPolicyInitialized
                                            && (hardRestricted || softRestricted)
                                                    && !restrictionExempt && !restrictionApplied) {
                                        flags |= FLAG_PERMISSION_APPLY_RESTRICTION;
                                        wasChanged = true;
                                    }
                                }

                                // If unrestricted or restriction exempt, don't apply restriction.
                                if (permissionPolicyInitialized) {
                                    if (!(hardRestricted || softRestricted) || restrictionExempt) {
                                        if (restrictionApplied) {
                                            flags &= ~FLAG_PERMISSION_APPLY_RESTRICTION;
                                            // Dropping restriction on a legacy app implies a review
                                            if (!appSupportsRuntimePermissions) {
                                                flags |= FLAG_PERMISSION_REVIEW_REQUIRED;
                                            }
                                            wasChanged = true;
                                        }
                                    }
                                }

                                if (wasChanged) {
                                    updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
                                }

                                uidState.updatePermissionFlags(bp,
                                        MASK_PERMISSION_FLAGS_ALL, flags);
                            } break;

                            default: {
                            default: {
                                if (packageOfInterest == null
                                if (packageOfInterest == null
                                        || packageOfInterest.equals(pkg.getPackageName())) {
                                        || packageOfInterest.equals(pkg.getPackageName())) {
@@ -3140,11 +2995,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {


        for (String permission : ps.getPermissions()) {
        for (String permission : ps.getPermissions()) {
            if (!pkg.getImplicitPermissions().contains(permission)) {
            if (!pkg.getImplicitPermissions().contains(permission)) {
                if (!ps.hasInstallPermission(permission)) {
                BasePermission bp = mSettings.getPermissionLocked(permission);
                if (bp.isRuntime()) {
                    int flags = ps.getPermissionFlags(permission);
                    int flags = ps.getPermissionFlags(permission);


                    if ((flags & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED) != 0) {
                    if ((flags & FLAG_PERMISSION_REVOKE_WHEN_REQUESTED) != 0) {
                        BasePermission bp = mSettings.getPermissionLocked(permission);


                        int flagsToRemove = FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;
                        int flagsToRemove = FLAG_PERMISSION_REVOKE_WHEN_REQUESTED;


@@ -3290,8 +3145,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            ArraySet<String> sourcePerms = newToSplitPerms.get(newPerm);
            ArraySet<String> sourcePerms = newToSplitPerms.get(newPerm);


            if (sourcePerms != null) {
            if (sourcePerms != null) {
                if (!ps.hasInstallPermission(newPerm)) {
                BasePermission bp = mSettings.getPermissionLocked(newPerm);
                BasePermission bp = mSettings.getPermissionLocked(newPerm);
                if (bp.isRuntime()) {


                    if (!newPerm.equals(Manifest.permission.ACTIVITY_RECOGNITION)) {
                    if (!newPerm.equals(Manifest.permission.ACTIVITY_RECOGNITION)) {
                        ps.updatePermissionFlags(bp,
                        ps.updatePermissionFlags(bp,
@@ -3300,27 +3155,31 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                    }
                    }
                    updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
                    updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);


                    if (!origPs.hasRequestedPermission(sourcePerms)) {
                        boolean inheritsFromInstallPerm = false;
                        boolean inheritsFromInstallPerm = false;
                        for (int sourcePermNum = 0; sourcePermNum < sourcePerms.size();
                        for (int sourcePermNum = 0; sourcePermNum < sourcePerms.size();
                                sourcePermNum++) {
                                sourcePermNum++) {
                        if (ps.hasInstallPermission(sourcePerms.valueAt(sourcePermNum))) {
                            final String sourcePerm = sourcePerms.valueAt(sourcePermNum);
                            BasePermission sourceBp = mSettings.getPermissionLocked(sourcePerm);
                            if (!sourceBp.isRuntime()) {
                                inheritsFromInstallPerm = true;
                                inheritsFromInstallPerm = true;
                                break;
                                break;
                            }
                            }
                        }
                        }


                    if (!origPs.hasRequestedPermission(sourcePerms)
                        if (!inheritsFromInstallPerm) {
                            && !inheritsFromInstallPerm) {
                            // Both permissions are new so nothing to inherit.
                            // Both permissions are new so nothing to inherit.
                            if (DEBUG_PERMISSIONS) {
                            if (DEBUG_PERMISSIONS) {
                                Slog.i(TAG, newPerm + " does not inherit from " + sourcePerms
                                Slog.i(TAG, newPerm + " does not inherit from " + sourcePerms
                                        + " for " + pkgName + " as split permission is also new");
                                        + " for " + pkgName + " as split permission is also new");
                            }
                            }
                    } else {
                            continue;
                        // Inherit from new install or existing runtime permissions
                        }
                        inheritPermissionStateToNewImplicitPermissionLocked(sourcePerms,
                                newPerm, ps, pkg);
                    }
                    }

                    // Inherit from new install or existing runtime permissions
                    inheritPermissionStateToNewImplicitPermissionLocked(sourcePerms, newPerm, ps,
                            pkg);
                }
                }
            }
            }
        }
        }
@@ -3606,7 +3465,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
            if (!allowed && bp.isDevelopment()) {
            if (!allowed && bp.isDevelopment()) {
                // For development permissions, a development permission
                // For development permissions, a development permission
                // is granted only if it was already granted.
                // is granted only if it was already granted.
                allowed = origPermissions.hasInstallPermission(perm);
                allowed = origPermissions.hasPermission(perm);
            }
            }
            if (!allowed && bp.isSetup()
            if (!allowed && bp.isSetup()
                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
                    && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames(
@@ -4778,19 +4637,18 @@ public class PermissionManagerService extends IPermissionManager.Stub {
                    uidState.reset();
                    uidState.reset();
                    uidState.setMissing(appIdState.isMissing(userId));
                    uidState.setMissing(appIdState.isMissing(userId));
                    readStateFromPermissionStates(uidState,
                    readStateFromPermissionStates(uidState,
                            appIdState.getInstallPermissionStates(), false);
                            appIdState.getInstallPermissionStates());
                    readStateFromPermissionStates(uidState,
                    readStateFromPermissionStates(uidState,
                            appIdState.getRuntimePermissionStates(userId), true);
                            appIdState.getRuntimePermissionStates(userId));
                }
                }
            }
            }
        });
        });
    }
    }


    private void readStateFromPermissionStates(@NonNull UidPermissionState uidState,
    private void readStateFromPermissionStates(@NonNull UidPermissionState uidState,
            @NonNull Collection<AppIdPermissionState.PermissionState> permissionStates,
            @NonNull Collection<AppIdPermissionState.PermissionState> permissionStates) {
            boolean isRuntime) {
        for (final AppIdPermissionState.PermissionState permissionState : permissionStates) {
        for (final AppIdPermissionState.PermissionState permissionState : permissionStates) {
            uidState.putPermissionState(permissionState.getPermission(), isRuntime,
            uidState.putPermissionState(permissionState.getPermission(),
                    permissionState.isGranted(), permissionState.getFlags());
                    permissionState.isGranted(), permissionState.getFlags());
        }
        }
    }
    }
+3 −4
Original line number Original line Diff line number Diff line
@@ -41,13 +41,12 @@ public final class PermissionState {
    @GuardedBy("mLock")
    @GuardedBy("mLock")
    private int mFlags;
    private int mFlags;


    public PermissionState(@NonNull BasePermission permission, boolean isRuntime) {
    public PermissionState(@NonNull BasePermission permission) {
        mPermission = permission;
        mPermission = permission;
        mRuntime = isRuntime;
    }
    }


    public PermissionState(@NonNull PermissionState other) {
    public PermissionState(@NonNull PermissionState other) {
        this(other.mPermission, other.mRuntime);
        this(other.mPermission);


        mGranted = other.mGranted;
        mGranted = other.mGranted;
        mFlags = other.mFlags;
        mFlags = other.mFlags;
@@ -70,7 +69,7 @@ public final class PermissionState {


    public boolean isRuntime() {
    public boolean isRuntime() {
        synchronized (mLock) {
        synchronized (mLock) {
            return mRuntime;
            return mPermission.isRuntime();
        }
        }
    }
    }


+4 −27
Original line number Original line Diff line number Diff line
@@ -206,23 +206,6 @@ public final class UidPermissionState {
        }
        }
    }
    }


    /**
     * Gets whether the state has a given install permission.
     *
     * @param name The permission name.
     * @return Whether the state has the install permission.
     */
    public boolean hasInstallPermission(@NonNull String name) {
        synchronized (mLock) {
            if (mPermissions == null) {
                return false;
            }
            PermissionState permissionState = mPermissions.get(name);
            return permissionState != null && permissionState.isGranted()
                    && !permissionState.isRuntime();
        }
    }

    /**
    /**
     * Returns whether the state has any known request for the given permission name,
     * Returns whether the state has any known request for the given permission name,
     * whether or not it has been granted.
     * whether or not it has been granted.
@@ -459,11 +442,11 @@ public final class UidPermissionState {
    /**
    /**
     * Put a permission state.
     * Put a permission state.
     */
     */
    public void putPermissionState(@NonNull BasePermission permission, boolean isRuntime,
    public void putPermissionState(@NonNull BasePermission permission, boolean isGranted,
            boolean isGranted, int flags) {
            int flags) {
        synchronized (mLock) {
        synchronized (mLock) {
            ensureNoPermissionState(permission.name);
            ensureNoPermissionState(permission.name);
            PermissionState permissionState = ensurePermissionState(permission, isRuntime);
            PermissionState permissionState = ensurePermissionState(permission);
            if (isGranted) {
            if (isGranted) {
                permissionState.grant();
                permissionState.grant();
            }
            }
@@ -540,12 +523,6 @@ public final class UidPermissionState {


    @NonNull
    @NonNull
    private PermissionState ensurePermissionState(@NonNull BasePermission permission) {
    private PermissionState ensurePermissionState(@NonNull BasePermission permission) {
        return ensurePermissionState(permission, permission.isRuntime());
    }

    @NonNull
    private PermissionState ensurePermissionState(@NonNull BasePermission permission,
            boolean isRuntime) {
        final String permissionName = permission.getName();
        final String permissionName = permission.getName();
        synchronized (mLock) {
        synchronized (mLock) {
            if (mPermissions == null) {
            if (mPermissions == null) {
@@ -553,7 +530,7 @@ public final class UidPermissionState {
            }
            }
            PermissionState permissionState = mPermissions.get(permissionName);
            PermissionState permissionState = mPermissions.get(permissionName);
            if (permissionState == null) {
            if (permissionState == null) {
                permissionState = new PermissionState(permission, isRuntime);
                permissionState = new PermissionState(permission);
                mPermissions.put(permissionName, permissionState);
                mPermissions.put(permissionName, permissionState);
            }
            }
            return permissionState;
            return permissionState;