Merge "Revert "Revert "Fixed UserVisibilityMediator profile scenario.""" into udc-dev am: 1a8c7c147d
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/21616568 Change-Id: Ie77a56d5ac38ad4e82327db34cc50fa819149112 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -64,12 +64,11 @@ public abstract class UserManagerInternal {
|
|||||||
})
|
})
|
||||||
public @interface UserAssignmentResult {}
|
public @interface UserAssignmentResult {}
|
||||||
|
|
||||||
// TODO(b/248408342): Move keep annotation to the method referencing these fields reflectively.
|
|
||||||
@Keep public static final int USER_START_MODE_FOREGROUND = 1;
|
|
||||||
@Keep public static final int USER_START_MODE_BACKGROUND = 2;
|
|
||||||
@Keep public static final int USER_START_MODE_BACKGROUND_VISIBLE = 3;
|
|
||||||
|
|
||||||
private static final String PREFIX_USER_START_MODE = "USER_START_MODE_";
|
private static final String PREFIX_USER_START_MODE = "USER_START_MODE_";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Type used to indicate how a user started.
|
||||||
|
*/
|
||||||
@IntDef(flag = false, prefix = {PREFIX_USER_START_MODE}, value = {
|
@IntDef(flag = false, prefix = {PREFIX_USER_START_MODE}, value = {
|
||||||
USER_START_MODE_FOREGROUND,
|
USER_START_MODE_FOREGROUND,
|
||||||
USER_START_MODE_BACKGROUND,
|
USER_START_MODE_BACKGROUND,
|
||||||
@@ -77,6 +76,32 @@ public abstract class UserManagerInternal {
|
|||||||
})
|
})
|
||||||
public @interface UserStartMode {}
|
public @interface UserStartMode {}
|
||||||
|
|
||||||
|
// TODO(b/248408342): Move keep annotations below to the method referencing these fields
|
||||||
|
// reflectively.
|
||||||
|
|
||||||
|
/** (Full) user started on foreground (a.k.a. "current user"). */
|
||||||
|
@Keep public static final int USER_START_MODE_FOREGROUND = 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User (full or profile) started on background and is
|
||||||
|
* {@link UserManager#isUserVisible() invisible}.
|
||||||
|
*
|
||||||
|
* <p>This is the "traditional" way of starting a background user, and can be used to start
|
||||||
|
* profiles as well, although starting an invisible profile is not common from the System UI
|
||||||
|
* (it could be done through APIs or adb, though).
|
||||||
|
*/
|
||||||
|
@Keep public static final int USER_START_MODE_BACKGROUND = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User (full or profile) started on background and is
|
||||||
|
* {@link UserManager#isUserVisible() visible}.
|
||||||
|
*
|
||||||
|
* <p>This is the "traditional" way of starting a profile (i.e., when the profile of the current
|
||||||
|
* user is the current foreground user), but it can also be used to start a full user associated
|
||||||
|
* with a display (which is the case on automotives with passenger displays).
|
||||||
|
*/
|
||||||
|
@Keep public static final int USER_START_MODE_BACKGROUND_VISIBLE = 3;
|
||||||
|
|
||||||
public interface UserRestrictionsListener {
|
public interface UserRestrictionsListener {
|
||||||
/**
|
/**
|
||||||
* Called when a user restriction changes.
|
* Called when a user restriction changes.
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import android.util.Dumpable;
|
|||||||
import android.util.EventLog;
|
import android.util.EventLog;
|
||||||
import android.util.IndentingPrintWriter;
|
import android.util.IndentingPrintWriter;
|
||||||
import android.util.IntArray;
|
import android.util.IntArray;
|
||||||
|
import android.util.Log;
|
||||||
import android.util.SparseIntArray;
|
import android.util.SparseIntArray;
|
||||||
import android.view.Display;
|
import android.view.Display;
|
||||||
|
|
||||||
@@ -55,6 +56,8 @@ import com.android.server.pm.UserManagerInternal.UserVisibilityListener;
|
|||||||
import com.android.server.utils.Slogf;
|
import com.android.server.utils.Slogf;
|
||||||
|
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,11 +80,11 @@ import java.util.concurrent.CopyOnWriteArrayList;
|
|||||||
*/
|
*/
|
||||||
public final class UserVisibilityMediator implements Dumpable {
|
public final class UserVisibilityMediator implements Dumpable {
|
||||||
|
|
||||||
private static final boolean DBG = false; // DO NOT SUBMIT WITH TRUE
|
|
||||||
private static final boolean VERBOSE = false; // DO NOT SUBMIT WITH TRUE
|
|
||||||
|
|
||||||
private static final String TAG = UserVisibilityMediator.class.getSimpleName();
|
private static final String TAG = UserVisibilityMediator.class.getSimpleName();
|
||||||
|
|
||||||
|
private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
|
private static final boolean VERBOSE = false; // DO NOT SUBMIT WITH TRUE
|
||||||
|
|
||||||
private static final String PREFIX_SECONDARY_DISPLAY_MAPPING = "SECONDARY_DISPLAY_MAPPING_";
|
private static final String PREFIX_SECONDARY_DISPLAY_MAPPING = "SECONDARY_DISPLAY_MAPPING_";
|
||||||
public static final int SECONDARY_DISPLAY_MAPPING_NEEDED = 1;
|
public static final int SECONDARY_DISPLAY_MAPPING_NEEDED = 1;
|
||||||
public static final int SECONDARY_DISPLAY_MAPPING_NOT_NEEDED = 2;
|
public static final int SECONDARY_DISPLAY_MAPPING_NOT_NEEDED = 2;
|
||||||
@@ -98,7 +101,7 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
})
|
})
|
||||||
public @interface SecondaryDisplayMappingStatus {}
|
public @interface SecondaryDisplayMappingStatus {}
|
||||||
|
|
||||||
// TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
|
// TODO(b/266158156): might need to change this if boot logic is refactored for HSUM devices
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final int INITIAL_CURRENT_USER_ID = USER_SYSTEM;
|
static final int INITIAL_CURRENT_USER_ID = USER_SYSTEM;
|
||||||
|
|
||||||
@@ -132,10 +135,23 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
private final SparseIntArray mExtraDisplaysAssignedToUsers;
|
private final SparseIntArray mExtraDisplaysAssignedToUsers;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mapping from each started user to its profile group.
|
* Mapping of each user that started visible (key) to its profile group id (value).
|
||||||
|
*
|
||||||
|
* <p>It's used to determine not just if the user is visible, but also
|
||||||
|
* {@link #isProfile(int, int) if it's a profile}.
|
||||||
*/
|
*/
|
||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private final SparseIntArray mStartedProfileGroupIds = new SparseIntArray();
|
private final SparseIntArray mStartedVisibleProfileGroupIds = new SparseIntArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of profiles that have explicitly started invisible.
|
||||||
|
*
|
||||||
|
* <p>Only used for debugging purposes (and set when {@link #DBG} is {@code true}), hence we
|
||||||
|
* don't care about autoboxing.
|
||||||
|
*/
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
@Nullable
|
||||||
|
private final List<Integer> mStartedInvisibleProfileUserIds;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler user to call listeners
|
* Handler user to call listeners
|
||||||
@@ -164,9 +180,14 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
mUsersAssignedToDisplayOnStart = null;
|
mUsersAssignedToDisplayOnStart = null;
|
||||||
mExtraDisplaysAssignedToUsers = null;
|
mExtraDisplaysAssignedToUsers = null;
|
||||||
}
|
}
|
||||||
|
mStartedInvisibleProfileUserIds = DBG ? new ArrayList<>(4) : null;
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
// TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
|
// TODO(b/266158156): might need to change this if boot logic is refactored for HSUM devices
|
||||||
mStartedProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);
|
mStartedVisibleProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);
|
||||||
|
|
||||||
|
if (DBG) {
|
||||||
|
Slogf.i(TAG, "UserVisibilityMediator created with DBG on");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -177,6 +198,8 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
int displayId) {
|
int displayId) {
|
||||||
Preconditions.checkArgument(!isSpecialUserId(userId), "user id cannot be generic: %d",
|
Preconditions.checkArgument(!isSpecialUserId(userId), "user id cannot be generic: %d",
|
||||||
userId);
|
userId);
|
||||||
|
validateUserStartMode(userStartMode);
|
||||||
|
|
||||||
// This method needs to perform 4 actions:
|
// This method needs to perform 4 actions:
|
||||||
//
|
//
|
||||||
// 1. Check if the user can be started given the provided arguments
|
// 1. Check if the user can be started given the provided arguments
|
||||||
@@ -224,14 +247,29 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
|
|
||||||
visibleUsersBefore = getVisibleUsers();
|
visibleUsersBefore = getVisibleUsers();
|
||||||
|
|
||||||
// Set current user / profiles state
|
// Set current user / started users state
|
||||||
if (userStartMode == USER_START_MODE_FOREGROUND) {
|
switch (userStartMode) {
|
||||||
mCurrentUserId = userId;
|
case USER_START_MODE_FOREGROUND:
|
||||||
|
mCurrentUserId = userId;
|
||||||
|
// Fallthrough
|
||||||
|
case USER_START_MODE_BACKGROUND_VISIBLE:
|
||||||
|
if (DBG) {
|
||||||
|
Slogf.d(TAG, "adding visible user / profile group id mapping (%d -> %d)",
|
||||||
|
userId, profileGroupId);
|
||||||
|
}
|
||||||
|
mStartedVisibleProfileGroupIds.put(userId, profileGroupId);
|
||||||
|
break;
|
||||||
|
case USER_START_MODE_BACKGROUND:
|
||||||
|
if (mStartedInvisibleProfileUserIds != null
|
||||||
|
&& isProfile(userId, profileGroupId)) {
|
||||||
|
Slogf.d(TAG, "adding user %d to list of invisible profiles", userId);
|
||||||
|
mStartedInvisibleProfileUserIds.add(userId);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Slogf.wtf(TAG, "invalid userStartMode passed to assignUserToDisplayOnStart: "
|
||||||
|
+ "%d", userStartMode);
|
||||||
}
|
}
|
||||||
if (DBG) {
|
|
||||||
Slogf.d(TAG, "adding user / profile mapping (%d -> %d)", userId, profileGroupId);
|
|
||||||
}
|
|
||||||
mStartedProfileGroupIds.put(userId, profileGroupId);
|
|
||||||
|
|
||||||
// Set user / display state
|
// Set user / display state
|
||||||
switch (mappingResult) {
|
switch (mappingResult) {
|
||||||
@@ -297,38 +335,44 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
boolean foreground = userStartMode == USER_START_MODE_FOREGROUND;
|
boolean foreground = userStartMode == USER_START_MODE_FOREGROUND;
|
||||||
if (displayId != DEFAULT_DISPLAY) {
|
if (displayId != DEFAULT_DISPLAY) {
|
||||||
if (foreground) {
|
if (foreground) {
|
||||||
Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: cannot start "
|
Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: cannot start "
|
||||||
+ "foreground user on secondary display", userId, profileGroupId,
|
+ "foreground user on secondary display", userId, profileGroupId,
|
||||||
foreground, displayId);
|
userStartModeToString(userStartMode), displayId);
|
||||||
return USER_ASSIGNMENT_RESULT_FAILURE;
|
return USER_ASSIGNMENT_RESULT_FAILURE;
|
||||||
}
|
}
|
||||||
if (!mVisibleBackgroundUsersEnabled) {
|
if (!mVisibleBackgroundUsersEnabled) {
|
||||||
Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: called on "
|
Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: called on "
|
||||||
+ "device that doesn't support multiple users on multiple displays",
|
+ "device that doesn't support multiple users on multiple displays",
|
||||||
userId, profileGroupId, foreground, displayId);
|
userId, profileGroupId, userStartModeToString(userStartMode), displayId);
|
||||||
return USER_ASSIGNMENT_RESULT_FAILURE;
|
return USER_ASSIGNMENT_RESULT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isProfile(userId, profileGroupId)) {
|
if (isProfile(userId, profileGroupId)) {
|
||||||
if (displayId != DEFAULT_DISPLAY) {
|
if (displayId != DEFAULT_DISPLAY) {
|
||||||
Slogf.w(TAG, "canStartUserLocked(%d, %d, %b, %d) failed: cannot start profile user "
|
Slogf.w(TAG, "canStartUserLocked(%d, %d, %s, %d) failed: cannot start profile user "
|
||||||
+ "on secondary display", userId, profileGroupId, foreground,
|
+ "on secondary display", userId, profileGroupId,
|
||||||
displayId);
|
userStartModeToString(userStartMode), displayId);
|
||||||
return USER_ASSIGNMENT_RESULT_FAILURE;
|
return USER_ASSIGNMENT_RESULT_FAILURE;
|
||||||
}
|
}
|
||||||
if (foreground) {
|
switch (userStartMode) {
|
||||||
Slogf.w(TAG, "startUser(%d, %d, %b, %d) failed: cannot start profile user in "
|
case USER_START_MODE_FOREGROUND:
|
||||||
+ "foreground", userId, profileGroupId, foreground, displayId);
|
Slogf.w(TAG, "startUser(%d, %d, %s, %d) failed: cannot start profile user in "
|
||||||
return USER_ASSIGNMENT_RESULT_FAILURE;
|
+ "foreground", userId, profileGroupId,
|
||||||
} else {
|
userStartModeToString(userStartMode), displayId);
|
||||||
boolean isParentVisibleOnDisplay = isUserVisible(profileGroupId, displayId);
|
return USER_ASSIGNMENT_RESULT_FAILURE;
|
||||||
if (DBG) {
|
case USER_START_MODE_BACKGROUND_VISIBLE:
|
||||||
Slogf.d(TAG, "parent visible on display: %b", isParentVisibleOnDisplay);
|
boolean isParentVisibleOnDisplay = isUserVisible(profileGroupId, displayId);
|
||||||
}
|
if (!isParentVisibleOnDisplay) {
|
||||||
return isParentVisibleOnDisplay
|
Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: cannot"
|
||||||
? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
|
+ " start profile user visible when its parent is not visible in "
|
||||||
: USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
|
+ "that display", userId, profileGroupId,
|
||||||
|
userStartModeToString(userStartMode), displayId);
|
||||||
|
return USER_ASSIGNMENT_RESULT_FAILURE;
|
||||||
|
}
|
||||||
|
return USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
|
||||||
|
case USER_START_MODE_BACKGROUND:
|
||||||
|
return USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
|
||||||
}
|
}
|
||||||
} else if (mUsersAssignedToDisplayOnStart != null
|
} else if (mUsersAssignedToDisplayOnStart != null
|
||||||
&& isUserAssignedToDisplayOnStartLocked(userId, displayId)) {
|
&& isUserAssignedToDisplayOnStartLocked(userId, displayId)) {
|
||||||
@@ -353,8 +397,9 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
if (mVisibleBackgroundUserOnDefaultDisplayAllowed
|
if (mVisibleBackgroundUserOnDefaultDisplayAllowed
|
||||||
&& userStartMode == USER_START_MODE_BACKGROUND_VISIBLE) {
|
&& userStartMode == USER_START_MODE_BACKGROUND_VISIBLE) {
|
||||||
int userStartedOnDefaultDisplay = getUserStartedOnDisplay(DEFAULT_DISPLAY);
|
int userStartedOnDefaultDisplay = getUserStartedOnDisplay(DEFAULT_DISPLAY);
|
||||||
if (userStartedOnDefaultDisplay != USER_NULL) {
|
if (userStartedOnDefaultDisplay != USER_NULL
|
||||||
Slogf.w(TAG, "getUserVisibilityOnStartLocked(): cannot start user %d visible on"
|
&& userStartedOnDefaultDisplay != profileGroupId) {
|
||||||
|
Slogf.w(TAG, "canAssignUserToDisplayLocked(): cannot start user %d visible on"
|
||||||
+ " default display because user %d already did so", userId,
|
+ " default display because user %d already did so", userId,
|
||||||
userStartedOnDefaultDisplay);
|
userStartedOnDefaultDisplay);
|
||||||
return SECONDARY_DISPLAY_MAPPING_FAILED;
|
return SECONDARY_DISPLAY_MAPPING_FAILED;
|
||||||
@@ -468,7 +513,7 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
userId, displayId);
|
userId, displayId);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (isStartedProfile(userId)) {
|
if (isStartedVisibleProfileLocked(userId)) {
|
||||||
Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user is a profile",
|
Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user is a profile",
|
||||||
userId, displayId);
|
userId, displayId);
|
||||||
return false;
|
return false;
|
||||||
@@ -556,10 +601,14 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
@GuardedBy("mLock")
|
@GuardedBy("mLock")
|
||||||
private void unassignUserFromAllDisplaysOnStopLocked(@UserIdInt int userId) {
|
private void unassignUserFromAllDisplaysOnStopLocked(@UserIdInt int userId) {
|
||||||
if (DBG) {
|
if (DBG) {
|
||||||
Slogf.d(TAG, "Removing %d from mStartedProfileGroupIds (%s)", userId,
|
Slogf.d(TAG, "Removing %d from mStartedVisibleProfileGroupIds (%s)", userId,
|
||||||
mStartedProfileGroupIds);
|
mStartedVisibleProfileGroupIds);
|
||||||
|
}
|
||||||
|
mStartedVisibleProfileGroupIds.delete(userId);
|
||||||
|
if (mStartedInvisibleProfileUserIds != null) {
|
||||||
|
Slogf.d(TAG, "Removing %d from list of invisible profiles", userId);
|
||||||
|
mStartedInvisibleProfileUserIds.remove(Integer.valueOf(userId));
|
||||||
}
|
}
|
||||||
mStartedProfileGroupIds.delete(userId);
|
|
||||||
|
|
||||||
if (!mVisibleBackgroundUsersEnabled) {
|
if (!mVisibleBackgroundUsersEnabled) {
|
||||||
// Don't need to update mUsersAssignedToDisplayOnStart because methods (such as
|
// Don't need to update mUsersAssignedToDisplayOnStart because methods (such as
|
||||||
@@ -589,7 +638,8 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
* See {@link UserManagerInternal#isUserVisible(int)}.
|
* See {@link UserManagerInternal#isUserVisible(int)}.
|
||||||
*/
|
*/
|
||||||
public boolean isUserVisible(@UserIdInt int userId) {
|
public boolean isUserVisible(@UserIdInt int userId) {
|
||||||
// First check current foreground user and their profiles (on main display)
|
// For optimization (as most devices don't support visible background users), check for
|
||||||
|
// current foreground user and their profiles first
|
||||||
if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
|
if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
|
||||||
if (VERBOSE) {
|
if (VERBOSE) {
|
||||||
Slogf.v(TAG, "isUserVisible(%d): true to current user or profile", userId);
|
Slogf.v(TAG, "isUserVisible(%d): true to current user or profile", userId);
|
||||||
@@ -598,19 +648,31 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!mVisibleBackgroundUsersEnabled) {
|
if (!mVisibleBackgroundUsersEnabled) {
|
||||||
if (DBG) {
|
if (VERBOSE) {
|
||||||
Slogf.d(TAG, "isUserVisible(%d): false for non-current user (or its profiles) when"
|
Slogf.v(TAG, "isUserVisible(%d): false for non-current user (or its profiles) when"
|
||||||
+ " device doesn't support visible background users", userId);
|
+ " device doesn't support visible background users", userId);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean visible;
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
visible = mUsersAssignedToDisplayOnStart.indexOfKey(userId) >= 0;
|
int profileGroupId;
|
||||||
|
synchronized (mLock) {
|
||||||
|
profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
|
||||||
|
}
|
||||||
|
if (isProfile(userId, profileGroupId)) {
|
||||||
|
return isUserAssignedToDisplayOnStartLocked(profileGroupId);
|
||||||
|
}
|
||||||
|
return isUserAssignedToDisplayOnStartLocked(userId);
|
||||||
}
|
}
|
||||||
if (DBG) {
|
}
|
||||||
Slogf.d(TAG, "isUserVisible(%d): %b from mapping", userId, visible);
|
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private boolean isUserAssignedToDisplayOnStartLocked(@UserIdInt int userId) {
|
||||||
|
boolean visible = mUsersAssignedToDisplayOnStart.indexOfKey(userId) >= 0;
|
||||||
|
if (VERBOSE) {
|
||||||
|
Slogf.v(TAG, "isUserAssignedToDisplayOnStartLocked(%d): %b", userId, visible);
|
||||||
}
|
}
|
||||||
return visible;
|
return visible;
|
||||||
}
|
}
|
||||||
@@ -640,7 +702,8 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current user is always visible on:
|
// For optimization (as most devices don't support visible background users), check for
|
||||||
|
// current user and profile first. Current user is always visible on:
|
||||||
// - Default display
|
// - Default display
|
||||||
// - Secondary displays when device doesn't support visible bg users
|
// - Secondary displays when device doesn't support visible bg users
|
||||||
// - Or when explicitly added (which is checked below)
|
// - Or when explicitly added (which is checked below)
|
||||||
@@ -662,16 +725,28 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
if (mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY) == displayId) {
|
int profileGroupId;
|
||||||
// User assigned to display on start
|
synchronized (mLock) {
|
||||||
return true;
|
profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
|
||||||
}
|
}
|
||||||
|
if (isProfile(userId, profileGroupId)) {
|
||||||
// Check for extra display assignment
|
return isFullUserVisibleOnBackgroundLocked(profileGroupId, displayId);
|
||||||
return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
|
}
|
||||||
|
return isFullUserVisibleOnBackgroundLocked(userId, displayId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: it doesn't check if the userId is a full user, it's up to the caller to check that
|
||||||
|
@GuardedBy("mLock")
|
||||||
|
private boolean isFullUserVisibleOnBackgroundLocked(@UserIdInt int userId, int displayId) {
|
||||||
|
if (mUsersAssignedToDisplayOnStart.get(userId, Display.INVALID_DISPLAY) == displayId) {
|
||||||
|
// User assigned to display on start
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Check for extra display assignment
|
||||||
|
return mExtraDisplaysAssignedToUsers.get(displayId, USER_NULL) == userId;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* See {@link UserManagerInternal#getDisplayAssignedToUser(int)}.
|
* See {@link UserManagerInternal#getDisplayAssignedToUser(int)}.
|
||||||
*/
|
*/
|
||||||
@@ -737,7 +812,7 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
int userId = mUsersAssignedToDisplayOnStart.keyAt(i);
|
int userId = mUsersAssignedToDisplayOnStart.keyAt(i);
|
||||||
if (!isStartedProfile(userId)) {
|
if (!isStartedVisibleProfileLocked(userId)) {
|
||||||
return userId;
|
return userId;
|
||||||
} else if (DBG) {
|
} else if (DBG) {
|
||||||
Slogf.d(TAG, "getUserAssignedToDisplay(%d): skipping user %d because it's "
|
Slogf.d(TAG, "getUserAssignedToDisplay(%d): skipping user %d because it's "
|
||||||
@@ -770,8 +845,8 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
// number of users is too small, the gain is probably not worth the increase on complexity.
|
// number of users is too small, the gain is probably not worth the increase on complexity.
|
||||||
IntArray visibleUsers = new IntArray();
|
IntArray visibleUsers = new IntArray();
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
for (int i = 0; i < mStartedProfileGroupIds.size(); i++) {
|
for (int i = 0; i < mStartedVisibleProfileGroupIds.size(); i++) {
|
||||||
int userId = mStartedProfileGroupIds.keyAt(i);
|
int userId = mStartedVisibleProfileGroupIds.keyAt(i);
|
||||||
if (isUserVisible(userId)) {
|
if (isUserVisible(userId)) {
|
||||||
visibleUsers.add(userId);
|
visibleUsers.add(userId);
|
||||||
}
|
}
|
||||||
@@ -804,7 +879,7 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(b/242195409): remove this method if not needed anymore
|
// TODO(b/266158156): remove this method if not needed anymore
|
||||||
/**
|
/**
|
||||||
* Nofify all listeners that the system user visibility changed.
|
* Nofify all listeners that the system user visibility changed.
|
||||||
*/
|
*/
|
||||||
@@ -866,6 +941,9 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
ipw.println("UserVisibilityMediator");
|
ipw.println("UserVisibilityMediator");
|
||||||
ipw.increaseIndent();
|
ipw.increaseIndent();
|
||||||
|
|
||||||
|
ipw.print("DBG: ");
|
||||||
|
ipw.println(DBG);
|
||||||
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
ipw.print("Current user id: ");
|
ipw.print("Current user id: ");
|
||||||
ipw.println(mCurrentUserId);
|
ipw.println(mCurrentUserId);
|
||||||
@@ -873,8 +951,12 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
ipw.print("Visible users: ");
|
ipw.print("Visible users: ");
|
||||||
ipw.println(getVisibleUsers());
|
ipw.println(getVisibleUsers());
|
||||||
|
|
||||||
dumpSparseIntArray(ipw, mStartedProfileGroupIds, "started user / profile group",
|
dumpSparseIntArray(ipw, mStartedVisibleProfileGroupIds,
|
||||||
"u", "pg");
|
"started visible user / profile group", "u", "pg");
|
||||||
|
if (mStartedInvisibleProfileUserIds != null) {
|
||||||
|
ipw.print("Profiles started invisible: ");
|
||||||
|
ipw.println(mStartedInvisibleProfileUserIds);
|
||||||
|
}
|
||||||
|
|
||||||
ipw.print("Supports visible background users on displays: ");
|
ipw.print("Supports visible background users on displays: ");
|
||||||
ipw.println(mVisibleBackgroundUsersEnabled);
|
ipw.println(mVisibleBackgroundUsersEnabled);
|
||||||
@@ -982,22 +1064,25 @@ public final class UserVisibilityMediator implements Dumpable {
|
|||||||
if (mCurrentUserId == userId) {
|
if (mCurrentUserId == userId) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID) == mCurrentUserId;
|
return mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID)
|
||||||
|
== mCurrentUserId;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isStartedProfile(@UserIdInt int userId) {
|
@GuardedBy("mLock")
|
||||||
int profileGroupId;
|
private boolean isStartedVisibleProfileLocked(@UserIdInt int userId) {
|
||||||
synchronized (mLock) {
|
int profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
|
||||||
profileGroupId = mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
|
|
||||||
}
|
|
||||||
return isProfile(userId, profileGroupId);
|
return isProfile(userId, profileGroupId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private @UserIdInt int getStartedProfileGroupId(@UserIdInt int userId) {
|
private void validateUserStartMode(@UserStartMode int userStartMode) {
|
||||||
synchronized (mLock) {
|
switch (userStartMode) {
|
||||||
return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
|
case USER_START_MODE_FOREGROUND:
|
||||||
|
case USER_START_MODE_BACKGROUND:
|
||||||
|
case USER_START_MODE_BACKGROUND_VISIBLE:
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
throw new IllegalArgumentException("Invalid user start mode: " + userStartMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String secondaryDisplayMappingStatusToString(
|
private static String secondaryDisplayMappingStatusToString(
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ import static android.view.Display.DEFAULT_DISPLAY;
|
|||||||
import static android.view.Display.INVALID_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_FAILURE;
|
||||||
|
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_ALREADY_VISIBLE;
|
||||||
|
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_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
|
||||||
import static com.android.server.pm.UserVisibilityChangedEvent.onInvisible;
|
import static com.android.server.pm.UserVisibilityChangedEvent.onInvisible;
|
||||||
import static com.android.server.pm.UserVisibilityChangedEvent.onVisible;
|
import static com.android.server.pm.UserVisibilityChangedEvent.onVisible;
|
||||||
@@ -73,8 +75,8 @@ public final class UserVisibilityMediatorMUPANDTest
|
|||||||
assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
|
assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
|
||||||
|
|
||||||
// Make sure another user cannot be started on default display
|
// Make sure another user cannot be started on default display
|
||||||
int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
|
int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, otherUserId, BG_VISIBLE,
|
||||||
BG_VISIBLE, DEFAULT_DISPLAY);
|
DEFAULT_DISPLAY);
|
||||||
assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
|
assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
|
||||||
"when user (%d) is starting on default display after it was started by user %d",
|
"when user (%d) is starting on default display after it was started by user %d",
|
||||||
otherUserId, visibleBgUserId);
|
otherUserId, visibleBgUserId);
|
||||||
@@ -117,8 +119,8 @@ public final class UserVisibilityMediatorMUPANDTest
|
|||||||
assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
|
assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);
|
||||||
|
|
||||||
// Make sure another user cannot be started on default display
|
// Make sure another user cannot be started on default display
|
||||||
int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
|
int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, otherUserId, BG_VISIBLE,
|
||||||
BG_VISIBLE, DEFAULT_DISPLAY);
|
DEFAULT_DISPLAY);
|
||||||
assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
|
assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
|
||||||
"when user (%d) is starting on default display after it was started by user %d",
|
"when user (%d) is starting on default display after it was started by user %d",
|
||||||
otherUserId, visibleBgUserId);
|
otherUserId, visibleBgUserId);
|
||||||
@@ -127,8 +129,6 @@ public final class UserVisibilityMediatorMUPANDTest
|
|||||||
listener.verify();
|
listener.verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO(b/261538337): re-add after the reverted CL is merged again
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void
|
public void
|
||||||
testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedVisibleOnBgOnSecondaryDisplay()
|
testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedVisibleOnBgOnSecondaryDisplay()
|
||||||
@@ -226,5 +226,4 @@ public final class UserVisibilityMediatorMUPANDTest
|
|||||||
|
|
||||||
listener.verify();
|
listener.verify();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ import android.text.TextUtils;
|
|||||||
import android.util.IntArray;
|
import android.util.IntArray;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.android.internal.util.Preconditions;
|
|
||||||
import com.android.server.DumpableDumperRule;
|
import com.android.server.DumpableDumperRule;
|
||||||
import com.android.server.ExpectableTestCase;
|
import com.android.server.ExpectableTestCase;
|
||||||
|
|
||||||
@@ -151,6 +150,12 @@ abstract class UserVisibilityMediatorTestCase extends ExpectableTestCase {
|
|||||||
.assignUserToDisplayOnStart(USER_CURRENT_OR_SELF, USER_ID, FG, DEFAULT_DISPLAY));
|
.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
|
@Test
|
||||||
public final void testStartFgUser_onSecondaryDisplay() throws Exception {
|
public final void testStartFgUser_onSecondaryDisplay() throws Exception {
|
||||||
AsyncUserVisibilityListener listener = addListenerForNoEvents();
|
AsyncUserVisibilityListener listener = addListenerForNoEvents();
|
||||||
@@ -286,7 +291,7 @@ abstract class UserVisibilityMediatorTestCase extends ExpectableTestCase {
|
|||||||
|
|
||||||
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
|
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
|
||||||
BG_VISIBLE, DEFAULT_DISPLAY);
|
BG_VISIBLE, DEFAULT_DISPLAY);
|
||||||
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
|
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
|
||||||
|
|
||||||
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
|
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
|
||||||
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
|
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
|
||||||
@@ -302,14 +307,14 @@ abstract class UserVisibilityMediatorTestCase extends ExpectableTestCase {
|
|||||||
|
|
||||||
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
|
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
|
||||||
BG_VISIBLE, DEFAULT_DISPLAY);
|
BG_VISIBLE, DEFAULT_DISPLAY);
|
||||||
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
|
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
|
||||||
|
|
||||||
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
|
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
|
||||||
|
|
||||||
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
|
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
|
||||||
expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
|
expectInitialCurrentUserAssignedToDisplay(DEFAULT_DISPLAY);
|
||||||
|
|
||||||
assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
|
assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
|
||||||
|
|
||||||
listener.verify();
|
listener.verify();
|
||||||
}
|
}
|
||||||
@@ -334,6 +339,41 @@ abstract class UserVisibilityMediatorTestCase extends ExpectableTestCase {
|
|||||||
listener.verify();
|
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
|
@Test
|
||||||
public final void testStartBgProfile_onSecondaryDisplay() throws Exception {
|
public final void testStartBgProfile_onSecondaryDisplay() throws Exception {
|
||||||
AsyncUserVisibilityListener listener = addListenerForNoEvents();
|
AsyncUserVisibilityListener listener = addListenerForNoEvents();
|
||||||
@@ -488,8 +528,6 @@ abstract class UserVisibilityMediatorTestCase extends ExpectableTestCase {
|
|||||||
* se.
|
* se.
|
||||||
*/
|
*/
|
||||||
protected final void startUserInSecondaryDisplay(@UserIdInt int userId, int displayId) {
|
protected final void startUserInSecondaryDisplay(@UserIdInt int userId, int displayId) {
|
||||||
Preconditions.checkArgument(displayId != INVALID_DISPLAY && displayId != DEFAULT_DISPLAY,
|
|
||||||
"must pass a secondary display, not %d", displayId);
|
|
||||||
Log.d(TAG, "startUserInSecondaryDisplay(" + userId + ", " + displayId + ")");
|
Log.d(TAG, "startUserInSecondaryDisplay(" + userId + ", " + displayId + ")");
|
||||||
int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG_VISIBLE, displayId);
|
int result = mMediator.assignUserToDisplayOnStart(userId, userId, BG_VISIBLE, displayId);
|
||||||
if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
|
if (result != USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE) {
|
||||||
|
|||||||
@@ -108,34 +108,6 @@ abstract class UserVisibilityMediatorVisibleBackgroundUserTestCase
|
|||||||
listener.verify();
|
listener.verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public final void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
|
|
||||||
throws Exception {
|
|
||||||
AsyncUserVisibilityListener listener = addListenerForEvents(
|
|
||||||
onInvisible(INITIAL_CURRENT_USER_ID),
|
|
||||||
onVisible(PARENT_USER_ID),
|
|
||||||
onVisible(PROFILE_USER_ID));
|
|
||||||
startForegroundUser(PARENT_USER_ID);
|
|
||||||
|
|
||||||
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
|
|
||||||
BG_VISIBLE, DEFAULT_DISPLAY);
|
|
||||||
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
|
|
||||||
expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
|
|
||||||
|
|
||||||
expectUserIsVisible(PROFILE_USER_ID);
|
|
||||||
expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
|
|
||||||
expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
|
|
||||||
expectUserIsVisibleOnDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
|
|
||||||
expectVisibleUsers(PARENT_USER_ID, PROFILE_USER_ID);
|
|
||||||
|
|
||||||
expectDisplayAssignedToUser(PROFILE_USER_ID, DEFAULT_DISPLAY);
|
|
||||||
expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
|
|
||||||
|
|
||||||
assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
|
|
||||||
|
|
||||||
listener.verify();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public final void testStartFgUser_onInvalidDisplay() throws Exception {
|
public final void testStartFgUser_onInvalidDisplay() throws Exception {
|
||||||
AsyncUserVisibilityListener listener = addListenerForNoEvents();
|
AsyncUserVisibilityListener listener = addListenerForNoEvents();
|
||||||
@@ -300,15 +272,84 @@ abstract class UserVisibilityMediatorVisibleBackgroundUserTestCase
|
|||||||
listener2.verify();
|
listener2.verify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public final void testStartVisibleBgProfile_onDefaultDisplay_whenParentIsCurrentUser()
|
||||||
|
throws Exception {
|
||||||
|
AsyncUserVisibilityListener listener = addListenerForEvents(
|
||||||
|
onInvisible(INITIAL_CURRENT_USER_ID),
|
||||||
|
onVisible(PARENT_USER_ID),
|
||||||
|
onVisible(PROFILE_USER_ID));
|
||||||
|
startForegroundUser(PARENT_USER_ID);
|
||||||
|
|
||||||
|
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
|
||||||
|
BG_VISIBLE, DEFAULT_DISPLAY);
|
||||||
|
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
|
||||||
|
expectUserCannotBeUnassignedFromDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
|
||||||
|
|
||||||
|
expectUserIsVisible(PROFILE_USER_ID);
|
||||||
|
expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, INVALID_DISPLAY);
|
||||||
|
expectUserIsNotVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
|
||||||
|
expectUserIsVisibleOnDisplay(PROFILE_USER_ID, DEFAULT_DISPLAY);
|
||||||
|
expectVisibleUsers(PARENT_USER_ID, PROFILE_USER_ID);
|
||||||
|
|
||||||
|
expectDisplayAssignedToUser(PROFILE_USER_ID, DEFAULT_DISPLAY);
|
||||||
|
expectUserAssignedToDisplay(DEFAULT_DISPLAY, PARENT_USER_ID);
|
||||||
|
|
||||||
|
assertUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
|
||||||
|
|
||||||
|
listener.verify();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public final void
|
public final void
|
||||||
testStartVisibleBgProfile_onDefaultDisplay_whenParentVisibleOnSecondaryDisplay()
|
testStartVisibleBgProfile_onDefaultDisplay_whenParentIsStartedVisibleOnAnotherDisplay()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
|
AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
|
||||||
startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
|
startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
|
||||||
|
|
||||||
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
|
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID,
|
||||||
BG_VISIBLE, DEFAULT_DISPLAY);
|
BG_VISIBLE, DEFAULT_DISPLAY);
|
||||||
|
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_FAILURE);
|
||||||
|
|
||||||
|
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
|
||||||
|
expectNoDisplayAssignedToUser(PROFILE_USER_ID);
|
||||||
|
expectUserAssignedToDisplay(OTHER_SECONDARY_DISPLAY_ID, PARENT_USER_ID);
|
||||||
|
|
||||||
|
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_whenParentIsStartedVisibleOnThatDisplay()
|
||||||
|
throws Exception {
|
||||||
|
AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
|
||||||
|
startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_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);
|
||||||
|
expectUserAssignedToDisplay(OTHER_SECONDARY_DISPLAY_ID, PARENT_USER_ID);
|
||||||
|
|
||||||
|
assertInvisibleUserCannotBeAssignedExtraDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID);
|
||||||
|
|
||||||
|
listener.verify();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public final void
|
||||||
|
testStartProfile_onDefaultDisplay_whenParentIsStartedVisibleOnSecondaryDisplay()
|
||||||
|
throws Exception {
|
||||||
|
AsyncUserVisibilityListener listener = addListenerForEvents(onVisible(PARENT_USER_ID));
|
||||||
|
startUserInSecondaryDisplay(PARENT_USER_ID, OTHER_SECONDARY_DISPLAY_ID);
|
||||||
|
|
||||||
|
int result = mMediator.assignUserToDisplayOnStart(PROFILE_USER_ID, PARENT_USER_ID, BG,
|
||||||
|
DEFAULT_DISPLAY);
|
||||||
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
|
assertStartUserResult(result, USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
|
||||||
|
|
||||||
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
|
expectUserIsNotVisibleAtAll(PROFILE_USER_ID);
|
||||||
|
|||||||
Reference in New Issue
Block a user