diff options
7 files changed, 162 insertions, 88 deletions
diff --git a/core/java/com/android/internal/colorextraction/ColorExtractor.java b/core/java/com/android/internal/colorextraction/ColorExtractor.java index 2608698f5b63..04819a5999eb 100644 --- a/core/java/com/android/internal/colorextraction/ColorExtractor.java +++ b/core/java/com/android/internal/colorextraction/ColorExtractor.java @@ -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); - - GradientColors[] systemColors = mGradientColors.get( - WallpaperManager.FLAG_SYSTEM); - 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(); } + + // Initialize all gradients with the current colors + extractInto(mSystemColors, + systemColors[TYPE_NORMAL], + systemColors[TYPE_DARK], + systemColors[TYPE_EXTRA_DARK]); + extractInto(mLockColors, + lockColors[TYPE_NORMAL], + lockColors[TYPE_DARK], + lockColors[TYPE_EXTRA_DARK]); } /** @@ -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) { diff --git a/core/java/com/android/internal/colorextraction/types/ExtractionType.java b/core/java/com/android/internal/colorextraction/types/ExtractionType.java index 762b54fb1e6b..7000e798f87b 100644 --- a/core/java/com/android/internal/colorextraction/types/ExtractionType.java +++ b/core/java/com/android/internal/colorextraction/types/ExtractionType.java @@ -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); diff --git a/core/java/com/android/internal/colorextraction/types/Tonal.java b/core/java/com/android/internal/colorextraction/types/Tonal.java index b8ebe3000d8e..e78ca3844bed 100644 --- a/core/java/com/android/internal/colorextraction/types/Tonal.java +++ b/core/java/com/android/internal/colorextraction/types/Tonal.java @@ -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]; diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java index ccb81172c75c..3c895abd5e88 100644 --- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java +++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java @@ -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. * diff --git a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java index a81188af85ef..690186e91f55 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java +++ b/packages/SystemUI/tests/src/com/android/systemui/colorextraction/SysuiColorExtractorTests.java @@ -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 diff --git a/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java b/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java index 71821472f55e..0060901578cd 100644 --- a/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java +++ b/tests/Internal/src/com/android/internal/colorextraction/ColorExtractorTest.java @@ -62,21 +62,6 @@ public class ColorExtractorTest { } @Test - public void getColors_usesFallbackIfFails() { - ExtractionType alwaysFail = - (inWallpaperColors, outGradientColorsNormal, outGradientColorsDark, - outGradientColorsExtraDark) -> false; - ColorExtractor extractor = new ColorExtractor(mContext, alwaysFail); - GradientColors colors = extractor.getColors(WallpaperManager.FLAG_SYSTEM); - - assertEquals("Should be using the fallback color.", - colors.getMainColor(), ColorExtractor.FALLBACK_COLOR); - assertEquals("Should be using the fallback color.", - colors.getSecondaryColor(), ColorExtractor.FALLBACK_COLOR); - assertFalse("Dark text support should be false.", colors.supportsDarkText()); - } - - @Test public void getColors_usesExtractedColors() { GradientColors colorsExpectedNormal = new GradientColors(); colorsExpectedNormal.setMainColor(Color.RED); @@ -96,8 +81,6 @@ public class ColorExtractorTest { outGradientColorsNormal.set(colorsExpectedNormal); outGradientColorsDark.set(colorsExpectedDark); outGradientColorsExtraDark.set(colorsExpectedExtraDark); - // Successful extraction - return true; }; ColorExtractor extractor = new ColorExtractor(mContext, type); diff --git a/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java b/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java index 1e3e8e91d9ef..d408b84109bc 100644 --- a/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java +++ b/tests/Internal/src/com/android/internal/colorextraction/types/TonalTest.java @@ -40,6 +40,31 @@ import java.util.Arrays; public class TonalTest { @Test + public void extractInto_usesFallback() { + GradientColors normal = new GradientColors(); + Tonal tonal = new Tonal(); + tonal.extractInto(null, normal, new GradientColors(), + new GradientColors()); + assertFalse("Should use fallback color if WallpaperColors is null.", + normal.getMainColor() == Tonal.MAIN_COLOR_LIGHT); + } + + @Test + public void extractInto_usesFallbackWhenTooLightOrDark() { + GradientColors normal = new GradientColors(); + Tonal tonal = new Tonal(); + tonal.extractInto(new WallpaperColors(Color.valueOf(0xff000000), null, null, 0), + normal, new GradientColors(), new GradientColors()); + assertTrue("Should use fallback color if WallpaperColors is too dark.", + normal.getMainColor() == Tonal.MAIN_COLOR_DARK); + + tonal.extractInto(new WallpaperColors(Color.valueOf(0xffffffff), null, null, 0), + normal, new GradientColors(), new GradientColors()); + assertTrue("Should use fallback color if WallpaperColors is too light.", + normal.getMainColor() == Tonal.MAIN_COLOR_LIGHT); + } + + @Test public void colorRange_containsColor() { Tonal.ColorRange colorRange = new Tonal.ColorRange(new Range<>(0f, 50f), new Range<>(0f, 1f), new Range<>(0f, 1f)); @@ -72,8 +97,10 @@ public class TonalTest { // Make sure that palette generation will fail Tonal tonal = new Tonal(); - boolean success = tonal.extractInto(colors, new GradientColors(), new GradientColors(), + GradientColors normal = new GradientColors(); + tonal.extractInto(colors, normal, new GradientColors(), new GradientColors()); - assertFalse("Cannot generate a tonal palette from blacklisted colors ", success); + assertFalse("Cannot generate a tonal palette from blacklisted colors.", + normal.getMainColor() == Tonal.MAIN_COLOR_LIGHT); } } |