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

Commit 4c0d15b9 authored by Hai Zhang's avatar Hai Zhang
Browse files

Generating missing permission state inside restorePermissionState().

PackageSettings.pkg isn't scanned yet when reading package settings,
but the generation needs information about the package, so we need to
defer it to restorePermissionState().

Fixes: 156204380
Test: devices boots
Change-Id: Id77222b2843395bbba17794a275df641d0d85d63
parent c8cd1ad5
Loading
Loading
Loading
Loading
+2 −44
Original line number Diff line number Diff line
@@ -5595,10 +5595,7 @@ public final class Settings {
                            userId);
                } else if (packageSetting.sharedUser == null && !isUpgradeToR) {
                    Slog.w(TAG, "Missing permission state for package: " + packageName);
                    generateFallbackPermissionsStateLpr(
                            packageSetting.pkg.getRequestedPermissions(),
                            packageSetting.pkg.getTargetSdkVersion(),
                            packageSetting.getPermissionsState(), userId);
                    packageSetting.getPermissionsState().setMissing(true, userId);
                }
            }

@@ -5616,22 +5613,7 @@ public final class Settings {
                            userId);
                } else if (!isUpgradeToR) {
                    Slog.w(TAG, "Missing permission state for shared user: " + sharedUserName);
                    ArraySet<String> requestedPermissions = new ArraySet<>();
                    int targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
                    int sharedUserPackagesSize = sharedUserSetting.packages.size();
                    for (int packagesI = 0; packagesI < sharedUserPackagesSize; packagesI++) {
                        PackageSetting packageSetting = sharedUserSetting.packages.valueAt(
                                packagesI);
                        if (packageSetting == null || packageSetting.pkg == null
                                || !packageSetting.getInstalled(userId)) {
                            continue;
                        }
                        AndroidPackage pkg = packageSetting.pkg;
                        requestedPermissions.addAll(pkg.getRequestedPermissions());
                        targetSdkVersion = Math.min(targetSdkVersion, pkg.getTargetSdkVersion());
                    }
                    generateFallbackPermissionsStateLpr(requestedPermissions, targetSdkVersion,
                            sharedUserSetting.getPermissionsState(), userId);
                    sharedUserSetting.getPermissionsState().setMissing(true, userId);
                }
            }
        }
@@ -5663,30 +5645,6 @@ public final class Settings {
            }
        }

        private void generateFallbackPermissionsStateLpr(
                @NonNull Collection<String> requestedPermissions, int targetSdkVersion,
                @NonNull PermissionsState permissionsState, @UserIdInt int userId) {
            for (String permissionName : requestedPermissions) {
                BasePermission permission = mPermissions.getPermission(permissionName);
                if (Objects.equals(permission.getSourcePackageName(), PLATFORM_PACKAGE_NAME)
                        && permission.isRuntime() && !permission.isRemoved()) {
                    if (permission.isHardOrSoftRestricted() || permission.isImmutablyRestricted()) {
                        permissionsState.updatePermissionFlags(permission, userId,
                                PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
                                PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);
                    }
                    if (targetSdkVersion < Build.VERSION_CODES.M) {
                        permissionsState.updatePermissionFlags(permission, userId,
                                PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
                                        | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
                                PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
                                        | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT);
                        permissionsState.grantRuntimePermission(permission, userId);
                    }
                }
            }
        }

        @GuardedBy("Settings.this.mLock")
        private void readLegacyStateForUserSyncLPr(int userId) {
            File permissionsFile = getUserRuntimePermissionsFile(userId);
+49 −1
Original line number Diff line number Diff line
@@ -154,6 +154,7 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -2473,13 +2474,60 @@ public class PermissionManagerService extends IPermissionManager.Stub {
        }

        final PermissionsState permissionsState = ps.getPermissionsState();
        PermissionsState origPermissions = permissionsState;

        final int[] currentUserIds = UserManagerService.getInstance().getUserIds();

        boolean runtimePermissionsRevoked = false;
        int[] updatedUserIds = EMPTY_INT_ARRAY;

        for (int userId : currentUserIds) {
            if (permissionsState.isMissing(userId)) {
                Collection<String> requestedPermissions;
                int targetSdkVersion;
                if (!ps.isSharedUser()) {
                    requestedPermissions = pkg.getRequestedPermissions();
                    targetSdkVersion = pkg.getTargetSdkVersion();
                } else {
                    requestedPermissions = new ArraySet<>();
                    targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT;
                    List<AndroidPackage> packages = ps.getSharedUser().getPackages();
                    int packagesSize = packages.size();
                    for (int i = 0; i < packagesSize; i++) {
                        AndroidPackage sharedUserPackage = packages.get(i);
                        requestedPermissions.addAll(sharedUserPackage.getRequestedPermissions());
                        targetSdkVersion = Math.min(targetSdkVersion,
                                sharedUserPackage.getTargetSdkVersion());
                    }
                }

                for (String permissionName : requestedPermissions) {
                    BasePermission permission = mSettings.getPermission(permissionName);
                    if (Objects.equals(permission.getSourcePackageName(), PLATFORM_PACKAGE_NAME)
                            && permission.isRuntime() && !permission.isRemoved()) {
                        if (permission.isHardOrSoftRestricted()
                                || permission.isImmutablyRestricted()) {
                            permissionsState.updatePermissionFlags(permission, userId,
                                    PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT,
                                    PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT);
                        }
                        if (targetSdkVersion < Build.VERSION_CODES.M) {
                            permissionsState.updatePermissionFlags(permission, userId,
                                    PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
                                            | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT,
                                    PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
                                            | PackageManager.FLAG_PERMISSION_REVOKED_COMPAT);
                            permissionsState.grantRuntimePermission(permission, userId);
                        }
                    }
                }

                permissionsState.setMissing(false, userId);
                updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
            }
        }

        PermissionsState origPermissions = permissionsState;

        boolean changedInstallPermission = false;

        if (replace) {
+57 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.pm.permission;

import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.util.ArrayMap;
@@ -30,6 +32,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
@@ -70,6 +73,9 @@ public final class PermissionsState {

    private int[] mGlobalGids = NO_GIDS;

    @Nullable
    private SparseBooleanArray mMissing;

    private SparseBooleanArray mPermissionReviewRequired;

    public PermissionsState() {
@@ -132,6 +138,23 @@ public final class PermissionsState {
                    other.mGlobalGids.length);
        }

        if (mMissing != null) {
            if (other.mMissing == null) {
                mMissing = null;
            } else {
                mMissing.clear();
            }
        }
        if (other.mMissing != null) {
            if (mMissing == null) {
                mMissing = new SparseBooleanArray();
            }
            final int missingSize = other.mMissing.size();
            for (int i = 0; i < missingSize; i++) {
                mMissing.put(other.mMissing.keyAt(i), other.mMissing.valueAt(i));
            }
        }

        if (mPermissionReviewRequired != null) {
            if (other.mPermissionReviewRequired == null) {
                mPermissionReviewRequired = null;
@@ -175,6 +198,10 @@ public final class PermissionsState {
            }
        }

        if (!Objects.equals(mMissing, other.mMissing)) {
            return false;
        }

        if (mPermissionReviewRequired == null) {
            if (other.mPermissionReviewRequired != null) {
                return false;
@@ -185,6 +212,35 @@ public final class PermissionsState {
        return Arrays.equals(mGlobalGids, other.mGlobalGids);
    }

    /**
     * Check whether the permissions state is missing for a user. This can happen if permission
     * state is rolled back and we'll need to generate a reasonable default state to keep the app
     * usable.
     */
    public boolean isMissing(@UserIdInt int userId) {
        return mMissing != null && mMissing.get(userId);
    }

    /**
     * Set whether the permissions state is missing for a user. This can happen if permission state
     * is rolled back and we'll need to generate a reasonable default state to keep the app usable.
     */
    public void setMissing(boolean missing, @UserIdInt int userId) {
        if (missing) {
            if (mMissing == null) {
                mMissing = new SparseBooleanArray();
            }
            mMissing.put(userId, true);
        } else {
            if (mMissing != null) {
                mMissing.delete(userId);
                if (mMissing.size() == 0) {
                    mMissing = null;
                }
            }
        }
    }

    public boolean isPermissionReviewRequired(int userId) {
        return mPermissionReviewRequired != null && mPermissionReviewRequired.get(userId);
    }
@@ -569,6 +625,7 @@ public final class PermissionsState {
            invalidateCache();
        }

        mMissing = null;
        mPermissionReviewRequired = null;
    }