diff options
| author | 2024-07-10 16:02:25 +0000 | |
|---|---|---|
| committer | 2024-07-18 23:01:39 +0000 | |
| commit | cc7d47adacae5a3d4522d759721a03ef4c6b51fe (patch) | |
| tree | d1f2529fc4be1230e5a2feeefa487a0e8a09e22f | |
| parent | 3afcb7c0fdefba546da875f3f56b3b9a27fe1a8c (diff) | |
[PIP2] Add bounds animator for enter/exit pip
Adds bounds animator for entering and exiting pip. This currently
implements the basic portrait case, and a follow up CL will add
rotation.
Test: manual check
Flag: com.android.wm.shell.enable_pip2_implementation
Bug: b/350801661
Change-Id: Ib570f7fa4f29cf6aa303e5c23fed7de7ffc63b6d
| -rw-r--r-- | libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipEnterExitAnimator.java | 150 | ||||
| -rw-r--r-- | libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java | 54 |
2 files changed, 196 insertions, 8 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipEnterExitAnimator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipEnterExitAnimator.java new file mode 100644 index 000000000000..8a9302bcfc98 --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/animation/PipEnterExitAnimator.java @@ -0,0 +1,150 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.wm.shell.pip2.animation; + +import android.animation.Animator; +import android.animation.RectEvaluator; +import android.animation.ValueAnimator; +import android.annotation.IntDef; +import android.content.Context; +import android.graphics.Rect; +import android.view.SurfaceControl; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import com.android.wm.shell.R; +import com.android.wm.shell.pip2.PipSurfaceTransactionHelper; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Animator that handles bounds animations for entering / exiting PIP. + */ +public class PipEnterExitAnimator extends ValueAnimator + implements ValueAnimator.AnimatorUpdateListener, ValueAnimator.AnimatorListener { + @IntDef(prefix = {"BOUNDS_"}, value = { + BOUNDS_ENTER, + BOUNDS_EXIT + }) + + @Retention(RetentionPolicy.SOURCE) + public @interface BOUNDS {} + + public static final int BOUNDS_ENTER = 0; + public static final int BOUNDS_EXIT = 1; + + @NonNull private final SurfaceControl mLeash; + private final SurfaceControl.Transaction mStartTransaction; + private final int mEnterAnimationDuration; + private final @BOUNDS int mDirection; + + // optional callbacks for tracking animation start and end + @Nullable private Runnable mAnimationStartCallback; + @Nullable private Runnable mAnimationEndCallback; + + private final Rect mBaseBounds = new Rect(); + private final Rect mStartBounds = new Rect(); + private final Rect mEndBounds = new Rect(); + + // Bounds updated by the evaluator as animator is running. + private final Rect mAnimatedRect = new Rect(); + + private final PipSurfaceTransactionHelper.SurfaceControlTransactionFactory + mSurfaceControlTransactionFactory; + private final RectEvaluator mRectEvaluator; + private final PipSurfaceTransactionHelper mPipSurfaceTransactionHelper; + + public PipEnterExitAnimator(Context context, + @NonNull SurfaceControl leash, + SurfaceControl.Transaction startTransaction, + @NonNull Rect baseBounds, + @NonNull Rect startBounds, + @NonNull Rect endBounds, + @BOUNDS int direction) { + mLeash = leash; + mStartTransaction = startTransaction; + mBaseBounds.set(baseBounds); + mStartBounds.set(startBounds); + mAnimatedRect.set(startBounds); + mEndBounds.set(endBounds); + mRectEvaluator = new RectEvaluator(mAnimatedRect); + mPipSurfaceTransactionHelper = new PipSurfaceTransactionHelper(context); + mDirection = direction; + + mSurfaceControlTransactionFactory = + new PipSurfaceTransactionHelper.VsyncSurfaceControlTransactionFactory(); + mEnterAnimationDuration = context.getResources() + .getInteger(R.integer.config_pipEnterAnimationDuration); + + setDuration(mEnterAnimationDuration); + setEvaluator(mRectEvaluator); + addListener(this); + addUpdateListener(this); + } + + public void setAnimationStartCallback(@NonNull Runnable runnable) { + mAnimationStartCallback = runnable; + } + + public void setAnimationEndCallback(@NonNull Runnable runnable) { + mAnimationEndCallback = runnable; + } + + @Override + public void onAnimationStart(@NonNull Animator animation) { + if (mAnimationStartCallback != null) { + mAnimationStartCallback.run(); + } + if (mStartTransaction != null) { + mStartTransaction.apply(); + } + } + + @Override + public void onAnimationEnd(@NonNull Animator animation) { + if (mAnimationEndCallback != null) { + mAnimationEndCallback.run(); + } + } + + @Override + public void onAnimationUpdate(@NonNull ValueAnimator animation) { + final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction(); + final float fraction = getAnimatedFraction(); + // TODO (b/350801661): implement fixed rotation + + mPipSurfaceTransactionHelper.scaleAndCrop(tx, mLeash, null, + mBaseBounds, mAnimatedRect, null, isInPipDirection(), fraction) + .round(tx, mLeash, isInPipDirection()) + .shadow(tx, mLeash, isInPipDirection()); + tx.apply(); + } + + private boolean isInPipDirection() { + return mDirection == BOUNDS_ENTER; + } + + // no-ops + + @Override + public void onAnimationCancel(@NonNull Animator animation) {} + + @Override + public void onAnimationRepeat(@NonNull Animator animation) {} +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java index 683d30d59b33..33703ad95a9c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTransition.java @@ -53,6 +53,7 @@ import com.android.wm.shell.common.pip.PipUtils; import com.android.wm.shell.pip.PipContentOverlay; import com.android.wm.shell.pip.PipTransitionController; import com.android.wm.shell.pip2.animation.PipAlphaAnimator; +import com.android.wm.shell.pip2.animation.PipEnterExitAnimator; import com.android.wm.shell.sysui.ShellInit; import com.android.wm.shell.transition.Transitions; @@ -378,12 +379,34 @@ public class PipTransition extends PipTransitionController implements if (pipChange == null) { return false; } - // cache the PiP task token and leash + WindowContainerToken pipTaskToken = pipChange.getContainer(); + if (pipTaskToken == null) { + return false; + } - startTransaction.apply(); - // TODO: b/275910498 Use a new implementation of the PiP animator here. - finishCallback.onTransitionFinished(null); + WindowContainerTransaction finishWct = new WindowContainerTransaction(); + SurfaceControl.Transaction tx = new SurfaceControl.Transaction(); + + Rect startBounds = pipChange.getStartAbsBounds(); + Rect endBounds = pipChange.getEndAbsBounds(); + SurfaceControl pipLeash = mPipTransitionState.mPinnedTaskLeash; + Preconditions.checkNotNull(pipLeash, "Leash is null for bounds transition."); + + PipEnterExitAnimator animator = new PipEnterExitAnimator(mContext, pipLeash, + startTransaction, startBounds, startBounds, endBounds, + PipEnterExitAnimator.BOUNDS_ENTER); + + tx.addTransactionCommittedListener(mPipScheduler.getMainExecutor(), + this::onClientDrawAtTransitionEnd); + finishWct.setBoundsChangeTransaction(pipTaskToken, tx); + + animator.setAnimationEndCallback(() -> { + mPipTransitionState.setState(PipTransitionState.ENTERED_PIP); + finishCallback.onTransitionFinished(finishWct.isEmpty() ? null : finishWct); + }); + + animator.start(); return true; } @@ -421,10 +444,25 @@ public class PipTransition extends PipTransitionController implements @NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction, @NonNull Transitions.TransitionFinishCallback finishCallback) { - startTransaction.apply(); - // TODO: b/275910498 Use a new implementation of the PiP animator here. - finishCallback.onTransitionFinished(null); - mPipTransitionState.setState(PipTransitionState.EXITED_PIP); + TransitionInfo.Change pipChange = getPipChange(info); + if (pipChange == null) { + return false; + } + + Rect startBounds = pipChange.getStartAbsBounds(); + Rect endBounds = pipChange.getEndAbsBounds(); + SurfaceControl pipLeash = mPipTransitionState.mPinnedTaskLeash; + Preconditions.checkNotNull(pipLeash, "Leash is null for bounds transition."); + + PipEnterExitAnimator animator = new PipEnterExitAnimator(mContext, pipLeash, + startTransaction, startBounds, startBounds, endBounds, + PipEnterExitAnimator.BOUNDS_EXIT); + animator.setAnimationEndCallback(() -> { + finishCallback.onTransitionFinished(null); + mPipTransitionState.setState(PipTransitionState.EXITED_PIP); + }); + + animator.start(); return true; } |