Applying API changes on WallpaperColors.

Bug: 62719001
Change-Id: Iabe2e446bd05c41ec910ed2ad534d623285e7e63
diff --git a/src/com/android/launcher3/compat/WallpaperColorsCompat.java b/src/com/android/launcher3/compat/WallpaperColorsCompat.java
index fd08f94..58d2a80 100644
--- a/src/com/android/launcher3/compat/WallpaperColorsCompat.java
+++ b/src/com/android/launcher3/compat/WallpaperColorsCompat.java
@@ -15,29 +15,40 @@
  */
 package com.android.launcher3.compat;
 
-import android.util.SparseIntArray;
-
 /**
  * A compatibility layer around platform implementation of WallpaperColors
  */
 public class WallpaperColorsCompat {
 
-    private final SparseIntArray mColors;
-    private final boolean mSupportsDarkText;
+    public static final int HINT_SUPPORTS_DARK_TEXT = 0x1;
 
-    public WallpaperColorsCompat(SparseIntArray colors, boolean supportsDarkText) {
-        mColors = colors;
-        mSupportsDarkText = supportsDarkText;
+    private final int mPrimaryColor;
+    private final int mSecondaryColor;
+    private final int mTertiaryColor;
+    private final int mColorHints;
+
+    public WallpaperColorsCompat(int primaryColor, int secondaryColor, int tertiaryColor,
+            int colorHints) {
+        mPrimaryColor = primaryColor;
+        mSecondaryColor = secondaryColor;
+        mTertiaryColor = tertiaryColor;
+        mColorHints = colorHints;
     }
 
-    /**
-     * A map of color code to their occurrences. The bigger the int, the more relevant the color.
-     */
-    public SparseIntArray getColors() {
-        return mColors;
+    public int getPrimaryColor() {
+        return mPrimaryColor;
     }
 
-    public boolean supportsDarkText() {
-        return mSupportsDarkText;
+    public int getSecondaryColor() {
+        return mSecondaryColor;
     }
+
+    public int getTertiaryColor() {
+        return mTertiaryColor;
+    }
+
+    public int getColorHints() {
+        return mColorHints;
+    }
+
 }
diff --git a/src/com/android/launcher3/compat/WallpaperManagerCompatVL.java b/src/com/android/launcher3/compat/WallpaperManagerCompatVL.java
index 8bdcedb..8e572ee 100644
--- a/src/com/android/launcher3/compat/WallpaperManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/WallpaperManagerCompatVL.java
@@ -15,10 +15,6 @@
  */
 package com.android.launcher3.compat;
 
-import static android.app.WallpaperManager.FLAG_SYSTEM;
-
-import static com.android.launcher3.Utilities.getDevicePrefs;
-
 import android.app.WallpaperInfo;
 import android.app.WallpaperManager;
 import android.app.job.JobInfo;
@@ -45,12 +41,17 @@
 import android.support.v7.graphics.Palette;
 import android.util.Log;
 import android.util.Pair;
-import android.util.SparseIntArray;
 
 import com.android.launcher3.Utilities;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import static android.app.WallpaperManager.FLAG_SYSTEM;
+import static com.android.launcher3.Utilities.getDevicePrefs;
 
 public class WallpaperManagerCompatVL extends WallpaperManagerCompat {
 
@@ -154,11 +155,12 @@
             return Pair.create(wallpaperId, null);
         }
 
-        SparseIntArray colorsToOccurrences = new SparseIntArray((parts.length - 2) / 2);
-        for (int i = 2; i < parts.length; i += 2) {
-            colorsToOccurrences.put(Integer.parseInt(parts[i]), Integer.parseInt(parts[i + 1]));
-        }
-        return Pair.create(wallpaperId, new WallpaperColorsCompat(colorsToOccurrences, false));
+        int primary = parts.length > 2 ? Integer.parseInt(parts[2]) : 0;
+        int secondary = parts.length > 3 ? Integer.parseInt(parts[3]) : 0;
+        int tertiary = parts.length > 4 ? Integer.parseInt(parts[4]) : 0;
+
+        return Pair.create(wallpaperId, new WallpaperColorsCompat(primary, secondary, tertiary,
+                0 /* hints */));
     }
 
     /**
@@ -262,12 +264,22 @@
                 bitmap.recycle();
 
                 StringBuilder builder = new StringBuilder(value);
+                List<Pair<Integer,Integer>> colorsToOccurrences = new ArrayList<>();
                 for (Palette.Swatch swatch : palette.getSwatches()) {
-                    builder.append(',')
-                            .append(swatch.getRgb())
-                            .append(',')
-                            .append(swatch.getPopulation());
+                    colorsToOccurrences.add(new Pair(swatch.getRgb(), swatch.getPopulation()));
                 }
+
+                Collections.sort(colorsToOccurrences, new Comparator<Pair<Integer, Integer>>() {
+                    @Override
+                    public int compare(Pair<Integer, Integer> a, Pair<Integer, Integer> b) {
+                        return b.second - a.second;
+                    }
+                });
+
+                for (int i=0; i < Math.min(3, colorsToOccurrences.size()); i++) {
+                    builder.append(',').append(colorsToOccurrences.get(i).first);
+                }
+
                 value = builder.toString();
             }
 
diff --git a/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java b/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java
index c74ccc0..6233fab 100644
--- a/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java
+++ b/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java
@@ -22,13 +22,10 @@
 import android.os.Build;
 import android.support.annotation.Nullable;
 import android.util.Log;
-import android.util.Pair;
-import android.util.SparseIntArray;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
-import java.util.List;
 
 @TargetApi(Build.VERSION_CODES.O)
 public class WallpaperManagerCompatVOMR1 extends WallpaperManagerCompat {
@@ -41,8 +38,10 @@
     private final Method mAddOCLMethod;
 
     private final Method mWCGetMethod;
-    private final Method mWCGetColorsMethod;
-    private final Method mWCSupportsDarkTextMethod;
+    private final Method mWCGetPrimaryColorMethod;
+    private final Method mWCGetSecondaryColorMethod;
+    private final Method mWCGetTertiaryColorMethod;
+    private final Method mWCColorHintsMethod;
 
     WallpaperManagerCompatVOMR1(Context context) throws Exception {
         mWm = context.getSystemService(WallpaperManager.class);
@@ -53,8 +52,10 @@
 
         mWCGetMethod = WallpaperManager.class.getDeclaredMethod("getWallpaperColors", int.class);
         Class wallpaperColorsClass = mWCGetMethod.getReturnType();
-        mWCGetColorsMethod = wallpaperColorsClass.getDeclaredMethod("getColors");
-        mWCSupportsDarkTextMethod = wallpaperColorsClass.getDeclaredMethod("supportsDarkText");
+        mWCGetPrimaryColorMethod = wallpaperColorsClass.getDeclaredMethod("getPrimaryColor");
+        mWCGetSecondaryColorMethod = wallpaperColorsClass.getDeclaredMethod("getSecondaryColor");
+        mWCGetTertiaryColorMethod = wallpaperColorsClass.getDeclaredMethod("getTertiaryColor");
+        mWCColorHintsMethod = wallpaperColorsClass.getDeclaredMethod("getColorHints");
     }
 
     @Nullable
@@ -98,12 +99,13 @@
         if (colors == null) {
             return null;
         }
-        List<Pair<Color, Integer>> list = (List) mWCGetColorsMethod.invoke(colors);
-        boolean supportsDarkText = (Boolean) mWCSupportsDarkTextMethod.invoke(colors);
-        SparseIntArray colorMap = new SparseIntArray(list.size());
-        for (Pair<Color, Integer> color : list) {
-            colorMap.put(color.first.toArgb(), color.second);
-        }
-        return new WallpaperColorsCompat(colorMap, supportsDarkText);
+        Color primary = (Color) mWCGetPrimaryColorMethod.invoke(colors);
+        Color secondary = (Color) mWCGetSecondaryColorMethod.invoke(colors);
+        Color tertiary = (Color) mWCGetTertiaryColorMethod.invoke(colors);
+        int primaryVal = primary != null ? primary.toArgb() : 0;
+        int secondaryVal = secondary != null ? secondary.toArgb() : 0;
+        int tertiaryVal = tertiary != null ? tertiary.toArgb() : 0;
+        int colorHints = (Integer) mWCColorHintsMethod.invoke(colors);
+        return new WallpaperColorsCompat(primaryVal, secondaryVal, tertiaryVal, colorHints);
     }
 }
diff --git a/src/com/android/launcher3/dynamicui/ColorExtractionAlgorithm.java b/src/com/android/launcher3/dynamicui/ColorExtractionAlgorithm.java
index 21d5b27..d2dd0d3 100644
--- a/src/com/android/launcher3/dynamicui/ColorExtractionAlgorithm.java
+++ b/src/com/android/launcher3/dynamicui/ColorExtractionAlgorithm.java
@@ -24,15 +24,12 @@
 import android.util.Log;
 import android.util.Pair;
 import android.util.Range;
-import android.util.SparseIntArray;
 
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.compat.WallpaperColorsCompat;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
+import java.util.LinkedList;
 import java.util.List;
 
 /**
@@ -52,20 +49,18 @@
     private static final float FIT_WEIGHT_S = 1.0f;
     private static final float FIT_WEIGHT_L = 10.0f;
 
-    // When extracting the main color, only consider colors
-    // present in at least MIN_COLOR_OCCURRENCE of the image
-    private static final float MIN_COLOR_OCCURRENCE = 0.1f;
-
     // Temporary variable to avoid allocations
-    private final float[] mTmpHSL = new float[3];
+    private float[] mTmpHSL = new float[3];
 
-    public @Nullable Pair<Integer, Integer> extractInto(WallpaperColorsCompat wallpaperColors) {
-        if (wallpaperColors == null) {
+    public @Nullable Pair<Integer, Integer> extractInto(WallpaperColorsCompat inWallpaperColors) {
+        if (inWallpaperColors == null) {
             return null;
         }
 
-        SparseIntArray colorsArray = wallpaperColors.getColors();
-        if (colorsArray.size() == 0) {
+        final List<Integer> mainColors = getMainColors(inWallpaperColors);
+        final int mainColorsSize = mainColors.size();
+
+        if (mainColorsSize == 0) {
             return null;
         }
         // Tonal is not really a sort, it takes a color from the extracted
@@ -73,35 +68,17 @@
         // palettes. The best fit is tweaked to be closer to the source color
         // and replaces the original palette
 
-        List<Pair<Integer, Integer>> colors = new ArrayList<>(colorsArray.size());
-        for (int i = colorsArray.size() - 1; i >= 0; i--) {
-            colors.add(Pair.create(colorsArray.keyAt(i), colorsArray.valueAt(i)));
-        }
-
-        // First find the most representative color in the image
-        populationSort(colors);
-        // Calculate total
-        int total = 0;
-        for (Pair<Integer, Integer> weightedColor : colors) {
-            total += weightedColor.second;
-        }
-
-        // Get bright colors that occur often enough in this image
-        Pair<Integer, Integer> bestColor = null;
-        float[] hsl = new float[3];
-        for (Pair<Integer, Integer> weightedColor : colors) {
-            float colorOccurrence = weightedColor.second / (float) total;
-            if (colorOccurrence < MIN_COLOR_OCCURRENCE) {
-                break;
-            }
-
-            int colorValue = weightedColor.first;
+        // Get the most preeminent, non-blacklisted color.
+        Integer bestColor = 0;
+        final float[] hsl = new float[3];
+        for (int i = 0; i < mainColorsSize; i++) {
+            final int colorValue = mainColors.get(i);
             ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue),
                     Color.blue(colorValue), hsl);
 
             // Stop when we find a color that meets our criteria
             if (!isBlacklisted(hsl)) {
-                bestColor = weightedColor;
+                bestColor = colorValue;
                 break;
             }
         }
@@ -111,7 +88,7 @@
             return null;
         }
 
-        int colorValue = bestColor.first;
+        int colorValue = bestColor;
         ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue), Color.blue(colorValue),
                 hsl);
 
@@ -121,7 +98,6 @@
 
         // Find the palette that contains the closest color
         TonalPalette palette = findTonalPalette(hsl[0]);
-
         if (palette == null) {
             Log.w(TAG, "Could not find a tonal palette!");
             return null;
@@ -140,8 +116,7 @@
         float[] s = fit(palette.s, hsl[1], fitIndex, 0.0f, 1.0f);
         float[] l = fit(palette.l, hsl[2], fitIndex, 0.0f, 1.0f);
 
-        final int textInversionIndex = h.length - 3;
-
+        // Normal colors:
         // best fit + a 2 colors offset
         int primaryIndex = fitIndex;
         int secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2);
@@ -172,15 +147,6 @@
         return false;
     }
 
-    private static void populationSort(@NonNull List<Pair<Integer, Integer>> wallpaperColors) {
-        Collections.sort(wallpaperColors, new Comparator<Pair<Integer, Integer>>() {
-            @Override
-            public int compare(Pair<Integer, Integer> a, Pair<Integer, Integer> b) {
-                return b.second - a.second;
-            }
-        });
-    }
-
     /**
      * Offsets all colors by a delta, clamping values that go beyond what's
      * supported on the color space.
@@ -234,7 +200,9 @@
         TonalPalette best = null;
         float error = Float.POSITIVE_INFINITY;
 
-        for (TonalPalette candidate : TONAL_PALETTES) {
+        for (int i = 0; i < TONAL_PALETTES.length; i++) {
+            final TonalPalette candidate = TONAL_PALETTES[i];
+
             if (h >= candidate.minHue && h <= candidate.maxHue) {
                 best = candidate;
                 break;
@@ -757,4 +725,18 @@
         }
     }
 
+    private static List<Integer> getMainColors(WallpaperColorsCompat wallpaperColors) {
+        LinkedList<Integer> colors = new LinkedList<>();
+        if (wallpaperColors.getPrimaryColor() != 0) {
+            colors.add(wallpaperColors.getPrimaryColor());
+        }
+        if (wallpaperColors.getSecondaryColor() != 0) {
+            colors.add(wallpaperColors.getSecondaryColor());
+        }
+        if (wallpaperColors.getTertiaryColor() != 0) {
+            colors.add(wallpaperColors.getTertiaryColor());
+        }
+        return colors;
+    }
+
 }
diff --git a/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java b/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java
index e23f42f..856a26c 100644
--- a/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java
+++ b/src/com/android/launcher3/dynamicui/WallpaperColorInfo.java
@@ -78,7 +78,9 @@
             mMainColor = FALLBACK_COLOR;
             mSecondaryColor = FALLBACK_COLOR;
         }
-        mSupportsDarkText = wallpaperColors != null ? wallpaperColors.supportsDarkText() : false;
+        mSupportsDarkText = wallpaperColors != null
+                ? (wallpaperColors.getColorHints()
+                    & WallpaperColorsCompat.HINT_SUPPORTS_DARK_TEXT) > 0 : false;
         float[] hsl = new float[3];
         ColorUtils.colorToHSL(mMainColor, hsl);
         mIsDark = hsl[2] < 0.2f;