From 7debc53f9377398ffa7eb53d473dff997098a40c Mon Sep 17 00:00:00 2001 From: Winson Chung Date: Mon, 13 Aug 2018 16:07:28 -0700 Subject: Skip logic to find the dominant color when loading recent task icons - Also move some allocations in ColorExtractor into thread locals to reduce allocations Bug: 78777731 Change-Id: I8819106d476a9af02e864135a2f44b55fe9219cd --- .../android/quickstep/NormalizedIconLoader.java | 8 +++++- .../src/com/android/quickstep/RecentsModel.java | 4 ++- src/com/android/launcher3/graphics/BitmapInfo.java | 8 +++++- .../android/launcher3/graphics/ColorExtractor.java | 30 ++++++++++++++++------ .../android/launcher3/graphics/LauncherIcons.java | 16 ++++++++++-- .../dynamicui/WallpaperManagerCompatVL.java | 7 +++-- 6 files changed, 58 insertions(+), 15 deletions(-) diff --git a/quickstep/src/com/android/quickstep/NormalizedIconLoader.java b/quickstep/src/com/android/quickstep/NormalizedIconLoader.java index f875bb786..a4a2e5690 100644 --- a/quickstep/src/com/android/quickstep/NormalizedIconLoader.java +++ b/quickstep/src/com/android/quickstep/NormalizedIconLoader.java @@ -42,12 +42,15 @@ public class NormalizedIconLoader extends IconLoader { private final SparseArray mDefaultIcons = new SparseArray<>(); private final DrawableFactory mDrawableFactory; + private final boolean mDisableColorExtraction; private LauncherIcons mLauncherIcons; public NormalizedIconLoader(Context context, TaskKeyLruCache iconCache, - LruCache activityInfoCache) { + LruCache activityInfoCache, + boolean disableColorExtraction) { super(context, iconCache, activityInfoCache); mDrawableFactory = DrawableFactory.get(context); + mDisableColorExtraction = disableColorExtraction; } @Override @@ -74,6 +77,9 @@ public class NormalizedIconLoader extends IconLoader { int primaryColor, boolean isInstantApp) { if (mLauncherIcons == null) { mLauncherIcons = LauncherIcons.obtain(mContext); + if (mDisableColorExtraction) { + mLauncherIcons.disableColorExtraction(); + } } mLauncherIcons.setWrapperBackgroundColor(primaryColor); diff --git a/quickstep/src/com/android/quickstep/RecentsModel.java b/quickstep/src/com/android/quickstep/RecentsModel.java index fa4e016db..a9b732639 100644 --- a/quickstep/src/com/android/quickstep/RecentsModel.java +++ b/quickstep/src/com/android/quickstep/RecentsModel.java @@ -94,7 +94,9 @@ public class RecentsModel extends TaskStackChangeListener { protected IconLoader createNewIconLoader(Context context, TaskKeyLruCache iconCache, LruCache activityInfoCache) { - return new NormalizedIconLoader(context, iconCache, activityInfoCache); + // Disable finding the dominant color since we don't need to use it + return new NormalizedIconLoader(context, iconCache, activityInfoCache, + true /* disableColorExtraction */); } }; mRecentsTaskLoader.startLoader(mContext); diff --git a/src/com/android/launcher3/graphics/BitmapInfo.java b/src/com/android/launcher3/graphics/BitmapInfo.java index ab906e2f0..c905a78e5 100644 --- a/src/com/android/launcher3/graphics/BitmapInfo.java +++ b/src/com/android/launcher3/graphics/BitmapInfo.java @@ -35,9 +35,15 @@ public class BitmapInfo { } public static BitmapInfo fromBitmap(Bitmap bitmap) { + return fromBitmap(bitmap, null); + } + + public static BitmapInfo fromBitmap(Bitmap bitmap, ColorExtractor dominantColorExtractor) { BitmapInfo info = new BitmapInfo(); info.icon = bitmap; - info.color = ColorExtractor.findDominantColorByHue(bitmap); + info.color = dominantColorExtractor != null + ? dominantColorExtractor.findDominantColorByHue(bitmap) + : 0; return info; } } diff --git a/src/com/android/launcher3/graphics/ColorExtractor.java b/src/com/android/launcher3/graphics/ColorExtractor.java index e9d72b793..da5da9cea 100644 --- a/src/com/android/launcher3/graphics/ColorExtractor.java +++ b/src/com/android/launcher3/graphics/ColorExtractor.java @@ -18,22 +18,32 @@ package com.android.launcher3.graphics; import android.graphics.Bitmap; import android.graphics.Color; import android.util.SparseArray; +import java.util.Arrays; /** * Utility class for extracting colors from a bitmap. */ public class ColorExtractor { - public static int findDominantColorByHue(Bitmap bitmap) { - return findDominantColorByHue(bitmap, 20); + private final int NUM_SAMPLES = 20; + private final float[] mTmpHsv = new float[3]; + private final float[] mTmpHueScoreHistogram = new float[360]; + private final int[] mTmpPixels = new int[NUM_SAMPLES]; + private final SparseArray mTmpRgbScores = new SparseArray<>(); + + /** + * This picks a dominant color, looking for high-saturation, high-value, repeated hues. + * @param bitmap The bitmap to scan + */ + public int findDominantColorByHue(Bitmap bitmap) { + return findDominantColorByHue(bitmap, NUM_SAMPLES); } /** * This picks a dominant color, looking for high-saturation, high-value, repeated hues. * @param bitmap The bitmap to scan - * @param samples The approximate max number of samples to use. */ - public static int findDominantColorByHue(Bitmap bitmap, int samples) { + public int findDominantColorByHue(Bitmap bitmap, int samples) { final int height = bitmap.getHeight(); final int width = bitmap.getWidth(); int sampleStride = (int) Math.sqrt((height * width) / samples); @@ -42,15 +52,18 @@ public class ColorExtractor { } // This is an out-param, for getting the hsv values for an rgb - float[] hsv = new float[3]; + float[] hsv = mTmpHsv; + Arrays.fill(hsv, 0); // First get the best hue, by creating a histogram over 360 hue buckets, // where each pixel contributes a score weighted by saturation, value, and alpha. - float[] hueScoreHistogram = new float[360]; + float[] hueScoreHistogram = mTmpHueScoreHistogram; + Arrays.fill(hueScoreHistogram, 0); float highScore = -1; int bestHue = -1; - int[] pixels = new int[samples]; + int[] pixels = mTmpPixels; + Arrays.fill(pixels, 0); int pixelCount = 0; for (int y = 0; y < height; y += sampleStride) { @@ -82,7 +95,8 @@ public class ColorExtractor { } } - SparseArray rgbScores = new SparseArray<>(); + SparseArray rgbScores = mTmpRgbScores; + rgbScores.clear(); int bestColor = 0xff000000; highScore = -1; // Go back over the RGB colors that match the winning hue, diff --git a/src/com/android/launcher3/graphics/LauncherIcons.java b/src/com/android/launcher3/graphics/LauncherIcons.java index 333fe5907..0167a1d9c 100644 --- a/src/com/android/launcher3/graphics/LauncherIcons.java +++ b/src/com/android/launcher3/graphics/LauncherIcons.java @@ -90,6 +90,7 @@ public class LauncherIcons implements AutoCloseable { synchronized (sPoolSync) { // Clear any temporary state variables mWrapperBackgroundColor = DEFAULT_WRAPPER_BACKGROUND; + mDisableColorExtractor = false; next = sPool; sPool = this; @@ -105,6 +106,8 @@ public class LauncherIcons implements AutoCloseable { private final Context mContext; private final Canvas mCanvas; private final PackageManager mPm; + private final ColorExtractor mColorExtractor; + private boolean mDisableColorExtractor; private final int mFillResIconDpi; private final int mIconBitmapSize; @@ -121,6 +124,7 @@ public class LauncherIcons implements AutoCloseable { private LauncherIcons(Context context) { mContext = context.getApplicationContext(); mPm = mContext.getPackageManager(); + mColorExtractor = new ColorExtractor(); InvariantDeviceProfile idp = LauncherAppState.getIDP(mContext); mFillResIconDpi = idp.fillResIconDpi; @@ -196,7 +200,7 @@ public class LauncherIcons implements AutoCloseable { * The bitmap is also visually normalized with other icons. */ public BitmapInfo createBadgedIconBitmap(Drawable icon, UserHandle user, int iconAppTargetSdk, - boolean isInstantApp, float [] scale) { + boolean isInstantApp, float[] scale) { if (scale == null) { scale = new float[1]; } @@ -223,7 +227,7 @@ public class LauncherIcons implements AutoCloseable { } else { result = bitmap; } - return BitmapInfo.fromBitmap(result); + return BitmapInfo.fromBitmap(result, mDisableColorExtractor ? null : mColorExtractor); } /** @@ -245,6 +249,14 @@ public class LauncherIcons implements AutoCloseable { mWrapperBackgroundColor = (Color.alpha(color) < 255) ? DEFAULT_WRAPPER_BACKGROUND : color; } + /** + * Disables the dominant color extraction for all icons loaded through this session (until + * this instance is recycled). + */ + public void disableColorExtraction() { + mDisableColorExtractor = true; + } + private Drawable normalizeAndWrapToAdaptiveIcon(Drawable icon, int iconAppTargetSdk, RectF outIconBounds, float[] outScale) { float scale = 1f; diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVL.java b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVL.java index 4a8bbbd5a..7529f17f4 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVL.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/dynamicui/WallpaperManagerCompatVL.java @@ -18,7 +18,6 @@ package com.android.launcher3.uioverrides.dynamicui; import static android.app.WallpaperManager.FLAG_SYSTEM; import static com.android.launcher3.Utilities.getDevicePrefs; -import static com.android.launcher3.graphics.ColorExtractor.findDominantColorByHue; import android.app.WallpaperInfo; import android.app.WallpaperManager; @@ -47,6 +46,7 @@ import android.util.Log; import android.util.Pair; import com.android.launcher3.Utilities; +import com.android.launcher3.graphics.ColorExtractor; import java.io.IOException; import java.util.ArrayList; @@ -169,6 +169,7 @@ public class WallpaperManagerCompatVL extends WallpaperManagerCompat { private HandlerThread mWorkerThread; private Handler mWorkerHandler; + private ColorExtractor mColorExtractor; @Override public void onCreate() { @@ -176,6 +177,7 @@ public class WallpaperManagerCompatVL extends WallpaperManagerCompat { mWorkerThread = new HandlerThread("ColorExtractionService"); mWorkerThread.start(); mWorkerHandler = new Handler(mWorkerThread.getLooper()); + mColorExtractor = new ColorExtractor(); } @Override @@ -258,7 +260,8 @@ public class WallpaperManagerCompatVL extends WallpaperManagerCompat { String value = VERSION_PREFIX + wallpaperId; if (bitmap != null) { - int color = findDominantColorByHue(bitmap, MAX_WALLPAPER_EXTRACTION_AREA); + int color = mColorExtractor.findDominantColorByHue(bitmap, + MAX_WALLPAPER_EXTRACTION_AREA); value += "," + color; } -- cgit v1.2.3