Merge "Delegated user visibility changes from UserController to UserVisibilityMediator."

This commit is contained in:
Felipe Leme
2022-12-01 17:47:06 +00:00
committed by Android (Google) Code Review
8 changed files with 62 additions and 206 deletions

View File

@@ -977,12 +977,11 @@ message UserControllerProto {
optional int32 profile = 2;
}
repeated UserProfile user_profile_group_ids = 4;
repeated int32 visible_users_array = 5;
// current_user contains the id of the current user, while current_profiles contains the ids of
// both the current user and its profiles (if any)
optional int32 current_user = 6;
repeated int32 current_profiles = 7;
optional int32 current_user = 5;
repeated int32 current_profiles = 6;
}
// sync with com.android.server.am.AppTimeTracker.java

View File

@@ -100,7 +100,6 @@ import android.util.EventLog;
import android.util.IntArray;
import android.util.Pair;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
@@ -177,7 +176,8 @@ class UserController implements Handler.Callback {
static final int START_USER_SWITCH_FG_MSG = 120;
static final int COMPLETE_USER_SWITCH_MSG = 130;
static final int USER_COMPLETED_EVENT_MSG = 140;
static final int USER_VISIBILITY_CHANGED_MSG = 150;
private static final int NO_ARG2 = 0;
// Message constant to clear {@link UserJourneySession} from {@link mUserIdToUserJourneyMap} if
// the user journey, defined in the UserLifecycleJourneyReported atom for statsd, is not
@@ -437,20 +437,6 @@ class UserController implements Handler.Callback {
/** @see #getLastUserUnlockingUptime */
private volatile long mLastUserUnlockingUptime = 0;
// TODO(b/244333150) remove this array and let UserVisibilityMediator call the listeners
// directly, as that class should be responsible for all user visibility logic (for example,
// when the foreground user is switched out, its profiles also become invisible)
/**
* List of visible users (as defined by {@link UserManager#isUserVisible()}).
*
* <p>It's only used to call {@link UserManagerInternal} when the visibility is changed upon
* the user starting or stopping.
*
* <p>Note: only the key is used, not the value.
*/
@GuardedBy("mLock")
private final SparseBooleanArray mVisibleUsers = new SparseBooleanArray();
private final UserLifecycleListener mUserLifecycleListener = new UserLifecycleListener() {
@Override
public void onUserCreated(UserInfo user, Object token) {
@@ -1092,24 +1078,11 @@ class UserController implements Handler.Callback {
// instead.
userManagerInternal.unassignUserFromDisplayOnStop(userId);
final boolean visibilityChanged;
boolean visibleBefore;
synchronized (mLock) {
visibleBefore = mVisibleUsers.get(userId);
if (visibleBefore) {
deleteVisibleUserLocked(userId);
visibilityChanged = true;
} else {
visibilityChanged = false;
}
}
updateStartedUserArrayLU();
final boolean allowDelayedLockingCopied = allowDelayedLocking;
Runnable finishUserStoppingAsync = () ->
mHandler.post(() -> finishUserStopping(userId, uss, allowDelayedLockingCopied,
visibilityChanged));
mHandler.post(() -> finishUserStopping(userId, uss, allowDelayedLockingCopied));
if (mInjector.getUserManager().isPreCreated(userId)) {
finishUserStoppingAsync.run();
@@ -1146,22 +1119,8 @@ class UserController implements Handler.Callback {
}
}
private void addVisibleUserLocked(@UserIdInt int userId) {
if (DEBUG_MU) {
Slogf.d(TAG, "adding %d to mVisibleUsers", userId);
}
mVisibleUsers.put(userId, true);
}
private void deleteVisibleUserLocked(@UserIdInt int userId) {
if (DEBUG_MU) {
Slogf.d(TAG, "deleting %d from mVisibleUsers", userId);
}
mVisibleUsers.delete(userId);
}
private void finishUserStopping(final int userId, final UserState uss,
final boolean allowDelayedLocking, final boolean visibilityChanged) {
final boolean allowDelayedLocking) {
EventLog.writeEvent(EventLogTags.UC_FINISH_USER_STOPPING, userId);
synchronized (mLock) {
if (uss.state != UserState.STATE_STOPPING) {
@@ -1179,9 +1138,6 @@ class UserController implements Handler.Callback {
BatteryStats.HistoryItem.EVENT_USER_RUNNING_FINISH,
Integer.toString(userId), userId);
mInjector.getSystemServiceManager().onUserStopping(userId);
if (visibilityChanged) {
mInjector.onUserVisibilityChanged(userId, /* visible= */ false);
}
Runnable finishUserStoppedAsync = () ->
mHandler.post(() -> finishUserStopped(uss, allowDelayedLocking));
@@ -1655,25 +1611,13 @@ class UserController implements Handler.Callback {
userInfo.profileGroupId, foreground, displayId);
t.traceEnd();
boolean visible;
switch (result) {
case UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE:
visible = true;
break;
case UserManagerInternal.USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE:
visible = false;
break;
default:
Slogf.wtf(TAG, "Wrong result from assignUserToDisplayOnStart(): %d", result);
// Fall through
case UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE:
Slogf.e(TAG, "%s user(%d) / display (%d) assignment failed: %s",
(foreground ? "fg" : "bg"), userId, displayId,
UserManagerInternal.userAssignmentResultToString(result));
return false;
if (result == UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE) {
Slogf.e(TAG, "%s user(%d) / display (%d) assignment failed: %s",
(foreground ? "fg" : "bg"), userId, displayId,
UserManagerInternal.userAssignmentResultToString(result));
return false;
}
// TODO(b/239982558): might need something similar for bg users on secondary display
if (foreground && isUserSwitchUiEnabled()) {
t.traceBegin("startFreezingScreen");
@@ -1724,15 +1668,7 @@ class UserController implements Handler.Callback {
// Make sure the old user is no longer considering the display to be on.
mInjector.reportGlobalUsageEvent(UsageEvents.Event.SCREEN_NON_INTERACTIVE);
boolean userSwitchUiEnabled;
// TODO(b/244333150): temporary state until the callback logic is moved to
// UserVisibilityManager
int previousCurrentUserId; boolean notifyPreviousCurrentUserId;
synchronized (mLock) {
previousCurrentUserId = mCurrentUserId;
notifyPreviousCurrentUserId = mVisibleUsers.get(previousCurrentUserId);
if (notifyPreviousCurrentUserId) {
deleteVisibleUserLocked(previousCurrentUserId);
}
mCurrentUserId = userId;
mTargetUserId = UserHandle.USER_NULL; // reset, mCurrentUserId has caught up
userSwitchUiEnabled = mUserSwitchUiEnabled;
@@ -1753,10 +1689,6 @@ class UserController implements Handler.Callback {
mInjector.getWindowManager().lockNow(null);
}
}
if (notifyPreviousCurrentUserId) {
mHandler.sendMessage(mHandler.obtainMessage(USER_VISIBILITY_CHANGED_MSG,
previousCurrentUserId, 0));
}
} else {
final Integer currentUserIdInt = mCurrentUserId;
@@ -1768,12 +1700,6 @@ class UserController implements Handler.Callback {
}
t.traceEnd();
if (visible) {
synchronized (mLock) {
addVisibleUserLocked(userId);
}
}
// Make sure user is in the started state. If it is currently
// stopping, we need to knock that off.
if (uss.state == UserState.STATE_STOPPING) {
@@ -1810,20 +1736,10 @@ class UserController implements Handler.Callback {
// Booting up a new user, need to tell system services about it.
// Note that this is on the same handler as scheduling of broadcasts,
// which is important because it needs to go first.
mHandler.sendMessage(mHandler.obtainMessage(USER_START_MSG, userId,
visible ? 1 : 0));
mHandler.sendMessage(mHandler.obtainMessage(USER_START_MSG, userId, NO_ARG2));
t.traceEnd();
}
if (visible) {
// User was already running and became visible (for example, when switching to a
// user that was started in the background before), so it's necessary to explicitly
// notify the services (while when the user starts from BOOTING, USER_START_MSG
// takes care of that.
mHandler.sendMessage(
mHandler.obtainMessage(USER_VISIBILITY_CHANGED_MSG, userId, 1));
}
t.traceBegin("sendMessages");
if (foreground) {
mHandler.sendMessage(mHandler.obtainMessage(USER_CURRENT_MSG, userId, oldUserId));
@@ -2248,11 +2164,6 @@ class UserController implements Handler.Callback {
uss.switching = false;
stopGuestOrEphemeralUserIfBackground(oldUserId);
stopUserOnSwitchIfEnforced(oldUserId);
if (oldUserId == UserHandle.USER_SYSTEM) {
// System user is never stopped, but its visibility is changed (as it is brought to the
// background)
updateSystemUserVisibility(t, /* visible= */ false);
}
t.traceEnd(); // end continueUserSwitch
}
@@ -2614,27 +2525,10 @@ class UserController implements Handler.Callback {
// Don't need to call on HSUM because it will be called when the system user is
// restarted on background
mInjector.onUserStarting(UserHandle.USER_SYSTEM);
mInjector.onUserVisibilityChanged(UserHandle.USER_SYSTEM, /* visible= */ true);
mInjector.onSystemUserVisibilityChanged(/* visible= */ true);
}
}
private void updateSystemUserVisibility(TimingsTraceAndSlog t, boolean visible) {
t.traceBegin("update-system-userVisibility-" + visible);
if (DEBUG_MU) {
Slogf.d(TAG, "updateSystemUserVisibility(): visible=%b", visible);
}
int userId = UserHandle.USER_SYSTEM;
synchronized (mLock) {
if (visible) {
addVisibleUserLocked(userId);
} else {
deleteVisibleUserLocked(userId);
}
}
mInjector.onUserVisibilityChanged(userId, visible);
t.traceEnd();
}
/**
* Refreshes the internal caches related to user profiles.
*
@@ -3032,9 +2926,6 @@ class UserController implements Handler.Callback {
proto.end(uToken);
}
}
for (int i = 0; i < mVisibleUsers.size(); i++) {
proto.write(UserControllerProto.VISIBLE_USERS_ARRAY, mVisibleUsers.keyAt(i));
}
proto.write(UserControllerProto.CURRENT_USER, mCurrentUserId);
for (int i = 0; i < mCurrentProfileIds.length; i++) {
proto.write(UserControllerProto.CURRENT_PROFILES, mCurrentProfileIds[i]);
@@ -3094,7 +2985,6 @@ class UserController implements Handler.Callback {
pw.println(" mSwitchingToSystemUserMessage: " + mSwitchingToSystemUserMessage);
}
pw.println(" mLastUserUnlockingUptime: " + mLastUserUnlockingUptime);
pw.println(" mVisibleUsers: " + mVisibleUsers);
}
}
@@ -3212,10 +3102,6 @@ class UserController implements Handler.Callback {
case COMPLETE_USER_SWITCH_MSG:
completeUserSwitch(msg.arg1);
break;
case USER_VISIBILITY_CHANGED_MSG:
mInjector.onUserVisibilityChanged(/* userId= */ msg.arg1,
/* visible= */ msg.arg2 == 1);
break;
}
return false;
}
@@ -3750,8 +3636,8 @@ class UserController implements Handler.Callback {
getSystemServiceManager().onUserStarting(TimingsTraceAndSlog.newAsyncLog(), userId);
}
void onUserVisibilityChanged(@UserIdInt int userId, boolean visible) {
getUserManagerInternal().onUserVisibilityChanged(userId, visible);
void onSystemUserVisibilityChanged(boolean visible) {
getUserManagerInternal().onSystemUserVisibilityChanged(visible);
}
}
}

View File

@@ -435,8 +435,10 @@ public abstract class UserManagerInternal {
/** Removes a {@link UserVisibilityListener}. */
public abstract void removeUserVisibilityListener(UserVisibilityListener listener);
/** TODO(b/244333150): temporary method until UserVisibilityMediator handles that logic */
public abstract void onUserVisibilityChanged(@UserIdInt int userId, boolean visible);
// TODO(b/242195409): remove this method if not needed anymore
/** Notify {@link UserVisibilityListener listeners} that the visibility of the
* {@link android.os.UserHandle#USER_SYSTEM} changed. */
public abstract void onSystemUserVisibilityChanged(boolean visible);
/** Return the integer types of the given user IDs. Only used for reporting metrics to statsd.
*/

View File

@@ -97,7 +97,6 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
import android.util.IntArray;
import android.util.Slog;
@@ -126,7 +125,6 @@ import com.android.server.BundleUtils;
import com.android.server.LocalServices;
import com.android.server.LockGuard;
import com.android.server.SystemService;
import com.android.server.am.EventLogTags;
import com.android.server.am.UserState;
import com.android.server.pm.UserManagerInternal.UserLifecycleListener;
import com.android.server.pm.UserManagerInternal.UserRestrictionsListener;
@@ -512,10 +510,6 @@ public class UserManagerService extends IUserManager.Stub {
@GuardedBy("mUserLifecycleListeners")
private final ArrayList<UserLifecycleListener> mUserLifecycleListeners = new ArrayList<>();
// TODO(b/244333150): temporary array, should belong to UserVisibilityMediator
@GuardedBy("mUserVisibilityListeners")
private final ArrayList<UserVisibilityListener> mUserVisibilityListeners = new ArrayList<>();
private final LockPatternUtils mLockPatternUtils;
private final String ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK =
@@ -6383,9 +6377,6 @@ public class UserManagerService extends IUserManager.Stub {
synchronized (mUserLifecycleListeners) {
pw.println(" user lifecycle events: " + mUserLifecycleListeners.size());
}
synchronized (mUserVisibilityListeners) {
pw.println(" user visibility events: " + mUserVisibilityListeners.size());
}
// Dump UserTypes
pw.println();
@@ -6961,31 +6952,17 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public void addUserVisibilityListener(UserVisibilityListener listener) {
synchronized (mUserVisibilityListeners) {
mUserVisibilityListeners.add(listener);
}
mUserVisibilityMediator.addListener(listener);
}
@Override
public void removeUserVisibilityListener(UserVisibilityListener listener) {
synchronized (mUserVisibilityListeners) {
mUserVisibilityListeners.remove(listener);
}
mUserVisibilityMediator.removeListener(listener);
}
@Override
public void onUserVisibilityChanged(@UserIdInt int userId, boolean visible) {
EventLog.writeEvent(EventLogTags.UM_USER_VISIBILITY_CHANGED, userId, visible ? 1 : 0);
mHandler.post(() -> {
UserVisibilityListener[] listeners;
synchronized (mUserVisibilityListeners) {
listeners = new UserVisibilityListener[mUserVisibilityListeners.size()];
mUserVisibilityListeners.toArray(listeners);
}
for (UserVisibilityListener listener : listeners) {
listener.onUserVisibilityChanged(userId, visible);
}
});
public void onSystemUserVisibilityChanged(boolean visible) {
mUserVisibilityMediator.onSystemUserVisibilityChanged(visible);
}
@Override

View File

@@ -32,6 +32,7 @@ import android.os.Handler;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Dumpable;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
import android.util.IntArray;
import android.util.SparseIntArray;
@@ -40,6 +41,7 @@ import android.view.Display;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.Preconditions;
import com.android.server.am.EventLogTags;
import com.android.server.pm.UserManagerInternal.UserAssignmentResult;
import com.android.server.pm.UserManagerInternal.UserVisibilityListener;
import com.android.server.utils.Slogf;
@@ -68,6 +70,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
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();
@@ -381,8 +384,8 @@ public final class UserVisibilityMediator implements Dumpable {
public boolean isUserVisible(@UserIdInt int userId) {
// First check current foreground user and their profiles (on main display)
if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
if (DBG) {
Slogf.d(TAG, "isUserVisible(%d): true to current user or profile", userId);
if (VERBOSE) {
Slogf.v(TAG, "isUserVisible(%d): true to current user or profile", userId);
}
return true;
}
@@ -517,6 +520,14 @@ public final class UserVisibilityMediator implements Dumpable {
}
}
// TODO(b/242195409): remove this method if not needed anymore
/**
* Nofify all listeners that the system user visibility changed.
*/
void onSystemUserVisibilityChanged(boolean visible) {
dispatchVisibilityChanged(mListeners, USER_SYSTEM, visible);
}
/**
* Nofify all listeners about the visibility changes from before / after a change of state.
*/
@@ -534,7 +545,7 @@ public final class UserVisibilityMediator implements Dumpable {
Slogf.d(TAG,
"dispatchVisibilityChanged(): visibleUsersBefore=%s, visibleUsersAfter=%s, "
+ "%d listeners (%s)", visibleUsersBefore, visibleUsersAfter, listeners.size(),
mListeners);
listeners);
}
for (int i = 0; i < visibleUsersBefore.size(); i++) {
int userId = visibleUsersBefore.get(i);
@@ -552,13 +563,14 @@ public final class UserVisibilityMediator implements Dumpable {
private void dispatchVisibilityChanged(CopyOnWriteArrayList<UserVisibilityListener> listeners,
@UserIdInt int userId, boolean visible) {
EventLog.writeEvent(EventLogTags.UM_USER_VISIBILITY_CHANGED, userId, visible ? 1 : 0);
if (DBG) {
Slogf.d(TAG, "dispatchVisibilityChanged(%d -> %b): sending to %d listeners",
userId, visible, listeners.size());
}
for (int i = 0; i < mListeners.size(); i++) {
UserVisibilityListener listener = mListeners.get(i);
if (DBG) {
if (VERBOSE) {
Slogf.v(TAG, "dispatchVisibilityChanged(%d -> %b): sending to %s",
userId, visible, listener);
}

View File

@@ -30,7 +30,6 @@ import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* {@link UserVisibilityListener} implementation that expects callback events to be asynchronously
* received.

View File

@@ -329,6 +329,15 @@ abstract class UserVisibilityMediatorTestCase extends ExtendedMockitoTestCase {
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.
*

View File

@@ -38,9 +38,6 @@ import static com.android.server.am.UserController.USER_COMPLETED_EVENT_MSG;
import static com.android.server.am.UserController.USER_CURRENT_MSG;
import static com.android.server.am.UserController.USER_START_MSG;
import static com.android.server.am.UserController.USER_SWITCH_TIMEOUT_MSG;
import static com.android.server.am.UserController.USER_VISIBILITY_CHANGED_MSG;
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.google.android.collect.Lists.newArrayList;
import static com.google.android.collect.Sets.newHashSet;
@@ -102,7 +99,6 @@ import com.android.server.FgThread;
import com.android.server.SystemService;
import com.android.server.am.UserState.KeyEvictedCallback;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerInternal.UserAssignmentResult;
import com.android.server.pm.UserManagerService;
import com.android.server.wm.WindowManagerService;
@@ -162,18 +158,12 @@ public class UserControllerTest {
REPORT_USER_SWITCH_MSG,
USER_SWITCH_TIMEOUT_MSG,
USER_START_MSG,
USER_VISIBILITY_CHANGED_MSG,
USER_CURRENT_MSG);
private static final Set<Integer> START_INVISIBLE_BACKGROUND_USER_MESSAGE_CODES = newHashSet(
private static final Set<Integer> START_BACKGROUND_USER_MESSAGE_CODES = newHashSet(
USER_START_MSG,
REPORT_LOCKED_BOOT_COMPLETE_MSG);
private static final Set<Integer> START_VISIBLE_BACKGROUND_USER_MESSAGE_CODES = newHashSet(
USER_START_MSG,
USER_VISIBILITY_CHANGED_MSG,
REPORT_LOCKED_BOOT_COMPLETE_MSG);
@Before
public void setUp() throws Exception {
runWithDexmakerShareClassLoader(() -> {
@@ -225,14 +215,12 @@ public class UserControllerTest {
@Test
public void testStartUser_background() {
mockAssignUserToMainDisplay(TEST_USER_ID, /* foreground= */ false,
USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
boolean started = mUserController.startUser(TEST_USER_ID, /* foreground= */ false);
assertWithMessage("startUser(%s, foreground=false)", TEST_USER_ID).that(started).isTrue();
verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
verify(mInjector, never()).clearAllLockedTasks(anyString());
startBackgroundUserAssertions(/*visible= */ false);
startBackgroundUserAssertions();
verifyUserAssignedToDisplay(TEST_USER_ID, Display.DEFAULT_DISPLAY);
}
@@ -267,7 +255,7 @@ public class UserControllerTest {
verify(mInjector.getWindowManager(), never()).startFreezingScreen(anyInt(), anyInt());
verify(mInjector.getWindowManager(), never()).setSwitchingUser(anyBoolean());
verify(mInjector, never()).clearAllLockedTasks(anyString());
startBackgroundUserAssertions(/*visible= */ true);
startBackgroundUserAssertions();
}
@Test
@@ -293,8 +281,6 @@ public class UserControllerTest {
@Test
public void testStartPreCreatedUser_background() throws Exception {
mockAssignUserToMainDisplay(TEST_PRE_CREATED_USER_ID, /* foreground= */ false,
USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
assertTrue(mUserController.startUser(TEST_PRE_CREATED_USER_ID, /* foreground= */ false));
// Make sure no intents have been fired for pre-created users.
assertTrue(mInjector.mSentIntents.isEmpty());
@@ -322,10 +308,8 @@ public class UserControllerTest {
assertEquals("Unexpected message sent", expectedMessageCodes, actualCodes);
}
private void startBackgroundUserAssertions(boolean visible) {
startUserAssertions(START_BACKGROUND_USER_ACTIONS,
visible ? START_VISIBLE_BACKGROUND_USER_MESSAGE_CODES
: START_INVISIBLE_BACKGROUND_USER_MESSAGE_CODES);
private void startBackgroundUserAssertions() {
startUserAssertions(START_BACKGROUND_USER_ACTIONS, START_BACKGROUND_USER_MESSAGE_CODES);
}
private void startForegroundUserAssertions() {
@@ -433,7 +417,7 @@ public class UserControllerTest {
verify(mInjector, times(0)).dismissKeyguard(any(), anyString());
verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
continueUserSwitchAssertions(TEST_USER_ID, false);
verifySystemUserVisibilityChangedNotified(/* visible= */ false);
verifySystemUserVisibilityChangesNeverNotified();
}
@Test
@@ -454,7 +438,7 @@ public class UserControllerTest {
verify(mInjector, times(1)).dismissKeyguard(any(), anyString());
verify(mInjector.getWindowManager(), times(1)).stopFreezingScreen();
continueUserSwitchAssertions(TEST_USER_ID, false);
verifySystemUserVisibilityChangedNotified(/* visible= */ false);
verifySystemUserVisibilityChangesNeverNotified();
}
@Test
@@ -561,7 +545,7 @@ public class UserControllerTest {
assertFalse(mUserController.canStartMoreUsers());
assertEquals(Arrays.asList(new Integer[] {0, TEST_USER_ID1, TEST_USER_ID2}),
mUserController.getRunningUsersLU());
verifySystemUserVisibilityChangedNotified(/* visible= */ false);
verifySystemUserVisibilityChangesNeverNotified();
}
/**
@@ -709,24 +693,19 @@ public class UserControllerTest {
@Test
public void testStartProfile() throws Exception {
mockAssignUserToMainDisplay(TEST_PRE_CREATED_USER_ID, /* foreground= */ false,
USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE);
setUpAndStartProfileInBackground(TEST_USER_ID1);
startBackgroundUserAssertions(/*visible= */ true);
startBackgroundUserAssertions();
verifyUserAssignedToDisplay(TEST_USER_ID1, Display.DEFAULT_DISPLAY);
}
@Test
public void testStartProfile_whenUsersOnSecondaryDisplaysIsEnabled() throws Exception {
mockAssignUserToMainDisplay(TEST_USER_ID1, /* foreground= */ false,
USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE);
mockIsUsersOnSecondaryDisplaysEnabled(true);
setUpAndStartProfileInBackground(TEST_USER_ID1);
startBackgroundUserAssertions(/*visible= */ true);
startBackgroundUserAssertions();
verifyUserAssignedToDisplay(TEST_USER_ID1, Display.DEFAULT_DISPLAY);
}
@@ -983,13 +962,6 @@ public class UserControllerTest {
when(mInjector.isUsersOnSecondaryDisplaysEnabled()).thenReturn(value);
}
private void mockAssignUserToMainDisplay(@UserIdInt int userId, boolean foreground,
@UserAssignmentResult int result) {
when(mInjector.mUserManagerInternalMock.assignUserToDisplayOnStart(eq(userId),
/* profileGroupId= */ anyInt(), eq(foreground), eq(Display.DEFAULT_DISPLAY)))
.thenReturn(result);
}
private void verifyUserAssignedToDisplay(@UserIdInt int userId, int displayId) {
verify(mInjector.getUserManagerInternal()).assignUserToDisplayOnStart(eq(userId), anyInt(),
anyBoolean(), eq(displayId));
@@ -1008,8 +980,8 @@ public class UserControllerTest {
verify(mInjector.getUserManagerInternal(), never()).unassignUserFromDisplayOnStop(userId);
}
private void verifySystemUserVisibilityChangedNotified(boolean visible) {
verify(mInjector).onUserVisibilityChanged(UserHandle.USER_SYSTEM, visible);
private void verifySystemUserVisibilityChangesNeverNotified() {
verify(mInjector, never()).onSystemUserVisibilityChanged(anyBoolean());
}
// Should be public to allow mocking
@@ -1154,8 +1126,8 @@ public class UserControllerTest {
}
@Override
void onUserVisibilityChanged(@UserIdInt int userId, boolean visible) {
Log.i(TAG, "onUserVisibilityChanged(" + userId + ", " + visible + ")");
void onSystemUserVisibilityChanged(boolean visible) {
Log.i(TAG, "onSystemUserVisibilityChanged(" + visible + ")");
}
}