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