Add monet to AOSP
Test: manual
Test: atest ColorSchemeTest
Test: atest SystemPalette
Fixes: 199401230
Change-Id: I0695257765335f12ad47d5d8f40d0885c652bff6
diff --git a/core/java/android/app/DisabledWallpaperManager.java b/core/java/android/app/DisabledWallpaperManager.java
index 1f323c3..ae3a9e6 100644
--- a/core/java/android/app/DisabledWallpaperManager.java
+++ b/core/java/android/app/DisabledWallpaperManager.java
@@ -74,6 +74,11 @@
return false;
}
+ private static int unsupportedInt() {
+ if (DEBUG) Log.w(TAG, "unsupported method called; returning -1", new Exception());
+ return -1;
+ }
+
@Override
public Drawable getDrawable() {
return unsupported();
@@ -189,12 +194,12 @@
@Override
public int getWallpaperId(int which) {
- return unsupported();
+ return unsupportedInt();
}
@Override
public int getWallpaperIdForUser(int which, int userId) {
- return unsupported();
+ return unsupportedInt();
}
@Override
@@ -209,7 +214,8 @@
@Override
public int setResource(int resid, int which) throws IOException {
- return unsupported();
+ unsupported();
+ return 0;
}
@Override
@@ -220,19 +226,22 @@
@Override
public int setBitmap(Bitmap fullImage, Rect visibleCropHint, boolean allowBackup)
throws IOException {
- return unsupported();
+ unsupported();
+ return 0;
}
@Override
public int setBitmap(Bitmap fullImage, Rect visibleCropHint, boolean allowBackup, int which)
throws IOException {
- return unsupported();
+ unsupported();
+ return 0;
}
@Override
public int setBitmap(Bitmap fullImage, Rect visibleCropHint, boolean allowBackup, int which,
int userId) throws IOException {
- return unsupported();
+ unsupported();
+ return 0;
}
@Override
@@ -243,13 +252,15 @@
@Override
public int setStream(InputStream bitmapData, Rect visibleCropHint, boolean allowBackup)
throws IOException {
- return unsupported();
+ unsupported();
+ return 0;
}
@Override
public int setStream(InputStream bitmapData, Rect visibleCropHint, boolean allowBackup,
int which) throws IOException {
- return unsupported();
+ unsupported();
+ return 0;
}
@Override
@@ -259,12 +270,12 @@
@Override
public int getDesiredMinimumWidth() {
- return unsupported();
+ return unsupportedInt();
}
@Override
public int getDesiredMinimumHeight() {
- return unsupported();
+ return unsupportedInt();
}
@Override
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index d051290..6671308 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -92,6 +92,7 @@
"iconloader_base",
"SystemUI-tags",
"SystemUI-proto",
+ "monet",
"dagger2",
"jsr330",
"lottie",
@@ -179,6 +180,7 @@
"mockito-target-extended-minus-junit4",
"testables",
"truth-prebuilt",
+ "monet",
"dagger2",
"jsr330",
"WindowManager-Shell",
diff --git a/packages/SystemUI/monet/Android.bp b/packages/SystemUI/monet/Android.bp
new file mode 100644
index 0000000..507ea25
--- /dev/null
+++ b/packages/SystemUI/monet/Android.bp
@@ -0,0 +1,31 @@
+//
+// Copyright (C) 2021 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 {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+java_library {
+ name: "monet",
+ platform_apis: true,
+ static_libs: [
+ "androidx.annotation_annotation",
+ "androidx.core_core",
+ ],
+ srcs: [
+ "src/**/*.java",
+ "src/**/*.kt",
+ ],
+}
diff --git a/packages/SystemUI/monet/AndroidManifest.xml b/packages/SystemUI/monet/AndroidManifest.xml
new file mode 100644
index 0000000..1fab528
--- /dev/null
+++ b/packages/SystemUI/monet/AndroidManifest.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2021 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.systemui.monet">
+</manifest>
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
new file mode 100644
index 0000000..b8039e1
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/ColorScheme.kt
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) 2021 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.android.systemui.monet
+
+import android.annotation.ColorInt
+import android.app.WallpaperColors
+import android.graphics.Color
+import com.android.internal.graphics.ColorUtils
+import com.android.internal.graphics.cam.Cam
+import com.android.internal.graphics.cam.CamUtils.lstarFromInt
+import kotlin.math.absoluteValue
+import kotlin.math.roundToInt
+
+const val TAG = "ColorScheme"
+
+const val ACCENT1_CHROMA = 48.0f
+const val ACCENT2_CHROMA = 16.0f
+const val ACCENT3_CHROMA = 32.0f
+const val ACCENT3_HUE_SHIFT = 60.0f
+
+const val NEUTRAL1_CHROMA = 4.0f
+const val NEUTRAL2_CHROMA = 8.0f
+
+const val GOOGLE_BLUE = 0xFF1b6ef3.toInt()
+
+const val MIN_CHROMA = 15
+const val MIN_LSTAR = 10
+
+public class ColorScheme(@ColorInt seed: Int, val darkTheme: Boolean) {
+
+ val accent1: List<Int>
+ val accent2: List<Int>
+ val accent3: List<Int>
+ val neutral1: List<Int>
+ val neutral2: List<Int>
+
+ constructor(wallpaperColors: WallpaperColors, darkTheme: Boolean):
+ this(getSeedColor(wallpaperColors), darkTheme)
+
+ val allAccentColors: List<Int>
+ get() {
+ val allColors = mutableListOf<Int>()
+ allColors.addAll(accent1)
+ allColors.addAll(accent2)
+ allColors.addAll(accent3)
+ return allColors
+ }
+
+ val allNeutralColors: List<Int>
+ get() {
+ val allColors = mutableListOf<Int>()
+ allColors.addAll(neutral1)
+ allColors.addAll(neutral2)
+ return allColors
+ }
+
+ val backgroundColor
+ get() = ColorUtils.setAlphaComponent(if (darkTheme) neutral1[8] else neutral1[0], 0xFF)
+
+ val accentColor
+ get() = ColorUtils.setAlphaComponent(if (darkTheme) accent1[2] else accent1[6], 0xFF)
+
+ init {
+ val seedArgb = if (seed == Color.TRANSPARENT) GOOGLE_BLUE else seed
+ val camSeed = Cam.fromInt(seedArgb)
+ val hue = camSeed.hue
+ val chroma = camSeed.chroma.coerceAtLeast(ACCENT1_CHROMA)
+ accent1 = Shades.of(hue, chroma).toList()
+ accent2 = Shades.of(hue, ACCENT2_CHROMA).toList()
+ accent3 = Shades.of(hue + ACCENT3_HUE_SHIFT, ACCENT3_CHROMA).toList()
+ neutral1 = Shades.of(hue, NEUTRAL1_CHROMA).toList()
+ neutral2 = Shades.of(hue, NEUTRAL2_CHROMA).toList()
+ }
+
+ override fun toString(): String {
+ return "ColorScheme {\n" +
+ " neutral1: ${humanReadable(neutral1)}\n" +
+ " neutral2: ${humanReadable(neutral2)}\n" +
+ " accent1: ${humanReadable(accent1)}\n" +
+ " accent2: ${humanReadable(accent2)}\n" +
+ " accent3: ${humanReadable(accent3)}\n" +
+ "}"
+ }
+
+ companion object {
+ /**
+ * Identifies a color to create a color scheme from.
+ *
+ * @param wallpaperColors Colors extracted from an image via quantization.
+ * @return ARGB int representing the color
+ */
+ @JvmStatic
+ @ColorInt
+ fun getSeedColor(wallpaperColors: WallpaperColors): Int {
+ return getSeedColors(wallpaperColors).first()
+ }
+
+ /**
+ * Filters and ranks colors from WallpaperColors.
+ *
+ * @param wallpaperColors Colors extracted from an image via quantization.
+ * @return List of ARGB ints, ordered from highest scoring to lowest.
+ */
+ @JvmStatic
+ fun getSeedColors(wallpaperColors: WallpaperColors): List<Int> {
+ val totalPopulation = wallpaperColors.allColors.values.reduce { a, b -> a + b }
+ .toDouble()
+ val totalPopulationMeaningless = (totalPopulation == 0.0)
+ if (totalPopulationMeaningless) {
+ // WallpaperColors with a population of 0 indicate the colors didn't come from
+ // quantization. Instead of scoring, trust the ordering of the provided primary
+ // secondary/tertiary colors.
+ //
+ // In this case, the colors are usually from a Live Wallpaper.
+ val distinctColors = wallpaperColors.mainColors.map {
+ it.toArgb()
+ }.distinct().filter {
+ val cam = Cam.fromInt(it)
+ val lstar = lstarFromInt(it)
+ cam.chroma >= MIN_CHROMA && lstar >= MIN_LSTAR
+ }.toList()
+
+ if (distinctColors.isEmpty()) {
+ return listOf(GOOGLE_BLUE)
+ }
+ return distinctColors
+ }
+
+ val intToProportion = wallpaperColors.allColors.mapValues {
+ it.value.toDouble() / totalPopulation
+ }
+ val intToCam = wallpaperColors.allColors.mapValues { Cam.fromInt(it.key) }
+
+ // Get an array with 360 slots. A slot contains the percentage of colors with that hue.
+ val hueProportions = huePopulations(intToCam, intToProportion)
+ // Map each color to the percentage of the image with its hue.
+ val intToHueProportion = wallpaperColors.allColors.mapValues {
+ val cam = intToCam[it.key]!!
+ val hue = cam.hue.roundToInt()
+ var proportion = 0.0
+ for (i in hue - 15..hue + 15) {
+ proportion += hueProportions[wrapDegrees(i)]
+ }
+ proportion
+ }
+ // Remove any inappropriate seed colors. For example, low chroma colors look grayscale
+ // raising their chroma will turn them to a much louder color that may not have been
+ // in the image.
+ val filteredIntToCam = intToCam.filter {
+ val cam = it.value
+ val lstar = lstarFromInt(it.key)
+ val proportion = intToHueProportion[it.key]!!
+ cam.chroma >= MIN_CHROMA && lstar >= MIN_LSTAR &&
+ (totalPopulationMeaningless || proportion > 0.01)
+ }
+ // Sort the colors by score, from high to low.
+ val seeds = mutableListOf<Int>()
+ val intToScoreIntermediate = filteredIntToCam.mapValues {
+ score(it.value, intToHueProportion[it.key]!!)
+ }
+ val intToScore = intToScoreIntermediate.entries.toMutableList()
+ intToScore.sortByDescending { it.value }
+
+ // Go through the colors, from high score to low score. If there isn't already a seed
+ // color with a hue close to color being examined, add the color being examined to the
+ // seed colors.
+ for (entry in intToScore) {
+ val int = entry.key
+ val existingSeedNearby = seeds.find {
+ val hueA = intToCam[int]!!.hue
+ val hueB = intToCam[it]!!.hue
+ hueDiff(hueA, hueB) < 15 } != null
+ if (existingSeedNearby) {
+ continue
+ }
+ seeds.add(int)
+ }
+
+ if (seeds.isEmpty()) {
+ // Use gBlue 500 if there are 0 colors
+ seeds.add(GOOGLE_BLUE)
+ }
+
+ return seeds
+ }
+
+ private fun wrapDegrees(degrees: Int): Int {
+ return when {
+ degrees < 0 -> {
+ (degrees % 360) + 360
+ }
+ degrees >= 360 -> {
+ degrees % 360
+ }
+ else -> {
+ degrees
+ }
+ }
+ }
+
+ private fun hueDiff(a: Float, b: Float): Float {
+ return 180f - ((a - b).absoluteValue - 180f).absoluteValue
+ }
+
+ private fun humanReadable(colors: List<Int>): String {
+ return colors.joinToString { "#" + Integer.toHexString(it) }
+ }
+
+ private fun score(cam: Cam, proportion: Double): Double {
+ val proportionScore = 0.7 * 100.0 * proportion
+ val chromaScore = if (cam.chroma < ACCENT1_CHROMA) 0.1 * (cam.chroma - ACCENT1_CHROMA)
+ else 0.3 * (cam.chroma - ACCENT1_CHROMA)
+ return chromaScore + proportionScore
+ }
+
+ private fun huePopulations(
+ camByColor: Map<Int, Cam>,
+ populationByColor: Map<Int, Double>
+ ): List<Double> {
+ val huePopulation = List(size = 360, init = { 0.0 }).toMutableList()
+
+ for (entry in populationByColor.entries) {
+ val population = populationByColor[entry.key]!!
+ val cam = camByColor[entry.key]!!
+ val hue = cam.hue.roundToInt() % 360
+ huePopulation[hue] = huePopulation[hue] + population
+ }
+
+ return huePopulation
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/Shades.java b/packages/SystemUI/monet/src/com/android/systemui/monet/Shades.java
new file mode 100644
index 0000000..498b7dd
--- /dev/null
+++ b/packages/SystemUI/monet/src/com/android/systemui/monet/Shades.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2021 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.android.systemui.monet;
+
+
+import androidx.annotation.ColorInt;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.graphics.ColorUtils;
+
+
+/**
+ * Generate sets of colors that are shades of the same color
+ */
+@VisibleForTesting
+public class Shades {
+ /**
+ * Combining the ability to convert between relative luminance and perceptual luminance with
+ * contrast leads to a design system that can be based on a linear value to determine contrast,
+ * rather than a ratio.
+ *
+ * This codebase implements a design system that has that property, and as a result, we can
+ * guarantee that any shades 5 steps from each other have a contrast ratio of at least 4.5.
+ * 4.5 is the requirement for smaller text contrast in WCAG 2.1 and earlier.
+ *
+ * However, lstar 50 does _not_ have a contrast ratio >= 4.5 with lstar 100.
+ * lstar 49.6 is the smallest lstar that will lead to a contrast ratio >= 4.5 with lstar 100,
+ * and it also contrasts >= 4.5 with lstar 100.
+ */
+ public static final float MIDDLE_LSTAR = 49.6f;
+
+ /**
+ * Generate shades of a color. Ordered in lightness _descending_.
+ * <p>
+ * The first shade will be at 95% lightness, the next at 90, 80, etc. through 0.
+ *
+ * @param hue hue in CAM16 color space
+ * @param chroma chroma in CAM16 color space
+ * @return shades of a color, as argb integers. Ordered by lightness descending.
+ */
+ public static @ColorInt int[] of(float hue, float chroma) {
+ int[] shades = new int[12];
+ shades[0] = ColorUtils.CAMToColor(hue, chroma, 99);
+ shades[1] = ColorUtils.CAMToColor(hue, chroma, 95);
+ for (int i = 2; i < 12; i++) {
+ float lStar = (i == 6) ? MIDDLE_LSTAR : 100 - 10 * (i - 1);
+ shades[i] = ColorUtils.CAMToColor(hue, chroma, lStar);
+ }
+ return shades;
+ }
+}
diff --git a/packages/SystemUI/res/values/flags.xml b/packages/SystemUI/res/values/flags.xml
index c2b87a5..d442cc5 100644
--- a/packages/SystemUI/res/values/flags.xml
+++ b/packages/SystemUI/res/values/flags.xml
@@ -22,7 +22,7 @@
<bool name="flag_notification_pipeline2_rendering">false</bool>
<bool name="flag_notif_updates">true</bool>
- <bool name="flag_monet">false</bool>
+ <bool name="flag_monet">true</bool>
<!-- AOD/Lockscreen alternate layout -->
<bool name="flag_keyguard_layout">true</bool>
diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
index 0130cb2..a288d999 100644
--- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
+++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java
@@ -37,6 +37,7 @@
import android.content.om.FabricatedOverlay;
import android.content.om.OverlayIdentifier;
import android.content.pm.UserInfo;
+import android.content.res.Configuration;
import android.database.ContentObserver;
import android.graphics.Color;
import android.net.Uri;
@@ -47,9 +48,11 @@
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.TypedValue;
import androidx.annotation.NonNull;
+import com.android.internal.graphics.ColorUtils;
import com.android.systemui.Dumpable;
import com.android.systemui.SystemUI;
import com.android.systemui.broadcast.BroadcastDispatcher;
@@ -59,6 +62,7 @@
import com.android.systemui.dump.DumpManager;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.monet.ColorScheme;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
@@ -71,6 +75,7 @@
import java.io.PrintWriter;
import java.util.Collection;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
@@ -107,6 +112,7 @@
private DeviceProvisionedController mDeviceProvisionedController;
private WallpaperColors mCurrentColors;
private WallpaperManager mWallpaperManager;
+ private ColorScheme mColorScheme;
// If fabricated overlays were already created for the current theme.
private boolean mNeedsOverlayCreation;
// Dominant color extracted from wallpaper, NOT the color used on the overlay
@@ -403,25 +409,47 @@
* Return the main theme color from a given {@link WallpaperColors} instance.
*/
protected int getNeutralColor(@NonNull WallpaperColors wallpaperColors) {
- return wallpaperColors.getPrimaryColor().toArgb();
+ return ColorScheme.getSeedColor(wallpaperColors);
}
protected int getAccentColor(@NonNull WallpaperColors wallpaperColors) {
- Color accentCandidate = wallpaperColors.getSecondaryColor();
- if (accentCandidate == null) {
- accentCandidate = wallpaperColors.getTertiaryColor();
- }
- if (accentCandidate == null) {
- accentCandidate = wallpaperColors.getPrimaryColor();
- }
- return accentCandidate.toArgb();
+ return ColorScheme.getSeedColor(wallpaperColors);
}
/**
* Given a color candidate, return an overlay definition.
*/
protected @Nullable FabricatedOverlay getOverlay(int color, int type) {
- return null;
+ boolean nightMode = (mContext.getResources().getConfiguration().uiMode
+ & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;
+
+ mColorScheme = new ColorScheme(color, nightMode);
+ List<Integer> colorShades = type == ACCENT
+ ? mColorScheme.getAllAccentColors() : mColorScheme.getAllNeutralColors();
+ String name = type == ACCENT ? "accent" : "neutral";
+ int paletteSize = mColorScheme.getAccent1().size();
+ FabricatedOverlay.Builder overlay =
+ new FabricatedOverlay.Builder("com.android.systemui", name, "android");
+ for (int i = 0; i < colorShades.size(); i++) {
+ int luminosity = i % paletteSize;
+ int paletteIndex = i / paletteSize + 1;
+ String resourceName;
+ switch (luminosity) {
+ case 0:
+ resourceName = "android:color/system_" + name + paletteIndex + "_10";
+ break;
+ case 1:
+ resourceName = "android:color/system_" + name + paletteIndex + "_50";
+ break;
+ default:
+ int l = luminosity - 1;
+ resourceName = "android:color/system_" + name + paletteIndex + "_" + l + "00";
+ }
+ overlay.setResourceValue(resourceName, TypedValue.TYPE_INT_COLOR_ARGB8,
+ ColorUtils.setAlphaComponent(colorShades.get(i), 0xFF));
+ }
+
+ return overlay.build();
}
private void updateThemeOverlays() {
@@ -521,7 +549,7 @@
.map(key -> key + " -> " + categoryToPackage.get(key)).collect(
Collectors.joining(", ")));
}
- Runnable overlaysAppliedRunnable = () -> onOverlaysApplied();
+ Runnable overlaysAppliedRunnable = this::onOverlaysApplied;
if (mNeedsOverlayCreation) {
mNeedsOverlayCreation = false;
mThemeManager.applyCurrentUserOverlays(categoryToPackage, new FabricatedOverlay[] {
@@ -544,6 +572,7 @@
pw.println("mSecondaryOverlay=" + mSecondaryOverlay);
pw.println("mNeutralOverlay=" + mNeutralOverlay);
pw.println("mIsMonetEnabled=" + mIsMonetEnabled);
+ pw.println("mColorScheme=" + mColorScheme);
pw.println("mNeedsOverlayCreation=" + mNeedsOverlayCreation);
pw.println("mAcceptColorEvents=" + mAcceptColorEvents);
pw.println("mDeferredThemeEvaluation=" + mDeferredThemeEvaluation);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
new file mode 100644
index 0000000..bc86ef9
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/monet/ColorSchemeTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2021 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.android.systemui.monet;
+
+import android.app.WallpaperColors;
+import android.graphics.Color;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.List;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+public class ColorSchemeTest extends SysuiTestCase {
+ @Test
+ public void testFilterTransparency() {
+ ColorScheme colorScheme = new ColorScheme(Color.TRANSPARENT, false /* darkTheme */);
+ Assert.assertEquals(colorScheme.getAllAccentColors(),
+ new ColorScheme(0xFF1b6ef3, false).getAllAccentColors());
+ }
+
+ @Test
+ public void testDontFilterOpaque() {
+ ColorScheme colorScheme = new ColorScheme(0xFFFF0000, false /* darkTheme */);
+ Assert.assertNotEquals(colorScheme.getAllAccentColors(),
+ new ColorScheme(0xFF1b6ef3, false).getAllAccentColors());
+ }
+
+ @Test
+ public void testUniqueColors() {
+ WallpaperColors wallpaperColors = new WallpaperColors(Color.valueOf(0xffaec00a),
+ Color.valueOf(0xffaec00a), Color.valueOf(0xffaec00a));
+
+ List<Integer> rankedSeedColors = ColorScheme.getSeedColors(wallpaperColors);
+ Assert.assertEquals(rankedSeedColors, List.of(0xffaec00a));
+ }
+
+
+ @Test
+ public void testFiltersInvalidColors() {
+ WallpaperColors wallpaperColors = new WallpaperColors(Color.valueOf(0xff5e7ea2),
+ Color.valueOf(0xff5e7ea2), Color.valueOf(0xff000000));
+
+ List<Integer> rankedSeedColors = ColorScheme.getSeedColors(wallpaperColors);
+ Assert.assertEquals(rankedSeedColors, List.of(0xff5e7ea2));
+ }
+
+ @Test
+ public void testInvalidColorBecomesGBlue() {
+ WallpaperColors wallpaperColors = new WallpaperColors(Color.valueOf(0xff000000), null,
+ null);
+
+ List<Integer> rankedSeedColors = ColorScheme.getSeedColors(wallpaperColors);
+ Assert.assertEquals(rankedSeedColors, List.of(0xFF1b6ef3));
+ }
+
+ @Test
+ public void testDontFilterRRGGBB() {
+ ColorScheme colorScheme = new ColorScheme(0xFF0000, false /* darkTheme */);
+ Assert.assertEquals(colorScheme.getAllAccentColors(),
+ new ColorScheme(0xFFFF0000, false).getAllAccentColors());
+ }
+
+ @Test
+ public void testNoPopulationSignal() {
+ WallpaperColors wallpaperColors = new WallpaperColors(Color.valueOf(0xffaec00a),
+ Color.valueOf(0xffbe0000), Color.valueOf(0xffcc040f));
+
+ List<Integer> rankedSeedColors = ColorScheme.getSeedColors(wallpaperColors);
+ Assert.assertEquals(rankedSeedColors, List.of(0xffaec00a, 0xffbe0000, 0xffcc040f));
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
index cd911cc..4c282bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/theme/ThemeOverlayControllerTest.java
@@ -167,7 +167,7 @@
assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_SYSTEM_PALETTE))
.isEqualTo(new OverlayIdentifier("ffff0000"));
assertThat(themeOverlays.getValue().get(OVERLAY_CATEGORY_ACCENT_COLOR))
- .isEqualTo(new OverlayIdentifier("ff0000ff"));
+ .isEqualTo(new OverlayIdentifier("ffff0000"));
// Should not ask again if changed to same value
mColorsListener.getValue().onColorsChanged(mainColors, WallpaperManager.FLAG_SYSTEM);