Loading services/core/java/com/android/server/policy/PermissionPolicyService.java +95 −21 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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, Loading @@ -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)) { Loading Loading @@ -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; } final int foregroundCount = mOpsToForegroundIfAllow.size(); for (int i = 0; i < foregroundCount; i++) { boolean wasSet = setUidModeAllowedIfDefault(op.code, op.uid, op.packageName); if (wasSet) { alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1); } } 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); } } Loading @@ -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()) { Loading Loading @@ -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; Loading Loading @@ -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; } Loading @@ -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) { Loading @@ -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) { Loading services/core/java/com/android/server/policy/TEST_MAPPING +3 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,9 @@ "options": [ { "include-filter": "android.permission.cts.SplitPermissionTest" }, { "include-filter": "android.permission.cts.BackgroundPermissionsTest" } ] } Loading Loading
services/core/java/com/android/server/policy/PermissionPolicyService.java +95 −21 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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, Loading @@ -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)) { Loading Loading @@ -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; } final int foregroundCount = mOpsToForegroundIfAllow.size(); for (int i = 0; i < foregroundCount; i++) { boolean wasSet = setUidModeAllowedIfDefault(op.code, op.uid, op.packageName); if (wasSet) { alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1); } } 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); } } Loading @@ -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()) { Loading Loading @@ -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; Loading Loading @@ -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; } Loading @@ -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) { Loading @@ -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) { Loading
services/core/java/com/android/server/policy/TEST_MAPPING +3 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,9 @@ "options": [ { "include-filter": "android.permission.cts.SplitPermissionTest" }, { "include-filter": "android.permission.cts.BackgroundPermissionsTest" } ] } Loading