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

Commit 8ea17a21 authored by Winson Chung's avatar Winson Chung Committed by Automerger Merge Worker
Browse files

Merge "Revert "Revert "Restore support for source hint rect""" into rvc-dev am: e5e4c105

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11819193

Change-Id: I4b878a65d22bf02d150de4d9dc883aef7e4dfe13
parents 455fda5c e5e4c105
Loading
Loading
Loading
Loading
+36 −26
Original line number Original line Diff line number Diff line
@@ -18,16 +18,16 @@ package com.android.systemui.pip;


import android.animation.AnimationHandler;
import android.animation.AnimationHandler;
import android.animation.Animator;
import android.animation.Animator;
import android.animation.RectEvaluator;
import android.animation.ValueAnimator;
import android.animation.ValueAnimator;
import android.annotation.IntDef;
import android.annotation.IntDef;
import android.content.Context;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.Rect;
import android.view.SurfaceControl;
import android.view.SurfaceControl;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.systemui.Interpolators;


import java.lang.annotation.Retention;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.RetentionPolicy;
@@ -76,7 +76,6 @@ public class PipAnimationController {
                || direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
                || direction == TRANSITION_DIRECTION_TO_SPLIT_SCREEN;
    }
    }


    private final Interpolator mFastOutSlowInInterpolator;
    private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
    private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;


    private PipTransitionAnimator mCurrentAnimator;
    private PipTransitionAnimator mCurrentAnimator;
@@ -90,8 +89,6 @@ public class PipAnimationController {


    @Inject
    @Inject
    PipAnimationController(Context context, PipSurfaceTransactionHelper helper) {
    PipAnimationController(Context context, PipSurfaceTransactionHelper helper) {
        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
                com.android.internal.R.interpolator.fast_out_slow_in);
        mSurfaceTransactionHelper = helper;
        mSurfaceTransactionHelper = helper;
    }
    }


@@ -113,10 +110,11 @@ public class PipAnimationController {
    }
    }


    @SuppressWarnings("unchecked")
    @SuppressWarnings("unchecked")
    PipTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds, Rect endBounds) {
    PipTransitionAnimator getAnimator(SurfaceControl leash, Rect startBounds, Rect endBounds,
            Rect sourceHintRect) {
        if (mCurrentAnimator == null) {
        if (mCurrentAnimator == null) {
            mCurrentAnimator = setupPipTransitionAnimator(
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
                    PipTransitionAnimator.ofBounds(leash, startBounds, endBounds, sourceHintRect));
        } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
        } else if (mCurrentAnimator.getAnimationType() == ANIM_TYPE_ALPHA
                && mCurrentAnimator.isRunning()) {
                && mCurrentAnimator.isRunning()) {
            // If we are still animating the fade into pip, then just move the surface and ensure
            // If we are still animating the fade into pip, then just move the surface and ensure
@@ -131,7 +129,7 @@ public class PipAnimationController {
        } else {
        } else {
            mCurrentAnimator.cancel();
            mCurrentAnimator.cancel();
            mCurrentAnimator = setupPipTransitionAnimator(
            mCurrentAnimator = setupPipTransitionAnimator(
                    PipTransitionAnimator.ofBounds(leash, startBounds, endBounds));
                    PipTransitionAnimator.ofBounds(leash, startBounds, endBounds, sourceHintRect));
        }
        }
        return mCurrentAnimator;
        return mCurrentAnimator;
    }
    }
@@ -142,7 +140,7 @@ public class PipAnimationController {


    private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) {
    private PipTransitionAnimator setupPipTransitionAnimator(PipTransitionAnimator animator) {
        animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper);
        animator.setSurfaceTransactionHelper(mSurfaceTransactionHelper);
        animator.setInterpolator(mFastOutSlowInInterpolator);
        animator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
        animator.setFloatValues(FRACTION_START, FRACTION_END);
        animator.setFloatValues(FRACTION_START, FRACTION_END);
        animator.setAnimationHandler(mSfAnimationHandlerThreadLocal.get());
        animator.setAnimationHandler(mSfAnimationHandlerThreadLocal.get());
        return animator;
        return animator;
@@ -341,6 +339,7 @@ public class PipAnimationController {
                @Override
                @Override
                void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
                void onStartTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
                    getSurfaceTransactionHelper()
                    getSurfaceTransactionHelper()
                            .resetScale(tx, leash, getDestinationBounds())
                            .crop(tx, leash, getDestinationBounds())
                            .crop(tx, leash, getDestinationBounds())
                            .round(tx, leash, shouldApplyCornerRadius());
                            .round(tx, leash, shouldApplyCornerRadius());
                    tx.show(leash);
                    tx.show(leash);
@@ -356,35 +355,46 @@ public class PipAnimationController {
        }
        }


        static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash,
        static PipTransitionAnimator<Rect> ofBounds(SurfaceControl leash,
                Rect startValue, Rect endValue) {
                Rect startValue, Rect endValue, Rect sourceHintRect) {
            // Just for simplicity we'll interpolate between the source rect hint insets and empty
            // insets to calculate the window crop
            final Rect initialStartValue = new Rect(startValue);
            final Rect sourceHintRectInsets = sourceHintRect != null
                    ? new Rect(sourceHintRect.left - startValue.left,
                            sourceHintRect.top - startValue.top,
                            startValue.right - sourceHintRect.right,
                            startValue.bottom - sourceHintRect.bottom)
                    : null;
            final Rect sourceInsets = new Rect(0, 0, 0, 0);

            // construct new Rect instances in case they are recycled
            // construct new Rect instances in case they are recycled
            return new PipTransitionAnimator<Rect>(leash, ANIM_TYPE_BOUNDS,
            return new PipTransitionAnimator<Rect>(leash, ANIM_TYPE_BOUNDS,
                    endValue, new Rect(startValue), new Rect(endValue)) {
                    endValue, new Rect(startValue), new Rect(endValue)) {
                private final Rect mTmpRect = new Rect();
                private final RectEvaluator mRectEvaluator = new RectEvaluator(new Rect());

                private final RectEvaluator mInsetsEvaluator = new RectEvaluator(new Rect());
                private int getCastedFractionValue(float start, float end, float fraction) {
                    return (int) (start * (1 - fraction) + end * fraction + .5f);
                }


                @Override
                @Override
                void applySurfaceControlTransaction(SurfaceControl leash,
                void applySurfaceControlTransaction(SurfaceControl leash,
                        SurfaceControl.Transaction tx, float fraction) {
                        SurfaceControl.Transaction tx, float fraction) {
                    final Rect start = getStartValue();
                    final Rect start = getStartValue();
                    final Rect end = getEndValue();
                    final Rect end = getEndValue();
                    mTmpRect.set(
                    Rect bounds = mRectEvaluator.evaluate(fraction, start, end);
                            getCastedFractionValue(start.left, end.left, fraction),
                    setCurrentValue(bounds);
                            getCastedFractionValue(start.top, end.top, fraction),
                            getCastedFractionValue(start.right, end.right, fraction),
                            getCastedFractionValue(start.bottom, end.bottom, fraction));
                    setCurrentValue(mTmpRect);
                    if (inScaleTransition()) {
                    if (inScaleTransition()) {
                        if (isOutPipDirection(getTransitionDirection())) {
                        if (isOutPipDirection(getTransitionDirection())) {
                            getSurfaceTransactionHelper().scale(tx, leash, end, mTmpRect);
                            getSurfaceTransactionHelper().scale(tx, leash, end, bounds);
                        } else {
                        } else {
                            getSurfaceTransactionHelper().scale(tx, leash, start, mTmpRect);
                            getSurfaceTransactionHelper().scale(tx, leash, start, bounds);
                        }
                        }
                    } else {
                    } else {
                        getSurfaceTransactionHelper().crop(tx, leash, mTmpRect);
                        if (sourceHintRectInsets != null) {
                            Rect insets = mInsetsEvaluator.evaluate(fraction, sourceInsets,
                                    sourceHintRectInsets);
                            getSurfaceTransactionHelper().scaleAndCrop(tx, leash, initialStartValue,
                                    bounds, insets);
                        } else {
                            getSurfaceTransactionHelper().scale(tx, leash, start, bounds);
                        }
                    }
                    }
                    tx.apply();
                    tx.apply();
                }
                }
@@ -400,11 +410,11 @@ public class PipAnimationController {


                @Override
                @Override
                void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
                void onEndTransaction(SurfaceControl leash, SurfaceControl.Transaction tx) {
                    if (!inScaleTransition()) return;
                    // NOTE: intentionally does not apply the transaction here.
                    // NOTE: intentionally does not apply the transaction here.
                    // this end transaction should get executed synchronously with the final
                    // this end transaction should get executed synchronously with the final
                    // WindowContainerTransaction in task organizer
                    // WindowContainerTransaction in task organizer
                    getSurfaceTransactionHelper().resetScale(tx, leash, getDestinationBounds())
                    getSurfaceTransactionHelper()
                            .resetScale(tx, leash, getDestinationBounds())
                            .crop(tx, leash, getDestinationBounds());
                            .crop(tx, leash, getDestinationBounds());
                }
                }


+18 −0
Original line number Original line Diff line number Diff line
@@ -288,6 +288,24 @@ public class PipBoundsHandler {
        return mDefaultAspectRatio;
        return mDefaultAspectRatio;
    }
    }


    /**
     * Updatest the display info and display layout on rotation change. This is needed even when we
     * aren't in PIP because the rotation layout is used to calculate the proper insets for the
     * next enter animation into PIP.
     */
    public void onDisplayRotationChangedNotInPip(int toRotation) {
        // Update the display layout, note that we have to do this on every rotation even if we
        // aren't in PIP since we need to update the display layout to get the right resources
        mDisplayLayout.rotateTo(mContext.getResources(), toRotation);

        // Populate the new {@link #mDisplayInfo}.
        // The {@link DisplayInfo} queried from DisplayManager would be the one before rotation,
        // therefore, the width/height may require a swap first.
        // Moving forward, we should get the new dimensions after rotation from DisplayLayout.
        mDisplayInfo.rotation = toRotation;
        updateDisplayInfoIfNeeded();
    }

    /**
    /**
     * Updates the display info, calculating and returning the new stack and movement bounds in the
     * Updates the display info, calculating and returning the new stack and movement bounds in the
     * new orientation of the device if necessary.
     * new orientation of the device if necessary.
+25 −1
Original line number Original line Diff line number Diff line
@@ -44,6 +44,7 @@ public class PipSurfaceTransactionHelper implements ConfigurationController.Conf
    private final float[] mTmpFloat9 = new float[9];
    private final float[] mTmpFloat9 = new float[9];
    private final RectF mTmpSourceRectF = new RectF();
    private final RectF mTmpSourceRectF = new RectF();
    private final RectF mTmpDestinationRectF = new RectF();
    private final RectF mTmpDestinationRectF = new RectF();
    private final Rect mTmpDestinationRect = new Rect();


    @Inject
    @Inject
    public PipSurfaceTransactionHelper(Context context, ConfigurationController configController) {
    public PipSurfaceTransactionHelper(Context context, ConfigurationController configController) {
@@ -90,7 +91,30 @@ public class PipSurfaceTransactionHelper implements ConfigurationController.Conf
        mTmpDestinationRectF.set(destinationBounds);
        mTmpDestinationRectF.set(destinationBounds);
        mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
        mTmpTransform.setRectToRect(mTmpSourceRectF, mTmpDestinationRectF, Matrix.ScaleToFit.FILL);
        tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
        tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
                .setPosition(leash, destinationBounds.left, destinationBounds.top);
                .setPosition(leash, mTmpDestinationRectF.left, mTmpDestinationRectF.top);
        return this;
    }

    /**
     * Operates the scale (setMatrix) on a given transaction and leash
     * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
     */
    PipSurfaceTransactionHelper scaleAndCrop(SurfaceControl.Transaction tx, SurfaceControl leash,
            Rect sourceBounds, Rect destinationBounds, Rect insets) {
        mTmpSourceRectF.set(sourceBounds);
        mTmpDestinationRect.set(sourceBounds);
        mTmpDestinationRect.inset(insets);
        // Scale by the shortest edge and offset such that the top/left of the scaled inset source
        // rect aligns with the top/left of the destination bounds
        final float scale = sourceBounds.width() <= sourceBounds.height()
                ? (float) destinationBounds.width() / sourceBounds.width()
                : (float) destinationBounds.height() / sourceBounds.height();
        final float left = destinationBounds.left - insets.left * scale;
        final float top = destinationBounds.top - insets.top * scale;
        mTmpTransform.setScale(scale, scale);
        tx.setMatrix(leash, mTmpTransform, mTmpFloat9)
                .setWindowCrop(leash, mTmpDestinationRect)
                .setPosition(leash, left, top);
        return this;
        return this;
    }
    }


+31 −9
Original line number Original line Diff line number Diff line
@@ -143,8 +143,10 @@ public class PipTaskOrganizer extends TaskOrganizer implements
            case MSG_RESIZE_ANIMATE: {
            case MSG_RESIZE_ANIMATE: {
                Rect currentBounds = (Rect) args.arg2;
                Rect currentBounds = (Rect) args.arg2;
                Rect toBounds = (Rect) args.arg3;
                Rect toBounds = (Rect) args.arg3;
                Rect sourceHintRect = (Rect) args.arg4;
                int duration = args.argi2;
                int duration = args.argi2;
                animateResizePip(currentBounds, toBounds, args.argi1 /* direction */, duration);
                animateResizePip(currentBounds, toBounds, sourceHintRect,
                        args.argi1 /* direction */, duration);
                if (updateBoundsCallback != null) {
                if (updateBoundsCallback != null) {
                    updateBoundsCallback.accept(toBounds);
                    updateBoundsCallback.accept(toBounds);
                }
                }
@@ -307,7 +309,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
                public void onTransactionReady(int id, SurfaceControl.Transaction t) {
                public void onTransactionReady(int id, SurfaceControl.Transaction t) {
                    t.apply();
                    t.apply();
                    scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
                    scheduleAnimateResizePip(mLastReportedBounds, destinationBounds,
                            direction, animationDurationMs, null /* updateBoundsCallback */);
                            null /* sourceHintRect */, direction, animationDurationMs,
                            null /* updateBoundsCallback */);
                    mInPip = false;
                    mInPip = false;
                }
                }
            });
            });
@@ -380,7 +383,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
        final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();
        final Rect currentBounds = mTaskInfo.configuration.windowConfiguration.getBounds();


        if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
        if (mOneShotAnimationType == ANIM_TYPE_BOUNDS) {
            scheduleAnimateResizePip(currentBounds, destinationBounds,
            final Rect sourceHintRect = getValidSourceHintRect(info, currentBounds);
            scheduleAnimateResizePip(currentBounds, destinationBounds, sourceHintRect,
                    TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
                    TRANSITION_DIRECTION_TO_PIP, mEnterExitAnimationDuration,
                    null /* updateBoundsCallback */);
                    null /* updateBoundsCallback */);
        } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
        } else if (mOneShotAnimationType == ANIM_TYPE_ALPHA) {
@@ -391,6 +395,21 @@ public class PipTaskOrganizer extends TaskOrganizer implements
        }
        }
    }
    }


    /**
     * Returns the source hint rect if it is valid (if provided and is contained by the current
     * task bounds).
     */
    private Rect getValidSourceHintRect(ActivityManager.RunningTaskInfo info, Rect sourceBounds) {
        final Rect sourceHintRect = info.pictureInPictureParams != null
                && info.pictureInPictureParams.hasSourceBoundsHint()
                ? info.pictureInPictureParams.getSourceRectHint()
                : null;
        if (sourceHintRect != null && sourceBounds.contains(sourceHintRect)) {
            return sourceHintRect;
        }
        return null;
    }

    private void enterPipWithAlphaAnimation(Rect destinationBounds, long durationMs) {
    private void enterPipWithAlphaAnimation(Rect destinationBounds, long durationMs) {
        // If we are fading the PIP in, then we should move the pip to the final location as
        // If we are fading the PIP in, then we should move the pip to the final location as
        // soon as possible, but set the alpha immediately since the transaction can take a
        // soon as possible, but set the alpha immediately since the transaction can take a
@@ -611,13 +630,13 @@ public class PipTaskOrganizer extends TaskOrganizer implements
            Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
            Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
            return;
            return;
        }
        }
        scheduleAnimateResizePip(mLastReportedBounds, toBounds,
        scheduleAnimateResizePip(mLastReportedBounds, toBounds, null /* sourceHintRect */,
                TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
                TRANSITION_DIRECTION_NONE, duration, updateBoundsCallback);
    }
    }


    private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
    private void scheduleAnimateResizePip(Rect currentBounds, Rect destinationBounds,
            @PipAnimationController.TransitionDirection int direction, int durationMs,
            Rect sourceHintRect, @PipAnimationController.TransitionDirection int direction,
            Consumer<Rect> updateBoundsCallback) {
            int durationMs, Consumer<Rect> updateBoundsCallback) {
        if (!mInPip) {
        if (!mInPip) {
            // TODO: tend to use shouldBlockResizeRequest here as well but need to consider
            // TODO: tend to use shouldBlockResizeRequest here as well but need to consider
            // the fact that when in exitPip, scheduleAnimateResizePip is executed in the window
            // the fact that when in exitPip, scheduleAnimateResizePip is executed in the window
@@ -629,6 +648,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
        args.arg1 = updateBoundsCallback;
        args.arg1 = updateBoundsCallback;
        args.arg2 = currentBounds;
        args.arg2 = currentBounds;
        args.arg3 = destinationBounds;
        args.arg3 = destinationBounds;
        args.arg4 = sourceHintRect;
        args.argi1 = direction;
        args.argi1 = direction;
        args.argi2 = durationMs;
        args.argi2 = durationMs;
        mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_ANIMATE, args));
        mUpdateHandler.sendMessage(mUpdateHandler.obtainMessage(MSG_RESIZE_ANIMATE, args));
@@ -732,7 +752,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
        }
        }
        final Rect destinationBounds = new Rect(originalBounds);
        final Rect destinationBounds = new Rect(originalBounds);
        destinationBounds.offset(xOffset, yOffset);
        destinationBounds.offset(xOffset, yOffset);
        animateResizePip(originalBounds, destinationBounds, TRANSITION_DIRECTION_SAME, durationMs);
        animateResizePip(originalBounds, destinationBounds, null /* sourceHintRect */,
                TRANSITION_DIRECTION_SAME, durationMs);
    }
    }


    private void resizePip(Rect destinationBounds) {
    private void resizePip(Rect destinationBounds) {
@@ -838,7 +859,8 @@ public class PipTaskOrganizer extends TaskOrganizer implements
        return WINDOWING_MODE_UNDEFINED;
        return WINDOWING_MODE_UNDEFINED;
    }
    }


    private void animateResizePip(Rect currentBounds, Rect destinationBounds,

    private void animateResizePip(Rect currentBounds, Rect destinationBounds, Rect sourceHintRect,
            @PipAnimationController.TransitionDirection int direction, int durationMs) {
            @PipAnimationController.TransitionDirection int direction, int durationMs) {
        if (Looper.myLooper() != mUpdateHandler.getLooper()) {
        if (Looper.myLooper() != mUpdateHandler.getLooper()) {
            throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
            throw new RuntimeException("Callers should call scheduleAnimateResizePip() instead of "
@@ -850,7 +872,7 @@ public class PipTaskOrganizer extends TaskOrganizer implements
            return;
            return;
        }
        }
        mPipAnimationController
        mPipAnimationController
                .getAnimator(mLeash, currentBounds, destinationBounds)
                .getAnimator(mLeash, currentBounds, destinationBounds, sourceHintRect)
                .setTransitionDirection(direction)
                .setTransitionDirection(direction)
                .setPipAnimationCallback(mPipAnimationCallback)
                .setPipAnimationCallback(mPipAnimationCallback)
                .setDuration(durationMs)
                .setDuration(durationMs)
+3 −1
Original line number Original line Diff line number Diff line
@@ -96,7 +96,9 @@ public class PipManager implements BasePipManager, PipTaskOrganizer.PipTransitio
    private final DisplayChangeController.OnDisplayChangingListener mRotationController = (
    private final DisplayChangeController.OnDisplayChangingListener mRotationController = (
            int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> {
            int displayId, int fromRotation, int toRotation, WindowContainerTransaction t) -> {
        if (!mPipTaskOrganizer.isInPip() || mPipTaskOrganizer.isDeferringEnterPipAnimation()) {
        if (!mPipTaskOrganizer.isInPip() || mPipTaskOrganizer.isDeferringEnterPipAnimation()) {
            // Skip if we aren't in PIP or haven't actually entered PIP yet
            // Skip if we aren't in PIP or haven't actually entered PIP yet. We still need to update
            // the display layout in the bounds handler in this case.
            mPipBoundsHandler.onDisplayRotationChangedNotInPip(toRotation);
            return;
            return;
        }
        }
        // If there is an animation running (ie. from a shelf offset), then ensure that we calculate
        // If there is an animation running (ie. from a shelf offset), then ensure that we calculate
Loading