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

Commit 82012de2 authored by Felipe Leme's avatar Felipe Leme
Browse files

Refactored user start mode boolean into a tri-state int.

Prior to Android U, a user would start either on foreground (A.K.A.
"current user") or background (in which case it could not launch
activities). But now, the background user could be associated with a
display, in which case it would become "visible" (and could launch
activities in that display).

So, this CL changes the foreground / background boolean state into a
new tri-state int (@UserStartMode):

- USER_START_MODE_FOREGROUND
- USER_START_MODE_BACKGROUND
- USER_START_MODE_BACKGROUND_VISIBLE

But it doesn't change any logic (yet :-).

Test: atest FrameworksServicesTests:UserControllerTest
Bug: 261537398

Change-Id: I30fd3b0f4ea3fa03c3520214b360fc6920138f9f
parent 74848985
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -137,6 +137,8 @@ import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_
import static com.android.server.am.ProcessProfileRecord.HOSTING_COMPONENT_TYPE_SYSTEM;
import static com.android.server.net.NetworkPolicyManagerInternal.updateBlockedReasonsWithProcState;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.pm.UserManagerInternal.USER_START_MODE_BACKGROUND;
import static com.android.server.pm.UserManagerInternal.USER_START_MODE_FOREGROUND;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_CLEANUP;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_SWITCH;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.POSTFIX_CONFIGURATION;
@@ -16566,14 +16568,14 @@ public class ActivityManagerService extends IActivityManager.Stub
    @Override
    public boolean startUserInBackgroundWithListener(final int userId,
                @Nullable IProgressListener unlockListener) {
        return mUserController.startUser(userId, /* foreground */ false, unlockListener);
        return mUserController.startUser(userId, USER_START_MODE_BACKGROUND, unlockListener);
    }
    @Override
    public boolean startUserInForegroundWithListener(final int userId,
            @Nullable IProgressListener unlockListener) {
        // Permission check done inside UserController.
        return mUserController.startUser(userId, /* foreground */ true, unlockListener);
        return mUserController.startUser(userId, USER_START_MODE_FOREGROUND, unlockListener);
    }
    @Override
@@ -18495,7 +18497,7 @@ public class ActivityManagerService extends IActivityManager.Stub
    @Override
    public int restartUserInBackground(final int userId) {
        return mUserController.restartUser(userId, /* foreground */ false);
        return mUserController.restartUser(userId, USER_START_MODE_BACKGROUND);
    }
    @Override
+44 −35
Original line number Diff line number Diff line
@@ -46,6 +46,11 @@ import static com.android.server.am.UserState.STATE_BOOTING;
import static com.android.server.am.UserState.STATE_RUNNING_LOCKED;
import static com.android.server.am.UserState.STATE_RUNNING_UNLOCKED;
import static com.android.server.am.UserState.STATE_RUNNING_UNLOCKING;
import static com.android.server.pm.UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE;
import static com.android.server.pm.UserManagerInternal.USER_START_MODE_BACKGROUND_VISIBLE;
import static com.android.server.pm.UserManagerInternal.USER_START_MODE_FOREGROUND;
import static com.android.server.pm.UserManagerInternal.userAssignmentResultToString;
import static com.android.server.pm.UserManagerInternal.userStartModeToString;

import android.annotation.IntDef;
import android.annotation.NonNull;
@@ -119,6 +124,7 @@ import com.android.server.SystemServiceManager;
import com.android.server.am.UserState.KeyEvictedCallback;
import com.android.server.pm.UserManagerInternal;
import com.android.server.pm.UserManagerInternal.UserLifecycleListener;
import com.android.server.pm.UserManagerInternal.UserStartMode;
import com.android.server.pm.UserManagerService;
import com.android.server.utils.Slogf;
import com.android.server.utils.TimingsTraceAndSlog;
@@ -903,14 +909,14 @@ class UserController implements Handler.Callback {
        });
    }

    int restartUser(final int userId, final boolean foreground) {
    int restartUser(final int userId, @UserStartMode int userStartMode) {
        return stopUser(userId, /* force= */ true, /* allowDelayedLocking= */ false,
                /* stopUserCallback= */ null, new KeyEvictedCallback() {
                    @Override
                    public void keyEvicted(@UserIdInt int userId) {
                        // Post to the same handler that this callback is called from to ensure
                        // the user cleanup is complete before restarting.
                        mHandler.post(() -> UserController.this.startUser(userId, foreground));
                        mHandler.post(() -> UserController.this.startUser(userId, userStartMode));
                    }
                });
    }
@@ -1267,7 +1273,7 @@ class UserController implements Handler.Callback {
                if (userStart.userId == userId) {
                    Slogf.i(TAG, "resumePendingUserStart for" + userStart);
                    mHandler.post(() -> startUser(userStart.userId,
                            userStart.isForeground, userStart.unlockListener));
                            userStart.userStartMode, userStart.unlockListener));

                    handledUserStarts.add(userStart);
                }
@@ -1450,7 +1456,7 @@ class UserController implements Handler.Callback {
        for (; i < profilesToStartSize && i < (getMaxRunningUsers() - 1); ++i) {
            // NOTE: this method is setting the profiles of the current user - which is always
            // assigned to the default display
            startUser(profilesToStart.get(i).id, /* foreground= */ false);
            startUser(profilesToStart.get(i).id, USER_START_MODE_BACKGROUND_VISIBLE);
        }
        if (i < profilesToStartSize) {
            Slogf.w(TAG, "More profiles than MAX_RUNNING_USERS");
@@ -1492,18 +1498,20 @@ class UserController implements Handler.Callback {
            return false;
        }

        return startUserNoChecks(userId, Display.DEFAULT_DISPLAY, /* foreground= */ false,
                /* unlockListener= */ null);
        return startUserNoChecks(userId, Display.DEFAULT_DISPLAY,
                USER_START_MODE_BACKGROUND_VISIBLE, /* unlockListener= */ null);
    }

    @VisibleForTesting
    boolean startUser(final @UserIdInt int userId, final boolean foreground) {
        return startUser(userId, foreground, null);
    boolean startUser(@UserIdInt int userId, @UserStartMode int userStartMode) {
        return startUser(userId, userStartMode, /* unlockListener= */ null);
    }

    /**
     * Start user, if its not already running.
     * <p>The user will be brought to the foreground, if {@code foreground} parameter is set.
     *
     * <p>The user will be brought to the foreground, if {@code userStartMode} parameter is
     * set to {@link UserManagerInternal#USER_START_MODE_FOREGROUND}
     * When starting the user, multiple intents will be broadcast in the following order:</p>
     * <ul>
     *     <li>{@link Intent#ACTION_USER_STARTED} - sent to registered receivers of the new user
@@ -1529,17 +1537,15 @@ class UserController implements Handler.Callback {
     * </ul>
     *
     * @param userId ID of the user to start
     * @param foreground true if user should be brought to the foreground
     * @param userStartMode user starting mode
     * @param unlockListener Listener to be informed when the user has started and unlocked.
     * @return true if the user has been successfully started
     */
    boolean startUser(
            final @UserIdInt int userId,
            final boolean foreground,
    boolean startUser(@UserIdInt int userId, @UserStartMode int userStartMode,
            @Nullable IProgressListener unlockListener) {
        checkCallingPermission(INTERACT_ACROSS_USERS_FULL, "startUser");

        return startUserNoChecks(userId, Display.DEFAULT_DISPLAY, foreground, unlockListener);
        return startUserNoChecks(userId, Display.DEFAULT_DISPLAY, userStartMode, unlockListener);
    }

    /**
@@ -1572,7 +1578,7 @@ class UserController implements Handler.Callback {
                "Cannot use DEFAULT_DISPLAY");

        try {
            return startUserNoChecks(userId, displayId, /* foreground= */ false,
            return startUserNoChecks(userId, displayId, USER_START_MODE_BACKGROUND_VISIBLE,
                    /* unlockListener= */ null);
        } catch (RuntimeException e) {
            Slogf.e(TAG, "startUserOnSecondaryDisplay(%d, %d) failed: %s", userId, displayId, e);
@@ -1580,26 +1586,29 @@ class UserController implements Handler.Callback {
        }
    }

    private boolean startUserNoChecks(@UserIdInt int userId, int displayId, boolean foreground,
            @Nullable IProgressListener unlockListener) {
    private boolean startUserNoChecks(@UserIdInt int userId, int displayId,
            @UserStartMode int userStartMode, @Nullable IProgressListener unlockListener) {
        TimingsTraceAndSlog t = new TimingsTraceAndSlog();

        t.traceBegin("UserController.startUser-" + userId
                + (displayId == Display.DEFAULT_DISPLAY ? "" : "-display-" + displayId)
                + "-" + (foreground ? "fg" : "bg"));
                + "-" + (userStartMode == USER_START_MODE_FOREGROUND ? "fg" : "bg")
                + "-start-mode-" + userStartMode);
        try {
            return startUserInternal(userId, displayId, foreground, unlockListener, t);
            return startUserInternal(userId, displayId, userStartMode, unlockListener, t);
        } finally {
            t.traceEnd();
        }
    }

    private boolean startUserInternal(@UserIdInt int userId, int displayId, boolean foreground,
            @Nullable IProgressListener unlockListener, @NonNull TimingsTraceAndSlog t) {
    private boolean startUserInternal(@UserIdInt int userId, int displayId,
            @UserStartMode int userStartMode, @Nullable IProgressListener unlockListener,
            TimingsTraceAndSlog t) {
        if (DEBUG_MU) {
            Slogf.i(TAG, "Starting user %d on display %d%s", userId, displayId,
                    foreground ? " in foreground" : "");
            Slogf.i(TAG, "Starting user %d on display %d with mode  %s", userId, displayId,
                    userStartModeToString(userStartMode));
        }
        boolean foreground = userStartMode == USER_START_MODE_FOREGROUND;

        boolean onSecondaryDisplay = displayId != Display.DEFAULT_DISPLAY;
        if (onSecondaryDisplay) {
@@ -1664,13 +1673,13 @@ class UserController implements Handler.Callback {

            t.traceBegin("assignUserToDisplayOnStart");
            int result = mInjector.getUserManagerInternal().assignUserToDisplayOnStart(userId,
                    userInfo.profileGroupId, foreground, displayId);
                    userInfo.profileGroupId, userStartMode, displayId);
            t.traceEnd();

            if (result == UserManagerInternal.USER_ASSIGNMENT_RESULT_FAILURE) {
            if (result == USER_ASSIGNMENT_RESULT_FAILURE) {
                Slogf.e(TAG, "%s user(%d) / display (%d) assignment failed: %s",
                        (foreground ? "fg" : "bg"), userId, displayId,
                        UserManagerInternal.userAssignmentResultToString(result));
                        userStartModeToString(userStartMode), userId, displayId,
                        userAssignmentResultToString(result));
                return false;
            }

@@ -1700,8 +1709,8 @@ class UserController implements Handler.Callback {
                } else if (uss.state == UserState.STATE_SHUTDOWN) {
                    Slogf.i(TAG, "User #" + userId
                            + " is shutting down - will start after full shutdown");
                    mPendingUserStarts.add(new PendingUserStart(userId,
                            foreground, unlockListener));
                    mPendingUserStarts.add(new PendingUserStart(userId, userStartMode,
                            unlockListener));
                    t.traceEnd(); // updateStartedUserArrayStarting
                    return true;
                }
@@ -1862,8 +1871,8 @@ class UserController implements Handler.Callback {
    /**
     * Start user, if its not already running, and bring it to foreground.
     */
    void startUserInForeground(final int targetUserId) {
        boolean success = startUser(targetUserId, /* foreground */ true);
    void startUserInForeground(@UserIdInt int targetUserId) {
        boolean success = startUser(targetUserId, USER_START_MODE_FOREGROUND);
        if (!success) {
            mInjector.getWindowManager().setSwitchingUser(false);
        }
@@ -3433,13 +3442,13 @@ class UserController implements Handler.Callback {
     */
    private static class PendingUserStart {
        public final @UserIdInt int userId;
        public final boolean isForeground;
        public final @UserStartMode int userStartMode;
        public final IProgressListener unlockListener;

        PendingUserStart(int userId, boolean foreground,
        PendingUserStart(int userId, @UserStartMode int userStartMode,
                IProgressListener unlockListener) {
            this.userId = userId;
            this.isForeground = foreground;
            this.userStartMode = userStartMode;
            this.unlockListener = unlockListener;
        }

@@ -3447,7 +3456,7 @@ class UserController implements Handler.Callback {
        public String toString() {
            return "PendingUserStart{"
                    + "userId=" + userId
                    + ", isForeground=" + isForeground
                    + ", userStartMode=" + userStartModeToString(userStartMode)
                    + ", unlockListener=" + unlockListener
                    + '}';
        }
+20 −2
Original line number Diff line number Diff line
@@ -59,6 +59,18 @@ public abstract class UserManagerInternal {
    })
    public @interface UserAssignmentResult {}

    public static final int USER_START_MODE_FOREGROUND = 1;
    public static final int USER_START_MODE_BACKGROUND = 2;
    public static final int USER_START_MODE_BACKGROUND_VISIBLE = 3;

    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,
            USER_START_MODE_BACKGROUND_VISIBLE
    })
    public @interface UserStartMode {}

    public interface UserRestrictionsListener {
        /**
         * Called when a user restriction changes.
@@ -367,8 +379,7 @@ public abstract class UserManagerInternal {
     * pass a valid display id.
     */
    public abstract @UserAssignmentResult int assignUserToDisplayOnStart(@UserIdInt int userId,
            @UserIdInt int profileGroupId,
            boolean foreground, int displayId);
            @UserIdInt int profileGroupId, @UserStartMode int userStartMode, int displayId);

    /**
     * Unassigns a user from its current display when it's stopping.
@@ -429,6 +440,13 @@ public abstract class UserManagerInternal {
                result);
    }

    /**
     * Gets the user-friendly representation of a user start {@code mode}.
     */
    public static String userStartModeToString(@UserStartMode int mode) {
        return DebugUtils.constantToString(UserManagerInternal.class, PREFIX_USER_START_MODE, mode);
    }

    /** Adds a {@link UserVisibilityListener}. */
    public abstract void addUserVisibilityListener(UserVisibilityListener listener);

+8 −2
Original line number Diff line number Diff line
@@ -127,8 +127,11 @@ import com.android.server.LocalServices;
import com.android.server.LockGuard;
import com.android.server.SystemService;
import com.android.server.am.UserState;
import com.android.server.pm.UserManagerInternal.UserAssignmentResult;
import com.android.server.pm.UserManagerInternal.UserLifecycleListener;
import com.android.server.pm.UserManagerInternal.UserRestrictionsListener;
import com.android.server.pm.UserManagerInternal.UserStartMode;
import com.android.server.pm.UserManagerInternal.UserVisibilityListener;
import com.android.server.storage.DeviceStorageMonitorInternal;
import com.android.server.utils.Slogf;
import com.android.server.utils.TimingsTraceAndSlog;
@@ -6976,8 +6979,11 @@ public class UserManagerService extends IUserManager.Stub {
        }

        @Override
        public int assignUserToDisplayOnStart(@UserIdInt int userId, @UserIdInt int profileGroupId,
                boolean foreground, int displayId) {
        @UserAssignmentResult
        public int assignUserToDisplayOnStart(@UserIdInt int userId,
                @UserIdInt int profileGroupId, @UserStartMode int userStartMode, int displayId) {
            // TODO(245939659): change UserVisibilityMediator to take @UserStartMode
            boolean foreground = userStartMode == UserManagerInternal.USER_START_MODE_FOREGROUND;
            return mUserVisibilityMediator.assignUserToDisplayOnStart(userId, profileGroupId,
                    foreground, displayId);
        }
+1 −1
Original line number Diff line number Diff line
@@ -139,7 +139,7 @@ public final class UserVisibilityMediator implements Dumpable {
    }

    /**
     * See {@link UserManagerInternal#assignUserToDisplayOnStart(int, int, boolean, int)}.
     * See {@link UserManagerInternal#assignUserToDisplayOnStart(int, int, int, int)}.
     */
    public @UserAssignmentResult int assignUserToDisplayOnStart(@UserIdInt int userId,
            @UserIdInt int unResolvedProfileGroupId, boolean foreground, int displayId) {
Loading