1 /*
2  * Copyright (C) 2022 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 com.android.server.pm;
17 
18 import static android.os.UserHandle.USER_ALL;
19 import static android.os.UserHandle.USER_CURRENT;
20 import static android.os.UserHandle.USER_CURRENT_OR_SELF;
21 import static android.os.UserHandle.USER_NULL;
22 import static android.os.UserHandle.USER_SYSTEM;
23 import static android.view.Display.DEFAULT_DISPLAY;
24 import static android.view.Display.INVALID_DISPLAY;
25 
26 import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
27 import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
28 import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
29 import static com.android.server.pm.UserManagerInternal.USER_START_MODE_BACKGROUND;
30 import static com.android.server.pm.UserManagerInternal.USER_START_MODE_BACKGROUND_VISIBLE;
31 import static com.android.server.pm.UserManagerInternal.USER_START_MODE_FOREGROUND;
32 import static com.android.server.pm.UserManagerInternal.userAssignmentResultToString;
33 import static com.android.server.pm.UserVisibilityChangedEvent.onInvisible;
34 import static com.android.server.pm.UserVisibilityChangedEvent.onVisible;
35 import static com.android.server.pm.UserVisibilityMediator.INITIAL_CURRENT_USER_ID;
36 
37 import static com.google.common.truth.Truth.assertWithMessage;
38 
39 import static org.junit.Assert.assertThrows;
40 
41 import android.annotation.UserIdInt;
42 import android.os.Handler;
43 import android.text.TextUtils;
44 import android.util.IntArray;
45 import android.util.Log;
46 
47 import com.android.server.DumpableDumperRule;
48 import com.android.server.ExpectableTestCase;
49 
50 import org.junit.Before;
51 import org.junit.Test;
52 
53 import java.util.Arrays;
54 
55 /**
56  * Base class for {@link UserVisibilityMediator} tests.
57  *
58  * <p>It contains common logics and tests for behaviors that should be invariant regardless of the
59  * device mode (for example, whether the device supports concurrent multiple users on multiple
60  * displays or not).
61  *
62  * <p><P>NOTE: <p> rather than adopting the "one test case for method approach", this class (and
63  * its subclass) adds "one test case for scenario" approach, so it can test many properties (if user
64  * is visible, display associated to the user, etc...) for each scenario (full user started on fg,
65  * profile user started on bg, etc...).
66  */
67 abstract class UserVisibilityMediatorTestCase extends ExpectableTestCase {
68 
69     private static final String TAG = UserVisibilityMediatorTestCase.class.getSimpleName();
70 
71     /**
72      * Id for a simple user (that doesn't have profiles).
73      */
74     protected static final int USER_ID = 600;
75 
76     /**
77      * Id for another simple user.
78      */
79     protected static final int OTHER_USER_ID = 666;
80 
81     /**
82      * Id for yeat another simple user.
83      */
84     protected static final int YET_ANOTHER_USER_ID = 700;
85 
86     /**
87      * Id for a user that has one profile (whose id is {@link #PROFILE_USER_ID}.
88      *
89      * <p>You can use {@link #addDefaultProfileAndParent()} to add both of this user to the service.
90      */
91     protected static final int PARENT_USER_ID = 642;
92 
93     /**
94      * Id for a profile whose parent is {@link #PARENTUSER_ID}.
95      *
96      * <p>You can use {@link #addDefaultProfileAndParent()} to add both of this user to the service.
97      */
98     protected static final int PROFILE_USER_ID = 643;
99 
100     /**
101      * Id of a secondary display (i.e, not {@link android.view.Display.DEFAULT_DISPLAY}).
102      */
103     protected static final int SECONDARY_DISPLAY_ID = 42;
104 
105     /**
106      * Id of another secondary display (i.e, not {@link android.view.Display.DEFAULT_DISPLAY}).
107      */
108     protected static final int OTHER_SECONDARY_DISPLAY_ID = 108;
109 
110     protected static final int FG = USER_START_MODE_FOREGROUND;
111     protected static final int BG = USER_START_MODE_BACKGROUND;
112     protected static final int BG_VISIBLE = USER_START_MODE_BACKGROUND_VISIBLE;
113 
114     private Handler mHandler;
115     protected AsyncUserVisibilityListener.Factory mListenerFactory;
116 
117     private final boolean mBackgroundUsersOnDisplaysEnabled;
118     private final boolean mBackgroundUserOnDefaultDisplayAllowed;
119 
120     protected UserVisibilityMediator mMediator;
121 
UserVisibilityMediatorTestCase(boolean backgroundUsersOnDisplaysEnabled, boolean backgroundUserOnDefaultDisplayAllowed)122     protected UserVisibilityMediatorTestCase(boolean backgroundUsersOnDisplaysEnabled,
123             boolean backgroundUserOnDefaultDisplayAllowed) {
124         mBackgroundUsersOnDisplaysEnabled = backgroundUsersOnDisplaysEnabled;
125         mBackgroundUserOnDefaultDisplayAllowed = backgroundUserOnDefaultDisplayAllowed;
126     }
127 
128     protected final DumpableDumperRule mDumpableDumperRule = new DumpableDumperRule();
129 
130     @Before
setFixtures()131     public final void setFixtures() {
132         mHandler = Handler.getMain();
133         Thread thread = mHandler.getLooper().getThread();
134         Log.i(TAG, "setFixtures(): using thread " + thread + " (from handler " + mHandler + ")");
135         mListenerFactory = new AsyncUserVisibilityListener.Factory(mExpect, thread);
136         mMediator = new UserVisibilityMediator(mBackgroundUsersOnDisplaysEnabled,
137                 mBackgroundUserOnDefaultDisplayAllowed, mHandler);
138         mDumpableDumperRule.addDumpable(mMediator);
139     }
140 
141     @Test
testInvalidMode()142     public void testInvalidMode() {
143         assertThrows(IllegalArgumentException.class, () -> new UserVisibilityMediator(
144                 /* visibleBackgroundUsersOnDisplaysEnabled= */ false,
145                 /* visibleBackgroundUserOnDefaultDisplayAllowed= */ true, mHandler));
146     }
147 
148     @Test
testAssignUserToDisplayOnStart_invalidUserIds()149     public final void testAssignUserToDisplayOnStart_invalidUserIds() {
150         assertThrows(IllegalArgumentException.class, () -> mMediator
151                 .assignUserToDisplayOnStart(USER_NULL, USER_ID, FG, DEFAULT_DISPLAY));
152         assertThrows(IllegalArgumentException.class, () -> mMediator
153                 .assignUserToDisplayOnStart(USER_ALL, USER_ID, FG, DEFAULT_DISPLAY));
154         assertThrows(IllegalArgumentException.class, () -> mMediator
155                 .assignUserToDisplayOnStart(USER_CURRENT, USER_ID, FG, DEFAULT_DISPLAY));
156         assertThrows(IllegalArgumentException.class, () -> mMediator
157                 .assignUserToDisplayOnStart(USER_CURRENT_OR_SELF, USER_ID, FG, DEFAULT_DISPLAY));
158     }
159 
160     @Test
testAssignUserToDisplayOnStart_invalidUserStartMode()161     public final void testAssignUserToDisplayOnStart_invalidUserStartMode() {
162         assertThrows(IllegalArgumentException.class, () -> mMediator
163                 .assignUserToDisplayOnStart(USER_ID, USER_ID, 666, DEFAULT_DISPLAY));
164     }
165 
166     @Test
testStartFgUser_onSecondaryDisplay()167     public final void testStartFgUser_onSecondaryDisplay() throws Exception {
168         AsyncUserVisibilityListener listener = addListenerForNoEvents();
169 
170         int result =
171                 mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, FG, SECONDARY_DISPLAY_ID);
172         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
173 
174         expectUserIsNotVisibleAtAll(USER_ID);
175         expectNoDisplayAssignedToUser(USER_ID);
176         expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
177 
178         listener.verify();
179     }
180 
181     @Test
testStartBgUser_onDefaultDisplay()182     public final void testStartBgUser_onDefaultDisplay() throws Exception {
183         AsyncUserVisibilityListener listener = addListenerForNoEvents();
184 
185         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG, DEFAULT_DISPLAY);
186         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
187 
188         expectUserIsNotVisibleAtAll(USER_ID);
189         expectNoDisplayAssignedToUser(USER_ID);
190         expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
191 
192         assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
193 
194         listener.verify();
195     }
196 
visibleBgUserCannotBeStartedOnDefaultDisplayTest()197     protected final @UserIdInt int visibleBgUserCannotBeStartedOnDefaultDisplayTest()
198             throws Exception {
199         AsyncUserVisibilityListener listener = addListenerForNoEvents();
200 
201         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
202                 DEFAULT_DISPLAY);
203         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
204 
205         expectUserIsNotVisibleAtAll(USER_ID);
206         expectNoDisplayAssignedToUser(USER_ID);
207 
208         listener.verify();
209 
210         return USER_ID;
211     }
212 
213     @Test
testStartBgUser_onSecondaryDisplay()214     public final void testStartBgUser_onSecondaryDisplay() throws Exception {
215         AsyncUserVisibilityListener listener = addListenerForNoEvents();
216 
217         int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG,
218                 SECONDARY_DISPLAY_ID);
219         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
220 
221         expectUserIsNotVisibleAtAll(USER_ID);
222         expectNoDisplayAssignedToUser(USER_ID);
223 
224         assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
225         assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
226 
227         listener.verify();
228     }
229 
230     @Test
testStartBgSystemUser_onSecondaryDisplay()231     public final void testStartBgSystemUser_onSecondaryDisplay() throws Exception {
232         AsyncUserVisibilityListener listener = addListenerForEvents(
233                 onInvisible(INITIAL_CURRENT_USER_ID),
234                 onVisible(USER_ID));
235         // Must explicitly set current user, as USER_SYSTEM is the default current user
236         startForegroundUser(USER_ID);
237 
238         int result = mMediator.assignUserToDisplayOnStart(USER_SYSTEM, USER_SYSTEM, BG,
239                 SECONDARY_DISPLAY_ID);
240         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
241 
242         expectUserIsNotVisibleAtAll(USER_SYSTEM);
243 
244         expectNoDisplayAssignedToUser(USER_SYSTEM);
245         expectUserAssignedToDisplay(SECONDARY_DISPLAY_ID, USER_ID);
246 
247         assertUserCannotBeAssignedExtraDisplay(USER_SYSTEM, SECONDARY_DISPLAY_ID);
248         assertUserCannotBeAssignedExtraDisplay(USER_SYSTEM, OTHER_SECONDARY_DISPLAY_ID);
249 
250         listener.verify();
251     }
252 
253     @Test
testStopVisibleBgProfile()254     public final void testStopVisibleBgProfile() throws Exception {
255         AsyncUserVisibilityListener listener = addListenerForEvents(
256                 onInvisible(INITIAL_CURRENT_USER_ID),
257                 onVisible(PARENT_USER_ID),
258                 onVisible(PROFILE_USER_ID),
259                 onInvisible(PROFILE_USER_ID));
260         startDefaultProfile();
261 
262         mMediator.unassignUserFromDisplayOnStop(PROFILE_USER_ID);
263 
264         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
265         expectNoDisplayAssignedToUser(PROFILE_USER_ID);
266         expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
267 
268         listener.verify();
269     }
270 
271     @Test
testVisibleBgProfileBecomesInvisibleWhenParentIsSwitchedOut()272     public final void testVisibleBgProfileBecomesInvisibleWhenParentIsSwitchedOut()
273             throws Exception {
274         AsyncUserVisibilityListener listener = addListenerForEvents(
275                 onInvisible(INITIAL_CURRENT_USER_ID),
276                 onVisible(PARENT_USER_ID),
277                 onVisible(PROFILE_USER_ID),
278                 onInvisible(PARENT_USER_ID),
279                 onInvisible(PROFILE_USER_ID),
280                 onVisible(OTHER_USER_ID));
281         startDefaultProfile();
282 
283         startForegroundUser(OTHER_USER_ID);
284 
285         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
286         expectNoDisplayAssignedToUser(PROFILE_USER_ID);
287         expectUserAssignedToDisplay(DEFAULT_DISPLAY, OTHER_USER_ID);
288 
289         assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
290 
291         listener.verify();
292     }
293 
294     @Test
testStartVisibleBgProfile_onDefaultDisplay_whenParentIsNotStarted()295     public final void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsNotStarted()
296             throws Exception {
297         AsyncUserVisibilityListener listener = addListenerForNoEvents();
298 
299         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
300                 BG_VISIBLE, DEFAULT_DISPLAY);
301         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
302 
303         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
304         expectNoDisplayAssignedToUser(PROFILE_USER_ID);
305 
306         listener.verify();
307     }
308 
309     @Test
testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedOnBg()310     public final void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedOnBg()
311             throws Exception {
312         AsyncUserVisibilityListener listener = addListenerForNoEvents();
313         startBackgroundUser(PARENT_USER_ID);
314 
315         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
316                 BG_VISIBLE, DEFAULT_DISPLAY);
317         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
318 
319         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
320 
321         expectNoDisplayAssignedToUser(PROFILE_USER_ID);
322         expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
323 
324         assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
325 
326         listener.verify();
327     }
328 
329     // Not supported - profiles can only be started on default display
330     @Test
testStartVisibleBgProfile_onSecondaryDisplay()331     public final void testStartVisibleBgProfile_onSecondaryDisplay() throws Exception {
332         AsyncUserVisibilityListener listener = addListenerForNoEvents();
333 
334         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
335                 BG_VISIBLE, SECONDARY_DISPLAY_ID);
336         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
337 
338         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
339         expectNoDisplayAssignedToUser(PROFILE_USER_ID);
340         expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);
341 
342         assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
343         assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID,
344                 OTHER_SECONDARY_DISPLAY_ID);
345 
346         listener.verify();
347     }
348 
349     @Test
testStartBgProfile_onDefaultDisplay_whenParentIsNotStarted()350     public final void testStartBgProfile_onDefaultDisplay_whenParentIsNotStarted()
351             throws Exception {
352         AsyncUserVisibilityListener listener = addListenerForNoEvents();
353 
354         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
355                 DEFAULT_DISPLAY);
356         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
357 
358         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
359         expectNoDisplayAssignedToUser(PROFILE_USER_ID);
360 
361         listener.verify();
362     }
363 
364     @Test
testStartBgProfile_onDefaultDisplay_whenParentIsStartedOnBg()365     public final void testStartBgProfile_onDefaultDisplay_whenParentIsStartedOnBg()
366             throws Exception {
367         AsyncUserVisibilityListener listener = addListenerForNoEvents();
368         startBackgroundUser(PARENT_USER_ID);
369 
370         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
371                 DEFAULT_DISPLAY);
372         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
373 
374         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
375 
376         expectNoDisplayAssignedToUser(PROFILE_USER_ID);
377         expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
378 
379         assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
380 
381         listener.verify();
382     }
383 
384     @Test
testStartBgProfile_onSecondaryDisplay()385     public final void testStartBgProfile_onSecondaryDisplay() throws Exception {
386         AsyncUserVisibilityListener listener = addListenerForNoEvents();
387 
388         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
389                 SECONDARY_DISPLAY_ID);
390         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
391 
392         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
393         expectNoDisplayAssignedToUser(PROFILE_USER_ID);
394         expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);
395 
396         assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
397         assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID,
398                 OTHER_SECONDARY_DISPLAY_ID);
399 
400         listener.verify();
401     }
402 
403     @Test
testStartFgProfile_onDefaultDisplay()404     public final void testStartFgProfile_onDefaultDisplay() throws Exception {
405         AsyncUserVisibilityListener listener = addListenerForNoEvents();
406 
407         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, FG,
408                 DEFAULT_DISPLAY);
409         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
410 
411         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
412 
413         expectNoDisplayAssignedToUser(PROFILE_USER_ID);
414         expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
415 
416         assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
417         assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
418 
419         listener.verify();
420     }
421 
422     @Test
testStartFgProfile_onSecondaryDisplay()423     public final void testStartFgProfile_onSecondaryDisplay() throws Exception {
424         AsyncUserVisibilityListener listener = addListenerForNoEvents();
425 
426         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, FG,
427                 SECONDARY_DISPLAY_ID);
428         assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
429 
430         expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
431         expectNoDisplayAssignedToUser(PROFILE_USER_ID);
432         expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);
433 
434         assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
435         assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID,
436                 OTHER_SECONDARY_DISPLAY_ID);
437 
438         listener.verify();
439     }
440 
441     @Test
testIsUserVisible_invalidUsers()442     public final void testIsUserVisible_invalidUsers() throws Exception {
443         expectWithMessage("isUserVisible(%s)", USER_NULL)
444                 .that(mMediator.isUserVisible(USER_NULL))
445                 .isFalse();
446         expectWithMessage("isUserVisible(%s)", USER_NULL)
447                 .that(mMediator.isUserVisible(USER_ALL))
448                 .isFalse();
449         expectWithMessage("isUserVisible(%s)", USER_NULL)
450                 .that(mMediator.isUserVisible(USER_CURRENT))
451                 .isFalse();
452         expectWithMessage("isUserVisible(%s)", USER_NULL)
453                 .that(mMediator.isUserVisible(USER_CURRENT_OR_SELF))
454                 .isFalse();
455     }
456 
457     @Test
testRemoveListener()458     public final void testRemoveListener() throws Exception {
459         AsyncUserVisibilityListener listener = addListenerForNoEvents();
460 
461         mMediator.removeListener(listener);
462 
463         startForegroundUser(USER_ID);
464         listener.verify();
465     }
466 
467     @Test
testOnSystemUserVisibilityChanged()468     public final void testOnSystemUserVisibilityChanged() throws Exception {
469         AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(USER_SYSTEM));
470 
471         mMediator.onSystemUserVisibilityChanged(/* visible= */ true);
472 
473         listener.verify();
474     }
475 
476     /**
477      * Starts a user in foreground on the default display, asserting it was properly started.
478      *
479      * <p><b>NOTE: </b>should only be used as a helper method, not to test the behavior of the
480      * {@link UserVisibilityMediator#assignUserToDisplayOnStart(int, int, boolean, int)} method per
481      * se.
482      */
startForegroundUser(@serIdInt int userId)483     protected void startForegroundUser(@UserIdInt int userId) {
484         Log.d(TAG, "startForegroundUSer(" + userId + ")");
485         int result = mMediator.assignUserToDisplayOnStart(userId, userId, FG, DEFAULT_DISPLAY);
486         if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
487             throw new IllegalStateException("Failed to start foreground user " + userId
488                     + ": mediator returned " + userAssignmentResultToString(result));
489         }
490     }
491 
492     /**
493      * Starts a user in background on the default display, asserting it was properly started.
494      *
495      * <p><b>NOTE: </b>should only be used as a helper method, not to test the behavior of the
496      * {@link UserVisibilityMediator#assignUserToDisplayOnStart(int, int, boolean, int)} method per
497      * se.
498      */
startBackgroundUser(@serIdInt int userId)499     protected void startBackgroundUser(@UserIdInt int userId) {
500         Log.d(TAG, "startBackgroundUser(" + userId + ")");
501         int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG, DEFAULT_DISPLAY);
502         if (result != USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE) {
503             throw new IllegalStateException("Failed to start background user " + userId
504                     + ": mediator returned " + userAssignmentResultToString(result));
505         }
506     }
507 
508     /**
509      * Starts the {@link #PROFILE_USER_ID default profile} in background and its
510      * {@link #PARENT_USER_ID parent} in foreground on the main display, asserting that
511      * both were properly started.
512      *
513      * <p><b>NOTE: </b>should only be used as a helper method, not to test the behavior of the
514      * {@link UserVisibilityMediator#assignUserToDisplayOnStart(int, int, boolean, int)} method per
515      * se.
516      */
startDefaultProfile()517     protected void startDefaultProfile() {
518         startForegroundUser(PARENT_USER_ID);
519         Log.d(TAG, "starting default profile (" + PROFILE_USER_ID + ") in background after starting"
520                 + " its parent (" + PARENT_USER_ID + ") on foreground");
521 
522         int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
523                 BG_VISIBLE, DEFAULT_DISPLAY);
524         if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
525             throw new IllegalStateException("Failed to start profile user " + PROFILE_USER_ID
526                     + ": mediator returned " + userAssignmentResultToString(result));
527         }
528     }
529 
530     /**
531      * Starts a user in background on the secondary display, asserting it was properly started.
532      *
533      * <p><b>NOTE: </b>should only be used as a helper method, not to test the behavior of the
534      * {@link UserVisibilityMediator#assignUserToDisplayOnStart(int, int, boolean, int)} method per
535      * se.
536      */
startUserInSecondaryDisplay(@serIdInt int userId, int displayId)537     protected final void startUserInSecondaryDisplay(@UserIdInt int userId, int displayId) {
538         Log.d(TAG, "startUserInSecondaryDisplay(" + userId + ", " + displayId + ")");
539         int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG_VISIBLE, displayId);
540         if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
541             throw new IllegalStateException("Failed to startuser " + userId
542                     + " on background: mediator returned " + userAssignmentResultToString(result));
543         }
544     }
545 
addListenerForNoEvents()546     protected AsyncUserVisibilityListener addListenerForNoEvents() {
547         AsyncUserVisibilityListener listener = mListenerFactory.forNoEvents();
548         mMediator.addListener(listener);
549         return listener;
550     }
551 
addListenerForEvents( UserVisibilityChangedEvent... events)552     protected AsyncUserVisibilityListener addListenerForEvents(
553             UserVisibilityChangedEvent... events) {
554         AsyncUserVisibilityListener listener = mListenerFactory.forEvents(events);
555         mMediator.addListener(listener);
556         return listener;
557     }
558 
assertStartUserResult(int actualResult, int expectedResult)559     protected void assertStartUserResult(int actualResult, int expectedResult) {
560         assertStartUserResult(actualResult, expectedResult, "");
561     }
562 
563     @SuppressWarnings("AnnotateFormatMethod")
assertStartUserResult(int actualResult, int expectedResult, String extraMessageFormat, Object... extraMessageArguments)564     protected void assertStartUserResult(int actualResult, int expectedResult,
565             String extraMessageFormat, Object... extraMessageArguments) {
566         String extraMessage = String.format(extraMessageFormat, extraMessageArguments);
567         assertWithMessage("startUser() result %s(where %s=%s and %s=%s)", extraMessage,
568                 expectedResult, userAssignmentResultToString(expectedResult),
569                 actualResult, userAssignmentResultToString(actualResult))
570                         .that(actualResult).isEqualTo(expectedResult);
571     }
572 
assertBgUserBecomesInvisibleOnStop(@serIdInt int userId)573     protected void assertBgUserBecomesInvisibleOnStop(@UserIdInt int userId) {
574         Log.d(TAG, "Stopping user " + userId);
575         mMediator.unassignUserFromDisplayOnStop(userId);
576         expectUserIsNotVisibleAtAll(userId);
577     }
578 
579     /**
580      * Assigns and unassigns the user to / from an extra display, asserting the visibility state in
581      * between.
582      *
583      * <p>It assumes the user was not visible in the display beforehand.
584      */
assertUserCanBeAssignedExtraDisplay(@serIdInt int userId, int displayId)585     protected void assertUserCanBeAssignedExtraDisplay(@UserIdInt int userId, int displayId) {
586         assertUserCanBeAssignedExtraDisplay(userId, displayId, /* unassign= */ true);
587     }
588 
assertUserCanBeAssignedExtraDisplay(@serIdInt int userId, int displayId, boolean unassign)589     protected void assertUserCanBeAssignedExtraDisplay(@UserIdInt int userId, int displayId,
590             boolean unassign) {
591 
592         expectUserIsNotVisibleOnDisplay(userId, displayId);
593 
594         Log.d(TAG, "Calling assignUserToExtraDisplay(" + userId + ", " + displayId + ")");
595         assertWithMessage("assignUserToExtraDisplay(%s, %s)", userId, displayId)
596                 .that(mMediator.assignUserToExtraDisplay(userId, displayId))
597                 .isTrue();
598         expectUserIsVisibleOnDisplay(userId, displayId);
599         expectDisplaysAssignedToUserContainsDisplayId(userId, displayId);
600 
601         if (unassign) {
602             Log.d(TAG, "Calling unassignUserFromExtraDisplay(" + userId + ", " + displayId + ")");
603             assertWithMessage("unassignUserFromExtraDisplay(%s, %s)", userId, displayId)
604                     .that(mMediator.unassignUserFromExtraDisplay(userId, displayId))
605                     .isTrue();
606             expectUserIsNotVisibleOnDisplay(userId, displayId);
607             expectDisplaysAssignedToUserDoesNotContainDisplayId(userId, displayId);
608         }
609     }
610 
611     /**
612      * Asserts that a user (already visible or not) cannot be assigned to an extra display (and
613      * hence won't be visible on that display).
614      */
assertUserCannotBeAssignedExtraDisplay(@serIdInt int userId, int displayId)615     protected void assertUserCannotBeAssignedExtraDisplay(@UserIdInt int userId, int displayId) {
616         expectWithMessage("assignUserToExtraDisplay(%s, %s)", userId, displayId)
617                 .that(mMediator.assignUserToExtraDisplay(userId, displayId))
618                 .isFalse();
619         expectUserIsNotVisibleOnDisplay(userId, displayId);
620     }
621 
622     /**
623      * Asserts that an invisible user cannot be assigned to an extra display.
624      */
assertInvisibleUserCannotBeAssignedExtraDisplay(@serIdInt int userId, int displayId)625     protected void assertInvisibleUserCannotBeAssignedExtraDisplay(@UserIdInt int userId,
626             int displayId) {
627         assertUserCannotBeAssignedExtraDisplay(userId, displayId);
628         expectNoDisplayAssignedToUser(userId);
629         expectInitialCurrentUserAssignedToDisplay(displayId);
630     }
631 
expectUserIsVisible(@serIdInt int userId)632     protected void expectUserIsVisible(@UserIdInt int userId) {
633         expectWithMessage("isUserVisible(%s)", userId)
634                 .that(mMediator.isUserVisible(userId))
635                 .isTrue();
636     }
637 
expectVisibleUsers(@serIdInt Integer... userIds)638     protected void expectVisibleUsers(@UserIdInt Integer... userIds) {
639         IntArray visibleUsers = mMediator.getVisibleUsers();
640         expectWithMessage("getVisibleUsers()").that(visibleUsers).isNotNull();
641         expectWithMessage("getVisibleUsers()").that(visibleUsers.toArray()).asList()
642                 .containsExactlyElementsIn(Arrays.asList(userIds));
643     }
644 
expectUserIsVisibleOnDisplay(@serIdInt int userId, int displayId)645     protected void expectUserIsVisibleOnDisplay(@UserIdInt int userId, int displayId) {
646         expectWithMessage("isUserVisible(%s, %s)", userId, displayId)
647                 .that(mMediator.isUserVisible(userId, displayId))
648                 .isTrue();
649     }
650 
expectUserIsNotVisibleOnDisplay(@serIdInt int userId, int displayId)651     protected void expectUserIsNotVisibleOnDisplay(@UserIdInt int userId, int displayId) {
652         expectWithMessage("isUserVisible(%s, %s)", userId, displayId)
653                 .that(mMediator.isUserVisible(userId, displayId))
654                 .isFalse();
655     }
656 
expectUserIsNotVisibleOnDisplay(String when, @UserIdInt int userId, int displayId)657     protected void expectUserIsNotVisibleOnDisplay(String when, @UserIdInt int userId,
658             int displayId) {
659         String suffix = TextUtils.isEmpty(when) ? "" : " on " + when;
660         expectWithMessage("isUserVisible(%s, %s)%s", userId, displayId, suffix)
661                 .that(mMediator.isUserVisible(userId, displayId))
662                 .isFalse();
663     }
664 
expectUserIsNotVisibleAtAll(@serIdInt int userId)665     protected void expectUserIsNotVisibleAtAll(@UserIdInt int userId) {
666         expectWithMessage("isUserVisible(%s)", userId)
667                 .that(mMediator.isUserVisible(userId))
668                 .isFalse();
669         expectUserIsNotVisibleOnDisplay(userId, DEFAULT_DISPLAY);
670         expectUserIsNotVisibleOnDisplay(userId, INVALID_DISPLAY);
671         expectUserIsNotVisibleOnDisplay(userId, SECONDARY_DISPLAY_ID);
672         expectUserIsNotVisibleOnDisplay(userId, OTHER_SECONDARY_DISPLAY_ID);
673         expectDisplaysAssignedToUserIsEmpty(userId);
674     }
675 
expectDisplayAssignedToUser(@serIdInt int userId, int displayId)676     protected void expectDisplayAssignedToUser(@UserIdInt int userId, int displayId) {
677         expectWithMessage("getMainDisplayAssignedToUser(%s)", userId)
678                 .that(mMediator.getMainDisplayAssignedToUser(userId)).isEqualTo(displayId);
679     }
680 
expectNoDisplayAssignedToUser(@serIdInt int userId)681     protected void expectNoDisplayAssignedToUser(@UserIdInt int userId) {
682         expectWithMessage("getMainDisplayAssignedToUser(%s)", userId)
683                 .that(mMediator.getMainDisplayAssignedToUser(userId)).isEqualTo(INVALID_DISPLAY);
684     }
685 
expectDisplaysAssignedToUserContainsDisplayId( @serIdInt int userId, int displayId)686     protected void expectDisplaysAssignedToUserContainsDisplayId(
687             @UserIdInt int userId, int displayId) {
688         expectWithMessage("getDisplaysAssignedToUser(%s)", userId)
689                 .that(mMediator.getDisplaysAssignedToUser(userId)).asList().contains(displayId);
690     }
691 
expectDisplaysAssignedToUserDoesNotContainDisplayId( @serIdInt int userId, int displayId)692     protected void expectDisplaysAssignedToUserDoesNotContainDisplayId(
693             @UserIdInt int userId, int displayId) {
694         expectWithMessage("getDisplaysAssignedToUser(%s)", userId)
695                 .that(mMediator.getDisplaysAssignedToUser(userId)).asList()
696                 .doesNotContain(displayId);
697     }
698 
expectDisplaysAssignedToUserIsEmpty(@serIdInt int userId)699     protected void expectDisplaysAssignedToUserIsEmpty(@UserIdInt int userId) {
700         expectWithMessage("getDisplaysAssignedToUser(%s)", userId)
701                 .that(mMediator.getDisplaysAssignedToUser(userId)).isNull();
702     }
703 
expectUserCannotBeUnassignedFromDisplay(@serIdInt int userId, int displayId)704     protected void expectUserCannotBeUnassignedFromDisplay(@UserIdInt int userId, int displayId) {
705         expectWithMessage("unassignUserFromExtraDisplay(%s, %s)", userId, displayId)
706                 .that(mMediator.unassignUserFromExtraDisplay(userId, displayId)).isFalse();
707     }
708 
expectUserAssignedToDisplay(int displayId, @UserIdInt int userId)709     protected void expectUserAssignedToDisplay(int displayId, @UserIdInt int userId) {
710         expectWithMessage("getUserAssignedToDisplay(%s)", displayId)
711                 .that(mMediator.getUserAssignedToDisplay(displayId)).isEqualTo(userId);
712     }
713 
expectInitialCurrentUserAssignedToDisplay(int displayId)714     protected void expectInitialCurrentUserAssignedToDisplay(int displayId) {
715         expectWithMessage("getUserAssignedToDisplay(%s)", displayId)
716                 .that(mMediator.getUserAssignedToDisplay(displayId))
717                 .isEqualTo(INITIAL_CURRENT_USER_ID);
718     }
719 }
720