diff --git a/AndroidManifest-common.xml b/AndroidManifest-common.xml
index 3a60a9878f..dd1446635d 100644
--- a/AndroidManifest-common.xml
+++ b/AndroidManifest-common.xml
@@ -85,6 +85,11 @@
android:process=":wallpaper_chooser">
+
+
diff --git a/src/com/android/launcher3/compat/WallpaperColorsCompat.java b/src/com/android/launcher3/compat/WallpaperColorsCompat.java
new file mode 100644
index 0000000000..fd08f947ed
--- /dev/null
+++ b/src/com/android/launcher3/compat/WallpaperColorsCompat.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+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 WallpaperColorsCompat(SparseIntArray colors, boolean supportsDarkText) {
+ mColors = colors;
+ mSupportsDarkText = supportsDarkText;
+ }
+
+ /**
+ * A map of color code to their occurrences. The bigger the int, the more relevant the color.
+ */
+ public SparseIntArray getColors() {
+ return mColors;
+ }
+
+ public boolean supportsDarkText() {
+ return mSupportsDarkText;
+ }
+}
diff --git a/src/com/android/launcher3/compat/WallpaperManagerCompat.java b/src/com/android/launcher3/compat/WallpaperManagerCompat.java
new file mode 100644
index 0000000000..cbcabdf9b1
--- /dev/null
+++ b/src/com/android/launcher3/compat/WallpaperManagerCompat.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.launcher3.compat;
+
+import android.content.Context;
+import android.support.annotation.Nullable;
+
+import com.android.launcher3.Utilities;
+
+public abstract class WallpaperManagerCompat {
+
+ private static final Object sInstanceLock = new Object();
+ private static WallpaperManagerCompat sInstance;
+
+ public static WallpaperManagerCompat getInstance(Context context) {
+ synchronized (sInstanceLock) {
+ if (sInstance == null) {
+ context = context.getApplicationContext();
+
+ if (Utilities.isAtLeastO()) {
+ try {
+ sInstance = new WallpaperManagerCompatVOMR1(context);
+ } catch (Exception e) {
+ // The wallpaper APIs do not yet exist
+ }
+ }
+ if (sInstance == null) {
+ sInstance = new WallpaperManagerCompatVL(context);
+ }
+ }
+ return sInstance;
+ }
+ }
+
+
+ public abstract @Nullable WallpaperColorsCompat getWallpaperColors(int which);
+
+ public abstract void addOnColorsChangedListener(OnColorsChangedListenerCompat listener);
+
+ /**
+ * Interface definition for a callback to be invoked when colors change on a wallpaper.
+ */
+ public interface OnColorsChangedListenerCompat {
+
+ void onColorsChanged(WallpaperColorsCompat colors, int which);
+ }
+}
diff --git a/src/com/android/launcher3/compat/WallpaperManagerCompatVL.java b/src/com/android/launcher3/compat/WallpaperManagerCompatVL.java
new file mode 100644
index 0000000000..b175f21136
--- /dev/null
+++ b/src/com/android/launcher3/compat/WallpaperManagerCompatVL.java
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.compat;
+
+import static android.app.WallpaperManager.FLAG_SYSTEM;
+
+import android.app.IntentService;
+import android.app.WallpaperInfo;
+import android.app.WallpaperManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.SharedPreferences;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapRegionDecoder;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ParcelFileDescriptor;
+import android.os.ResultReceiver;
+import android.support.annotation.Nullable;
+import android.support.v7.graphics.Palette;
+import android.util.Log;
+import android.util.Pair;
+import android.util.SparseIntArray;
+
+import com.android.launcher3.LauncherFiles;
+import com.android.launcher3.Utilities;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+public class WallpaperManagerCompatVL extends WallpaperManagerCompat {
+
+ private static final String TAG = "WMCompatVL";
+
+ private static final String VERSION_PREFIX = "1,";
+ private static final String KEY_COLORS = "wallpaper_parsed_colors";
+ private static final String EXTRA_RECEIVER = "receiver";
+
+ private final ArrayList mListeners = new ArrayList<>();
+
+ private final Context mContext;
+ private WallpaperColorsCompat mColorsCompat;
+
+ WallpaperManagerCompatVL(Context context) {
+ mContext = context;
+
+ String colors = prefs(mContext).getString(KEY_COLORS, "");
+ int wallpaperId = -1;
+ if (colors.startsWith(VERSION_PREFIX)) {
+ Pair storedValue = parseValue(colors);
+ wallpaperId = storedValue.first;
+ mColorsCompat = storedValue.second;
+ }
+
+ if (wallpaperId == -1 || wallpaperId != getWallpaperId(context)) {
+ reloadColors();
+ }
+ context.registerReceiver(new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ reloadColors();
+ }
+ }, new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED));
+ }
+
+ @Nullable
+ @Override
+ public WallpaperColorsCompat getWallpaperColors(int which) {
+ return which == FLAG_SYSTEM ? mColorsCompat : null;
+ }
+
+ @Override
+ public void addOnColorsChangedListener(OnColorsChangedListenerCompat listener) {
+ mListeners.add(listener);
+ }
+
+ private void reloadColors() {
+ ResultReceiver receiver = new ResultReceiver(new Handler()) {
+
+ @Override
+ protected void onReceiveResult(int resultCode, Bundle resultData) {
+ handleResult(resultData.getString(KEY_COLORS));
+ }
+ };
+ mContext.startService(new Intent(mContext, ColorExtractionService.class)
+ .putExtra(EXTRA_RECEIVER, receiver));
+ }
+
+ private void handleResult(String result) {
+ prefs(mContext).edit().putString(KEY_COLORS, result).apply();
+ mColorsCompat = parseValue(result).second;
+ for (OnColorsChangedListenerCompat listener : mListeners) {
+ listener.onColorsChanged(mColorsCompat, FLAG_SYSTEM);
+ }
+ }
+
+ private static SharedPreferences prefs(Context context) {
+ return context.getSharedPreferences(
+ LauncherFiles.DEVICE_PREFERENCES_KEY, Context.MODE_PRIVATE);
+ }
+
+ private static final int getWallpaperId(Context context) {
+ if (!Utilities.ATLEAST_NOUGAT) {
+ return -1;
+ }
+ return context.getSystemService(WallpaperManager.class).getWallpaperId(FLAG_SYSTEM);
+ }
+
+ /**
+ * Parses the stored value and returns the wallpaper id and wallpaper colors.
+ */
+ private static Pair parseValue(String value) {
+ String[] parts = value.split(",");
+ Integer wallpaperId = Integer.parseInt(parts[1]);
+ if (parts.length == 2) {
+ return Pair.create(wallpaperId, null);
+ }
+
+ SparseIntArray colors = new SparseIntArray((parts.length - 2) / 2);
+ for (int i = 2; i < parts.length; i += 2) {
+ colors.put(Integer.parseInt(parts[i]), Integer.parseInt(parts[i + 1]));
+ }
+ return Pair.create(wallpaperId, new WallpaperColorsCompat(colors, false));
+ }
+
+ /**
+ * Intent service to handle color extraction
+ */
+ public static class ColorExtractionService extends IntentService {
+ private static final int MAX_WALLPAPER_EXTRACTION_AREA = 112 * 112;
+
+ public ColorExtractionService() {
+ super("ColorExtractionService");
+ }
+
+ /**
+ * Extracts the wallpaper colors and sends the result back through the receiver.
+ */
+ @Override
+ protected void onHandleIntent(@Nullable Intent intent) {
+ int wallpaperId = getWallpaperId(this);
+
+ Bitmap bitmap = null;
+ Drawable drawable = null;
+
+ WallpaperManager wm = WallpaperManager.getInstance(this);
+ WallpaperInfo info = wm.getWallpaperInfo();
+ if (info != null) {
+ // For live wallpaper, extract colors from thumbnail
+ drawable = info.loadThumbnail(getPackageManager());
+ } else {
+ if (Utilities.ATLEAST_NOUGAT) {
+ try (ParcelFileDescriptor fd = wm.getWallpaperFile(FLAG_SYSTEM)) {
+ BitmapRegionDecoder decoder = BitmapRegionDecoder
+ .newInstance(fd.getFileDescriptor(), false);
+
+ int requestedArea = decoder.getWidth() * decoder.getHeight();
+ BitmapFactory.Options options = new BitmapFactory.Options();
+
+ if (requestedArea > MAX_WALLPAPER_EXTRACTION_AREA) {
+ double areaRatio =
+ MAX_WALLPAPER_EXTRACTION_AREA / (double) requestedArea;
+ double nearestPowOf2 =
+ Math.floor(Math.log(areaRatio) / (2 * Math.log(2)));
+ options.inSampleSize = (int) Math.pow(2, nearestPowOf2);
+ }
+ Rect region = new Rect(0, 0, decoder.getWidth(), decoder.getHeight());
+ bitmap = decoder.decodeRegion(region, options);
+ decoder.recycle();
+ } catch (IOException | NullPointerException e) {
+ Log.e(TAG, "Fetching partial bitmap failed, trying old method", e);
+ }
+ }
+ if (bitmap == null) {
+ drawable = wm.getDrawable();
+ }
+ }
+
+ if (drawable != null) {
+ // Calculate how big the bitmap needs to be.
+ // This avoids unnecessary processing and allocation inside Palette.
+ final int requestedArea = drawable.getIntrinsicWidth() *
+ drawable.getIntrinsicHeight();
+ double scale = 1;
+ if (requestedArea > MAX_WALLPAPER_EXTRACTION_AREA) {
+ scale = Math.sqrt(MAX_WALLPAPER_EXTRACTION_AREA / (double) requestedArea);
+ }
+ bitmap = Bitmap.createBitmap((int) (drawable.getIntrinsicWidth() * scale),
+ (int) (drawable.getIntrinsicHeight() * scale), Bitmap.Config.ARGB_8888);
+ final Canvas bmpCanvas = new Canvas(bitmap);
+ drawable.setBounds(0, 0, bitmap.getWidth(), bitmap.getHeight());
+ drawable.draw(bmpCanvas);
+ }
+
+ String value = VERSION_PREFIX + wallpaperId;
+
+ if (bitmap != null) {
+ Palette palette = Palette.from(bitmap).generate();
+ bitmap.recycle();
+
+ StringBuilder builder = new StringBuilder(value);
+ for (Palette.Swatch swatch : palette.getSwatches()) {
+ builder.append(',')
+ .append(swatch.getRgb())
+ .append(',')
+ .append(swatch.getPopulation());
+ }
+ value = builder.toString();
+ }
+
+ ResultReceiver receiver = intent.getParcelableExtra(EXTRA_RECEIVER);
+ Bundle result = new Bundle();
+ result.putString(KEY_COLORS, value);
+ receiver.send(0, result);
+ }
+ }
+}
diff --git a/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java b/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java
new file mode 100644
index 0000000000..c74ccc0ccf
--- /dev/null
+++ b/src/com/android/launcher3/compat/WallpaperManagerCompatVOMR1.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.compat;
+
+import android.annotation.TargetApi;
+import android.app.WallpaperManager;
+import android.content.Context;
+import android.graphics.Color;
+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 {
+
+ private static final String TAG = "WMCompatVOMR1";
+
+ private final WallpaperManager mWm;
+
+ private final Class mOCLClass;
+ private final Method mAddOCLMethod;
+
+ private final Method mWCGetMethod;
+ private final Method mWCGetColorsMethod;
+ private final Method mWCSupportsDarkTextMethod;
+
+ WallpaperManagerCompatVOMR1(Context context) throws Exception {
+ mWm = context.getSystemService(WallpaperManager.class);
+
+ mOCLClass = Class.forName("android.app.WallpaperManager$OnColorsChangedListener");
+ mAddOCLMethod = WallpaperManager.class.getDeclaredMethod(
+ "addOnColorsChangedListener", mOCLClass);
+
+ mWCGetMethod = WallpaperManager.class.getDeclaredMethod("getWallpaperColors", int.class);
+ Class wallpaperColorsClass = mWCGetMethod.getReturnType();
+ mWCGetColorsMethod = wallpaperColorsClass.getDeclaredMethod("getColors");
+ mWCSupportsDarkTextMethod = wallpaperColorsClass.getDeclaredMethod("supportsDarkText");
+ }
+
+ @Nullable
+ @Override
+ public WallpaperColorsCompat getWallpaperColors(int which) {
+ try {
+ return convertColorsObject(mWCGetMethod.invoke(mWm, which));
+ } catch (Exception e) {
+ Log.e(TAG, "Error calling wallpaper API", e);
+ return null;
+ }
+ }
+
+ @Override
+ public void addOnColorsChangedListener(final OnColorsChangedListenerCompat listener) {
+ Object onChangeListener = Proxy.newProxyInstance(
+ WallpaperManager.class.getClassLoader(),
+ new Class[]{mOCLClass},
+ new InvocationHandler() {
+ @Override
+ public Object invoke(Object o, Method method, Object[] objects)
+ throws Throwable {
+ String methodName = method.getName();
+ if ("onColorsChanged".equals(methodName)) {
+ listener.onColorsChanged(
+ convertColorsObject(objects[0]), (Integer) objects[1]);
+ } else if ("toString".equals(methodName)) {
+ return listener.toString();
+ }
+ return null;
+ }
+ });
+ try {
+ mAddOCLMethod.invoke(mWm, onChangeListener);
+ } catch (Exception e) {
+ Log.e(TAG, "Error calling wallpaper API", e);
+ }
+ }
+
+ private WallpaperColorsCompat convertColorsObject(Object colors) throws Exception {
+ if (colors == null) {
+ return null;
+ }
+ List> list = (List) mWCGetColorsMethod.invoke(colors);
+ boolean supportsDarkText = (Boolean) mWCSupportsDarkTextMethod.invoke(colors);
+ SparseIntArray colorMap = new SparseIntArray(list.size());
+ for (Pair color : list) {
+ colorMap.put(color.first.toArgb(), color.second);
+ }
+ return new WallpaperColorsCompat(colorMap, supportsDarkText);
+ }
+}
diff --git a/src/com/android/launcher3/dynamicui/ExtractedColors.java b/src/com/android/launcher3/dynamicui/ExtractedColors.java
index e60a1bd7d0..96fe31a734 100644
--- a/src/com/android/launcher3/dynamicui/ExtractedColors.java
+++ b/src/com/android/launcher3/dynamicui/ExtractedColors.java
@@ -170,7 +170,7 @@ public class ExtractedColors {
try {
WallpaperManager.class.getDeclaredMethod("getWallpaperColors", int.class);
ColorExtractor extractor = new ColorExtractor(context);
- ColorExtractor.GradientColors colors = extractor.getColors(WallpaperManager.FLAG_SYSTEM);
+ ColorExtractor.GradientColors colors = extractor.getColors();
setColorAtIndex(ALLAPPS_GRADIENT_MAIN_INDEX, colors.getMainColor());
setColorAtIndex(ALLAPPS_GRADIENT_SECONDARY_INDEX, colors.getSecondaryColor());
} catch (NoSuchMethodException e) {
diff --git a/src/com/android/launcher3/dynamicui/colorextraction/ColorExtractor.java b/src/com/android/launcher3/dynamicui/colorextraction/ColorExtractor.java
index 153b529140..98558677ae 100644
--- a/src/com/android/launcher3/dynamicui/colorextraction/ColorExtractor.java
+++ b/src/com/android/launcher3/dynamicui/colorextraction/ColorExtractor.java
@@ -1,16 +1,15 @@
package com.android.launcher3.dynamicui.colorextraction;
-import android.app.WallpaperManager;
+import static android.app.WallpaperManager.FLAG_SYSTEM;
+
import android.content.Context;
import android.graphics.Color;
-import android.os.Parcelable;
-import android.util.Log;
+import com.android.launcher3.compat.WallpaperColorsCompat;
+import com.android.launcher3.compat.WallpaperManagerCompat;
import com.android.launcher3.dynamicui.colorextraction.types.ExtractionType;
import com.android.launcher3.dynamicui.colorextraction.types.Tonal;
-import java.lang.reflect.Method;
-
/**
* Class to process wallpaper colors and generate a tonal palette based on them.
@@ -18,59 +17,32 @@ import java.lang.reflect.Method;
* TODO remove this class if available by platform
*/
public class ColorExtractor {
- private static final String TAG = "ColorExtractor";
private static final int FALLBACK_COLOR = Color.WHITE;
+ private final Context mContext;
private int mMainFallbackColor = FALLBACK_COLOR;
private int mSecondaryFallbackColor = FALLBACK_COLOR;
private final GradientColors mSystemColors;
- private final GradientColors mLockColors;
- private final Context mContext;
private final ExtractionType mExtractionType;
public ColorExtractor(Context context) {
mContext = context;
mSystemColors = new GradientColors();
- mLockColors = new GradientColors();
mExtractionType = new Tonal();
- WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
- if (wallpaperManager == null) {
- Log.w(TAG, "Can't listen to color changes!");
- } else {
- Parcelable wallpaperColorsObj;
- try {
- Method method = WallpaperManager.class
- .getDeclaredMethod("getWallpaperColors", int.class);
-
- wallpaperColorsObj = (Parcelable) method.invoke(wallpaperManager,
- WallpaperManager.FLAG_SYSTEM);
- extractInto(new WallpaperColorsCompat(wallpaperColorsObj), mSystemColors);
- wallpaperColorsObj = (Parcelable) method.invoke(wallpaperManager,
- WallpaperManager.FLAG_LOCK);
- extractInto(new WallpaperColorsCompat(wallpaperColorsObj), mLockColors);
- } catch (Exception e) {
- Log.e(TAG, "reflection failed", e);
- }
- }
+ extractFrom(WallpaperManagerCompat.getInstance(context).getWallpaperColors(FLAG_SYSTEM));
}
- public GradientColors getColors(int which) {
- if (which == WallpaperManager.FLAG_LOCK) {
- return mLockColors;
- } else if (which == WallpaperManager.FLAG_SYSTEM) {
- return mSystemColors;
- } else {
- throw new IllegalArgumentException("which should be either FLAG_SYSTEM or FLAG_LOCK");
- }
+ public GradientColors getColors() {
+ return mSystemColors;
}
- private void extractInto(WallpaperColorsCompat inWallpaperColors, GradientColors outGradientColors) {
- applyFallback(outGradientColors);
+ private void extractFrom(WallpaperColorsCompat inWallpaperColors) {
+ applyFallback(mSystemColors);
if (inWallpaperColors == null) {
return;
}
- mExtractionType.extractInto(inWallpaperColors, outGradientColors);
+ mExtractionType.extractInto(inWallpaperColors, mSystemColors);
}
private void applyFallback(GradientColors outGradientColors) {
diff --git a/src/com/android/launcher3/dynamicui/colorextraction/WallpaperColorsCompat.java b/src/com/android/launcher3/dynamicui/colorextraction/WallpaperColorsCompat.java
deleted file mode 100644
index f80a675cbd..0000000000
--- a/src/com/android/launcher3/dynamicui/colorextraction/WallpaperColorsCompat.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package com.android.launcher3.dynamicui.colorextraction;
-
-import android.graphics.Color;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.Pair;
-
-import java.util.List;
-
-/**
- * A wrapper around platform implementation of WallpaperColors until the
- * updated SDK is available.
- *
- * TODO remove this class if available by platform
- */
-public class WallpaperColorsCompat implements Parcelable {
-
- private final Parcelable mObject;
-
- public WallpaperColorsCompat(Parcelable object) {
- mObject = object;
- }
-
- private Object invokeMethod(String methodName) {
- try {
- return mObject.getClass().getDeclaredMethod(methodName).invoke(mObject);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- @Override
- public int describeContents() {
- return 0;
- }
-
- @Override
- public void writeToParcel(Parcel parcel, int i) {
- parcel.writeParcelable(mObject, i);
- }
-
- public static final Parcelable.Creator CREATOR =
- new Parcelable.Creator() {
- public WallpaperColorsCompat createFromParcel(Parcel source) {
- Parcelable object = source.readParcelable(null);
- return new WallpaperColorsCompat(object);
- }
-
- public WallpaperColorsCompat[] newArray(int size) {
- return new WallpaperColorsCompat[size];
- }
- };
-
- public List> getColors() {
- try {
- return (List>) invokeMethod("getColors");
- } catch (Exception e) {
- return null;
- }
- }
-
- public boolean supportsDarkText() {
- try {
- return (Boolean) invokeMethod("supportsDarkText");
- } catch (Exception e) {
- return false;
- }
- }
-}
diff --git a/src/com/android/launcher3/dynamicui/colorextraction/types/ExtractionType.java b/src/com/android/launcher3/dynamicui/colorextraction/types/ExtractionType.java
index 166c7c6f40..88958a480b 100644
--- a/src/com/android/launcher3/dynamicui/colorextraction/types/ExtractionType.java
+++ b/src/com/android/launcher3/dynamicui/colorextraction/types/ExtractionType.java
@@ -1,7 +1,7 @@
package com.android.launcher3.dynamicui.colorextraction.types;
+import com.android.launcher3.compat.WallpaperColorsCompat;
import com.android.launcher3.dynamicui.colorextraction.ColorExtractor;
-import com.android.launcher3.dynamicui.colorextraction.WallpaperColorsCompat;
/**
diff --git a/src/com/android/launcher3/dynamicui/colorextraction/types/Tonal.java b/src/com/android/launcher3/dynamicui/colorextraction/types/Tonal.java
index 1e165a382a..800dcd2039 100644
--- a/src/com/android/launcher3/dynamicui/colorextraction/types/Tonal.java
+++ b/src/com/android/launcher3/dynamicui/colorextraction/types/Tonal.java
@@ -6,11 +6,15 @@ import android.support.annotation.Nullable;
import android.support.v4.graphics.ColorUtils;
import android.util.Log;
import android.util.Pair;
+import android.util.SparseIntArray;
+import com.android.launcher3.compat.WallpaperColorsCompat;
import com.android.launcher3.dynamicui.colorextraction.ColorExtractor;
-import com.android.launcher3.dynamicui.colorextraction.WallpaperColorsCompat;
+import java.util.ArrayList;
+import java.util.Collections;
import java.util.Comparator;
+import java.util.List;
/**
@@ -29,9 +33,10 @@ public class Tonal implements ExtractionType {
private static final float MIN_COLOR_OCCURRENCE = 0.1f;
private static final float MIN_LUMINOSITY = 0.5f;
- public void extractInto(WallpaperColorsCompat wallpaperColors,
- ColorExtractor.GradientColors gradientColors) {
- if (wallpaperColors.getColors().size() == 0) {
+ public void extractInto(
+ WallpaperColorsCompat wallpaperColors, ColorExtractor.GradientColors gradientColors) {
+ SparseIntArray colorsArray = wallpaperColors.getColors();
+ if (colorsArray.size() == 0) {
return;
}
// Tonal is not really a sort, it takes a color from the extracted
@@ -39,24 +44,30 @@ public class Tonal implements ExtractionType {
// palettes. The best fit is tweaked to be closer to the source color
// and replaces the original palette
+ List> 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(wallpaperColors);
+ populationSort(colors);
+
// Calculate total
int total = 0;
- for (Pair weightedColor : wallpaperColors.getColors()) {
+ for (Pair weightedColor : colors) {
total += weightedColor.second;
}
// Get bright colors that occur often enough in this image
- Pair bestColor = null;
+ Pair bestColor = null;
float[] hsl = new float[3];
- for (Pair weightedColor : wallpaperColors.getColors()) {
+ for (Pair weightedColor : colors) {
float colorOccurrence = weightedColor.second / (float) total;
if (colorOccurrence < MIN_COLOR_OCCURRENCE) {
break;
}
- int colorValue = weightedColor.first.toArgb();
+ int colorValue = weightedColor.first;
ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue),
Color.blue(colorValue), hsl);
if (hsl[2] > MIN_LUMINOSITY) {
@@ -66,10 +77,10 @@ public class Tonal implements ExtractionType {
// Fallback to first color
if (bestColor == null) {
- bestColor = wallpaperColors.getColors().get(0);
+ bestColor = colors.get(0);
}
- int colorValue = bestColor.first.toArgb();
+ int colorValue = bestColor.first;
ColorUtils.RGBToHSL(Color.red(colorValue), Color.green(colorValue), Color.blue(colorValue),
hsl);
hsl[0] /= 360.0f; // normalize
@@ -105,10 +116,10 @@ public class Tonal implements ExtractionType {
gradientColors.setSecondaryColor(ColorUtils.HSLToColor(hsl));
}
- private static void populationSort(@NonNull WallpaperColorsCompat wallpaperColors) {
- wallpaperColors.getColors().sort(new Comparator>() {
+ private static void populationSort(@NonNull List> wallpaperColors) {
+ Collections.sort(wallpaperColors, new Comparator>() {
@Override
- public int compare(Pair a, Pair b) {
+ public int compare(Pair a, Pair b) {
return b.second - a.second;
}
});