summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/wm/AnimationAdapter.java21
-rw-r--r--services/core/java/com/android/server/wm/SurfaceAnimator.java11
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java71
3 files changed, 102 insertions, 1 deletions
diff --git a/services/core/java/com/android/server/wm/AnimationAdapter.java b/services/core/java/com/android/server/wm/AnimationAdapter.java
index 0519b80c732a..529c4f608743 100644
--- a/services/core/java/com/android/server/wm/AnimationAdapter.java
+++ b/services/core/java/com/android/server/wm/AnimationAdapter.java
@@ -85,4 +85,25 @@ interface AnimationAdapter {
}
void dumpDebug(ProtoOutputStream proto);
+
+ /**
+ * Gets called when the animation is about to finish and gives the client the opportunity to
+ * defer finishing the animation, i.e. it keeps the leash around until the client calls
+ * endDeferFinishCallback.
+ * <p>
+ * This has the same effect as
+ * {@link com.android.server.wm.SurfaceAnimator.Animatable#shouldDeferAnimationFinish(Runnable)}
+ * . The later will be evaluated first and has precedence over this method if it returns true,
+ * which means that if the {@link com.android.server.wm.SurfaceAnimator.Animatable} requests to
+ * defer its finish, this method won't be called so this adapter will never have access to the
+ * finish callback. On the other hand, if the
+ * {@link com.android.server.wm.SurfaceAnimator.Animatable}, doesn't request to defer, this
+ * {@link AnimationAdapter} is responsible for ending the animation.
+ *
+ * @param endDeferFinishCallback The callback to call when defer finishing should be ended.
+ * @return Whether the client would like to defer the animation finish.
+ */
+ default boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimator.java b/services/core/java/com/android/server/wm/SurfaceAnimator.java
index 18e32c0683d6..42342a60ba16 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimator.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimator.java
@@ -109,7 +109,10 @@ class SurfaceAnimator {
animationFinishCallback.onAnimationFinished(type, anim);
}
};
- if (!mAnimatable.shouldDeferAnimationFinish(resetAndInvokeFinish)) {
+ // If both the Animatable and AnimationAdapter requests to be deferred, only the
+ // first one will be called.
+ if (!(mAnimatable.shouldDeferAnimationFinish(resetAndInvokeFinish)
+ || anim.shouldDeferAnimationFinish(resetAndInvokeFinish))) {
resetAndInvokeFinish.run();
}
}
@@ -592,6 +595,12 @@ class SurfaceAnimator {
* Gets called when the animation is about to finish and gives the client the opportunity to
* defer finishing the animation, i.e. it keeps the leash around until the client calls
* {@link #cancelAnimation}.
+ * <p>
+ * {@link AnimationAdapter} has a similar method which is called only if this method returns
+ * false. This mean that if both this {@link Animatable} and the {@link AnimationAdapter}
+ * request to be deferred, this method is the sole responsible to call
+ * endDeferFinishCallback. On the other hand, the animation finish might still be deferred
+ * if this method return false and the one from the {@link AnimationAdapter} returns true.
*
* @param endDeferFinishCallback The callback to call when defer finishing should be ended.
* @return Whether the client would like to defer the animation finish.
diff --git a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
index 552c476613b2..79ba1759f4c4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SurfaceAnimatorTest.java
@@ -33,6 +33,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import android.platform.test.annotations.Presubmit;
+import android.util.proto.ProtoOutputStream;
import android.view.SurfaceControl;
import android.view.SurfaceControl.Builder;
import android.view.SurfaceControl.Transaction;
@@ -52,6 +53,8 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.io.PrintWriter;
+
/**
* Test class for {@link SurfaceAnimatorTest}.
*
@@ -267,6 +270,27 @@ public class SurfaceAnimatorTest extends WindowTestsBase {
assertFalse(mDeferFinishAnimatable.mFinishedCallbackCalled);
}
+ @Test
+ public void testDeferFinishFromAdapter() {
+
+ DeferredFinishAdapter deferredFinishAdapter = new DeferredFinishAdapter();
+ // Start animation
+ mAnimatable.mSurfaceAnimator.startAnimation(mTransaction, deferredFinishAdapter,
+ true /* hidden */,
+ ANIMATION_TYPE_APP_TRANSITION);
+ assertAnimating(mAnimatable);
+ deferredFinishAdapter.mFinishCallback.onAnimationFinished(ANIMATION_TYPE_APP_TRANSITION,
+ deferredFinishAdapter);
+
+ assertAnimating(mAnimatable);
+ assertFalse(mAnimatable.mFinishedCallbackCalled);
+ // Now end defer finishing.
+ deferredFinishAdapter.mEndDeferFinishCallback.run();
+ assertNotAnimating(mAnimatable);
+ assertTrue(mAnimatable.mFinishedCallbackCalled);
+ verify(mTransaction).remove(eq(deferredFinishAdapter.mAnimationLeash));
+ }
+
private OnAnimationFinishedCallback startDeferFinishAnimatable(AnimationAdapter anim) {
mDeferFinishAnimatable.mSurfaceAnimator.startAnimation(mTransaction, anim,
true /* hidden */, ANIMATION_TYPE_APP_TRANSITION);
@@ -389,4 +413,51 @@ public class SurfaceAnimatorTest extends WindowTestsBase {
return true;
}
}
+
+ private static class DeferredFinishAdapter implements AnimationAdapter {
+
+ private Runnable mEndDeferFinishCallback;
+ private OnAnimationFinishedCallback mFinishCallback;
+ private SurfaceControl mAnimationLeash;
+
+ @Override
+ public boolean getShowWallpaper() {
+ return true;
+ }
+
+ @Override
+ public void startAnimation(SurfaceControl animationLeash, Transaction t, int type,
+ OnAnimationFinishedCallback finishCallback) {
+ mFinishCallback = finishCallback;
+ mAnimationLeash = animationLeash;
+ }
+
+ @Override
+ public void onAnimationCancelled(SurfaceControl animationLeash) {
+ }
+
+ @Override
+ public long getDurationHint() {
+ return 100;
+ }
+
+ @Override
+ public long getStatusBarTransitionsStartTime() {
+ return 100;
+ }
+
+ @Override
+ public void dump(PrintWriter pw, String prefix) {
+ }
+
+ @Override
+ public void dumpDebug(ProtoOutputStream proto) {
+ }
+
+ @Override
+ public boolean shouldDeferAnimationFinish(Runnable endDeferFinishCallback) {
+ mEndDeferFinishCallback = endDeferFinishCallback;
+ return true;
+ }
+ }
}