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

Commit 2cf94d08 authored by Alex Chau's avatar Alex Chau Committed by Automerger Merge Worker
Browse files

Merge "Refactor TaskbarLauncherStateController to use a single AnimatedFLoat"...

Merge "Refactor TaskbarLauncherStateController to use a single AnimatedFLoat" into tm-qpr-dev am: 2f7fd17d am: 4cbe6267

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/20082145



Change-Id: I35961d8403dae852741af0836dd83e62afff5784
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 1fa6de17 4cbe6267
Loading
Loading
Loading
Loading
+106 −186
Original line number Diff line number Diff line
@@ -50,7 +50,6 @@ import java.io.PrintWriter;
import java.util.HashMap;
import java.util.StringJoiner;
import java.util.function.Consumer;
import java.util.function.Supplier;

/**
 * Track LauncherState, RecentsAnimation, resumed state for task bar in one place here and animate
@@ -65,15 +64,12 @@ import java.util.function.Supplier;
    public static final int FLAG_RECENTS_ANIMATION_RUNNING = 1 << 1;
    public static final int FLAG_TRANSITION_STATE_RUNNING = 1 << 2;

    private static final int FLAGS_LAUNCHER = FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING;
    /** Equivalent to an int with all 1s for binary operation purposes */
    private static final int FLAGS_ALL = ~0;

    private final AnimatedFloat mIconAlignmentForResumedState =
            new AnimatedFloat(this::onIconAlignmentRatioChangedForAppAndHomeTransition);
    private final AnimatedFloat mIconAlignmentForGestureState =
            new AnimatedFloat(this::onIconAlignmentRatioChangedForAppAndHomeTransition);
    private final AnimatedFloat mIconAlignmentForLauncherState =
            new AnimatedFloat(this::onIconAlignmentRatioChangedForStateTransition);
    private final AnimatedFloat mIconAlignment =
            new AnimatedFloat(this::onIconAlignmentRatioChanged);

    private TaskbarControllers mControllers;
    private AnimatedFloat mTaskbarBackgroundAlpha;
@@ -86,8 +82,7 @@ import java.util.function.Supplier;

    private @Nullable TaskBarRecentsAnimationListener mTaskBarRecentsAnimationListener;

    private boolean mIsAnimatingToLauncherViaGesture;
    private boolean mIsAnimatingToLauncherViaResume;
    private boolean mIsAnimatingToLauncher;

    private boolean mShouldDelayLauncherStateAnim;

@@ -148,8 +143,8 @@ import java.util.function.Supplier;
        mIconAlphaForHome = taskbarIconAlpha.getProperty(ALPHA_INDEX_HOME);
        mIconAlphaForHome.setConsumer(mIconAlphaForHomeConsumer);

        mIconAlignmentForResumedState.finishAnimation();
        onIconAlignmentRatioChangedForAppAndHomeTransition();
        mIconAlignment.finishAnimation();
        onIconAlignmentRatioChanged();

        mLauncher.getStateManager().addStateListener(mStateListener);

@@ -165,9 +160,7 @@ import java.util.function.Supplier;
    public void onDestroy() {
        mCanSyncViews = false;

        mIconAlignmentForResumedState.finishAnimation();
        mIconAlignmentForGestureState.finishAnimation();
        mIconAlignmentForLauncherState.finishAnimation();
        mIconAlignment.finishAnimation();

        mIconAlphaForHome.setConsumer(null);
        mLauncher.getHotseat().setIconsAlpha(1f);
@@ -187,6 +180,9 @@ import java.util.function.Supplier;
        TaskbarStashController stashController = mControllers.taskbarStashController;
        stashController.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE,
                toState.isTaskbarStashed(mLauncher));
        if (DEBUG) {
            Log.d(TAG, "createAnimToLauncher - FLAG_IN_APP: " + false);
        }
        stashController.updateStateForFlag(FLAG_IN_APP, false);

        updateStateForFlag(FLAG_RECENTS_ANIMATION_RUNNING, true);
@@ -201,7 +197,7 @@ import java.util.function.Supplier;
    }

    public boolean isAnimatingToLauncher() {
        return mIsAnimatingToLauncherViaResume || mIsAnimatingToLauncherViaGesture;
        return mIsAnimatingToLauncher;
    }

    public void setShouldDelayLauncherStateAnim(boolean shouldDelayLauncherStateAnim) {
@@ -261,11 +257,29 @@ import java.util.function.Supplier;
    }

    private Animator onStateChangeApplied(int changedFlags, long duration, boolean start) {
        boolean goingToLauncher = isInLauncher();
        final float toAlignment;
        if (goingToLauncher) {
            boolean isInStashedState = mLauncherState.isTaskbarStashed(mLauncher);
            boolean willStashVisually = isInStashedState
                    && mControllers.taskbarStashController.supportsVisualStashing();
            boolean isTaskbarAlignedWithHotseat =
                    mLauncherState.isTaskbarAlignedWithHotseat(mLauncher);
            toAlignment = isTaskbarAlignedWithHotseat && !willStashVisually ? 1 : 0;
        } else {
            toAlignment = 0;
        }
        if (DEBUG) {
            Log.d(TAG, "onStateChangeApplied - mState: " + getStateString(mState)
                    + ", changedFlags: " + getStateString(changedFlags)
                    + ", goingToLauncher: " + goingToLauncher
                    + ", mLauncherState: " + mLauncherState
                    + ", toAlignment: " + toAlignment);
        }
        AnimatorSet animatorSet = new AnimatorSet();

        // Add the state animation first to ensure FLAG_IN_STASHED_LAUNCHER_STATE is set and we can
        // determine whether goingToUnstashedLauncherStateChanged.
        boolean wasGoingToUnstashedLauncherState = goingToUnstashedLauncherState();
        if (hasAnyFlag(changedFlags, FLAG_TRANSITION_STATE_RUNNING)) {
            boolean committed = !hasAnyFlag(FLAG_TRANSITION_STATE_RUNNING);
            playStateTransitionAnim(animatorSet, duration, committed);
@@ -276,95 +290,69 @@ import java.util.function.Supplier;
                applyState(0 /* duration */);
            }
        }
        boolean goingToUnstashedLauncherStateChanged = wasGoingToUnstashedLauncherState
                != goingToUnstashedLauncherState();

        boolean launcherStateChangedDuringAnimToResumeAlignment =
                mIconAlignmentForResumedState.isAnimating() && goingToUnstashedLauncherStateChanged;
        if (hasAnyFlag(changedFlags, FLAG_RESUMED)
                || launcherStateChangedDuringAnimToResumeAlignment) {
            boolean isResumed = isResumed();
            // If launcher is resumed, we show the icons when going to an unstashed launcher state
            // or launcher state is not changed (e.g. in overview, launcher is paused and resumed).
            float toAlignmentForResumedState = isResumed && (goingToUnstashedLauncherState()
                    || !goingToUnstashedLauncherStateChanged) ? 1 : 0;
            // If we're already animating to the value, just leave it be instead of restarting it.
            if (!mIconAlignmentForResumedState.isAnimatingToValue(toAlignmentForResumedState)) {
                ObjectAnimator resumeAlignAnim = mIconAlignmentForResumedState
                        .animateToValue(toAlignmentForResumedState)
                        .setDuration(duration);
                if (DEBUG) {
                    Log.d(TAG, "mIconAlignmentForResumedState - "
                            + mIconAlignmentForResumedState.value
                            + " -> " + toAlignmentForResumedState + ": " + duration);
                }

                resumeAlignAnim.addListener(new AnimatorListenerAdapter() {
        if (hasAnyFlag(changedFlags, FLAGS_LAUNCHER)) {
            animatorSet.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                        mIsAnimatingToLauncherViaResume = false;
                    mIsAnimatingToLauncher = false;
                }

                @Override
                public void onAnimationStart(Animator animation) {
                        mIsAnimatingToLauncherViaResume = isResumed;
                    mIsAnimatingToLauncher = goingToLauncher;

                    TaskbarStashController stashController =
                            mControllers.taskbarStashController;
                        stashController.updateStateForFlag(FLAG_IN_APP, !isResumed);
                        stashController.applyState(duration);
                    }
                });
                animatorSet.play(resumeAlignAnim);
            }
        }


        boolean launcherStateChangedDuringAnimToGestureAlignment =
                mIconAlignmentForGestureState.isAnimating() && goingToUnstashedLauncherStateChanged;
        if (hasAnyFlag(changedFlags, FLAG_RECENTS_ANIMATION_RUNNING)
                || launcherStateChangedDuringAnimToGestureAlignment) {
            boolean isRecentsAnimationRunning = isRecentsAnimationRunning();
            float toAlignmentForGestureState = isRecentsAnimationRunning
                    && goingToUnstashedLauncherState() ? 1 : 0;
            // If we're already animating to the value, just leave it be instead of restarting it.
            if (!mIconAlignmentForGestureState.isAnimatingToValue(toAlignmentForGestureState)) {
                Animator gestureAlignAnim = mIconAlignmentForGestureState
                        .animateToValue(toAlignmentForGestureState);
                if (isRecentsAnimationRunning) {
                    gestureAlignAnim.setDuration(duration);
                }
                    if (DEBUG) {
                    Log.d(TAG, "mIconAlignmentForGestureState - "
                            + mIconAlignmentForGestureState.value
                            + " -> " + toAlignmentForGestureState + ": " + duration);
                        Log.d(TAG, "onAnimationStart - FLAG_IN_APP: " + !goingToLauncher);
                    }
                gestureAlignAnim.addListener(new AnimatorListenerAdapter() {
                    @Override
                    public void onAnimationEnd(Animator animation) {
                        mIsAnimatingToLauncherViaGesture = false;
                    }

                    @Override
                    public void onAnimationStart(Animator animation) {
                        mIsAnimatingToLauncherViaGesture = isRecentsAnimationRunning();
                    stashController.updateStateForFlag(FLAG_IN_APP, !goingToLauncher);
                    stashController.applyState(duration);
                }
            });
                animatorSet.play(gestureAlignAnim);
            }
        }

        if (hasAnyFlag(changedFlags, FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING)) {
            boolean goingToLauncher = hasAnyFlag(FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING);
            if (goingToLauncher) {
                // Handle closing open popups when going home/overview
                AbstractFloatingView.closeAllOpenViews(mControllers.taskbarActivityContext);
            }
            animatorSet.play(mTaskbarBackgroundAlpha.animateToValue(goingToLauncher ? 0 : 1)
        }

        float backgroundAlpha =
                goingToLauncher && mLauncherState.isTaskbarAlignedWithHotseat(mLauncher)
                        ? 0 : 1;
        // Don't animate if background has reached desired value.
        if (mTaskbarBackgroundAlpha.isAnimating()
                || mTaskbarBackgroundAlpha.value != backgroundAlpha) {
            mTaskbarBackgroundAlpha.cancelAnimation();
            if (DEBUG) {
                Log.d(TAG, "onStateChangeApplied - taskbarBackgroundAlpha - "
                        + mTaskbarBackgroundAlpha.value
                        + " -> " + backgroundAlpha + ": " + duration);
            }
            animatorSet.play(mTaskbarBackgroundAlpha.animateToValue(backgroundAlpha)
                    .setDuration(duration));
        }

        if (mIconAlignment.isAnimatingToValue(toAlignment)
                || mIconAlignment.isSettledOnValue(toAlignment)) {
            // Already at desired value, but make sure we run the callback at the end.
            animatorSet.addListener(AnimatorListeners.forEndCallback(
                    this::onIconAlignmentRatioChanged));
        } else {
            mIconAlignment.cancelAnimation();
            ObjectAnimator iconAlignAnim = mIconAlignment
                    .animateToValue(toAlignment)
                    .setDuration(duration);
            if (DEBUG) {
                Log.d(TAG, "onStateChangeApplied - iconAlignment - "
                        + mIconAlignment.value
                        + " -> " + toAlignment + ": " + duration);
            }
            animatorSet.play(iconAlignAnim);
        }
        animatorSet.setInterpolator(EMPHASIZED);

        if (start) {
            animatorSet.start();
        }
@@ -372,18 +360,13 @@ import java.util.function.Supplier;
    }

    /** Returns whether we're going to a state where taskbar icons should align with launcher. */
    private boolean goingToUnstashedLauncherState() {
        return !mControllers.taskbarStashController.isInStashedLauncherState();
    public boolean goingToAlignedLauncherState() {
        return mLauncherState.isTaskbarAlignedWithHotseat(mLauncher);
    }

    private void playStateTransitionAnim(AnimatorSet animatorSet, long duration,
            boolean committed) {
        boolean isInStashedState = mLauncherState.isTaskbarStashed(mLauncher);
        boolean willStashVisually =
                isInStashedState && mControllers.taskbarStashController.supportsVisualStashing();
        float toAlignment =
                mLauncherState.isTaskbarAlignedWithHotseat(mLauncher) && !willStashVisually ? 1 : 0;

        TaskbarStashController stashController = mControllers.taskbarStashController;
        stashController.updateStateForFlag(FLAG_IN_STASHED_LAUNCHER_STATE, isInStashedState);
        Animator stashAnimator = stashController.applyStateWithoutStart(duration);
@@ -406,55 +389,23 @@ import java.util.function.Supplier;
            });
            animatorSet.play(stashAnimator);
        }
        if (mIconAlignmentForLauncherState.value == toAlignment) {
            // Already at expected value, but make sure we run the callback at the end.
            animatorSet.addListener(AnimatorListeners.forEndCallback(
                    this::onIconAlignmentRatioChangedForStateTransition));
        }
        if (!mIconAlignmentForLauncherState.isAnimatingToValue(toAlignment)) {
            // If we're already animating to the value, just leave it be instead of restarting it.
            mIconAlignmentForLauncherState.finishAnimation();
            animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment)
                    .setDuration(duration));
            if (DEBUG) {
                Log.d(TAG, "mIconAlignmentForLauncherState - "
                        + mIconAlignmentForLauncherState.value
                        + " -> " + toAlignment + ": " + duration);
            }
            animatorSet.setInterpolator(EMPHASIZED);
        }
    }

    private boolean isResumed() {
        return (mState & FLAG_RESUMED) != 0;
    private boolean isInLauncher() {
        return (mState & FLAGS_LAUNCHER) != 0;
    }

    private boolean isRecentsAnimationRunning() {
        return (mState & FLAG_RECENTS_ANIMATION_RUNNING) != 0;
    }

    private void onIconAlignmentRatioChangedForStateTransition() {
        if (!isResumed() && mTaskBarRecentsAnimationListener == null) {
            return;
        }
        onIconAlignmentRatioChanged(this::getCurrentIconAlignmentRatioForLauncherState);
    }

    private void onIconAlignmentRatioChangedForAppAndHomeTransition() {
        onIconAlignmentRatioChanged(this::getCurrentIconAlignmentRatioBetweenAppAndHome);
    }

    private void onIconAlignmentRatioChanged(Supplier<AnimatedFloat> alignmentSupplier) {
        if (mControllers == null) {
            return;
        }
        AnimatedFloat animatedFloat = alignmentSupplier.get();
    private void onIconAlignmentRatioChanged() {
        float currentValue = mIconAlphaForHome.getValue();
        boolean taskbarWillBeVisible = animatedFloat.value < 1;
        boolean taskbarWillBeVisible = mIconAlignment.value < 1;
        boolean firstFrameVisChanged = (taskbarWillBeVisible && Float.compare(currentValue, 1) != 0)
                || (!taskbarWillBeVisible && Float.compare(currentValue, 0) != 0);

        updateIconAlignment(animatedFloat.value, animatedFloat.getEndValue());
        mControllers.taskbarViewController.setLauncherIconAlignment(
                mIconAlignment.value, mIconAlignment.getEndValue(), mLauncher.getDeviceProfile());
        mControllers.navbarButtonsViewController.updateTaskbarAlignment(mIconAlignment.value);
        // Switch taskbar and hotseat in last frame
        mIconAlphaForHome.setValue(taskbarWillBeVisible ? 1 : 0);

        // Sync the first frame where we swap taskbar and hotseat.
        if (firstFrameVisChanged && mCanSyncViews && !Utilities.IS_RUNNING_IN_TEST_HARNESS) {
@@ -464,28 +415,6 @@ import java.util.function.Supplier;
        }
    }

    private void updateIconAlignment(float alignment, Float endAlignment) {
        mControllers.taskbarViewController.setLauncherIconAlignment(
                alignment, endAlignment, mLauncher.getDeviceProfile());

        // Switch taskbar and hotseat in last frame
        setTaskbarViewVisible(alignment < 1);
        mControllers.navbarButtonsViewController.updateTaskbarAlignment(alignment);
    }

    private AnimatedFloat getCurrentIconAlignmentRatioBetweenAppAndHome() {
        return mIconAlignmentForResumedState.value > mIconAlignmentForGestureState.value
                ? mIconAlignmentForResumedState : mIconAlignmentForGestureState;
    }

    private AnimatedFloat getCurrentIconAlignmentRatioForLauncherState() {
        return mIconAlignmentForLauncherState;
    }

    private void setTaskbarViewVisible(boolean isVisible) {
        mIconAlphaForHome.setValue(isVisible ? 1 : 0);
    }

    private final class TaskBarRecentsAnimationListener implements
            RecentsAnimationCallbacks.RecentsAnimationListener {
        private final RecentsAnimationCallbacks mCallbacks;
@@ -515,11 +444,11 @@ import java.util.function.Supplier;
            updateStateForFlag(FLAG_RECENTS_ANIMATION_RUNNING, false);
            updateStateForFlag(FLAG_RESUMED, launcherResumed);
            applyState();
            // Set this last because applyState() might also animate it.
            mIconAlignmentForResumedState.cancelAnimation();
            mIconAlignmentForResumedState.updateValue(launcherResumed ? 1 : 0);

            TaskbarStashController controller = mControllers.taskbarStashController;
            if (DEBUG) {
                Log.d(TAG, "endGestureStateOverride - FLAG_IN_APP: " + finishedToApp);
            }
            controller.updateStateForFlag(FLAG_IN_APP, finishedToApp);
            controller.applyState();
        }
@@ -527,29 +456,24 @@ import java.util.function.Supplier;

    private static String getStateString(int flags) {
        StringJoiner str = new StringJoiner("|");
        str.add((flags & FLAG_RESUMED) != 0 ? "FLAG_RESUMED" : "");
        str.add((flags & FLAG_RECENTS_ANIMATION_RUNNING) != 0
                ? "FLAG_RECENTS_ANIMATION_RUNNING" : "");
        str.add((flags & FLAG_TRANSITION_STATE_RUNNING) != 0
                ? "FLAG_TRANSITION_STATE_RUNNING" : "");
        if ((flags & FLAG_RESUMED) != 0) {
            str.add("FLAG_RESUMED");
        }
        if ((flags & FLAG_RECENTS_ANIMATION_RUNNING) != 0) {
            str.add("FLAG_RECENTS_ANIMATION_RUNNING");
        }
        if ((flags & FLAG_TRANSITION_STATE_RUNNING) != 0) {
            str.add("FLAG_TRANSITION_STATE_RUNNING");
        }
        return str.toString();
    }

    protected void dumpLogs(String prefix, PrintWriter pw) {
        pw.println(prefix + "TaskbarLauncherStateController:");

        pw.println(String.format(
                "%s\tmIconAlignmentForResumedState=%.2f",
                prefix,
                mIconAlignmentForResumedState.value));
        pw.println(String.format(
                "%s\tmIconAlignmentForGestureState=%.2f",
                prefix,
                mIconAlignmentForGestureState.value));
        pw.println(String.format(
                "%s\tmIconAlignmentForLauncherState=%.2f",
                "%s\tmIconAlignment=%.2f",
                prefix,
                mIconAlignmentForLauncherState.value));
                mIconAlignment.value));
        pw.println(String.format(
                "%s\tmTaskbarBackgroundAlpha=%.2f", prefix, mTaskbarBackgroundAlpha.value));
        pw.println(String.format(
@@ -558,13 +482,9 @@ import java.util.function.Supplier;
        pw.println(String.format("%s\tmState=%s", prefix, getStateString(mState)));
        pw.println(String.format("%s\tmLauncherState=%s", prefix, mLauncherState));
        pw.println(String.format(
                "%s\tmIsAnimatingToLauncherViaGesture=%b",
                prefix,
                mIsAnimatingToLauncherViaGesture));
        pw.println(String.format(
                "%s\tmIsAnimatingToLauncherViaResume=%b",
                "%s\tmIsAnimatingToLauncher=%b",
                prefix,
                mIsAnimatingToLauncherViaResume));
                mIsAnimatingToLauncher));
        pw.println(String.format(
                "%s\tmShouldDelayLauncherStateAnim=%b", prefix, mShouldDelayLauncherStateAnim));
    }
+7 −0
Original line number Diff line number Diff line
@@ -134,6 +134,13 @@ public class AnimatedFloat {
        return isAnimating() && mEndValue != null && mEndValue == endValue;
    }

    /**
     * Returns whether we are currently not animating, and the animation's value matches the given.
     */
    public boolean isSettledOnValue(float endValue) {
        return !isAnimating() && value == endValue;
    }

    /**
     * Returns the value we are animating to, or {@code null} if we are not currently animating.
     */