diff options
author | 2024-11-14 15:04:18 -0800 | |
---|---|---|
committer | 2024-11-25 23:07:32 +0000 | |
commit | df5008d7ea4a52d0e7ccaf0eb9f27c457205c2ac (patch) | |
tree | 43dfa11dcd46dd6bdd51a7f74e507b35fd125f35 /service | |
parent | ee21d2f5803df7c90d0ed7e9157344c0cff30261 (diff) |
Set activeuser when setting role holder
Set active user for profilegroup exclusive roles when calling
setDefaultApplication and addRoleHolderAsUser API
LOW_COVERAGE_REASON=FLAG_NOT_ENABLED
Relnote: N/A
Flag: com.android.permission.flags.cross_user_role_enabled
Test: atest RoleManagerMultiUserTest
Bug: 378887974
Bug: 378888547
Change-Id: Ifd8e9a60f5024799dd4dc81d00cd578d799a4114
Diffstat (limited to 'service')
-rw-r--r-- | service/java/com/android/role/RoleService.java | 183 |
1 files changed, 107 insertions, 76 deletions
diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java index 1145f273d..7c2ab01b1 100644 --- a/service/java/com/android/role/RoleService.java +++ b/service/java/com/android/role/RoleService.java @@ -18,7 +18,6 @@ package com.android.role; import android.Manifest; import android.annotation.AnyThread; -import android.annotation.ChecksSdkIntAtLeast; import android.annotation.MainThread; import android.annotation.NonNull; import android.annotation.Nullable; @@ -72,6 +71,8 @@ import com.android.permission.util.ThrottledRunnable; import com.android.permission.util.UserUtils; import com.android.role.controller.model.Role; import com.android.role.controller.model.Roles; +import com.android.role.controller.service.RoleControllerServiceImpl; +import com.android.role.controller.util.RoleFlags; import com.android.server.LocalManagerRegistry; import com.android.server.SystemService; import com.android.server.role.RoleServicePlatformHelper; @@ -118,6 +119,10 @@ public class RoleService extends SystemService implements RoleUserState.Callback if (SdkLevel.isAtLeastV()) { defaultApplicationRoles.add(RoleManager.ROLE_WALLET); } + if (RoleFlags.isProfileGroupExclusivityAvailable()) { + defaultApplicationRoles.add( + RoleManager.ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY); + } DEFAULT_APPLICATION_ROLES = defaultApplicationRoles.toArray(new String[0]); } @@ -169,6 +174,11 @@ public class RoleService extends SystemService implements RoleUserState.Callback public RoleService(@NonNull Context context) { super(context); + if (RoleFlags.isProfileGroupExclusivityAvailable()) { + RoleControllerServiceImpl.sSetActiveUserForRoleMethod = + this::setActiveUserForRoleFromController; + } + mPlatformHelper = LocalManagerRegistry.getManager(RoleServicePlatformHelper.class); RoleControllerManager.initializeRemoteServiceComponentName(context); @@ -466,6 +476,94 @@ public class RoleService extends SystemService implements RoleUserState.Callback } } + private void enforceProfileGroupExclusiveRole(@NonNull String roleName) { + Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); + Preconditions.checkArgument(isProfileGroupExclusiveRole(roleName, getContext()), + roleName + " is not a profile-group exclusive role"); + } + + /** + * Returns whether the given role has profile group exclusivity + * + * @param roleName The name of role to check + * @param context The context + * @return {@code true} if the role is profile group exclusive, {@code false} otherwise + */ + private static boolean isProfileGroupExclusiveRole(String roleName, Context context) { + if (!RoleFlags.isProfileGroupExclusivityAvailable()) { + return false; + } + Role role = Roles.get(context).get(roleName); + return role != null && role.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP; + } + + private void setActiveUserForRoleFromController(@NonNull String roleName, @UserIdInt int userId, + @RoleManager.ManageHoldersFlags int flags) { + setActiveUserForRoleAsUserInternal(roleName, userId, flags, false, userId); + } + + private void setActiveUserForRoleAsUserInternal(@NonNull String roleName, + @UserIdInt int activeUserId, @RoleManager.ManageHoldersFlags int flags, + boolean clearRoleHoldersForActiveUser, @UserIdInt int userId) { + Preconditions.checkState(RoleFlags.isProfileGroupExclusivityAvailable(), + "setActiveUserForRoleAsUser not available"); + enforceProfileGroupExclusiveRole(roleName); + + if (!UserUtils.isUserExistent(userId, getContext())) { + Log.e(LOG_TAG, "user " + userId + " does not exist"); + return; + } + if (!UserUtils.isUserExistent(activeUserId, getContext())) { + Log.e(LOG_TAG, "user " + activeUserId + " does not exist"); + return; + } + if (UserUtils.isPrivateProfile(activeUserId, getContext())) { + Log.e(LOG_TAG, "Cannot set private profile " + activeUserId + " as active user" + + " for role"); + return; + } + Context userContext = UserUtils.getUserContext(userId, getContext()); + List<UserHandle> profiles = UserUtils.getUserProfiles(userContext, true); + if (!profiles.contains(UserHandle.of(activeUserId))) { + Log.e(LOG_TAG, "User " + activeUserId + " is not in the same profile-group as " + + userId); + return; + } + + int profileParentId = UserUtils.getProfileParentIdOrSelf(userId, getContext()); + RoleUserState userState = getOrCreateUserState(profileParentId); + + if (!userState.setActiveUserForRole(roleName, activeUserId)) { + Log.i(LOG_TAG, "User " + activeUserId + " is already the active user for role"); + return; + } + + final int profilesSize = profiles.size(); + for (int i = 0; i < profilesSize; i++) { + int profilesUserId = profiles.get(i).getIdentifier(); + if (!clearRoleHoldersForActiveUser && profilesUserId == activeUserId) { + continue; + } + final AndroidFuture<Void> future = new AndroidFuture<>(); + final RemoteCallback callback = new RemoteCallback(result -> { + boolean successful = result != null; + if (successful) { + future.complete(null); + } else { + future.completeExceptionally(new RuntimeException()); + } + }); + getOrCreateController(profilesUserId) + .onClearRoleHolders(roleName, flags, callback); + try { + future.get(5, TimeUnit.SECONDS); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + Log.e(LOG_TAG, "Exception while clearing role holders for non-active user: " + + profilesUserId, e); + } + } + } + private class Stub extends IRoleManager.Stub { @Override @@ -530,8 +628,9 @@ public class RoleService extends SystemService implements RoleUserState.Callback public void addRoleHolderAsUser(@NonNull String roleName, @NonNull String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback) { + boolean enforceForProfileGroup = isProfileGroupExclusiveRole(roleName, getContext()); UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, - /* enforceForProfileGroup= */ false, "addRoleHolderAsUser", getContext()); + enforceForProfileGroup, "addRoleHolderAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return; @@ -618,9 +717,9 @@ public class RoleService extends SystemService implements RoleUserState.Callback public void setDefaultApplicationAsUser(@NonNull String roleName, @Nullable String packageName, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId, @NonNull RemoteCallback callback) { + boolean enforceForProfileGroup = isProfileGroupExclusiveRole(roleName, getContext()); UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, - /* enforceForProfileGroup= */ false, "setDefaultApplicationAsUser", - getContext()); + enforceForProfileGroup, "setDefaultApplicationAsUser", getContext()); if (!UserUtils.isUserExistent(userId, getContext())) { Log.e(LOG_TAG, "user " + userId + " does not exist"); return; @@ -643,7 +742,7 @@ public class RoleService extends SystemService implements RoleUserState.Callback @Override public int getActiveUserForRoleAsUser(@NonNull String roleName, @UserIdInt int userId) { - Preconditions.checkState(isProfileGroupExclusivityAvailable(), + Preconditions.checkState(RoleFlags.isProfileGroupExclusivityAvailable(), "getActiveUserForRoleAsUser not available"); enforceProfileGroupExclusiveRole(roleName); @@ -668,67 +767,15 @@ public class RoleService extends SystemService implements RoleUserState.Callback public void setActiveUserForRoleAsUser(@NonNull String roleName, @UserIdInt int activeUserId, @RoleManager.ManageHoldersFlags int flags, @UserIdInt int userId) { - Preconditions.checkState(isProfileGroupExclusivityAvailable(), + Preconditions.checkState(RoleFlags.isProfileGroupExclusivityAvailable(), "setActiveUserForRoleAsUser not available"); - enforceProfileGroupExclusiveRole(roleName); - UserUtils.enforceCrossUserPermission(userId, /* allowAll= */ false, /* enforceForProfileGroup= */ true, "setActiveUserForRole", getContext()); - if (!UserUtils.isUserExistent(userId, getContext())) { - Log.e(LOG_TAG, "user " + userId + " does not exist"); - return; - } - if (!UserUtils.isUserExistent(activeUserId, getContext())) { - Log.e(LOG_TAG, "user " + activeUserId + " does not exist"); - return; - } - if (UserUtils.isPrivateProfile(activeUserId, getContext())) { - Log.e(LOG_TAG, "Cannot set private profile " + activeUserId + " as active user" - + " for role"); - return; - } - Context userContext = UserUtils.getUserContext(userId, getContext()); - List<UserHandle> profiles = UserUtils.getUserProfiles(userContext, true); - if (!profiles.contains(UserHandle.of(activeUserId))) { - Log.e(LOG_TAG, "User " + activeUserId + " is not in the same profile-group as " - + userId); - return; - } - enforceCallingOrSelfAnyPermissions(new String[] { Manifest.permission.MANAGE_DEFAULT_APPLICATIONS, Manifest.permission.MANAGE_ROLE_HOLDERS - }, "setDefaultApplicationAsUser"); - - int profileParentId = UserUtils.getProfileParentIdOrSelf(userId, getContext()); - RoleUserState userState = getOrCreateUserState(profileParentId); - - if (!userState.setActiveUserForRole(roleName, activeUserId)) { - Log.i(LOG_TAG, "User " + activeUserId + " is already the active user for role"); - return; - } - - final int profilesSize = profiles.size(); - for (int i = 0; i < profilesSize; i++) { - final AndroidFuture<Void> future = new AndroidFuture<>(); - final RemoteCallback callback = new RemoteCallback(result -> { - boolean successful = result != null; - if (successful) { - future.complete(null); - } else { - future.completeExceptionally(new RuntimeException()); - } - }); - int profilesUserId = profiles.get(i).getIdentifier(); - getOrCreateController(profilesUserId) - .onClearRoleHolders(roleName, flags, callback); - try { - future.get(5, TimeUnit.SECONDS); - } catch (InterruptedException | ExecutionException | TimeoutException e) { - Log.e(LOG_TAG, "Exception while clearing role holders for non-active" - + "user: " + profilesUserId, e); - } - } + }, "setActiveUserForRoleAsUser"); + setActiveUserForRoleAsUserInternal(roleName, activeUserId, flags, true, userId); } @Override @@ -1164,22 +1211,6 @@ public class RoleService extends SystemService implements RoleUserState.Callback + " nor current process has at least one of" + Arrays.toString(permissions) + "."); } - - private void enforceProfileGroupExclusiveRole(@NonNull String roleName) { - Preconditions.checkStringNotEmpty(roleName, "roleName cannot be null or empty"); - Role role = Roles.get(getContext()).get(roleName); - Objects.requireNonNull(role, "Unknown role: " + roleName); - Preconditions.checkArgument( - role.getExclusivity() == Role.EXCLUSIVITY_PROFILE_GROUP, - roleName + " is not a profile-group exclusive role"); - } - - @ChecksSdkIntAtLeast(api = Build.VERSION_CODES.VANILLA_ICE_CREAM) - private boolean isProfileGroupExclusivityAvailable() { - // TODO(b/372743073): change to isAtLeastB once available - return SdkLevel.isAtLeastV() - && com.android.permission.flags.Flags.crossUserRoleEnabled(); - } } private class Local implements RoleManagerLocal { |