diff options
author | 2025-01-17 17:53:13 -0800 | |
---|---|---|
committer | 2025-01-24 13:37:57 -0800 | |
commit | 787ec3d945b1557225c76a998f2b16d72104a789 (patch) | |
tree | c37d95206d25a3b0b3c3fe4f96178c43cc28ac8a | |
parent | 9cb2450013fa4f84f408490ba9c341b8319d9c21 (diff) |
Show profilegroup exclusive roles in defaultapps
Fix bug where default apps list opened using work profile context
wouldn't show profilegroup exclusive roles when full-user is set
as active user
LOW_COVERAGE_REASON=FLAG_NOT_ENABLED
Bug: 385424712
Flag: com.android.permission.flags.cross_user_role_ux_bugfix_enabled
Relnote: N/A
Test: atest RoleManagerMultiUserTest
Change-Id: I35bb290179432ff44b60bcab53cdf0952aa7573c
4 files changed, 210 insertions, 18 deletions
diff --git a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java index e4a3cbc17..718af090e 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java +++ b/PermissionController/src/com/android/permissioncontroller/role/ui/DefaultAppListViewModel.java @@ -28,12 +28,14 @@ import androidx.lifecycle.LiveData; import androidx.lifecycle.Transformations; import androidx.lifecycle.ViewModel; +import com.android.permission.flags.Flags; import com.android.permissioncontroller.permission.utils.Utils; import com.android.permissioncontroller.role.utils.UserUtils; import com.android.role.controller.model.Role; import com.android.role.controller.util.RoleFlags; import java.util.List; +import java.util.Objects; import java.util.function.Predicate; /** @@ -58,18 +60,21 @@ public class DefaultAppListViewModel extends AndroidViewModel { super(application); mUser = Process.myUserHandle(); - boolean isProfileParent = UserUtils.isProfileParent(mUser, application); + UserHandle profileParent = UserUtils.getProfileParentOrSelf(mUser, application); + UserHandle workProfile = UserUtils.getWorkProfileOrSelf(application); + boolean isProfileParent = Objects.equals(mUser, profileParent); + boolean isWorkProfile = Objects.equals(mUser, workProfile); RoleListLiveData liveData = new RoleListLiveData(true, mUser, application); RoleListSortFunction sortFunction = new RoleListSortFunction(application); // Only show the work profile section if the current user is a full user mWorkProfile = isProfileParent ? UserUtils.getWorkProfile(application) : null; if (RoleFlags.isProfileGroupExclusivityAvailable()) { + Predicate<RoleItem> exclusivityPredicate = roleItem -> + roleItem.getRole().getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP; if (mWorkProfile != null) { // Show profile group exclusive roles from work profile in primary group. RoleListLiveData workLiveData = new RoleListLiveData(true, mWorkProfile, application); - Predicate<RoleItem> exclusivityPredicate = roleItem -> - roleItem.getRole().getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP; mLiveData = Transformations.map( new MergeRoleListLiveData(liveData, Transformations.map(workLiveData, @@ -79,6 +84,17 @@ public class DefaultAppListViewModel extends AndroidViewModel { Transformations.map(workLiveData, new RoleListFilterFunction(exclusivityPredicate.negate())), sortFunction); + } else if (Flags.crossUserRoleUxBugfixEnabled() && isWorkProfile) { + // Show profile group exclusive roles from the profile parent (full user) in primary + // group when the current user (primary group) is a work profile + RoleListLiveData profileParentLiveData = + new RoleListLiveData(true, profileParent, application); + mLiveData = Transformations.map( + new MergeRoleListLiveData(liveData, + Transformations.map(profileParentLiveData, + new RoleListFilterFunction(exclusivityPredicate))), + sortFunction); + mWorkLiveData = null; } else { mLiveData = Transformations.map(liveData, sortFunction); mWorkLiveData = null; diff --git a/PermissionController/src/com/android/permissioncontroller/role/utils/UserUtils.java b/PermissionController/src/com/android/permissioncontroller/role/utils/UserUtils.java index f03c31bd8..4d778befb 100644 --- a/PermissionController/src/com/android/permissioncontroller/role/utils/UserUtils.java +++ b/PermissionController/src/com/android/permissioncontroller/role/utils/UserUtils.java @@ -132,19 +132,6 @@ public class UserUtils { } /** - * Returns whether the user is a parent/full-user or not. - * - * @param userHandle the {@code UserHandle} to check is private profile - * @param context the {@code Context} to retrieve system services - */ - public static boolean isProfileParent(@NonNull UserHandle userHandle, - @NonNull Context context) { - // If profile parent user is null, then original user is the parent - return com.android.role.controller.util.UserUtils.getProfileParent(userHandle, context) - == null; - } - - /** * Returns whether the user is a private profile or not. * * @param userHandle the {@code UserHandle} to check is private profile diff --git a/flags/flags.aconfig b/flags/flags.aconfig index 45afa5ff4..372fed403 100644 --- a/flags/flags.aconfig +++ b/flags/flags.aconfig @@ -119,6 +119,18 @@ flag { } flag { + name: "cross_user_role_ux_bugfix_enabled" + is_exported: true + namespace: "permissions" + description: "This flag enables cross-user roles support ux bug fixes" + bug: "367732307" + is_fixed_read_only: true + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { name: "permission_timeline_attribution_label_fix" is_exported: true namespace: "permissions" 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 e8aaddf4c..724549149 100644 --- a/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt +++ b/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt @@ -16,8 +16,8 @@ package android.app.rolemultiuser.cts import android.app.Activity -import android.app.role.cts.RoleManagerUtil import android.app.role.RoleManager +import android.app.role.cts.RoleManagerUtil import android.content.ComponentName import android.content.Context import android.content.Intent @@ -90,7 +90,7 @@ class RoleManagerMultiUserTest { @Before @Throws(java.lang.Exception::class) fun setUp() { - assumeTrue(RoleManagerUtil.isCddCompliantScreenSize()); + assumeTrue(RoleManagerUtil.isCddCompliantScreenSize()) installAppForAllUsers() } @@ -1085,6 +1085,183 @@ class RoleManagerMultiUserTest { } @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) + @EnsureHasWorkProfile + @RequireRunOnPrimaryUser + @Test + @Throws(java.lang.Exception::class) + fun openDefaultAppListFromPrimaryUserAndShowsPrimaryIsDefaultAppInList() { + try { + // Set test default role holder. Ensures fallbacks to a default holder + setDefaultHoldersForTestForAllUsers() + setRoleVisibleForTestForAllUsers() + + val targetActiveUser = deviceState.initialUser().userHandle() + val future = CallbackFuture() + roleManager.addRoleHolderAsUser( + PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, + APP_PACKAGE_NAME, + 0, + targetActiveUser, + context.mainExecutor, + future, + ) + assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue() + assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) + .isEqualTo(targetActiveUser) + assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) + + context.startActivity( + Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS) + .addCategory(Intent.CATEGORY_DEFAULT) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) + ) + getUiDevice().waitForIdle() + + val targetAppLabel = "$APP_LABEL@${targetActiveUser.identifier}" + waitFindObject(By.text(targetAppLabel)) + + pressBack() + } finally { + clearDefaultHoldersForTestForAllUsers() + clearRoleVisibleForTestForAllUsers() + } + } + + @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) + @EnsureHasWorkProfile + @RequireRunOnPrimaryUser + @Test + @Throws(java.lang.Exception::class) + fun openDefaultAppListFromPrimaryUserAndShowsWorkIsDefaultAppInList() { + try { + // Set test default role holder. Ensures fallbacks to a default holder + setDefaultHoldersForTestForAllUsers() + setRoleVisibleForTestForAllUsers() + + val targetActiveUser = deviceState.workProfile().userHandle() + val future = CallbackFuture() + roleManager.addRoleHolderAsUser( + PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, + APP_PACKAGE_NAME, + 0, + targetActiveUser, + context.mainExecutor, + future, + ) + assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue() + assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) + .isEqualTo(targetActiveUser) + assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) + + context.startActivity( + Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS) + .addCategory(Intent.CATEGORY_DEFAULT) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) + ) + getUiDevice().waitForIdle() + + val targetAppLabel = "$APP_LABEL@${targetActiveUser.identifier}" + waitFindObject(By.text(targetAppLabel)) + + pressBack() + } finally { + clearDefaultHoldersForTestForAllUsers() + clearRoleVisibleForTestForAllUsers() + } + } + + @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED, + com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_UX_BUGFIX_ENABLED) + @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) + @EnsureHasWorkProfile + @RequireRunOnWorkProfile + @Test + @Throws(java.lang.Exception::class) + fun openDefaultAppListFromWorkProfileAndShowsPrimaryIsDefaultAppInList() { + try { + // Set test default role holder. Ensures fallbacks to a default holder + setDefaultHoldersForTestForAllUsers() + setRoleVisibleForTestForAllUsers() + + val targetActiveUser = deviceState.initialUser().userHandle() + val future = CallbackFuture() + roleManager.addRoleHolderAsUser( + PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, + APP_PACKAGE_NAME, + 0, + targetActiveUser, + context.mainExecutor, + future, + ) + assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue() + assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) + .isEqualTo(targetActiveUser) + assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) + + context.startActivity( + Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS) + .addCategory(Intent.CATEGORY_DEFAULT) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) + ) + getUiDevice().waitForIdle() + + val targetAppLabel = "$APP_LABEL@${targetActiveUser.identifier}" + waitFindObject(By.text(targetAppLabel)) + + pressBack() + } finally { + clearDefaultHoldersForTestForAllUsers() + clearRoleVisibleForTestForAllUsers() + } + } + + @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) + @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) + @EnsureHasWorkProfile + @RequireRunOnWorkProfile + @Test + @Throws(java.lang.Exception::class) + fun openDefaultAppListFromWorkProfileAndShowsWorkIsDefaultAppInList() { + try { + // Set test default role holder. Ensures fallbacks to a default holder + setDefaultHoldersForTestForAllUsers() + setRoleVisibleForTestForAllUsers() + + val targetActiveUser = deviceState.workProfile().userHandle() + val future = CallbackFuture() + roleManager.addRoleHolderAsUser( + PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, + APP_PACKAGE_NAME, + 0, + targetActiveUser, + context.mainExecutor, + future, + ) + assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue() + assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) + .isEqualTo(targetActiveUser) + assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) + + context.startActivity( + Intent(Settings.ACTION_MANAGE_DEFAULT_APPS_SETTINGS) + .addCategory(Intent.CATEGORY_DEFAULT) + .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK) + ) + getUiDevice().waitForIdle() + + val targetAppLabel = "$APP_LABEL@${targetActiveUser.identifier}" + waitFindObject(By.text(targetAppLabel)) + + pressBack() + } finally { + clearDefaultHoldersForTestForAllUsers() + clearRoleVisibleForTestForAllUsers() + } + } + + @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) @EnsureHasWorkProfile @RequireRunOnPrimaryUser @Test |