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

Commit ee9e655c authored by Jeremy Sim's avatar Jeremy Sim
Browse files

Fix bug with flickering actions bar

This CL fixes a bug caused by ag/27148514. The bug occurred because:

1) The new way we use FloatProperty to set the alpha did not have a working `get()` function, so it just returned a junk value, set to `-1f` (I didn't think `get()` would ever be called meaningfully for this property).

2) However, during certain UI interactions, `RecentsView#updateActionsViewFocusedScroll()` is called many times in a loop, which repeatedly tries to re-start the fade-in animation for actions bar. Pre ag/27148514, even though the fade-in animation was called repeatedly, it would start and then immediately stop running because it realized that it was already set to the desired alpha. However now that we return a junk value for `get()`, it didn't know to skip and just ran the full fade-in animation again and again.

Fixed by refactoring FLOAT_SETTER (now ALPHA_PROPERTY) and creating a new data class, OverviewActionsAlphaProperty, that handles some of the intricacies of this increasingly complicated alpha system.

Fixes: 339545510
Test: Swipe to Overview, move tiles around, actions bar does not flicker.
Flag: ACONFIG com.android.wm.shell.enable_app_pairs NEXTFOOD
Change-Id: I1093363780db5e0780deda2ff14b4f7361d63940
Merged-In: I1093363780db5e0780deda2ff14b4f7361d63940
parent 740a52a2
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import androidx.annotation.NonNull;

import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
@@ -167,8 +168,8 @@ public final class RecentsViewStateController extends
        propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
                clearAllButtonAlpha, LINEAR);
        float overviewButtonAlpha = state.areElementsVisible(mLauncher, OVERVIEW_ACTIONS) ? 1 : 0;
        propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlphaSetter(),
                OverviewActionsView.FLOAT_SETTER, overviewButtonAlpha, config.getInterpolator(
        propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(),
                AnimatedFloat.VALUE, overviewButtonAlpha, config.getInterpolator(
                        ANIM_OVERVIEW_ACTIONS_FADE, LINEAR));
    }

+1 −1
Original line number Diff line number Diff line
@@ -254,7 +254,7 @@ public class NoButtonQuickSwitchTouchController implements TouchController,
        TASK_THUMBNAIL_SPLASH_ALPHA.set(mRecentsView, fromState.showTaskThumbnailSplash() ? 1f : 0);
        mRecentsView.setContentAlpha(1);
        mRecentsView.setFullscreenProgress(fromState.getOverviewFullscreenProgress());
        mLauncher.getActionsView().getVisibilityAlphaSetter().accept(
        mLauncher.getActionsView().getVisibilityAlpha().updateValue(
                (fromState.getVisibleElements(mLauncher) & OVERVIEW_ACTIONS) != 0 ? 1f : 0f);
        mRecentsView.setTaskIconScaledDown(true);

+3 −3
Original line number Diff line number Diff line
@@ -42,13 +42,13 @@ import android.view.animation.Interpolator;

import androidx.annotation.NonNull;

import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.views.ClearAllButton;
import com.android.quickstep.views.OverviewActionsView;

/**
 * State controller for fallback recents activity
@@ -95,8 +95,8 @@ public class FallbackRecentsStateController implements StateHandler<RecentsState
        setter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
                clearAllButtonAlpha, LINEAR);
        float overviewButtonAlpha = state.hasOverviewActions() ? 1 : 0;
        setter.setFloat(mActivity.getActionsView().getVisibilityAlphaSetter(),
                OverviewActionsView.FLOAT_SETTER, overviewButtonAlpha, LINEAR);
        setter.setFloat(mActivity.getActionsView().getVisibilityAlpha(),
                AnimatedFloat.VALUE, overviewButtonAlpha, LINEAR);

        float[] scaleAndOffset = state.getOverviewScaleAndOffset(mActivity);
        setter.setFloat(mRecentsView, RECENTS_SCALE_PROPERTY, scaleAndOffset[0],
+31 −31
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Flags;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.NavigationMode;
@@ -42,27 +43,14 @@ import com.android.quickstep.util.LayoutUtils;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

import java.util.Arrays;
import java.util.function.Consumer;

/**
 * View for showing action buttons in Overview
 */
public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayout
        implements OnClickListener, Insettable {
    public static final FloatProperty<Consumer<Float>> FLOAT_SETTER =
            new FloatProperty<>("floatSetter") {
                @Override
                public void setValue(Consumer<Float> consumer, float v) {
                    consumer.accept(v);
                }

                @Override
                public Float get(Consumer<Float> consumer) {
                    return -1f;
                }
            };

    private final Rect mInsets = new Rect();

    @IntDef(flag = true, value = {
@@ -109,7 +97,13 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
    public @interface SplitButtonHiddenFlags { }
    public static final int FLAG_SMALL_SCREEN_HIDE_SPLIT = 1 << 0;

    /** Holds MultiValueAlpha values for all actions buttons */
    /**
     * Holds an AnimatedFloat for each alpha property, used to set or animate alpha values in
     * {@link #mMultiValueAlphas}.
     */
    private final AnimatedFloat[] mAlphaProperties = new AnimatedFloat[NUM_ALPHAS];

    /** Holds MultiValueAlpha values for all actions bars */
    private final MultiValueAlpha[] mMultiValueAlphas = new MultiValueAlpha[2];
    /** Index used for single-task actions in the mMultiValueAlphas array */
    private static final int ACTIONS_ALPHAS = 0;
@@ -159,11 +153,21 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
        // These will take up the same space on the screen and alternate visibility as needed.
        mActionButtons = findViewById(R.id.action_buttons);
        mGroupActionButtons = findViewById(R.id.group_action_buttons);
        // Initialize a list to set alpha on mActionButtons and mGroupActionButtons simultaneously.
        // Initialize a list to hold alphas for mActionButtons and mGroupActionButtons.
        mMultiValueAlphas[ACTIONS_ALPHAS] = new MultiValueAlpha(mActionButtons, NUM_ALPHAS);
        mMultiValueAlphas[GROUP_ACTIONS_ALPHAS] =
                new MultiValueAlpha(mGroupActionButtons, NUM_ALPHAS);
        Arrays.stream(mMultiValueAlphas).forEach(a -> a.setUpdateVisibility(true));
        // To control alpha simultaneously on mActionButtons and mGroupActionButtons, we set up an
        // AnimatedFloat for each alpha property.
        for (int i = 0; i < NUM_ALPHAS; i++) {
            final int index = i;
            mAlphaProperties[index] = new AnimatedFloat(() -> {
                for (MultiValueAlpha multiValueAlpha : mMultiValueAlphas) {
                    multiValueAlpha.get(index).setValue(mAlphaProperties[index].value);
                }
            }, 1f /* initialValue */);
        }

        // The screenshot button is implemented as a Button in launcher3 and NexusLauncher, but is
        // an ImageButton in go launcher (does not share a common class with Button). Take care when
@@ -220,7 +224,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
            mHiddenFlags &= ~visibilityFlags;
        }
        boolean isHidden = mHiddenFlags != 0;
        setActionsAlpha(INDEX_HIDDEN_FLAGS_ALPHA, isHidden ? 0 : 1);
        mAlphaProperties[INDEX_HIDDEN_FLAGS_ALPHA].updateValue(isHidden ? 0 : 1);
    }

    /**
@@ -305,28 +309,24 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
        }
    }

    private void setActionsAlpha(int index, float value) {
        Arrays.stream(mMultiValueAlphas).forEach(a -> a.get(index).setValue(value));
    }

    public Consumer<Float> getContentAlphaSetter() {
        return v -> setActionsAlpha(INDEX_CONTENT_ALPHA, v);
    public AnimatedFloat getContentAlpha() {
        return mAlphaProperties[INDEX_CONTENT_ALPHA];
    }

    public Consumer<Float> getVisibilityAlphaSetter() {
        return v -> setActionsAlpha(INDEX_VISIBILITY_ALPHA, v);
    public AnimatedFloat getVisibilityAlpha() {
        return mAlphaProperties[INDEX_VISIBILITY_ALPHA];
    }

    public Consumer<Float> getFullscreenAlphaSetter() {
        return v -> setActionsAlpha(INDEX_FULLSCREEN_ALPHA, v);
    public AnimatedFloat getFullscreenAlpha() {
        return mAlphaProperties[INDEX_FULLSCREEN_ALPHA];
    }

    public Consumer<Float> getShareTargetAlphaSetter() {
        return v -> setActionsAlpha(INDEX_SHARE_TARGET_ALPHA, v);
    public AnimatedFloat getShareTargetAlpha() {
        return mAlphaProperties[INDEX_SHARE_TARGET_ALPHA];
    }

    public Consumer<Float> getIndexScrollAlphaSetter() {
        return v -> setActionsAlpha(INDEX_SCROLL_ALPHA, v);
    public AnimatedFloat getIndexScrollAlpha() {
        return mAlphaProperties[INDEX_SCROLL_ALPHA];
    }

    /**
+5 −5
Original line number Diff line number Diff line
@@ -2025,7 +2025,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        mClearAllButton.setFullscreenProgress(fullscreenProgress);

        // Fade out the actions view quickly (0.1 range)
        mActionsView.getFullscreenAlphaSetter().accept(
        mActionsView.getFullscreenAlpha().updateValue(
                mapToRange(fullscreenProgress, 0, 0.1f, 1f, 0f, LINEAR));
    }

@@ -2284,8 +2284,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
    }

    private void animateActionsViewAlpha(float alphaValue, long duration) {
        mActionsViewAlphaAnimator = ObjectAnimator.ofFloat(mActionsView.getVisibilityAlphaSetter(),
                OverviewActionsView.FLOAT_SETTER, alphaValue);
        mActionsViewAlphaAnimator = ObjectAnimator.ofFloat(mActionsView.getVisibilityAlpha(),
                AnimatedFloat.VALUE, alphaValue);
        mActionsViewAlphaAnimatorFinalValue = alphaValue;
        mActionsViewAlphaAnimator.setDuration(duration);
        // Set autocancel to prevent race-conditiony setting of alpha from other animations
@@ -2304,7 +2304,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        mClearAllButton.onRecentsViewScroll(scroll, mOverviewGridEnabled);

        // Clear all button alpha was set by the previous line.
        mActionsView.getIndexScrollAlphaSetter().accept(1 - mClearAllButton.getScrollAlpha());
        mActionsView.getIndexScrollAlpha().updateValue(1 - mClearAllButton.getScrollAlpha());
    }

    @Override
@@ -4312,7 +4312,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        int alphaInt = Math.round(alpha * 255);
        mEmptyMessagePaint.setAlpha(alphaInt);
        mEmptyIcon.setAlpha(alphaInt);
        mActionsView.getContentAlphaSetter().accept(mContentAlpha);
        mActionsView.getContentAlpha().updateValue(mContentAlpha);

        if (alpha > 0) {
            setVisibility(VISIBLE);