Merge "Synchronize mPermissions to void NullPointerException."
am: 9e7c6b3865
Change-Id: I8cb95984bf85c6a687d20fa9cd7305b712754439
This commit is contained in:
@@ -30,6 +30,7 @@ import java.util.Arrays;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import com.android.internal.annotations.GuardedBy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class encapsulates the permissions for a package or a shared user.
|
* This class encapsulates the permissions for a package or a shared user.
|
||||||
@@ -62,6 +63,9 @@ public final class PermissionsState {
|
|||||||
|
|
||||||
private static final int[] NO_GIDS = {};
|
private static final int[] NO_GIDS = {};
|
||||||
|
|
||||||
|
private final Object mLock = new Object();
|
||||||
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
private ArrayMap<String, PermissionData> mPermissions;
|
private ArrayMap<String, PermissionData> mPermissions;
|
||||||
|
|
||||||
private int[] mGlobalGids = NO_GIDS;
|
private int[] mGlobalGids = NO_GIDS;
|
||||||
@@ -96,22 +100,25 @@ public final class PermissionsState {
|
|||||||
if (other == this) {
|
if (other == this) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mPermissions != null) {
|
|
||||||
if (other.mPermissions == null) {
|
synchronized (mLock) {
|
||||||
mPermissions = null;
|
if (mPermissions != null) {
|
||||||
} else {
|
if (other.mPermissions == null) {
|
||||||
mPermissions.clear();
|
mPermissions = null;
|
||||||
|
} else {
|
||||||
|
mPermissions.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if (other.mPermissions != null) {
|
||||||
if (other.mPermissions != null) {
|
if (mPermissions == null) {
|
||||||
if (mPermissions == null) {
|
mPermissions = new ArrayMap<>();
|
||||||
mPermissions = new ArrayMap<>();
|
}
|
||||||
}
|
final int permissionCount = other.mPermissions.size();
|
||||||
final int permissionCount = other.mPermissions.size();
|
for (int i = 0; i < permissionCount; i++) {
|
||||||
for (int i = 0; i < permissionCount; i++) {
|
String name = other.mPermissions.keyAt(i);
|
||||||
String name = other.mPermissions.keyAt(i);
|
PermissionData permissionData = other.mPermissions.valueAt(i);
|
||||||
PermissionData permissionData = other.mPermissions.valueAt(i);
|
mPermissions.put(name, new PermissionData(permissionData));
|
||||||
mPermissions.put(name, new PermissionData(permissionData));
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,13 +160,16 @@ public final class PermissionsState {
|
|||||||
}
|
}
|
||||||
final PermissionsState other = (PermissionsState) obj;
|
final PermissionsState other = (PermissionsState) obj;
|
||||||
|
|
||||||
if (mPermissions == null) {
|
synchronized (mLock) {
|
||||||
if (other.mPermissions != null) {
|
if (mPermissions == null) {
|
||||||
|
if (other.mPermissions != null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (!mPermissions.equals(other.mPermissions)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (!mPermissions.equals(other.mPermissions)) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mPermissionReviewRequired == null) {
|
if (mPermissionReviewRequired == null) {
|
||||||
if (other.mPermissionReviewRequired != null) {
|
if (other.mPermissionReviewRequired != null) {
|
||||||
return false;
|
return false;
|
||||||
@@ -266,12 +276,15 @@ public final class PermissionsState {
|
|||||||
public boolean hasPermission(String name, int userId) {
|
public boolean hasPermission(String name, int userId) {
|
||||||
enforceValidUserId(userId);
|
enforceValidUserId(userId);
|
||||||
|
|
||||||
if (mPermissions == null) {
|
synchronized (mLock) {
|
||||||
return false;
|
if (mPermissions == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PermissionData permissionData = mPermissions.get(name);
|
||||||
|
|
||||||
|
return permissionData != null && permissionData.isGranted(userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
PermissionData permissionData = mPermissions.get(name);
|
|
||||||
return permissionData != null && permissionData.isGranted(userId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -279,14 +292,17 @@ public final class PermissionsState {
|
|||||||
* whether or not it has been granted.
|
* whether or not it has been granted.
|
||||||
*/
|
*/
|
||||||
public boolean hasRequestedPermission(ArraySet<String> names) {
|
public boolean hasRequestedPermission(ArraySet<String> names) {
|
||||||
if (mPermissions == null) {
|
synchronized (mLock) {
|
||||||
return false;
|
if (mPermissions == null) {
|
||||||
}
|
return false;
|
||||||
for (int i=names.size()-1; i>=0; i--) {
|
}
|
||||||
if (mPermissions.get(names.valueAt(i)) != null) {
|
for (int i=names.size()-1; i>=0; i--) {
|
||||||
return true;
|
if (mPermissions.get(names.valueAt(i)) != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,29 +316,31 @@ public final class PermissionsState {
|
|||||||
public Set<String> getPermissions(int userId) {
|
public Set<String> getPermissions(int userId) {
|
||||||
enforceValidUserId(userId);
|
enforceValidUserId(userId);
|
||||||
|
|
||||||
if (mPermissions == null) {
|
synchronized (mLock) {
|
||||||
return Collections.emptySet();
|
if (mPermissions == null) {
|
||||||
}
|
return Collections.emptySet();
|
||||||
|
|
||||||
Set<String> permissions = new ArraySet<>(mPermissions.size());
|
|
||||||
|
|
||||||
final int permissionCount = mPermissions.size();
|
|
||||||
for (int i = 0; i < permissionCount; i++) {
|
|
||||||
String permission = mPermissions.keyAt(i);
|
|
||||||
|
|
||||||
if (hasInstallPermission(permission)) {
|
|
||||||
permissions.add(permission);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (userId != UserHandle.USER_ALL) {
|
Set<String> permissions = new ArraySet<>(mPermissions.size());
|
||||||
if (hasRuntimePermission(permission, userId)) {
|
|
||||||
|
final int permissionCount = mPermissions.size();
|
||||||
|
for (int i = 0; i < permissionCount; i++) {
|
||||||
|
String permission = mPermissions.keyAt(i);
|
||||||
|
|
||||||
|
if (hasInstallPermission(permission)) {
|
||||||
permissions.add(permission);
|
permissions.add(permission);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (userId != UserHandle.USER_ALL) {
|
||||||
|
if (hasRuntimePermission(permission, userId)) {
|
||||||
|
permissions.add(permission);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return permissions;
|
return permissions;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -399,14 +417,20 @@ public final class PermissionsState {
|
|||||||
|
|
||||||
final boolean mayChangeFlags = flagValues != 0 || flagMask != 0;
|
final boolean mayChangeFlags = flagValues != 0 || flagMask != 0;
|
||||||
|
|
||||||
if (mPermissions == null) {
|
synchronized (mLock) {
|
||||||
if (!mayChangeFlags) {
|
if (mPermissions == null) {
|
||||||
return false;
|
if (!mayChangeFlags) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ensurePermissionData(permission);
|
||||||
}
|
}
|
||||||
ensurePermissionData(permission);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PermissionData permissionData = mPermissions.get(permission.getName());
|
PermissionData permissionData = null;
|
||||||
|
synchronized (mLock) {
|
||||||
|
permissionData = mPermissions.get(permission.getName());
|
||||||
|
}
|
||||||
|
|
||||||
if (permissionData == null) {
|
if (permissionData == null) {
|
||||||
if (!mayChangeFlags) {
|
if (!mayChangeFlags) {
|
||||||
return false;
|
return false;
|
||||||
@@ -439,14 +463,17 @@ public final class PermissionsState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasPermissionRequiringReview(int userId) {
|
private boolean hasPermissionRequiringReview(int userId) {
|
||||||
final int permissionCount = mPermissions.size();
|
synchronized (mLock) {
|
||||||
for (int i = 0; i < permissionCount; i++) {
|
final int permissionCount = mPermissions.size();
|
||||||
final PermissionData permission = mPermissions.valueAt(i);
|
for (int i = 0; i < permissionCount; i++) {
|
||||||
if ((permission.getFlags(userId)
|
final PermissionData permission = mPermissions.valueAt(i);
|
||||||
& PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
|
if ((permission.getFlags(userId)
|
||||||
return true;
|
& PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,16 +481,19 @@ public final class PermissionsState {
|
|||||||
int userId, int flagMask, int flagValues) {
|
int userId, int flagMask, int flagValues) {
|
||||||
enforceValidUserId(userId);
|
enforceValidUserId(userId);
|
||||||
|
|
||||||
if (mPermissions == null) {
|
synchronized (mLock) {
|
||||||
return false;
|
if (mPermissions == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean changed = false;
|
||||||
|
final int permissionCount = mPermissions.size();
|
||||||
|
for (int i = 0; i < permissionCount; i++) {
|
||||||
|
PermissionData permissionData = mPermissions.valueAt(i);
|
||||||
|
changed |= permissionData.updateFlags(userId, flagMask, flagValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
return changed;
|
||||||
}
|
}
|
||||||
boolean changed = false;
|
|
||||||
final int permissionCount = mPermissions.size();
|
|
||||||
for (int i = 0; i < permissionCount; i++) {
|
|
||||||
PermissionData permissionData = mPermissions.valueAt(i);
|
|
||||||
changed |= permissionData.updateFlags(userId, flagMask, flagValues);
|
|
||||||
}
|
|
||||||
return changed;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -479,17 +509,19 @@ public final class PermissionsState {
|
|||||||
|
|
||||||
int[] gids = mGlobalGids;
|
int[] gids = mGlobalGids;
|
||||||
|
|
||||||
if (mPermissions != null) {
|
synchronized (mLock) {
|
||||||
final int permissionCount = mPermissions.size();
|
if (mPermissions != null) {
|
||||||
for (int i = 0; i < permissionCount; i++) {
|
final int permissionCount = mPermissions.size();
|
||||||
String permission = mPermissions.keyAt(i);
|
for (int i = 0; i < permissionCount; i++) {
|
||||||
if (!hasPermission(permission, userId)) {
|
String permission = mPermissions.keyAt(i);
|
||||||
continue;
|
if (!hasPermission(permission, userId)) {
|
||||||
}
|
continue;
|
||||||
PermissionData permissionData = mPermissions.valueAt(i);
|
}
|
||||||
final int[] permGids = permissionData.computeGids(userId);
|
PermissionData permissionData = mPermissions.valueAt(i);
|
||||||
if (permGids != NO_GIDS) {
|
final int[] permGids = permissionData.computeGids(userId);
|
||||||
gids = appendInts(gids, permGids);
|
if (permGids != NO_GIDS) {
|
||||||
|
gids = appendInts(gids, permGids);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -519,41 +551,50 @@ public final class PermissionsState {
|
|||||||
*/
|
*/
|
||||||
public void reset() {
|
public void reset() {
|
||||||
mGlobalGids = NO_GIDS;
|
mGlobalGids = NO_GIDS;
|
||||||
mPermissions = null;
|
|
||||||
|
synchronized (mLock) {
|
||||||
|
mPermissions = null;
|
||||||
|
}
|
||||||
|
|
||||||
mPermissionReviewRequired = null;
|
mPermissionReviewRequired = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PermissionState getPermissionState(String name, int userId) {
|
private PermissionState getPermissionState(String name, int userId) {
|
||||||
if (mPermissions == null) {
|
synchronized (mLock) {
|
||||||
return null;
|
if (mPermissions == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
PermissionData permissionData = mPermissions.get(name);
|
||||||
|
if (permissionData == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissionData.getPermissionState(userId);
|
||||||
}
|
}
|
||||||
PermissionData permissionData = mPermissions.get(name);
|
|
||||||
if (permissionData == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return permissionData.getPermissionState(userId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PermissionState> getPermissionStatesInternal(int userId) {
|
private List<PermissionState> getPermissionStatesInternal(int userId) {
|
||||||
enforceValidUserId(userId);
|
enforceValidUserId(userId);
|
||||||
|
|
||||||
if (mPermissions == null) {
|
synchronized (mLock) {
|
||||||
return Collections.emptyList();
|
if (mPermissions == null) {
|
||||||
}
|
return Collections.emptyList();
|
||||||
|
|
||||||
List<PermissionState> permissionStates = new ArrayList<>();
|
|
||||||
|
|
||||||
final int permissionCount = mPermissions.size();
|
|
||||||
for (int i = 0; i < permissionCount; i++) {
|
|
||||||
PermissionData permissionData = mPermissions.valueAt(i);
|
|
||||||
|
|
||||||
PermissionState permissionState = permissionData.getPermissionState(userId);
|
|
||||||
if (permissionState != null) {
|
|
||||||
permissionStates.add(permissionState);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return permissionStates;
|
List<PermissionState> permissionStates = new ArrayList<>();
|
||||||
|
|
||||||
|
final int permissionCount = mPermissions.size();
|
||||||
|
for (int i = 0; i < permissionCount; i++) {
|
||||||
|
PermissionData permissionData = mPermissions.valueAt(i);
|
||||||
|
|
||||||
|
PermissionState permissionState = permissionData.getPermissionState(userId);
|
||||||
|
if (permissionState != null) {
|
||||||
|
permissionStates.add(permissionState);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return permissionStates;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int grantPermission(BasePermission permission, int userId) {
|
private int grantPermission(BasePermission permission, int userId) {
|
||||||
@@ -589,7 +630,10 @@ public final class PermissionsState {
|
|||||||
final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId));
|
final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId));
|
||||||
final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS;
|
final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS;
|
||||||
|
|
||||||
PermissionData permissionData = mPermissions.get(permName);
|
PermissionData permissionData = null;
|
||||||
|
synchronized (mLock) {
|
||||||
|
permissionData = mPermissions.get(permName);
|
||||||
|
}
|
||||||
|
|
||||||
if (!permissionData.revoke(userId)) {
|
if (!permissionData.revoke(userId)) {
|
||||||
return PERMISSION_OPERATION_FAILURE;
|
return PERMISSION_OPERATION_FAILURE;
|
||||||
@@ -627,25 +671,32 @@ public final class PermissionsState {
|
|||||||
|
|
||||||
private PermissionData ensurePermissionData(BasePermission permission) {
|
private PermissionData ensurePermissionData(BasePermission permission) {
|
||||||
final String permName = permission.getName();
|
final String permName = permission.getName();
|
||||||
if (mPermissions == null) {
|
|
||||||
mPermissions = new ArrayMap<>();
|
synchronized (mLock) {
|
||||||
|
if (mPermissions == null) {
|
||||||
|
mPermissions = new ArrayMap<>();
|
||||||
|
}
|
||||||
|
PermissionData permissionData = mPermissions.get(permName);
|
||||||
|
if (permissionData == null) {
|
||||||
|
permissionData = new PermissionData(permission);
|
||||||
|
mPermissions.put(permName, permissionData);
|
||||||
|
}
|
||||||
|
return permissionData;
|
||||||
}
|
}
|
||||||
PermissionData permissionData = mPermissions.get(permName);
|
|
||||||
if (permissionData == null) {
|
|
||||||
permissionData = new PermissionData(permission);
|
|
||||||
mPermissions.put(permName, permissionData);
|
|
||||||
}
|
|
||||||
return permissionData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ensureNoPermissionData(String name) {
|
private void ensureNoPermissionData(String name) {
|
||||||
if (mPermissions == null) {
|
synchronized (mLock) {
|
||||||
return;
|
if (mPermissions == null) {
|
||||||
}
|
return;
|
||||||
mPermissions.remove(name);
|
}
|
||||||
if (mPermissions.isEmpty()) {
|
mPermissions.remove(name);
|
||||||
mPermissions = null;
|
if (mPermissions.isEmpty()) {
|
||||||
|
mPermissions = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class PermissionData {
|
private static final class PermissionData {
|
||||||
|
|||||||
Reference in New Issue
Block a user