Implement merge animations for AE Shell animation.

Fixes: 280196874
Bug: 281576532
Test: atest

Change-Id: I7af2c4c9d8f9783b46b6074667565527b2a00297
This commit is contained in:
An An Yu
2023-05-10 04:19:57 +00:00
parent c6b780a5c0
commit 9ec0670b2f
5 changed files with 74 additions and 4 deletions

View File

@@ -61,6 +61,9 @@ class ActivityEmbeddingAnimationRunner {
@VisibleForTesting
final ActivityEmbeddingAnimationSpec mAnimationSpec;
@Nullable
private Animator mActiveAnimator;
ActivityEmbeddingAnimationRunner(@NonNull Context context,
@NonNull ActivityEmbeddingController controller) {
mController = controller;
@@ -75,8 +78,10 @@ class ActivityEmbeddingAnimationRunner {
// applied to make sure the surface is ready.
final List<Consumer<SurfaceControl.Transaction>> postStartTransactionCallbacks =
new ArrayList<>();
final Animator animator = createAnimator(info, startTransaction, finishTransaction,
final Animator animator = createAnimator(info, startTransaction,
finishTransaction,
() -> mController.onAnimationFinished(transition), postStartTransactionCallbacks);
mActiveAnimator = animator;
// Start the animation.
if (!postStartTransactionCallbacks.isEmpty()) {
@@ -98,6 +103,17 @@ class ActivityEmbeddingAnimationRunner {
}
}
void cancelAnimationFromMerge() {
if (mActiveAnimator == null) {
Log.e(TAG,
"No active ActivityEmbedding animator running but mergeAnimation is "
+ "trying to cancel one."
);
return;
}
mActiveAnimator.end();
}
/**
* Sets transition animation scale settings value.
* @param scale The setting value of transition animation scale.
@@ -153,6 +169,7 @@ class ActivityEmbeddingAnimationRunner {
adapter.onAnimationEnd(t);
}
t.apply();
mActiveAnimator = null;
animationFinishCallback.run();
}

View File

@@ -118,6 +118,13 @@ public class ActivityEmbeddingController implements Transitions.TransitionHandle
return true;
}
@Override
public void mergeAnimation(@NonNull IBinder transition, @NonNull TransitionInfo info,
@NonNull SurfaceControl.Transaction t, @NonNull IBinder mergeTarget,
@NonNull Transitions.TransitionFinishCallback finishCallback) {
mAnimationRunner.cancelAnimationFromMerge();
}
private boolean handleNonEmbeddedChanges(List<TransitionInfo.Change> changes) {
final Rect nonClosingEmbeddedArea = new Rect();
for (int i = changes.size() - 1; i >= 0; i--) {

View File

@@ -65,12 +65,14 @@ public class ActivityEmbeddingAnimationRunnerTests extends ActivityEmbeddingAnim
final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0)
.addChange(createChange(FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY))
.build();
doReturn(mAnimator).when(mAnimRunner).createAnimator(any(), any(), any(), any(), any());
doReturn(mAnimator).when(mAnimRunner).createAnimator(any(), any(), any(), any(),
any());
mAnimRunner.startAnimation(mTransition, info, mStartTransaction, mFinishTransaction);
final ArgumentCaptor<Runnable> finishCallback = ArgumentCaptor.forClass(Runnable.class);
verify(mAnimRunner).createAnimator(eq(info), eq(mStartTransaction), eq(mFinishTransaction),
verify(mAnimRunner).createAnimator(eq(info), eq(mStartTransaction),
eq(mFinishTransaction),
finishCallback.capture(), any());
verify(mStartTransaction).apply();
verify(mAnimator).start();

View File

@@ -47,6 +47,7 @@ abstract class ActivityEmbeddingAnimationTestBase extends ShellTestCase {
@Mock
ShellInit mShellInit;
@Mock
Transitions mTransitions;
@Mock

View File

@@ -29,9 +29,13 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import android.animation.Animator;
import android.animation.ValueAnimator;
import android.graphics.Rect;
import android.view.SurfaceControl;
import android.window.TransitionInfo;
import androidx.test.annotation.UiThreadTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
@@ -58,7 +62,8 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation
@Before
public void setup() {
super.setUp();
doReturn(mAnimator).when(mAnimRunner).createAnimator(any(), any(), any(), any(), any());
doReturn(mAnimator).when(mAnimRunner).createAnimator(any(), any(), any(), any(),
any());
}
@Test
@@ -182,6 +187,44 @@ public class ActivityEmbeddingControllerTests extends ActivityEmbeddingAnimation
verifyNoMoreInteractions(mFinishTransaction);
}
@UiThreadTest
@Test
public void testMergeAnimation() {
final TransitionInfo info = new TransitionInfoBuilder(TRANSIT_OPEN, 0)
.addChange(createEmbeddedChange(
EMBEDDED_LEFT_BOUNDS, EMBEDDED_LEFT_BOUNDS, TASK_BOUNDS))
.build();
final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
mController.onAnimationFinished(mTransition);
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
doReturn(animator).when(mAnimRunner).createAnimator(any(), any(), any(), any(), any());
mController.startAnimation(mTransition, info, mStartTransaction,
mFinishTransaction, mFinishCallback);
verify(mFinishCallback, never()).onTransitionFinished(any(), any());
mController.mergeAnimation(mTransition, info, new SurfaceControl.Transaction(),
mTransition,
(wct, cb) -> {
});
verify(mFinishCallback).onTransitionFinished(any(), any());
}
@Test
public void testOnAnimationFinished() {
// Should not call finish when there is no transition.