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

Commit a2e56c5a authored by Craig Mautner's avatar Craig Mautner Committed by Android (Google) Code Review
Browse files

Merge "Fix user switching."

parents c56b831a 858d8a65
Loading
Loading
Loading
Loading
+14 −9
Original line number Original line Diff line number Diff line
@@ -4133,7 +4133,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                }
                }
            }
            }
            if (mBooted) {
            if (mBooted) {
                mStackSupervisor.resumeTopActivityLocked();
                mStackSupervisor.resumeTopActivitiesLocked();
                mStackSupervisor.scheduleIdleLocked();
                mStackSupervisor.scheduleIdleLocked();
            }
            }
        }
        }
@@ -4984,6 +4984,7 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
        }
    }
    }
    @Override
    public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
    public void setProcessForeground(IBinder token, int pid, boolean isForeground) {
        enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
        enforceCallingPermission(android.Manifest.permission.SET_PROCESS_LIMIT,
                "setProcessForeground()");
                "setProcessForeground()");
@@ -5007,6 +5008,7 @@ public final class ActivityManagerService extends ActivityManagerNative
                }
                }
                if (isForeground && token != null) {
                if (isForeground && token != null) {
                    ForegroundToken newToken = new ForegroundToken() {
                    ForegroundToken newToken = new ForegroundToken() {
                        @Override
                        public void binderDied() {
                        public void binderDied() {
                            foregroundTokenDied(this);
                            foregroundTokenDied(this);
                        }
                        }
@@ -5041,6 +5043,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            mActivityManagerService = activityManagerService;
            mActivityManagerService = activityManagerService;
        }
        }
        @Override
        public boolean checkPermission(String permission, int pid, int uid) {
        public boolean checkPermission(String permission, int pid, int uid) {
            return mActivityManagerService.checkPermission(permission, pid,
            return mActivityManagerService.checkPermission(permission, pid,
                    uid) == PackageManager.PERMISSION_GRANTED;
                    uid) == PackageManager.PERMISSION_GRANTED;
@@ -5048,12 +5051,14 @@ public final class ActivityManagerService extends ActivityManagerNative
    }
    }
    class IntentFirewallInterface implements IntentFirewall.AMSInterface {
    class IntentFirewallInterface implements IntentFirewall.AMSInterface {
        @Override
        public int checkComponentPermission(String permission, int pid, int uid,
        public int checkComponentPermission(String permission, int pid, int uid,
                int owningUid, boolean exported) {
                int owningUid, boolean exported) {
            return ActivityManagerService.this.checkComponentPermission(permission, pid, uid,
            return ActivityManagerService.this.checkComponentPermission(permission, pid, uid,
                    owningUid, exported);
                    owningUid, exported);
        }
        }
        @Override
        public Object getAMSLock() {
        public Object getAMSLock() {
            return ActivityManagerService.this;
            return ActivityManagerService.this;
        }
        }
@@ -8281,7 +8286,7 @@ public final class ActivityManagerService extends ActivityManagerNative
            } finally {
            } finally {
                Binder.restoreCallingIdentity(ident);
                Binder.restoreCallingIdentity(ident);
            }
            }
            mStackSupervisor.resumeTopActivityLocked();
            mStackSupervisor.resumeTopActivitiesLocked();
            sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);
            sendUserSwitchBroadcastsLocked(-1, mCurrentUserId);
        }
        }
    }
    }
@@ -8396,10 +8401,10 @@ public final class ActivityManagerService extends ActivityManagerNative
                // annoy the user repeatedly.  Unless it is persistent, since those
                // annoy the user repeatedly.  Unless it is persistent, since those
                // processes run critical code.
                // processes run critical code.
                removeProcessLocked(app, false, false, "crash");
                removeProcessLocked(app, false, false, "crash");
                mStackSupervisor.resumeTopActivityLocked();
                mStackSupervisor.resumeTopActivitiesLocked();
                return false;
                return false;
            }
            }
            mStackSupervisor.resumeTopActivityLocked();
            mStackSupervisor.resumeTopActivitiesLocked();
        } else {
        } else {
            mStackSupervisor.finishTopRunningActivityLocked(app);
            mStackSupervisor.finishTopRunningActivityLocked(app);
        }
        }
+4 −6
Original line number Original line Diff line number Diff line
@@ -234,7 +234,7 @@ final class ActivityStack {
    int mThumbnailWidth = -1;
    int mThumbnailWidth = -1;
    int mThumbnailHeight = -1;
    int mThumbnailHeight = -1;


    private int mCurrentUser;
    int mCurrentUser;


    final int mStackId;
    final int mStackId;


@@ -576,7 +576,8 @@ final class ActivityStack {
    }
    }


    /*
    /*
     * Move the activities around in the stack to bring a user to the foreground.
     * Move the activities around in the stack to bring a user to the foreground. This only
     * matters on the home stack. All other stacks are single user.
     * @return whether there are any activities for the specified user.
     * @return whether there are any activities for the specified user.
     */
     */
    final boolean switchUserLocked(int userId, UserStartedState uss) {
    final boolean switchUserLocked(int userId, UserStartedState uss) {
@@ -602,9 +603,6 @@ final class ActivityStack {
            }
            }
        }
        }


        // task is now the original topmost TaskRecord. Transition from the old top to the new top.
        ActivityRecord top = task != null ? task.getTopActivity() : null;
        resumeTopActivityLocked(top);
        return haveActivities;
        return haveActivities;
    }
    }


@@ -1718,7 +1716,7 @@ final class ActivityStack {
        }
        }


        if (doResume) {
        if (doResume) {
            mStackSupervisor.resumeTopActivityLocked();
            mStackSupervisor.resumeTopActivitiesLocked();
        }
        }
    }
    }


+62 −22
Original line number Original line Diff line number Diff line
@@ -61,6 +61,7 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserHandle;
import android.util.EventLog;
import android.util.EventLog;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArray;


import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
@@ -160,6 +161,9 @@ public class ActivityStackSupervisor {
     * is being brought in front of us. */
     * is being brought in front of us. */
    boolean mUserLeaving = false;
    boolean mUserLeaving = false;


    /** Stacks belonging to users other than mCurrentUser. Indexed by userId. */
    final SparseArray<UserState> mUserStates = new SparseArray<UserState>();

    public ActivityStackSupervisor(ActivityManagerService service, Context context,
    public ActivityStackSupervisor(ActivityManagerService service, Context context,
            Looper looper) {
            Looper looper) {
        mService = service;
        mService = service;
@@ -213,6 +217,9 @@ public class ActivityStackSupervisor {
    }
    }


    boolean isFrontStack(ActivityStack stack) {
    boolean isFrontStack(ActivityStack stack) {
        if (stack.mCurrentUser != mCurrentUser) {
            return false;
        }
        return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
        return !(stack.isHomeStack() ^ getFocusedStack().isHomeStack());
    }
    }


@@ -319,6 +326,9 @@ public class ActivityStackSupervisor {
        final String processName = app.processName;
        final String processName = app.processName;
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = mStacks.get(stackNdx);
            final ActivityStack stack = mStacks.get(stackNdx);
            if (!isFrontStack(stack)) {
                continue;
            }
            ActivityRecord hr = stack.topRunningActivityLocked(null);
            ActivityRecord hr = stack.topRunningActivityLocked(null);
            if (hr != null) {
            if (hr != null) {
                if (hr.app == null && app.uid == hr.info.applicationInfo.uid
                if (hr.app == null && app.uid == hr.info.applicationInfo.uid
@@ -449,6 +459,9 @@ public class ActivityStackSupervisor {
        }
        }
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = mStacks.get(stackNdx);
            final ActivityStack stack = mStacks.get(stackNdx);
            if (stack.mCurrentUser != mCurrentUser) {
                continue;
            }
            if (stack != mFocusedStack && isFrontStack(stack)) {
            if (stack != mFocusedStack && isFrontStack(stack)) {
                r = stack.topRunningActivityLocked(null);
                r = stack.topRunningActivityLocked(null);
                if (r != null) {
                if (r != null) {
@@ -1145,8 +1158,14 @@ public class ActivityStackSupervisor {


    ActivityStack getCorrectStack(ActivityRecord r) {
    ActivityStack getCorrectStack(ActivityRecord r) {
        if (!r.isHomeActivity) {
        if (!r.isHomeActivity) {
            if (mStacks.size() == 1) {
            int stackNdx;
                // Time to create the first app stack.
            for (stackNdx = mStacks.size() - 1; stackNdx > 0; --stackNdx) {
                if (mStacks.get(stackNdx).mCurrentUser == mCurrentUser) {
                    break;
                }
            }
            if (stackNdx == 0) {
                // Time to create the first app stack for this user.
                int stackId = mService.createStack(-1, HOME_STACK_ID,
                int stackId = mService.createStack(-1, HOME_STACK_ID,
                        StackBox.TASK_STACK_GOES_OVER, 1.0f);
                        StackBox.TASK_STACK_GOES_OVER, 1.0f);
                mFocusedStack = getStack(stackId);
                mFocusedStack = getStack(stackId);
@@ -1776,7 +1795,7 @@ public class ActivityStackSupervisor {
        return didSomething;
        return didSomething;
    }
    }


    void resumeTopActivityLocked() {
    void resumeTopActivitiesLocked() {
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
        for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
            final ActivityStack stack = mStacks.get(stackNdx);
            final ActivityStack stack = mStacks.get(stackNdx);
            if (isFrontStack(stack)) {
            if (isFrontStack(stack)) {
@@ -1816,7 +1835,6 @@ public class ActivityStackSupervisor {
    }
    }


    int createStack() {
    int createStack() {
        synchronized (this) {
        while (true) {
        while (true) {
            if (++mLastStackId <= HOME_STACK_ID) {
            if (++mLastStackId <= HOME_STACK_ID) {
                mLastStackId = HOME_STACK_ID + 1;
                mLastStackId = HOME_STACK_ID + 1;
@@ -1828,7 +1846,6 @@ public class ActivityStackSupervisor {
        mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
        mStacks.add(new ActivityStack(mService, mContext, mLooper, mLastStackId));
        return mLastStackId;
        return mLastStackId;
    }
    }
    }


    void moveTaskToStack(int taskId, int stackId, boolean toTop) {
    void moveTaskToStack(int taskId, int stackId, boolean toTop) {
        final ActivityStack stack = getStack(stackId);
        final ActivityStack stack = getStack(stackId);
@@ -1938,16 +1955,22 @@ public class ActivityStackSupervisor {
    }
    }


    boolean switchUserLocked(int userId, UserStartedState uss) {
    boolean switchUserLocked(int userId, UserStartedState uss) {
        mUserStates.put(mCurrentUser, new UserState());
        mCurrentUser = userId;
        mCurrentUser = userId;
        mStartingUsers.add(uss);
        UserState userState = mUserStates.get(userId);
        boolean haveActivities = false;
        if (userState != null) {
        final int numStacks = mStacks.size();
            userState.restore();
        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
            mUserStates.delete(userId);
            final ActivityStack stack = mStacks.get(stackNdx);
        } else {
            if (isFrontStack(stack)) {
            mFocusedStack = null;
                haveActivities |= stack.switchUserLocked(userId, uss);
            mStackState = STACK_STATE_HOME_IN_FRONT;
            }
        }
        }

        mStartingUsers.add(uss);
        boolean haveActivities = mHomeStack.switchUserLocked(userId, uss);

        resumeTopActivitiesLocked();

        return haveActivities;
        return haveActivities;
    }
    }


@@ -2203,4 +2226,21 @@ public class ActivityStackSupervisor {
            }
            }
        }
        }
    }
    }

    private final class UserState {
        final ActivityStack mSavedFocusedStack;
        final int mSavedStackState;

        public UserState() {
            ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
            mSavedFocusedStack = supervisor.mFocusedStack;
            mSavedStackState = supervisor.mStackState;
        }

        void restore() {
            ActivityStackSupervisor supervisor = ActivityStackSupervisor.this;
            supervisor.mFocusedStack = mSavedFocusedStack;
            supervisor.mStackState = mSavedStackState;
        }
    }
}
}
+91 −0
Original line number Original line Diff line number Diff line
@@ -18,10 +18,12 @@ package com.android.server.wm;


import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
import static com.android.server.wm.WindowManagerService.DEBUG_STACK;
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerService.TAG;
import static com.android.server.wm.WindowManagerService.TAG;


import android.graphics.Rect;
import android.graphics.Rect;
import android.util.Slog;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.DisplayInfo;
import android.view.InputChannel;
import android.view.InputChannel;
@@ -104,6 +106,8 @@ class DisplayContent {
    /** Detect user tapping outside of current focused stack bounds .*/
    /** Detect user tapping outside of current focused stack bounds .*/
    StackTapDetector mTapDetector;
    StackTapDetector mTapDetector;


    SparseArray<UserStacks> mUserStacks = new SparseArray<UserStacks>();

    /**
    /**
     * @param display May not be null.
     * @param display May not be null.
     */
     */
@@ -145,6 +149,22 @@ class DisplayContent {
     */
     */
    ArrayList<Task> getTasks() {
    ArrayList<Task> getTasks() {
        mTmpTasks.clear();
        mTmpTasks.clear();
        // First do the tasks belonging to other users.
        final int numUserStacks = mUserStacks.size();
        for (int i = 0; i < numUserStacks; ++i) {
            UserStacks userStacks = mUserStacks.valueAt(i);
            ArrayList<TaskStack> stacks = userStacks.mSavedStackHistory;
            final int numStacks = stacks.size();
            for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
                TaskStack stack = stacks.get(stackNdx);
                if (stack != mHomeStack) {
                    if (WindowManagerService.DEBUG_LAYERS) Slog.i(TAG, "getTasks: mStackHistory=" +
                            mStackHistory);
                    mTmpTasks.addAll(stack.getTasks());
                }
            }
        }
        // Now do the current user's tasks.
        final int numStacks = mStackHistory.size();
        final int numStacks = mStackHistory.size();
        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
            mTmpTasks.addAll(mStackHistory.get(stackNdx).getTasks());
            mTmpTasks.addAll(mStackHistory.get(stackNdx).getTasks());
@@ -292,6 +312,14 @@ class DisplayContent {
                return bounds;
                return bounds;
            }
            }
        }
        }
        // Not in the visible stacks, try the saved ones.
        for (int userNdx = mUserStacks.size() - 1; userNdx >= 0; --userNdx) {
            UserStacks userStacks = mUserStacks.valueAt(userNdx);
            Rect bounds = userStacks.mSavedStackBox.getStackBounds(stackId);
            if (bounds != null) {
                return bounds;
            }
        }
        return null;
        return null;
    }
    }


@@ -300,6 +328,26 @@ class DisplayContent {
        return topBox.stackIdFromPoint(x, y);
        return topBox.stackIdFromPoint(x, y);
    }
    }


    void switchUserStacks(int oldUserId, int newUserId) {
        final WindowList windows = getWindowList();
        for (int i = 0; i < windows.size(); i++) {
            final WindowState win = windows.get(i);
            if (win.isHiddenFromUserLocked()) {
                if (DEBUG_VISIBILITY) Slog.w(TAG, "user changing " + newUserId + " hiding "
                        + win + ", attrs=" + win.mAttrs.type + ", belonging to "
                        + win.mOwnerUid);
                win.hideLw(false);
            }
        }
        // Clear the old user's non-home StackBox
        mUserStacks.put(oldUserId, new UserStacks());
        UserStacks userStacks = mUserStacks.get(newUserId);
        if (userStacks != null) {
            userStacks.restore();
            mUserStacks.delete(newUserId);
        }
    }

    public void dump(String prefix, PrintWriter pw) {
    public void dump(String prefix, PrintWriter pw) {
        pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
        pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
        final String subPrefix = "  " + prefix;
        final String subPrefix = "  " + prefix;
@@ -365,6 +413,49 @@ class DisplayContent {
                  token.dump(pw, "    ");
                  token.dump(pw, "    ");
            }
            }
        }
        }
        if (mUserStacks.size() > 0) {
            pw.println();
            pw.println();
            pw.println("  Saved user stacks:");
            for (int i = 0; i < mUserStacks.size(); ++i) {
                UserStacks userStacks = mUserStacks.valueAt(i);
                pw.print("  UserId="); pw.println(Integer.toHexString(mUserStacks.keyAt(i)));
                pw.print("  StackHistory="); pw.println(userStacks.mSavedStackHistory);
                pw.print("  StackBox="); userStacks.mSavedStackBox.dump("    ", pw);
            }
        }
        pw.println();
    }

    private final class UserStacks {
        final ArrayList<TaskStack> mSavedStackHistory;
        StackBox mSavedStackBox;
        int mBoxNdx;

        public UserStacks() {
            mSavedStackHistory = new ArrayList<TaskStack>(mStackHistory);
            for (int stackNdx = mStackHistory.size() - 1; stackNdx >=0; --stackNdx) {
                if (mStackHistory.get(stackNdx) != mHomeStack) {
                    mStackHistory.remove(stackNdx);
                }
            }
            mSavedStackBox = null;
            mBoxNdx = -1;
            for (int boxNdx = mStackBoxes.size() - 1; boxNdx >= 0; --boxNdx) {
                StackBox box = mStackBoxes.get(boxNdx);
                if (box.mStack != mHomeStack) {
                    mSavedStackBox = box;
                    mBoxNdx = boxNdx;
                    mStackBoxes.remove(boxNdx);
                    break;
                }
            }
        }

        void restore() {
            mStackHistory = mSavedStackHistory;
            if (mBoxNdx >= 0) {
                mStackBoxes.add(mBoxNdx, mSavedStackBox);
            }
        }
    }
    }
}
}
+4 −10
Original line number Original line Diff line number Diff line
@@ -5094,22 +5094,16 @@ public class WindowManagerService extends IWindowManager.Stub


    public void setCurrentUser(final int newUserId) {
    public void setCurrentUser(final int newUserId) {
        synchronized (mWindowMap) {
        synchronized (mWindowMap) {
            int oldUserId = mCurrentUserId;
            mCurrentUserId = newUserId;
            mCurrentUserId = newUserId;
            mPolicy.setCurrentUserLw(newUserId);
            mPolicy.setCurrentUserLw(newUserId);


            // Hide windows that should not be seen by the new user.
            // Hide windows that should not be seen by the new user.
            DisplayContentsIterator iterator = new DisplayContentsIterator();
            DisplayContentsIterator iterator = new DisplayContentsIterator();
            while (iterator.hasNext()) {
            while (iterator.hasNext()) {
                final WindowList windows = iterator.next().getWindowList();
                DisplayContent displayContent = iterator.next();
                for (int i = 0; i < windows.size(); i++) {
                displayContent.switchUserStacks(oldUserId, newUserId);
                    final WindowState win = windows.get(i);
                rebuildAppWindowListLocked(displayContent);
                    if (win.isHiddenFromUserLocked()) {
                        Slog.w(TAG, "current user violation " + newUserId + " hiding "
                                + win + ", attrs=" + win.mAttrs.type + ", belonging to "
                                + win.mOwnerUid);
                        win.hideLw(false);
                    }
                }
            }
            }
            performLayoutAndPlaceSurfacesLocked();
            performLayoutAndPlaceSurfacesLocked();
        }
        }