1 /* <lambda>null2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package android.app.rolemultiuser.cts 17 18 import android.app.role.RoleManager 19 import android.content.Context 20 import android.os.Build 21 import android.os.Process 22 import android.os.UserHandle 23 import androidx.test.filters.SdkSuppress 24 import com.android.bedstead.enterprise.annotations.EnsureHasWorkProfile 25 import com.android.bedstead.enterprise.annotations.RequireRunOnWorkProfile 26 import com.android.bedstead.enterprise.workProfile 27 import com.android.bedstead.flags.annotations.RequireFlagsEnabled 28 import com.android.bedstead.harrier.BedsteadJUnit4 29 import com.android.bedstead.harrier.DeviceState 30 import com.android.bedstead.multiuser.annotations.EnsureHasAdditionalUser 31 import com.android.bedstead.multiuser.annotations.EnsureHasPrivateProfile 32 import com.android.bedstead.multiuser.annotations.EnsureHasSecondaryUser 33 import com.android.bedstead.multiuser.annotations.RequireRunNotOnSecondaryUser 34 import com.android.bedstead.multiuser.annotations.RequireRunOnPrimaryUser 35 import com.android.bedstead.multiuser.privateProfile 36 import com.android.bedstead.multiuser.secondaryUser 37 import com.android.bedstead.nene.TestApis.context 38 import com.android.bedstead.nene.TestApis.permissions 39 import com.android.bedstead.nene.TestApis.users 40 import com.android.bedstead.nene.types.OptionalBoolean 41 import com.android.bedstead.permissions.CommonPermissions.INTERACT_ACROSS_USERS_FULL 42 import com.android.bedstead.permissions.CommonPermissions.MANAGE_DEFAULT_APPLICATIONS 43 import com.android.bedstead.permissions.CommonPermissions.MANAGE_ROLE_HOLDERS 44 import com.android.bedstead.permissions.annotations.EnsureDoesNotHavePermission 45 import com.android.bedstead.permissions.annotations.EnsureHasPermission 46 import com.android.compatibility.common.util.SystemUtil 47 import com.android.compatibility.common.util.SystemUtil.eventually 48 import com.google.common.truth.Truth.assertThat 49 import com.google.common.truth.Truth.assertWithMessage 50 import java.util.Objects 51 import java.util.concurrent.CompletableFuture 52 import java.util.concurrent.TimeUnit 53 import java.util.function.Consumer 54 import org.junit.After 55 import org.junit.Assert.assertThrows 56 import org.junit.Assume.assumeFalse 57 import org.junit.Before 58 import org.junit.ClassRule 59 import org.junit.Rule 60 import org.junit.Test 61 import org.junit.runner.RunWith 62 63 @SdkSuppress(minSdkVersion = Build.VERSION_CODES.BAKLAVA, codeName = "Baklava") 64 @RunWith(BedsteadJUnit4::class) 65 class RoleManagerMultiUserTest { 66 @Before 67 @Throws(java.lang.Exception::class) 68 fun setUp() { 69 installAppForAllUsers() 70 } 71 72 @After 73 @Throws(java.lang.Exception::class) 74 fun tearDown() { 75 uninstallAppForAllUsers() 76 } 77 78 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 79 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 80 @EnsureHasWorkProfile(installInstrumentedApp = OptionalBoolean.TRUE) 81 @EnsureHasPrivateProfile(installInstrumentedApp = OptionalBoolean.TRUE) 82 @RequireRunOnPrimaryUser 83 @Test 84 @Throws(Exception::class) 85 fun isAvailableAsUserForProfileGroupExclusiveRole() { 86 val workProfileRoleManager = getRoleManagerForUser(deviceState.workProfile().userHandle()) 87 val privateProfileRoleManager = 88 getRoleManagerForUser(deviceState.privateProfile().userHandle()) 89 90 assertThat(roleManager.isRoleAvailable(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)).isTrue() 91 assertThat(workProfileRoleManager.isRoleAvailable(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 92 .isTrue() 93 assertThat(privateProfileRoleManager.isRoleAvailable(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 94 .isFalse() 95 } 96 97 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 98 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 99 @Test 100 @Throws(Exception::class) 101 fun cannotGetActiveUserForNonCrossUserRole() { 102 assertThrows(IllegalArgumentException::class.java) { 103 roleManager.getActiveUserForRole(RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER) 104 } 105 } 106 107 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 108 @EnsureHasPermission(MANAGE_ROLE_HOLDERS) 109 @EnsureDoesNotHavePermission(INTERACT_ACROSS_USERS_FULL) 110 @Test 111 @Throws(Exception::class) 112 fun cannotGetActiveUserForRoleWithoutInteractAcrossUserPermission() { 113 assertThrows(SecurityException::class.java) { 114 roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME) 115 } 116 } 117 118 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 119 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL) 120 @EnsureDoesNotHavePermission(MANAGE_ROLE_HOLDERS, MANAGE_DEFAULT_APPLICATIONS) 121 @Test 122 @Throws(Exception::class) 123 fun cannotGetActiveUserForRoleWithoutManageRoleAndManageDefaultApplicationsPermission() { 124 assertThrows(SecurityException::class.java) { 125 roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME) 126 } 127 } 128 129 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 130 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 131 @Test 132 @Throws(Exception::class) 133 fun cannotSetActiveUserForNonCrossUserRole() { 134 assertThrows(IllegalArgumentException::class.java) { 135 roleManager.setActiveUserForRole( 136 RoleManager.ROLE_SYSTEM_ACTIVITY_RECOGNIZER, 137 Process.myUserHandle(), 138 0, 139 ) 140 } 141 } 142 143 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 144 @EnsureHasPermission(MANAGE_ROLE_HOLDERS) 145 @EnsureDoesNotHavePermission(INTERACT_ACROSS_USERS_FULL) 146 @Test 147 @Throws(Exception::class) 148 fun cannotSetActiveUserForRoleWithoutInteractAcrossUserPermission() { 149 assertThrows(SecurityException::class.java) { 150 roleManager.setActiveUserForRole( 151 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 152 Process.myUserHandle(), 153 0, 154 ) 155 } 156 } 157 158 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 159 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL) 160 @EnsureDoesNotHavePermission(MANAGE_ROLE_HOLDERS, MANAGE_DEFAULT_APPLICATIONS) 161 @Test 162 @Throws(Exception::class) 163 fun cannotSetActiveUserForRoleWithoutManageRoleAndManageDefaultApplicationsPermission() { 164 assertThrows(SecurityException::class.java) { 165 roleManager.setActiveUserForRole( 166 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 167 Process.myUserHandle(), 168 0, 169 ) 170 } 171 } 172 173 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 174 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 175 @Test 176 @Throws(Exception::class) 177 fun cannotSetActiveUserForRoleToNonExistentUser() { 178 val targetActiveUser = users().nonExisting().userHandle() 179 roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, targetActiveUser, 0) 180 181 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 182 .isNotEqualTo(targetActiveUser) 183 } 184 185 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 186 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 187 @EnsureHasPrivateProfile(installInstrumentedApp = OptionalBoolean.TRUE) 188 @Test 189 @Throws(Exception::class) 190 fun cannotSetActiveUserForRoleToPrivateProfileUser() { 191 val targetActiveUser = deviceState.privateProfile().userHandle() 192 roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, targetActiveUser, 0) 193 194 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 195 .isNotEqualTo(targetActiveUser) 196 } 197 198 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 199 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 200 @EnsureHasAdditionalUser(installInstrumentedApp = OptionalBoolean.TRUE) 201 @EnsureHasSecondaryUser 202 @RequireRunNotOnSecondaryUser 203 @Test 204 @Throws(Exception::class) 205 fun cannotSetActiveUserForRoleToUserNotInProfileGroup() { 206 val targetActiveUser = deviceState.secondaryUser().userHandle() 207 roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, targetActiveUser, 0) 208 209 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 210 .isNotEqualTo(targetActiveUser) 211 } 212 213 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 214 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 215 @EnsureHasWorkProfile 216 @EnsureHasAdditionalUser(installInstrumentedApp = OptionalBoolean.TRUE) 217 @EnsureHasSecondaryUser 218 @RequireRunNotOnSecondaryUser 219 @Test 220 @Throws(java.lang.Exception::class) 221 fun ensureRoleHasActiveUser() { 222 val primaryUser = deviceState.initialUser().userHandle() 223 val primaryUserRoleManager = getRoleManagerForUser(primaryUser) 224 val secondaryUser = deviceState.secondaryUser().userHandle() 225 val secondaryUserRoleManager = getRoleManagerForUser(secondaryUser) 226 227 assertWithMessage( 228 "Expected active user in profile group for user ${primaryUser.identifier}" 229 ) 230 .that(primaryUserRoleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 231 .isNotNull() 232 assertWithMessage( 233 "Expected active user in profile group for user ${secondaryUser.identifier}" 234 ) 235 .that( 236 secondaryUserRoleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME) 237 ) 238 .isNotNull() 239 } 240 241 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 242 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 243 @EnsureHasWorkProfile 244 @Test 245 @Throws(java.lang.Exception::class) 246 fun ensureOnlyActiveUserIsRoleHolder() { 247 try { 248 // Set test default role holder. Ensures fallbacks to a default holder 249 roleManager.setDefaultHoldersForTest( 250 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 251 listOf(APP_PACKAGE_NAME), 252 ) 253 254 val activeUser = roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)!! 255 // Test app install might take a moment 256 eventually { assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(activeUser) } 257 } finally { 258 // Clear test default role holder 259 roleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, null) 260 } 261 } 262 263 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 264 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 265 @EnsureDoesNotHavePermission(MANAGE_DEFAULT_APPLICATIONS) 266 @EnsureHasWorkProfile(installInstrumentedApp = OptionalBoolean.TRUE) 267 @Test 268 @Throws(Exception::class) 269 fun setAndGetActiveUserForRoleSetCurrentUserWithManageRoleHoldersPermission() { 270 assumeFalse( 271 "setActiveUser not supported for private profile", 272 users().current().type().name() == PRIVATE_PROFILE_TYPE_NAME, 273 ) 274 275 val targetActiveUser = users().current().userHandle() 276 roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, targetActiveUser, 0) 277 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 278 .isEqualTo(targetActiveUser) 279 } 280 281 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 282 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_DEFAULT_APPLICATIONS) 283 @EnsureDoesNotHavePermission(MANAGE_ROLE_HOLDERS) 284 @EnsureHasWorkProfile(installInstrumentedApp = OptionalBoolean.TRUE) 285 @Test 286 @Throws(Exception::class) 287 fun setAndGetActiveUserForRoleSetCurrentUserWithManageDefaultApplicationPermission() { 288 assumeFalse( 289 "setActiveUser not supported for private profile", 290 users().current().type().name() == PRIVATE_PROFILE_TYPE_NAME, 291 ) 292 293 val targetActiveUser = users().current().userHandle() 294 roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, targetActiveUser, 0) 295 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 296 .isEqualTo(targetActiveUser) 297 } 298 299 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 300 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 301 @EnsureHasWorkProfile(installInstrumentedApp = OptionalBoolean.TRUE) 302 @Test 303 @Throws(Exception::class) 304 fun setAndGetActiveUserForRoleSetCurrentUserEnsureRoleNotHeldByInactiveUser() { 305 assumeFalse( 306 "setActiveUser not supported for private profile", 307 users().current().type().name() == PRIVATE_PROFILE_TYPE_NAME, 308 ) 309 // initialUser needs to be not the targetUser 310 val targetActiveUser = users().current().userHandle() 311 val initialUser = 312 if (Objects.equals(targetActiveUser, deviceState.initialUser())) { 313 deviceState.workProfile().userHandle() 314 } else { 315 deviceState.initialUser().userHandle() 316 } 317 roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, initialUser, 0) 318 319 try { 320 // Set test default role holder. Ensures fallbacks to a default holder 321 roleManager.setDefaultHoldersForTest( 322 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 323 listOf(APP_PACKAGE_NAME), 324 ) 325 326 roleManager.setActiveUserForRole( 327 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 328 targetActiveUser, 329 0, 330 ) 331 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 332 .isEqualTo(targetActiveUser) 333 // We can assume targetActiveUser is role holder since fallback is enabled 334 eventually { assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) } 335 } finally { 336 // Clear test default role holder 337 roleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, null) 338 } 339 } 340 341 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 342 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 343 @EnsureHasWorkProfile(installInstrumentedApp = OptionalBoolean.TRUE) 344 @Test 345 @Throws(Exception::class) 346 fun setAndGetActiveUserForRoleSetWorkProfile() { 347 try { 348 // Set test default role holder. Ensures fallbacks to a default holder 349 roleManager.setDefaultHoldersForTest( 350 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 351 listOf(APP_PACKAGE_NAME), 352 ) 353 354 val targetActiveUser = deviceState.workProfile().userHandle() 355 roleManager.setActiveUserForRole( 356 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 357 targetActiveUser, 358 0, 359 ) 360 361 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 362 .isEqualTo(targetActiveUser) 363 // We can assume targetActiveUser is role holder since fallback is enabled 364 eventually { assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) } 365 } finally { 366 // Clear test default role holder 367 roleManager.setDefaultHoldersForTest(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, null) 368 } 369 } 370 371 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 372 @EnsureHasPermission(MANAGE_ROLE_HOLDERS) 373 @EnsureDoesNotHavePermission(INTERACT_ACROSS_USERS_FULL) 374 @EnsureHasWorkProfile 375 @RequireRunOnPrimaryUser 376 @Test 377 @Throws(Exception::class) 378 fun cannotAddRoleHolderAsUserForProfileExclusiveRoleWithoutInteractAcrossUserPermission() { 379 // Set other user as active 380 val initialUser = deviceState.workProfile().userHandle() 381 // setActiveUserForRole and getActiveUserForRole is used to ensure initial active users 382 // state and requires INTERACT_ACROSS_USERS_FULL 383 permissions().withPermission(INTERACT_ACROSS_USERS_FULL).use { _ -> 384 roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, initialUser, 0) 385 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 386 .isEqualTo(initialUser) 387 } 388 389 val targetActiveUser = users().current().userHandle() 390 val future = CallbackFuture() 391 assertThrows(SecurityException::class.java) { 392 roleManager.addRoleHolderAsUser( 393 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 394 APP_PACKAGE_NAME, 395 0, 396 targetActiveUser, 397 context.mainExecutor, 398 future, 399 ) 400 } 401 assertThat( 402 roleManager.getRoleHoldersAsUser( 403 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 404 targetActiveUser, 405 ) 406 ) 407 .isEmpty() 408 409 // getActiveUserForRole is used to ensure addRoleHolderAsUser didn't set active user, and 410 // requires INTERACT_ACROSS_USERS_FULL 411 permissions().withPermission(INTERACT_ACROSS_USERS_FULL).use { _ -> 412 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 413 .isEqualTo(initialUser) 414 } 415 } 416 417 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 418 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 419 @EnsureHasWorkProfile 420 @Test 421 @Throws(java.lang.Exception::class) 422 fun addRoleHolderAsUserSetsCurrentUserAsActive() { 423 // Set other user as active 424 val initialUser = deviceState.workProfile().userHandle() 425 roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, initialUser, 0) 426 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 427 .isEqualTo(initialUser) 428 429 val targetActiveUser = users().current().userHandle() 430 val future = CallbackFuture() 431 roleManager.addRoleHolderAsUser( 432 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 433 APP_PACKAGE_NAME, 434 0, 435 targetActiveUser, 436 context.mainExecutor, 437 future, 438 ) 439 assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue() 440 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 441 .isEqualTo(targetActiveUser) 442 assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) 443 } 444 445 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 446 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_ROLE_HOLDERS) 447 @EnsureHasWorkProfile 448 @RequireRunOnWorkProfile 449 @Test 450 @Throws(java.lang.Exception::class) 451 fun addRoleHolderAsUserSetsWorkProfileAsActive() { 452 // Set other user as active 453 val initialUser = users().main()!!.userHandle() 454 roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, initialUser, 0) 455 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 456 .isEqualTo(initialUser) 457 458 val targetActiveUser = deviceState.workProfile().userHandle() 459 460 assertThat(targetActiveUser).isNotEqualTo(initialUser) 461 val future = CallbackFuture() 462 roleManager.addRoleHolderAsUser( 463 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 464 APP_PACKAGE_NAME, 465 0, 466 targetActiveUser, 467 context.mainExecutor, 468 future, 469 ) 470 assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue() 471 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 472 .isEqualTo(targetActiveUser) 473 assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser(targetActiveUser) 474 } 475 476 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 477 @EnsureHasPermission(MANAGE_DEFAULT_APPLICATIONS) 478 @EnsureDoesNotHavePermission(INTERACT_ACROSS_USERS_FULL) 479 @EnsureHasWorkProfile 480 @RequireRunOnPrimaryUser 481 @Test 482 @Throws(Exception::class) 483 fun cannotSetDefaultApplicationForProfileExclusiveRoleWithoutInteractAcrossUserPermission() { 484 // Set other user as active 485 val initialUser = deviceState.workProfile().userHandle() 486 // setActiveUserForRole and getActiveUserForRole is used to ensure initial active users 487 // state and requires INTERACT_ACROSS_USERS_FULL 488 permissions().withPermission(INTERACT_ACROSS_USERS_FULL).use { _ -> 489 roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, initialUser, 0) 490 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 491 .isEqualTo(initialUser) 492 } 493 494 val future = CallbackFuture() 495 assertThrows(SecurityException::class.java) { 496 roleManager.setDefaultApplication( 497 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 498 APP_PACKAGE_NAME, 499 0, 500 context.mainExecutor, 501 future, 502 ) 503 } 504 assertThat(roleManager.getDefaultApplication(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)).isNull() 505 506 // getActiveUserForRole is used to ensure setDefaultApplication didn't set active user, 507 // and requires INTERACT_ACROSS_USERS_FULL 508 permissions().withPermission(INTERACT_ACROSS_USERS_FULL).use { _ -> 509 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 510 .isEqualTo(initialUser) 511 } 512 } 513 514 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 515 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_DEFAULT_APPLICATIONS) 516 @EnsureHasWorkProfile 517 @Test 518 @Throws(java.lang.Exception::class) 519 fun setDefaultApplicationSetsCurrentUserAsActive() { 520 // Set other user as active 521 val initialUser = deviceState.workProfile().userHandle() 522 roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, initialUser, 0) 523 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 524 .isEqualTo(initialUser) 525 526 val targetActiveUser = users().current().userHandle() 527 val future = CallbackFuture() 528 roleManager.setDefaultApplication( 529 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 530 APP_PACKAGE_NAME, 531 0, 532 context.mainExecutor, 533 future, 534 ) 535 assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue() 536 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 537 .isEqualTo(targetActiveUser) 538 assertExpectedProfileHasRoleUsingGetDefaultApplication(targetActiveUser) 539 } 540 541 @RequireFlagsEnabled(com.android.permission.flags.Flags.FLAG_CROSS_USER_ROLE_ENABLED) 542 @EnsureHasPermission(INTERACT_ACROSS_USERS_FULL, MANAGE_DEFAULT_APPLICATIONS) 543 @EnsureHasWorkProfile 544 @RequireRunOnWorkProfile 545 @Test 546 @Throws(java.lang.Exception::class) 547 fun setDefaultApplicationSetsWorkProfileAsActive() { 548 // Set other user as active 549 val initialUser = users().main()!!.userHandle() 550 roleManager.setActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, initialUser, 0) 551 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 552 .isEqualTo(initialUser) 553 554 val targetActiveUser = deviceState.workProfile().userHandle() 555 assertThat(targetActiveUser).isNotEqualTo(initialUser) 556 val future = CallbackFuture() 557 roleManager.setDefaultApplication( 558 PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, 559 APP_PACKAGE_NAME, 560 0, 561 context.mainExecutor, 562 future, 563 ) 564 assertThat(future.get(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS)).isTrue() 565 assertThat(roleManager.getActiveUserForRole(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME)) 566 .isEqualTo(targetActiveUser) 567 assertExpectedProfileHasRoleUsingGetDefaultApplication(targetActiveUser) 568 } 569 570 @Throws(java.lang.Exception::class) 571 private fun installAppForAllUsers() { 572 SystemUtil.runShellCommandOrThrow("pm install -r --user all $APP_APK_PATH") 573 } 574 575 private fun uninstallAppForAllUsers() { 576 SystemUtil.runShellCommand("pm uninstall $APP_PACKAGE_NAME") 577 } 578 579 private fun assertExpectedProfileHasRoleUsingGetRoleHoldersAsUser( 580 expectedActiveUser: UserHandle 581 ) { 582 for (userReference in users().profileGroup()) { 583 val user = userReference.userHandle() 584 if (Objects.equals(user, expectedActiveUser)) { 585 val roleHolders = 586 roleManager.getRoleHoldersAsUser(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, user) 587 assertWithMessage( 588 "Expected user ${user.identifier} to have a role holder for " + 589 " $PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME" 590 ) 591 .that(roleHolders) 592 .isNotEmpty() 593 assertWithMessage( 594 "Expected user ${user.identifier} to have $APP_PACKAGE_NAME as role " + 595 "holder for $PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME" 596 ) 597 .that(roleHolders.first()) 598 .isEqualTo(APP_PACKAGE_NAME) 599 } else { 600 // Verify the non-active user does not hold the role 601 assertWithMessage( 602 "Expected user ${user.identifier} to not have a role holder for" + 603 " $PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME" 604 ) 605 .that( 606 roleManager.getRoleHoldersAsUser(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME, user) 607 ) 608 .isEmpty() 609 } 610 } 611 } 612 613 private fun assertExpectedProfileHasRoleUsingGetDefaultApplication( 614 expectedActiveUser: UserHandle 615 ) { 616 for (userReference in users().profileGroup()) { 617 val user = userReference.userHandle() 618 val userRoleManager = getRoleManagerForUser(user) 619 if (Objects.equals(user, expectedActiveUser)) { 620 assertWithMessage("Expected default application for user ${user.identifier}") 621 .that( 622 userRoleManager.getDefaultApplication(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME) 623 ) 624 .isEqualTo(APP_PACKAGE_NAME) 625 } else { 626 // Verify the non-active user does not hold the role 627 assertWithMessage("Expected no default application for user ${user.identifier}") 628 .that( 629 userRoleManager.getDefaultApplication(PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME) 630 ) 631 .isNull() 632 } 633 } 634 } 635 636 private fun getRoleManagerForUser(user: UserHandle): RoleManager { 637 val userContext = context.createContextAsUser(user, 0) 638 return userContext.getSystemService(RoleManager::class.java) 639 } 640 641 class CallbackFuture : CompletableFuture<Boolean?>(), Consumer<Boolean?> { 642 override fun accept(successful: Boolean?) { 643 complete(successful) 644 } 645 } 646 647 companion object { 648 private const val TIMEOUT_MILLIS: Long = (15 * 1000).toLong() 649 private const val PROFILE_GROUP_EXCLUSIVITY_ROLE_NAME = 650 RoleManager.ROLE_RESERVED_FOR_TESTING_PROFILE_GROUP_EXCLUSIVITY 651 private const val PRIVATE_PROFILE_TYPE_NAME = "android.os.usertype.profile.PRIVATE" 652 private const val APP_APK_PATH: String = 653 "/data/local/tmp/cts-role/CtsRoleMultiUserTestApp.apk" 654 private const val APP_PACKAGE_NAME: String = "android.app.rolemultiuser.cts.app" 655 private val context: Context = context().instrumentedContext() 656 private val roleManager: RoleManager = context.getSystemService(RoleManager::class.java) 657 658 @JvmField @ClassRule @Rule val deviceState = DeviceState() 659 } 660 } 661