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

Commit 5fa687dd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add transition when swiping from fullscreen to enter PiP"

parents 618ba37e 0f6b6cc7
Loading
Loading
Loading
Loading
+17 −3
Original line number Diff line number Diff line
@@ -15,6 +15,9 @@
 */
package com.android.quickstep;

import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.widget.Toast.LENGTH_SHORT;

import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
@@ -1065,7 +1068,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
                            runningTaskTarget.pictureInPictureParams) != null;
            if (mIsSwipingPipToHome) {
                mSwipePipToHomeAnimator = getSwipePipToHomeAnimator(
                        homeAnimFactory, runningTaskTarget);
                        homeAnimFactory, runningTaskTarget, start);
                mSwipePipToHomeAnimator.setDuration(SWIPE_PIP_TO_HOME_DURATION);
                mSwipePipToHomeAnimator.setInterpolator(interpolator);
                mSwipePipToHomeAnimator.setFloatValues(0f, 1f);
@@ -1135,23 +1138,34 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
    }

    private SwipePipToHomeAnimator getSwipePipToHomeAnimator(HomeAnimationFactory homeAnimFactory,
            RemoteAnimationTargetCompat runningTaskTarget) {
            RemoteAnimationTargetCompat runningTaskTarget, float startProgress) {
        // Directly animate the app to PiP (picture-in-picture) mode
        final ActivityManager.RunningTaskInfo taskInfo = mGestureState.getRunningTask();
        final RecentsOrientedState orientationState = mTaskViewSimulator.getOrientationState();
        final int windowRotation = orientationState.getDisplayRotation();
        final int homeRotation = orientationState.getRecentsActivityRotation();
        final Rect destinationBounds = SystemUiProxy.INSTANCE.get(mContext)
                .startSwipePipToHome(taskInfo.topActivity,
                        TaskInfoCompat.getTopActivityInfo(taskInfo),
                        runningTaskTarget.pictureInPictureParams,
                        orientationState.getRecentsActivityRotation(),
                        homeRotation,
                        mDp.hotseatBarSizePx);
        final Rect startBounds = new Rect();
        updateProgressForStartRect(new Matrix(), startProgress).round(startBounds);
        final SwipePipToHomeAnimator swipePipToHomeAnimator = new SwipePipToHomeAnimator(
                runningTaskTarget.taskId,
                taskInfo.topActivity,
                runningTaskTarget.leash.getSurfaceControl(),
                TaskInfoCompat.getPipSourceRectHint(runningTaskTarget.pictureInPictureParams),
                TaskInfoCompat.getWindowConfigurationBounds(taskInfo),
                startBounds,
                destinationBounds);
        // We would assume home and app window always in the same rotation While homeRotation
        // is not ROTATION_0 (which implies the rotation is turned on in launcher settings).
        if (homeRotation == ROTATION_0
                && (windowRotation == ROTATION_90 || windowRotation == ROTATION_270)) {
            swipePipToHomeAnimator.setFromRotation(mTaskViewSimulator, windowRotation);
        }
        swipePipToHomeAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationStart(Animator animation) {
+21 −8
Original line number Diff line number Diff line
@@ -174,6 +174,24 @@ public abstract class SwipeUpAnimationLogic {
        }
    }

    /**
     * Update with start progress for window animation to home.
     * @param outMatrix {@link Matrix} to map a rect in Launcher space to window space.
     * @param startProgress The progress of {@link #mCurrentShift} to start thw window from.
     * @return {@link RectF} represents the bounds as starting point in window space.
     */
    protected RectF updateProgressForStartRect(Matrix outMatrix, float startProgress) {
        mCurrentShift.updateValue(startProgress);
        mTaskViewSimulator.apply(mTransformParams.setProgress(startProgress));
        RectF cropRectF = new RectF(mTaskViewSimulator.getCurrentCropRect());

        mTaskViewSimulator.applyWindowToHomeRotation(outMatrix);

        final RectF startRect = new RectF(cropRectF);
        mTaskViewSimulator.getCurrentMatrix().mapRect(startRect);
        return startRect;
    }

    /**
     * Creates an animation that transforms the current app window into the home app.
     * @param startProgress The progress of {@link #mCurrentShift} to start the window from.
@@ -183,16 +201,11 @@ public abstract class SwipeUpAnimationLogic {
            HomeAnimationFactory homeAnimationFactory) {
        final RectF targetRect = homeAnimationFactory.getWindowTargetRect();

        mCurrentShift.updateValue(startProgress);
        mTaskViewSimulator.apply(mTransformParams.setProgress(startProgress));
        RectF cropRectF = new RectF(mTaskViewSimulator.getCurrentCropRect());

        // Matrix to map a rect in Launcher space to window space
        Matrix homeToWindowPositionMap = new Matrix();
        mTaskViewSimulator.applyWindowToHomeRotation(homeToWindowPositionMap);
        final RectF startRect = updateProgressForStartRect(
                homeToWindowPositionMap, startProgress);
        RectF cropRectF = new RectF(mTaskViewSimulator.getCurrentCropRect());

        final RectF startRect = new RectF(cropRectF);
        mTaskViewSimulator.getCurrentMatrix().mapRect(startRect);
        // Move the startRect to Launcher space as floatingIconView runs in Launcher
        Matrix windowToHomePositionMap = new Matrix();
        homeToWindowPositionMap.invert(windowToHomePositionMap);
+84 −9
Original line number Diff line number Diff line
@@ -22,7 +22,11 @@ import android.animation.Animator;
import android.animation.RectEvaluator;
import android.animation.ValueAnimator;
import android.content.ComponentName;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceControl;

import androidx.annotation.NonNull;
@@ -42,9 +46,12 @@ import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
 */
public class SwipePipToHomeAnimator extends ValueAnimator implements
        ValueAnimator.AnimatorUpdateListener {
    private static final String TAG = SwipePipToHomeAnimator.class.getSimpleName();

    private final int mTaskId;
    private final ComponentName mComponentName;
    private final SurfaceControl mLeash;
    private final Rect mAppBounds = new Rect();
    private final Rect mStartBounds = new Rect();
    private final Rect mDestinationBounds = new Rect();
    private final PipSurfaceTransactionHelper mSurfaceTransactionHelper;
@@ -55,29 +62,50 @@ public class SwipePipToHomeAnimator extends ValueAnimator implements
    private final Rect mSourceHintRectInsets = new Rect();
    private final Rect mSourceInsets = new Rect();

    /** for rotation via {@link #setFromRotation(TaskViewSimulator, int)} */
    private @RecentsOrientedState.SurfaceRotation int mFromRotation = Surface.ROTATION_0;
    private final Rect mDestinationBoundsTransformed = new Rect();
    private final Rect mDestinationBoundsAnimation = new Rect();

    /**
     * Flag to avoid the double-end problem since the leash would have been released
     * after the first end call and any further operations upon it would lead to NPE.
     */
    private boolean mHasAnimationEnded;

    /**
     * @param taskId Task id associated with this animator, see also {@link #getTaskId()}
     * @param componentName Component associated with this animator,
     *                      see also {@link #getComponentName()}
     * @param leash {@link SurfaceControl} this animator operates on
     * @param sourceRectHint See the definition in {@link android.app.PictureInPictureParams}
     * @param appBounds Bounds of the application, sourceRectHint is based on this bounds
     * @param startBounds Bounds of the application when this animator starts. This can be
     *                    different from the appBounds if user has swiped a certain distance and
     *                    Launcher has performed transform on the leash.
     * @param destinationBounds Bounds of the destination this animator ends to
     */
    public SwipePipToHomeAnimator(int taskId,
            @NonNull ComponentName componentName,
            @NonNull SurfaceControl leash,
            @NonNull Rect sourceRectHint,
            @NonNull Rect appBounds,
            @NonNull Rect startBounds,
            @NonNull Rect destinationBounds) {
        mTaskId = taskId;
        mComponentName = componentName;
        mLeash = leash;
        mAppBounds.set(appBounds);
        mStartBounds.set(startBounds);
        mDestinationBounds.set(destinationBounds);
        mDestinationBoundsTransformed.set(mDestinationBounds);
        mDestinationBoundsAnimation.set(mDestinationBounds);
        mSurfaceTransactionHelper = new PipSurfaceTransactionHelper();

        mSourceHintRectInsets.set(sourceRectHint.left - startBounds.left,
                sourceRectHint.top - startBounds.top,
                startBounds.right - sourceRectHint.right,
                startBounds.bottom - sourceRectHint.bottom);
        mSourceHintRectInsets.set(sourceRectHint.left - appBounds.left,
                sourceRectHint.top - appBounds.top,
                appBounds.right - sourceRectHint.right,
                appBounds.bottom - sourceRectHint.bottom);

        addListener(new AnimationSuccessListener() {
            @Override
@@ -106,16 +134,62 @@ public class SwipePipToHomeAnimator extends ValueAnimator implements
        addUpdateListener(this);
    }

    /** sets the from rotation if it's different from the target rotation. */
    public void setFromRotation(TaskViewSimulator taskViewSimulator,
            @RecentsOrientedState.SurfaceRotation int fromRotation) {
        if (fromRotation != Surface.ROTATION_90 && fromRotation != Surface.ROTATION_270) {
            Log.wtf(TAG, "Not a supported rotation, rotation=" + fromRotation);
            return;
        }
        mFromRotation = fromRotation;
        final Matrix matrix = new Matrix();
        taskViewSimulator.applyWindowToHomeRotation(matrix);

        // map the destination bounds into window space. mDestinationBounds is always calculated
        // in the final home space and the animation runs in original window space.
        final RectF transformed = new RectF(mDestinationBounds);
        matrix.mapRect(transformed, new RectF(mDestinationBounds));
        transformed.round(mDestinationBoundsTransformed);

        // set the animation destination bounds for RectEvaluator calculation.
        // bounds and insets are calculated as if the transition is from mAppBounds to
        // mDestinationBoundsAnimation, separated from rotate / scale / position.
        mDestinationBoundsAnimation.set(mAppBounds.left, mAppBounds.top,
                mAppBounds.left + mDestinationBounds.width(),
                mAppBounds.top + mDestinationBounds.height());
    }

    @Override
    public void onAnimationUpdate(ValueAnimator animator) {
        if (mHasAnimationEnded) return;

        final float fraction = animator.getAnimatedFraction();
        final Rect bounds = mRectEvaluator.evaluate(fraction, mStartBounds, mDestinationBounds);
        final Rect bounds = mRectEvaluator.evaluate(fraction, mStartBounds,
                mDestinationBoundsAnimation);
        final Rect insets = mInsetsEvaluator.evaluate(fraction, mSourceInsets,
                mSourceHintRectInsets);
        final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
        mSurfaceTransactionHelper.scaleAndCrop(tx, mLeash, mStartBounds, bounds, insets);
        final SurfaceControl.Transaction tx =
                PipSurfaceTransactionHelper.newSurfaceControlTransaction();
        if (mFromRotation == Surface.ROTATION_90 || mFromRotation == Surface.ROTATION_270) {
            final float degree, positionX, positionY;
            if (mFromRotation == Surface.ROTATION_90) {
                degree = -90 * fraction;
                positionX = fraction * (mDestinationBoundsTransformed.left - mAppBounds.left)
                        + mAppBounds.left;
                positionY = fraction * (mDestinationBoundsTransformed.bottom - mAppBounds.top)
                        + mAppBounds.top;
            } else {
                degree = 90 * fraction;
                positionX = fraction * (mDestinationBoundsTransformed.right - mAppBounds.left)
                        + mAppBounds.left;
                positionY = fraction * (mDestinationBoundsTransformed.top - mAppBounds.top)
                        + mAppBounds.top;
            }
            mSurfaceTransactionHelper.scaleAndRotate(tx, mLeash, mAppBounds, bounds, insets,
                    degree, positionX, positionY);
        } else {
            mSurfaceTransactionHelper.scaleAndCrop(tx, mLeash, mAppBounds, bounds, insets);
        }
        mSurfaceTransactionHelper.resetCornerRadius(tx, mLeash);
        tx.apply();
    }
@@ -135,8 +209,9 @@ public class SwipePipToHomeAnimator extends ValueAnimator implements
    private void onAnimationEnd() {
        if (mHasAnimationEnded) return;

        final SurfaceControl.Transaction tx = new SurfaceControl.Transaction();
        mSurfaceTransactionHelper.reset(tx, mLeash, mDestinationBounds);
        final SurfaceControl.Transaction tx =
                PipSurfaceTransactionHelper.newSurfaceControlTransaction();
        mSurfaceTransactionHelper.reset(tx, mLeash, mDestinationBoundsTransformed, mFromRotation);
        tx.apply();
        mHasAnimationEnded = true;
    }