Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b0e342ca authored by Felipe Leme's avatar Felipe Leme Committed by Android (Google) Code Review
Browse files

Merge "Further improvements on isUserVisibleOnDisplay(userId, displayId)."

parents bfdba14a 5a82b5ae
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1514,8 +1514,6 @@ class UserController implements Handler.Callback {
            Preconditions.checkArgument(!foreground, "Cannot start user %d in foreground AND "
                    + "on secondary display (%d)", userId, displayId);
        }
        mInjector.getUserManagerInternal().assignUserToDisplay(userId, displayId);

        // TODO(b/239982558): log display id (or use a new event)
        EventLog.writeEvent(EventLogTags.UC_START_USER_INTERNAL, userId);

@@ -1571,6 +1569,8 @@ class UserController implements Handler.Callback {
                return false;
            }

            mInjector.getUserManagerInternal().assignUserToDisplay(userId, displayId);

            // TODO(b/239982558): might need something similar for bg users on secondary display
            if (foreground && isUserSwitchUiEnabled()) {
                t.traceBegin("startFreezingScreen");
+37 −11
Original line number Diff line number Diff line
@@ -1862,22 +1862,48 @@ public class UserManagerService extends IUserManager.Stub {
    }

    // TODO(b/239982558): try to merge with isUserVisibleUnchecked() (once both are unit tested)
    /**
     * See {@link UserManagerInternal#isUserVisible(int, int)}.
     */
    boolean isUserVisibleOnDisplay(@UserIdInt int userId, int displayId) {
        // TODO(b/244644281): temporary workaround to let WM use this API without breaking current
        // behavior (otherwise current user / profiles wouldn't be able to launch activities on
        // other non-passenger displays, like cluster, display, or virtual displays)
        if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
            return true;
        if (displayId == Display.INVALID_DISPLAY) {
            return false;
        }

        if (displayId == Display.DEFAULT_DISPLAY) {
        if (!mUsersOnSecondaryDisplaysEnabled) {
            return isCurrentUserOrRunningProfileOfCurrentUser(userId);
        }

        // Device doesn't support multiple users on multiple displays, so only users checked above
        // can be visible
        if (!mUsersOnSecondaryDisplaysEnabled) {
            return false;
        // TODO(b/244644281): temporary workaround to let WM use this API without breaking current
        // behavior - return true for current user / profile for any display (other than those
        // explicitly assigned to another users), otherwise they wouldn't be able to launch
        // activities on other non-passenger displays, like cluster, display, or virtual displays).
        // In the long-term, it should rely just on mUsersOnSecondaryDisplays, which
        // would be updated by DisplayManagerService when displays are created / initialized.
        if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
            synchronized (mUsersOnSecondaryDisplays) {
                boolean assignedToUser = false;
                boolean assignedToAnotherUser = false;
                for (int i = 0; i < mUsersOnSecondaryDisplays.size(); i++) {
                    if (mUsersOnSecondaryDisplays.valueAt(i) == displayId) {
                        if (mUsersOnSecondaryDisplays.keyAt(i) == userId) {
                            assignedToUser = true;
                            break;
                        } else {
                            assignedToAnotherUser = true;
                            // Cannot break because it could be assigned to a profile of the user
                            // (and we better not assume that the iteration will check for the
                            // parent user before its profiles)
                        }
                    }
                }
                if (DBG_MUMD) {
                    Slogf.d(LOG_TAG, "isUserVisibleOnDisplay(%d, %d): assignedToUser=%b, "
                            + "assignedToAnotherUser=%b, mUsersOnSecondaryDisplays=%s",
                            userId, displayId, assignedToUser, assignedToAnotherUser,
                            mUsersOnSecondaryDisplays);
                }
                return assignedToUser || !assignedToAnotherUser;
            }
        }

        synchronized (mUsersOnSecondaryDisplays) {
+4 −10
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.util.IndentingPrintWriter;
import android.util.Slog;
import android.view.Display;

import com.android.internal.widget.LockPatternUtils;
import com.android.server.LocalServices;
@@ -374,19 +373,14 @@ public class UserManagerServiceShellCommand extends ShellCommand {
    })
    private int runIsUserVisible() {
        PrintWriter pw = getOutPrintWriter();
        int displayId = Display.INVALID_DISPLAY;
        Integer displayId = null;
        String opt;
        while ((opt = getNextOption()) != null) {
            boolean invalidOption = false;
            switch (opt) {
                case "--display":
                    displayId = Integer.parseInt(getNextArgRequired());
                    invalidOption = displayId == Display.INVALID_DISPLAY;
                    break;
                default:
                    invalidOption = true;
            }
            if (invalidOption) {
                    pw.println("Invalid option: " + opt);
                    return -1;
            }
@@ -404,7 +398,7 @@ public class UserManagerServiceShellCommand extends ShellCommand {
        }

        boolean isVisible;
        if (displayId != Display.INVALID_DISPLAY) {
        if (displayId != null) {
            isVisible = mService.isUserVisibleOnDisplay(userId, displayId);
        } else {
            isVisible = getUserManagerForUser(userId).isUserVisible();
+61 −2
Original line number Diff line number Diff line
@@ -101,6 +101,11 @@ abstract class UserManagerServiceOrInternalTestCase extends ExtendedMockitoTestC
     */
    protected static final int OTHER_SECONDARY_DISPLAY_ID = 108;

    /**
     * Id of another secondary display (i.e, not {@link android.view.Display.DEFAULT_DISPLAY}).
     */
    private static final int ANOTHER_SECONDARY_DISPLAY_ID = 108;

    private final Object mPackagesLock = new Object();
    private final Context mRealContext = androidx.test.InstrumentationRegistry.getInstrumentation()
            .getTargetContext();
@@ -267,7 +272,7 @@ abstract class UserManagerServiceOrInternalTestCase extends ExtendedMockitoTestC
        mockCurrentUser(USER_ID);

        assertWithMessage("isUserVisibleOnDisplay(%s, %s)", USER_ID, INVALID_DISPLAY)
                .that(isUserVisibleOnDisplay(USER_ID, INVALID_DISPLAY)).isTrue();
                .that(isUserVisibleOnDisplay(USER_ID, INVALID_DISPLAY)).isFalse();
    }

    @Test
@@ -286,6 +291,49 @@ abstract class UserManagerServiceOrInternalTestCase extends ExtendedMockitoTestC
                .that(isUserVisibleOnDisplay(USER_ID, SECONDARY_DISPLAY_ID)).isTrue();
    }

    @Test
    public void testIsUserVisibleOnDisplay_mumd_currentUserUnassignedSecondaryDisplay() {
        enableUsersOnSecondaryDisplays();
        mockCurrentUser(USER_ID);

        assertWithMessage("isUserVisibleOnDisplay(%s, %s)", USER_ID, SECONDARY_DISPLAY_ID)
                .that(isUserVisibleOnDisplay(USER_ID, SECONDARY_DISPLAY_ID)).isTrue();
    }

    @Test
    public void testIsUserVisibleOnDisplay_mumd_currentUserSecondaryDisplayAssignedToAnotherUser() {
        enableUsersOnSecondaryDisplays();
        mockCurrentUser(USER_ID);
        assignUserToDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID);

        assertWithMessage("isUserVisibleOnDisplay(%s, %s)", USER_ID, SECONDARY_DISPLAY_ID)
                .that(isUserVisibleOnDisplay(USER_ID, SECONDARY_DISPLAY_ID)).isFalse();
    }

    @Test
    public void testIsUserVisibleOnDisplay_mumd_startedProfileOfCurrentUserSecondaryDisplayAssignedToAnotherUser() {
        enableUsersOnSecondaryDisplays();
        addDefaultProfileAndParent();
        startDefaultProfile();
        mockCurrentUser(PARENT_USER_ID);
        assignUserToDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID);

        assertWithMessage("isUserVisibleOnDisplay(%s, %s)", PROFILE_USER_ID, SECONDARY_DISPLAY_ID)
                .that(isUserVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)).isFalse();
    }

    @Test
    public void testIsUserVisibleOnDisplay_mumd_stoppedProfileOfCurrentUserSecondaryDisplayAssignedToAnotherUser() {
        enableUsersOnSecondaryDisplays();
        addDefaultProfileAndParent();
        stopDefaultProfile();
        mockCurrentUser(PARENT_USER_ID);
        assignUserToDisplay(OTHER_USER_ID, SECONDARY_DISPLAY_ID);

        assertWithMessage("isUserVisibleOnDisplay(%s, %s)", PROFILE_USER_ID, SECONDARY_DISPLAY_ID)
                .that(isUserVisibleOnDisplay(PROFILE_USER_ID, SECONDARY_DISPLAY_ID)).isFalse();
    }

    @Test
    public void testIsUserVisibleOnDisplay_nonCurrentUserDefaultDisplay() {
        mockCurrentUser(OTHER_USER_ID);
@@ -358,7 +406,7 @@ abstract class UserManagerServiceOrInternalTestCase extends ExtendedMockitoTestC
    }

    @Test
    public void testIsUserVisibleOnDisplay_bgUserOnSecondaryDisplay() {
    public void testIsUserVisibleOnDisplay_mumd_bgUserOnSecondaryDisplay() {
        enableUsersOnSecondaryDisplays();
        mockCurrentUser(OTHER_USER_ID);
        assignUserToDisplay(USER_ID, SECONDARY_DISPLAY_ID);
@@ -367,6 +415,17 @@ abstract class UserManagerServiceOrInternalTestCase extends ExtendedMockitoTestC
                .that(isUserVisibleOnDisplay(USER_ID, SECONDARY_DISPLAY_ID)).isTrue();
    }

    @Test
    public void testIsUserVisibleOnDisplay_mumd_bgUserOnAnotherSecondaryDisplay() {
        enableUsersOnSecondaryDisplays();
        mockCurrentUser(OTHER_USER_ID);
        assignUserToDisplay(USER_ID, SECONDARY_DISPLAY_ID);

        assertWithMessage("isUserVisibleOnDisplay(%s, %s)", USER_ID, SECONDARY_DISPLAY_ID)
                .that(isUserVisibleOnDisplay(USER_ID, ANOTHER_SECONDARY_DISPLAY_ID)).isFalse();
    }


    // NOTE: we don't need to add tests for profiles (started / stopped profiles of bg user), as
    // isUserVisibleOnDisplay() for bg users relies only on the user / display assignments