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

Commit ca111769 authored by Hongwei Wang's avatar Hongwei Wang Committed by Android (Google) Code Review
Browse files

Merge "Get PiP bounds from layout dimensions if applicable" into rvc-dev

parents e6045973 2e725bee
Loading
Loading
Loading
Loading
+21 −3
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Parcel;
import android.os.RemoteException;
@@ -161,6 +162,13 @@ public class TaskInfo {
     */
    public @WindowConfiguration.ActivityType int topActivityType;

    /**
     * The {@link ActivityInfo} of the top activity in this task.
     * @hide
     */
    @Nullable
    public ActivityInfo topActivityInfo;

    TaskInfo() {
        // Do nothing
    }
@@ -219,6 +227,9 @@ public class TaskInfo {
        pictureInPictureParams = source.readInt() != 0
                ? PictureInPictureParams.CREATOR.createFromParcel(source)
                : null;
        topActivityInfo = source.readInt() != 0
                ? ActivityInfo.CREATOR.createFromParcel(source)
                : null;
    }

    /**
@@ -262,6 +273,12 @@ public class TaskInfo {
            dest.writeInt(1);
            pictureInPictureParams.writeToParcel(dest, flags);
        }
        if (topActivityInfo == null) {
            dest.writeInt(0);
        } else {
            dest.writeInt(1);
            topActivityInfo.writeToParcel(dest, flags);
        }
    }

    @Override
@@ -278,6 +295,7 @@ public class TaskInfo {
                + " resizeMode=" + resizeMode
                + " token=" + token
                + " topActivityType=" + topActivityType
                + " pictureInPictureParams=" + pictureInPictureParams;
                + " pictureInPictureParams=" + pictureInPictureParams
                + " topActivityInfo=" + topActivityInfo;
    }
}
+34 −3
Original line number Diff line number Diff line
@@ -67,7 +67,7 @@ public class PipBoundsHandler {

    private ComponentName mLastPipComponentName;
    private float mReentrySnapFraction = INVALID_SNAP_FRACTION;
    private Size mReentrySize = null;
    private Size mReentrySize;

    private float mDefaultAspectRatio;
    private float mMinAspectRatio;
@@ -77,6 +77,7 @@ public class PipBoundsHandler {
    private int mDefaultMinSize;
    private Point mScreenEdgeInsets;
    private int mCurrentMinSize;
    private Size mOverrideMinimalSize;

    private boolean mIsImeShowing;
    private int mImeHeight;
@@ -226,11 +227,14 @@ public class PipBoundsHandler {
    /**
     * @return {@link Rect} of the destination PiP window bounds.
     */
    Rect getDestinationBounds(float aspectRatio, Rect bounds) {
    Rect getDestinationBounds(float aspectRatio, Rect bounds, Size minimalSize) {
        final Rect destinationBounds;
        final Rect defaultBounds = getDefaultBounds(mReentrySnapFraction, mReentrySize);
        if (bounds == null) {
            destinationBounds = new Rect(defaultBounds);
            if (mReentrySnapFraction == INVALID_SNAP_FRACTION && mReentrySize == null) {
                mOverrideMinimalSize = minimalSize;
            }
        } else {
            destinationBounds = new Rect(bounds);
        }
@@ -335,7 +339,6 @@ public class PipBoundsHandler {
     */
    private void transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio,
            boolean useCurrentMinEdgeSize) {

        // Save the snap fraction and adjust the size based on the new aspect ratio.
        final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds,
                getMovementBounds(stackBounds));
@@ -354,9 +357,37 @@ public class PipBoundsHandler {
        final int left = (int) (stackBounds.centerX() - size.getWidth() / 2f);
        final int top = (int) (stackBounds.centerY() - size.getHeight() / 2f);
        stackBounds.set(left, top, left + size.getWidth(), top + size.getHeight());
        // apply the override minimal size if applicable, this minimal size is specified by app
        if (mOverrideMinimalSize != null) {
            transformBoundsToMinimalSize(stackBounds, aspectRatio, mOverrideMinimalSize);
        }
        mSnapAlgorithm.applySnapFraction(stackBounds, getMovementBounds(stackBounds), snapFraction);
    }

    /**
     * Transforms a given bounds to meet the minimal size constraints.
     * This function assumes the given {@param stackBounds} qualifies {@param aspectRatio}.
     */
    private void transformBoundsToMinimalSize(Rect stackBounds, float aspectRatio,
            Size minimalSize) {
        if (minimalSize == null) return;
        final Size adjustedMinimalSize;
        final float minimalSizeAspectRatio =
                minimalSize.getWidth() / (float) minimalSize.getHeight();
        if (minimalSizeAspectRatio > aspectRatio) {
            // minimal size is wider, fixed the width and increase the height
            adjustedMinimalSize = new Size(
                    minimalSize.getWidth(), (int) (minimalSize.getWidth() / aspectRatio));
        } else {
            adjustedMinimalSize = new Size(
                    (int) (minimalSize.getHeight() * aspectRatio), minimalSize.getHeight());
        }
        final Rect containerBounds = new Rect(stackBounds);
        Gravity.apply(mDefaultStackGravity,
                adjustedMinimalSize.getWidth(), adjustedMinimalSize.getHeight(),
                containerBounds, stackBounds);
    }

    /**
     * @return the default bounds to show the PIP, if a {@param snapFraction} and {@param size} are
     * provided, then it will apply the default bounds to the provided snap fraction and size.
+14 −17
Original line number Diff line number Diff line
@@ -30,11 +30,13 @@ import android.app.ActivityTaskManager;
import android.app.ITaskOrganizerController;
import android.app.PictureInPictureParams;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.util.Log;
import android.util.Size;
import android.view.ITaskOrganizer;
import android.view.IWindowContainer;
import android.view.SurfaceControl;
@@ -204,26 +206,12 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
        mOneShotAnimationType = animationType;
    }

    /**
     * Callback to issue the final {@link WindowContainerTransaction} on end of movements.
     * @param destinationBounds the final bounds.
     */
    public void onMotionMovementEnd(Rect destinationBounds) {
        try {
            mLastReportedBounds.set(destinationBounds);
            final WindowContainerTransaction wct = new WindowContainerTransaction();
            wct.setBounds(mToken, destinationBounds);
            mTaskOrganizerController.applyContainerTransaction(wct, null /* ITaskOrganizer */);
        } catch (RemoteException e) {
            Log.w(TAG, "Failed to apply window container transaction", e);
        }
    }

    @Override
    public void taskAppeared(ActivityManager.RunningTaskInfo info) {
        Objects.requireNonNull(info, "Requires RunningTaskInfo");
        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                getAspectRatioOrDefault(info.pictureInPictureParams), null /* bounds */);
                getAspectRatioOrDefault(info.pictureInPictureParams),
                null /* bounds */, getMinimalSize(info.topActivityInfo));
        Objects.requireNonNull(destinationBounds, "Missing destination bounds");
        mTaskInfo = info;
        mToken = mTaskInfo.token;
@@ -276,7 +264,8 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
            return;
        }
        final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                getAspectRatioOrDefault(newParams), null /* bounds */);
                getAspectRatioOrDefault(newParams),
                null /* bounds */, getMinimalSize(info.topActivityInfo));
        Objects.requireNonNull(destinationBounds, "Missing destination bounds");
        scheduleAnimateResizePip(destinationBounds, mEnterExitAnimationDuration, null);
    }
@@ -446,6 +435,14 @@ public class PipTaskOrganizer extends ITaskOrganizer.Stub {
                .start());
    }

    private Size getMinimalSize(ActivityInfo activityInfo) {
        if (activityInfo == null || activityInfo.windowLayout == null) {
            return null;
        }
        final ActivityInfo.WindowLayout windowLayout = activityInfo.windowLayout;
        return new Size(windowLayout.minWidth, windowLayout.minHeight);
    }

    private float getAspectRatioOrDefault(@Nullable PictureInPictureParams params) {
        return params == null
                ? mPipBoundsHandler.getDefaultAspectRatio()
+1 −1
Original line number Diff line number Diff line
@@ -426,7 +426,7 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,
        cancelAnimations();

        mAnimatedBoundsPhysicsAnimator
                .withEndActions(() ->  mPipTaskOrganizer.onMotionMovementEnd(mAnimatedBounds))
                .withEndActions(() ->  mPipTaskOrganizer.scheduleFinishResizePip(mAnimatedBounds))
                .addUpdateListener(mResizePipUpdateListener)
                .start();
    }
+59 −13
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import android.graphics.Rect;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableResources;
import android.util.Size;
import android.view.DisplayInfo;
import android.view.Gravity;

@@ -51,6 +52,7 @@ public class PipBoundsHandlerTest extends SysuiTestCase {
    private static final float MIN_ASPECT_RATIO = 0.5f;
    private static final float MAX_ASPECT_RATIO = 2f;
    private static final Rect EMPTY_CURRENT_BOUNDS = null;
    private static final Size EMPTY_MINIMAL_SIZE = null;

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

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

        final float actualAspectRatio =
                destinationBounds.width() / (destinationBounds.height() * 1f);
@@ -159,15 +161,59 @@ public class PipBoundsHandlerTest extends SysuiTestCase {
                aspectRatio, actualAspectRatio, ASPECT_RATIO_ERROR_MARGIN);
    }

    @Test
    public void getDestinationBounds_withMinSize_returnMinBounds() {
        final float[] aspectRatios = new float[] {
                (MIN_ASPECT_RATIO + DEFAULT_ASPECT_RATIO) / 2,
                DEFAULT_ASPECT_RATIO,
                (MAX_ASPECT_RATIO + DEFAULT_ASPECT_RATIO) / 2
        };
        final Size[] minimalSizes = new Size[] {
                new Size((int) (100 * aspectRatios[0]), 100),
                new Size((int) (100 * aspectRatios[1]), 100),
                new Size((int) (100 * aspectRatios[2]), 100)
        };
        for (int i = 0; i < aspectRatios.length; i++) {
            final float aspectRatio = aspectRatios[i];
            final Size minimalSize = minimalSizes[i];
            final Rect destinationBounds = mPipBoundsHandler.getDestinationBounds(
                    aspectRatio, EMPTY_CURRENT_BOUNDS, minimalSize);
            assertTrue("Destination bounds is no smaller than minimal requirement",
                    (destinationBounds.width() == minimalSize.getWidth()
                            && destinationBounds.height() >= minimalSize.getHeight())
                            || (destinationBounds.height() == minimalSize.getHeight()
                            && destinationBounds.width() >= minimalSize.getWidth()));
            final float actualAspectRatio =
                    destinationBounds.width() / (destinationBounds.height() * 1f);
            assertEquals("Destination bounds matches the given aspect ratio",
                    aspectRatio, actualAspectRatio, ASPECT_RATIO_ERROR_MARGIN);
        }
    }

    @Test
    public void getDestinationBounds_withCurrentBounds_ignoreMinBounds() {
        final float aspectRatio = (DEFAULT_ASPECT_RATIO + MAX_ASPECT_RATIO) / 2;
        final Rect currentBounds = new Rect(0, 0, 0, 100);
        currentBounds.right = (int) (currentBounds.height() * aspectRatio) + currentBounds.left;
        final Size minSize = new Size(currentBounds.width() / 2, currentBounds.height() / 2);

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

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

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

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

        oldPosition.offset(0, -shelfHeight);
        assertBoundsWithMargin("offsetBounds by shelf", oldPosition, newPosition);
@@ -177,11 +223,11 @@ public class PipBoundsHandlerTest extends SysuiTestCase {
    public void onImeVisibilityChanged_offsetBounds() {
        final int imeHeight = 100;
        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);

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

        oldPosition.offset(0, -imeHeight);
        assertBoundsWithMargin("offsetBounds by IME", oldPosition, newPosition);
@@ -191,13 +237,13 @@ public class PipBoundsHandlerTest extends SysuiTestCase {
    public void onSaveReentryBounds_restoreLastPosition() {
        final ComponentName componentName = new ComponentName(mContext, "component1");
        final Rect oldPosition = mPipBoundsHandler.getDestinationBounds(
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);

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

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

        assertBoundsWithMargin("restoreLastPosition", oldPosition, newPosition);
    }
@@ -206,14 +252,14 @@ public class PipBoundsHandlerTest extends SysuiTestCase {
    public void onResetReentryBounds_useDefaultBounds() {
        final ComponentName componentName = new ComponentName(mContext, "component1");
        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
        final Rect newBounds = new Rect(defaultBounds);
        newBounds.offset(0, -100);
        mPipBoundsHandler.onSaveReentryBounds(componentName, newBounds);

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

        assertBoundsWithMargin("useDefaultBounds", defaultBounds, actualBounds);
    }
@@ -222,14 +268,14 @@ public class PipBoundsHandlerTest extends SysuiTestCase {
    public void onResetReentryBounds_componentMismatch_restoreLastPosition() {
        final ComponentName componentName = new ComponentName(mContext, "component1");
        final Rect defaultBounds = mPipBoundsHandler.getDestinationBounds(
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS);
                DEFAULT_ASPECT_RATIO, EMPTY_CURRENT_BOUNDS, EMPTY_MINIMAL_SIZE);
        final Rect newBounds = new Rect(defaultBounds);
        newBounds.offset(0, -100);
        mPipBoundsHandler.onSaveReentryBounds(componentName, newBounds);

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

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