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

Commit 17b76b76 authored by Vadim Caen's avatar Vadim Caen
Browse files

Defer animation finish from AnimationAdatpter

Add a method similar to Animatable.shouldDeferAnimationFinish() in
AnimationAdatper to give more flexibility when we can't override
Animatable.

Bug: 150676212
Test: atest
WmTests: com.android.server.wm.SurfaceAnimatorTest#testDeferFinishFromAdapter
Change-Id: I9db3c5d1e1ac92c68fe00eca886ea71965d0142e
parent 772be3e0
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -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;
    }
}
+10 −1
Original line number Diff line number Diff line
@@ -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.
+71 −0
Original line number Diff line number Diff line
@@ -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;
        }
    }
}