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

    private int mCurrentUser;
    int mCurrentUser;

    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.
     */
    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;
    }

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

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

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

import com.android.internal.app.HeavyWeightSwitcherActivity;
import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
@@ -160,6 +161,9 @@ public class ActivityStackSupervisor {
     * is being brought in front of us. */
    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,
            Looper looper) {
        mService = service;
@@ -213,6 +217,9 @@ public class ActivityStackSupervisor {
    }

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

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

    ActivityStack getCorrectStack(ActivityRecord r) {
        if (!r.isHomeActivity) {
            if (mStacks.size() == 1) {
                // Time to create the first app stack.
            int stackNdx;
            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,
                        StackBox.TASK_STACK_GOES_OVER, 1.0f);
                mFocusedStack = getStack(stackId);
@@ -1776,7 +1795,7 @@ public class ActivityStackSupervisor {
        return didSomething;
    }

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

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

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

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

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

        resumeTopActivitiesLocked();

        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 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.wm.WindowManagerService.DEBUG_STACK;
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
import static com.android.server.wm.WindowManagerService.TAG;

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

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

    /**
     * @param display May not be null.
     */
@@ -145,6 +149,22 @@ class DisplayContent {
     */
    ArrayList<Task> getTasks() {
        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();
        for (int stackNdx = 0; stackNdx < numStacks; ++stackNdx) {
            mTmpTasks.addAll(mStackHistory.get(stackNdx).getTasks());
@@ -292,6 +312,14 @@ class DisplayContent {
                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;
    }

@@ -300,6 +328,26 @@ class DisplayContent {
        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) {
        pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
        final String subPrefix = "  " + prefix;
@@ -365,6 +413,49 @@ class DisplayContent {
                  token.dump(pw, "    ");
            }
        }
        if (mUserStacks.size() > 0) {
            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 Diff line number Diff line
@@ -5094,22 +5094,16 @@ public class WindowManagerService extends IWindowManager.Stub

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

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