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

Commit 0d98528c authored by Jorge Gil's avatar Jorge Gil Committed by Android (Google) Code Review
Browse files

Merge "Add crossfade animation on finish resize"

parents 4fa4dd10 fe0ab242
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -56,6 +56,8 @@ public class PipAnimationController {
    public static final int TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN = 4;
    public static final int TRANSITION_DIRECTION_REMOVE_STACK = 5;
    public static final int TRANSITION_DIRECTION_SNAP_AFTER_RESIZE = 6;
    public static final int TRANSITION_DIRECTION_USER_RESIZE = 7;
    public static final int TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND = 8;

    @IntDef(prefix = { "TRANSITION_DIRECTION_" }, value = {
            TRANSITION_DIRECTION_NONE,
@@ -64,7 +66,9 @@ public class PipAnimationController {
            TRANSITION_DIRECTION_LEAVE_PIP,
            TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN,
            TRANSITION_DIRECTION_REMOVE_STACK,
            TRANSITION_DIRECTION_SNAP_AFTER_RESIZE
            TRANSITION_DIRECTION_SNAP_AFTER_RESIZE,
            TRANSITION_DIRECTION_USER_RESIZE,
            TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND
    })
    @Retention(RetentionPolicy.SOURCE)
    public @interface TransitionDirection {}
+12 −0
Original line number Diff line number Diff line
@@ -151,6 +151,18 @@ public class PipSurfaceTransactionHelper {
        return this;
    }

    /**
     * Re-parents the snapshot to the parent's surface control and shows it.
     */
    public PipSurfaceTransactionHelper reparentAndShowSurfaceSnapshot(
            SurfaceControl.Transaction t, SurfaceControl parent, SurfaceControl snapshot) {
        t.reparent(snapshot, parent);
        t.setLayer(snapshot, Integer.MAX_VALUE);
        t.show(snapshot);
        t.apply();
        return this;
    }

    public interface SurfaceControlTransactionFactory {
        SurfaceControl.Transaction getTransaction();
    }
+79 −4
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import static com.android.wm.shell.ShellTaskOrganizer.TASK_LISTENER_TYPE_PIP;
import static com.android.wm.shell.ShellTaskOrganizer.taskListenerTypeToString;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_BOUNDS;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_LEAVE_PIP_TO_SPLIT_SCREEN;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_NONE;
@@ -32,9 +33,13 @@ import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTI
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_SAME;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_SNAP_AFTER_RESIZE;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_TO_PIP;
import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE;
import static com.android.wm.shell.pip.PipAnimationController.isInPipDirection;
import static com.android.wm.shell.pip.PipAnimationController.isOutPipDirection;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.ActivityManager;
@@ -820,13 +825,22 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
     */
    public void scheduleAnimateResizePip(Rect toBounds, int duration,
            Consumer<Rect> updateBoundsCallback) {
        scheduleAnimateResizePip(toBounds, duration, TRANSITION_DIRECTION_NONE,
                updateBoundsCallback);
    }

    /**
     * Animates resizing of the pinned stack given the duration.
     */
    public void scheduleAnimateResizePip(Rect toBounds, int duration,
            @PipAnimationController.TransitionDirection int direction,
            Consumer<Rect> updateBoundsCallback) {
        if (mWaitForFixedRotation) {
            Log.d(TAG, "skip scheduleAnimateResizePip, entering pip deferred");
            return;
        }
        scheduleAnimateResizePip(mPipBoundsState.getBounds(), toBounds, 0 /* startingAngle */,
                null /* sourceHintRect */, TRANSITION_DIRECTION_NONE, duration,
                updateBoundsCallback);
                null /* sourceHintRect */, direction, duration, updateBoundsCallback);
    }

    /**
@@ -919,7 +933,15 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,
        scheduleFinishResizePip(destinationBounds, TRANSITION_DIRECTION_NONE, updateBoundsCallback);
    }

    private void scheduleFinishResizePip(Rect destinationBounds,
    /**
     * Finish an intermediate resize operation. This is expected to be called after
     * {@link #scheduleResizePip}.
     *
     * @param destinationBounds the final bounds of the PIP after resizing
     * @param direction the transition direction
     * @param updateBoundsCallback a callback to invoke after finishing the resize
     */
    public void scheduleFinishResizePip(Rect destinationBounds,
            @PipAnimationController.TransitionDirection int direction,
            Consumer<Rect> updateBoundsCallback) {
        if (mState.shouldBlockResizeRequest()) {
@@ -1049,7 +1071,60 @@ public class PipTaskOrganizer implements ShellTaskOrganizer.TaskListener,

        WindowContainerTransaction wct = new WindowContainerTransaction();
        prepareFinishResizeTransaction(destinationBounds, direction, tx, wct);

        // Only corner drag, pinch or expand/un-expand resizing may lead to animating the finish
        // resize operation.
        final boolean mayAnimateFinishResize = direction == TRANSITION_DIRECTION_USER_RESIZE
                || direction == TRANSITION_DIRECTION_SNAP_AFTER_RESIZE
                || direction == TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND;
        // Animate with a cross-fade if enabled and seamless resize is disables by the app.
        final boolean animateCrossFadeResize = mayAnimateFinishResize
                && !mPictureInPictureParams.isSeamlessResizeEnabled();
        if (animateCrossFadeResize) {
            // Take a snapshot of the PIP task and hide it. We'll show it and fade it out after
            // the wct transaction is applied and the activity is laid out again.
            final SurfaceControl snapshotSurface = mTaskOrganizer.takeScreenshot(mToken);
            mSurfaceTransactionHelper.reparentAndShowSurfaceSnapshot(
                    mSurfaceControlTransactionFactory.getTransaction(), mLeash, snapshotSurface);
            mTaskOrganizer.applySyncTransaction(wct, new WindowContainerTransactionCallback() {
                @Override
                public void onTransactionReady(int id, @NonNull SurfaceControl.Transaction t) {
                    // Scale the snapshot from its pre-resize bounds to the post-resize bounds.
                    final Rect snapshotSrc = new Rect(0, 0, snapshotSurface.getWidth(),
                            snapshotSurface.getHeight());
                    final Rect snapshotDest = new Rect(0, 0, destinationBounds.width(),
                            destinationBounds.height());
                    mSurfaceTransactionHelper.scale(t, snapshotSurface, snapshotSrc, snapshotDest);
                    t.apply();

                    mUpdateHandler.post(() -> {
                        // Start animation to fade out the snapshot.
                        final ValueAnimator animator = ValueAnimator.ofFloat(1.0f, 0.0f);
                        animator.setDuration(mEnterExitAnimationDuration);
                        animator.addUpdateListener(animation -> {
                            final float alpha = (float) animation.getAnimatedValue();
                            final SurfaceControl.Transaction tx =
                                    mSurfaceControlTransactionFactory.getTransaction();
                            tx.setAlpha(snapshotSurface, alpha);
                            tx.apply();
                        });
                        animator.addListener(new AnimatorListenerAdapter() {
                            @Override
                            public void onAnimationEnd(Animator animation) {
                                final SurfaceControl.Transaction tx =
                                        mSurfaceControlTransactionFactory.getTransaction();
                                tx.remove(snapshotSurface);
                                tx.apply();
                            }
                        });
                        animator.start();
                    });
                }
            });
        } else {
            applyFinishBoundsResize(wct, direction);
        }

        finishResizeForMenu(destinationBounds);
    }

+3 −1
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.pip.phone;

import static com.android.wm.shell.pip.PipAnimationController.TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND;
import static com.android.wm.shell.pip.PipBoundsState.STASH_TYPE_LEFT;
import static com.android.wm.shell.pip.PipBoundsState.STASH_TYPE_RIGHT;

@@ -624,7 +625,8 @@ public class PipMotionHelper implements PipAppOpsListener.Callback,

        // Intentionally resize here even if the current bounds match the destination bounds.
        // This is so all the proper callbacks are performed.
        mPipTaskOrganizer.scheduleAnimateResizePip(toBounds, duration, mUpdateBoundsCallback);
        mPipTaskOrganizer.scheduleAnimateResizePip(toBounds, duration,
                TRANSITION_DIRECTION_EXPAND_OR_UNEXPAND, mUpdateBoundsCallback);
        setAnimatingToBounds(toBounds);
    }

+2 −0
Original line number Diff line number Diff line
@@ -45,6 +45,7 @@ import androidx.annotation.VisibleForTesting;

import com.android.internal.policy.TaskResizingAlgorithm;
import com.android.wm.shell.R;
import com.android.wm.shell.pip.PipAnimationController;
import com.android.wm.shell.pip.PipBoundsAlgorithm;
import com.android.wm.shell.pip.PipBoundsState;
import com.android.wm.shell.pip.PipTaskOrganizer;
@@ -542,6 +543,7 @@ public class PipResizeGestureHandler {
                        });
            } else {
                mPipTaskOrganizer.scheduleFinishResizePip(mLastResizeBounds,
                        PipAnimationController.TRANSITION_DIRECTION_USER_RESIZE,
                        (Rect bounds) -> {
                            mHandler.post(callback);
                        });