summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Lucas Dupin <dupin@google.com> 2017-05-28 08:51:07 -0700
committer Lucas Dupin <dupin@google.com> 2017-06-05 12:59:35 -0700
commit7aaa353cbb872c308b9be292e11e88d4e497645c (patch)
tree8b1f28933418f80126ab03ea75caac802e568d17
parentb1d93c61d8e2296f6fcf368a37299cf923296709 (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
-rw-r--r--packages/SystemUI/colorextraction/src/com/google/android/colorextraction/ColorExtractor.java157
-rw-r--r--packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/ExtractionType.java15
-rw-r--r--packages/SystemUI/colorextraction/src/com/google/android/colorextraction/types/Tonal.java124
-rw-r--r--packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/ColorExtractorTest.java114
-rw-r--r--packages/SystemUI/colorextraction/tests/src/com/google/android/colorextraction/types/TonalTest.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java36
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java6
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));
}
}
}