From 4f3deb875f42f9c196ff183446bbfa7f6ef56c8e Mon Sep 17 00:00:00 2001 From: Chris Li Date: Thu, 9 Feb 2023 17:09:34 +0800 Subject: [PATCH] Set starting frame to startTransaction for ActivityEmbedding transition Before, the first frame is set later when the animation starts, which can have a flicker between the startTransaction.apply(). Fix: 268309880 Test: deflaky the OpenActivityEmbeddingSecondaryToSplitTest Change-Id: Iedeb91295ec365e9a82f5b06539d07745ff6d699 --- .../ActivityEmbeddingAnimationAdapter.java | 21 +++++++++---------- .../ActivityEmbeddingAnimationRunner.java | 12 +++++++++++ 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java index 00b9fcede4cad..579f7aae9321a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationAdapter.java @@ -22,7 +22,6 @@ import static android.graphics.Matrix.MTRANS_Y; import android.annotation.CallSuper; import android.graphics.Point; import android.graphics.Rect; -import android.view.Choreographer; import android.view.SurfaceControl; import android.view.animation.Animation; import android.view.animation.Transformation; @@ -71,7 +70,6 @@ class ActivityEmbeddingAnimationAdapter { final float[] mVecs = new float[4]; @NonNull final Rect mRect = new Rect(); - private boolean mIsFirstFrame = true; private int mOverrideLayer = LAYER_NO_OVERRIDE; ActivityEmbeddingAnimationAdapter(@NonNull Animation animation, @@ -117,20 +115,21 @@ class ActivityEmbeddingAnimationAdapter { mOverrideLayer = layer; } + /** Called to prepare for the starting state. */ + final void prepareForFirstFrame(@NonNull SurfaceControl.Transaction startTransaction) { + startTransaction.show(mLeash); + if (mOverrideLayer != LAYER_NO_OVERRIDE) { + startTransaction.setLayer(mLeash, mOverrideLayer); + } + mAnimation.getTransformationAt(0, mTransformation); + onAnimationUpdateInner(startTransaction); + } + /** Called on frame update. */ final void onAnimationUpdate(@NonNull SurfaceControl.Transaction t, long currentPlayTime) { - if (mIsFirstFrame) { - t.show(mLeash); - if (mOverrideLayer != LAYER_NO_OVERRIDE) { - t.setLayer(mLeash, mOverrideLayer); - } - mIsFirstFrame = false; - } - // Extract the transformation to the current time. mAnimation.getTransformation(Math.min(currentPlayTime, mAnimation.getDuration()), mTransformation); - t.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId()); onAnimationUpdateInner(t); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java index 164d2f149931f..fe3c4ea3fee9f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/activityembedding/ActivityEmbeddingAnimationRunner.java @@ -32,6 +32,7 @@ import android.graphics.Rect; import android.os.IBinder; import android.util.ArraySet; import android.util.Log; +import android.view.Choreographer; import android.view.SurfaceControl; import android.view.animation.Animation; import android.window.TransitionInfo; @@ -130,11 +131,13 @@ class ActivityEmbeddingAnimationRunner { animator.addUpdateListener((anim) -> { // Update all adapters in the same transaction. final SurfaceControl.Transaction t = new SurfaceControl.Transaction(); + t.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId()); for (ActivityEmbeddingAnimationAdapter adapter : adapters) { adapter.onAnimationUpdate(t, animator.getCurrentPlayTime()); } t.apply(); }); + prepareForFirstFrame(startTransaction, adapters); } animator.setDuration(duration); animator.addListener(new Animator.AnimatorListener() { @@ -248,6 +251,15 @@ class ActivityEmbeddingAnimationRunner { return adapters; } + /** Sets the first frame to the {@code startTransaction} to avoid any flicker on start. */ + private void prepareForFirstFrame(@NonNull SurfaceControl.Transaction startTransaction, + @NonNull List adapters) { + startTransaction.setFrameTimelineVsync(Choreographer.getInstance().getVsyncId()); + for (ActivityEmbeddingAnimationAdapter adapter : adapters) { + adapter.prepareForFirstFrame(startTransaction); + } + } + /** Adds edge extension to the surfaces that have such an animation property. */ private void addEdgeExtensionIfNeeded(@NonNull SurfaceControl.Transaction startTransaction, @NonNull SurfaceControl.Transaction finishTransaction,