diff options
| author | 2017-05-28 08:51:07 -0700 | |
|---|---|---|
| committer | 2017-06-05 12:59:35 -0700 | |
| commit | 7aaa353cbb872c308b9be292e11e88d4e497645c (patch) | |
| tree | 8b1f28933418f80126ab03ea75caac802e568d17 | |
| parent | b1d93c61d8e2296f6fcf368a37299cf923296709 (diff) | |
Tonal palette gradient types
The tonal palette now has 3 gradient types, one for regular scrims
another one for places that require stronger contrast, and a last
version for extra contrast.
Bug: 62161354
Test: runtest -x frameworks/base/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/ColorExtractorTest.java
Change-Id: I0be6726334f7a71f04ee02c61994101c97771f1a
10 files changed, 362 insertions, 111 deletions
diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java index 1b3519b1d4c2..4a5d8b460517 100644 --- a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java +++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java @@ -19,9 +19,10 @@ package com.google.android.colorextraction; import android.app.WallpaperColors; import android.app.WallpaperManager; import android.content.Context; -import android.graphics.Color; -import android.support.v4.graphics.ColorUtils; +import android.support.annotation.NonNull; +import android.support.annotation.VisibleForTesting; import android.util.Log; +import android.util.SparseArray; import com.google.android.colorextraction.types.ExtractionType; import com.google.android.colorextraction.types.Tonal; @@ -32,81 +33,143 @@ import java.util.ArrayList; * Class to process wallpaper colors and generate a tonal palette based on them. */ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener { + + public static final int TYPE_NORMAL = 0; + public static final int TYPE_DARK = 1; + public static final int TYPE_EXTRA_DARK = 2; + private static final int[] sGradientTypes = new int[]{TYPE_NORMAL, TYPE_DARK, TYPE_EXTRA_DARK}; + private static final String TAG = "ColorExtractor"; - private static final int FALLBACK_COLOR = Color.BLACK; - private static final float DARK_TEXT_LUMINOSITY = 0.7f; + + @VisibleForTesting + static final int FALLBACK_COLOR = 0xff83888d; private int mMainFallbackColor = FALLBACK_COLOR; private int mSecondaryFallbackColor = FALLBACK_COLOR; - private final GradientColors mSystemColors; - private final GradientColors mLockColors; + private final SparseArray<GradientColors[]> mGradientColors; + private final ArrayList<OnColorsChangedListener> mOnColorsChangedListeners; + // Colors to return when the wallpaper isn't visible + private final GradientColors mWpHiddenColors; private final Context mContext; private final ExtractionType mExtractionType; - private final ArrayList<OnColorsChangedListener> mOnColorsChangedListeners; public ColorExtractor(Context context) { + this(context, new Tonal()); + } + + @VisibleForTesting + public ColorExtractor(Context context, ExtractionType extractionType) { mContext = context; - mSystemColors = new GradientColors(); - mLockColors = new GradientColors(); - mExtractionType = new Tonal(); + mWpHiddenColors = new GradientColors(); + mWpHiddenColors.setMainColor(FALLBACK_COLOR); + mWpHiddenColors.setSecondaryColor(FALLBACK_COLOR); + mExtractionType = extractionType; + + mGradientColors = new SparseArray<>(); + for (int which : new int[] { WallpaperManager.FLAG_LOCK, WallpaperManager.FLAG_SYSTEM}) { + GradientColors[] colors = new GradientColors[sGradientTypes.length]; + mGradientColors.append(which, colors); + for (int type : sGradientTypes) { + colors[type] = new GradientColors(); + } + } + mOnColorsChangedListeners = new ArrayList<>(); WallpaperManager wallpaperManager = mContext.getSystemService(WallpaperManager.class); - if (wallpaperManager == null) { Log.w(TAG, "Can't listen to color changes!"); } else { wallpaperManager.addOnColorsChangedListener(this); + + // Initialize all gradients with the current colors + GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM); extractInto(wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_SYSTEM), - mSystemColors); + systemColors[TYPE_NORMAL], + systemColors[TYPE_DARK], + systemColors[TYPE_EXTRA_DARK]); + + GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK); extractInto(wallpaperManager.getWallpaperColors(WallpaperManager.FLAG_LOCK), - mLockColors); + lockColors[TYPE_NORMAL], + lockColors[TYPE_DARK], + lockColors[TYPE_EXTRA_DARK]); } } + /** + * Retrieve TYPE_NORMAL gradient colors considering wallpaper visibility. + * + * @param which FLAG_LOCK or FLAG_SYSTEM + * @return colors + */ + @NonNull 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"); + return getColors(which, TYPE_NORMAL); + } + + /** + * Get current gradient colors for one of the possible gradient types + * + * @param which FLAG_LOCK or FLAG_SYSTEM + * @param type TYPE_NORMAL, TYPE_DARK or TYPE_EXTRA_DARK + * @return colors + */ + public GradientColors getColors(int which, int type) { + if (type != TYPE_NORMAL && type != TYPE_DARK && type != TYPE_EXTRA_DARK) { + throw new IllegalArgumentException( + "type should be TYPE_NORMAL, TYPE_DARK or TYPE_EXTRA_DARK"); } + if (which != WallpaperManager.FLAG_LOCK && which != WallpaperManager.FLAG_SYSTEM) { + throw new IllegalArgumentException("which should be FLAG_SYSTEM or FLAG_NORMAL"); + } + + return mGradientColors.get(which)[type]; } @Override public void onColorsChanged(WallpaperColors colors, int which) { + boolean changed = false; if ((which & WallpaperManager.FLAG_LOCK) != 0) { - extractInto(colors, mLockColors); - for (OnColorsChangedListener listener : mOnColorsChangedListeners) { - listener.onColorsChanged(mLockColors, WallpaperManager.FLAG_LOCK); - } + GradientColors[] lockColors = mGradientColors.get(WallpaperManager.FLAG_LOCK); + extractInto(colors, lockColors[TYPE_NORMAL], lockColors[TYPE_DARK], + lockColors[TYPE_EXTRA_DARK]); + + changed = true; } if ((which & WallpaperManager.FLAG_SYSTEM) != 0) { - extractInto(colors, mSystemColors); - for (OnColorsChangedListener listener : mOnColorsChangedListeners) { - listener.onColorsChanged(mSystemColors, WallpaperManager.FLAG_SYSTEM); - } + GradientColors[] systemColors = mGradientColors.get(WallpaperManager.FLAG_SYSTEM); + extractInto(colors, systemColors[TYPE_NORMAL], systemColors[TYPE_DARK], + systemColors[TYPE_EXTRA_DARK]); + changed = true; + } + + if (changed) { + triggerColorsChanged(which); + } + } + + private void triggerColorsChanged(int which) { + for (OnColorsChangedListener listener: mOnColorsChangedListeners) { + listener.onColorsChanged(this, which); } } - private void extractInto(WallpaperColors inWallpaperColors, GradientColors outGradientColors) { - applyFallback(outGradientColors); + 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, outGradientColors); - if (success) { - // Updating dark text support. We're going to verify if the mean luminosity - // is greater then a threshold. - float hsl[] = new float[3]; - float meanLuminosity = 0; - ColorUtils.colorToHSL(outGradientColors.getMainColor(), hsl); - meanLuminosity += hsl[2]; - ColorUtils.colorToHSL(outGradientColors.getSecondaryColor(), hsl); - meanLuminosity += hsl[2]; - meanLuminosity /= 2; - outGradientColors.setSupportsDarkText(meanLuminosity >= DARK_TEXT_LUMINOSITY); + boolean success = mExtractionType.extractInto(inWallpaperColors, outGradientColorsNormal, + outGradientColorsDark, outGradientColorsExtraDark); + if (!success) { + applyFallback(outGradientColorsNormal); + applyFallback(outGradientColorsDark); + applyFallback(outGradientColorsExtraDark); } } @@ -123,11 +186,11 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener } } - public void addOnColorsChangedListener(OnColorsChangedListener listener) { + public void addOnColorsChangedListener(@NonNull OnColorsChangedListener listener) { mOnColorsChangedListeners.add(listener); } - public void removeOnColorsChangedListener(OnColorsChangedListener listener) { + public void removeOnColorsChangedListener(@NonNull OnColorsChangedListener listener) { mOnColorsChangedListeners.remove(listener); } @@ -184,9 +247,15 @@ public class ColorExtractor implements WallpaperManager.OnColorsChangedListener code = 31 * code + (mSupportsDarkText ? 0 : 1); return code; } + + @Override + public String toString() { + return "GradientColors(" + Integer.toHexString(mMainColor) + ", " + + Integer.toHexString(mSecondaryColor) + ")"; + } } public interface OnColorsChangedListener { - void onColorsChanged(GradientColors colors, int which); + void onColorsChanged(ColorExtractor colorExtractor, int which); } } diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java index 36cabc999720..4c3ac3e038de 100644 --- a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java +++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java @@ -29,10 +29,19 @@ public interface ExtractionType { * Executes color extraction by reading WallpaperColors and setting * main and secondary colors on GradientColors. * + * Extraction is expected to happen with 3 different gradient types: + * Normal, with the main extracted colors + * Dark, with extra contrast + * ExtraDark, for places where GAR is mandatory, like the emergency dialer + * * @param inWallpaperColors where to read from - * @param outGradientColors object that should receive the colors - * @return true if successful + * @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, - ColorExtractor.GradientColors outGradientColors); + ColorExtractor.GradientColors outGradientColorsNormal, + ColorExtractor.GradientColors outGradientColorsDark, + ColorExtractor.GradientColors outGradientColorsExtraDark); } diff --git a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java index 85ac90a53ea8..5b4b3ed77f3a 100644 --- a/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java +++ b/packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java @@ -27,7 +27,7 @@ import android.util.MathUtils; import android.util.Pair; import android.util.Range; -import com.google.android.colorextraction.ColorExtractor; +import com.google.android.colorextraction.ColorExtractor.GradientColors; /** * Implementation of tonal color extraction @@ -43,25 +43,25 @@ public class Tonal implements ExtractionType { // When extracting the main color, only consider colors // present in at least MIN_COLOR_OCCURRENCE of the image private static final float MIN_COLOR_OCCURRENCE = 0.1f; + private static final boolean DEBUG = true; - // Secondary color will be darker than the main color when - // main color is brighter than this variable. - private static final float MAX_COLOR_LUMINOSITY = 0.8f; - // Luminosity difference between main and secondary colors - // should never be greater then this. - private static final float MAX_LUMINOSITY_DISTANCE = 0.35f; + // Temporary variable to avoid allocations + private float[] mTmpHSL = new float[3]; /** * Grab colors from WallpaperColors as set them into GradientColors * - * @param wallpaperColors input - * @param gradientColors output + * @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 */ - public boolean extractInto(WallpaperColors wallpaperColors, - ColorExtractor.GradientColors gradientColors) { + public boolean extractInto(@NonNull WallpaperColors inWallpaperColors, + @NonNull GradientColors outColorsNormal, @NonNull GradientColors outColorsDark, + @NonNull GradientColors outColorsExtraDark) { - if (wallpaperColors.getColors().size() == 0) { + if (inWallpaperColors.getColors().size() == 0) { return false; } // Tonal is not really a sort, it takes a color from the extracted @@ -70,17 +70,17 @@ public class Tonal implements ExtractionType { // and replaces the original palette // First find the most representative color in the image - populationSort(wallpaperColors); + populationSort(inWallpaperColors); // Calculate total int total = 0; - for (Pair<Color, Integer> weightedColor : wallpaperColors.getColors()) { + for (Pair<Color, Integer> weightedColor : inWallpaperColors.getColors()) { total += weightedColor.second; } // Get bright colors that occur often enough in this image Pair<Color, Integer> bestColor = null; float[] hsl = new float[3]; - for (Pair<Color, Integer> weightedColor : wallpaperColors.getColors()) { + for (Pair<Color, Integer> weightedColor : inWallpaperColors.getColors()) { float colorOccurrence = weightedColor.second / (float) total; if (colorOccurrence < MIN_COLOR_OCCURRENCE) { break; @@ -97,7 +97,7 @@ public class Tonal implements ExtractionType { } } - // Fallback to first color + // Fail if not found if (bestColor == null) { return false; } @@ -107,59 +107,97 @@ public class Tonal implements ExtractionType { hsl); // The Android HSL definition requires the hue to go from 0 to 360 but - // the Material Tonal Palette defines hues from 0 to 1 - hsl[0] /= 360.0f; // normalize + // the Material Tonal Palette defines hues from 0 to 1. + hsl[0] /= 360f; // Find the palette that contains the closest color TonalPalette palette = findTonalPalette(hsl[0]); - if (palette == null) { Log.w(TAG, "Could not find a tonal palette!"); return false; } + // Figure out what's the main color index in the optimal palette int fitIndex = bestFit(palette, hsl[0], hsl[1], hsl[2]); if (fitIndex == -1) { Log.w(TAG, "Could not find best fit!"); return false; } + + // Generate the 10 colors palette by offsetting each one of them float[] h = fit(palette.h, hsl[0], fitIndex, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY); float[] s = fit(palette.s, hsl[1], fitIndex, 0.0f, 1.0f); float[] l = fit(palette.l, hsl[2], fitIndex, 0.0f, 1.0f); - hsl[0] = fract(h[fitIndex]) * 360.0f; - hsl[1] = s[fitIndex]; - hsl[2] = l[fitIndex]; - gradientColors.setMainColor(ColorUtils.HSLToColor(hsl)); - - int secondColorIndex = fitIndex; - if (hsl[2] > MAX_COLOR_LUMINOSITY) { - for (int i = secondColorIndex - 1; i >= 0; i--) { - float distance = Math.abs(hsl[2] - l[i]); - if (distance > MAX_LUMINOSITY_DISTANCE) { - break; - } - secondColorIndex = i; - } - } else { - for (int i = secondColorIndex + 1; i < h.length; i++) { - float distance = Math.abs(hsl[2] - l[i]); - if (distance > MAX_LUMINOSITY_DISTANCE) { - break; + 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)) + + "\nColors: "); + + for (int i=0; i < h.length; i++) { + builder.append(Integer.toHexString(getColorInt(i, h, s, l))); + if (i < h.length - 1) { + builder.append(", "); } - secondColorIndex = i; } + Log.d(TAG, builder.toString()); } - hsl[0] = fract(h[secondColorIndex]) * 360.0f; - hsl[1] = s[secondColorIndex]; - hsl[2] = l[secondColorIndex]; - gradientColors.setSecondaryColor(ColorUtils.HSLToColor(hsl)); + // Normal colors: + // best fit + a 2 colors offset + int primaryIndex = fitIndex; + 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) { + primaryIndex = 0; + } else if (fitIndex < textInversionIndex) { + primaryIndex = Math.min(fitIndex, 3); + } else { + primaryIndex = h.length - 1; + } + secondaryIndex = primaryIndex + (primaryIndex >= 2 ? -2 : 2); + outColorsDark.setMainColor(getColorInt(primaryIndex, h, s, l)); + outColorsDark.setSecondaryColor(getColorInt(secondaryIndex, h, s, l)); + + // Extra Dark: + // Stay close to dark colors until dark text is supported + if (fitIndex < 2) { + primaryIndex = 0; + } else if (fitIndex < textInversionIndex) { + primaryIndex = 2; + } else { + primaryIndex = h.length - 1; + } + 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); + + if (DEBUG) { + Log.d(TAG, "Gradients: \n\tNormal " + outColorsNormal + "\n\tDark " + outColorsDark + + "\n\tExtra dark: " + outColorsExtraDark); + } return true; } + private int getColorInt(int fitIndex, float[] h, float[] s, float[] l) { + mTmpHSL[0] = fract(h[fitIndex]) * 360.0f; + mTmpHSL[1] = s[fitIndex]; + mTmpHSL[2] = l[fitIndex]; + return ColorUtils.HSLToColor(mTmpHSL); + } + /** * Checks if a given color exists in the blacklist * @param hsl float array with 3 components (H 0..360, S 0..1 and L 0..1) diff --git a/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/ColorExtractorTest.java b/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/ColorExtractorTest.java new file mode 100644 index 000000000000..fd698d050a0c --- /dev/null +++ b/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/ColorExtractorTest.java @@ -0,0 +1,114 @@ +/* + * 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.google.android.colorextraction; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.app.WallpaperColors; +import android.app.WallpaperManager; +import android.content.Context; +import android.graphics.Color; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.support.test.runner.AndroidJUnit4; + +import com.google.android.colorextraction.ColorExtractor.GradientColors; +import com.google.android.colorextraction.types.ExtractionType; +import com.google.android.colorextraction.types.Tonal; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Tests tonal palette generation. + */ +@SmallTest +@RunWith(AndroidJUnit4.class) +public class ColorExtractorTest { + + Context mContext; + + @Before + public void setup() { + mContext = InstrumentationRegistry.getContext(); + } + + @Test + public void ColorExtractor_extractWhenInitialized() { + ExtractionType type = mock(Tonal.class); + new ColorExtractor(mContext, type); + // 1 for lock and 1 for system + verify(type, times(2)) + .extractInto(any(), any(), any(), any()); + } + + @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); + colorsExpectedNormal.setSecondaryColor(Color.GRAY); + + GradientColors colorsExpectedDark = new GradientColors(); + colorsExpectedNormal.setMainColor(Color.BLACK); + colorsExpectedNormal.setSecondaryColor(Color.BLUE); + + GradientColors colorsExpectedExtraDark = new GradientColors(); + colorsExpectedNormal.setMainColor(Color.MAGENTA); + colorsExpectedNormal.setSecondaryColor(Color.GREEN); + + ExtractionType type = + (inWallpaperColors, outGradientColorsNormal, outGradientColorsDark, + outGradientColorsExtraDark) -> { + outGradientColorsNormal.set(colorsExpectedNormal); + outGradientColorsDark.set(colorsExpectedDark); + outGradientColorsExtraDark.set(colorsExpectedExtraDark); + // Successful extraction + return true; + }; + ColorExtractor extractor = new ColorExtractor(mContext, type); + + assertEquals("Extracted colors not being used!", + extractor.getColors(WallpaperManager.FLAG_SYSTEM, ColorExtractor.TYPE_NORMAL), + colorsExpectedNormal); + assertEquals("Extracted colors not being used!", + extractor.getColors(WallpaperManager.FLAG_SYSTEM, ColorExtractor.TYPE_DARK), + colorsExpectedDark); + assertEquals("Extracted colors not being used!", + extractor.getColors(WallpaperManager.FLAG_SYSTEM, ColorExtractor.TYPE_EXTRA_DARK), + colorsExpectedExtraDark); + } +} diff --git a/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/types/TonalTest.java b/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/types/TonalTest.java index 537ee1ac2fae..404076cb5301 100644 --- a/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/types/TonalTest.java +++ b/packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/types/TonalTest.java @@ -27,6 +27,7 @@ import android.util.Pair; import android.util.Range; import com.google.android.colorextraction.ColorExtractor; +import com.google.android.colorextraction.ColorExtractor.GradientColors; import org.junit.Test; import org.junit.runner.RunWith; @@ -76,7 +77,8 @@ public class TonalTest { // Make sure that palette generation will fail Tonal tonal = new Tonal(); - boolean success = tonal.extractInto(colors, new ColorExtractor.GradientColors()); + boolean success = tonal.extractInto(colors, new GradientColors(), new GradientColors(), + new GradientColors()); assertFalse("Cannot generate a tonal palette from blacklisted colors ", success); } } diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java index ae6249d57599..e8dcf6c1f0b2 100644 --- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java @@ -1339,14 +1339,14 @@ class GlobalActionsDialog implements DialogInterface.OnDismissListener, DialogIn } @Override - public void onColorsChanged(GradientColors colors, int which) { + public void onColorsChanged(ColorExtractor extractor, int which) { if (mKeyguardShowing) { if ((WallpaperManager.FLAG_LOCK & which) != 0) { - mGradientDrawable.setColors(colors); + mGradientDrawable.setColors(extractor.getColors(WallpaperManager.FLAG_LOCK)); } } else { if ((WallpaperManager.FLAG_SYSTEM & which) != 0) { - mGradientDrawable.setColors(colors); + mGradientDrawable.setColors(extractor.getColors(WallpaperManager.FLAG_SYSTEM)); } } } diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java index 978533cfdf56..319b4638713a 100644 --- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java +++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java @@ -21,6 +21,7 @@ import static android.app.ActivityManager.StackId.INVALID_STACK_ID; import android.animation.Animator; import android.animation.ObjectAnimator; import android.app.ActivityOptions.OnAnimationStartedListener; +import android.app.WallpaperColors; import android.app.WallpaperManager; import android.content.Context; import android.graphics.Canvas; @@ -111,7 +112,7 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC private int mDividerSize; private final float mScrimAlpha; - private final GradientDrawable mBackgroundScrim; + private GradientDrawable mBackgroundScrim; private final ColorExtractor mColorExtractor; private Animator mBackgroundScrimAnimator; @@ -828,9 +829,9 @@ public class RecentsView extends FrameLayout implements ColorExtractor.OnColorsC } @Override - public void onColorsChanged(ColorExtractor.GradientColors colors, int which) { + public void onColorsChanged(ColorExtractor extractor, int which) { if ((which & WallpaperManager.FLAG_SYSTEM) != 0) { - mBackgroundScrim.setColors(colors); + mBackgroundScrim.setColors(extractor.getColors(WallpaperManager.FLAG_SYSTEM)); } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java index 69f5135d406f..f502bb5c5dfc 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -25,7 +25,6 @@ import android.content.Context; import android.graphics.Color; import android.graphics.Rect; import android.graphics.drawable.Drawable; -import android.util.Log; import android.util.MathUtils; import android.view.View; import android.view.ViewGroup; @@ -44,13 +43,14 @@ import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener; import com.android.systemui.statusbar.stack.ViewState; import com.google.android.colorextraction.ColorExtractor; +import com.google.android.colorextraction.ColorExtractor.OnColorsChangedListener; /** * Controls both the scrim behind the notifications and in front of the notifications (when a * security method gets shown). */ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, - OnHeadsUpChangedListener, ColorExtractor.OnColorsChangedListener { + OnHeadsUpChangedListener, OnColorsChangedListener { public static final long ANIMATION_DURATION = 220; public static final Interpolator KEYGUARD_FADE_OUT_INTERPOLATOR = new PathInterpolator(0f, 0, 0.7f, 1f); @@ -80,7 +80,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, private final ColorExtractor mColorExtractor; private ColorExtractor.GradientColors mLockColors; + private ColorExtractor.GradientColors mLockColorsDark; private ColorExtractor.GradientColors mSystemColors; + private ColorExtractor.GradientColors mSystemColorsDark; private boolean mNeedsDrawableColorUpdate; protected float mScrimBehindAlpha; @@ -133,6 +135,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, mColorExtractor.addOnColorsChangedListener(this); mLockColors = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK); mSystemColors = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM); + // Darker gradient for the top scrim (mScrimInFront) + mLockColorsDark = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK, + ColorExtractor.TYPE_DARK); + mSystemColorsDark = mColorExtractor.getColors(WallpaperManager.FLAG_SYSTEM, + ColorExtractor.TYPE_DARK); mNeedsDrawableColorUpdate = true; updateHeadsUpScrim(false); @@ -142,8 +149,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, public void setKeyguardShowing(boolean showing) { mKeyguardShowing = showing; - // Showing/hiding the keyguard means that scrim colors - // will probably have to be switched + // Showing/hiding the keyguard means that scrim colors have to be switched mNeedsDrawableColorUpdate = true; scheduleUpdate(); } @@ -301,11 +307,15 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, if (mNeedsDrawableColorUpdate) { mNeedsDrawableColorUpdate = false; if (mKeyguardShowing) { - mScrimInFront.setColors(mLockColors); + // Always animate color changes if we're seeing the keyguard + mScrimInFront.setColors(mLockColorsDark); mScrimBehind.setColors(mLockColors); } else { - mScrimInFront.setColors(mSystemColors, true); - mScrimBehind.setColors(mSystemColors, true); + // Only animate scrim color if the scrim view is actually visible + boolean animateScrimInFront = mScrimInFront.getViewAlpha() != 0; + boolean animateScrimBehind = mScrimBehind.getViewAlpha() != 0; + mScrimInFront.setColors(mSystemColorsDark, animateScrimInFront); + mScrimBehind.setColors(mSystemColors, animateScrimBehind); } } @@ -647,14 +657,20 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, } @Override - public void onColorsChanged(ColorExtractor.GradientColors colors, int which) { + public void onColorsChanged(ColorExtractor colorExtractor, int which) { if ((which & WallpaperManager.FLAG_LOCK) != 0) { - mLockColors = colors; + mLockColors = colorExtractor.getColors(WallpaperManager.FLAG_LOCK, + ColorExtractor.TYPE_NORMAL); + mLockColorsDark = colorExtractor.getColors(WallpaperManager.FLAG_LOCK, + ColorExtractor.TYPE_DARK); mNeedsDrawableColorUpdate = true; scheduleUpdate(); } if ((which & WallpaperManager.FLAG_SYSTEM) != 0) { - mSystemColors = colors; + mSystemColors = colorExtractor.getColors(WallpaperManager.FLAG_SYSTEM, + ColorExtractor.TYPE_NORMAL); + mSystemColorsDark = colorExtractor.getColors(WallpaperManager.FLAG_SYSTEM, + ColorExtractor.TYPE_DARK); mNeedsDrawableColorUpdate = true; scheduleUpdate(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java index 7564c8275ce4..046bc480bf67 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java @@ -2829,7 +2829,7 @@ public class StatusBar extends SystemUI implements DemoMode, } @Override - public void onColorsChanged(ColorExtractor.GradientColors colors, int which) { + public void onColorsChanged(ColorExtractor extractor, int which) { updateTheme(); } @@ -4501,6 +4501,8 @@ public class StatusBar extends SystemUI implements DemoMode, */ private void updateTheme() { boolean useDarkTheme; + // Ignore visibility since we calculate the theme based on the real colors, + // not the current state. if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) { useDarkTheme = mColorExtractor.getColors(WallpaperManager.FLAG_LOCK) .supportsDarkText(); diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java index 9e26c1eaf415..1e0efda40ace 100644 --- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java +++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java @@ -1099,14 +1099,14 @@ public class VolumeDialogImpl implements VolumeDialog, TunerService.Tunable, }; @Override - public void onColorsChanged(ColorExtractor.GradientColors colors, int which) { + public void onColorsChanged(ColorExtractor extractor, int which) { if (mKeyguard.isKeyguardLocked()) { if ((WallpaperManager.FLAG_LOCK & which) != 0) { - mGradientDrawable.setColors(colors); + mGradientDrawable.setColors(extractor.getColors(WallpaperManager.FLAG_LOCK)); } } else { if ((WallpaperManager.FLAG_SYSTEM & which) != 0) { - mGradientDrawable.setColors(colors); + mGradientDrawable.setColors(extractor.getColors(WallpaperManager.FLAG_SYSTEM)); } } } |