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

Commit 2ebfc419 authored by Mike Schneider's avatar Mike Schneider
Browse files

Factor out explicit animation types for the stash/unstash animations.

This consolidates the logic on what animation to play into one place, and will simplify tuning the lock/unlock transitions

Bug: 275319714
Test: manually (http://shortn/_Q1dTzmIpqK), unit tests
Change-Id: I9ba9c9f13dbbff88d8515e567fdb3dfe5556553e
parent 08a13d6a
Loading
Loading
Loading
Loading
+103 −50
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ import android.view.ViewConfiguration;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.Interpolator;

import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
@@ -68,6 +69,8 @@ import com.android.launcher3.util.MultiPropertyFactory.MultiProperty;
import com.android.quickstep.SystemUiProxy;

import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.StringJoiner;
import java.util.function.IntPredicate;

@@ -184,6 +187,36 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
    // Auto stashes when user has not interacted with the Taskbar after X ms.
    private static final long NO_TOUCH_TIMEOUT_TO_STASH_MS = 5000;

    /**
     * The default stash animation, morphing the taskbar into the navbar.
     */
    private static final int TRANSITION_DEFAULT = 0;
    /**
     * Transitioning from launcher to app. Same as TRANSITION_DEFAULT, differs in internal
     * animation timings.
     */
    private static final int TRANSITION_HOME_TO_APP = 1;
    /**
     * Fading the navbar in and out, where the taskbar jumpcuts in and out at the very begin/end of
     * the transition. Used to transition between the hotseat and navbar` without the stash/unstash
     * transition.
     */
    private static final int TRANSITION_HANDLE_FADE = 2;
    /**
     * Same as TRANSITION_DEFAULT, but exclusively used during an "navbar unstash to hotseat
     * animation" bound to the progress of a swipe gesture. It differs from TRANSITION_DEFAULT
     * by not scaling the height of the taskbar background.
     */
    private static final int TRANSITION_UNSTASH_SUW_MANUAL = 3;
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(value = {
            TRANSITION_DEFAULT,
            TRANSITION_HOME_TO_APP,
            TRANSITION_HANDLE_FADE,
            TRANSITION_UNSTASH_SUW_MANUAL,
    })
    private @interface StashAnimation {}

    private final TaskbarActivityContext mActivity;
    private final SharedPreferences mPrefs;
    private final int mStashedHeight;
@@ -553,8 +586,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
        createAnimToIsStashed(
                /* isStashed= */ false,
                placeholderDuration,
                /* animateBg= */ false,
                /* changedFlags=*/ 0);
                TRANSITION_UNSTASH_SUW_MANUAL);
        animation.play(mAnimator);
    }

@@ -562,10 +594,15 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
     * Create a stash animation and save to {@link #mAnimator}.
     * @param isStashed whether it's a stash animation or an unstash animation
     * @param duration duration of the animation
     * @param animateBg whether the taskbar's background should be animated
     * @param animationType what transition type to play.
     */
    private void createAnimToIsStashed(boolean isStashed, long duration, boolean animateBg,
            int changedFlags) {
    private void createAnimToIsStashed(boolean isStashed, long duration,
            @StashAnimation int animationType) {
        if (animationType == TRANSITION_UNSTASH_SUW_MANUAL && isStashed) {
            // The STASH_ANIMATION_SUW_MANUAL must only be used during an unstash animation.
            Log.e(TAG, "Illegal arguments:Using TRANSITION_UNSTASH_SUW_MANUAL to stash taskbar");
        }

        if (mAnimator != null) {
            mAnimator.cancel();
        }
@@ -591,23 +628,10 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
            return;
        }

        // If Hotseat is not the top element during animation to/from Launcher, fade in/out a
        // already stashed Taskbar.
        boolean hotseatTopElement = mControllers.uiController.isHotseatIconOnTopWhenAligned()
                || !hasAnyFlag(changedFlags, FLAG_IN_APP);
        // If transitioning to unlocked device, do not play a stash animation.
        // Keep isUnlockTransition in sync with its counterpart in
        // TaskbarLauncherStateController#onStateChangeApplied.
        boolean isUnlockTransition = hasAnyFlag(changedFlags, FLAG_STASHED_DEVICE_LOCKED)
                && !hasAnyFlag(FLAG_STASHED_DEVICE_LOCKED);
        boolean skipStashAnimation = !hotseatTopElement || isUnlockTransition;

        if (isTransientTaskbar) {
            createTransientAnimToIsStashed(mAnimator, isStashed, duration, animateBg, changedFlags,
                    skipStashAnimation);
            createTransientAnimToIsStashed(mAnimator, isStashed, duration, animationType);
        } else {
            createAnimToIsStashed(mAnimator, isStashed, duration, animateBg, skipStashAnimation,
                    stashTranslation);
            createAnimToIsStashed(mAnimator, isStashed, duration, stashTranslation, animationType);
        }

        mAnimator.addListener(new AnimatorListenerAdapter() {
@@ -636,7 +660,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
    }

    private void createAnimToIsStashed(AnimatorSet as, boolean isStashed, long duration,
            boolean animateBg, boolean skipStashAnimation, float stashTranslation) {
            float stashTranslation, @StashAnimation int animationType) {
        AnimatorSet fullLengthAnimatorSet = new AnimatorSet();
        // Not exactly half and may overlap. See [first|second]HalfDurationScale below.
        AnimatorSet firstHalfAnimatorSet = new AnimatorSet();
@@ -650,12 +674,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
            secondHalfDurationScale = 0.5f;

            fullLengthAnimatorSet.play(mIconTranslationYForStash.animateToValue(stashTranslation));
            if (animateBg) {
            fullLengthAnimatorSet.play(mTaskbarBackgroundOffset.animateToValue(1));
            } else {
                fullLengthAnimatorSet.addListener(AnimatorListeners.forEndCallback(
                        () -> mTaskbarBackgroundOffset.updateValue(1)));
            }

            firstHalfAnimatorSet.playTogether(
                    mIconAlphaForStash.animateToValue(0),
@@ -666,7 +685,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
                    mTaskbarStashedHandleAlpha.animateToValue(1)
            );

            if (skipStashAnimation) {
            if (animationType == TRANSITION_HANDLE_FADE) {
                fullLengthAnimatorSet.setInterpolator(INSTANT);
                firstHalfAnimatorSet.setInterpolator(INSTANT);
            }
@@ -677,6 +696,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
            fullLengthAnimatorSet.playTogether(
                    mIconScaleForStash.animateToValue(1),
                    mIconTranslationYForStash.animateToValue(0));

            final boolean animateBg = animationType != TRANSITION_UNSTASH_SUW_MANUAL;
            if (animateBg) {
                fullLengthAnimatorSet.play(mTaskbarBackgroundOffset.animateToValue(0));
            } else {
@@ -691,7 +712,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
                    mIconAlphaForStash.animateToValue(1)
            );

            if (skipStashAnimation) {
            if (animationType == TRANSITION_HANDLE_FADE) {
                fullLengthAnimatorSet.setInterpolator(FINAL_FRAME);
                secondHalfAnimatorSet.setInterpolator(FINAL_FRAME);
            }
@@ -714,18 +735,13 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
    }

    private void createTransientAnimToIsStashed(AnimatorSet as, boolean isStashed, long duration,
            boolean animateBg, int changedFlags, boolean skipStashAnimation) {
            @StashAnimation int animationType) {
        Interpolator skipInterpolator = null;

        if (isStashed) {
            if (animateBg) {
            play(as, mTaskbarBackgroundOffset.animateToValue(1), 0, duration, EMPHASIZED);
            } else {
                as.addListener(AnimatorListeners.forEndCallback(
                        () -> mTaskbarBackgroundOffset.updateValue(1)));
            }

            long alphaStartDelay = duration == 0 ? 0 : (changedFlags == FLAG_IN_APP)
            long alphaStartDelay = duration == 0 ? 0 : animationType == TRANSITION_HOME_TO_APP
                    ? TASKBAR_STASH_ICON_ALPHA_HOME_TO_APP_START_DELAY
                    : TASKBAR_STASH_ALPHA_START_DELAY;
            long alphaDuration = duration == 0 ? 0 : TASKBAR_STASH_ALPHA_DURATION;
@@ -736,10 +752,11 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
            play(as, mControllers.taskbarSpringOnStashController.createSpringToStash(), 0, duration,
                    LINEAR);

            if (skipStashAnimation) {
            if (animationType == TRANSITION_HANDLE_FADE) {
                skipInterpolator = INSTANT;
            }
        } else  {
            final boolean animateBg = animationType != TRANSITION_UNSTASH_SUW_MANUAL;
            if (animateBg) {
                play(as, mTaskbarBackgroundOffset.animateToValue(0), 0, duration, EMPHASIZED);
            } else {
@@ -752,7 +769,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
            play(as, mIconAlphaForStash.animateToValue(1), alphaStartDelay, alphaDuration, LINEAR);
            play(as, mTaskbarStashedHandleAlpha.animateToValue(0), 0, alphaDuration, LINEAR);

            if (skipStashAnimation) {
            if (animationType == TRANSITION_HANDLE_FADE) {
                skipInterpolator = FINAL_FRAME;
            }
        }
@@ -1150,7 +1167,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
        private final IntPredicate mStashCondition;

        private boolean mIsStashed;
        private boolean mIsHotseatIconOnTopWhenAligned;
        private @StashAnimation int mLastStartedTransitionType = TRANSITION_DEFAULT;
        private int mPrevFlags;

        StatePropertyHolder(IntPredicate stashCondition) {
@@ -1182,28 +1199,64 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
                onStateChangeApplied(changedFlags);
                mPrevFlags = flags;
            }
            boolean isHotseatIconOnTopWhenAligned =
                    mControllers.uiController.isHotseatIconOnTopWhenAligned();
            // If an animation has started and mIsHotseatIconOnTopWhenAligned is changed, we need
            // to restart the animation with new parameters.
            if (mIsStashed != isStashed
                    || (mIsHotseatIconOnTopWhenAligned != isHotseatIconOnTopWhenAligned
                    && mAnimator != null && mAnimator.isStarted())) {

            @StashAnimation int animationType = computeTransitionType(changedFlags);

            // Allow re-starting animation if upgrading from default animation type, otherwise
            // stick with the already started transition.
            boolean transitionTypeChanged = mAnimator != null && mAnimator.isStarted()
                    && mLastStartedTransitionType == TRANSITION_DEFAULT
                    && animationType != TRANSITION_DEFAULT;

            if (mIsStashed != isStashed || transitionTypeChanged) {
                if (TestProtocol.sDebugTracing) {
                    Log.d(TestProtocol.TASKBAR_IN_APP_STATE, String.format(
                            "setState: mIsStashed=%b, isStashed=%b, duration=%d",
                            "setState: mIsStashed=%b, isStashed=%b, "
                                    + "mAnimationType=%d, animationType=%d, duration=%d",
                            mIsStashed,
                            isStashed,
                            mLastStartedTransitionType,
                            animationType,
                            duration));
                }
                mIsStashed = isStashed;
                mIsHotseatIconOnTopWhenAligned = isHotseatIconOnTopWhenAligned;
                mLastStartedTransitionType = animationType;

                // This sets mAnimator.
                createAnimToIsStashed(mIsStashed, duration, /* animateBg= */ true, changedFlags);
                createAnimToIsStashed(mIsStashed, duration, animationType);
                return mAnimator;
            }
            return null;
        }

        private @StashAnimation int computeTransitionType(int changedFlags) {
            boolean hotseatHiddenDuringAppLaunch =
                    !mControllers.uiController.isHotseatIconOnTopWhenAligned()
                            && hasAnyFlag(changedFlags, FLAG_IN_APP);
            if (hotseatHiddenDuringAppLaunch) {
                // When launching an app from the all-apps drawer, the hotseat is hidden behind the
                // drawer. In this case, the navbar must just fade in, without a stash transition,
                // as the taskbar stash animation would otherwise be visible above the all-apps
                // drawer once the hotseat is detached.
                return TRANSITION_HANDLE_FADE;
            }

            boolean isUnlockTransition = hasAnyFlag(changedFlags, FLAG_STASHED_DEVICE_LOCKED)
                    && !hasAnyFlag(FLAG_STASHED_DEVICE_LOCKED);
            if (isUnlockTransition) {
                // When transitioning to unlocked device, the  hotseat will already be visible on
                // the homescreen, thus do not play an un-stash animation.
                // Keep isUnlockTransition in sync with its counterpart in
                // TaskbarLauncherStateController#onStateChangeApplied.
                return TRANSITION_HANDLE_FADE;
            }

            boolean homeToApp = hasAnyFlag(changedFlags, FLAG_IN_APP) && hasAnyFlag(FLAG_IN_APP);
            if (homeToApp) {
                return TRANSITION_HOME_TO_APP;
            }

            return TRANSITION_DEFAULT;
        }
    }
}