Merge "Add finish icon scale animation for downloading apps" into tm-qpr-dev
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 9f54f09..edbce10 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -16,11 +16,14 @@
 
 package com.android.launcher3;
 
+import static com.android.launcher3.config.FeatureFlags.ENABLE_DOWNLOAD_APP_UX_V2;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_ICON_LABEL_AUTO_SCALING;
 import static com.android.launcher3.graphics.PreloadIconDrawable.newPendingIcon;
 import static com.android.launcher3.icons.BitmapInfo.FLAG_NO_BADGE;
 import static com.android.launcher3.icons.BitmapInfo.FLAG_THEMED;
 import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
+import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INCREMENTAL_DOWNLOAD_ACTIVE;
+import static com.android.launcher3.model.data.ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -291,7 +294,7 @@
 
     @UiThread
     public void applyFromWorkspaceItem(WorkspaceItemInfo info, boolean animate, int staggerIndex) {
-        applyFromWorkspaceItem(info, false);
+        applyFromWorkspaceItem(info, null);
     }
 
     /**
@@ -320,10 +323,10 @@
     }
 
     @UiThread
-    public void applyFromWorkspaceItem(WorkspaceItemInfo info, boolean promiseStateChanged) {
+    public void applyFromWorkspaceItem(WorkspaceItemInfo info, PreloadIconDrawable icon) {
         applyIconAndLabel(info);
         setItemInfo(info);
-        applyLoadingState(promiseStateChanged);
+        applyLoadingState(icon);
         applyDotState(info, false /* animate */);
         setDownloadStateContentDescription(info, info.getProgressLevel());
     }
@@ -710,23 +713,23 @@
      * If this app is installed and downloading incrementally, the progress bar will be updated
      * with the total download progress.
      */
-    public void applyLoadingState(boolean promiseStateChanged) {
+    public void applyLoadingState(PreloadIconDrawable icon) {
         if (getTag() instanceof ItemInfoWithIcon) {
             WorkspaceItemInfo info = (WorkspaceItemInfo) getTag();
-            if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_INCREMENTAL_DOWNLOAD_ACTIVE)
-                    != 0) {
-                updateProgressBarUi(info.getProgressLevel() == 100);
-            } else if (info.hasPromiseIconUi() || (info.runtimeStatusFlags
-                        & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
-                updateProgressBarUi(promiseStateChanged);
+            if ((info.runtimeStatusFlags & FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0
+                    || info.hasPromiseIconUi()
+                    || (info.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0
+                    || (ENABLE_DOWNLOAD_APP_UX_V2.get() && icon != null)) {
+                updateProgressBarUi(icon);
             }
         }
     }
 
-    private void updateProgressBarUi(boolean maybePerformFinishedAnimation) {
+    private void updateProgressBarUi(PreloadIconDrawable oldIcon) {
+        FastBitmapDrawable originalIcon = mIcon;
         PreloadIconDrawable preloadDrawable = applyProgressLevel();
-        if (preloadDrawable != null && maybePerformFinishedAnimation) {
-            preloadDrawable.maybePerformFinishedAnimation();
+        if (preloadDrawable != null && oldIcon != null) {
+            preloadDrawable.maybePerformFinishedAnimation(oldIcon, () -> setIcon(originalIcon));
         }
     }
 
@@ -824,12 +827,12 @@
                 != 0) {
             String percentageString = NumberFormat.getPercentInstance()
                     .format(progressLevel * 0.01);
-            if ((info.runtimeStatusFlags & ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE) != 0) {
+            if ((info.runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) {
                 setContentDescription(getContext()
                         .getString(
                             R.string.app_installing_title, info.title, percentageString));
             } else if ((info.runtimeStatusFlags
-                    & ItemInfoWithIcon.FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0) {
+                    & FLAG_INCREMENTAL_DOWNLOAD_ACTIVE) != 0) {
                 setContentDescription(getContext()
                         .getString(
                             R.string.app_downloading_title, info.title, percentageString));
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index de47cb5..9001a52 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -28,6 +28,7 @@
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.ColorFilter;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Path;
@@ -41,6 +42,7 @@
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatedFloat;
+import com.android.launcher3.anim.AnimatorListeners;
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.icons.GraphicsUtils;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
@@ -53,7 +55,7 @@
 /**
  * Extension of {@link FastBitmapDrawable} which shows a progress bar around the icon.
  */
-public class PreloadIconDrawable extends FastBitmapDrawable implements Runnable {
+public class PreloadIconDrawable extends FastBitmapDrawable {
 
     private static final Property<PreloadIconDrawable, Float> INTERNAL_STATE =
             new Property<PreloadIconDrawable, Float>(Float.TYPE, "internalStateProgress") {
@@ -78,16 +80,19 @@
 
     // The smaller the number, the faster the animation would be.
     // Duration = COMPLETE_ANIM_FRACTION * DURATION_SCALE
-    private static final float COMPLETE_ANIM_FRACTION = 0.3f;
+    private static final float COMPLETE_ANIM_FRACTION = 1f;
 
     private static final float SMALL_SCALE = ENABLE_DOWNLOAD_APP_UX_V2.get() ? 0.867f : 0.7f;
-    private static final float PROGRESS_STROKE_SCALE = 0.075f;
+    private static final float PROGRESS_STROKE_SCALE = ENABLE_DOWNLOAD_APP_UX_V2.get()
+            ? 0.0655f
+            : 0.075f;
+    private static final float PROGRESS_BOUNDS_SCALE = 0.075f;
 
     private static final int PRELOAD_ACCENT_COLOR_INDEX = 0;
     private static final int PRELOAD_BACKGROUND_COLOR_INDEX = 1;
 
     private static final int ALPHA_DURATION_MILLIS = 3000;
-    private static final float OVERLAY_ALPHA_RANGE = 127.5f;
+    private static final int OVERLAY_ALPHA_RANGE = 127;
     private static final long WAVE_MOTION_DELAY_FACTOR_MILLIS = 100;
     private static final WeakHashMap<Integer, PorterDuffColorFilter> COLOR_FILTER_MAP =
             new WeakHashMap<>();
@@ -111,19 +116,17 @@
     private final int mSystemBackgroundColor;
     private final boolean mIsDarkMode;
 
-    private int mTrackAlpha;
     private float mTrackLength;
 
     private boolean mRanFinishAnimation;
-
     private final int mRefreshRateMillis;
-    private final AnimatedFloat mIconScale = new AnimatedFloat(this::invalidateSelf);
-    private final AnimatedFloat mOverlayAlpha = new AnimatedFloat(this::updateOverlayAlpha);
-    private boolean mShouldAnimateScaleAndAlpha;
 
     // Progress of the internal state. [0, 1] indicates the fraction of completed progress,
     // [1, (1 + COMPLETE_ANIM_FRACTION)] indicates the progress of zoom animation.
     private float mInternalStateProgress;
+    // This multiplier is used to animate scale when going from 0 to non-zero and expanding
+    private final Runnable mInvalidateRunnable = this::invalidateSelf;
+    private final AnimatedFloat mIconScaleMultiplier = new AnimatedFloat(mInvalidateRunnable);
 
     private ObjectAnimator mCurrentAnim;
 
@@ -160,10 +163,7 @@
         mRefreshRateMillis = refreshRateMillis;
 
         // If it's a pending app we will animate scale and alpha when it's no longer pending.
-        if (ENABLE_DOWNLOAD_APP_UX_V2.get() && info.getProgressLevel() == 0) {
-            mShouldAnimateScaleAndAlpha = true;
-            mOverlayAlpha.updateValue(127);
-        }
+        mIconScaleMultiplier.updateValue(info.getProgressLevel() == 0 ? 0 : 1);
 
         setLevel(info.getProgressLevel());
         setIsStartable(info.isAppStartable());
@@ -173,14 +173,17 @@
     protected void onBoundsChange(Rect bounds) {
         super.onBoundsChange(bounds);
 
-        float progressWidth = PROGRESS_STROKE_SCALE * bounds.width();
+
+        float progressWidth = bounds.width() * (ENABLE_DOWNLOAD_APP_UX_V2.get()
+                ? PROGRESS_BOUNDS_SCALE
+                : PROGRESS_STROKE_SCALE);
         mTmpMatrix.setScale(
                 (bounds.width() - 2 * progressWidth) / DEFAULT_PATH_SIZE,
                 (bounds.height() - 2 * progressWidth) / DEFAULT_PATH_SIZE);
         mTmpMatrix.postTranslate(bounds.left + progressWidth, bounds.top + progressWidth);
 
         mShapePath.transform(mTmpMatrix, mScaledTrackPath);
-        mProgressPaint.setStrokeWidth(progressWidth);
+        mProgressPaint.setStrokeWidth(PROGRESS_STROKE_SCALE * bounds.width());
 
         mPathMeasure.setPath(mScaledTrackPath, true);
         mTrackLength = mPathMeasure.getLength();
@@ -195,26 +198,35 @@
             return;
         }
 
-        // Draw background.
-        mProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);
-        mProgressPaint.setColor(mSystemBackgroundColor);
-        canvas.drawPath(mScaledTrackPath, mProgressPaint);
+        if (!ENABLE_DOWNLOAD_APP_UX_V2.get() && mInternalStateProgress > 0) {
+            // Draw background.
+            mProgressPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+            mProgressPaint.setColor(mSystemBackgroundColor);
+            canvas.drawPath(mScaledTrackPath, mProgressPaint);
+        }
 
-        // Draw track and progress.
-        mProgressPaint.setStyle(Paint.Style.STROKE);
-        mProgressPaint.setColor(mIsStartable ? mIndicatorColor : mSystemAccentColor);
-        mProgressPaint.setAlpha(TRACK_ALPHA);
-        canvas.drawPath(mScaledTrackPath, mProgressPaint);
-        mProgressPaint.setAlpha(mTrackAlpha);
-        canvas.drawPath(mScaledProgressPath, mProgressPaint);
+        if (!ENABLE_DOWNLOAD_APP_UX_V2.get() || mInternalStateProgress > 0) {
+            // Draw track and progress.
+            mProgressPaint.setStyle(Paint.Style.STROKE);
+            mProgressPaint.setColor(mSystemAccentColor);
+            mProgressPaint.setAlpha(TRACK_ALPHA);
+            canvas.drawPath(mScaledTrackPath, mProgressPaint);
+            mProgressPaint.setAlpha(MAX_PAINT_ALPHA);
+            canvas.drawPath(mScaledProgressPath, mProgressPaint);
+        }
 
         int saveCount = canvas.save();
-        canvas.scale(
-                mIconScale.value, mIconScale.value, bounds.exactCenterX(), bounds.exactCenterY());
+        float scale = ENABLE_DOWNLOAD_APP_UX_V2.get()
+                ? 1 - mIconScaleMultiplier.value * (1 - SMALL_SCALE)
+                : SMALL_SCALE;
+        canvas.scale(scale, scale, bounds.exactCenterX(), bounds.exactCenterY());
+
+        ColorFilter filter = getOverlayFilter();
+        mPaint.setColorFilter(filter);
         super.drawInternal(canvas, bounds);
         canvas.restoreToCount(saveCount);
 
-        if (ENABLE_DOWNLOAD_APP_UX_V2.get() && mInternalStateProgress == 0) {
+        if (ENABLE_DOWNLOAD_APP_UX_V2.get() && filter != null) {
             reschedule();
         }
     }
@@ -232,7 +244,7 @@
     @Override
     protected boolean onLevelChange(int level) {
         // Run the animation if we have already been bound.
-        updateInternalState(level * 0.01f,  getBounds().width() > 0, false);
+        updateInternalState(level * 0.01f, false, null);
         return true;
     }
 
@@ -240,12 +252,18 @@
      * Runs the finish animation if it is has not been run after last call to
      * {@link #onLevelChange}
      */
-    public void maybePerformFinishedAnimation() {
+    public void maybePerformFinishedAnimation(
+            PreloadIconDrawable oldIcon, Runnable onFinishCallback) {
+
+        if (oldIcon.mInternalStateProgress >= 1) {
+            mInternalStateProgress = oldIcon.mInternalStateProgress;
+        }
+
         // If the drawable was recently initialized, skip the progress animation.
         if (mInternalStateProgress == 0) {
             mInternalStateProgress = 1;
         }
-        updateInternalState(1 + COMPLETE_ANIM_FRACTION, true, true);
+        updateInternalState(1 + COMPLETE_ANIM_FRACTION, true, onFinishCallback);
     }
 
     public boolean hasNotCompleted() {
@@ -260,26 +278,29 @@
         }
     }
 
-    private void updateInternalState(float finalProgress, boolean shouldAnimate, boolean isFinish) {
+    private void updateInternalState(
+            float finalProgress, boolean isFinish, Runnable onFinishCallback) {
         if (mCurrentAnim != null) {
             mCurrentAnim.cancel();
             mCurrentAnim = null;
         }
 
-        if (Float.compare(finalProgress, mInternalStateProgress) == 0) {
-            return;
-        }
-        if (finalProgress < mInternalStateProgress) {
-            shouldAnimate = false;
-        }
-        if (!shouldAnimate || mRanFinishAnimation) {
+        boolean animateProgress =
+                finalProgress >= mInternalStateProgress && getBounds().width() > 0;
+        if (!animateProgress || mRanFinishAnimation) {
             setInternalProgress(finalProgress);
+            if (isFinish && onFinishCallback != null) {
+                onFinishCallback.run();
+            }
         } else {
             mCurrentAnim = ObjectAnimator.ofFloat(this, INTERNAL_STATE, finalProgress);
             mCurrentAnim.setDuration(
                     (long) ((finalProgress - mInternalStateProgress) * DURATION_SCALE));
             mCurrentAnim.setInterpolator(LINEAR);
             if (isFinish) {
+                if (onFinishCallback != null) {
+                    mCurrentAnim.addListener(AnimatorListeners.forEndCallback(onFinishCallback));
+                }
                 mCurrentAnim.addListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationEnd(Animator animation) {
@@ -297,62 +318,38 @@
      *     - icon with pending motion
      *     - progress track is not visible
      *     - progress bar is not visible
-     *   for progress < 1
+     *   for progress < 1:
      *     - icon without pending motion
      *     - progress track is visible
      *     - progress bar is visible. Progress bar is drawn as a fraction of
      *       {@link #mScaledTrackPath}.
      *       @see PathMeasure#getSegment(float, float, Path, boolean)
-     *   for 1 <= progress < (1 + COMPLETE_ANIM_FRACTION)
-     *     - we calculate fraction of progress in the above range
-     *     - progress track is drawn with alpha based on fraction
-     *     - progress bar is drawn at 100% with alpha based on fraction
-     *     - icon is scaled up based on fraction and is drawn in enabled state
-     *   for progress >= (1 + COMPLETE_ANIM_FRACTION)
-     *     - only icon is drawn in normal state
+     *   for progress > 1:
+     *     - scale the icon back to full size
      */
     private void setInternalProgress(float progress) {
         // Animate scale and alpha from pending to downloading state.
-        if (ENABLE_DOWNLOAD_APP_UX_V2.get()
-                && mShouldAnimateScaleAndAlpha && mInternalStateProgress == 0 && progress > 0) {
-            Animator iconScaleAnimator = mIconScale.animateToValue(SMALL_SCALE);
+        if (ENABLE_DOWNLOAD_APP_UX_V2.get() && progress > 0 && mInternalStateProgress == 0) {
+            // Progress is changing for the first time, animate the icon scale
+            Animator iconScaleAnimator = mIconScaleMultiplier.animateToValue(1);
             iconScaleAnimator.setDuration(SCALE_AND_ALPHA_ANIM_DURATION);
             iconScaleAnimator.setInterpolator(EMPHASIZED);
             iconScaleAnimator.start();
-
-            Animator overlayAlphaAnimator = mOverlayAlpha.animateToValue(0);
-            overlayAlphaAnimator.setDuration(SCALE_AND_ALPHA_ANIM_DURATION);
-            overlayAlphaAnimator.setInterpolator(EMPHASIZED);
-            overlayAlphaAnimator.start();
         }
 
         mInternalStateProgress = progress;
         if (progress <= 0) {
-            mIconScale.updateValue(ENABLE_DOWNLOAD_APP_UX_V2.get() ? 1 : SMALL_SCALE);
-            mScaledTrackPath.reset();
-            mTrackAlpha = MAX_PAINT_ALPHA;
-        } else if (progress < 1) {
-            mPathMeasure.getSegment(0, progress * mTrackLength, mScaledProgressPath, true);
-            if (ENABLE_DOWNLOAD_APP_UX_V2.get()) {
-                mPathMeasure.getSegment(0, mTrackLength, mScaledTrackPath, true);
+            if (!ENABLE_DOWNLOAD_APP_UX_V2.get()) {
+                mScaledTrackPath.reset();
             }
-
-            if (!ENABLE_DOWNLOAD_APP_UX_V2.get() || !mShouldAnimateScaleAndAlpha) {
-                mIconScale.updateValue(SMALL_SCALE);
-            }
-            mTrackAlpha = MAX_PAINT_ALPHA;
+            mIconScaleMultiplier.updateValue(0);
         } else {
-            setIsDisabled(mItem.isDisabled());
-            mScaledTrackPath.set(mScaledProgressPath);
-            float fraction = (progress - 1) / COMPLETE_ANIM_FRACTION;
-
-            if (fraction >= 1) {
-                // Animation has completed
-                mIconScale.updateValue(1);
-                mTrackAlpha = 0;
-            } else {
-                mTrackAlpha = Math.round((1 - fraction) * MAX_PAINT_ALPHA);
-                mIconScale.updateValue(SMALL_SCALE + (1 - SMALL_SCALE) * fraction);
+            mPathMeasure.getSegment(
+                    0, Math.min(progress, 1) * mTrackLength, mScaledProgressPath, true);
+            if (progress > 1 && ENABLE_DOWNLOAD_APP_UX_V2.get()) {
+                // map the scale back to original value
+                mIconScaleMultiplier.updateValue(Utilities.mapBoundToRange(
+                        progress - 1, 0, COMPLETE_ANIM_FRACTION, 1, 0, EMPHASIZED));
             }
         }
         invalidateSelf();
@@ -393,71 +390,48 @@
     }
 
     @Override
-    public void run() {
-        if (!ENABLE_DOWNLOAD_APP_UX_V2.get() || mInternalStateProgress > 0) {
-            return;
-        }
-        if (!applyPendingIconOverlay()) {
-            reschedule();
-        }
-    }
-
-    @Override
     public boolean setVisible(boolean visible, boolean restart) {
-        boolean result = super.setVisible(visible, restart);
-        if (visible) {
-            reschedule();
-        } else {
-            unscheduleSelf(this);
+        if (!visible) {
+            unscheduleSelf(mInvalidateRunnable);
         }
-        return result;
+        return super.setVisible(visible, restart);
     }
 
     private void reschedule() {
-        unscheduleSelf(this);
-
+        unscheduleSelf(mInvalidateRunnable);
         if (!isVisible()) {
             return;
         }
-
         final long upTime = SystemClock.uptimeMillis();
-        scheduleSelf(this, upTime - ((upTime % mRefreshRateMillis)) + mRefreshRateMillis);
+        scheduleSelf(mInvalidateRunnable,
+                upTime - ((upTime % mRefreshRateMillis)) + mRefreshRateMillis);
     }
 
-
     /**
-     * Apply an overlay on the pending icon with cascading motion based on its position.
-     * Returns {@code true} if the icon alpha is updated, so that we re-draw.
+     * Returns a color filter to be used as an overlay on the pending icon with cascading motion
+     * based on its position.
      */
-    private boolean applyPendingIconOverlay() {
+    private ColorFilter getOverlayFilter() {
+        if (!ENABLE_DOWNLOAD_APP_UX_V2.get() || mInternalStateProgress > 0) {
+            // If the download has started, we do no need to animate
+            return null;
+        }
         long waveMotionDelay = (mItem.cellX * WAVE_MOTION_DELAY_FACTOR_MILLIS)
                 + (mItem.cellY * WAVE_MOTION_DELAY_FACTOR_MILLIS);
         long time = SystemClock.uptimeMillis();
-        float newAlpha = Utilities.mapBoundToRange(
-                (float) (time + waveMotionDelay) % ALPHA_DURATION_MILLIS,
+        int alpha = (int) Utilities.mapBoundToRange(
+                (int) ((time + waveMotionDelay) % ALPHA_DURATION_MILLIS),
                 0,
                 ALPHA_DURATION_MILLIS,
                 0,
-                MAX_PAINT_ALPHA,
+                OVERLAY_ALPHA_RANGE * 2,
                 LINEAR);
-        if (newAlpha > OVERLAY_ALPHA_RANGE) {
-            newAlpha = (OVERLAY_ALPHA_RANGE - (newAlpha % OVERLAY_ALPHA_RANGE));
+        if (alpha > OVERLAY_ALPHA_RANGE) {
+            alpha = (OVERLAY_ALPHA_RANGE - (alpha % OVERLAY_ALPHA_RANGE));
         }
-
-        boolean invalidate = false;
-        if ((int) mOverlayAlpha.value != newAlpha) {
-            mOverlayAlpha.updateValue(newAlpha);
-            invalidate = true;
-        }
-        return invalidate;
-    }
-
-    private void updateOverlayAlpha() {
         int overlayColor = mIsDarkMode ? 0 : 255;
-        int currArgb =
-                Color.argb((int) mOverlayAlpha.value, overlayColor, overlayColor, overlayColor);
-        mPaint.setColorFilter(COLOR_FILTER_MAP.computeIfAbsent(currArgb, FILTER_FACTORY));
-        invalidateSelf();
+        int currArgb = Color.argb(alpha, overlayColor, overlayColor, overlayColor);
+        return COLOR_FILTER_MAP.computeIfAbsent(currArgb, FILTER_FACTORY);
     }
 
     protected static class PreloadIconConstantState extends FastBitmapConstantState {
diff --git a/src/com/android/launcher3/util/LauncherBindableItemsContainer.java b/src/com/android/launcher3/util/LauncherBindableItemsContainer.java
index a4cb30a..f73940b 100644
--- a/src/com/android/launcher3/util/LauncherBindableItemsContainer.java
+++ b/src/com/android/launcher3/util/LauncherBindableItemsContainer.java
@@ -50,7 +50,12 @@
                 Drawable oldIcon = shortcut.getIcon();
                 boolean oldPromiseState = (oldIcon instanceof PreloadIconDrawable)
                         && ((PreloadIconDrawable) oldIcon).hasNotCompleted();
-                shortcut.applyFromWorkspaceItem(si, si.isPromise() != oldPromiseState);
+                shortcut.applyFromWorkspaceItem(
+                        si,
+                        si.isPromise() != oldPromiseState
+                                && oldIcon instanceof PreloadIconDrawable
+                                ? (PreloadIconDrawable) oldIcon
+                                : null);
             } else if (info instanceof FolderInfo && v instanceof FolderIcon) {
                 ((FolderIcon) v).updatePreviewItems(updates::contains);
             }
@@ -74,7 +79,7 @@
         ItemOperator op = (info, v) -> {
             if (info instanceof WorkspaceItemInfo && v instanceof BubbleTextView
                     && updates.contains(info)) {
-                ((BubbleTextView) v).applyLoadingState(false /* promiseStateChanged */);
+                ((BubbleTextView) v).applyLoadingState(null);
             } else if (v instanceof PendingAppWidgetHostView
                     && info instanceof LauncherAppWidgetInfo
                     && updates.contains(info)) {