Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7debc53f authored by Winson Chung's avatar Winson Chung
Browse files

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
parent b6ecb173
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -42,12 +42,15 @@ public class NormalizedIconLoader extends IconLoader {

    private final SparseArray<BitmapInfo> mDefaultIcons = new SparseArray<>();
    private final DrawableFactory mDrawableFactory;
    private final boolean mDisableColorExtraction;
    private LauncherIcons mLauncherIcons;

    public NormalizedIconLoader(Context context, TaskKeyLruCache<Drawable> iconCache,
            LruCache<ComponentName, ActivityInfo> activityInfoCache) {
            LruCache<ComponentName, ActivityInfo> 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);
+3 −1
Original line number Diff line number Diff line
@@ -94,7 +94,9 @@ public class RecentsModel extends TaskStackChangeListener {
            protected IconLoader createNewIconLoader(Context context,
                    TaskKeyLruCache<Drawable> iconCache,
                    LruCache<ComponentName, ActivityInfo> 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);
+7 −1
Original line number Diff line number Diff line
@@ -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;
    }
}
+22 −8
Original line number Diff line number Diff line
@@ -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<Float> 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<Float> rgbScores = new SparseArray<>();
        SparseArray<Float> rgbScores = mTmpRgbScores;
        rgbScores.clear();
        int bestColor = 0xff000000;
        highScore = -1;
        // Go back over the RGB colors that match the winning hue,
+14 −2
Original line number Diff line number Diff line
@@ -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;
@@ -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;
Loading