Merge "Add monet to AOSP" into sc-v2-dev
This commit is contained in:
@@ -74,6 +74,11 @@ final class DisabledWallpaperManager extends WallpaperManager {
|
||||
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 @@ final class DisabledWallpaperManager extends WallpaperManager {
|
||||
|
||||
@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 @@ final class DisabledWallpaperManager extends WallpaperManager {
|
||||
|
||||
@Override
|
||||
public int setResource(int resid, int which) throws IOException {
|
||||
return unsupported();
|
||||
unsupported();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -220,19 +226,22 @@ final class DisabledWallpaperManager extends WallpaperManager {
|
||||
@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 @@ final class DisabledWallpaperManager extends WallpaperManager {
|
||||
@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 @@ final class DisabledWallpaperManager extends WallpaperManager {
|
||||
|
||||
@Override
|
||||
public int getDesiredMinimumWidth() {
|
||||
return unsupported();
|
||||
return unsupportedInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getDesiredMinimumHeight() {
|
||||
return unsupported();
|
||||
return unsupportedInt();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -92,6 +92,7 @@ android_library {
|
||||
"iconloader_base",
|
||||
"SystemUI-tags",
|
||||
"SystemUI-proto",
|
||||
"monet",
|
||||
"dagger2",
|
||||
"jsr330",
|
||||
"lottie",
|
||||
@@ -179,6 +180,7 @@ android_library {
|
||||
"mockito-target-extended-minus-junit4",
|
||||
"testables",
|
||||
"truth-prebuilt",
|
||||
"monet",
|
||||
"dagger2",
|
||||
"jsr330",
|
||||
"WindowManager-Shell",
|
||||
|
||||
31
packages/SystemUI/monet/Android.bp
Normal file
31
packages/SystemUI/monet/Android.bp
Normal file
@@ -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",
|
||||
],
|
||||
}
|
||||
20
packages/SystemUI/monet/AndroidManifest.xml
Normal file
20
packages/SystemUI/monet/AndroidManifest.xml
Normal file
@@ -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>
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -37,6 +37,7 @@ import android.content.IntentFilter;
|
||||
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.provider.Settings;
|
||||
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.dagger.qualifiers.Main;
|
||||
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.FileDescriptor;
|
||||
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 @@ public class ThemeOverlayController extends SystemUI implements Dumpable {
|
||||
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 @@ public class ThemeOverlayController extends SystemUI implements Dumpable {
|
||||
* 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 @@ public class ThemeOverlayController extends SystemUI implements Dumpable {
|
||||
.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 @@ public class ThemeOverlayController extends SystemUI implements Dumpable {
|
||||
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);
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -167,7 +167,7 @@ public class ThemeOverlayControllerTest extends SysuiTestCase {
|
||||
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);
|
||||
|
||||
Reference in New Issue
Block a user