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

Commit 8b9cd557 authored by Felipe Leme's avatar Felipe Leme
Browse files

Revert "Fixed UserVisibilityMediator profile scenario."

Fix; 267600463
Test: no, sorry

This reverts commit 6638c3c4.

Change-Id: I93d5a0925982eef93a076e8c647c6e040dc6fda9
parent bba0a909
Loading
Loading
Loading
Loading
+5 −30
Original line number Diff line number Diff line
@@ -64,11 +64,12 @@ public abstract class UserManagerInternal {
    })
    public @interface UserAssignmentResult {}

    private static final String PREFIX_USER_START_MODE = "USER_START_MODE_";
    // 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;

    /**
     * Type used to indicate how a user started.
     */
    private static final String PREFIX_USER_START_MODE = "USER_START_MODE_";
    @IntDef(flag = false, prefix = {PREFIX_USER_START_MODE}, value = {
            USER_START_MODE_FOREGROUND,
            USER_START_MODE_BACKGROUND,
@@ -76,32 +77,6 @@ public abstract class UserManagerInternal {
    })
    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 {
        /**
         * Called when a user restriction changes.
+68 −154
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ import android.util.Dumpable;
import android.util.EventLog;
import android.util.IndentingPrintWriter;
import android.util.IntArray;
import android.util.Log;
import android.util.SparseIntArray;
import android.view.Display;

@@ -56,8 +55,6 @@ import com.android.server.pm.UserManagerInternal.UserVisibilityListener;
import com.android.server.utils.Slogf;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
@@ -80,11 +77,11 @@ import java.util.concurrent.CopyOnWriteArrayList;
 */
public final class UserVisibilityMediator implements Dumpable {

    private static final String TAG = UserVisibilityMediator.class.getSimpleName();

    private static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
    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 PREFIX_SECONDARY_DISPLAY_MAPPING = "SECONDARY_DISPLAY_MAPPING_";
    public static final int SECONDARY_DISPLAY_MAPPING_NEEDED = 1;
    public static final int SECONDARY_DISPLAY_MAPPING_NOT_NEEDED = 2;
@@ -101,7 +98,7 @@ public final class UserVisibilityMediator implements Dumpable {
    })
    public @interface SecondaryDisplayMappingStatus {}

    // TODO(b/266158156): might need to change this if boot logic is refactored for HSUM devices
    // TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
    @VisibleForTesting
    static final int INITIAL_CURRENT_USER_ID = USER_SYSTEM;

@@ -135,23 +132,10 @@ public final class UserVisibilityMediator implements Dumpable {
    private final SparseIntArray mExtraDisplaysAssignedToUsers;

    /**
     * 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")
    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.
     * Mapping from each started user to its profile group.
     */
    @GuardedBy("mLock")
    @Nullable
    private final List<Integer> mStartedInvisibleProfileUserIds;
    private final SparseIntArray mStartedProfileGroupIds = new SparseIntArray();

    /**
     * Handler user to call listeners
@@ -180,14 +164,9 @@ public final class UserVisibilityMediator implements Dumpable {
            mUsersAssignedToDisplayOnStart = null;
            mExtraDisplaysAssignedToUsers = null;
        }
        mStartedInvisibleProfileUserIds = DBG ? new ArrayList<>(4) : null;
        mHandler = handler;
        // TODO(b/266158156): might need to change this if boot logic is refactored for HSUM devices
        mStartedVisibleProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);

        if (DBG) {
            Slogf.i(TAG, "UserVisibilityMediator created with DBG on");
        }
        // TODO(b/242195409): might need to change this if boot logic is refactored for HSUM devices
        mStartedProfileGroupIds.put(INITIAL_CURRENT_USER_ID, INITIAL_CURRENT_USER_ID);
    }

    /**
@@ -198,8 +177,6 @@ public final class UserVisibilityMediator implements Dumpable {
            int displayId) {
        Preconditions.checkArgument(!isSpecialUserId(userId), "user id cannot be generic: %d",
                userId);
        validateUserStartMode(userStartMode);

        // This method needs to perform 4 actions:
        //
        // 1. Check if the user can be started given the provided arguments
@@ -247,29 +224,14 @@ public final class UserVisibilityMediator implements Dumpable {

            visibleUsersBefore = getVisibleUsers();

            // Set current user / started users state
            switch (userStartMode) {
                case USER_START_MODE_FOREGROUND:
            // Set current user / profiles state
            if (userStartMode == 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
            switch (mappingResult) {
@@ -335,46 +297,39 @@ public final class UserVisibilityMediator implements Dumpable {
        boolean foreground = userStartMode == USER_START_MODE_FOREGROUND;
        if (displayId != DEFAULT_DISPLAY) {
            if (foreground) {
                Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: cannot start "
                Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: cannot start "
                        + "foreground user on secondary display", userId, profileGroupId,
                        userStartModeToString(userStartMode), displayId);
                        foreground, displayId);
                return USER_ASSIGNMENT_RESULT_FAILURE;
            }
            if (!mVisibleBackgroundUsersEnabled) {
                Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: called on "
                Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %b, %d) failed: called on "
                        + "device that doesn't support multiple users on multiple displays",
                        userId, profileGroupId, userStartModeToString(userStartMode), displayId);
                        userId, profileGroupId, foreground, displayId);
                return USER_ASSIGNMENT_RESULT_FAILURE;
            }
        }

        if (isProfile(userId, profileGroupId)) {
            if (displayId != DEFAULT_DISPLAY) {
                Slogf.w(TAG, "canStartUserLocked(%d, %d, %s, %d) failed: cannot start profile user "
                        + "on secondary display", userId, profileGroupId,
                        userStartModeToString(userStartMode), displayId);
                Slogf.w(TAG, "canStartUserLocked(%d, %d, %b, %d) failed: cannot start profile user "
                        + "on secondary display", userId, profileGroupId, foreground,
                        displayId);
                return USER_ASSIGNMENT_RESULT_FAILURE;
            }
            switch (userStartMode) {
                case USER_START_MODE_FOREGROUND:
                    Slogf.w(TAG, "startUser(%d, %d, %s, %d) failed: cannot start profile user in "
                            + "foreground", userId, profileGroupId,
                            userStartModeToString(userStartMode), displayId);
            if (foreground) {
                Slogf.w(TAG, "startUser(%d, %d, %b, %d) failed: cannot start profile user in "
                        + "foreground", userId, profileGroupId, foreground, displayId);
                return USER_ASSIGNMENT_RESULT_FAILURE;
                case USER_START_MODE_BACKGROUND_VISIBLE:
            } else {
                boolean isParentVisibleOnDisplay = isUserVisible(profileGroupId, displayId);
                    if (!isParentVisibleOnDisplay) {
                        Slogf.w(TAG, "getUserVisibilityOnStartLocked(%d, %d, %s, %d) failed: cannot"
                                + " start profile user visible when its parent is not visible in "
                                + "that display", userId, profileGroupId,
                                userStartModeToString(userStartMode), displayId);
                        return USER_ASSIGNMENT_RESULT_FAILURE;
                if (DBG) {
                    Slogf.d(TAG, "parent visible on display: %b", isParentVisibleOnDisplay);
                }
                    return USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE;
                case USER_START_MODE_BACKGROUND:
                    return USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
                return isParentVisibleOnDisplay
                        ? USER_ASSIGNMENT_RESULT_SUCCESS_VISIBLE
                        : USER_ASSIGNMENT_RESULT_SUCCESS_INVISIBLE;
            }

        }

        return foreground || displayId != DEFAULT_DISPLAY
@@ -392,9 +347,8 @@ public final class UserVisibilityMediator implements Dumpable {
            if (mVisibleBackgroundUserOnDefaultDisplayAllowed
                    && userStartMode == USER_START_MODE_BACKGROUND_VISIBLE) {
                int userStartedOnDefaultDisplay = getUserStartedOnDisplay(DEFAULT_DISPLAY);
                if (userStartedOnDefaultDisplay != USER_NULL
                        && userStartedOnDefaultDisplay != profileGroupId) {
                    Slogf.w(TAG, "canAssignUserToDisplayLocked(): cannot start user %d visible on"
                if (userStartedOnDefaultDisplay != USER_NULL) {
                    Slogf.w(TAG, "getUserVisibilityOnStartLocked(): cannot start user %d visible on"
                            + " default display because user %d already did so", userId,
                            userStartedOnDefaultDisplay);
                    return SECONDARY_DISPLAY_MAPPING_FAILED;
@@ -500,7 +454,7 @@ public final class UserVisibilityMediator implements Dumpable {
                        userId, displayId);
                return false;
            }
            if (isStartedVisibleProfileLocked(userId)) {
            if (isStartedProfile(userId)) {
                Slogf.w(TAG, "assignUserToExtraDisplay(%d, %d): failed because user is a profile",
                        userId, displayId);
                return false;
@@ -588,14 +542,10 @@ public final class UserVisibilityMediator implements Dumpable {
    @GuardedBy("mLock")
    private void unassignUserFromAllDisplaysOnStopLocked(@UserIdInt int userId) {
        if (DBG) {
            Slogf.d(TAG, "Removing %d from mStartedVisibleProfileGroupIds (%s)", userId,
                    mStartedVisibleProfileGroupIds);
        }
        mStartedVisibleProfileGroupIds.delete(userId);
        if (mStartedInvisibleProfileUserIds != null) {
            Slogf.d(TAG, "Removing %d from list of invisible profiles", userId);
            mStartedInvisibleProfileUserIds.remove(Integer.valueOf(userId));
            Slogf.d(TAG, "Removing %d from mStartedProfileGroupIds (%s)", userId,
                    mStartedProfileGroupIds);
        }
        mStartedProfileGroupIds.delete(userId);

        if (!mVisibleBackgroundUsersEnabled) {
            // Don't need to update mUsersAssignedToDisplayOnStart because methods (such as
@@ -625,8 +575,7 @@ public final class UserVisibilityMediator implements Dumpable {
     * See {@link UserManagerInternal#isUserVisible(int)}.
     */
    public boolean isUserVisible(@UserIdInt int userId) {
        // For optimization (as most devices don't support visible background users), check for
        // current foreground user and their profiles first
        // First check current foreground user and their profiles (on main display)
        if (isCurrentUserOrRunningProfileOfCurrentUser(userId)) {
            if (VERBOSE) {
                Slogf.v(TAG, "isUserVisible(%d): true to current user or profile", userId);
@@ -635,31 +584,19 @@ public final class UserVisibilityMediator implements Dumpable {
        }

        if (!mVisibleBackgroundUsersEnabled) {
            if (VERBOSE) {
                Slogf.v(TAG, "isUserVisible(%d): false for non-current user (or its profiles) when"
            if (DBG) {
                Slogf.d(TAG, "isUserVisible(%d): false for non-current user (or its profiles) when"
                        + " device doesn't support visible background users", userId);
            }
            return false;
        }


        synchronized (mLock) {
            int profileGroupId;
        boolean visible;
        synchronized (mLock) {
                profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
            }
            if (isProfile(userId, profileGroupId)) {
                return isUserAssignedToDisplayOnStartLocked(profileGroupId);
            }
            return isUserAssignedToDisplayOnStartLocked(userId);
            visible = mUsersAssignedToDisplayOnStart.indexOfKey(userId) >= 0;
        }
    }

    @GuardedBy("mLock")
    private boolean isUserAssignedToDisplayOnStartLocked(@UserIdInt int userId) {
        boolean visible = mUsersAssignedToDisplayOnStart.indexOfKey(userId) >= 0;
        if (VERBOSE) {
            Slogf.v(TAG, "isUserAssignedToDisplayOnStartLocked(%d): %b", userId, visible);
        if (DBG) {
            Slogf.d(TAG, "isUserVisible(%d): %b from mapping", userId, visible);
        }
        return visible;
    }
@@ -672,8 +609,7 @@ public final class UserVisibilityMediator implements Dumpable {
            return false;
        }

        // For optimization (as most devices don't support visible background users), check for
        // current user and profile first. Current user is always visible on:
        // Current user is always visible on:
        // - Default display
        // - Secondary displays when device doesn't support visible bg users
        //   - Or when explicitly added (which is checked below)
@@ -695,27 +631,15 @@ public final class UserVisibilityMediator implements Dumpable {
        }

        synchronized (mLock) {
            int profileGroupId;
            synchronized (mLock) {
                profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
            }
            if (isProfile(userId, profileGroupId)) {
                return isFullUserVisibleOnBackgroundLocked(profileGroupId, displayId);
            }
            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)}.
@@ -782,7 +706,7 @@ public final class UserVisibilityMediator implements Dumpable {
                    continue;
                }
                int userId = mUsersAssignedToDisplayOnStart.keyAt(i);
                if (!isStartedVisibleProfileLocked(userId)) {
                if (!isStartedProfile(userId)) {
                    return userId;
                } else if (DBG) {
                    Slogf.d(TAG, "getUserAssignedToDisplay(%d): skipping user %d because it's "
@@ -815,8 +739,8 @@ public final class UserVisibilityMediator implements Dumpable {
        // number of users is too small, the gain is probably not worth the increase on complexity.
        IntArray visibleUsers = new IntArray();
        synchronized (mLock) {
            for (int i = 0; i < mStartedVisibleProfileGroupIds.size(); i++) {
                int userId = mStartedVisibleProfileGroupIds.keyAt(i);
            for (int i = 0; i < mStartedProfileGroupIds.size(); i++) {
                int userId = mStartedProfileGroupIds.keyAt(i);
                if (isUserVisible(userId)) {
                    visibleUsers.add(userId);
                }
@@ -849,7 +773,7 @@ public final class UserVisibilityMediator implements Dumpable {
        }
    }

    // TODO(b/266158156): remove this method if not needed anymore
    // TODO(b/242195409): remove this method if not needed anymore
    /**
     * Nofify all listeners that the system user visibility changed.
     */
@@ -911,9 +835,6 @@ public final class UserVisibilityMediator implements Dumpable {
        ipw.println("UserVisibilityMediator");
        ipw.increaseIndent();

        ipw.print("DBG: ");
        ipw.println(DBG);

        synchronized (mLock) {
            ipw.print("Current user id: ");
            ipw.println(mCurrentUserId);
@@ -921,12 +842,8 @@ public final class UserVisibilityMediator implements Dumpable {
            ipw.print("Visible users: ");
            ipw.println(getVisibleUsers());

            dumpSparseIntArray(ipw, mStartedVisibleProfileGroupIds,
                    "started visible user / profile group", "u", "pg");
            if (mStartedInvisibleProfileUserIds != null) {
                ipw.print("Profiles started invisible: ");
                ipw.println(mStartedInvisibleProfileUserIds);
            }
            dumpSparseIntArray(ipw, mStartedProfileGroupIds, "started user / profile group",
                    "u", "pg");

            ipw.print("Supports visible background users on displays: ");
            ipw.println(mVisibleBackgroundUsersEnabled);
@@ -1034,25 +951,22 @@ public final class UserVisibilityMediator implements Dumpable {
            if (mCurrentUserId == userId) {
                return true;
            }
            return mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID)
                    == mCurrentUserId;
            return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID) == mCurrentUserId;
        }
    }

    @GuardedBy("mLock")
    private boolean isStartedVisibleProfileLocked(@UserIdInt int userId) {
        int profileGroupId = mStartedVisibleProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
    private boolean isStartedProfile(@UserIdInt int userId) {
        int profileGroupId;
        synchronized (mLock) {
            profileGroupId = mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
        }
        return isProfile(userId, profileGroupId);
    }

    private void validateUserStartMode(@UserStartMode int userStartMode) {
        switch (userStartMode) {
            case USER_START_MODE_FOREGROUND:
            case USER_START_MODE_BACKGROUND:
            case USER_START_MODE_BACKGROUND_VISIBLE:
                return;
    private @UserIdInt int getStartedProfileGroupId(@UserIdInt int userId) {
        synchronized (mLock) {
            return mStartedProfileGroupIds.get(userId, NO_PROFILE_GROUP_ID);
        }
        throw new IllegalArgumentException("Invalid user start mode: " + userStartMode);
    }

    private static String secondaryDisplayMappingStatusToString(
+6 −4
Original line number Diff line number Diff line
@@ -75,8 +75,8 @@ public final class UserVisibilityMediatorMUPANDTest
        assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);

        // Make sure another user cannot be started on default display
        int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, otherUserId, BG_VISIBLE,
                DEFAULT_DISPLAY);
        int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
                BG_VISIBLE, DEFAULT_DISPLAY);
        assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
                "when user (%d) is starting on default display after it was started by user %d",
                otherUserId, visibleBgUserId);
@@ -119,8 +119,8 @@ public final class UserVisibilityMediatorMUPANDTest
        assertUserCanBeAssignedExtraDisplay(USER_ID, OTHER_SECONDARY_DISPLAY_ID);

        // Make sure another user cannot be started on default display
        int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, otherUserId, BG_VISIBLE,
                DEFAULT_DISPLAY);
        int result2 = mMediator.assignUserToDisplayOnStart(otherUserId, visibleBgUserId,
                BG_VISIBLE, DEFAULT_DISPLAY);
        assertStartUserResult(result2, USER_ASSIGNMENT_RESULT_FAILURE,
                "when user (%d) is starting on default display after it was started by user %d",
                otherUserId, visibleBgUserId);
@@ -128,6 +128,7 @@ public final class UserVisibilityMediatorMUPANDTest

        listener.verify();
    }
  /* TODO: re-add

    @Test
    public void
@@ -226,4 +227,5 @@ public final class UserVisibilityMediatorMUPANDTest

        listener.verify();
    }
  */
}
+6 −44

File changed.

Preview size limit exceeded, changes collapsed.

+30 −71

File changed.

Preview size limit exceeded, changes collapsed.