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

Commit de3597c7 authored by Lucas Dupin's avatar Lucas Dupin Committed by android-build-merger
Browse files

Merge "In-app gradient color based on systemui theme." into oc-dr1-dev

am: 717dd58c

Change-Id: I35c7baae2e373f4d8bea87d1afc175833de7f59e
parents d4a3ca8d 717dd58c
Loading
Loading
Loading
Loading
+16 −39
Original line number Diff line number Diff line
@@ -43,10 +43,6 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener

    private static final String TAG = "ColorExtractor";

    public static final int FALLBACK_COLOR = 0xff83888d;

    private int mMainFallbackColor = FALLBACK_COLOR;
    private int mSecondaryFallbackColor = FALLBACK_COLOR;
    private final SparseArray<GradientColors[]> mGradientColors;
    private final ArrayList<OnColorsChangedListener> mOnColorsChangedListeners;
    private final Context mContext;
@@ -73,6 +69,9 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener
        }

        mOnColorsChangedListeners = new ArrayList<>();
        GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM);
        GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK);

        WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class);
        if (wallpaperManager == null) {
            Log.w(TAG, "Can't listen to color changes!");
@@ -83,23 +82,18 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener
            Trace.beginSection("ColorExtractor#getWallpaperColors");
            mSystemColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
            mLockColors = wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_LOCK);
            Trace.endSection();
        }

            GradientColors[] systemColors = mGradientColors.get(
                    WallpaperManager.FLAG_SYSTEM);
        // Initialize all gradients with the current colors
        extractInto(mSystemColors,
                systemColors[TYPE_NORMAL],
                systemColors[TYPE_DARK],
                systemColors[TYPE_EXTRA_DARK]);

            GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK);
        extractInto(mLockColors,
                lockColors[TYPE_NORMAL],
                lockColors[TYPE_DARK],
                lockColors[TYPE_EXTRA_DARK]);
            triggerColorsChanged(WallpaperManager.FLAG_SYSTEM
                    | WallpaperManager.FLAG_LOCK);
            Trace.endSection();
        }
    }

    /**
@@ -181,25 +175,8 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener
    private void extractInto(WallpaperColors inWallpaperColors,
            GradientColors outGradientColorsNormal, GradientColors outGradientColorsDark,
            GradientColors outGradientColorsExtraDark) {
        if (inWallpaperColors == null) {
            applyFallback(outGradientColorsNormal);
            applyFallback(outGradientColorsDark);
            applyFallback(outGradientColorsExtraDark);
            return;
        }
        boolean success = mExtractionType.extractInto(inWallpaperColors, outGradientColorsNormal,
        mExtractionType.extractInto(inWallpaperColors, outGradientColorsNormal,
                outGradientColorsDark, outGradientColorsExtraDark);
        if (!success) {
            applyFallback(outGradientColorsNormal);
            applyFallback(outGradientColorsDark);
            applyFallback(outGradientColorsExtraDark);
        }
    }

    private void applyFallback(GradientColors outGradientColors) {
        outGradientColors.setMainColor(mMainFallbackColor);
        outGradientColors.setSecondaryColor(mSecondaryFallbackColor);
        outGradientColors.setSupportsDarkText(false);
    }

    public void destroy() {
@@ -218,8 +195,8 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener
    }

    public static class GradientColors {
        private int mMainColor = FALLBACK_COLOR;
        private int mSecondaryColor = FALLBACK_COLOR;
        private int mMainColor;
        private int mSecondaryColor;
        private boolean mSupportsDarkText;

        public void setMainColor(int mainColor) {
+1 −2
Original line number Diff line number Diff line
@@ -38,9 +38,8 @@ public interface ExtractionType {
     * @param outGradientColorsNormal object that should receive normal colors
     * @param outGradientColorsDark object that should receive dark colors
     * @param outGradientColorsExtraDark object that should receive extra dark colors
     * @return true if successful.
     */
    boolean extractInto(WallpaperColors inWallpaperColors,
    void extractInto(WallpaperColors inWallpaperColors,
            ColorExtractor.GradientColors outGradientColorsNormal,
            ColorExtractor.GradientColors outGradientColorsDark,
            ColorExtractor.GradientColors outGradientColorsExtraDark);
+91 −19
Original line number Diff line number Diff line
@@ -44,24 +44,54 @@ public class Tonal implements ExtractionType {

    private static final boolean DEBUG = true;

    public static final int MAIN_COLOR_LIGHT = 0xffe0e0e0;
    public static final int SECONDARY_COLOR_LIGHT = 0xff9e9e9e;
    public static final int MAIN_COLOR_DARK = 0xff212121;
    public static final int SECONDARY_COLOR_DARK = 0xff000000;

    // Temporary variable to avoid allocations
    private float[] mTmpHSL = new float[3];

    /**
     * Grab colors from WallpaperColors as set them into GradientColors
     * Grab colors from WallpaperColors and set them into GradientColors.
     * Also applies the default gradient in case extraction fails.
     *
     * @param inWallpaperColors Input.
     * @param outColorsNormal Colors for normal theme.
     * @param outColorsDark Colors for dar theme.
     * @param outColorsExtraDark Colors for extra dark theme.
     */
    public void extractInto(@Nullable WallpaperColors inWallpaperColors,
            @NonNull GradientColors outColorsNormal, @NonNull GradientColors outColorsDark,
            @NonNull GradientColors outColorsExtraDark) {
        boolean success = runTonalExtraction(inWallpaperColors, outColorsNormal, outColorsDark,
                outColorsExtraDark);
        if (!success) {
            applyFallback(inWallpaperColors, outColorsNormal, outColorsDark, outColorsExtraDark);
        }
    }

    /**
     * Grab colors from WallpaperColors and set them into GradientColors.
     *
     * @param inWallpaperColors input
     * @param outColorsNormal colors for normal theme
     * @param outColorsDark colors for dar theme
     * @param outColorsExtraDark colors for extra dark theme
     * @return true if successful
     * @param inWallpaperColors Input.
     * @param outColorsNormal Colors for normal theme.
     * @param outColorsDark Colors for dar theme.
     * @param outColorsExtraDark Colors for extra dark theme.
     * @return True if succeeded or false if failed.
     */
    public boolean extractInto(@NonNull WallpaperColors inWallpaperColors,
    private boolean runTonalExtraction(@Nullable WallpaperColors inWallpaperColors,
            @NonNull GradientColors outColorsNormal, @NonNull GradientColors outColorsDark,
            @NonNull GradientColors outColorsExtraDark) {

        if (inWallpaperColors == null) {
            return false;
        }

        final List<Color> mainColors = inWallpaperColors.getMainColors();
        final int mainColorsSize = mainColors.size();
        final boolean supportsDarkText = (inWallpaperColors.getColorHints() &
                WallpaperColors.HINT_SUPPORTS_DARK_TEXT) != 0;

        if (mainColorsSize == 0) {
            return false;
@@ -120,7 +150,6 @@ public class Tonal implements ExtractionType {
        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;
        if (DEBUG) {
            StringBuilder builder = new StringBuilder("Tonal Palette - index: " + fitIndex +
                    ". Main color: " + Integer.toHexString(getColorInt(fitIndex, h, s, l)) +
@@ -135,21 +164,38 @@ public class Tonal implements ExtractionType {
            Log.d(TAG, builder.toString());
        }

        int primaryIndex = fitIndex;
        int mainColor = getColorInt(primaryIndex, h, s, l);

        // We might want use the fallback in case the extracted color is brighter than our
        // light fallback or darker than our dark fallback.
        ColorUtils.colorToHSL(mainColor, mTmpHSL);
        final float mainLuminosity = mTmpHSL[2];
        ColorUtils.colorToHSL(MAIN_COLOR_LIGHT, mTmpHSL);
        final float lightLuminosity = mTmpHSL[2];
        if (mainLuminosity > lightLuminosity) {
            return false;
        }
        ColorUtils.colorToHSL(MAIN_COLOR_DARK, mTmpHSL);
        final float darkLuminosity = mTmpHSL[2];
        if (mainLuminosity < darkLuminosity) {
            return false;
        }

        // Normal colors:
        // best fit + a 2 colors offset
        int primaryIndex = fitIndex;
        outColorsNormal.setMainColor(mainColor);
        int secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2);
        outColorsNormal.setMainColor(getColorInt(primaryIndex, h, s, l));
        outColorsNormal.setSecondaryColor(getColorInt(secondaryIndex, h, s, l));

        // Dark colors:
        // Stops at 4th color, only lighter if dark text is supported
        if (fitIndex < 2) {
        if (supportsDarkText) {
            primaryIndex = h.length - 1;
        } else if (fitIndex < 2) {
            primaryIndex = 0;
        } else if (fitIndex < textInversionIndex) {
            primaryIndex = Math.min(fitIndex, 3);
        } else {
            primaryIndex = h.length - 1;
            primaryIndex = Math.min(fitIndex, 3);
        }
        secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2);
        outColorsDark.setMainColor(getColorInt(primaryIndex, h, s, l));
@@ -157,18 +203,17 @@ public class Tonal implements ExtractionType {

        // Extra Dark:
        // Stay close to dark colors until dark text is supported
        if (fitIndex < 2) {
        if (supportsDarkText) {
            primaryIndex = h.length - 1;
        } else if (fitIndex < 2) {
            primaryIndex = 0;
        } else if (fitIndex < textInversionIndex) {
            primaryIndex = 2;
        } else {
            primaryIndex = h.length - 1;
            primaryIndex = 2;
        }
        secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2);
        outColorsExtraDark.setMainColor(getColorInt(primaryIndex, h, s, l));
        outColorsExtraDark.setSecondaryColor(getColorInt(secondaryIndex, h, s, l));

        final boolean supportsDarkText = fitIndex >= textInversionIndex;
        outColorsNormal.setSupportsDarkText(supportsDarkText);
        outColorsDark.setSupportsDarkText(supportsDarkText);
        outColorsExtraDark.setSupportsDarkText(supportsDarkText);
@@ -181,6 +226,33 @@ public class Tonal implements ExtractionType {
        return true;
    }

    private void applyFallback(@Nullable WallpaperColors inWallpaperColors,
            GradientColors outColorsNormal, GradientColors outColorsDark,
            GradientColors outColorsExtraDark) {
        applyFallback(inWallpaperColors, outColorsNormal);
        applyFallback(inWallpaperColors, outColorsDark);
        applyFallback(inWallpaperColors, outColorsExtraDark);
    }

    /**
     * Sets the gradient to the light or dark fallbacks based on the current wallpaper colors.
     *
     * @param inWallpaperColors Colors to read.
     * @param outGradientColors Destination.
     */
    public static void applyFallback(@Nullable WallpaperColors inWallpaperColors,
            @NonNull GradientColors outGradientColors) {
        boolean light = inWallpaperColors != null
                && (inWallpaperColors.getColorHints() & WallpaperColors.HINT_SUPPORTS_DARK_TEXT)
                != 0;
        int innerColor = light ? MAIN_COLOR_LIGHT : MAIN_COLOR_DARK;
        int outerColor = light ? SECONDARY_COLOR_LIGHT : SECONDARY_COLOR_DARK;

        outGradientColors.setMainColor(innerColor);
        outGradientColors.setSecondaryColor(outerColor);
        outGradientColors.setSupportsDarkText(light);
    }

    private int getColorInt(int fitIndex, float[] h, float[] s, float[] l) {
        mTmpHSL[0] = fract(h[fitIndex]) * 360.0f;
        mTmpHSL[1] = s[fitIndex];
+22 −3
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.colorextraction;

import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.content.Context;
import android.os.Handler;
@@ -47,10 +48,10 @@ public class SysuiColorExtractor extends ColorExtractor {
    @VisibleForTesting
    public SysuiColorExtractor(Context context, ExtractionType type, boolean registerVisibility) {
        super(context, type);

        mWpHiddenColors = new GradientColors();
        mWpHiddenColors.setMainColor(FALLBACK_COLOR);
        mWpHiddenColors.setSecondaryColor(FALLBACK_COLOR);

        WallpaperColors systemColors = getWallpaperColors(WallpaperManager.FLAG_SYSTEM);
        updateDefaultGradients(systemColors);

        if (registerVisibility) {
            try {
@@ -71,6 +72,24 @@ public class SysuiColorExtractor extends ColorExtractor {
        }
    }

    private void updateDefaultGradients(WallpaperColors colors) {
        Tonal.applyFallback(colors, mWpHiddenColors);
    }

    @Override
    public void onColorsChanged(WallpaperColors colors, int which) {
        super.onColorsChanged(colors, which);

        if ((which & WallpaperManager.FLAG_SYSTEM) != 0) {
            updateDefaultGradients(colors);
        }
    }

    @VisibleForTesting
    GradientColors getFallbackColors() {
        return mWpHiddenColors;
    }

    /**
     * Get TYPE_NORMAL colors when wallpaper is visible, or fallback otherwise.
     *
+3 −6
Original line number Diff line number Diff line
@@ -48,14 +48,12 @@ public class SysuiColorExtractorTests extends SysuiTestCase {

    @Test
    public void getColors_usesGreyIfWallpaperNotVisible() {
        ColorExtractor.GradientColors fallbackColors = new ColorExtractor.GradientColors();
        fallbackColors.setMainColor(ColorExtractor.FALLBACK_COLOR);
        fallbackColors.setSecondaryColor(ColorExtractor.FALLBACK_COLOR);

        SysuiColorExtractor extractor = new SysuiColorExtractor(getContext(), new Tonal(), false);
        simulateEvent(extractor);
        extractor.setWallpaperVisible(false);

        ColorExtractor.GradientColors fallbackColors = extractor.getFallbackColors();

        for (int which : sWhich) {
            for (int type : sTypes) {
                assertEquals("Not using fallback!", extractor.getColors(which, type),
@@ -76,7 +74,6 @@ public class SysuiColorExtractorTests extends SysuiTestCase {
                    outGradientColorsNormal.set(colors);
                    outGradientColorsDark.set(colors);
                    outGradientColorsExtraDark.set(colors);
                    return true;
                }, false);
        simulateEvent(extractor);
        extractor.setWallpaperVisible(true);
@@ -91,7 +88,7 @@ public class SysuiColorExtractorTests extends SysuiTestCase {

    private void simulateEvent(SysuiColorExtractor extractor) {
        // Let's fake a color event
        extractor.onColorsChanged(new WallpaperColors(Color.valueOf(Color.BLACK), null, null, 0),
        extractor.onColorsChanged(new WallpaperColors(Color.valueOf(Color.GREEN), null, null, 0),
                WallpaperManager.FLAG_SYSTEM | WallpaperManager.FLAG_LOCK);
    }
}
 No newline at end of file
Loading