summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--service/java/com/android/role/RoleService.java26
-rw-r--r--service/java/com/android/role/RoleUserState.java16
-rw-r--r--tests/cts/rolemultiuser/Android.bp2
-rw-r--r--tests/cts/rolemultiuser/AndroidTest.xml2
-rw-r--r--tests/cts/rolemultiuser/CtsRoleMultiUserTestApp/Android.bp23
-rw-r--r--tests/cts/rolemultiuser/CtsRoleMultiUserTestApp/AndroidManifest.xml24
-rw-r--r--tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt43
7 files changed, 82 insertions, 54 deletions
diff --git a/service/java/com/android/role/RoleService.java b/service/java/com/android/role/RoleService.java
index deb0cf3b0..5bc79efbb 100644
--- a/service/java/com/android/role/RoleService.java
+++ b/service/java/com/android/role/RoleService.java
@@ -219,7 +219,6 @@ 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());
@@ -440,6 +439,9 @@ public class RoleService extends SystemService implements RoleUserState.Callback
private void onRemoveUser(@UserIdInt int userId) {
RemoteCallbackList<IOnRoleHoldersChangedListener> listeners;
RoleUserState userState;
+ // UserManager still knows the user until ACTION_USER_REMOVED broadcasts are processed
+ int profileParentId = UserUtils.getProfileParentIdOrSelf(userId, getContext());
+ List<String> activeRoleNames = null;
synchronized (mLock) {
mGrantDefaultRolesThrottledRunnables.remove(userId);
listeners = mListeners.get(userId);
@@ -447,7 +449,29 @@ public class RoleService extends SystemService implements RoleUserState.Callback
mControllers.remove(userId);
userState = mUserStates.get(userId);
mUserStates.remove(userId);
+
+ if (RoleFlags.isProfileGroupExclusivityAvailable() && userId != profileParentId) {
+ RoleUserState profileParentState = mUserStates.get(profileParentId);
+ activeRoleNames = profileParentState.getActiveRolesForUser(userId);
+ }
}
+ if (RoleFlags.isProfileGroupExclusivityAvailable() && userId != profileParentId
+ && !CollectionUtils.isEmpty(activeRoleNames)) {
+ int activeRoleNamesSize = activeRoleNames.size();
+ for (int i = 0; i < activeRoleNamesSize; i++) {
+ String roleName = activeRoleNames.get(i);
+
+ // If the previous active user had a set role holder, attempt to fallback for
+ // the profile parent.
+ Log.i(LOG_TAG, "User " + userId + " removed, falling back to profile parent "
+ + profileParentId + " for role " + roleName);
+ // Use profileParentId instead of userId here, since userId is in a state of removal
+ // and might be excluded from UserManager#getUserHandles with excludeDying=true
+ setActiveUserForRoleAsUserInternal(roleName, profileParentId, 0, true,
+ profileParentId);
+ }
+ }
+
if (listeners != null) {
listeners.kill();
}
diff --git a/service/java/com/android/role/RoleUserState.java b/service/java/com/android/role/RoleUserState.java
index 7f59f1385..18574a6fc 100644
--- a/service/java/com/android/role/RoleUserState.java
+++ b/service/java/com/android/role/RoleUserState.java
@@ -447,6 +447,22 @@ class RoleUserState {
}
}
+ @NonNull
+ public List<String> getActiveRolesForUser(@UserIdInt int userId) {
+ synchronized (mLock) {
+ List<String> activeRoleNames = new ArrayList<>();
+ int activeUserIdsSize = mActiveUserIds.size();
+ for (int i = 0; i < activeUserIdsSize; i++) {
+ int activeUserId = mActiveUserIds.valueAt(i);
+ if (activeUserId == userId) {
+ String roleName = mActiveUserIds.keyAt(i);
+ activeRoleNames.add(roleName);
+ }
+ }
+ return activeRoleNames;
+ }
+ }
+
/**
* Set the active user for the role
*
diff --git a/tests/cts/rolemultiuser/Android.bp b/tests/cts/rolemultiuser/Android.bp
index 7de55fc1b..7a49bc4e5 100644
--- a/tests/cts/rolemultiuser/Android.bp
+++ b/tests/cts/rolemultiuser/Android.bp
@@ -45,6 +45,6 @@ android_test {
],
data: [
- ":CtsRoleMultiUserTestApp",
+ ":CtsRoleTestApp",
],
}
diff --git a/tests/cts/rolemultiuser/AndroidTest.xml b/tests/cts/rolemultiuser/AndroidTest.xml
index 15c34f54a..510b70fdb 100644
--- a/tests/cts/rolemultiuser/AndroidTest.xml
+++ b/tests/cts/rolemultiuser/AndroidTest.xml
@@ -41,7 +41,7 @@
<target_preparer class="com.android.compatibility.common.tradefed.targetprep.FilePusher">
<option name="cleanup" value="true" />
- <option name="push" value="CtsRoleMultiUserTestApp.apk->/data/local/tmp/cts-role/CtsRoleMultiUserTestApp.apk" />
+ <option name="push" value="CtsRoleTestApp.apk->/data/local/tmp/cts-role/CtsRoleTestApp.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
diff --git a/tests/cts/rolemultiuser/CtsRoleMultiUserTestApp/Android.bp b/tests/cts/rolemultiuser/CtsRoleMultiUserTestApp/Android.bp
deleted file mode 100644
index 71ccd0e59..000000000
--- a/tests/cts/rolemultiuser/CtsRoleMultiUserTestApp/Android.bp
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (C) 2024 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package {
- default_applicable_licenses: ["Android-Apache-2.0"],
-}
-
-android_test_helper_app {
- name: "CtsRoleMultiUserTestApp",
- defaults: ["mts-target-sdk-version-current"],
- min_sdk_version: "30",
-}
diff --git a/tests/cts/rolemultiuser/CtsRoleMultiUserTestApp/AndroidManifest.xml b/tests/cts/rolemultiuser/CtsRoleMultiUserTestApp/AndroidManifest.xml
deleted file mode 100644
index eea3be741..000000000
--- a/tests/cts/rolemultiuser/CtsRoleMultiUserTestApp/AndroidManifest.xml
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
- ~ Copyright (C) 2024 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-
-<manifest
- xmlns:android="http://schemas.android.com/apk/res/android"
- package="android.app.rolemultiuser.cts.app">
-
- <application android:label="CtsRoleMultiUserTestApp" />
-</manifest>
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 9af594070..72abf0678 100644
--- a/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt
+++ b/tests/cts/rolemultiuser/src/android/app/rolemultiuser/cts/RoleManagerMultiUserTest.kt
@@ -25,12 +25,14 @@ import android.os.UserHandle
import android.provider.Settings
import androidx.test.filters.SdkSuppress
import androidx.test.uiautomator.By
+import com.android.bedstead.enterprise.annotations.EnsureHasNoWorkProfile
import com.android.bedstead.enterprise.annotations.EnsureHasWorkProfile
import com.android.bedstead.enterprise.annotations.RequireRunOnWorkProfile
import com.android.bedstead.enterprise.workProfile
import com.android.bedstead.flags.annotations.RequireFlagsEnabled
import com.android.bedstead.harrier.BedsteadJUnit4
import com.android.bedstead.harrier.DeviceState
+import com.android.bedstead.multiuser.annotations.EnsureCanAddUser
import com.android.bedstead.multiuser.annotations.EnsureHasAdditionalUser
import com.android.bedstead.multiuser.annotations.EnsureHasPrivateProfile
import com.android.bedstead.multiuser.annotations.EnsureHasSecondaryUser
@@ -42,6 +44,7 @@ import com.android.bedstead.nene.TestApis.context
import com.android.bedstead.nene.TestApis.permissions
import com.android.bedstead.nene.TestApis.users
import com.android.bedstead.nene.types.OptionalBoolean
+import com.android.bedstead.nene.users.UserType
import com.android.bedstead.permissions.CommonPermissions.INTERACT_ACROSS_USERS_FULL
import com.android.bedstead.permissions.CommonPermissions.MANAGE_DEFAULT_APPLICATIONS
import com.android.bedstead.permissions.CommonPermissions.MANAGE_ROLE_HOLDERS
@@ -565,6 +568,39 @@ class RoleManagerMultiUserTest {
@RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED)
@EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS)
+ @EnsureCanAddUser
+ @EnsureHasNoWorkProfile
+ @RequireRunOnPrimaryUser
+ @Test
+ @Throws(Exception::class)
+ fun ensureActiveUserSetToParentOnUserRemoved() {
+ users()
+ .createUser()
+ .parent(users().initial())
+ .type(users().supportedType(UserType.MANAGED_PROFILE_TYPE_NAME))
+ .createAndStart()
+ .use { userReference ->
+ val targetActiveUser = userReference.userHandle()
+ roleManager.setActiveUserForRole(
+ PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME,
+ targetActiveUser,
+ 0,
+ )
+ assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME))
+ .isEqualTo(targetActiveUser)
+
+ userReference.remove()
+ }
+
+ // Removal of users in roles service might take a moment
+ eventually {
+ assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME))
+ .isEqualTo(users().current().userHandle())
+ }
+ }
+
+ @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED)
+ @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS)
@EnsureHasWorkProfile
@RequireRunOnPrimaryUser
@Test
@@ -915,10 +951,9 @@ class RoleManagerMultiUserTest {
private const val PROFILE_GROUP_EXCLUSIVITY_ROLE_SHORT_LABEL =
"Test profile group exclusive role app"
private const val PRIVATE_PROFILE_TYPE_NAME = "android.os.usertype.profile.PRIVATE"
- private const val APP_APK_PATH: String =
- "/data/local/tmp/cts-role/CtsRoleMultiUserTestApp.apk"
- private const val APP_PACKAGE_NAME: String = "android.app.rolemultiuser.cts.app"
- private const val APP_LABEL: String = "CtsRoleMultiUserTestApp"
+ private const val APP_APK_PATH = "/data/local/tmp/cts-role/CtsRoleTestApp.apk"
+ private const val APP_PACKAGE_NAME = "android.app.role.cts.app"
+ private const val APP_LABEL = "CtsRoleTestApp"
private val context: Context = context().instrumentedContext()
private val roleManager: RoleManager = context.getSystemService(RoleManager::class.java)