diff options
8 files changed, 114 insertions, 85 deletions
diff --git a/PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java b/PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java index a9be00806..91b4e1531 100644 --- a/PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java +++ b/PermissionController/role-controller/java/com/android/role/controller/behavior/ReservedForTestingProfileGroupExclusivityRoleBehavior.java @@ -37,8 +37,8 @@ public class ReservedForTestingProfileGroupExclusivityRoleBehavior implements Ro @NonNull Context context) { if (RoleFlags.isProfileGroupExclusivityAvailable()) { Context userContext = UserUtils.getUserContext(context, user); - RoleManager roleManager = userContext.getSystemService(RoleManager.class); - return roleManager.getDefaultHoldersForTest(role.getName()); + RoleManager userRoleManager = userContext.getSystemService(RoleManager.class); + return userRoleManager.getDefaultHoldersForTest(role.getName()); } else { return null; } @@ -49,8 +49,8 @@ public class ReservedForTestingProfileGroupExclusivityRoleBehavior implements Ro @NonNull Context context) { if (RoleFlags.isProfileGroupExclusivityAvailable()) { Context userContext = UserUtils.getUserContext(context, user); - RoleManager roleManager = userContext.getSystemService(RoleManager.class); - return roleManager.isRoleVisibleForTest(role.getName()); + RoleManager userRoleManager = userContext.getSystemService(RoleManager.class); + return userRoleManager.isRoleVisibleForTest(role.getName()); } else { return false; } diff --git a/framework-s/api/system-current.txt b/framework-s/api/system-current.txt index fc06d6927..e312dcd5b 100644 --- a/framework-s/api/system-current.txt +++ b/framework-s/api/system-current.txt @@ -54,7 +54,7 @@ package android.app.role { method @FlaggedApi("com.android.permission.flags.cross_user_role_enabled") @RequiresPermission(allOf={android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, android.Manifest.permission.MANAGE_ROLE_HOLDERS, android.Manifest.permission.MANAGE_DEFAULT_APPLICATIONS}, conditional=true) public void setActiveUserForRole(@NonNull String, @NonNull android.os.UserHandle, int); method @RequiresPermission(android.Manifest.permission.BYPASS_ROLE_QUALIFICATION) public void setBypassingRoleQualification(boolean); method @RequiresPermission(android.Manifest.permission.MANAGE_DEFAULT_APPLICATIONS) public void setDefaultApplication(@NonNull String, @Nullable String, int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<java.lang.Boolean>); - method @FlaggedApi("com.android.permission.flags.cross_user_role_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void setDefaultHoldersForTest(@NonNull String, @Nullable java.util.List<java.lang.String>); + method @FlaggedApi("com.android.permission.flags.cross_user_role_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void setDefaultHoldersForTest(@NonNull String, @NonNull java.util.List<java.lang.String>); method @FlaggedApi("android.permission.flags.system_server_role_controller_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void setRoleFallbackEnabled(@NonNull String, boolean); method @Deprecated @RequiresPermission("com.android.permissioncontroller.permission.MANAGE_ROLES_FROM_CONTROLLER") public void setRoleNamesFromController(@NonNull java.util.List<java.lang.String>); method @FlaggedApi("com.android.permission.flags.cross_user_role_enabled") @RequiresPermission(android.Manifest.permission.MANAGE_ROLE_HOLDERS) public void setRoleVisibleForTest(@NonNull String, boolean); diff --git a/framework-s/java/android/app/role/IRoleManager.aidl b/framework-s/java/android/app/role/IRoleManager.aidl index dc5bc8cb4..cf98a6016 100644 --- a/framework-s/java/android/app/role/IRoleManager.aidl +++ b/framework-s/java/android/app/role/IRoleManager.aidl @@ -85,11 +85,12 @@ interface IRoleManager { boolean isApplicationVisibleForRoleAsUser(in String roleName, in String packageName, int userId); - List<String> getDefaultHoldersForTest(in String roleName); + List<String> getDefaultHoldersForTestAsUser(in String roleName, int userId); - void setDefaultHoldersForTest(in String roleName, in List<String> packageNames); + void setDefaultHoldersForTestAsUser(in String roleName, in List<String> packageNames, + int userId); - boolean isRoleVisibleForTest(in String roleName); + boolean isRoleVisibleForTestAsUser(in String roleName, int userId); - void setRoleVisibleForTest(in String roleName, boolean visible); + void setRoleVisibleForTestAsUser(in String roleName, boolean visible, int userId); } diff --git a/framework-s/java/android/app/role/RoleManager.java b/framework-s/java/android/app/role/RoleManager.java index 42445b4d6..65b513e9d 100644 --- a/framework-s/java/android/app/role/RoleManager.java +++ b/framework-s/java/android/app/role/RoleManager.java @@ -1189,7 +1189,8 @@ public final class RoleManager { public List<String> getDefaultHoldersForTest(@NonNull String roleName) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); try { - return mService.getDefaultHoldersForTest(roleName); + return mService.getDefaultHoldersForTestAsUser(roleName, + mContext.getUser().getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1203,9 +1204,10 @@ public final class RoleManager { * not persisted. * <p> * Throws {@link IllegalArgumentException} if role is not a test role + * Throws {@link NullPointerException} if packageNames is {@code null} * * @param roleName the name of the role to set test default holders for - * @param packageNames a list of package names of the default holders or {@code null} to unset + * @param packageNames a list of package names of the default holders, or an empty list to unset * * @hide */ @@ -1215,10 +1217,12 @@ public final class RoleManager { @UserHandleAware @FlaggedApi(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) public void setDefaultHoldersForTest( - @NonNull String roleName, @Nullable List<String> packageNames) { + @NonNull String roleName, @NonNull List<String> packageNames) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + Objects.requireNonNull(packageNames, "packageNames cannot be null"); try { - mService.setDefaultHoldersForTest(roleName, packageNames); + mService.setDefaultHoldersForTestAsUser(roleName, packageNames, + mContext.getUser().getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1245,7 +1249,8 @@ public final class RoleManager { public boolean isRoleVisibleForTest(@NonNull String roleName) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); try { - return mService.isRoleVisibleForTest(roleName); + return mService.isRoleVisibleForTestAsUser(roleName, + mContext.getUser().getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } @@ -1272,7 +1277,8 @@ public final class RoleManager { public void setRoleVisibleForTest(@NonNull String roleName, boolean visible) { Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); try { - mService.setRoleVisibleForTest(roleName, visible); + mService.setRoleVisibleForTestAsUser(roleName, visible, + mContext.getUser().getIdentifier()); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java index 0fea33899..deb0cf3b0 100644 --- a/service/java/com/android/role/RoleService.java +++ b/service/java/com/android/role/RoleService.java @@ -16,8 +16,6 @@ package com.android.role; -import static android.app.role.RoleManager.ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY; - import android.Manifest; import android.annotation.AnyThread; import android.annotation.MainThread; @@ -52,7 +50,6 @@ import android.permission.flags.Flags; import android.permission.internal.compat.UserHandleCompat; import android.provider.Settings; import android.text.TextUtils; -import android.util.ArrayMap; import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Log; @@ -125,7 +122,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback defaultApplicationRoles.add(RoleManager.ROLE_WALLET); } if (RoleFlags.isProfileGroupExclusivityAvailable()) { - defaultApplicationRoles.add(ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY); + defaultApplicationRoles.add( + RoleManager.ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY); } DEFAULT_APPLICATION_ROLES = defaultApplicationRoles.toArray(new String[0]); } @@ -134,7 +132,8 @@ public class RoleService extends SystemService implements RoleUserState.Callback static { if (RoleFlags.isProfileGroupExclusivityAvailable()) { - TEST_ROLES = new String[] {ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY}; + TEST_ROLES = + new String[] {RoleManager.ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY}; } else { TEST_ROLES = new String[0]; } @@ -185,14 +184,6 @@ public class RoleService extends SystemService implements RoleUserState.Callback private final SparseArray<ThrottledRunnable> mGrantDefaultRolesThrottledRunnables = new SparseArray<>(); - @GuardedBy("mLock") - @NonNull - private final Map<String, List<String>> mDefaultHoldersForTest = new ArrayMap<>(); - - @GuardedBy("mLock") - @NonNull - private final Set<String> mRolesVisibleForTest = new ArraySet<>(); - public RoleService(@NonNull Context context) { super(context); @@ -1192,8 +1183,10 @@ public class RoleService extends SystemService implements RoleUserState.Callback return getOrCreateController(userId).isApplicationVisibleForRole(roleName, packageName); } + @NonNull @Override - public List<String> getDefaultHoldersForTest(String roleName) { + public List<String> getDefaultHoldersForTestAsUser(@NonNull String roleName, + @UserIdInt int userId) { Preconditions.checkState(RoleFlags.isProfileGroupExclusivityAvailable(), "getDefaultHoldersForTest not available"); getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, @@ -1201,31 +1194,25 @@ public class RoleService extends SystemService implements RoleUserState.Callback Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkArgumentIsSupported(TEST_ROLES, roleName); - synchronized (mLock) { - return mDefaultHoldersForTest.getOrDefault(roleName, Collections.emptyList()); - } + return getOrCreateUserState(userId).getDefaultHoldersForTest(roleName); } @Override - public void setDefaultHoldersForTest(String roleName, List<String> packageNames) { + public void setDefaultHoldersForTestAsUser(@NonNull String roleName, + @NonNull List<String> packageNames, @UserIdInt int userId) { Preconditions.checkState(RoleFlags.isProfileGroupExclusivityAvailable(), "setDefaultHoldersForTest not available"); getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, "setDefaultHoldersForTest"); Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkArgumentIsSupported(TEST_ROLES, roleName); + Objects.requireNonNull(packageNames, "packageNames cannot be null"); - synchronized (mLock) { - if (packageNames == null || packageNames.isEmpty()) { - mDefaultHoldersForTest.remove(roleName); - } else { - mDefaultHoldersForTest.put(roleName, packageNames); - } - } + getOrCreateUserState(userId).setDefaultHoldersForTest(roleName, packageNames); } @Override - public boolean isRoleVisibleForTest(String roleName) { + public boolean isRoleVisibleForTestAsUser(@NonNull String roleName, @UserIdInt int userId) { Preconditions.checkState(RoleFlags.isProfileGroupExclusivityAvailable(), "isRoleVisibleForTest not available"); getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, @@ -1233,13 +1220,12 @@ public class RoleService extends SystemService implements RoleUserState.Callback Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkArgumentIsSupported(TEST_ROLES, roleName); - synchronized (mLock) { - return mRolesVisibleForTest.contains(roleName); - } + return getOrCreateUserState(userId).isRoleVisibleForTest(roleName); } @Override - public void setRoleVisibleForTest(String roleName, boolean visible) { + public void setRoleVisibleForTestAsUser(@NonNull String roleName, boolean visible, + @UserIdInt int userId) { Preconditions.checkState(RoleFlags.isProfileGroupExclusivityAvailable(), "setRoleVisibleForTest not available"); getContext().enforceCallingOrSelfPermission(Manifest.permission.MANAGE_ROLE_HOLDERS, @@ -1247,13 +1233,7 @@ public class RoleService extends SystemService implements RoleUserState.Callback Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); Preconditions.checkArgumentIsSupported(TEST_ROLES, roleName); - synchronized (mLock) { - if (visible) { - mRolesVisibleForTest.add(roleName); - } else { - mRolesVisibleForTest.remove(roleName); - } - } + getOrCreateUserState(userId).setRoleVisibleForTest(roleName, visible); } @Override diff --git a/service/java/com/android/role/RoleUserState.java b/service/java/com/android/role/RoleUserState.java index c94b58826..7f59f1385 100644 --- a/service/java/com/android/role/RoleUserState.java +++ b/service/java/com/android/role/RoleUserState.java @@ -102,6 +102,14 @@ class RoleUserState { private ArrayMap<String, Integer> mActiveUserIds = new ArrayMap<>(); @GuardedBy("mLock") + @NonNull + private final Map<String, List<String>> mDefaultHoldersForTest = new ArrayMap<>(); + + @GuardedBy("mLock") + @NonNull + private final Set<String> mRolesVisibleForTest = new ArraySet<>(); + + @GuardedBy("mLock") private boolean mWriteScheduled; @GuardedBy("mLock") @@ -464,6 +472,36 @@ class RoleUserState { } } + @NonNull + public List<String> getDefaultHoldersForTest(@NonNull String roleName) { + synchronized (mLock) { + return mDefaultHoldersForTest.getOrDefault(roleName, Collections.emptyList()); + } + } + + public void setDefaultHoldersForTest(@NonNull String roleName, + @NonNull List<String> packageNames) { + synchronized (mLock) { + mDefaultHoldersForTest.put(roleName, packageNames); + } + } + + public boolean isRoleVisibleForTest(@NonNull String roleName) { + synchronized (mLock) { + return mRolesVisibleForTest.contains(roleName); + } + } + + public void setRoleVisibleForTest(@NonNull String roleName, boolean visible) { + synchronized (mLock) { + if (visible) { + mRolesVisibleForTest.add(roleName); + } else { + mRolesVisibleForTest.remove(roleName); + } + } + } + /** * Schedule writing the state to file. */ diff --git a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java index 00245a086..f26bc0eb5 100644 --- a/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java +++ b/tests/cts/role/src/android/app/role/cts/RoleManagerTest.java @@ -1489,27 +1489,21 @@ public class RoleManagerTest { @RequiresFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, codeName = "Baklava") @Test - public void setAndGetDefaultHolders() throws Exception { - List<String> testRoleHolders = List.of("a", "b", "c"); + public void cannotSetDefaultHoldersForTestNullPackageNames() throws Exception { runWithShellPermissionIdentity(() -> { - sRoleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME, - testRoleHolders); - List<String> roleHolders = - sRoleManager.getDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME); - assertThat(roleHolders).isEqualTo(testRoleHolders); + assertThrows(NullPointerException.class, () -> + sRoleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME, + null)); }); } @RequiresFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, codeName = "Baklava") @Test - public void setAndGetDefaultHoldersNoRoleHolders() throws Exception { - List<String> initialRoleHolders = List.of("a", "b", "c"); - List<String> testRoleHolders = Collections.emptyList(); + public void setAndGetDefaultHolders() throws Exception { + List<String> testRoleHolders = List.of("a", "b", "c"); runWithShellPermissionIdentity(() -> { sRoleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME, - initialRoleHolders); - sRoleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME, testRoleHolders); List<String> roleHolders = sRoleManager.getDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME); @@ -1520,15 +1514,17 @@ public class RoleManagerTest { @RequiresFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, codeName = "Baklava") @Test - public void setAndGetDefaultHoldersNullRoleHolders() throws Exception { + public void setAndGetDefaultHoldersNoRoleHolders() throws Exception { List<String> initialRoleHolders = List.of("a", "b", "c"); + List<String> testRoleHolders = Collections.emptyList(); runWithShellPermissionIdentity(() -> { sRoleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME, initialRoleHolders); - sRoleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME, null); + sRoleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME, + testRoleHolders); List<String> roleHolders = sRoleManager.getDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVE_ROLE_NAME); - assertThat(roleHolders).isEqualTo(Collections.emptyList()); + assertThat(roleHolders).isEqualTo(testRoleHolders); }); } diff --git a/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt b/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt index 134f45131..e33e95706 100644 --- a/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt +++ b/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt @@ -246,17 +246,13 @@ class RoleManagerMultiUserTest { fun ensureOnlyActiveUserIsRoleHolder() { try { // Set test default role holder. Ensures fallbacks to a default holder - roleManager.setDefaultHoldersForTest( - PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, - listOf(APP_PACKAGE_NAME), - ) + setDefaultHoldersForTestForAllUsers() val activeUser = roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)!! // Test app install might take a moment eventually { assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(activeUser) } } finally { - // Clear test default role holder - roleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, null) + clearDefaultHoldersForTestForAllUsers() } } @@ -318,10 +314,7 @@ class RoleManagerMultiUserTest { try { // Set test default role holder. Ensures fallbacks to a default holder - roleManager.setDefaultHoldersForTest( - PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, - listOf(APP_PACKAGE_NAME), - ) + setDefaultHoldersForTestForAllUsers() roleManager.setActiveUserForRole( PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, @@ -333,8 +326,7 @@ class RoleManagerMultiUserTest { // We can assume targetActiveUser is role holder since fallback is enabled eventually { assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) } } finally { - // Clear test default role holder - roleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, null) + clearDefaultHoldersForTestForAllUsers() } } @@ -346,10 +338,7 @@ class RoleManagerMultiUserTest { fun setAndGetActiveUserForRoleSetWorkProfile() { try { // Set test default role holder. Ensures fallbacks to a default holder - roleManager.setDefaultHoldersForTest( - PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, - listOf(APP_PACKAGE_NAME), - ) + setDefaultHoldersForTestForAllUsers() val targetActiveUser = deviceState.workProfile().userHandle() roleManager.setActiveUserForRole( @@ -363,8 +352,7 @@ class RoleManagerMultiUserTest { // We can assume targetActiveUser is role holder since fallback is enabled eventually { assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) } } finally { - // Clear test default role holder - roleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, null) + setDefaultHoldersForTestForAllUsers() } } @@ -633,6 +621,26 @@ class RoleManagerMultiUserTest { } } + private fun setDefaultHoldersForTestForAllUsers() { + // Set test default role holder. Ensures fallbacks to a default holder + for (userRoleManager in users().all().map { getRoleManagerForUser(it.userHandle()) }) { + userRoleManager.setDefaultHoldersForTest( + PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, + listOf(APP_PACKAGE_NAME), + ) + } + } + + private fun clearDefaultHoldersForTestForAllUsers() { + // Set test default role holder. Ensures fallbacks to a default holder + for (userRoleManager in users().all().map { getRoleManagerForUser(it.userHandle()) }) { + userRoleManager.setDefaultHoldersForTest( + PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, + emptyList(), + ) + } + } + private fun getRoleManagerForUser(user: UserHandle): RoleManager { val userContext = context.createContextAsUser(user, 0) return userContext.getSystemService(RoleManager::class.java) |