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

Commit 6567742d authored by Louis Chang's avatar Louis Chang
Browse files

Move task to the bottom when force hidden

Move a task to the bottom when the task was hidden to prevent
the top focused activity unable to enter pip (while pausing)
due to a invisible task remained on top.

Move the task to top once being visible again

Bug: 180405672
Test: atest TaskTests PinnedStackTests
Change-Id: I038076c58cd41cc90039c9db5a295da5d5ee2cde
parent c717ef59
Loading
Loading
Loading
Loading
+25 −8
Original line number Diff line number Diff line
@@ -5245,17 +5245,29 @@ class Task extends WindowContainer<WindowContainer> {
        if (mForceHiddenFlags == newFlags) {
            return false;
        }

        final boolean wasHidden = isForceHidden();
        final boolean wasVisible = isVisible();
        mForceHiddenFlags = newFlags;
        if (wasHidden != isForceHidden() && isTopActivityFocusable()) {
            // The change in force-hidden state will change visibility without triggering a root
            // task order change, so we should reset the preferred top focusable root task to ensure
            // it's not used if a new activity is started from this task.
            getDisplayArea().resetPreferredTopFocusableRootTaskIfNeeded(this);
        final boolean nowHidden = isForceHidden();
        if (wasHidden != nowHidden) {
            final String reason = "setForceHidden";
            if (wasVisible && nowHidden) {
                // Move this visible task to back when the task is forced hidden
                moveToBack(reason, null);
            } else if (isAlwaysOnTop()) {
                // Move this always-on-top task to front when no longer hidden
                moveToFront(reason);
            }
        }
        return true;
    }

    @Override
    public boolean isAlwaysOnTop() {
        return !isForceHidden() && super.isAlwaysOnTop();
    }

    /**
     * Returns whether this task is currently forced to be hidden for any reason.
     */
@@ -7482,17 +7494,22 @@ class Task extends WindowContainer<WindowContainer> {
    }

    public void setAlwaysOnTop(boolean alwaysOnTop) {
        if (isAlwaysOnTop() == alwaysOnTop) {
        // {@link #isAwaysonTop} overrides the original behavior which also evaluates if this
        // task is force hidden, so super.isAlwaysOnTop() is used here to see whether the
        // alwaysOnTop attributes should be updated.
        if (super.isAlwaysOnTop() == alwaysOnTop) {
            return;
        }
        super.setAlwaysOnTop(alwaysOnTop);
        final TaskDisplayArea taskDisplayArea = getDisplayArea();
        // positionChildAtTop() must be called even when always on top gets turned off because we
        // need to make sure that the root task is moved from among always on top windows to
        // below other always on top windows. Since the position the root task should be inserted
        // into is calculated properly in {@link DisplayContent#getTopInsertPosition()} in both
        // cases, we can just request that the root task is put at top here.
        taskDisplayArea.positionChildAt(POSITION_TOP, this, false /* includingParents */);
        // Don't bother moving task to top if this task is force hidden and invisible to user.
        if (!isForceHidden()) {
            getDisplayArea().positionChildAt(POSITION_TOP, this, false /* includingParents */);
        }
    }

    void dismissPip() {
+1 −9
Original line number Diff line number Diff line
@@ -393,7 +393,7 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
        final boolean moveToBottom = position <= 0;

        final int oldPosition = mChildren.indexOf(child);
        if (child.getWindowConfiguration().isAlwaysOnTop() && !moveToTop) {
        if (child.isAlwaysOnTop() && !moveToTop) {
            // This root task is always-on-top, override the default behavior.
            Slog.w(TAG_WM, "Ignoring move of always-on-top root task=" + this + " to bottom");

@@ -974,14 +974,6 @@ final class TaskDisplayArea extends DisplayArea<WindowContainer> {
        onRootTaskOrderChanged(rootTask);
    }

    /** Reset the mPreferredTopFocusableRootTask if it is or below the given task. */
    void resetPreferredTopFocusableRootTaskIfNeeded(Task task) {
        if (mPreferredTopFocusableRootTask != null
                && mPreferredTopFocusableRootTask.compareTo(task) <= 0) {
            mPreferredTopFocusableRootTask = null;
        }
    }

    /**
     * Moves/reparents `task` to the back of whatever container the root home task is in. This is
     * for when we just want to move a task to "the back" vs. a specific place. The primary use-case
+12 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
import static com.android.server.wm.Task.FLAG_FORCE_HIDDEN_FOR_TASK_ORG;

import static com.google.common.truth.Truth.assertThat;

@@ -277,4 +278,15 @@ public class TaskTests extends WindowTestsBase {
        // Orientation request from standard activity in multi window will not be handled.
        assertFalse(leafTask2.handlesOrientationChangeFromDescendant());
    }

    @Test
    public void testAlwaysOnTop() {
        final Task task = createTaskStackOnDisplay(mDisplayContent);
        task.setAlwaysOnTop(true);
        task.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
        assertTrue(task.isAlwaysOnTop());

        task.setForceHidden(FLAG_FORCE_HIDDEN_FOR_TASK_ORG, true /* set */);
        assertFalse(task.isAlwaysOnTop());
    }
}