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

Commit 48f4b575 authored by Bryce Lee's avatar Bryce Lee
Browse files

Don't allow stacks above pinned stack.

Previously, stacks would be allowed above the pinned stack if the
pinned stack was not visible. We however do not correct the stack
position when the pinned stack later becomes visible. This can lead
to a scenario where the pinned stack has become visible yet is below
other stacks. When a stack is positioned in this state, an
IllegalStateException is thrown to indicate the invalid pinned stack
position.

Since the pinned stack should only be present and populated when
there is a pip activity, we can instead use its presence as an
indicator other stacks should be underneath it. This avoids placing a
stack above the pinned stack during transitional states where the
stack children might not be visible, therefore preventing the above
exception from occurring.

Fixes: 36669386
Test: bit FrameworksServicesTests:com.android.server.wm.DisplayContentTests#testPinnedStackLocation
Change-Id: I67a58806e83b11f0b135c12441bb0a9bec58eee7
parent 9c80a16c
Loading
Loading
Loading
Loading
+20 −2
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ import android.view.Surface;
import android.view.SurfaceControl;
import android.view.WindowManagerPolicy;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ToBooleanFunction;
import com.android.internal.view.IInputMethodClient;

@@ -1396,6 +1397,22 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
        return null;
    }

    @VisibleForTesting
    int getStackCount() {
        return mTaskStackContainers.size();
    }

    @VisibleForTesting
    int getStaskPosById(int stackId) {
        for (int i = mTaskStackContainers.size() - 1; i >= 0; --i) {
            final TaskStack stack = mTaskStackContainers.get(i);
            if (stack.mStackId == stackId) {
                return i;
            }
        }
        return -1;
    }

    @Override
    void onConfigurationChanged(Configuration newParentConfig) {
        super.onConfigurationChanged(newParentConfig);
@@ -3263,8 +3280,9 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
                    : requestedPosition >= topChildPosition;
            int targetPosition = requestedPosition;

            if (toTop && isStackVisible(PINNED_STACK_ID) && stack.mStackId != PINNED_STACK_ID) {
                // The pinned stack is always the top most stack (always-on-top) when it is visible.
            if (toTop && stack.mStackId != PINNED_STACK_ID
                    && getStackById(PINNED_STACK_ID) != null) {
                // The pinned stack is always the top most stack (always-on-top) when it is present.
                TaskStack topStack = mChildren.get(topChildPosition);
                if (topStack.mStackId != PINNED_STACK_ID) {
                    throw new IllegalStateException("Pinned stack isn't top stack??? " + mChildren);
+19 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.wm;

import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
@@ -289,6 +290,24 @@ public class DisplayContentTests extends WindowTestsBase {
        verifySizes(sDisplayContent, smallerWidth, smallerHeight, smallerDensity);
    }

    /**
     * This test enforces that the pinned stack is always kept as the top stack.
     */
    @Test
    public void testPinnedStackLocation() {
        createStackControllerOnStackOnDisplay(PINNED_STACK_ID, sDisplayContent);
        final int initialStackCount = sDisplayContent.getStackCount();
        // Ensure that the pinned stack was placed at the end
        assertEquals(initialStackCount - 1, sDisplayContent.getStaskPosById(PINNED_STACK_ID));
        // By default, this should try to create a new stack on top
        createTaskStackOnDisplay(sDisplayContent);
        final int afterStackCount = sDisplayContent.getStackCount();
        // Make sure the stack count has increased
        assertEquals(initialStackCount + 1, afterStackCount);
        // Ensure that the pinned stack is still on top
        assertEquals(afterStackCount - 1, sDisplayContent.getStaskPosById(PINNED_STACK_ID));
    }

    private static void verifySizes(DisplayContent displayContent, int expectedBaseWidth,
                             int expectedBaseHeight, int expectedBaseDensity) {
        assertEquals(displayContent.mBaseDisplayWidth, expectedBaseWidth);