Merge "Animate the dot with the bubble bar" into main
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
index 07481a2..753237a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarView.java
@@ -895,16 +895,18 @@
                 // where the bubble will end up when the animation ends
                 final float targetX = expandedX + expandedBarShift;
                 bv.setTranslationX(widthState * (targetX - collapsedX) + collapsedX);
-                // When we're expanded, we're not stacked so we're not behind the stack
-                bv.setBehindStack(false, animate);
+                // When we're expanded, the badge is visible for all bubbles
+                bv.updateBadgeVisibility(/* show= */ true);
+                bv.setDotScale(widthState);
                 bv.setAlpha(1);
             } else {
                 // If bar is on the right, account for bubble bar expanding and shifting left
                 final float collapsedBarShift = onLeft ? 0 : currentWidth - collapsedWidth;
                 final float targetX = collapsedX + collapsedBarShift;
                 bv.setTranslationX(widthState * (expandedX - targetX) + targetX);
-                // If we're not the first bubble we're behind the stack
-                bv.setBehindStack(i > 0, animate);
+                // The badge is always visible for the first bubble
+                bv.updateBadgeVisibility(/* show= */ i == 0);
+                bv.setDotScale(widthState);
                 // If we're fully collapsed, hide all bubbles except for the first 2. If there are
                 // only 2 bubbles, hide the second bubble as well because it's the overflow.
                 if (widthState == 0) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
index 2f92fbb..0e26c54 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleView.java
@@ -35,8 +35,6 @@
 import com.android.launcher3.icons.IconNormalizer;
 import com.android.wm.shell.animation.Interpolators;
 
-import java.util.EnumSet;
-
 // TODO: (b/276978250) This is will be similar to WMShell's BadgedImageView, it'd be nice to share.
 
 /**
@@ -47,22 +45,6 @@
 
     public static final int DEFAULT_PATH_SIZE = 100;
 
-    /**
-     * Flags that suppress the visibility of the 'new' dot or the app badge, for one reason or
-     * another. If any of these flags are set, the dot will not be shown.
-     * If {@link SuppressionFlag#BEHIND_STACK} then the app badge will not be shown.
-     */
-    enum SuppressionFlag {
-        // TODO: (b/277815200) implement flyout
-        // Suppressed because the flyout is visible - it will morph into the dot via animation.
-        FLYOUT_VISIBLE,
-        // Suppressed because this bubble is behind others in the collapsed stack.
-        BEHIND_STACK,
-    }
-
-    private final EnumSet<SuppressionFlag> mSuppressionFlags =
-            EnumSet.noneOf(SuppressionFlag.class);
-
     private final ImageView mBubbleIcon;
     private final ImageView mAppIcon;
     private final int mBubbleSize;
@@ -230,7 +212,7 @@
         }
     }
 
-    void updateBadgeVisibility() {
+    void updateBadgeVisibility(boolean show) {
         if (mBubble instanceof BubbleBarOverflow) {
             // The overflow bubble does not have a badge, so just bail.
             return;
@@ -241,39 +223,24 @@
                 ? -(bubble.getIcon().getWidth() - appBadgeBitmap.getWidth())
                 : 0;
         mAppIcon.setTranslationX(translationX);
-        mAppIcon.setVisibility(isBehindStack() ? GONE : VISIBLE);
-    }
-
-    /** Sets whether this bubble is in the stack & not the first bubble. **/
-    void setBehindStack(boolean behindStack, boolean animate) {
-        if (behindStack) {
-            mSuppressionFlags.add(SuppressionFlag.BEHIND_STACK);
-        } else {
-            mSuppressionFlags.remove(SuppressionFlag.BEHIND_STACK);
-        }
-        updateDotVisibility(animate);
-        updateBadgeVisibility();
-    }
-
-    /** Whether this bubble is in the stack & not the first bubble. **/
-    boolean isBehindStack() {
-        return mSuppressionFlags.contains(SuppressionFlag.BEHIND_STACK);
+        mAppIcon.setVisibility(show ? VISIBLE : GONE);
     }
 
     /** Whether the dot indicating unseen content in a bubble should be shown. */
     private boolean shouldDrawDot() {
         boolean bubbleHasUnseenContent = mBubble != null
                 && mBubble instanceof BubbleBarBubble
-                && mSuppressionFlags.isEmpty()
                 && !((BubbleBarBubble) mBubble).getInfo().isNotificationSuppressed();
-
         // Always render the dot if it's animating, since it could be animating out. Otherwise, show
         // it if the bubble wants to show it, and we aren't suppressing it.
         return bubbleHasUnseenContent || mDotIsAnimating;
     }
 
     /** How big the dot should be, fraction from 0 to 1. */
-    private void setDotScale(float fraction) {
+    void setDotScale(float fraction) {
+        if (!shouldDrawDot()) {
+            return;
+        }
         mDotScale = fraction;
         invalidate();
     }
@@ -283,14 +250,14 @@
      */
     private void animateDotScale() {
         float toScale = shouldDrawDot() ? 1f : 0f;
-        mDotIsAnimating = true;
+        boolean isDotScaleChanging = Float.compare(mDotScale, toScale) != 0;
 
-        // Don't restart the animation if we're already animating to the given value.
-        if (mAnimatingToDotScale == toScale || !shouldDrawDot()) {
-            mDotIsAnimating = false;
+        // Don't restart the animation if we're already animating to the given value or if the dot
+        // scale is not changing
+        if ((mDotIsAnimating && mAnimatingToDotScale == toScale) || !isDotScaleChanging) {
             return;
         }
-
+        mDotIsAnimating = true;
         mAnimatingToDotScale = toScale;
 
         final boolean showDot = toScale > 0f;