Merge "Further refactor UidPermissionState and GIDs."

This commit is contained in:
TreeHugger Robot
2020-09-30 22:01:01 +00:00
committed by Android (Google) Code Review
5 changed files with 149 additions and 290 deletions

View File

@@ -46,6 +46,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.XmlUtils;
import libcore.io.IoUtils;
import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -55,7 +56,6 @@ import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -95,7 +95,7 @@ public class SystemConfig {
private static final String VENDOR_SKU_PROPERTY = "ro.boot.product.vendor.sku";
// Group-ids that are given to all packages as read from etc/permissions/*.xml.
int[] mGlobalGids;
int[] mGlobalGids = EmptyArray.INT;
// These are the built-in uid -> permission mappings that were read from the
// system configuration files.

View File

@@ -36,13 +36,14 @@ import android.os.UserHandle;
import android.util.Log;
import android.util.Slog;
import com.android.internal.util.ArrayUtils;
import com.android.server.pm.DumpState;
import com.android.server.pm.PackageManagerService;
import com.android.server.pm.PackageSettingBase;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import libcore.util.EmptyArray;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer;
@@ -95,7 +96,8 @@ public final class BasePermission {
int uid;
/** Additional GIDs given to apps granted this permission */
private int[] gids;
@NonNull
private int[] gids = EmptyArray.INT;
/**
* Flag indicating that {@link #gids} should be adjusted based on the
@@ -132,7 +134,7 @@ public final class BasePermission {
public int getUid() {
return uid;
}
public void setGids(int[] gids, boolean perUser) {
public void setGids(@NonNull int[] gids, boolean perUser) {
this.gids = gids;
this.perUser = perUser;
}
@@ -141,18 +143,20 @@ public final class BasePermission {
}
public boolean hasGids() {
return !ArrayUtils.isEmpty(gids);
return gids.length != 0;
}
@NonNull
public int[] computeGids(int userId) {
if (perUser) {
final int[] userGids = new int[gids.length];
for (int i = 0; i < gids.length; i++) {
userGids[i] = UserHandle.getUid(userId, gids[i]);
final int gid = gids[i];
userGids[i] = UserHandle.getUid(userId, gid);
}
return userGids;
} else {
return gids;
return gids.length != 0 ? gids.clone() : gids;
}
}
@@ -291,7 +295,8 @@ public final class BasePermission {
pendingPermissionInfo.packageName = newPackageName;
}
uid = 0;
setGids(null, false);
gids = EmptyArray.INT;
perUser = false;
}
public boolean addToTree(@ProtectionLevel int protectionLevel,

View File

@@ -55,7 +55,6 @@ import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING
import static com.android.server.pm.PackageManagerService.DEBUG_PERMISSIONS;
import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.pm.permission.UidPermissionState.PERMISSION_OPERATION_FAILURE;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -154,6 +153,8 @@ import com.android.server.pm.permission.PermissionManagerServiceInternal.Permiss
import com.android.server.policy.PermissionPolicyInternal;
import com.android.server.policy.SoftRestrictedPermissionPolicy;
import libcore.util.EmptyArray;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.lang.annotation.Retention;
@@ -247,6 +248,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private final SparseArray<ArraySet<String>> mSystemPermissions;
/** Built-in group IDs given to all packages. Read from system configuration files. */
@NonNull
private final int[] mGlobalGids;
private final HandlerThread mHandlerThread;
@@ -1513,7 +1515,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// normal runtime permissions. For now they apply to all users.
// TODO(zhanghai): We are breaking the behavior above by making all permission state
// per-user. It isn't documented behavior and relatively rarely used anyway.
if (uidState.grantPermission(bp) != PERMISSION_OPERATION_FAILURE) {
if (uidState.grantPermission(bp)) {
if (callback != null) {
callback.onInstallPermissionGranted();
}
@@ -1531,18 +1533,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return;
}
final int result = uidState.grantPermission(bp);
switch (result) {
case PERMISSION_OPERATION_FAILURE: {
return;
}
if (!uidState.grantPermission(bp)) {
return;
}
case UidPermissionState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED: {
if (callback != null) {
callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId);
}
if (bp.hasGids()) {
if (callback != null) {
callback.onGidsChanged(UserHandle.getAppId(pkg.getUid()), userId);
}
break;
}
if (bp.isRuntime()) {
@@ -1662,7 +1660,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// normal runtime permissions. For now they apply to all users.
// TODO(zhanghai): We are breaking the behavior above by making all permission state
// per-user. It isn't documented behavior and relatively rarely used anyway.
if (uidState.revokePermission(bp) != PERMISSION_OPERATION_FAILURE) {
if (uidState.revokePermission(bp)) {
if (callback != null) {
mDefaultPermissionCallback.onInstallPermissionRevoked();
}
@@ -1670,12 +1668,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return;
}
// Permission is already revoked, no need to do anything.
if (!uidState.isPermissionGranted(permName)) {
return;
}
if (uidState.revokePermission(bp) == PERMISSION_OPERATION_FAILURE) {
if (!uidState.revokePermission(bp)) {
return;
}
@@ -2525,11 +2518,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
@Nullable
@NonNull
private int[] getPermissionGids(@NonNull String permissionName, @UserIdInt int userId) {
BasePermission permission = mSettings.getPermission(permissionName);
if (permission == null) {
return null;
return EmptyArray.INT;
}
return permission.computeGids(userId);
}
@@ -2650,8 +2643,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
uidState.setGlobalGids(mGlobalGids);
ArraySet<String> newImplicitPermissions = new ArraySet<>();
final String friendlyName = pkg.getPackageName() + "(" + pkg.getUid() + ")";
@@ -2786,7 +2777,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
switch (grant) {
case GRANT_INSTALL: {
// Grant an install permission.
if (uidState.grantPermission(bp) != PERMISSION_OPERATION_FAILURE) {
if (uidState.grantPermission(bp)) {
changedInstallPermission = true;
}
} break;
@@ -2818,8 +2809,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if (permissionPolicyInitialized && hardRestricted) {
if (!restrictionExempt) {
if (origPermState != null && origPermState.isGranted()
&& uidState.revokePermission(
bp) != PERMISSION_OPERATION_FAILURE) {
&& uidState.revokePermission(bp)) {
wasChanged = true;
}
if (!restrictionApplied) {
@@ -2851,8 +2841,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
|| (!hardRestricted || restrictionExempt)) {
if ((origPermState != null && origPermState.isGranted())
|| upgradedActivityRecognitionPermission != null) {
if (uidState.grantPermission(bp)
== PERMISSION_OPERATION_FAILURE) {
if (!uidState.grantPermission(bp)) {
wasChanged = true;
}
}
@@ -2871,8 +2860,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
if (!uidState.isPermissionGranted(bp.name)
&& uidState.grantPermission(bp)
!= PERMISSION_OPERATION_FAILURE) {
&& uidState.grantPermission(bp)) {
wasChanged = true;
}
@@ -2920,13 +2908,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
} break;
}
} else {
if (uidState.revokePermission(bp) != PERMISSION_OPERATION_FAILURE) {
// Also drop the permission flags.
uidState.updatePermissionFlags(bp,
MASK_PERMISSION_FLAGS_ALL, 0);
changedInstallPermission = true;
if (DEBUG_PERMISSIONS) {
Slog.i(TAG, "Un-granting permission " + perm
if (DEBUG_PERMISSIONS) {
boolean wasGranted = uidState.isPermissionGranted(bp.name);
if (wasGranted || bp.isAppOp()) {
Slog.i(TAG, (wasGranted ? "Un-granting" : "Not granting")
+ " permission " + perm
+ " from package " + friendlyName
+ " (protectionLevel=" + bp.getProtectionLevel()
+ " flags=0x"
@@ -2934,20 +2920,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
ps))
+ ")");
}
} else if (bp.isAppOp()) {
// Don't print warning for app op permissions, since it is fine for them
// not to be granted, there is a UI for the user to decide.
if (DEBUG_PERMISSIONS
&& (packageOfInterest == null
|| packageOfInterest.equals(pkg.getPackageName()))) {
Slog.i(TAG, "Not granting permission " + perm
+ " to package " + friendlyName
+ " (protectionLevel=" + bp.getProtectionLevel()
+ " flags=0x"
+ Integer.toHexString(PackageInfoUtils.appInfoFlags(pkg,
ps))
+ ")");
}
}
if (uidState.removePermissionState(bp.name)) {
changedInstallPermission = true;
}
}
}
@@ -3026,8 +3001,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
if ((flags & BLOCKING_PERMISSION_FLAGS) == 0
&& supportsRuntimePermissions) {
int revokeResult = ps.revokePermission(bp);
if (revokeResult != PERMISSION_OPERATION_FAILURE) {
if (ps.revokePermission(bp)) {
if (DEBUG_PERMISSIONS) {
Slog.i(TAG, "Revoking runtime permission "
+ permission + " for " + pkgName
@@ -3895,14 +3869,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
// The package is gone - no need to keep flags for applying policy.
uidState.updatePermissionFlags(bp, PackageManager.MASK_PERMISSION_FLAGS_ALL, 0);
// Try to revoke as a runtime permission which is per user.
// TODO(zhanghai): This doesn't make sense. revokePermission() doesn't fail, and why are
// we only killing the uid when gids changed, instead of any permission change?
if (uidState.revokePermission(bp)
== UidPermissionState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED) {
// TODO(zhanghai): Why are we only killing the UID when GIDs changed, instead of any
// permission change?
if (uidState.removePermissionState(bp.name) && bp.hasGids()) {
affectedUserId = userId;
}
}
@@ -3935,17 +3904,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
boolean runtimePermissionChanged = false;
// Prune permissions
final List<com.android.server.pm.permission.PermissionState> permissionStates =
uidState.getPermissionStates();
final List<PermissionState> permissionStates = uidState.getPermissionStates();
final int permissionStatesSize = permissionStates.size();
for (int i = permissionStatesSize - 1; i >= 0; i--) {
PermissionState permissionState = permissionStates.get(i);
if (!usedPermissions.contains(permissionState.getName())) {
BasePermission bp = mSettings.getPermissionLocked(permissionState.getName());
if (bp != null) {
uidState.revokePermission(bp);
uidState.updatePermissionFlags(bp, MASK_PERMISSION_FLAGS_ALL, 0);
if (permissionState.isRuntime()) {
if (uidState.removePermissionState(bp.name) && permissionState.isRuntime()) {
runtimePermissionChanged = true;
}
}
@@ -4208,11 +4174,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
+ p.getPackageName() + " and user " + userId);
return;
}
if (uidState.getPermissionState(bp.getName()) != null) {
uidState.revokePermission(bp);
uidState.updatePermissionFlags(bp, MASK_PERMISSION_FLAGS_ALL,
0);
}
uidState.removePermissionState(bp.name);
}
});
}
@@ -4771,7 +4733,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
Slog.e(TAG, "Missing permissions state for app ID " + appId + " and user ID " + userId);
return EMPTY_INT_ARRAY;
}
return uidState.computeGids(userId);
return uidState.computeGids(mGlobalGids, userId);
}
private class PermissionManagerServiceInternalImpl extends PermissionManagerServiceInternal {
@@ -4834,7 +4796,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@UserIdInt int userId) {
return PermissionManagerService.this.getGrantedPermissions(packageName, userId);
}
@Nullable
@NonNull
@Override
public int[] getPermissionGids(@NonNull String permissionName, @UserIdInt int userId) {
return PermissionManagerService.this.getPermissionGids(permissionName, userId);

View File

@@ -17,7 +17,6 @@
package com.android.server.pm.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
import com.android.internal.annotations.GuardedBy;
@@ -62,7 +61,7 @@ public final class PermissionState {
return mPermission.getName();
}
@Nullable
@NonNull
public int[] computeGids(@UserIdInt int userId) {
return mPermission.computeGids(userId);
}

View File

@@ -22,35 +22,19 @@ import android.annotation.UserIdInt;
import android.content.pm.PackageManager;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.IntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* Permission state for a UID.
* <p>
* This class is also responsible for keeping track of the Linux GIDs per
* user for a package or a shared user. The GIDs are computed as a set of
* the GIDs for all granted permissions' GIDs on a per user basis.
*/
public final class UidPermissionState {
/** The permission operation failed. */
public static final int PERMISSION_OPERATION_FAILURE = -1;
/** The permission operation succeeded and no gids changed. */
public static final int PERMISSION_OPERATION_SUCCESS = 0;
/** The permission operation succeeded and gids changed. */
public static final int PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED = 1;
private static final int[] NO_GIDS = {};
@NonNull
private final Object mLock = new Object();
@@ -60,11 +44,6 @@ public final class UidPermissionState {
@Nullable
private ArrayMap<String, PermissionState> mPermissions;
private boolean mPermissionReviewRequired;
@NonNull
private int[] mGlobalGids = NO_GIDS;
public UidPermissionState() {}
public UidPermissionState(@NonNull UidPermissionState other) {
@@ -80,12 +59,6 @@ public final class UidPermissionState {
mPermissions.put(name, new PermissionState(permissionState));
}
}
mPermissionReviewRequired = other.mPermissionReviewRequired;
if (other.mGlobalGids != NO_GIDS) {
mGlobalGids = other.mGlobalGids.clone();
}
}
}
@@ -96,8 +69,6 @@ public final class UidPermissionState {
synchronized (mLock) {
mMissing = false;
mPermissions = null;
mPermissionReviewRequired = false;
mGlobalGids = NO_GIDS;
invalidateCache();
}
}
@@ -156,8 +127,8 @@ public final class UidPermissionState {
/**
* Gets the state for a permission or null if none.
*
* @param name the permission name.
* @return the permission state.
* @param name the permission name
* @return the permission state
*/
@Nullable
public PermissionState getPermissionState(@NonNull String name) {
@@ -169,6 +140,22 @@ public final class UidPermissionState {
}
}
@NonNull
private PermissionState getOrCreatePermissionState(@NonNull BasePermission permission) {
synchronized (mLock) {
if (mPermissions == null) {
mPermissions = new ArrayMap<>();
}
final String name = permission.getName();
PermissionState permissionState = mPermissions.get(name);
if (permissionState == null) {
permissionState = new PermissionState(permission);
mPermissions.put(name, permissionState);
}
return permissionState;
}
}
/**
* Get all permission states.
*
@@ -186,19 +173,44 @@ public final class UidPermissionState {
/**
* Put a permission state.
*
* @param permission the permission
* @param granted whether the permission is granted
* @param flags the permission flags
*/
public void putPermissionState(@NonNull BasePermission permission, boolean isGranted,
int flags) {
public void putPermissionState(@NonNull BasePermission permission, boolean granted, int flags) {
synchronized (mLock) {
ensureNoPermissionState(permission.name);
PermissionState permissionState = ensurePermissionState(permission);
if (isGranted) {
final String name = permission.getName();
if (mPermissions == null) {
mPermissions = new ArrayMap<>();
} else {
mPermissions.remove(name);
}
final PermissionState permissionState = new PermissionState(permission);
if (granted) {
permissionState.grant();
}
permissionState.updateFlags(flags, flags);
if ((flags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
mPermissionReviewRequired = true;
mPermissions.put(name, permissionState);
}
}
/**
* Remove a permission state.
*
* @param name the permission name
* @return whether the permission state changed
*/
public boolean removePermissionState(@NonNull String name) {
synchronized (mLock) {
if (mPermissions == null) {
return false;
}
boolean changed = mPermissions.remove(name) != null;
if (changed && mPermissions.isEmpty()) {
mPermissions = null;
}
return changed;
}
}
@@ -209,13 +221,8 @@ public final class UidPermissionState {
* @return whether the permission is granted
*/
public boolean isPermissionGranted(@NonNull String name) {
synchronized (mLock) {
if (mPermissions == null) {
return false;
}
PermissionState permissionState = mPermissions.get(name);
return permissionState != null && permissionState.isGranted();
}
final PermissionState permissionState = getPermissionState(name);
return permissionState != null && permissionState.isGranted();
}
/**
@@ -246,61 +253,37 @@ public final class UidPermissionState {
/**
* Grant a permission.
*
* @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}.
* @param permission the permission to grant
* @return whether the permission grant state changed
*/
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;
public boolean grantPermission(@NonNull BasePermission permission) {
PermissionState permissionState = getOrCreatePermissionState(permission);
return permissionState.grant();
}
/**
* Revoke a permission.
*
* @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}.
* @return whether the permission grant state changed
*/
public int revokePermission(@NonNull BasePermission permission) {
public boolean revokePermission(@NonNull BasePermission permission) {
final String name = permission.getName();
if (!isPermissionGranted(name)) {
return PERMISSION_OPERATION_SUCCESS;
final PermissionState permissionState = getPermissionState(name);
if (permissionState == null) {
return false;
}
PermissionState permissionState;
synchronized (mLock) {
permissionState = mPermissions.get(name);
final boolean changed = permissionState.revoke();
if (changed && permissionState.isDefault()) {
removePermissionState(name);
}
if (!permissionState.revoke()) {
return PERMISSION_OPERATION_FAILURE;
}
if (permissionState.isDefault()) {
ensureNoPermissionState(name);
}
return permission.hasGids() ? PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED
: PERMISSION_OPERATION_SUCCESS;
return changed;
}
/**
* Get the flags for a permission.
*
* @param name the permission name.
* @param name the permission name
* @return the permission flags
*/
public int getPermissionFlags(@NonNull String name) {
@@ -324,76 +307,36 @@ public final class UidPermissionState {
if (flagMask == 0) {
return false;
}
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();
if ((oldFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) == 0
&& (newFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
mPermissionReviewRequired = true;
} else if ((oldFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0
&& (newFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
if (mPermissionReviewRequired && !hasPermissionRequiringReview()) {
mPermissionReviewRequired = false;
}
}
}
return updated;
final PermissionState permissionState = getOrCreatePermissionState(permission);
final boolean changed = permissionState.updateFlags(flagMask, flagValues);
if (changed && permissionState.isDefault()) {
removePermissionState(permission.name);
}
return changed;
}
public boolean updatePermissionFlagsForAllPermissions(int flagMask, int flagValues) {
if (flagMask == 0) {
return false;
}
synchronized (mLock) {
if (mPermissions == null) {
return false;
}
boolean changed = false;
final int permissionsSize = mPermissions.size();
for (int i = 0; i < permissionsSize; i++) {
boolean anyChanged = false;
for (int i = mPermissions.size() - 1; i >= 0; i--) {
final PermissionState permissionState = mPermissions.valueAt(i);
changed |= permissionState.updateFlags(flagMask, flagValues);
}
return changed;
}
}
@NonNull
private PermissionState ensurePermissionState(@NonNull BasePermission permission) {
final String name = permission.getName();
synchronized (mLock) {
if (mPermissions == null) {
mPermissions = new ArrayMap<>();
}
PermissionState permissionState = mPermissions.get(name);
if (permissionState == null) {
permissionState = new PermissionState(permission);
mPermissions.put(name, permissionState);
}
return permissionState;
}
}
private void ensureNoPermissionState(@NonNull String name) {
synchronized (mLock) {
if (mPermissions == null) {
return;
}
mPermissions.remove(name);
if (mPermissions.isEmpty()) {
mPermissions = null;
final boolean changed = permissionState.updateFlags(flagMask, flagValues);
if (changed && permissionState.isDefault()) {
mPermissions.removeAt(i);
}
anyChanged |= changed;
}
return anyChanged;
}
}
public boolean isPermissionReviewRequired() {
return mPermissionReviewRequired;
}
private boolean hasPermissionRequiringReview() {
synchronized (mLock) {
final int permissionsSize = mPermissions.size();
for (int i = 0; i < permissionsSize; i++) {
@@ -406,27 +349,6 @@ public final class UidPermissionState {
}
}
/**
* Gets the global gids, applicable to all users.
*/
@NonNull
public int[] getGlobalGids() {
return mGlobalGids;
}
/**
* Sets the global gids, applicable to all users.
*
* @param globalGids The global gids.
*/
public void setGlobalGids(@NonNull int[] globalGids) {
if (!ArrayUtils.isEmpty(globalGids)) {
mGlobalGids = Arrays.copyOf(globalGids, globalGids.length);
} else {
mGlobalGids = NO_GIDS;
}
}
/**
* Compute the Linux GIDs from the permissions granted to a user.
*
@@ -434,54 +356,25 @@ public final class UidPermissionState {
* @return the GIDs for the user
*/
@NonNull
public int[] computeGids(@UserIdInt int userId) {
int[] gids = mGlobalGids;
public int[] computeGids(@NonNull int[] globalGids, @UserIdInt int userId) {
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);
}
IntArray gids = IntArray.wrap(globalGids);
if (mPermissions == null) {
return gids.toArray();
}
final int permissionsSize = mPermissions.size();
for (int i = 0; i < permissionsSize; i++) {
PermissionState permissionState = mPermissions.valueAt(i);
if (!permissionState.isGranted()) {
continue;
}
final int[] permissionGids = permissionState.computeGids(userId);
if (permissionGids.length != 0) {
gids.addAll(permissionGids);
}
}
return gids.toArray();
}
return gids;
}
/**
* Compute the Linux GIDs from the permissions granted to specified users.
*
* @param userIds the user IDs
* @return the GIDs for the user
*/
@NonNull
public int[] computeGids(@NonNull int[] userIds) {
int[] gids = mGlobalGids;
for (final int userId : userIds) {
final int[] userGids = computeGids(userId);
gids = appendInts(gids, userGids);
}
return gids;
}
// TODO: fix this to use arraycopy and append all ints in one go
private static int[] appendInts(int[] current, int[] added) {
if (current != null && added != null) {
for (int guid : added) {
current = ArrayUtils.appendInt(current, guid);
}
}
return current;
}
static void invalidateCache() {