Add synchronization for PermissionData.
Concurrent modifications of mUserStates need to be synchronized.
Fixes: 142476570
Test: presubmit
Change-Id: If0f57bd8027a5631a81f377907205db67d6979a8
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 505a0e2..b68d541 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionsState.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionsState.java
@@ -23,6 +23,7 @@
import android.util.SparseArray;
import android.util.SparseBooleanArray;
+import com.android.internal.annotations.GuardedBy;
import com.android.internal.util.ArrayUtils;
import java.util.ArrayList;
@@ -30,7 +31,6 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
-import com.android.internal.annotations.GuardedBy;
/**
* This class encapsulates the permissions for a package or a shared user.
@@ -708,7 +708,11 @@
}
private static final class PermissionData {
+
+ private final Object mLock = new Object();
+
private final BasePermission mPerm;
+ @GuardedBy("mLock")
private SparseArray<PermissionState> mUserStates = new SparseArray<>();
public PermissionData(BasePermission perm) {
@@ -717,11 +721,14 @@
public PermissionData(PermissionData other) {
this(other.mPerm);
- final int otherStateCount = other.mUserStates.size();
- for (int i = 0; i < otherStateCount; i++) {
- final int otherUserId = other.mUserStates.keyAt(i);
- PermissionState otherState = other.mUserStates.valueAt(i);
- mUserStates.put(otherUserId, new PermissionState(otherState));
+
+ synchronized (mLock) {
+ final int otherStateCount = other.mUserStates.size();
+ for (int i = 0; i < otherStateCount; i++) {
+ final int otherUserId = other.mUserStates.keyAt(i);
+ PermissionState otherState = other.mUserStates.valueAt(i);
+ mUserStates.put(otherUserId, new PermissionState(otherState));
+ }
}
}
@@ -730,71 +737,83 @@
}
public boolean isGranted(int userId) {
- if (isInstallPermission()) {
- userId = UserHandle.USER_ALL;
- }
+ synchronized (mLock) {
+ if (isInstallPermission()) {
+ userId = UserHandle.USER_ALL;
+ }
- PermissionState userState = mUserStates.get(userId);
- if (userState == null) {
- return false;
- }
+ PermissionState userState = mUserStates.get(userId);
+ if (userState == null) {
+ return false;
+ }
- return userState.mGranted;
+ return userState.mGranted;
+ }
}
public boolean grant(int userId) {
- if (!isCompatibleUserId(userId)) {
- return false;
+ synchronized (mLock) {
+ if (!isCompatibleUserId(userId)) {
+ return false;
+ }
+
+ if (isGranted(userId)) {
+ return false;
+ }
+
+ PermissionState userState = mUserStates.get(userId);
+ if (userState == null) {
+ userState = new PermissionState(mPerm.getName());
+ mUserStates.put(userId, userState);
+ }
+
+ userState.mGranted = true;
+
+ return true;
}
-
- if (isGranted(userId)) {
- return false;
- }
-
- PermissionState userState = mUserStates.get(userId);
- if (userState == null) {
- userState = new PermissionState(mPerm.getName());
- mUserStates.put(userId, userState);
- }
-
- userState.mGranted = true;
-
- return true;
}
public boolean revoke(int userId) {
- if (!isCompatibleUserId(userId)) {
- return false;
+ synchronized (mLock) {
+ if (!isCompatibleUserId(userId)) {
+ return false;
+ }
+
+ if (!isGranted(userId)) {
+ return false;
+ }
+
+ PermissionState userState = mUserStates.get(userId);
+ userState.mGranted = false;
+
+ if (userState.isDefault()) {
+ mUserStates.remove(userId);
+ }
+
+ return true;
}
-
- if (!isGranted(userId)) {
- return false;
- }
-
- PermissionState userState = mUserStates.get(userId);
- userState.mGranted = false;
-
- if (userState.isDefault()) {
- mUserStates.remove(userId);
- }
-
- return true;
}
public PermissionState getPermissionState(int userId) {
- return mUserStates.get(userId);
+ synchronized (mLock) {
+ return mUserStates.get(userId);
+ }
}
public int getFlags(int userId) {
- PermissionState userState = mUserStates.get(userId);
- if (userState != null) {
- return userState.mFlags;
+ synchronized (mLock) {
+ PermissionState userState = mUserStates.get(userId);
+ if (userState != null) {
+ return userState.mFlags;
+ }
+ return 0;
}
- return 0;
}
public boolean isDefault() {
- return mUserStates.size() <= 0;
+ synchronized (mLock) {
+ return mUserStates.size() <= 0;
+ }
}
public static boolean isInstallPermissionKey(int userId) {
@@ -802,32 +821,34 @@
}
public boolean updateFlags(int userId, int flagMask, int flagValues) {
- if (isInstallPermission()) {
- userId = UserHandle.USER_ALL;
- }
+ synchronized (mLock) {
+ if (isInstallPermission()) {
+ userId = UserHandle.USER_ALL;
+ }
- if (!isCompatibleUserId(userId)) {
+ if (!isCompatibleUserId(userId)) {
+ return false;
+ }
+
+ final int newFlags = flagValues & flagMask;
+
+ PermissionState userState = mUserStates.get(userId);
+ if (userState != null) {
+ final int oldFlags = userState.mFlags;
+ userState.mFlags = (userState.mFlags & ~flagMask) | newFlags;
+ if (userState.isDefault()) {
+ mUserStates.remove(userId);
+ }
+ return userState.mFlags != oldFlags;
+ } else if (newFlags != 0) {
+ userState = new PermissionState(mPerm.getName());
+ userState.mFlags = newFlags;
+ mUserStates.put(userId, userState);
+ return true;
+ }
+
return false;
}
-
- final int newFlags = flagValues & flagMask;
-
- PermissionState userState = mUserStates.get(userId);
- if (userState != null) {
- final int oldFlags = userState.mFlags;
- userState.mFlags = (userState.mFlags & ~flagMask) | newFlags;
- if (userState.isDefault()) {
- mUserStates.remove(userId);
- }
- return userState.mFlags != oldFlags;
- } else if (newFlags != 0) {
- userState = new PermissionState(mPerm.getName());
- userState.mFlags = newFlags;
- mUserStates.put(userId, userState);
- return true;
- }
-
- return false;
}
private boolean isCompatibleUserId(int userId) {