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

Commit 8a88ca81 authored by Riddle Hsu's avatar Riddle Hsu
Browse files

Fix index out of bounds when removing deferred containers

This makes the commit 793442c5 general to handle the removal from
all level since the hierarchy won't always keep the same shape.

Also rename to handleCompleteDeferredRemoval since it is not a
pure function for checking.

Fixes: 159865315
Test: atest WindowContainerTests#testHandleCompleteDeferredRemoval

Change-Id: I34e02652fb765c1cf78cbd3e86a07e592f02e7df
Merged-In: I34e02652fb765c1cf78cbd3e86a07e592f02e7df
parent 46986caa
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -3146,11 +3146,11 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A
    }

    @Override
    boolean checkCompleteDeferredRemoval() {
    boolean handleCompleteDeferredRemoval() {
        if (mIsExiting) {
            removeIfPossible();
        }
        return super.checkCompleteDeferredRemoval();
        return super.handleCompleteDeferredRemoval();
    }

    void onRemovedFromDisplay() {
+2 −15
Original line number Diff line number Diff line
@@ -86,7 +86,6 @@ import static com.android.server.wm.TaskProto.ACTIVITY_TYPE;
import static com.android.server.wm.TaskProto.ANIMATING_BOUNDS;
import static com.android.server.wm.TaskProto.BOUNDS;
import static com.android.server.wm.TaskProto.CREATED_BY_ORGANIZER;
import static com.android.server.wm.TaskProto.DEFER_REMOVAL;
import static com.android.server.wm.TaskProto.DISPLAY_ID;
import static com.android.server.wm.TaskProto.FILLS_PARENT;
import static com.android.server.wm.TaskProto.LAST_NON_FULLSCREEN_BOUNDS;
@@ -248,11 +247,6 @@ class ActivityStack extends Task {
    private Rect mTmpRect = new Rect();
    private Rect mTmpRect2 = new Rect();

    /** Detach this stack from its display when animation completes. */
    // TODO: maybe tie this to WindowContainer#removeChild some how...
    // TODO: This is no longer set. Okay to remove or was the set removed by accident?
    private boolean mDeferRemoval;

    // If this is true, we are in the bounds animating mode. The task will be down or upscaled to
    // perfectly fit the region it would have been cropped to. We may also avoid certain logic we
    // would otherwise apply while resizing, while resizing in the bounds animating mode.
@@ -3232,9 +3226,6 @@ class ActivityStack extends Task {

    @Override
    void dump(PrintWriter pw, String prefix, boolean dumpAll) {
        if (mDeferRemoval) {
            pw.println(prefix + "mDeferRemoval=true");
        }
        super.dump(pw, prefix, dumpAll);
        if (!mExitingActivities.isEmpty()) {
            pw.println();
@@ -3304,15 +3295,12 @@ class ActivityStack extends Task {
    }

    /** Returns true if a removal action is still being deferred. */
    boolean checkCompleteDeferredRemoval() {
    boolean handleCompleteDeferredRemoval() {
        if (isAnimating(TRANSITION | CHILDREN)) {
            return true;
        }
        if (mDeferRemoval) {
            removeImmediately();
        }

        return super.checkCompleteDeferredRemoval();
        return super.handleCompleteDeferredRemoval();
    }

    public DisplayInfo getDisplayInfo() {
@@ -3380,7 +3368,6 @@ class ActivityStack extends Task {
            mLastNonFullscreenBounds.dumpDebug(proto, LAST_NON_FULLSCREEN_BOUNDS);
        }

        proto.write(DEFER_REMOVAL, mDeferRemoval);
        proto.write(ANIMATING_BOUNDS, mBoundsAnimating);

        if (mSurfaceControl != null) {
+4 −20
Original line number Diff line number Diff line
@@ -2739,6 +2739,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
    @Override
    void removeImmediately() {
        mRemovingDisplay = true;
        mDeferredRemoval = false;
        try {
            if (mParentWindow != null) {
                mParentWindow.removeEmbeddedDisplayContent(this);
@@ -2771,31 +2772,14 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo

    /** Returns true if a removal action is still being deferred. */
    @Override
    boolean checkCompleteDeferredRemoval() {
        boolean stillDeferringRemoval = false;

        for (int i = getChildCount() - 1; i >= 0; --i) {
            final DisplayChildWindowContainer child = getChildAt(i);
            stillDeferringRemoval |= child.checkCompleteDeferredRemoval();
            if (getChildCount() == 0) {
                // If this display is pending to be removed because it contains an activity with
                // {@link ActivityRecord#mIsExiting} is true, this display may be removed when
                // completing the removal of the last activity from
                // {@link ActivityRecord#checkCompleteDeferredRemoval}.
                return false;
            }
        }
    boolean handleCompleteDeferredRemoval() {
        final boolean stillDeferringRemoval = super.handleCompleteDeferredRemoval();

        if (!stillDeferringRemoval && mDeferredRemoval) {
            removeImmediately();
            return false;
        }
        return true;
    }

    /** @return 'true' if removal of this display content is deferred due to active animation. */
    boolean isRemovalDeferred() {
        return mDeferredRemoval;
        return stillDeferringRemoval;
    }

    void adjustForImeIfNeeded() {
+1 −3
Original line number Diff line number Diff line
@@ -990,9 +990,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
        }

        // Remove all deferred displays stacks, tasks, and activities.
        for (int displayNdx = mChildren.size() - 1; displayNdx >= 0; --displayNdx) {
            mChildren.get(displayNdx).checkCompleteDeferredRemoval();
        }
        handleCompleteDeferredRemoval();

        forAllDisplays(dc -> {
            dc.getInputMonitor().updateInputWindowsLw(true /*force*/);
+15 −3
Original line number Diff line number Diff line
@@ -1044,13 +1044,25 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<
        return mChildren.peekLast();
    }

    /** Returns true if there is still a removal being deferred */
    boolean checkCompleteDeferredRemoval() {
    /**
     * Removes the containers which were deferred.
     *
     * @return {@code true} if there is still a removal being deferred.
     */
    boolean handleCompleteDeferredRemoval() {
        boolean stillDeferringRemoval = false;

        for (int i = mChildren.size() - 1; i >= 0; --i) {
            final WindowContainer wc = mChildren.get(i);
            stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
            stillDeferringRemoval |= wc.handleCompleteDeferredRemoval();
            if (!hasChild()) {
                // All child containers of current level could be removed from a removal of
                // descendant. E.g. if a display is pending to be removed because it contains an
                // activity with {@link ActivityRecord#mIsExiting} is true, the display may be
                // removed when completing the removal of the last activity from
                // {@link ActivityRecord#checkCompleteDeferredRemoval}.
                return false;
            }
        }

        return stillDeferringRemoval;
Loading