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

Commit 87a6ad18 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Fixing controller state is not properly cleared when the animaiton is cancelled.

This was leading to a pending animation running while the state had changes,
leaving user in an inconsistent state.

Various atomic animation fixes
> Ensuring that there is only one success listener on atomic animation, so that atomic
  controller is created only once and to the final mToState
> If atomic controller is already running, skip animating the atomic conmonenets as
  part of main animaiton
> Cancel atomic controller if it is going to a different state

Bug: 80549582
Bug: 109583168
Change-Id: Ie7a032e0fa73b1f1c2ef53055c08d16444f0385e
parent d936f6a5
Loading
Loading
Loading
Loading
+3 −0
Original line number Original line Diff line number Diff line
@@ -556,6 +556,9 @@ public class LauncherStateManager {


        @Override
        @Override
        public void onAnimationEnd(Animator animation) {
        public void onAnimationEnd(Animator animation) {
            if (playbackController != null && playbackController.getTarget() == animation) {
                playbackController = null;
            }
            if (mCurrentAnimation == animation) {
            if (mCurrentAnimation == animation) {
                mCurrentAnimation = null;
                mCurrentAnimation = null;
            }
            }
+43 −17
Original line number Original line Diff line number Diff line
@@ -86,6 +86,9 @@ public abstract class AbstractStateChangeTouchController
    private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
    private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();


    private AnimatorSet mAtomicAnim;
    private AnimatorSet mAtomicAnim;
    // True if we want to resume playing atomic components when mAtomicAnim completes.
    private boolean mScheduleResumeAtomicComponent;

    private boolean mPassedOverviewAtomicThreshold;
    private boolean mPassedOverviewAtomicThreshold;
    // mAtomicAnim plays the atomic components of the state animations when we pass the threshold.
    // mAtomicAnim plays the atomic components of the state animations when we pass the threshold.
    // However, if we reinit to transition to a new state (e.g. OVERVIEW -> ALL_APPS) before the
    // However, if we reinit to transition to a new state (e.g. OVERVIEW -> ALL_APPS) before the
@@ -93,6 +96,8 @@ public abstract class AbstractStateChangeTouchController
    // interfere with the atomic animation. When the atomic animation ends, we start controlling
    // interfere with the atomic animation. When the atomic animation ends, we start controlling
    // the atomic components as well, using this controller.
    // the atomic components as well, using this controller.
    private AnimatorPlaybackController mAtomicComponentsController;
    private AnimatorPlaybackController mAtomicComponentsController;
    private LauncherState mAtomicComponentsTargetState = NORMAL;

    private float mAtomicComponentsStartProgress;
    private float mAtomicComponentsStartProgress;


    public AbstractStateChangeTouchController(Launcher l, SwipeDetector.Direction dir) {
    public AbstractStateChangeTouchController(Launcher l, SwipeDetector.Direction dir) {
@@ -191,27 +196,21 @@ public abstract class AbstractStateChangeTouchController
        }
        }
        int animComponents = goingBetweenNormalAndOverview(mFromState, mToState)
        int animComponents = goingBetweenNormalAndOverview(mFromState, mToState)
                ? NON_ATOMIC_COMPONENT : ANIM_ALL;
                ? NON_ATOMIC_COMPONENT : ANIM_ALL;
        mScheduleResumeAtomicComponent = false;
        if (mAtomicAnim != null) {
        if (mAtomicAnim != null) {
            animComponents = NON_ATOMIC_COMPONENT;
            // Control the non-atomic components until the atomic animation finishes, then control
            // Control the non-atomic components until the atomic animation finishes, then control
            // the atomic components as well.
            // the atomic components as well.
            animComponents = NON_ATOMIC_COMPONENT;
            mScheduleResumeAtomicComponent = true;
            mAtomicAnim.addListener(new AnimationSuccessListener() {
                @Override
                public void onAnimationSuccess(Animator animation) {
                    cancelAtomicComponentsController();
                    if (mCurrentAnimation != null) {
                        mAtomicComponentsStartProgress = mCurrentAnimation.getProgressFraction();
                        long duration = (long) (getShiftRange() * 2);
                        mAtomicComponentsController = AnimatorPlaybackController.wrap(
                                createAtomicAnimForState(mFromState, mToState, duration), duration);
                        mAtomicComponentsController.dispatchOnStart();
                    }
                }
            });
        }
        }
        if (goingBetweenNormalAndOverview(mFromState, mToState)) {
        if (goingBetweenNormalAndOverview(mFromState, mToState)
                || mAtomicComponentsTargetState != mToState) {
            cancelAtomicComponentsController();
            cancelAtomicComponentsController();
        }
        }

        if (mAtomicComponentsController != null) {
            animComponents &= ~ATOMIC_COMPONENT;
        }
        mProgressMultiplier = initCurrentAnimation(animComponents);
        mProgressMultiplier = initCurrentAnimation(animComponents);
        mCurrentAnimation.dispatchOnStart();
        mCurrentAnimation.dispatchOnStart();
        return true;
        return true;
@@ -302,10 +301,28 @@ public abstract class AbstractStateChangeTouchController
                mAtomicAnim.cancel();
                mAtomicAnim.cancel();
            }
            }
            mAtomicAnim = createAtomicAnimForState(atomicFromState, atomicToState, ATOMIC_DURATION);
            mAtomicAnim = createAtomicAnimForState(atomicFromState, atomicToState, ATOMIC_DURATION);
            mAtomicAnim.addListener(new AnimatorListenerAdapter() {
            mAtomicAnim.addListener(new AnimationSuccessListener() {
                @Override
                @Override
                public void onAnimationEnd(Animator animation) {
                public void onAnimationEnd(Animator animation) {
                    super.onAnimationEnd(animation);
                    mAtomicAnim = null;
                    mAtomicAnim = null;
                    mScheduleResumeAtomicComponent = false;
                }

                @Override
                public void onAnimationSuccess(Animator animator) {
                    if (!mScheduleResumeAtomicComponent) {
                        return;
                    }
                    cancelAtomicComponentsController();
                    if (mCurrentAnimation != null) {
                        mAtomicComponentsStartProgress = mCurrentAnimation.getProgressFraction();
                        long duration = (long) (getShiftRange() * 2);
                        mAtomicComponentsController = AnimatorPlaybackController.wrap(
                                createAtomicAnimForState(mFromState, mToState, duration), duration);
                        mAtomicComponentsController.dispatchOnStart();
                        mAtomicComponentsTargetState = mToState;
                    }
                }
                }
            });
            });
            mAtomicAnim.start();
            mAtomicAnim.start();
@@ -457,7 +474,7 @@ public abstract class AbstractStateChangeTouchController
    }
    }


    protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
    protected void onSwipeInteractionCompleted(LauncherState targetState, int logAction) {
        clearState();
        cancelAnimationControllers();
        boolean shouldGoToTargetState = true;
        boolean shouldGoToTargetState = true;
        if (mPendingAnimation != null) {
        if (mPendingAnimation != null) {
            boolean reachedTarget = mToState == targetState;
            boolean reachedTarget = mToState == targetState;
@@ -484,6 +501,15 @@ public abstract class AbstractStateChangeTouchController
    }
    }


    protected void clearState() {
    protected void clearState() {
        cancelAnimationControllers();
        if (mAtomicAnim != null) {
            mAtomicAnim.cancel();
            mAtomicAnim = null;
        }
        mScheduleResumeAtomicComponent = false;
    }

    private void cancelAnimationControllers() {
        mCurrentAnimation = null;
        mCurrentAnimation = null;
        cancelAtomicComponentsController();
        cancelAtomicComponentsController();
        mDetector.finishedScrolling();
        mDetector.finishedScrolling();