summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/policy/PermissionPolicyService.java116
-rw-r--r--services/core/java/com/android/server/policy/TEST_MAPPING3
2 files changed, 98 insertions, 21 deletions
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 3a78aa2fbbf5..037293f9536c 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -50,6 +50,7 @@ import android.permission.PermissionControllerManager;
import android.provider.Telephony;
import android.telecom.TelecomManager;
import android.util.ArraySet;
+import android.util.LongSparseLongArray;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseBooleanArray;
@@ -58,6 +59,7 @@ import android.util.SparseIntArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
+import com.android.internal.util.IntPair;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -147,11 +149,9 @@ public final class PermissionPolicyService extends SystemService {
PermissionInfo perm = dangerousPerms.get(i);
if (perm.isHardRestricted() || perm.backgroundPermission != null) {
- appOpsService.startWatchingMode(AppOpsManager.permissionToOpCode(perm.name),
- null, appOpsListener);
+ appOpsService.startWatchingMode(getSwitchOp(perm.name), null, appOpsListener);
} else if (perm.isSoftRestricted()) {
- appOpsService.startWatchingMode(AppOpsManager.permissionToOpCode(perm.name),
- null, appOpsListener);
+ appOpsService.startWatchingMode(getSwitchOp(perm.name), null, appOpsListener);
SoftRestrictedPermissionPolicy policy =
SoftRestrictedPermissionPolicy.forPermission(null, null, null,
@@ -167,6 +167,25 @@ public final class PermissionPolicyService extends SystemService {
}
}
+ /**
+ * Get op that controls the access related to the permission.
+ *
+ * <p>Usually the permission-op relationship is 1:1 but some permissions (e.g. fine location)
+ * {@link AppOpsManager#sOpToSwitch share an op} to control the access.
+ *
+ * @param permission The permission
+ *
+ * @return The op that controls the access of the permission
+ */
+ private static int getSwitchOp(@NonNull String permission) {
+ int op = AppOpsManager.permissionToOpCode(permission);
+ if (op == OP_NONE) {
+ return OP_NONE;
+ }
+
+ return AppOpsManager.opToSwitch(op);
+ }
+
private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName,
@UserIdInt int changedUserId) {
if (isStarted(changedUserId)) {
@@ -430,40 +449,89 @@ public final class PermissionPolicyService extends SystemService {
* <p>This processes ops previously added by {@link #addOpIfRestricted}
*/
private void syncPackages() {
+ // Remember which ops were already set. This makes sure that we always set the most
+ // permissive mode if two OpChanges are scheduled. This can e.g. happen if two
+ // permissions change the same op. See {@link #getSwitchOp}.
+ LongSparseLongArray alreadySetAppOps = new LongSparseLongArray();
+
final int allowCount = mOpsToAllow.size();
for (int i = 0; i < allowCount; i++) {
final OpToChange op = mOpsToAllow.get(i);
+
setUidModeAllowed(op.code, op.uid, op.packageName);
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
+
final int allowIfDefaultCount = mOpsToAllowIfDefault.size();
for (int i = 0; i < allowIfDefaultCount; i++) {
final OpToChange op = mOpsToAllowIfDefault.get(i);
- setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
+ boolean wasSet = setUidModeAllowedIfDefault(op.code, op.uid, op.packageName);
+ if (wasSet) {
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
+ }
}
- final int foregroundCount = mOpsToForegroundIfAllow.size();
- for (int i = 0; i < foregroundCount; i++) {
+
+ final int foregroundIfAllowedCount = mOpsToForegroundIfAllow.size();
+ for (int i = 0; i < foregroundIfAllowedCount; i++) {
final OpToChange op = mOpsToForegroundIfAllow.get(i);
- setUidModeForegroundIfAllow(op.code, op.uid, op.packageName);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
+ boolean wasSet = setUidModeForegroundIfAllow(op.code, op.uid, op.packageName);
+ if (wasSet) {
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
+ }
}
- final int foregroundIfAllowCount = mOpsToForeground.size();
- for (int i = 0; i < foregroundIfAllowCount; i++) {
+
+ final int foregroundCount = mOpsToForeground.size();
+ for (int i = 0; i < foregroundCount; i++) {
final OpToChange op = mOpsToForeground.get(i);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
setUidModeForeground(op.code, op.uid, op.packageName);
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
+
final int ignoreCount = mOpsToIgnore.size();
for (int i = 0; i < ignoreCount; i++) {
final OpToChange op = mOpsToIgnore.get(i);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
setUidModeIgnored(op.code, op.uid, op.packageName);
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
+
final int ignoreIfDefaultCount = mOpsToIgnoreIfDefault.size();
for (int i = 0; i < ignoreIfDefaultCount; i++) {
final OpToChange op = mOpsToIgnoreIfDefault.get(i);
- setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
+ boolean wasSet = setUidModeIgnoredIfDefault(op.code, op.uid, op.packageName);
+ if (wasSet) {
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
+ }
}
+
final int defaultCount = mOpsToDefault.size();
for (int i = 0; i < defaultCount; i++) {
final OpToChange op = mOpsToDefault.get(i);
+ if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
+ continue;
+ }
+
setUidModeDefault(op.code, op.uid, op.packageName);
+ alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
}
@@ -479,7 +547,7 @@ public final class PermissionPolicyService extends SystemService {
private void addOpIfRestricted(@NonNull PermissionInfo permissionInfo,
@NonNull PackageInfo pkg) {
final String permission = permissionInfo.name;
- final int opCode = AppOpsManager.permissionToOpCode(permission);
+ final int opCode = getSwitchOp(permission);
final int uid = pkg.applicationInfo.uid;
if (!permissionInfo.isRestricted()) {
@@ -581,7 +649,7 @@ public final class PermissionPolicyService extends SystemService {
}
final String permission = permissionInfo.name;
- final int opCode = AppOpsManager.permissionToOpCode(permission);
+ final int opCode = getSwitchOp(permission);
final String pkgName = pkg.packageName;
final int uid = pkg.applicationInfo.uid;
@@ -641,7 +709,7 @@ public final class PermissionPolicyService extends SystemService {
}
for (String permission : pkg.requestedPermissions) {
- final int opCode = AppOpsManager.permissionToOpCode(permission);
+ final int opCode = getSwitchOp(permission);
if (opCode == OP_NONE) {
continue;
}
@@ -658,24 +726,27 @@ public final class PermissionPolicyService extends SystemService {
}
}
- private void setUidModeAllowedIfDefault(int opCode, int uid, @NonNull String packageName) {
- setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_ALLOWED, packageName);
+ private boolean setUidModeAllowedIfDefault(int opCode, int uid,
+ @NonNull String packageName) {
+ return setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_ALLOWED, packageName);
}
private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_ALLOWED, packageName);
}
- private void setUidModeForegroundIfAllow(int opCode, int uid, @NonNull String packageName) {
- setUidModeIfMode(opCode, uid, MODE_ALLOWED, MODE_FOREGROUND, packageName);
+ private boolean setUidModeForegroundIfAllow(int opCode, int uid,
+ @NonNull String packageName) {
+ return setUidModeIfMode(opCode, uid, MODE_ALLOWED, MODE_FOREGROUND, packageName);
}
private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
}
- private void setUidModeIgnoredIfDefault(int opCode, int uid, @NonNull String packageName) {
- setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_IGNORED, packageName);
+ private boolean setUidModeIgnoredIfDefault(int opCode, int uid,
+ @NonNull String packageName) {
+ return setUidModeIfMode(opCode, uid, MODE_DEFAULT, MODE_IGNORED, packageName);
}
private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
@@ -692,14 +763,17 @@ public final class PermissionPolicyService extends SystemService {
}
}
- private void setUidModeIfMode(int opCode, int uid, int requiredModeBefore, int newMode,
+ private boolean setUidModeIfMode(int opCode, int uid, int requiredModeBefore, int newMode,
@NonNull String packageName) {
final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager
.opToPublicName(opCode), uid, packageName);
if (currentMode == requiredModeBefore) {
mAppOpsManager.setUidMode(opCode, uid, newMode);
+ return true;
}
+
+ return false;
}
private void setUidModeDefault(int opCode, int uid, String packageName) {
diff --git a/services/core/java/com/android/server/policy/TEST_MAPPING b/services/core/java/com/android/server/policy/TEST_MAPPING
index c7f8c07432a8..c7e241b35e9a 100644
--- a/services/core/java/com/android/server/policy/TEST_MAPPING
+++ b/services/core/java/com/android/server/policy/TEST_MAPPING
@@ -41,6 +41,9 @@
"options": [
{
"include-filter": "android.permission.cts.SplitPermissionTest"
+ },
+ {
+ "include-filter": "android.permission.cts.BackgroundPermissionsTest"
}
]
}