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

Commit 309cffad authored by Hongwei Wang's avatar Hongwei Wang
Browse files

Ensure clear state when getDestinationBounds for PiP

When request PipBoundsHandler#getDestinationBounds from different
component, simply reset any internal states.

Bug: 153349821
Test: atest PipBoundsHandlerTest
Test: atest PinnedStackTests#testAutoEnterPictureInPicture \
            PinnedStackTests#testEnterPipWithMinimalSize
Change-Id: I71a64fa169918fc0b191caf583a22f864152c2fe
parent 5b8c53ff
Loading
Loading
Loading
Loading
+7 −5
Original line number Original line Diff line number Diff line
@@ -231,7 +231,12 @@ public class PipBoundsHandler {
    /**
    /**
     * @return {@link Rect} of the destination PiP window bounds.
     * @return {@link Rect} of the destination PiP window bounds.
     */
     */
    Rect getDestinationBounds(float aspectRatio, Rect bounds, Size minimalSize) {
    Rect getDestinationBounds(ComponentName componentName, float aspectRatio, Rect bounds,
            Size minimalSize) {
        if (!componentName.equals(mLastPipComponentName)) {
            onResetReentryBoundsUnchecked();
            mLastPipComponentName = componentName;
        }
        final Rect destinationBounds;
        final Rect destinationBounds;
        if (bounds == null) {
        if (bounds == null) {
            final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
            final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
@@ -246,11 +251,7 @@ public class PipBoundsHandler {
            transformBoundsToAspectRatio(destinationBounds, aspectRatio,
            transformBoundsToAspectRatio(destinationBounds, aspectRatio,
                    false /* useCurrentMinEdgeSize */);
                    false /* useCurrentMinEdgeSize */);
        }
        }
        if (destinationBounds.equals(bounds)) {
            return bounds;
        }
        mAspectRatio = aspectRatio;
        mAspectRatio = aspectRatio;
        onResetReentryBoundsUnchecked();
        mLastDestinationBounds.set(destinationBounds);
        mLastDestinationBounds.set(destinationBounds);
        return destinationBounds;
        return destinationBounds;
    }
    }
@@ -483,6 +484,7 @@ public class PipBoundsHandler {
        pw.println(prefix + TAG);
        pw.println(prefix + TAG);
        pw.println(innerPrefix + "mLastPipComponentName=" + mLastPipComponentName);
        pw.println(innerPrefix + "mLastPipComponentName=" + mLastPipComponentName);
        pw.println(innerPrefix + "mReentrySnapFraction=" + mReentrySnapFraction);
        pw.println(innerPrefix + "mReentrySnapFraction=" + mReentrySnapFraction);
        pw.println(innerPrefix + "mReentrySize=" + mReentrySize);
        pw.println(innerPrefix + "mDisplayInfo=" + mDisplayInfo);
        pw.println(innerPrefix + "mDisplayInfo=" + mDisplayInfo);
        pw.println(innerPrefix + "mDefaultAspectRatio=" + mDefaultAspectRatio);
        pw.println(innerPrefix + "mDefaultAspectRatio=" + mDefaultAspectRatio);
        pw.println(innerPrefix + "mMinAspectRatio=" + mMinAspectRatio);
        pw.println(innerPrefix + "mMinAspectRatio=" + mMinAspectRatio);
+3 −3
Original line number Original line Diff line number Diff line
@@ -247,7 +247,7 @@ public class PipTaskOrganizer extends TaskOrganizer {
    public void onTaskAppeared(ActivityManager.RunningTaskInfo info) {
    public void onTaskAppeared(ActivityManager.RunningTaskInfo info) {
        Objects.requireNonNull(info, "Requires RunningTaskInfo");
        Objects.requireNonNull(info, "Requires RunningTaskInfo");
        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                getAspectRatioOrDefault(info.pictureInPictureParams),
                info.topActivity, getAspectRatioOrDefault(info.pictureInPictureParams),
                null /* bounds */, getMinimalSize(info.topActivityInfo));
                null /* bounds */, getMinimalSize(info.topActivityInfo));
        Objects.requireNonNull(destinationBounds, "Missing destination bounds");
        Objects.requireNonNull(destinationBounds, "Missing destination bounds");
        mTaskInfo = info;
        mTaskInfo = info;
@@ -303,7 +303,7 @@ public class PipTaskOrganizer extends TaskOrganizer {
            return;
            return;
        }
        }
        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                getAspectRatioOrDefault(newParams),
                info.topActivity, getAspectRatioOrDefault(newParams),
                null /* bounds */, getMinimalSize(info.topActivityInfo));
                null /* bounds */, getMinimalSize(info.topActivityInfo));
        Objects.requireNonNull(destinationBounds, "Missing destination bounds");
        Objects.requireNonNull(destinationBounds, "Missing destination bounds");
        scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration,
        scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration,
@@ -335,7 +335,7 @@ public class PipTaskOrganizer extends TaskOrganizer {
        }
        }


        final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds(
        final Rect newDestinationBounds = mPipBoundsHandler.getDestinationBounds(
                getAspectRatioOrDefault(mTaskInfo.pictureInPictureParams),
                mTaskInfo.topActivity, getAspectRatioOrDefault(mTaskInfo.pictureInPictureParams),
                null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
                null /* bounds */, getMinimalSize(mTaskInfo.topActivityInfo));
        if (newDestinationBounds.equals(currentDestinationBounds)) return;
        if (newDestinationBounds.equals(currentDestinationBounds)) return;
        if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) {
        if (animator.getAnimationType() == ANIM_TYPE_BOUNDS) {
+54 −29
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.pip;
package com.android.systemui.pip;


import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;


import android.content.ComponentName;
import android.content.ComponentName;
@@ -56,11 +57,15 @@ public class PipBoundsHandlerTest extends SysuiTestCase {


    private PipBoundsHandler mPipBoundsHandler;
    private PipBoundsHandler mPipBoundsHandler;
    private DisplayInfo mDefaultDisplayInfo;
    private DisplayInfo mDefaultDisplayInfo;
    private ComponentName mTestComponentName1;
    private ComponentName mTestComponentName2;


    @Before
    @Before
    public void setUp() throws Exception {
    public void setUp() throws Exception {
        initializeMockResources();
        initializeMockResources();
        mPipBoundsHandler = new PipBoundsHandler(mContext, new PipSnapAlgorithm(mContext));
        mPipBoundsHandler = new PipBoundsHandler(mContext, new PipSnapAlgorithm(mContext));
        mTestComponentName1 = new ComponentName(mContext, "component1");
        mTestComponentName2 = new ComponentName(mContext, "component2");


        mPipBoundsHandler.onDisplayInfoChanged(mDefaultDisplayInfo);
        mPipBoundsHandler.onDisplayInfoChanged(mDefaultDisplayInfo);
    }
    }
@@ -121,7 +126,7 @@ public class PipBoundsHandlerTest extends SysuiTestCase {
        };
        };
        for (float aspectRatio : aspectRatios) {
        for (float aspectRatio : aspectRatios) {
            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                    aspectRatio, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
                    mTestComponentName1, aspectRatio, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
            final float actualAspectRatio =
            final float actualAspectRatio =
                    destinationBounds.width() / (destinationBounds.height() * 1f);
                    destinationBounds.width() / (destinationBounds.height() * 1f);
            assertEquals("Destination bounds matches the given aspect ratio",
            assertEquals("Destination bounds matches the given aspect ratio",
@@ -137,7 +142,7 @@ public class PipBoundsHandlerTest extends SysuiTestCase {
        };
        };
        for (float aspectRatio : invalidAspectRatios) {
        for (float aspectRatio : invalidAspectRatios) {
            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                    aspectRatio, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
                    mTestComponentName1, aspectRatio, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
            final float actualAspectRatio =
            final float actualAspectRatio =
                    destinationBounds.width() / (destinationBounds.height() * 1f);
                    destinationBounds.width() / (destinationBounds.height() * 1f);
            assertEquals("Destination bounds fallbacks to default aspect ratio",
            assertEquals("Destination bounds fallbacks to default aspect ratio",
@@ -153,7 +158,7 @@ public class PipBoundsHandlerTest extends SysuiTestCase {
        currentBounds.right = (int) (currentBounds.height() * aspectRatio) + currentBounds.left;
        currentBounds.right = (int) (currentBounds.height() * aspectRatio) + currentBounds.left;


        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                aspectRatio, currentBounds, EMPTY_MINIMAL_SIZE);
                mTestComponentName1, aspectRatio, currentBounds, EMPTY_MINIMAL_SIZE);


        final float actualAspectRatio =
        final float actualAspectRatio =
                destinationBounds.width() / (destinationBounds.height() * 1f);
                destinationBounds.width() / (destinationBounds.height() * 1f);
@@ -177,7 +182,7 @@ public class PipBoundsHandlerTest extends SysuiTestCase {
            final float aspectRatio = aspectRatios[i];
            final float aspectRatio = aspectRatios[i];
            final Size minimalSize = minimalSizes[i];
            final Size minimalSize = minimalSizes[i];
            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                    aspectRatio, EMPTY_CURRENT_BOUNDS, minimalSize);
                    mTestComponentName1, aspectRatio, EMPTY_CURRENT_BOUNDS, minimalSize);
            assertTrue("Destination bounds is no smaller than minimal requirement",
            assertTrue("Destination bounds is no smaller than minimal requirement",
                    (destinationBounds.width() == minimalSize.getWidth()
                    (destinationBounds.width() == minimalSize.getWidth()
                            && destinationBounds.height() >= minimalSize.getHeight())
                            && destinationBounds.height() >= minimalSize.getHeight())
@@ -198,89 +203,100 @@ public class PipBoundsHandlerTest extends SysuiTestCase {
        final Size minSize = new Size(currentBounds.width() / 2, currentBounds.height() / 2);
        final Size minSize = new Size(currentBounds.width() / 2, currentBounds.height() / 2);


        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                aspectRatio, currentBounds, minSize);
                mTestComponentName1, aspectRatio, currentBounds, minSize);


        assertTrue("Destination bounds ignores minimal size",
        assertTrue("Destination bounds ignores minimal size",
                destinationBounds.width() > minSize.getWidth()
                destinationBounds.width() > minSize.getWidth()
                        && destinationBounds.height() > minSize.getHeight());
                        && destinationBounds.height() > minSize.getHeight());
    }
    }


    @Test
    public void getDestinationBounds_withDifferentComponentName_ignoreLastPosition() {
        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);

        oldPosition.offset(0, -100);
        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, oldPosition);

        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName2,
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);

        assertNonBoundsInclusionWithMargin("ignore saved bounds", oldPosition, newPosition);
    }

    @Test
    @Test
    public void setShelfHeight_offsetBounds() {
    public void setShelfHeight_offsetBounds() {
        final int shelfHeight = 100;
        final int shelfHeight = 100;
        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(
        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);


        mPipBoundsHandler.setShelfHeight(true, shelfHeight);
        mPipBoundsHandler.setShelfHeight(true, shelfHeight);
        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(
        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);


        oldPosition.offset(0, -shelfHeight);
        oldPosition.offset(0, -shelfHeight);
        assertBoundsWithMargin("offsetBounds by shelf", oldPosition, newPosition);
        assertBoundsInclusionWithMargin("offsetBounds by shelf", oldPosition, newPosition);
    }
    }


    @Test
    @Test
    public void onImeVisibilityChanged_offsetBounds() {
    public void onImeVisibilityChanged_offsetBounds() {
        final int imeHeight = 100;
        final int imeHeight = 100;
        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(
        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);


        mPipBoundsHandler.onImeVisibilityChanged(true, imeHeight);
        mPipBoundsHandler.onImeVisibilityChanged(true, imeHeight);
        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(
        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);


        oldPosition.offset(0, -imeHeight);
        oldPosition.offset(0, -imeHeight);
        assertBoundsWithMargin("offsetBounds by IME", oldPosition, newPosition);
        assertBoundsInclusionWithMargin("offsetBounds by IME", oldPosition, newPosition);
    }
    }


    @Test
    @Test
    public void onSaveReentryBounds_restoreLastPosition() {
    public void onSaveReentryBounds_restoreLastPosition() {
        final ComponentName componentName = new ComponentName(mContext, "component1");
        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);


        oldPosition.offset(0, -100);
        oldPosition.offset(0, -100);
        mPipBoundsHandler.onSaveReentryBounds(componentName, oldPosition);
        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, oldPosition);


        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(
        final Rect newPosition = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);


        assertBoundsWithMargin("restoreLastPosition", oldPosition, newPosition);
        assertBoundsInclusionWithMargin("restoreLastPosition", oldPosition, newPosition);
    }
    }


    @Test
    @Test
    public void onResetReentryBounds_useDefaultBounds() {
    public void onResetReentryBounds_useDefaultBounds() {
        final ComponentName componentName = new ComponentName(mContext, "component1");
        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
        final Rect newBounds = new Rect(defaultBounds);
        final Rect newBounds = new Rect(defaultBounds);
        newBounds.offset(0, -100);
        newBounds.offset(0, -100);
        mPipBoundsHandler.onSaveReentryBounds(componentName, newBounds);
        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, newBounds);


        mPipBoundsHandler.onResetReentryBounds(componentName);
        mPipBoundsHandler.onResetReentryBounds(mTestComponentName1);
        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(
        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);


        assertBoundsWithMargin("useDefaultBounds", defaultBounds, actualBounds);
        assertBoundsInclusionWithMargin("useDefaultBounds", defaultBounds, actualBounds);
    }
    }


    @Test
    @Test
    public void onResetReentryBounds_componentMismatch_restoreLastPosition() {
    public void onResetReentryBounds_componentMismatch_restoreLastPosition() {
        final ComponentName componentName = new ComponentName(mContext, "component1");
        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
        final Rect newBounds = new Rect(defaultBounds);
        final Rect newBounds = new Rect(defaultBounds);
        newBounds.offset(0, -100);
        newBounds.offset(0, -100);
        mPipBoundsHandler.onSaveReentryBounds(componentName, newBounds);
        mPipBoundsHandler.onSaveReentryBounds(mTestComponentName1, newBounds);


        mPipBoundsHandler.onResetReentryBounds(new ComponentName(mContext, "component2"));
        mPipBoundsHandler.onResetReentryBounds(mTestComponentName2);
        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(
        final Rect actualBounds = mPipBoundsHandler.getDestinationBounds(mTestComponentName1,
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);


        assertBoundsWithMargin("restoreLastPosition", newBounds, actualBounds);
        assertBoundsInclusionWithMargin("restoreLastPosition", newBounds, actualBounds);
    }
    }


    private void assertBoundsWithMargin(String from, Rect expected, Rect actual) {
    private void assertBoundsInclusionWithMargin(String from, Rect expected, Rect actual) {
        final Rect expectedWithMargin = new Rect(expected);
        final Rect expectedWithMargin = new Rect(expected);
        expectedWithMargin.inset(-ROUNDING_ERROR_MARGIN, -ROUNDING_ERROR_MARGIN);
        expectedWithMargin.inset(-ROUNDING_ERROR_MARGIN, -ROUNDING_ERROR_MARGIN);
        assertTrue(from + ": expect " + expected
        assertTrue(from + ": expect " + expected
@@ -288,4 +304,13 @@ public class PipBoundsHandlerTest extends SysuiTestCase {
                + " with error margin " + ROUNDING_ERROR_MARGIN,
                + " with error margin " + ROUNDING_ERROR_MARGIN,
                expectedWithMargin.contains(actual));
                expectedWithMargin.contains(actual));
    }
    }

    private void assertNonBoundsInclusionWithMargin(String from, Rect expected, Rect actual) {
        final Rect expectedWithMargin = new Rect(expected);
        expectedWithMargin.inset(-ROUNDING_ERROR_MARGIN, -ROUNDING_ERROR_MARGIN);
        assertFalse(from + ": expect " + expected
                        + " not contains " + actual
                        + " with error margin " + ROUNDING_ERROR_MARGIN,
                expectedWithMargin.contains(actual));
    }
}
}