blob: 70b5ac06331640c289f41abd2e23e05a35f78d79 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.pm;
import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_CURRENT;
import static android.os.UserHandle.USER_CURRENT_OR_SELF;
import static android.os.UserHandle.USER_NULL;
import static android.os.UserHandle.USER_SYSTEM;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.INVALID_DISPLAY;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
import static com.android.server.pm.UserManagerInternal.USER_START_MODE_BACKGROUND;
import static com.android.server.pm.UserManagerInternal.USER_START_MODE_BACKGROUND_VISIBLE;
import static com.android.server.pm.UserManagerInternal.USER_START_MODE_FOREGROUND;
import static com.android.server.pm.UserManagerInternal.userAssignmentResultToString;
import static com.android.server.pm.UserVisibilityChangedEvent.onInvisible;
import static com.android.server.pm.UserVisibilityChangedEvent.onVisible;
import static com.android.server.pm.UserVisibilityMediator.INITIAL_CURRENT_USER_ID;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.junit.Assert.assertThrows;
import android.annotation.UserIdInt;
import android.os.Handler;
import android.text.TextUtils;
import android.util.IntArray;
import android.util.Log;
import com.android.server.DumpableDumperRule;
import com.android.server.ExpectableTestCase;
import org.junit.Before;
import org.junit.Test;
import java.util.Arrays;
/**
* Base class for {@link UserVisibilityMediator} tests.
*
* <p>It contains common logics and tests for behaviors that should be invariant regardless of the
* device mode (for example, whether the device supports concurrent multiple users on multiple
* displays or not).
*
* <p><P>NOTE: <p> rather than adopting the "one test case for method approach", this class (and
* its subclass) adds "one test case for scenario" approach, so it can test many properties (if user
* is visible, display associated to the user, etc...) for each scenario (full user started on fg,
* profile user started on bg, etc...).
*/
abstract class UserVisibilityMediatorTestCase extends ExpectableTestCase {
private static final String TAG = UserVisibilityMediatorTestCase.class.getSimpleName();
/**
* Id for a simple user (that doesn't have profiles).
*/
protected static final int USER_ID = 600;
/**
* Id for another simple user.
*/
protected static final int OTHER_USER_ID = 666;
/**
* Id for yeat another simple user.
*/
protected static final int YET_ANOTHER_USER_ID = 700;
/**
* Id for a user that has one profile (whose id is {@link #PROFILE_USER_ID}.
*
* <p>You can use {@link #addDefaultProfileAndParent()} to add both of this user to the service.
*/
protected static final int PARENT_USER_ID = 642;
/**
* Id for a profile whose parent is {@link #PARENTUSER_ID}.
*
* <p>You can use {@link #addDefaultProfileAndParent()} to add both of this user to the service.
*/
protected static final int PROFILE_USER_ID = 643;
/**
* Id of a secondary display (i.e, not {@link android.view.Display.DEFAULT_DISPLAY}).
*/
protected static final int SECONDARY_DISPLAY_ID = 42;
/**
* Id of another secondary display (i.e, not {@link android.view.Display.DEFAULT_DISPLAY}).
*/
protected static final int OTHER_SECONDARY_DISPLAY_ID = 108;
protected static final int FG = USER_START_MODE_FOREGROUND;
protected static final int BG = USER_START_MODE_BACKGROUND;
protected static final int BG_VISIBLE = USER_START_MODE_BACKGROUND_VISIBLE;
private Handler mHandler;
protected AsyncUserVisibilityListener.Factory mListenerFactory;
private final boolean mBackgroundUsersOnDisplaysEnabled;
private final boolean mBackgroundUserOnDefaultDisplayAllowed;
protected UserVisibilityMediator mMediator;
protected UserVisibilityMediatorTestCase(boolean backgroundUsersOnDisplaysEnabled,
boolean backgroundUserOnDefaultDisplayAllowed) {
mBackgroundUsersOnDisplaysEnabled = backgroundUsersOnDisplaysEnabled;
mBackgroundUserOnDefaultDisplayAllowed = backgroundUserOnDefaultDisplayAllowed;
}
protected final DumpableDumperRule mDumpableDumperRule = new DumpableDumperRule();
@Before
public final void setFixtures() {
mHandler = Handler.getMain();
Thread thread = mHandler.getLooper().getThread();
Log.i(TAG, "setFixtures(): using thread " + thread + " (from handler " + mHandler + ")");
mListenerFactory = new AsyncUserVisibilityListener.Factory(mExpect, thread);
mMediator = new UserVisibilityMediator(mBackgroundUsersOnDisplaysEnabled,
mBackgroundUserOnDefaultDisplayAllowed, mHandler);
mDumpableDumperRule.addDumpable(mMediator);
}
@Test
public void testInvalidMode() {
assertThrows(IllegalArgumentException.class, () -> new UserVisibilityMediator(
/* visibleBackgroundUsersOnDisplaysEnabled= */ false,
/* visibleBackgroundUserOnDefaultDisplayAllowed= */ true, mHandler));
}
@Test
public final void testAssignUserToDisplayOnStart_invalidUserIds() {
assertThrows(IllegalArgumentException.class, () -> mMediator
.assignUserToDisplayOnStart(USER_NULL, USER_ID, FG, DEFAULT_DISPLAY));
assertThrows(IllegalArgumentException.class, () -> mMediator
.assignUserToDisplayOnStart(USER_ALL, USER_ID, FG, DEFAULT_DISPLAY));
assertThrows(IllegalArgumentException.class, () -> mMediator
.assignUserToDisplayOnStart(USER_CURRENT, USER_ID, FG, DEFAULT_DISPLAY));
assertThrows(IllegalArgumentException.class, () -> mMediator
.assignUserToDisplayOnStart(USER_CURRENT_OR_SELF, USER_ID, FG, DEFAULT_DISPLAY));
}
@Test
public final void testAssignUserToDisplayOnStart_invalidUserStartMode() {
assertThrows(IllegalArgumentException.class, () -> mMediator
.assignUserToDisplayOnStart(USER_ID, USER_ID, 666, DEFAULT_DISPLAY));
}
@Test
public final void testStartFgUser_onSecondaryDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
int result =
mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, FG, SECONDARY_DISPLAY_ID);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(USER_ID);
expectNoDisplayAssignedToUser(USER_ID);
expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
listener.verify();
}
@Test
public final void testStartBgUser_onDefaultDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG, DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
expectUserIsNotVisibleAtAll(USER_ID);
expectNoDisplayAssignedToUser(USER_ID);
expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
listener.verify();
}
protected final @UserIdInt int visibleBgUserCannotBeStartedOnDefaultDisplayTest()
throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG_VISIBLE,
DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(USER_ID);
expectNoDisplayAssignedToUser(USER_ID);
listener.verify();
return USER_ID;
}
@Test
public final void testStartBgUser_onSecondaryDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
int result = mMediator.assignUserToDisplayOnStart(USER_ID, USER_ID, BG,
SECONDARY_DISPLAY_ID);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(USER_ID);
expectNoDisplayAssignedToUser(USER_ID);
assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, SECONDARY_DISPLAY_ID);
assertInvisibleUserCannotBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
listener.verify();
}
@Test
public final void testStartBgSystemUser_onSecondaryDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForEvents(
onInvisible(INITIAL_CURRENT_USER_ID),
onVisible(USER_ID));
// Must explicitly set current user, as USER_SYSTEM is the default current user
startForegroundUser(USER_ID);
int result = mMediator.assignUserToDisplayOnStart(USER_SYSTEM, USER_SYSTEM, BG,
SECONDARY_DISPLAY_ID);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(USER_SYSTEM);
expectNoDisplayAssignedToUser(USER_SYSTEM);
expectUserAssignedToDisplay(SECONDARY_DISPLAY_ID, USER_ID);
assertUserCannotBeAssignedExtraDisplay(USER_SYSTEM, SECONDARY_DISPLAY_ID);
assertUserCannotBeAssignedExtraDisplay(USER_SYSTEM, OTHER_SECONDARY_DISPLAY_ID);
listener.verify();
}
@Test
public final void testStopVisibleBgProfile() throws Exception {
AsyncUserVisibilityListener listener = addListenerForEvents(
onInvisible(INITIAL_CURRENT_USER_ID),
onVisible(PARENT_USER_ID),
onVisible(PROFILE_USER_ID),
onInvisible(PROFILE_USER_ID));
startDefaultProfile();
mMediator.unassignUserFromDisplayOnStop(PROFILE_USER_ID);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
listener.verify();
}
@Test
public final void testVisibleBgProfileBecomesInvisibleWhenParentIsSwitchedOut()
throws Exception {
AsyncUserVisibilityListener listener = addListenerForEvents(
onInvisible(INITIAL_CURRENT_USER_ID),
onVisible(PARENT_USER_ID),
onVisible(PROFILE_USER_ID),
onInvisible(PARENT_USER_ID),
onInvisible(PROFILE_USER_ID),
onVisible(OTHER_USER_ID));
startDefaultProfile();
startForegroundUser(OTHER_USER_ID);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectUserAssignedToDisplay(DEFAULT_DISPLAY, OTHER_USER_ID);
assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
listener.verify();
}
@Test
public final void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsNotStarted()
throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
BG_VISIBLE, DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
listener.verify();
}
@Test
public final void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedOnBg()
throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
startBackgroundUser(PARENT_USER_ID);
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
BG_VISIBLE, DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
listener.verify();
}
// Not supported - profiles can only be started on default display
@Test
public final void testStartVisibleBgProfile_onSecondaryDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
BG_VISIBLE, SECONDARY_DISPLAY_ID);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);
assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID,
OTHER_SECONDARY_DISPLAY_ID);
listener.verify();
}
@Test
public final void testStartBgProfile_onDefaultDisplay_whenParentIsNotStarted()
throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
listener.verify();
}
@Test
public final void testStartBgProfile_onDefaultDisplay_whenParentIsStartedOnBg()
throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
startBackgroundUser(PARENT_USER_ID);
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
listener.verify();
}
@Test
public final void testStartBgProfile_onSecondaryDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
SECONDARY_DISPLAY_ID);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);
assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID,
OTHER_SECONDARY_DISPLAY_ID);
listener.verify();
}
@Test
public final void testStartFgProfile_onDefaultDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, FG,
DEFAULT_DISPLAY);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
listener.verify();
}
@Test
public final void testStartFgProfile_onSecondaryDisplay() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, FG,
SECONDARY_DISPLAY_ID);
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
expectInitialCurrentUserAssignedToDisplay(SECONDARY_DISPLAY_ID);
assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID,
OTHER_SECONDARY_DISPLAY_ID);
listener.verify();
}
@Test
public final void testIsUserVisible_invalidUsers() throws Exception {
expectWithMessage("isUserVisible(%s)", USER_NULL)
.that(mMediator.isUserVisible(USER_NULL))
.isFalse();
expectWithMessage("isUserVisible(%s)", USER_NULL)
.that(mMediator.isUserVisible(USER_ALL))
.isFalse();
expectWithMessage("isUserVisible(%s)", USER_NULL)
.that(mMediator.isUserVisible(USER_CURRENT))
.isFalse();
expectWithMessage("isUserVisible(%s)", USER_NULL)
.that(mMediator.isUserVisible(USER_CURRENT_OR_SELF))
.isFalse();
}
@Test
public final void testRemoveListener() throws Exception {
AsyncUserVisibilityListener listener = addListenerForNoEvents();
mMediator.removeListener(listener);
startForegroundUser(USER_ID);
listener.verify();
}
@Test
public final void testOnSystemUserVisibilityChanged() throws Exception {
AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(USER_SYSTEM));
mMediator.onSystemUserVisibilityChanged(/* visible= */ true);
listener.verify();
}
/**
* Starts a user in foreground on the default display, asserting it was properly started.
*
* <p><b>NOTE: </b>should only be used as a helper method, not to test the behavior of the
* {@link UserVisibilityMediator#assignUserToDisplayOnStart(int, int, boolean, int)} method per
* se.
*/
protected void startForegroundUser(@UserIdInt int userId) {
Log.d(TAG, "startForegroundUSer(" + userId + ")");
int result = mMediator.assignUserToDisplayOnStart(userId, userId, FG, DEFAULT_DISPLAY);
if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
throw new IllegalStateException("Failed to start foreground user " + userId
+ ": mediator returned " + userAssignmentResultToString(result));
}
}
/**
* Starts a user in background on the default display, asserting it was properly started.
*
* <p><b>NOTE: </b>should only be used as a helper method, not to test the behavior of the
* {@link UserVisibilityMediator#assignUserToDisplayOnStart(int, int, boolean, int)} method per
* se.
*/
protected void startBackgroundUser(@UserIdInt int userId) {
Log.d(TAG, "startBackgroundUser(" + userId + ")");
int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG, DEFAULT_DISPLAY);
if (result != USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE) {
throw new IllegalStateException("Failed to start background user " + userId
+ ": mediator returned " + userAssignmentResultToString(result));
}
}
/**
* Starts the {@link #PROFILE_USER_ID default profile} in background and its
* {@link #PARENT_USER_ID parent} in foreground on the main display, asserting that
* both were properly started.
*
* <p><b>NOTE: </b>should only be used as a helper method, not to test the behavior of the
* {@link UserVisibilityMediator#assignUserToDisplayOnStart(int, int, boolean, int)} method per
* se.
*/
protected void startDefaultProfile() {
startForegroundUser(PARENT_USER_ID);
Log.d(TAG, "starting default profile (" + PROFILE_USER_ID + ") in background after starting"
+ " its parent (" + PARENT_USER_ID + ") on foreground");
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
BG_VISIBLE, DEFAULT_DISPLAY);
if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
throw new IllegalStateException("Failed to start profile user " + PROFILE_USER_ID
+ ": mediator returned " + userAssignmentResultToString(result));
}
}
/**
* Starts a user in background on the secondary display, asserting it was properly started.
*
* <p><b>NOTE: </b>should only be used as a helper method, not to test the behavior of the
* {@link UserVisibilityMediator#assignUserToDisplayOnStart(int, int, boolean, int)} method per
* se.
*/
protected final void startUserInSecondaryDisplay(@UserIdInt int userId, int displayId) {
Log.d(TAG, "startUserInSecondaryDisplay(" + userId + ", " + displayId + ")");
int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG_VISIBLE, displayId);
if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
throw new IllegalStateException("Failed to startuser " + userId
+ " on background: mediator returned " + userAssignmentResultToString(result));
}
}
protected AsyncUserVisibilityListener addListenerForNoEvents() {
AsyncUserVisibilityListener listener = mListenerFactory.forNoEvents();
mMediator.addListener(listener);
return listener;
}
protected AsyncUserVisibilityListener addListenerForEvents(
UserVisibilityChangedEvent... events) {
AsyncUserVisibilityListener listener = mListenerFactory.forEvents(events);
mMediator.addListener(listener);
return listener;
}
protected void assertStartUserResult(int actualResult, int expectedResult) {
assertStartUserResult(actualResult, expectedResult, "");
}
@SuppressWarnings("AnnotateFormatMethod")
protected void assertStartUserResult(int actualResult, int expectedResult,
String extraMessageFormat, Object... extraMessageArguments) {
String extraMessage = String.format(extraMessageFormat, extraMessageArguments);
assertWithMessage("startUser() result %s(where %s=%s and %s=%s)", extraMessage,
expectedResult, userAssignmentResultToString(expectedResult),
actualResult, userAssignmentResultToString(actualResult))
.that(actualResult).isEqualTo(expectedResult);
}
protected void assertBgUserBecomesInvisibleOnStop(@UserIdInt int userId) {
Log.d(TAG, "Stopping user " + userId);
mMediator.unassignUserFromDisplayOnStop(userId);
expectUserIsNotVisibleAtAll(userId);
}
/**
* Assigns and unassigns the user to / from an extra display, asserting the visibility state in
* between.
*
* <p>It assumes the user was not visible in the display beforehand.
*/
protected void assertUserCanBeAssignedExtraDisplay(@UserIdInt int userId, int displayId) {
assertUserCanBeAssignedExtraDisplay(userId, displayId, /* unassign= */ true);
}
protected void assertUserCanBeAssignedExtraDisplay(@UserIdInt int userId, int displayId,
boolean unassign) {
expectUserIsNotVisibleOnDisplay(userId, displayId);
Log.d(TAG, "Calling assignUserToExtraDisplay(" + userId + ", " + displayId + ")");
assertWithMessage("assignUserToExtraDisplay(%s, %s)", userId, displayId)
.that(mMediator.assignUserToExtraDisplay(userId, displayId))
.isTrue();
expectUserIsVisibleOnDisplay(userId, displayId);
expectDisplaysAssignedToUserContainsDisplayId(userId, displayId);
if (unassign) {
Log.d(TAG, "Calling unassignUserFromExtraDisplay(" + userId + ", " + displayId + ")");
assertWithMessage("unassignUserFromExtraDisplay(%s, %s)", userId, displayId)
.that(mMediator.unassignUserFromExtraDisplay(userId, displayId))
.isTrue();
expectUserIsNotVisibleOnDisplay(userId, displayId);
expectDisplaysAssignedToUserDoesNotContainDisplayId(userId, displayId);
}
}
/**
* Asserts that a user (already visible or not) cannot be assigned to an extra display (and
* hence won't be visible on that display).
*/
protected void assertUserCannotBeAssignedExtraDisplay(@UserIdInt int userId, int displayId) {
expectWithMessage("assignUserToExtraDisplay(%s, %s)", userId, displayId)
.that(mMediator.assignUserToExtraDisplay(userId, displayId))
.isFalse();
expectUserIsNotVisibleOnDisplay(userId, displayId);
}
/**
* Asserts that an invisible user cannot be assigned to an extra display.
*/
protected void assertInvisibleUserCannotBeAssignedExtraDisplay(@UserIdInt int userId,
int displayId) {
assertUserCannotBeAssignedExtraDisplay(userId, displayId);
expectNoDisplayAssignedToUser(userId);
expectInitialCurrentUserAssignedToDisplay(displayId);
}
protected void expectUserIsVisible(@UserIdInt int userId) {
expectWithMessage("isUserVisible(%s)", userId)
.that(mMediator.isUserVisible(userId))
.isTrue();
}
protected void expectVisibleUsers(@UserIdInt Integer... userIds) {
IntArray visibleUsers = mMediator.getVisibleUsers();
expectWithMessage("getVisibleUsers()").that(visibleUsers).isNotNull();
expectWithMessage("getVisibleUsers()").that(visibleUsers.toArray()).asList()
.containsExactlyElementsIn(Arrays.asList(userIds));
}
protected void expectUserIsVisibleOnDisplay(@UserIdInt int userId, int displayId) {
expectWithMessage("isUserVisible(%s, %s)", userId, displayId)
.that(mMediator.isUserVisible(userId, displayId))
.isTrue();
}
protected void expectUserIsNotVisibleOnDisplay(@UserIdInt int userId, int displayId) {
expectWithMessage("isUserVisible(%s, %s)", userId, displayId)
.that(mMediator.isUserVisible(userId, displayId))
.isFalse();
}
protected void expectUserIsNotVisibleOnDisplay(String when, @UserIdInt int userId,
int displayId) {
String suffix = TextUtils.isEmpty(when) ? "" : " on " + when;
expectWithMessage("isUserVisible(%s, %s)%s", userId, displayId, suffix)
.that(mMediator.isUserVisible(userId, displayId))
.isFalse();
}
protected void expectUserIsNotVisibleAtAll(@UserIdInt int userId) {
expectWithMessage("isUserVisible(%s)", userId)
.that(mMediator.isUserVisible(userId))
.isFalse();
expectUserIsNotVisibleOnDisplay(userId, DEFAULT_DISPLAY);
expectUserIsNotVisibleOnDisplay(userId, INVALID_DISPLAY);
expectUserIsNotVisibleOnDisplay(userId, SECONDARY_DISPLAY_ID);
expectUserIsNotVisibleOnDisplay(userId, OTHER_SECONDARY_DISPLAY_ID);
expectDisplaysAssignedToUserIsEmpty(userId);
}
protected void expectDisplayAssignedToUser(@UserIdInt int userId, int displayId) {
expectWithMessage("getDisplayAssignedToUser(%s)", userId)
.that(mMediator.getDisplayAssignedToUser(userId)).isEqualTo(displayId);
}
protected void expectNoDisplayAssignedToUser(@UserIdInt int userId) {
expectWithMessage("getDisplayAssignedToUser(%s)", userId)
.that(mMediator.getDisplayAssignedToUser(userId)).isEqualTo(INVALID_DISPLAY);
}
protected void expectDisplaysAssignedToUserContainsDisplayId(
@UserIdInt int userId, int displayId) {
expectWithMessage("getDisplaysAssignedToUser(%s)", userId)
.that(mMediator.getDisplaysAssignedToUser(userId)).asList().contains(displayId);
}
protected void expectDisplaysAssignedToUserDoesNotContainDisplayId(
@UserIdInt int userId, int displayId) {
expectWithMessage("getDisplaysAssignedToUser(%s)", userId)
.that(mMediator.getDisplaysAssignedToUser(userId)).asList()
.doesNotContain(displayId);
}
protected void expectDisplaysAssignedToUserIsEmpty(@UserIdInt int userId) {
expectWithMessage("getDisplaysAssignedToUser(%s)", userId)
.that(mMediator.getDisplaysAssignedToUser(userId)).isNull();
}
protected void expectUserCannotBeUnassignedFromDisplay(@UserIdInt int userId, int displayId) {
expectWithMessage("unassignUserFromExtraDisplay(%s, %s)", userId, displayId)
.that(mMediator.unassignUserFromExtraDisplay(userId, displayId)).isFalse();
}
protected void expectUserAssignedToDisplay(int displayId, @UserIdInt int userId) {
expectWithMessage("getUserAssignedToDisplay(%s)", displayId)
.that(mMediator.getUserAssignedToDisplay(displayId)).isEqualTo(userId);
}
protected void expectInitialCurrentUserAssignedToDisplay(int displayId) {
expectWithMessage("getUserAssignedToDisplay(%s)", displayId)
.that(mMediator.getUserAssignedToDisplay(displayId))
.isEqualTo(INITIAL_CURRENT_USER_ID);
}
}