diff options
| author | 2020-09-25 14:47:34 -0700 | |
|---|---|---|
| committer | 2020-09-25 16:09:44 -0700 | |
| commit | 4280835e64ebac2fa87ca586aefd90fa7f63d0a2 (patch) | |
| tree | ea762e76dab38c2a6f926cbf48d4222d5f95c9d7 | |
| parent | b66035bb44b5505e12adb5107837966c09d5f6b8 (diff) | |
Refactor UidPermissionState.
Renamed hasPermission() to isPermissionGranted(),
hasRequestedPermission() to hasPermissionState(), and re-ordered the
fields and methods. No behavioral change is expected.
Bug: 158736025
Test: presubmit
Change-Id: Iecfc9d0b66ab95625e26476b80dca116f247c0b2
3 files changed, 267 insertions, 329 deletions
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index 865b8a1e97eb..524f9acf15cd 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -425,8 +425,7 @@ public final class BasePermission { public void enforceDeclaredUsedAndRuntimeOrDevelopment(AndroidPackage pkg, UidPermissionState uidState) { - int index = pkg.getRequestedPermissions().indexOf(name); - if (!uidState.hasRequestedPermission(name) && index == -1) { + if (!uidState.hasPermissionState(name) && !pkg.getRequestedPermissions().contains(name)) { throw new SecurityException("Package " + pkg.getPackageName() + " has not requested permission " + name); } 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 840b233902f6..474ce7c32c5a 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -943,7 +943,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { private boolean checkSinglePermissionInternal(int uid, @NonNull UidPermissionState uidState, @NonNull String permissionName) { - if (!uidState.hasPermission(permissionName)) { + if (!uidState.isPermissionGranted(permissionName)) { return false; } @@ -1659,7 +1659,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } // Permission is already revoked, no need to do anything. - if (!uidState.hasPermission(permName)) { + if (!uidState.isPermissionGranted(permName)) { return; } @@ -2482,12 +2482,12 @@ public class PermissionManagerService extends IPermissionManager.Stub { return Collections.emptySet(); } if (!ps.getInstantApp(userId)) { - return uidState.getPermissions(); + return uidState.getGrantedPermissions(); } else { // Install permission state is shared among all users, but instant app state is // per-user, so we can only filter it here unless we make install permission state // per-user as well. - final Set<String> instantPermissions = new ArraySet<>(uidState.getPermissions()); + final Set<String> instantPermissions = new ArraySet<>(uidState.getGrantedPermissions()); instantPermissions.removeIf(permissionName -> { BasePermission permission = mSettings.getPermission(permissionName); if (permission == null) { @@ -2660,7 +2660,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // Cache newImplicitPermissions before modifing permissionsState as for the shared // uids the original and new state are the same object - if (!origState.hasRequestedPermission(permName) + if (!origState.hasPermissionState(permName) && (pkg.getImplicitPermissions().contains(permName) || (permName.equals(Manifest.permission.ACTIVITY_RECOGNITION)))) { if (pkg.getImplicitPermissions().contains(permName)) { @@ -2685,7 +2685,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { SplitPermissionInfoParcelable sp = permissionList.get(splitPermNum); String splitPermName = sp.getSplitPermission(); if (sp.getNewPermissions().contains(permName) - && origState.hasPermission(splitPermName)) { + && origState.isPermissionGranted(splitPermName)) { upgradedActivityRecognitionPermission = splitPermName; newImplicitPermissions.add(permName); @@ -2741,7 +2741,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - if (grant == GRANT_INSTALL && !allowedSig && !origState.hasPermission(perm)) { + if (grant == GRANT_INSTALL && !allowedSig && !origState.isPermissionGranted(perm)) { // If this is an existing, non-system package, then // we can't add any new permissions to it. Runtime // permissions can be added any time - they are dynamic. @@ -2849,7 +2849,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } } - if (!uidState.hasPermission(bp.name) + if (!uidState.isPermissionGranted(bp.name) && uidState.grantPermission(bp) != PERMISSION_OPERATION_FAILURE) { wasChanged = true; @@ -2993,7 +2993,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { boolean supportsRuntimePermissions = pkg.getTargetSdkVersion() >= Build.VERSION_CODES.M; - for (String permission : ps.getPermissions()) { + for (String permission : ps.getGrantedPermissions()) { if (!pkg.getImplicitPermissions().contains(permission)) { BasePermission bp = mSettings.getPermissionLocked(permission); if (bp.isRuntime()) { @@ -3050,7 +3050,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { int numSourcePerm = sourcePerms.size(); for (int i = 0; i < numSourcePerm; i++) { String sourcePerm = sourcePerms.valueAt(i); - if (ps.hasPermission(sourcePerm)) { + if (ps.isPermissionGranted(sourcePerm)) { if (!isGranted) { flags = 0; } @@ -3155,7 +3155,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { } updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId); - if (!origPs.hasRequestedPermission(sourcePerms)) { + if (!origPs.hasPermissionState(sourcePerms)) { boolean inheritsFromInstallPerm = false; for (int sourcePermNum = 0; sourcePermNum < sourcePerms.size(); sourcePermNum++) { @@ -3465,7 +3465,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { if (!allowed && bp.isDevelopment()) { // For development permissions, a development permission // is granted only if it was already granted. - allowed = origPermissions.hasPermission(perm); + allowed = origPermissions.isPermissionGranted(perm); } if (!allowed && bp.isSetup() && ArrayUtils.contains(mPackageManagerInt.getKnownPackageNames( @@ -3687,7 +3687,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { continue; } - if (uidState.hasPermission(permissionName)) { + if (uidState.isPermissionGranted(permissionName)) { if (oldGrantedRestrictedPermissions.get(userId) == null) { oldGrantedRestrictedPermissions.put(userId, new ArraySet<>()); } @@ -3749,7 +3749,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { // as whitelisting trumps policy i.e. policy cannot grant a non // grantable permission. if ((oldFlags & PackageManager.FLAG_PERMISSION_POLICY_FIXED) != 0) { - final boolean isGranted = uidState.hasPermission(permissionName); + final boolean isGranted = uidState.isPermissionGranted(permissionName); if (!isWhitelisted && isGranted) { mask |= PackageManager.FLAG_PERMISSION_POLICY_FIXED; newFlags &= ~PackageManager.FLAG_PERMISSION_POLICY_FIXED; @@ -3791,7 +3791,7 @@ public class PermissionManagerService extends IPermissionManager.Stub { + " and user " + userId); continue; } - if (!newUidState.hasPermission(permission)) { + if (!newUidState.isPermissionGranted(permission)) { callback.onPermissionRevoked(pkg.getUid(), userId, null); break; } diff --git a/services/core/java/com/android/server/pm/permission/UidPermissionState.java b/services/core/java/com/android/server/pm/permission/UidPermissionState.java index b45176b720b5..06a7f8dbd2be 100644 --- a/services/core/java/com/android/server/pm/permission/UidPermissionState.java +++ b/services/core/java/com/android/server/pm/permission/UidPermissionState.java @@ -54,149 +54,161 @@ public final class UidPermissionState { @NonNull private final Object mLock = new Object(); + private boolean mMissing; + @GuardedBy("mLock") + @Nullable private ArrayMap<String, PermissionState> mPermissions; + private boolean mPermissionReviewRequired; + @NonNull private int[] mGlobalGids = NO_GIDS; - private boolean mMissing; + public UidPermissionState() {} - private boolean mPermissionReviewRequired; + public UidPermissionState(@NonNull UidPermissionState other) { + synchronized (mLock) { + mMissing = other.mMissing; - public UidPermissionState() { - /* do nothing */ - } + if (other.mPermissions != null) { + mPermissions = new ArrayMap<>(); + final int permissionsSize = other.mPermissions.size(); + for (int i = 0; i < permissionsSize; i++) { + final String name = other.mPermissions.keyAt(i); + final PermissionState permissionState = other.mPermissions.valueAt(i); + mPermissions.put(name, new PermissionState(permissionState)); + } + } + + mPermissionReviewRequired = other.mPermissionReviewRequired; - public UidPermissionState(@NonNull UidPermissionState prototype) { - copyFrom(prototype); + if (other.mGlobalGids != NO_GIDS) { + mGlobalGids = other.mGlobalGids.clone(); + } + } } /** - * Gets the global gids, applicable to all users. + * Reset the internal state of this object. */ - @NonNull - public int[] getGlobalGids() { - return mGlobalGids; + public void reset() { + synchronized (mLock) { + mMissing = false; + mPermissions = null; + mPermissionReviewRequired = false; + mGlobalGids = NO_GIDS; + invalidateCache(); + } } /** - * Sets the global gids, applicable to all users. - * - * @param globalGids The global gids. + * 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 void setGlobalGids(@NonNull int[] globalGids) { - if (!ArrayUtils.isEmpty(globalGids)) { - mGlobalGids = Arrays.copyOf(globalGids, globalGids.length); - } + public boolean isMissing() { + return mMissing; } - static void invalidateCache() { - PackageManager.invalidatePackageInfoCache(); + /** + * 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) { + mMissing = missing; } /** - * Initialized this instance from another one. + * Get whether there is a permission state for a permission. * - * @param other The other instance. + * @deprecated This used to be named hasRequestedPermission() and its usage is confusing */ - public void copyFrom(@NonNull UidPermissionState other) { - if (other == this) { - return; + @Deprecated + public boolean hasPermissionState(@NonNull String name) { + synchronized (mLock) { + return mPermissions != null && mPermissions.containsKey(name); } + } + /** + * Get whether there is a permission state for any of the permissions. + * + * @deprecated This used to be named hasRequestedPermission() and its usage is confusing + */ + @Deprecated + public boolean hasPermissionState(@NonNull ArraySet<String> names) { synchronized (mLock) { - if (mPermissions != null) { - if (other.mPermissions == null) { - mPermissions = null; - } else { - mPermissions.clear(); - } + if (mPermissions == null) { + return false; } - if (other.mPermissions != null) { - if (mPermissions == null) { - mPermissions = new ArrayMap<>(); - } - final int permissionCount = other.mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - String name = other.mPermissions.keyAt(i); - PermissionState permissionState = other.mPermissions.valueAt(i); - mPermissions.put(name, new PermissionState(permissionState)); + final int namesSize = names.size(); + for (int i = 0; i < namesSize; i++) { + final String name = names.valueAt(i); + if (mPermissions.containsKey(name)) { + return true; } } - } - - mGlobalGids = NO_GIDS; - if (other.mGlobalGids != NO_GIDS) { - mGlobalGids = other.mGlobalGids.clone(); - } - - mMissing = other.mMissing; - - mPermissionReviewRequired = other.mPermissionReviewRequired; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { return false; } - if (getClass() != obj.getClass()) { - return false; - } - final UidPermissionState other = (UidPermissionState) obj; + } + /** + * Gets the state for a permission or null if none. + * + * @param name the permission name. + * @return the permission state. + */ + @Nullable + public PermissionState getPermissionState(@NonNull String name) { synchronized (mLock) { if (mPermissions == null) { - if (other.mPermissions != null) { - return false; - } - } else if (!mPermissions.equals(other.mPermissions)) { - return false; + return null; } + return mPermissions.get(name); } - - if (mMissing != other.mMissing) { - return false; - } - - if (mPermissionReviewRequired != other.mPermissionReviewRequired) { - return false; - } - 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. + * Get all permission states. + * + * @return the permission states */ - public boolean isMissing() { - return mMissing; + @NonNull + public List<PermissionState> getPermissionStates() { + synchronized (mLock) { + if (mPermissions == null) { + return Collections.emptyList(); + } + return new ArrayList<>(mPermissions.values()); + } } /** - * 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. + * Put a permission state. */ - public void setMissing(boolean missing) { - mMissing = missing; - } - - public boolean isPermissionReviewRequired() { - return mPermissionReviewRequired; + public void putPermissionState(@NonNull BasePermission permission, boolean isGranted, + int flags) { + synchronized (mLock) { + ensureNoPermissionState(permission.name); + PermissionState permissionState = ensurePermissionState(permission); + if (isGranted) { + permissionState.grant(); + } + permissionState.updateFlags(flags, flags); + if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) { + mPermissionReviewRequired = true; + } + } } /** - * Gets whether the state has a given permission. + * Get whether a permission is granted. * - * @param name The permission name. - * @return Whether the state has the permission. + * @param name the permission name + * @return whether the permission is granted */ - public boolean hasPermission(@NonNull String name) { + public boolean isPermissionGranted(@NonNull String name) { synchronized (mLock) { if (mPermissions == null) { return false; @@ -207,86 +219,105 @@ public final class UidPermissionState { } /** - * Returns whether the state has any known request for the given permission name, - * whether or not it has been granted. + * Get all the granted permissions. * - * @deprecated Not all requested permissions may be here. + * @return the granted permissions */ - @Deprecated - public boolean hasRequestedPermission(@NonNull ArraySet<String> names) { + @NonNull + public Set<String> getGrantedPermissions() { synchronized (mLock) { if (mPermissions == null) { - return false; + return Collections.emptySet(); } - for (int i = names.size() - 1; i >= 0; i--) { - if (mPermissions.get(names.valueAt(i)) != null) { - return true; + + Set<String> permissions = new ArraySet<>(mPermissions.size()); + final int permissionsSize = mPermissions.size(); + for (int i = 0; i < permissionsSize; i++) { + PermissionState permissionState = mPermissions.valueAt(i); + + if (permissionState.isGranted()) { + permissions.add(permissionState.getName()); } } + return permissions; } - - return false; } /** - * Returns whether the state has any known request for the given permission name, - * whether or not it has been granted. + * Grant a permission. * - * @deprecated Not all requested permissions may be here. + * @param permission the permission to grantt + * @return the operation result, which is either {@link #PERMISSION_OPERATION_SUCCESS}, + * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link + * #PERMISSION_OPERATION_FAILURE}. */ - @Deprecated - public boolean hasRequestedPermission(@NonNull String name) { - return mPermissions != null && (mPermissions.get(name) != null); + public int grantPermission(@NonNull BasePermission permission) { + if (isPermissionGranted(permission.getName())) { + return PERMISSION_OPERATION_SUCCESS; + } + + PermissionState permissionState = ensurePermissionState(permission); + + if (!permissionState.grant()) { + return PERMISSION_OPERATION_FAILURE; + } + + return permission.hasGids() ? PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED + : PERMISSION_OPERATION_SUCCESS; } /** - * Gets all permissions for a given device user id regardless if they - * are install time or runtime permissions. + * Revoke a permission. * - * @return The permissions or an empty set. + * @param permission the permission to revoke + * @return the operation result, which is either {@link #PERMISSION_OPERATION_SUCCESS}, + * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link + * #PERMISSION_OPERATION_FAILURE}. */ - @NonNull - public Set<String> getPermissions() { - synchronized (mLock) { - if (mPermissions == null) { - return Collections.emptySet(); - } - - Set<String> permissions = new ArraySet<>(mPermissions.size()); + public int revokePermission(@NonNull BasePermission permission) { + final String name = permission.getName(); + if (!isPermissionGranted(name)) { + return PERMISSION_OPERATION_SUCCESS; + } - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - String permission = mPermissions.keyAt(i); + PermissionState permissionState; + synchronized (mLock) { + permissionState = mPermissions.get(name); + } - if (hasPermission(permission)) { - permissions.add(permission); - } - } + if (!permissionState.revoke()) { + return PERMISSION_OPERATION_FAILURE; + } - return permissions; + if (permissionState.isDefault()) { + ensureNoPermissionState(name); } + + return permission.hasGids() ? PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED + : PERMISSION_OPERATION_SUCCESS; } /** - * Gets the flags for a permission. + * Get the flags for a permission. * - * @param name The permission name. - * @return The permission state or null if no such. + * @param name the permission name. + * @return the permission flags */ public int getPermissionFlags(@NonNull String name) { - PermissionState permState = getPermissionState(name); - if (permState != null) { - return permState.getFlags(); + final PermissionState permissionState = getPermissionState(name); + if (permissionState == null) { + return 0; } - return 0; + return permissionState.getFlags(); } /** - * Update the flags associated with a given permission. - * @param permission The permission whose flags to update. - * @param flagMask Mask for which flags to change. - * @param flagValues New values for the mask flags. - * @return Whether the permission flags changed. + * Update the flags for a permission. + * + * @param permission the permission name + * @param flagMask the mask for the flags + * @param flagValues the new values for the masked flags + * @return whether the permission flags changed */ public boolean updatePermissionFlags(@NonNull BasePermission permission, int flagMask, int flagValues) { @@ -294,11 +325,10 @@ public final class UidPermissionState { return false; } - PermissionState permissionState = ensurePermissionState(permission); - - final int oldFlags = permissionState.getFlags(); - synchronized (mLock) { + final PermissionState permissionState = ensurePermissionState(permission); + final int oldFlags = permissionState.getFlags(); + final boolean updated = permissionState.updateFlags(flagMask, flagValues); if (updated) { final int newFlags = permissionState.getFlags(); @@ -316,199 +346,132 @@ public final class UidPermissionState { } } - private boolean hasPermissionRequiringReview() { - synchronized (mLock) { - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - final PermissionState permission = mPermissions.valueAt(i); - if ((permission.getFlags() & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) { - return true; - } - } - } - return false; - } - public boolean updatePermissionFlagsForAllPermissions(int flagMask, int flagValues) { synchronized (mLock) { if (mPermissions == null) { return false; } boolean changed = false; - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - PermissionState permissionState = mPermissions.valueAt(i); + final int permissionsSize = mPermissions.size(); + for (int i = 0; i < permissionsSize; i++) { + final PermissionState permissionState = mPermissions.valueAt(i); changed |= permissionState.updateFlags(flagMask, flagValues); } return changed; } } - /** - * Compute the Linux gids for a given device user from the permissions - * granted to this user. Note that these are computed to avoid additional - * state as they are rarely accessed. - * - * @param userId The device user id. - * @return The gids for the device user. - */ @NonNull - public int[] computeGids(@UserIdInt int userId) { - int[] gids = mGlobalGids; - + private PermissionState ensurePermissionState(@NonNull BasePermission permission) { + final String name = permission.getName(); synchronized (mLock) { - if (mPermissions != null) { - final int permissionCount = mPermissions.size(); - for (int i = 0; i < permissionCount; i++) { - PermissionState permissionState = mPermissions.valueAt(i); - if (!permissionState.isGranted()) { - continue; - } - final int[] permGids = permissionState.computeGids(userId); - if (permGids != NO_GIDS) { - gids = appendInts(gids, permGids); - } - } + if (mPermissions == null) { + mPermissions = new ArrayMap<>(); } + PermissionState permissionState = mPermissions.get(name); + if (permissionState == null) { + permissionState = new PermissionState(permission); + mPermissions.put(name, permissionState); + } + return permissionState; } - - return gids; - } - - /** - * Compute the Linux gids for all device users from the permissions - * granted to these users. - * - * @return The gids for all device users. - */ - @NonNull - public int[] computeGids(@NonNull int[] userIds) { - int[] gids = mGlobalGids; - - for (int userId : userIds) { - final int[] userGids = computeGids(userId); - gids = appendInts(gids, userGids); - } - - return gids; } - /** - * Resets the internal state of this object. - */ - public void reset() { - mGlobalGids = NO_GIDS; - + private void ensureNoPermissionState(@NonNull String name) { synchronized (mLock) { - mPermissions = null; - invalidateCache(); + if (mPermissions == null) { + return; + } + mPermissions.remove(name); + if (mPermissions.isEmpty()) { + mPermissions = null; + } } + } - mMissing = false; - mPermissionReviewRequired = false; + public boolean isPermissionReviewRequired() { + return mPermissionReviewRequired; } - /** - * Gets the state for a permission or null if no such. - * - * @param name The permission name. - * @return The permission state. - */ - @Nullable - public PermissionState getPermissionState(@NonNull String name) { + private boolean hasPermissionRequiringReview() { synchronized (mLock) { - if (mPermissions == null) { - return null; + final int permissionsSize = mPermissions.size(); + for (int i = 0; i < permissionsSize; i++) { + final PermissionState permission = mPermissions.valueAt(i); + if ((permission.getFlags() & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) { + return true; + } } - return mPermissions.get(name); + return false; } } /** - * Gets all permission states. - * - * @return The permission states or an empty set. + * Gets the global gids, applicable to all users. */ @NonNull - public List<PermissionState> getPermissionStates() { - synchronized (mLock) { - if (mPermissions == null) { - return Collections.emptyList(); - } - return new ArrayList<>(mPermissions.values()); - } + public int[] getGlobalGids() { + return mGlobalGids; } /** - * Put a permission state. + * Sets the global gids, applicable to all users. + * + * @param globalGids The global gids. */ - public void putPermissionState(@NonNull BasePermission permission, boolean isGranted, - int flags) { - synchronized (mLock) { - ensureNoPermissionState(permission.name); - PermissionState permissionState = ensurePermissionState(permission); - if (isGranted) { - permissionState.grant(); - } - permissionState.updateFlags(flags, flags); - if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) { - mPermissionReviewRequired = true; - } + public void setGlobalGids(@NonNull int[] globalGids) { + if (!ArrayUtils.isEmpty(globalGids)) { + mGlobalGids = Arrays.copyOf(globalGids, globalGids.length); + } else { + mGlobalGids = NO_GIDS; } } /** - * Grant a permission. + * Compute the Linux GIDs from the permissions granted to a user. * - * @param permission The permission to grant. - * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS}, - * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link - * #PERMISSION_OPERATION_FAILURE}. + * @param userId the user ID + * @return the GIDs for the user */ - public int grantPermission(@NonNull BasePermission permission) { - if (hasPermission(permission.getName())) { - return PERMISSION_OPERATION_SUCCESS; - } - - PermissionState permissionState = ensurePermissionState(permission); + @NonNull + public int[] computeGids(@UserIdInt int userId) { + int[] gids = mGlobalGids; - if (!permissionState.grant()) { - return PERMISSION_OPERATION_FAILURE; + synchronized (mLock) { + if (mPermissions != null) { + final int permissionCount = mPermissions.size(); + for (int i = 0; i < permissionCount; i++) { + PermissionState permissionState = mPermissions.valueAt(i); + if (!permissionState.isGranted()) { + continue; + } + final int[] permGids = permissionState.computeGids(userId); + if (permGids != NO_GIDS) { + gids = appendInts(gids, permGids); + } + } + } } - return permission.hasGids() ? PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED - : PERMISSION_OPERATION_SUCCESS; + return gids; } /** - * Revoke a permission. + * Compute the Linux GIDs from the permissions granted to specified users. * - * @param permission The permission to revoke. - * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS}, - * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link - * #PERMISSION_OPERATION_FAILURE}. + * @param userIds the user IDs + * @return the GIDs for the user */ - public int revokePermission(@NonNull BasePermission permission) { - final String permissionName = permission.getName(); - if (!hasPermission(permissionName)) { - return PERMISSION_OPERATION_SUCCESS; - } - - PermissionState permissionState; - synchronized (mLock) { - permissionState = mPermissions.get(permissionName); - } - - if (!permissionState.revoke()) { - return PERMISSION_OPERATION_FAILURE; - } + @NonNull + public int[] computeGids(@NonNull int[] userIds) { + int[] gids = mGlobalGids; - if (permissionState.isDefault()) { - ensureNoPermissionState(permissionName); + for (final int userId : userIds) { + final int[] userGids = computeGids(userId); + gids = appendInts(gids, userGids); } - return permission.hasGids() ? PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED - : PERMISSION_OPERATION_SUCCESS; + return gids; } // TODO: fix this to use arraycopy and append all ints in one go @@ -521,31 +484,7 @@ public final class UidPermissionState { return current; } - @NonNull - private PermissionState ensurePermissionState(@NonNull BasePermission permission) { - final String permissionName = permission.getName(); - synchronized (mLock) { - if (mPermissions == null) { - mPermissions = new ArrayMap<>(); - } - PermissionState permissionState = mPermissions.get(permissionName); - if (permissionState == null) { - permissionState = new PermissionState(permission); - mPermissions.put(permissionName, permissionState); - } - return permissionState; - } - } - - private void ensureNoPermissionState(@NonNull String name) { - synchronized (mLock) { - if (mPermissions == null) { - return; - } - mPermissions.remove(name); - if (mPermissions.isEmpty()) { - mPermissions = null; - } - } + static void invalidateCache() { + PackageManager.invalidatePackageInfoCache(); } } |