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

Commit 048e2661 authored by Kazuki Takise's avatar Kazuki Takise
Browse files

Defer always on top state when task gets maximized

This CL enables always on top to be restored/deferred when
stacks switch between freeform and fullscreen.

Bug: 110494387
Test: ActivityStackTests
Test: DisplayContentTests
Test: go/wm-smoke
Change-Id: Iccb9824f845dea4925fac5d5dcb5eeaab2acdfcd
parent a800f9ab
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -575,7 +575,8 @@ public class WindowConfiguration implements Parcelable, Comparable<WindowConfigu
     * @hide
     */
    public boolean isAlwaysOnTop() {
        return mWindowingMode == WINDOWING_MODE_PINNED || mAlwaysOnTop == ALWAYS_ON_TOP_ON;
        return mWindowingMode == WINDOWING_MODE_PINNED
                || (mWindowingMode == WINDOWING_MODE_FREEFORM && mAlwaysOnTop == ALWAYS_ON_TOP_ON);
    }

    /**
+8 −2
Original line number Diff line number Diff line
@@ -167,8 +167,14 @@ class ActivityDisplay extends ConfigurationContainer<ActivityStack>
        mStacks.remove(stack);
        final int insertPosition = getTopInsertPosition(stack, position);
        mStacks.add(insertPosition, stack);
        // Since positionChildAt() is called during the creation process of pinned stacks,
        // ActivityStack#getWindowContainerController() can be null. In this special case,
        // since DisplayContest#positionStackAt() is called in TaskStack#onConfigurationChanged(),
        // we don't have to call WindowContainerController#positionChildAt() here.
        if (stack.getWindowContainerController() != null) {
            mWindowContainerController.positionChildAt(stack.getWindowContainerController(),
                    insertPosition);
        }
        onStackOrderChanged();
    }

+11 −1
Original line number Diff line number Diff line
@@ -503,11 +503,21 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
    @Override
    public void onConfigurationChanged(Configuration newParentConfig) {
        final int prevWindowingMode = getWindowingMode();
        final boolean prevIsAlwaysOnTop = isAlwaysOnTop();
        super.onConfigurationChanged(newParentConfig);
        final ActivityDisplay display = getDisplay();
        if (display != null && prevWindowingMode != getWindowingMode()) {
        if (display == null) {
          return;
        }
        if (prevWindowingMode != getWindowingMode()) {
            display.onStackWindowingModeChanged(this);
        }
        if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
            // Since always on top is only on when the stack is freeform or pinned, the state
            // can be toggled when the windowing mode changes. We must make sure the stack is
            // placed properly when always on top state changes.
            display.positionChildAtTop(this);
        }
    }

    @Override
+9 −0
Original line number Diff line number Diff line
@@ -507,6 +507,15 @@ public class ActivityStackTests extends ActivityTestsBase {
        // Ensure, when always on top is turned off for a stack, the stack is put just below all
        // other always on top stacks.
        assertTrue(mDefaultDisplay.getStackAbove(alwaysOnTopStack2) == alwaysOnTopStack);
        alwaysOnTopStack2.setAlwaysOnTop(true);

        // Ensure always on top state changes properly when windowing mode changes.
        alwaysOnTopStack2.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        assertFalse(alwaysOnTopStack2.isAlwaysOnTop());
        assertTrue(mDefaultDisplay.getStackAbove(alwaysOnTopStack2) == alwaysOnTopStack);
        alwaysOnTopStack2.setWindowingMode(WINDOWING_MODE_FREEFORM);
        assertTrue(alwaysOnTopStack2.isAlwaysOnTop());
        assertTrue(mDefaultDisplay.getStackAbove(alwaysOnTopStack2) == pinnedStack);
    }

    @Test
+17 −4
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.server.wm;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
@@ -384,7 +386,8 @@ public class DisplayContentTests extends WindowTestsBase {
     */
    @Test
    public void testAlwaysOnTopStackLocation() {
        final TaskStack alwaysOnTopStack = createTaskStackOnDisplay(mDisplayContent);
        final TaskStack alwaysOnTopStack = createStackControllerOnStackOnDisplay(
                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
        final Task task = createTaskInStack(alwaysOnTopStack, 0 /* userId */);
        alwaysOnTopStack.setAlwaysOnTop(true);
        mDisplayContent.positionStackAt(POSITION_TOP, alwaysOnTopStack);
@@ -398,7 +401,8 @@ public class DisplayContentTests extends WindowTestsBase {
        assertEquals(pinnedStack, mDisplayContent.getPinnedStack());
        assertEquals(pinnedStack, mDisplayContent.getTopStack());

        final TaskStack anotherAlwaysOnTopStack = createTaskStackOnDisplay(mDisplayContent);
        final TaskStack anotherAlwaysOnTopStack = createStackControllerOnStackOnDisplay(
                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
        anotherAlwaysOnTopStack.setAlwaysOnTop(true);
        mDisplayContent.positionStackAt(POSITION_TOP, anotherAlwaysOnTopStack);
        assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
@@ -407,7 +411,8 @@ public class DisplayContentTests extends WindowTestsBase {
        // existing alwaysOnTop stack.
        assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 1));

        final TaskStack nonAlwaysOnTopStack = createTaskStackOnDisplay(mDisplayContent);
        final TaskStack nonAlwaysOnTopStack = createStackControllerOnStackOnDisplay(
                WINDOWING_MODE_FREEFORM, ACTIVITY_TYPE_STANDARD, mDisplayContent).mContainer;
        assertEquals(mDisplayContent, nonAlwaysOnTopStack.getDisplayContent());
        topPosition = mDisplayContent.getStacks().size() - 1;
        // Ensure the non-alwaysOnTop stack is put below the three alwaysOnTop stacks, but above the
@@ -417,10 +422,18 @@ public class DisplayContentTests extends WindowTestsBase {
        anotherAlwaysOnTopStack.setAlwaysOnTop(false);
        mDisplayContent.positionStackAt(POSITION_TOP, anotherAlwaysOnTopStack);
        assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
        topPosition = mDisplayContent.getStacks().size() - 1;
        // Ensure, when always on top is turned off for a stack, the stack is put just below all
        // other always on top stacks.
        assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 2));
        anotherAlwaysOnTopStack.setAlwaysOnTop(true);

        // Ensure always on top state changes properly when windowing mode changes.
        anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
        assertFalse(anotherAlwaysOnTopStack.isAlwaysOnTop());
        assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 2));
        anotherAlwaysOnTopStack.setWindowingMode(WINDOWING_MODE_FREEFORM);
        assertTrue(anotherAlwaysOnTopStack.isAlwaysOnTop());
        assertEquals(anotherAlwaysOnTopStack, mDisplayContent.getStacks().get(topPosition - 1));
    }

    /**