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

Commit 9a5460ee authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge changes from topic "physics_animator_end_runnable" into main

* changes:
  Fix an issue where the end runnable may not get called
  Fix an issue with canceling a PhysicsAnimator
parents 0fe8ec92 e097073f
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -279,6 +279,29 @@ class BubbleBarAnimationHelperTest {
        assertThat(bbev.alpha).isEqualTo(1)
    }

    @Test
    fun animateExpansion_cancelCallsEndCallback() {
        val bubble = createBubble(key = "b1").initialize(container)
        val bbev = bubble.bubbleBarExpandedView!!

        val semaphore = Semaphore(0)
        var afterCalled = false
        val after = Runnable {
            afterCalled = true
            semaphore.release()
        }

        activityScenario.onActivity {
            bbev.onTaskCreated()
            animationHelper.animateExpansion(bubble, after)
            animationHelper.cancelAnimations()
        }
        getInstrumentation().waitForIdleSync()

        assertThat(semaphore.tryAcquire(5, TimeUnit.SECONDS)).isTrue()
        assertThat(afterCalled).isTrue()
    }

    @Test
    fun onImeTopChanged_noOverlap() {
        val bubble = createBubble(key = "b1").initialize(container)
+36 −11
Original line number Diff line number Diff line
@@ -117,6 +117,9 @@ class PhysicsAnimator<T> private constructor (target: T) {
    /** End actions to run when all animations have completed.  */
    private val endActions = ArrayList<EndAction>()

    /** End actions to run when all animations have completed or canceled.  */
    private val endOrCancelActions = ArrayList<EndAction>()

    /** SpringConfig to use by default for properties whose springs were not provided. */
    private var defaultSpring: SpringConfig = globalDefaultSpring

@@ -384,7 +387,8 @@ class PhysicsAnimator<T> private constructor (target: T) {
     * Adds a listener that will be called when a property stops animating. This is useful if
     * you care about a specific property ending, or want to use the end value/end velocity from a
     * particular property's animation. If you just want to run an action when all property
     * animations have ended, use [withEndActions].
     * animations have ended, use [withEndActions]. If you want an action to run when all property
     * animations have ended or canceled, use [withEndOrCancelActions].
     */
    fun addEndListener(listener: EndListener<T>): PhysicsAnimator<T> {
        endListeners.add(listener)
@@ -393,8 +397,8 @@ class PhysicsAnimator<T> private constructor (target: T) {

    /**
     * Adds end actions that will be run sequentially when animations for every property involved in
     * this specific animation have ended (unless they were explicitly canceled). For example, if
     * you call:
     * this specific animation have ended (unless they were explicitly canceled, in which you should
     * use [withEndOrCancelActions]). For example, if you call:
     *
     * animator
     *   .spring(TRANSLATION_X, ...)
@@ -424,6 +428,9 @@ class PhysicsAnimator<T> private constructor (target: T) {
     * access to the animation's end value/velocity, or you want to run these actions even if the
     * animation is explicitly canceled, use [addEndListener]. End listeners have an allEnded param,
     * which indicates that all relevant animations have ended.
     *
     * These actions run after those added via [addEndListener], and before actions added via
     * [withEndOrCancelActions].
     */
    fun withEndActions(vararg endActions: EndAction?): PhysicsAnimator<T> {
        this.endActions.addAll(endActions.filterNotNull())
@@ -439,6 +446,15 @@ class PhysicsAnimator<T> private constructor (target: T) {
        return this
    }

    /**
     * Like [withEndActions], but called if the animator is canceled as well. These actions are
     * always run after those added via [addEndListener] and [withEndActions].
     */
    fun withEndOrCancelActions(vararg endOrCancelActions: Runnable?): PhysicsAnimator<T> {
        this.endOrCancelActions.addAll(endOrCancelActions.filterNotNull().map { it::run })
        return this
    }

    fun setDefaultSpringConfig(defaultSpring: SpringConfig) {
        this.defaultSpring = defaultSpring
    }
@@ -581,7 +597,8 @@ class PhysicsAnimator<T> private constructor (target: T) {
                getAnimatedProperties(),
                ArrayList(updateListeners),
                ArrayList(endListeners),
                ArrayList(endActions)))
                ArrayList(endActions),
                ArrayList(endOrCancelActions)))

        // Actually start the DynamicAnimations. This is delayed until after the InternalListener is
        // constructed and added so that we don't miss the end listener firing for any animations
@@ -599,6 +616,7 @@ class PhysicsAnimator<T> private constructor (target: T) {
        updateListeners.clear()
        endListeners.clear()
        endActions.clear()
        endOrCancelActions.clear()
    }

    /** Retrieves a spring animation for the given property, building one if needed. */
@@ -659,7 +677,8 @@ class PhysicsAnimator<T> private constructor (target: T) {
        private var properties: Set<FloatPropertyCompat<in T>>,
        private var updateListeners: List<UpdateListener<T>>,
        private var endListeners: List<EndListener<T>>,
        private var endActions: List<EndAction>
        private var endActions: List<EndAction>,
        private var endOrCancelActions: List<EndAction>
    ) {

        /** The number of properties whose animations haven't ended. */
@@ -735,10 +754,13 @@ class PhysicsAnimator<T> private constructor (target: T) {
            }

            // If all of the animations that this listener cares about have ended, run the end
            // actions unless the animation was canceled.
            if (allEnded && !canceled) {
            // actions
            if (allEnded) {
                if (!canceled) {
                    endActions.forEach { it() }
                }
                endOrCancelActions.forEach { it() }
            }

            return allEnded
        }
@@ -785,7 +807,8 @@ class PhysicsAnimator<T> private constructor (target: T) {
     * animator is under test.
     */
    internal fun cancelInternal(properties: Set<FloatPropertyCompat<in T>>) {
        for (property in properties) {
        val propertiesCopy = properties.toSet()
        for (property in propertiesCopy) {
            flingAnimations[property]?.cancel()
            springAnimations[property]?.cancel()
        }
@@ -911,8 +934,10 @@ class PhysicsAnimator<T> private constructor (target: T) {
         * to respond to specific property animations concluding (such as hiding a view when ALPHA
         * ends, even if the corresponding TRANSLATION animations have not ended).
         *
         * If you just want to run an action when all of the property animations have ended, you can
         * use [PhysicsAnimator.withEndActions].
         * If you just want to run an action when all of the property animations have ended (but not
         * canceled), you can use [PhysicsAnimator.withEndActions].  If you need to run an action
         * regardless of whether the animations were canceled, use
         * [PhysicsAnimator.withEndOrCancelActions].
         *
         * @param target The animated object itself.
         * @param property The property whose animation has just ended.
+4 −0
Original line number Diff line number Diff line
@@ -2750,6 +2750,8 @@ public class BubbleStackView extends FrameLayout
                        if (expView != null) {
                            expView.setSurfaceZOrderedOnTop(false);
                        }
                    })
                    .withEndOrCancelActions(() -> {
                        if (mAfterTransitionRunnable != null) {
                            mAfterTransitionRunnable.run();
                            mAfterTransitionRunnable = null;
@@ -2966,6 +2968,8 @@ public class BubbleStackView extends FrameLayout
                            expandedView.setSurfaceZOrderedOnTop(false);
                            expandedView.setAnimating(false);
                        }
                    })
                    .withEndOrCancelActions(() -> {
                        if (mAfterTransitionRunnable != null) {
                            mAfterTransitionRunnable.run();
                            mAfterTransitionRunnable = null;
+32 −14
Original line number Diff line number Diff line
@@ -546,6 +546,7 @@ public class BubbleTransitions {

        @Override
        public void skip() {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "LaunchNewTaskBubble.skip()");
            mBubble.setPreparingTransition(null);
            cleanup();
        }
@@ -582,6 +583,7 @@ public class BubbleTransitions {
                @NonNull SurfaceControl.Transaction startTransaction,
                @NonNull SurfaceControl.Transaction finishTransaction,
                @NonNull Transitions.TransitionFinishCallback finishCallback) {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "LaunchNewTaskBubble.startAnimation()");

            // Identify the task that we are converting or launching. Note, we iterate back to front
            // so that we can adjust alpha for revealed surfaces as needed.
@@ -648,13 +650,13 @@ public class BubbleTransitions {
        }

        private void startExpandAnim() {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubbleTransitions.startExpandAnim(): "
                    + "readyToAnimate=%b", mTransitionProgress.isReadyToAnimate());
            if (mExpandedViewAnimator.canExpandView(mBubble)) {
                mPriorBubble = mExpandedViewAnimator.prepareConvertedView(mBubble);
            } else if (mExpandedViewAnimator.isExpanded()) {
                mTransitionProgress.setReadyToExpand();
            }
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "LaunchNewTaskBubble.startExpandAnim(): "
                    + "readyToAnimate=%b", mTransitionProgress.isReadyToAnimate());
            if (mTransitionProgress.isReadyToAnimate()) {
                playAnimation();
            }
@@ -669,8 +671,9 @@ public class BubbleTransitions {
        public void surfaceCreated() {
            mTransitionProgress.setSurfaceReady();
            mMainExecutor.execute(() -> {
                ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubbleTransitions.surfaceCreated(): "
                        + "mTaskLeash=%s", mTaskLeash);
                ProtoLog.d(WM_SHELL_BUBBLES_NOISY,
                        "LaunchNewTaskBubble.surfaceCreated(): mTaskLeash=%s readyToAnimate=%b",
                        mTaskLeash, mTransitionProgress.isReadyToAnimate());
                final TaskViewTaskController tvc = mBubble.getTaskView().getController();
                final TaskViewRepository.TaskViewState state = mRepository.byTaskView(tvc);
                if (state == null) return;
@@ -682,7 +685,8 @@ public class BubbleTransitions {
        }

        private void playAnimation() {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubbleTransitions.playAnimation(): playConvert=%b",
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY,
                    "LaunchNewTaskBubble.playAnimation(): playConvert=%b",
                    mPlayConvertTaskAnimation);
            final TaskViewTaskController tv = mBubble.getTaskView().getController();
            final SurfaceControl.Transaction startT = new SurfaceControl.Transaction();
@@ -715,6 +719,7 @@ public class BubbleTransitions {
        }

        private void cleanup() {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "LaunchNewTaskBubble.cleanup()");
            mFinishCb.onTransitionFinished(mFinishWct);
            mFinishCb = null;
        }
@@ -868,6 +873,7 @@ public class BubbleTransitions {

        @Override
        public void skip() {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "LaunchOrConvert.skip()");
            mBubble.setPreparingTransition(null);
            cleanup();
        }
@@ -910,6 +916,7 @@ public class BubbleTransitions {
                @NonNull SurfaceControl.Transaction startTransaction,
                @NonNull SurfaceControl.Transaction finishTransaction,
                @NonNull Transitions.TransitionFinishCallback finishCallback) {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "LaunchOrConvert.startAnimation()");
            mPlayingTransition = transition;

            // Identify the task that we are converting or launching. Note, we iterate back to front
@@ -976,12 +983,12 @@ public class BubbleTransitions {
        }

        private void startExpandAnim() {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubbleTransitions.startExpandAnim(): "
                    + "readyToAnimate=%b", mTransitionProgress.isReadyToAnimate());
            final boolean animate = mExpandedViewAnimator.canExpandView(mBubble);
            if (animate) {
                mPriorBubble = mExpandedViewAnimator.prepareConvertedView(mBubble);
            }
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "LaunchOrConvert.startExpandAnim(): "
                    + "readyToAnimate=%b", mTransitionProgress.isReadyToAnimate());
            if (mPriorBubble != null) {
                // TODO: an animation. For now though, just remove it.
                final BubbleBarExpandedView priorView = mPriorBubble.getBubbleBarExpandedView();
@@ -1002,8 +1009,9 @@ public class BubbleTransitions {
        public void surfaceCreated() {
            mTransitionProgress.setSurfaceReady();
            mMainExecutor.execute(() -> {
                ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubbleTransitions.surfaceCreated(): "
                        + "mTaskLeash=%s", mTaskLeash);
                ProtoLog.d(WM_SHELL_BUBBLES_NOISY,
                        "LaunchOrConvert.surfaceCreated(): mTaskLeash=%s readyToAnimate=%b",
                        mTaskLeash, mTransitionProgress.isReadyToAnimate());
                final TaskViewTaskController tvc = mBubble.getTaskView().getController();
                final TaskViewRepository.TaskViewState state = mRepository.byTaskView(tvc);
                if (state == null) return;
@@ -1015,8 +1023,9 @@ public class BubbleTransitions {
        }

        private void playAnimation(boolean animate) {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "BubbleTransitions.playAnimation(): animate=%b",
                    animate);
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY,
                    "LaunchOrConvert.playAnimation(): playConvert=%b",
                    mPlayConvertTaskAnimation);
            final TaskViewTaskController tv = mBubble.getTaskView().getController();
            final SurfaceControl.Transaction startT = new SurfaceControl.Transaction();
            // Set task position to 0,0 as it will be placed inside the TaskView
@@ -1053,10 +1062,10 @@ public class BubbleTransitions {
        }

        private void cleanup() {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "LaunchNewTaskBubble.cleanup(): removeCookie=%s",
                    mLaunchCookie.binder);
            mFinishCb.onTransitionFinished(mFinishWct);
            mFinishCb = null;
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "Removing pending transition on cleanup for "
                            + "cookie=%s", mLaunchCookie.binder);
            mPendingEnterTransitions.remove(mLaunchCookie.binder);
            mEnterTransitions.remove(mPlayingTransition);
        }
@@ -1135,6 +1144,7 @@ public class BubbleTransitions {

        @VisibleForTesting
        void onInflated(Bubble b) {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "ConvertToBubble.onInflated()");
            if (b != mBubble) {
                throw new IllegalArgumentException("inflate callback doesn't match bubble");
            }
@@ -1167,6 +1177,7 @@ public class BubbleTransitions {

        @Override
        public void skip() {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "ConvertToBubble.skip()");
            mBubble.setPreparingTransition(null);
            mFinishCb.onTransitionFinished(mFinishWct);
            mFinishCb = null;
@@ -1201,6 +1212,7 @@ public class BubbleTransitions {
                @NonNull SurfaceControl.Transaction finishTransaction,
                @NonNull Transitions.TransitionFinishCallback finishCallback) {
            if (mTransition != transition) return false;
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "ConvertToBubble.startAnimation()");
            boolean found = false;
            for (int i = 0; i < info.getChanges().size(); ++i) {
                final TransitionInfo.Change chg = info.getChanges().get(i);
@@ -1260,6 +1272,8 @@ public class BubbleTransitions {
            if (animate) {
                mPriorBubble = mExpandedViewAnimator.prepareConvertedView(mBubble);
            }
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "ConvertToBubble.startExpandAnim(): "
                    + "readyToAnimate=%b", mTransitionProgress.isReadyToAnimate());
            if (mPriorBubble != null) {
                // TODO: an animation. For now though, just remove it.
                final BubbleBarExpandedView priorView = mPriorBubble.getBubbleBarExpandedView();
@@ -1280,6 +1294,9 @@ public class BubbleTransitions {
        public void surfaceCreated() {
            mTransitionProgress.setSurfaceReady();
            mMainExecutor.execute(() -> {
                ProtoLog.d(WM_SHELL_BUBBLES_NOISY,
                        "ConvertToBubble.surfaceCreated(): mTaskLeash=%s readyToAnimate=%b",
                        mTaskLeash, mTransitionProgress.isReadyToAnimate());
                final TaskViewTaskController tvc = mBubble.getTaskView().getController();
                final TaskViewRepository.TaskViewState state = mRepository.byTaskView(tvc);
                if (state == null) return;
@@ -1291,6 +1308,7 @@ public class BubbleTransitions {
        }

        private void playAnimation(boolean animate) {
            ProtoLog.d(WM_SHELL_BUBBLES_NOISY, "ConvertToBubble.playAnimation()");
            final TaskViewTaskController tv = mBubble.getTaskView().getController();
            final SurfaceControl.Transaction startT = new SurfaceControl.Transaction();
            // Set task position to 0,0 as it will be placed inside the TaskView
@@ -1298,7 +1316,7 @@ public class BubbleTransitions {
            mTaskViewTransitions.prepareOpenAnimation(tv, true /* new */, startT, mFinishT,
                    (ActivityManager.RunningTaskInfo) mTaskInfo, mTaskLeash, mFinishWct);
            // Add the task view task listener manually since we aren't going through
            // TaskViewTransitions (which normally sets up the listener via a pending launch cookie
            // TaskViewTransitions (which normally sets up the listener via a pending launch cookie)
            mTaskOrganizer.addListenerForTaskId(tv, mTaskInfo.taskId);

            if (mFinishWct.isEmpty()) {
+53 −30

File changed.

Preview size limit exceeded, changes collapsed.

Loading