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

Commit 0671cc5f authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Restrict PiP bounds to the display's min/max PiP size upon display transfer." into main

parents dbf9baf9 224ab6ca
Loading
Loading
Loading
Loading
+39 −5
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.android.wm.shell.pip2.phone.PipTransition.PIP_DESTINATION_BOUN
import android.annotation.Nullable;
import android.app.TaskInfo;
import android.content.Context;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Bundle;
@@ -97,6 +98,10 @@ public class PipDisplayTransferHandler implements
            Rect boundsOnRelease) {
        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
                "%s scheduleMovePipToDisplay from=%d to=%d", TAG, originDisplayId, targetDisplayId);
        mPipDisplayLayoutState.setDisplayId(targetDisplayId);
        mPipDisplayLayoutState.setDisplayLayout(
                mDisplayController.getDisplayLayout(targetDisplayId));
        mPipBoundsState.updateMinMaxSize(mPipBoundsState.getAspectRatio());

        // Set bounds to the bounds on drag release so that we can use this as the origin bounds
        // during animation to snap to the display's edge.
@@ -107,6 +112,7 @@ public class PipDisplayTransferHandler implements
        // is released and the display ID and layout are updated.
        mPipBoundsAlgorithm.snapToMovementBoundsEdge(boundsOnRelease,
                mDisplayController.getDisplayLayout(targetDisplayId));
        snapBoundsWithinMinMaxSize(boundsOnRelease);

        Bundle extra = new Bundle();
        extra.putInt(ORIGIN_DISPLAY_ID_KEY, originDisplayId);
@@ -116,6 +122,38 @@ public class PipDisplayTransferHandler implements
        mPipTransitionState.setState(PipTransitionState.SCHEDULED_BOUNDS_CHANGE, extra);
    }

    /**
     * Restricts {@param bounds} to the allowed min/max size constraints and snaps bounds to the
     * correct edge based on the snap fraction.
     */
    private void snapBoundsWithinMinMaxSize(Rect bounds) {
        final float snapFraction = mPipBoundsAlgorithm.getSnapAlgorithm().getSnapFraction(
                bounds,
                mPipBoundsAlgorithm.getMovementBounds(bounds),
                mPipBoundsState.getStashedState());

        final Point minSize = mPipBoundsState.getMinSize();
        final Point maxSize = mPipBoundsState.getMaxSize();
        int newWidth = bounds.width();
        int newHeight = bounds.height();

        if (bounds.width() < minSize.x || bounds.height() < minSize.y) {
            newWidth = minSize.x;
            newHeight = minSize.y;
        } else if (bounds.width() > maxSize.x || bounds.height() > maxSize.y) {
            newWidth = maxSize.x;
            newHeight = maxSize.y;
        }

        bounds.set(0, 0, newWidth, newHeight);

        mPipBoundsAlgorithm.getSnapAlgorithm().applySnapFraction(bounds,
                mPipBoundsAlgorithm.getMovementBounds(bounds), snapFraction,
                mPipBoundsState.getStashedState(), mPipBoundsState.getStashOffset(),
                mPipDisplayLayoutState.getDisplayBounds(),
                mPipDisplayLayoutState.getDisplayLayout().stableInsets());
    }

    @Override
    public void onPipTransitionStateChanged(@PipTransitionState.TransitionState int oldState,
            @PipTransitionState.TransitionState int newState, @Nullable Bundle extra) {
@@ -158,10 +196,6 @@ public class PipDisplayTransferHandler implements
                Trace.instant(Trace.TRACE_TAG_WINDOW_MANAGER,
                        "PipDisplayTransferHandler#changingPipBounds");

                mPipDisplayLayoutState.setDisplayId(mTargetDisplayId);
                mPipDisplayLayoutState.setDisplayLayout(
                        mDisplayController.getDisplayLayout(mTargetDisplayId));

                mPipSurfaceTransactionHelper.round(startTx, pipLeash, true).shadow(startTx,
                        pipLeash, true /* applyShadowRadius */);
                // Set state to exiting and exited PiP to unregister input consumer on the current
@@ -177,7 +211,7 @@ public class PipDisplayTransferHandler implements

                final PipResizeAnimator animator = mPipResizeAnimatorSupplier.get(mContext,
                        mPipSurfaceTransactionHelper, pipLeash, startTx, finishTx,
                        mPipBoundsState.getBounds(), mPipBoundsState.getBounds(), pipBounds,
                        pipBounds, mPipBoundsState.getBounds(), pipBounds,
                        duration, 0);

                animator.setAnimationEndCallback(() -> {
+18 −1
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ import org.mockito.kotlin.whenever
import org.mockito.kotlin.verify
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.Point
import android.graphics.PointF
import android.graphics.Rect
import android.os.Bundle
@@ -63,6 +64,7 @@ import com.android.wm.shell.common.DisplayLayout
import com.android.wm.shell.common.MultiDisplayDragMoveBoundsCalculator
import com.android.wm.shell.common.MultiDisplayTestUtil.TestDisplay
import com.android.wm.shell.common.pip.PipBoundsAlgorithm
import com.android.wm.shell.common.pip.PipSnapAlgorithm
import com.android.wm.shell.pip2.animation.PipResizeAnimator
import com.android.wm.shell.pip2.phone.PipTransitionState.EXITED_PIP
import com.android.wm.shell.pip2.phone.PipTransitionState.EXITING_PIP
@@ -86,6 +88,7 @@ class PipDisplayTransferHandlerTest : ShellTestCase() {
    private val mockRootTaskDisplayAreaOrganizer = mock<RootTaskDisplayAreaOrganizer>()
    private val mockPipBoundsState = mock<PipBoundsState>()
    private val mockPipBoundsAlgorithm = mock<PipBoundsAlgorithm>()
    private val mockPipSnapAlgorithm = mock<PipSnapAlgorithm>()
    private val mockTaskInfo = mock<ActivityManager.RunningTaskInfo>()
    private val mockDisplayController = mock<DisplayController>()
    private val mockTransaction = mock<SurfaceControl.Transaction>()
@@ -133,6 +136,10 @@ class PipDisplayTransferHandlerTest : ShellTestCase() {
        whenever(mockTransaction.show(any())).thenReturn(mockTransaction)
        whenever(mockFactory.transaction).thenReturn(mockTransaction)
        whenever(mockPipBoundsState.bounds).thenReturn(mockBounds)
        whenever(mockPipBoundsAlgorithm.snapAlgorithm).thenReturn(mockPipSnapAlgorithm)
        whenever(mockPipSnapAlgorithm.getSnapFraction(any(), any(), any())).thenReturn(0.5f)
        whenever(mockPipBoundsState.minSize).thenReturn(MIN_SIZE)
        whenever(mockPipBoundsState.maxSize).thenReturn(MAX_SIZE)
        whenever(
            mockSurfaceTransactionHelper.setPipTransformations(
                any(),
@@ -165,6 +172,11 @@ class PipDisplayTransferHandlerTest : ShellTestCase() {
            whenever(mockDisplayController.getDisplayLayout(id)).thenReturn(displayLayout)
            whenever(mockDisplayController.isDisplayInTopology(id)).thenReturn(true)
        }
        whenever(mockPipDisplayLayoutState.displayLayout).thenReturn(
            displayLayouts.get(
                ORIGIN_DISPLAY_ID
            )
        )

        pipDisplayTransferHandler =
            PipDisplayTransferHandler(
@@ -181,13 +193,16 @@ class PipDisplayTransferHandlerTest : ShellTestCase() {
    }

    @Test
    fun scheduleMovePipToDisplay_setsTransitionState() {
    fun scheduleMovePipToDisplay_setsDisplayAndTransitionStates() {
        pipDisplayTransferHandler.scheduleMovePipToDisplay(
            ORIGIN_DISPLAY_ID,
            TARGET_DISPLAY_ID,
            DESTINATION_BOUNDS
        )

        verify(mockPipDisplayLayoutState).displayId = eq(TARGET_DISPLAY_ID)
        verify(mockPipDisplayLayoutState).displayLayout =
            eq(displayLayouts.get(TARGET_DISPLAY_ID))!!
        verify(mockPipBoundsAlgorithm).snapToMovementBoundsEdge(
            eq(DESTINATION_BOUNDS),
            eq(displayLayouts.get(TARGET_DISPLAY_ID))
@@ -480,5 +495,7 @@ class PipDisplayTransferHandlerTest : ShellTestCase() {
        val START_DRAG_COORDINATES = PointF(100f, 100f)
        val PIP_BOUNDS = Rect(0, 0, 700, 700)
        val DESTINATION_BOUNDS = Rect(100, 100, 800, 800)
        val MIN_SIZE = Point(100, 200)
        val MAX_SIZE = Point(300, 400)
    }
}
 No newline at end of file