summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
author Richard MacGregor <rmacgregor@google.com> 2024-11-14 15:04:18 -0800
committer Richard MacGregor <rmacgregor@google.com> 2024-11-25 23:07:32 +0000
commitdf5008d7ea4a52d0e7ccaf0eb9f27c457205c2ac (patch)
tree43dfa11dcd46dd6bdd51a7f74e507b35fd125f35 /service
parentee21d2f5803df7c90d0ed7e9157344c0cff30261 (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.java183
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 {