WallpaperColors caching and synchronization

Making sure that colors are being cached in
WallpaperManagerService and that sysui won't
force a new color extraction.

Fixes: 62958267
Test: manual, reboot, look at systrace
Test: runtest -x cts/tests/app/src/android/app/cts/WallpaperManagerTest.java
Change-Id: Ic079a8e3d4d4ad65947b718dcc544f795c16f152
diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java
index 2d794fb..62fcef3 100644
--- a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java
+++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java
@@ -16,12 +16,14 @@
 
 package com.google.android.colorextraction;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.WallpaperColors;
 import android.app.WallpaperManager;
 import android.content.Context;
-import android.support.annotation.NonNull;
+import android.os.AsyncTask;
+import android.os.Trace;
 import android.support.annotation.VisibleForTesting;
-import android.support.v4.graphics.ColorUtils;
 import android.util.Log;
 import android.util.SparseArray;
 
@@ -29,6 +31,7 @@
 import com.google.android.colorextraction.types.Tonal;
 
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Class to process wallpaper colors and generate a tonal palette based on them.
@@ -50,6 +53,8 @@
     private final ArrayList<OnColorsChangedListener> mOnColorsChangedListeners;
     private final Context mContext;
     private final ExtractionType mExtractionType;
+    private WallpaperColors mSystemColors;
+    private WallpaperColors mLockColors;
 
     public ColorExtractor(Context context) {
         this(context, new Tonal());
@@ -70,7 +75,6 @@
         }
 
         mOnColorsChangedListeners = new ArrayList<>();
-
         WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
         if (wallpaperManager == null) {
             Log.w(TAG, "Can't listen to color changes!");
@@ -78,17 +82,25 @@
             wallpaperManager.addOnColorsChangedListener(this);
 
             // Initialize all gradients with the current colors
-            GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
-            extractInto(wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM),
+            Trace.beginSection("ColorExtractor#getWallpaperColors");
+            mSystemColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
+            mLockColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_LOCK);
+
+            GradientColors[] systemColors = mGradientColors.get(
+                    WallpaperManager.FLAG_SYSTEM);
+            extractInto(mSystemColors,
                     systemColors[TYPE_NORMAL],
                     systemColors[TYPE_DARK],
                     systemColors[TYPE_EXTRA_DARK]);
 
             GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK);
-            extractInto(wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_LOCK),
+            extractInto(mLockColors,
                     lockColors[TYPE_NORMAL],
                     lockColors[TYPE_DARK],
                     lockColors[TYPE_EXTRA_DARK]);
+            triggerColorsChanged(WallpaperManager.FLAG_SYSTEM
+                    | WallpaperManager.FLAG_LOCK);
+            Trace.endSection();
         }
     }
 
@@ -110,6 +122,7 @@
      * @param type TYPE_NORMAL, TYPE_DARK or TYPE_EXTRA_DARK
      * @return colors
      */
+    @NonNull
     public GradientColors getColors(int which, int type) {
         if (type != TYPE_NORMAL && type != TYPE_DARK && type != TYPE_EXTRA_DARK) {
             throw new IllegalArgumentException(
@@ -121,16 +134,35 @@
         return mGradientColors.get(which)[type];
     }
 
+    /**
+     * Get the last available WallpaperColors without forcing new extraction.
+     *
+     * @param which FLAG_LOCK or FLAG_SYSTEM
+     * @return Last cached colors
+     */
+    @Nullable
+    public WallpaperColors getWallpaperColors(int which) {
+        if (which == WallpaperManager.FLAG_LOCK) {
+            return mLockColors;
+        } else if (which == WallpaperManager.FLAG_SYSTEM) {
+            return mSystemColors;
+        } else {
+            throw new IllegalArgumentException("Invalid value for which: " + which);
+        }
+    }
+
     @Override
     public void onColorsChanged(WallpaperColors colors, int which) {
         boolean changed = false;
         if ((which & WallpaperManager.FLAG_LOCK) != 0) {
+            mLockColors = colors;
             GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK);
             extractInto(colors, lockColors[TYPE_NORMAL], lockColors[TYPE_DARK],
                     lockColors[TYPE_EXTRA_DARK]);
             changed = true;
         }
         if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
+            mSystemColors = colors;
             GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
             extractInto(colors, systemColors[TYPE_NORMAL], systemColors[TYPE_DARK],
                     systemColors[TYPE_EXTRA_DARK]);
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index bb44123..776d076 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -268,6 +268,9 @@
         mProviders.put(AccessibilityManagerWrapper.class,
                 () -> new AccessibilityManagerWrapper(mContext));
 
+        // Creating a new instance will trigger color extraction.
+        // Thankfully this only happens once - during boot - and WallpaperManagerService
+        // loads colors from cache.
         mProviders.put(SysuiColorExtractor.class, () -> new SysuiColorExtractor(mContext));
 
         mProviders.put(TunablePaddingService.class, () -> new TunablePaddingService());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 754c344..0bd58df 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -304,8 +304,8 @@
             mNeedsDrawableColorUpdate = false;
             if (mKeyguardShowing) {
                 // Always animate color changes if we're seeing the keyguard
-                mScrimInFront.setColors(mLockColors);
-                mScrimBehind.setColors(mLockColors);
+                mScrimInFront.setColors(mLockColors, true /* animated */);
+                mScrimBehind.setColors(mLockColors, true /* animated */);
             } else {
                 // Only animate scrim color if the scrim view is actually visible
                 boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index f6fab44..2118fbd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4559,16 +4559,13 @@
                 .supportsDarkText();
         // And wallpaper defines if QS should be light or dark.
         boolean useDarkTheme = false;
-        final WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
-        if (wallpaperManager != null) {
-            WallpaperColors wallpaperColors = wallpaperManager
-                    .getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
-            if (wallpaperColors != null) {
-                final int mainColor = wallpaperColors.getPrimaryColor().toArgb();
-                final float[] hsl = new float[3];
-                ColorUtils.colorToHSL(mainColor, hsl);
-                useDarkTheme = hsl[2] < 0.2f;
-            }
+        final WallpaperColors systemColors =
+                mColorExtractor.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
+        if (systemColors != null) {
+            int mainColor = systemColors.getPrimaryColor().toArgb();
+            float[] hsl = new float[3];
+            ColorUtils.colorToHSL(mainColor, hsl);
+            useDarkTheme = hsl[2] < 0.2f;
         }
 
         // Enable/disable dark UI.