Desaturating thumbnails for tasks over their usage limit

Bug: 118319143
Test: Manual
Change-Id: Iae78c42fb392a49d734d35a80f6331438149d458
diff --git a/quickstep/res/layout/task.xml b/quickstep/res/layout/task.xml
index fcc0c53..43ae9b8 100644
--- a/quickstep/res/layout/task.xml
+++ b/quickstep/res/layout/task.xml
@@ -42,6 +42,7 @@
         android:importantForAccessibility="noHideDescendants"
         android:background="#800000FF"
         android:layout_gravity="bottom"
+        android:visibility="gone"
     >
         <TextView
             android:id="@+id/remaining_time"
diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
index 4e7a0c4..a92295e 100644
--- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -34,7 +34,7 @@
 
 public final class DigitalWellBeingToast extends LinearLayout {
     public interface InitializeCallback {
-        void call(long remainingTimeMs, boolean isGroupLimit, String contentDescription);
+        void call(float saturation, String contentDescription);
     }
 
     private static final String TAG = DigitalWellBeingToast.class.getSimpleName();
@@ -49,34 +49,33 @@
 
     }
 
-    private void setRemainingTime(long remainingTime, boolean isGroupLimit) {
-        final TextView remainingTimeText = findViewById(R.id.remaining_time);
-        if (remainingTime <= 0) {
-            setVisibility(GONE);
-        } else {
-            setVisibility(VISIBLE);
-            remainingTimeText.setText(getText(remainingTime, isGroupLimit));
-        }
-    }
-
     public void initialize(Task task, InitializeCallback callback) {
         mTask = task;
         Utilities.THREAD_POOL_EXECUTOR.execute(() -> {
+            final long appUsageLimitTimeMs = -1;
             final long appRemainingTimeMs = -1;
             final boolean isGroupLimit = true;
             post(() -> {
-                setRemainingTime(appRemainingTimeMs, isGroupLimit);
+                final TextView remainingTimeText = findViewById(R.id.remaining_time);
+                if (appUsageLimitTimeMs < 0) {
+                    setVisibility(GONE);
+                } else {
+                    setVisibility(VISIBLE);
+                    remainingTimeText.setText(getText(appRemainingTimeMs, isGroupLimit));
+                }
+
                 callback.call(
-                        appRemainingTimeMs,
-                        isGroupLimit,
+                        appUsageLimitTimeMs >= 0 && appRemainingTimeMs < 0 ? 0 : 1,
                         getContentDescriptionForTask(task, appRemainingTimeMs, isGroupLimit));
             });
         });
     }
 
     public static String getText(long remainingTime, boolean isGroupLimit) {
-        return "Remaining time:" + (remainingTime + 119999) / 120000
-                + " min " + (isGroupLimit ? "for group" : "for the app");
+        return remainingTime < 0 ?
+                "Grayed" :
+                "Remaining time:" + (remainingTime + 59999) / 60000
+                        + " min " + (isGroupLimit ? "for group" : "for the app");
     }
 
     public void openAppUsageSettings() {
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index c92c8d6..6c5ddd8 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -17,13 +17,16 @@
 package com.android.quickstep.views;
 
 import static com.android.systemui.shared.system.WindowManagerWrapper.WINDOWING_MODE_FULLSCREEN;
+
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.BitmapShader;
 import android.graphics.Canvas;
 import android.graphics.Color;
-import android.graphics.LightingColorFilter;
+import android.graphics.ColorFilter;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Rect;
@@ -32,7 +35,7 @@
 import android.util.FloatProperty;
 import android.util.Property;
 import android.view.View;
-import android.view.ViewGroup;
+
 import com.android.launcher3.BaseActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
@@ -50,8 +53,8 @@
  */
 public class TaskThumbnailView extends View {
 
-    private static final LightingColorFilter[] sDimFilterCache = new LightingColorFilter[256];
-    private static final LightingColorFilter[] sHighlightFilterCache = new LightingColorFilter[256];
+    private final static ColorMatrix COLOR_MATRIX = new ColorMatrix();
+    private final static ColorMatrix SATURATION_COLOR_MATRIX = new ColorMatrix();
 
     public static final Property<TaskThumbnailView, Float> DIM_ALPHA =
             new FloatProperty<TaskThumbnailView>("dimAlpha") {
@@ -85,6 +88,7 @@
 
     private float mDimAlpha = 1f;
     private float mDimAlphaMultiplier = 1f;
+    private float mSaturation = 1f;
 
     public TaskThumbnailView(Context context) {
         this(context, null);
@@ -148,6 +152,11 @@
         updateThumbnailPaintFilter();
     }
 
+    public void setSaturation(float saturation) {
+        mSaturation = saturation;
+        updateThumbnailPaintFilter();
+    }
+
     public float getDimAlpha() {
         return mDimAlpha;
     }
@@ -221,7 +230,7 @@
     private void updateThumbnailPaintFilter() {
         int mul = (int) ((1 - mDimAlpha * mDimAlphaMultiplier) * 255);
         if (mBitmapShader != null) {
-            LightingColorFilter filter = getDimmingColorFilter(mul, mIsDarkTextTheme);
+            ColorFilter filter = getColorFilter(mul, mIsDarkTextTheme, mSaturation);
             mPaint.setColorFilter(filter);
             mBackgroundPaint.setColorFilter(filter);
         } else {
@@ -313,25 +322,34 @@
         updateThumbnailMatrix();
     }
 
-    private static LightingColorFilter getDimmingColorFilter(int intensity, boolean shouldLighten) {
+    /**
+     * @param intensity multiplier for color values. 0 - make black (white if shouldLighten), 255 -
+     *                  leave unchanged.
+     */
+    private static ColorFilter getColorFilter(int intensity, boolean shouldLighten,
+            float saturation) {
         intensity = Utilities.boundToRange(intensity, 0, 255);
-        if (intensity == 255) {
+
+        if (intensity == 255 && saturation == 1) {
             return null;
         }
-        if (shouldLighten) {
-            if (sHighlightFilterCache[intensity] == null) {
-                int colorAdd = 255 - intensity;
-                sHighlightFilterCache[intensity] = new LightingColorFilter(
-                        Color.argb(255, intensity, intensity, intensity),
-                        Color.argb(255, colorAdd, colorAdd, colorAdd));
-            }
-            return sHighlightFilterCache[intensity];
-        } else {
-            if (sDimFilterCache[intensity] == null) {
-                sDimFilterCache[intensity] = new LightingColorFilter(
-                        Color.argb(255, intensity, intensity, intensity), 0);
-            }
-            return sDimFilterCache[intensity];
+
+        final float intensityScale = intensity / 255f;
+        COLOR_MATRIX.setScale(intensityScale, intensityScale, intensityScale, 1);
+
+        if (saturation != 1) {
+            SATURATION_COLOR_MATRIX.setSaturation(saturation);
+            COLOR_MATRIX.postConcat(SATURATION_COLOR_MATRIX);
         }
+
+        if (shouldLighten) {
+            final float[] colorArray = COLOR_MATRIX.getArray();
+            final int colorAdd = 255 - intensity;
+            colorArray[4] = colorAdd;
+            colorArray[9] = colorAdd;
+            colorArray[14] = colorAdd;
+        }
+
+        return new ColorMatrixColorFilter(COLOR_MATRIX);
     }
 }
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 9b26d08..c2d7d78 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -149,8 +149,6 @@
     private TaskThumbnailCache.ThumbnailLoadRequest mThumbnailLoadRequest;
     private TaskIconCache.IconLoadRequest mIconLoadRequest;
 
-    private long mAppRemainingTimeMs = -1;
-
     public TaskView(Context context) {
         this(context, null);
     }
@@ -208,10 +206,6 @@
         return mSnapshotView.getTaskOverlay();
     }
 
-    private boolean hasRemainingTime() {
-        return mAppRemainingTimeMs > 0;
-    }
-
     public void launchTask(boolean animate) {
         launchTask(animate, (result) -> {
             if (!result) {
@@ -268,9 +262,9 @@
                         setIcon(task.icon);
                         mDigitalWellBeingToast.initialize(
                                 mTask,
-                                (appRemainingTimeMs, isGroupLimit, contentDescription) -> {
-                                    mAppRemainingTimeMs = appRemainingTimeMs;
+                                (saturation, contentDescription) -> {
                                     setContentDescription(contentDescription);
+                                    mSnapshotView.setSaturation(saturation);
                                 });
                     });
         } else {
@@ -444,7 +438,7 @@
             }
         }
 
-        if (hasRemainingTime()) {
+        if (mDigitalWellBeingToast.getVisibility() == VISIBLE) {
             info.addAction(
                     new AccessibilityNodeInfo.AccessibilityAction(
                             R.string.accessibility_app_usage_settings,