diff options
3 files changed, 108 insertions, 45 deletions
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 9de34a92cdf7..a5b1bf98cdb7 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -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); diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 7d49f788c063..567a3b6ae227 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -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) { diff --git a/services/core/java/com/android/server/pm/permission/PermissionsState.java b/services/core/java/com/android/server/pm/permission/PermissionsState.java index 11e29a02068c..bad59cb1b567 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionsState.java +++ b/services/core/java/com/android/server/pm/permission/PermissionsState.java @@ -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; } |