summaryrefslogtreecommitdiff
path: root/service
diff options
context:
space:
mode:
author Richard MacGregor <rmacgregor@google.com> 2024-11-08 17:23:19 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-11-08 17:23:19 +0000
commitd78b126bf5bc457a7fec74f84de587699efb5fa6 (patch)
treec5c4bf4c6df2c2748c8de7f8423d9e3d40ade38f /service
parent1a8b376aacf729ca1ec72aa4c6a9c0d5bd9ff2f5 (diff)
parent7f27dc5ff6a4b2197218d02b680da802e73f4302 (diff)
Merge "Add Cross-user role persistence" into main
Diffstat (limited to 'service')
-rw-r--r--service/java/com/android/role/RoleService.java2
-rw-r--r--service/java/com/android/role/RoleUserState.java36
-rw-r--r--service/java/com/android/role/persistence/RolesPersistenceImpl.java22
-rw-r--r--service/java/com/android/role/persistence/RolesState.java42
-rw-r--r--service/proto/role_service.proto3
5 files changed, 98 insertions, 7 deletions
diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java
index 20250b4f6..b8e3ad8b1 100644
--- a/service/java/com/android/role/RoleService.java
+++ b/service/java/com/android/role/RoleService.java
@@ -176,6 +176,7 @@ public class RoleService extends SystemService implements RoleUserState.Callback
registerUserRemovedReceiver();
}
+ // TODO(b/375029649): enforce single active user for all cross-user roles
private void registerUserRemovedReceiver() {
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_USER_REMOVED);
@@ -191,6 +192,7 @@ public class RoleService extends SystemService implements RoleUserState.Callback
}, intentFilter, null, null);
}
+ // TODO(b/375029649): enforce single active user for all cross-user roles
@Override
public void onStart() {
publishBinderService(Context.ROLE_SERVICE, new Stub());
diff --git a/service/java/com/android/role/RoleUserState.java b/service/java/com/android/role/RoleUserState.java
index 81007d65e..cda7fcfa8 100644
--- a/service/java/com/android/role/RoleUserState.java
+++ b/service/java/com/android/role/RoleUserState.java
@@ -39,6 +39,7 @@ import com.android.role.persistence.RolesState;
import com.android.server.role.RoleServicePlatformHelper;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -96,6 +97,10 @@ class RoleUserState {
private ArraySet<String> mFallbackEnabledRoles = new ArraySet<>();
@GuardedBy("mLock")
+ @NonNull
+ private ArrayMap<String, Integer> mActiveUserIds = new ArrayMap<>();
+
+ @GuardedBy("mLock")
private boolean mWriteScheduled;
@GuardedBy("mLock")
@@ -449,9 +454,15 @@ class RoleUserState {
// Force a reconciliation on next boot if we are bypassing role qualification now.
String packagesHash = mBypassingRoleQualification ? null : mPackagesHash;
- roles = new RolesState(mVersion, packagesHash,
- (Map<String, Set<String>>) (Map<String, ?>) snapshotRolesLocked(),
- snapshotFallbackEnabledRoles());
+ if (com.android.permission.flags.Flags.crossUserRoleEnabled()) {
+ roles = new RolesState(mVersion, packagesHash,
+ (Map<String, Set<String>>) (Map<String, ?>) snapshotRolesLocked(),
+ snapshotFallbackEnabledRoles(), snapshotActiveUserIds());
+ } else {
+ roles = new RolesState(mVersion, packagesHash,
+ (Map<String, Set<String>>) (Map<String, ?>) snapshotRolesLocked(),
+ snapshotFallbackEnabledRoles());
+ }
}
mPersistence.writeForUser(roles, UserHandle.of(mUserId));
@@ -463,14 +474,17 @@ class RoleUserState {
Map<String, Set<String>> roles;
Set<String> fallbackEnabledRoles;
+ Map<String, Integer> activeUserIds;
if (roleState != null) {
mVersion = roleState.getVersion();
mPackagesHash = roleState.getPackagesHash();
roles = roleState.getRoles();
fallbackEnabledRoles = roleState.getFallbackEnabledRoles();
+ activeUserIds = roleState.getActiveUserIds();
} else {
roles = mPlatformHelper.getLegacyRoleState(mUserId);
fallbackEnabledRoles = roles.keySet();
+ activeUserIds = Collections.emptyMap();
}
mRoles.clear();
for (Map.Entry<String, Set<String>> entry : roles.entrySet()) {
@@ -480,6 +494,10 @@ class RoleUserState {
}
mFallbackEnabledRoles.clear();
mFallbackEnabledRoles.addAll(fallbackEnabledRoles);
+ mActiveUserIds.clear();
+ if (com.android.permission.flags.Flags.crossUserRoleEnabled()) {
+ mActiveUserIds.putAll(activeUserIds);
+ }
if (roleState == null) {
scheduleWriteFileLocked();
}
@@ -496,12 +514,14 @@ class RoleUserState {
int version;
String packagesHash;
ArrayMap<String, ArraySet<String>> roles;
+ ArrayMap<String, Integer> activeUserIds;
ArraySet<String> fallbackEnabledRoles;
synchronized (mLock) {
version = mVersion;
packagesHash = mPackagesHash;
roles = snapshotRolesLocked();
fallbackEnabledRoles = snapshotFallbackEnabledRoles();
+ activeUserIds = snapshotActiveUserIds();
}
long fieldToken = dumpOutputStream.start(fieldName, fieldId);
@@ -514,10 +534,14 @@ class RoleUserState {
String roleName = roles.keyAt(rolesIndex);
ArraySet<String> roleHolders = roles.valueAt(rolesIndex);
boolean fallbackEnabled = fallbackEnabledRoles.contains(roleName);
+ Integer activeUserId = activeUserIds.get(roleName);
long rolesToken = dumpOutputStream.start("roles", RoleUserStateProto.ROLES);
dumpOutputStream.write("name", RoleProto.NAME, roleName);
dumpOutputStream.write("fallback_enabled", RoleProto.FALLBACK_ENABLED, fallbackEnabled);
+ if (activeUserId != null) {
+ dumpOutputStream.write("active_user_id", RoleProto.ACTIVE_USER_ID, activeUserId);
+ }
int roleHoldersSize = roleHolders.size();
for (int roleHoldersIndex = 0; roleHoldersIndex < roleHoldersSize; roleHoldersIndex++) {
String roleHolder = roleHolders.valueAt(roleHoldersIndex);
@@ -563,6 +587,12 @@ class RoleUserState {
return new ArraySet<>(mFallbackEnabledRoles);
}
+ @GuardedBy("mLock")
+ @NonNull
+ private ArrayMap<String, Integer> snapshotActiveUserIds() {
+ return new ArrayMap<>(mActiveUserIds);
+ }
+
/**
* Destroy this user state and delete the corresponding file. Any pending writes to the file
* will be cancelled, and any future interaction with this state will throw an exception.
diff --git a/service/java/com/android/role/persistence/RolesPersistenceImpl.java b/service/java/com/android/role/persistence/RolesPersistenceImpl.java
index 220a8440b..8382d3632 100644
--- a/service/java/com/android/role/persistence/RolesPersistenceImpl.java
+++ b/service/java/com/android/role/persistence/RolesPersistenceImpl.java
@@ -67,6 +67,7 @@ public class RolesPersistenceImpl implements RolesPersistence {
private static final String ATTRIBUTE_VERSION = "version";
private static final String ATTRIBUTE_NAME = "name";
private static final String ATTRIBUTE_FALLBACK_ENABLED = "fallbackEnabled";
+ private static final String ATTRIBUTE_ACTIVE_USER_ID = "activeUserId";
private static final String ATTRIBUTE_PACKAGES_HASH = "packagesHash";
@VisibleForTesting
@@ -144,6 +145,7 @@ public class RolesPersistenceImpl implements RolesPersistence {
Map<String, Set<String>> roles = new ArrayMap<>();
Set<String> fallbackEnabledRoles = new ArraySet<>();
+ Map<String, Integer> activeUserIds = new ArrayMap<>();
int type;
int depth;
int innerDepth = parser.getDepth() + 1;
@@ -159,12 +161,23 @@ public class RolesPersistenceImpl implements RolesPersistence {
if (Boolean.parseBoolean(fallbackEnabled)) {
fallbackEnabledRoles.add(roleName);
}
+ if (com.android.permission.flags.Flags.crossUserRoleEnabled()) {
+ String activeUserId = parser.getAttributeValue(null, ATTRIBUTE_ACTIVE_USER_ID);
+ if (activeUserId != null) {
+ activeUserIds.put(roleName, Integer.parseInt(activeUserId));
+ }
+ }
Set<String> roleHolders = parseRoleHolders(parser);
roles.put(roleName, roleHolders);
}
}
- return new RolesState(version, packagesHash, roles, fallbackEnabledRoles);
+ if (com.android.permission.flags.Flags.crossUserRoleEnabled()) {
+ return new RolesState(version, packagesHash, roles, fallbackEnabledRoles,
+ activeUserIds);
+ } else {
+ return new RolesState(version, packagesHash, roles, fallbackEnabledRoles);
+ }
}
@NonNull
@@ -244,15 +257,22 @@ public class RolesPersistenceImpl implements RolesPersistence {
}
Set<String> fallbackEnabledRoles = roles.getFallbackEnabledRoles();
+ Map<String, Integer> activeUserIds = roles.getActiveUserIds();
for (Map.Entry<String, Set<String>> entry : roles.getRoles().entrySet()) {
String roleName = entry.getKey();
Set<String> roleHolders = entry.getValue();
boolean isFallbackEnabled = fallbackEnabledRoles.contains(roleName);
+ Integer activeUserId = com.android.permission.flags.Flags.crossUserRoleEnabled()
+ ? activeUserIds.get(roleName) : null;
serializer.startTag(null, TAG_ROLE);
serializer.attribute(null, ATTRIBUTE_NAME, roleName);
serializer.attribute(null, ATTRIBUTE_FALLBACK_ENABLED,
Boolean.toString(isFallbackEnabled));
+ if (activeUserId != null) {
+ serializer.attribute(
+ null, ATTRIBUTE_ACTIVE_USER_ID, Integer.toString(activeUserId));
+ }
serializeRoleHolders(serializer, roleHolders);
serializer.endTag(null, TAG_ROLE);
}
diff --git a/service/java/com/android/role/persistence/RolesState.java b/service/java/com/android/role/persistence/RolesState.java
index a189dd4c2..f1b3d8dfa 100644
--- a/service/java/com/android/role/persistence/RolesState.java
+++ b/service/java/com/android/role/persistence/RolesState.java
@@ -23,12 +23,13 @@ import android.annotation.SystemApi;
import android.annotation.SystemApi.Client;
import android.permission.flags.Flags;
+import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
/**
- * State of all roles.
+ * State of all roles for a user.
*
* TODO(b/147914847): Remove @hide when it becomes the default.
* @hide
@@ -59,6 +60,12 @@ public final class RolesState {
private final Set<String> mFallbackEnabledRoles;
/**
+ * The active users for cross user roles.
+ */
+ @NonNull
+ private final Map<String, Integer> mActiveUserIds;
+
+ /**
* Create a new instance of this class.
*
* @param version the version of the roles
@@ -81,10 +88,27 @@ public final class RolesState {
@FlaggedApi(Flags.FLAG_SYSTEM_SERVER_ROLE_CONTROLLER_ENABLED)
public RolesState(int version, @Nullable String packagesHash,
@NonNull Map<String, Set<String>> roles, @NonNull Set<String> fallbackEnabledRoles) {
+ this(version, packagesHash, roles, fallbackEnabledRoles, Collections.emptyMap());
+ }
+
+ /**
+ * Create a new instance of this class.
+ *
+ * @param version the version of the roles
+ * @param packagesHash the hash of all packages in the system
+ * @param roles the roles
+ * @param fallbackEnabledRoles the roles with fallback enabled
+ * @param activeUserIds the active users for cross user roles
+ * @hide
+ */
+ public RolesState(int version, @Nullable String packagesHash,
+ @NonNull Map<String, Set<String>> roles, @NonNull Set<String> fallbackEnabledRoles,
+ @NonNull Map<String, Integer> activeUserIds) {
mVersion = version;
mPackagesHash = packagesHash;
mRoles = roles;
mFallbackEnabledRoles = fallbackEnabledRoles;
+ mActiveUserIds = activeUserIds;
}
/**
@@ -127,6 +151,17 @@ public final class RolesState {
return mFallbackEnabledRoles;
}
+ /**
+ * Get the active users for cross user roles.
+ *
+ * @return active users for cross user roles
+ * @hide
+ */
+ @NonNull
+ public Map<String, Integer> getActiveUserIds() {
+ return mActiveUserIds;
+ }
+
@Override
public boolean equals(Object object) {
if (this == object) {
@@ -139,11 +174,12 @@ public final class RolesState {
return mVersion == that.mVersion
&& Objects.equals(mPackagesHash, that.mPackagesHash)
&& Objects.equals(mRoles, that.mRoles)
- && Objects.equals(mFallbackEnabledRoles, that.mFallbackEnabledRoles);
+ && Objects.equals(mFallbackEnabledRoles, that.mFallbackEnabledRoles)
+ && Objects.equals(mActiveUserIds, that.mActiveUserIds);
}
@Override
public int hashCode() {
- return Objects.hash(mVersion, mPackagesHash, mRoles, mFallbackEnabledRoles);
+ return Objects.hash(mVersion, mPackagesHash, mRoles, mFallbackEnabledRoles, mActiveUserIds);
}
}
diff --git a/service/proto/role_service.proto b/service/proto/role_service.proto
index f982ead5b..fb1866d83 100644
--- a/service/proto/role_service.proto
+++ b/service/proto/role_service.proto
@@ -56,4 +56,7 @@ message RoleProto {
// Whether fallback holders are enabled for this role.
optional bool fallback_enabled = 3;
+
+ // The active user id of this cross user role.
+ optional int32 active_user_id = 4;
}