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

Commit fc46bc2d authored by Filip Gruszczynski's avatar Filip Gruszczynski Committed by The Android Automerger
Browse files

Don't perform layout while adjusting displays/stacks state.

When we detach the stack from the display we are in an inconsistent
state. We need to finish that operation, before we start laying out
things again. Otherwise we will encounter subtle bugs, where stack is
partially closed, but still used during the layout.

Display detachment was already doing the right thing and scheduling a
layout after it finishes the display detach. However, removing the
stack's windows was triggering immediate relayout and causing a crash.

This CL also adds some missing synchronization around
WindowManagerService.mStackIdToStack, which is in most cases protected by
mWindowMap.

Bug: 22191609
Bug: 23615329
Change-Id: I1e2fc42e1a5b673be808acdec473f85f138d7062
parent 77ed3fc4
Loading
Loading
Loading
Loading
+4 −1
Original line number Diff line number Diff line
@@ -375,7 +375,10 @@ public class TaskStack {
            for (int appNdx = appWindowTokens.size() - 1; appNdx >= 0; --appNdx) {
                final WindowList appWindows = appWindowTokens.get(appNdx).allAppWindows;
                for (int winNdx = appWindows.size() - 1; winNdx >= 0; --winNdx) {
                    mService.removeWindowInnerLocked(appWindows.get(winNdx));
                    // We are in the middle of changing the state of displays/stacks/tasks. We need
                    // to finish that, before we let layout interfere with it.
                    mService.removeWindowInnerLocked(appWindows.get(winNdx),
                            false /* performLayout */);
                    doAnotherLayoutPass = true;
                }
            }
+16 −6
Original line number Diff line number Diff line
@@ -2793,6 +2793,10 @@ public class WindowManagerService extends IWindowManager.Stub
    }

    void removeWindowInnerLocked(WindowState win) {
        removeWindowInnerLocked(win, true);
    }

    void removeWindowInnerLocked(WindowState win, boolean performLayout) {
        if (win.mRemoved) {
            // Nothing to do.
            return;
@@ -2890,7 +2894,9 @@ public class WindowManagerService extends IWindowManager.Stub
                if (displayContent != null) {
                    displayContent.layoutNeeded = true;
                }
                if (performLayout) {
                    performLayoutAndPlaceSurfacesLocked();
                }
                if (win.mAppToken != null) {
                    win.mAppToken.updateReportedVisibilityLocked();
                }
@@ -5193,8 +5199,10 @@ public class WindowManagerService extends IWindowManager.Stub
    }

    public void removeStack(int stackId) {
        synchronized (mWindowMap) {
            mStackIdToStack.remove(stackId);
        }
    }

    public void removeTask(int taskId) {
        synchronized (mWindowMap) {
@@ -5267,11 +5275,13 @@ public class WindowManagerService extends IWindowManager.Stub
    }

    public void getStackBounds(int stackId, Rect bounds) {
        synchronized (mWindowMap) {
            final TaskStack stack = mStackIdToStack.get(stackId);
            if (stack != null) {
                stack.getBounds(bounds);
                return;
            }
        }
        bounds.setEmpty();
    }