Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dbb5cf77 authored by Marcelo Arteiro's avatar Marcelo Arteiro
Browse files

Base color API updates

Including new tokens for shades base color and ColorScheme updates

Test: atest ColorSchemeTest
Test: atest ThemeOverlayControllerTest
Test: atest SystemPaletteTest
Bug: 241778903
Change-Id: I45a398245ae45adbfe58d32e11a4d18097e3eca1
parent 8e315bb1
Loading
Loading
Loading
Loading
+80 −38
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ internal class HueSubtract(val amountDegrees: Double) : Hue {
internal class HueVibrantSecondary() : Hue {
    val hueToRotations = listOf(Pair(0, 18), Pair(41, 15), Pair(61, 10), Pair(101, 12),
            Pair(131, 15), Pair(181, 18), Pair(251, 15), Pair(301, 12), Pair(360, 12))

    override fun get(sourceColor: Cam): Double {
        return getHueRotation(sourceColor.hue, hueToRotations)
    }
@@ -88,6 +89,7 @@ internal class HueVibrantSecondary() : Hue {
internal class HueVibrantTertiary() : Hue {
    val hueToRotations = listOf(Pair(0, 35), Pair(41, 30), Pair(61, 20), Pair(101, 25),
            Pair(131, 30), Pair(181, 35), Pair(251, 30), Pair(301, 25), Pair(360, 25))

    override fun get(sourceColor: Cam): Double {
        return getHueRotation(sourceColor.hue, hueToRotations)
    }
@@ -96,6 +98,7 @@ internal class HueVibrantTertiary() : Hue {
internal class HueExpressiveSecondary() : Hue {
    val hueToRotations = listOf(Pair(0, 45), Pair(21, 95), Pair(51, 45), Pair(121, 20),
            Pair(151, 45), Pair(191, 90), Pair(271, 45), Pair(321, 45), Pair(360, 45))

    override fun get(sourceColor: Cam): Double {
        return getHueRotation(sourceColor.hue, hueToRotations)
    }
@@ -104,6 +107,7 @@ internal class HueExpressiveSecondary() : Hue {
internal class HueExpressiveTertiary() : Hue {
    val hueToRotations = listOf(Pair(0, 120), Pair(21, 120), Pair(51, 20), Pair(121, 45),
            Pair(151, 20), Pair(191, 15), Pair(271, 20), Pair(321, 120), Pair(360, 120))

    override fun get(sourceColor: Cam): Double {
        return getHueRotation(sourceColor.hue, hueToRotations)
    }
@@ -214,17 +218,47 @@ enum class Style(internal val coreSpec: CoreSpec) {
    )),
}

class TonalPalette {
    val shadeKeys = listOf(10, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000)
    val allShades: List<Int>
    val allShadesMapped: Map<Int, Int>
    val baseColor: Int

    internal constructor(spec: TonalSpec, seedColor: Int) {
        val seedCam = Cam.fromInt(seedColor)
        allShades = spec.shades(seedCam)
        allShadesMapped = shadeKeys.zip(allShades).toMap()

        val h = spec.hue.get(seedCam).toFloat()
        val c = spec.chroma.get(seedCam).toFloat()
        baseColor = ColorUtils.CAMToColor(h, c, CamUtils.lstarFromInt(seedColor))
    }

    val s10: Int get() = this.allShades[0]
    val s50: Int get() = this.allShades[1]
    val s100: Int get() = this.allShades[2]
    val s200: Int get() = this.allShades[3]
    val s300: Int get() = this.allShades[4]
    val s400: Int get() = this.allShades[5]
    val s500: Int get() = this.allShades[6]
    val s600: Int get() = this.allShades[7]
    val s700: Int get() = this.allShades[8]
    val s800: Int get() = this.allShades[9]
    val s900: Int get() = this.allShades[10]
    val s1000: Int get() = this.allShades[11]
}

class ColorScheme(
        @ColorInt val seed: Int,
        val darkTheme: Boolean,
        val style: Style = Style.TONAL_SPOT
) {

    val accent1: List<Int>
    val accent2: List<Int>
    val accent3: List<Int>
    val neutral1: List<Int>
    val neutral2: List<Int>
    val accent1: TonalPalette
    val accent2: TonalPalette
    val accent3: TonalPalette
    val neutral1: TonalPalette
    val neutral2: TonalPalette

    constructor(@ColorInt seed: Int, darkTheme: Boolean) :
            this(seed, darkTheme, Style.TONAL_SPOT)
@@ -237,28 +271,33 @@ class ColorScheme(
    ) :
            this(getSeedColor(wallpaperColors, style != Style.CONTENT), darkTheme, style)

    val allHues: List<TonalPalette>
        get() {
            return listOf(accent1, accent2, accent3, neutral1, neutral2)
        }

    val allAccentColors: List<Int>
        get() {
            val allColors = mutableListOf<Int>()
            allColors.addAll(accent1)
            allColors.addAll(accent2)
            allColors.addAll(accent3)
            allColors.addAll(accent1.allShades)
            allColors.addAll(accent2.allShades)
            allColors.addAll(accent3.allShades)
            return allColors
        }

    val allNeutralColors: List<Int>
        get() {
            val allColors = mutableListOf<Int>()
            allColors.addAll(neutral1)
            allColors.addAll(neutral2)
            allColors.addAll(neutral1.allShades)
            allColors.addAll(neutral2.allShades)
            return allColors
        }

    val backgroundColor
        get() = ColorUtils.setAlphaComponent(if (darkTheme) neutral1[8] else neutral1[0], 0xFF)
        get() = ColorUtils.setAlphaComponent(if (darkTheme) neutral1.s700 else neutral1.s10, 0xFF)

    val accentColor
        get() = ColorUtils.setAlphaComponent(if (darkTheme) accent1[2] else accent1[6], 0xFF)
        get() = ColorUtils.setAlphaComponent(if (darkTheme) accent1.s100 else accent1.s500, 0xFF)

    init {
        val proposedSeedCam = Cam.fromInt(seed)
@@ -269,24 +308,26 @@ class ColorScheme(
        } else {
            seed
        }
        val camSeed = Cam.fromInt(seedArgb)
        accent1 = style.coreSpec.a1.shades(camSeed)
        accent2 = style.coreSpec.a2.shades(camSeed)
        accent3 = style.coreSpec.a3.shades(camSeed)
        neutral1 = style.coreSpec.n1.shades(camSeed)
        neutral2 = style.coreSpec.n2.shades(camSeed)

        accent1 = TonalPalette(style.coreSpec.a1, seedArgb)
        accent2 = TonalPalette(style.coreSpec.a2, seedArgb)
        accent3 = TonalPalette(style.coreSpec.a3, seedArgb)
        neutral1 = TonalPalette(style.coreSpec.n1, seedArgb)
        neutral2 = TonalPalette(style.coreSpec.n2, seedArgb)
    }

    val shadeCount get() = this.accent1.allShades.size

    override fun toString(): String {
        return "ColorScheme {\n" +
                "  seed color: ${stringForColor(seed)}\n" +
                "  style: $style\n" +
                "  palettes: \n" +
                "  ${humanReadable("PRIMARY", accent1)}\n" +
                "  ${humanReadable("SECONDARY", accent2)}\n" +
                "  ${humanReadable("TERTIARY", accent3)}\n" +
                "  ${humanReadable("NEUTRAL", neutral1)}\n" +
                "  ${humanReadable("NEUTRAL VARIANT", neutral2)}\n" +
                "  ${humanReadable("PRIMARY", accent1.allShades)}\n" +
                "  ${humanReadable("SECONDARY", accent2.allShades)}\n" +
                "  ${humanReadable("TERTIARY", accent3.allShades)}\n" +
                "  ${humanReadable("NEUTRAL", neutral1.allShades)}\n" +
                "  ${humanReadable("NEUTRAL VARIANT", neutral2.allShades)}\n" +
                "}"
    }

@@ -385,7 +426,8 @@ class ColorScheme(
                    val existingSeedNearby = seeds.find {
                        val hueA = intToCam[int]!!.hue
                        val hueB = intToCam[it]!!.hue
                        hueDiff(hueA, hueB) < i } != null
                        hueDiff(hueA, hueB) < i
                    } != null
                    if (existingSeedNearby) {
                        continue
                    }
+2 −2
Original line number Diff line number Diff line
@@ -162,8 +162,8 @@ internal constructor(
                    context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK ==
                        UI_MODE_NIGHT_YES
                )
                    colorScheme.accent1[2]
                else colorScheme.accent1[3]
                    colorScheme.accent1.s100
                else colorScheme.accent1.s200
            },
            { seamlessColor: Int ->
                val accentColorList = ColorStateList.valueOf(seamlessColor)
+9 −9
Original line number Diff line number Diff line
@@ -19,28 +19,28 @@ package com.android.systemui.media.controls.ui
import com.android.systemui.monet.ColorScheme

/** Returns the surface color for media controls based on the scheme. */
internal fun surfaceFromScheme(scheme: ColorScheme) = scheme.accent2[9] // A2-800
internal fun surfaceFromScheme(scheme: ColorScheme) = scheme.accent2.s800 // A2-800

/** Returns the primary accent color for media controls based on the scheme. */
internal fun accentPrimaryFromScheme(scheme: ColorScheme) = scheme.accent1[2] // A1-100
internal fun accentPrimaryFromScheme(scheme: ColorScheme) = scheme.accent1.s100 // A1-100

/** Returns the secondary accent color for media controls based on the scheme. */
internal fun accentSecondaryFromScheme(scheme: ColorScheme) = scheme.accent1[3] // A1-200
internal fun accentSecondaryFromScheme(scheme: ColorScheme) = scheme.accent1.s200 // A1-200

/** Returns the primary text color for media controls based on the scheme. */
internal fun textPrimaryFromScheme(scheme: ColorScheme) = scheme.neutral1[1] // N1-50
internal fun textPrimaryFromScheme(scheme: ColorScheme) = scheme.neutral1.s50 // N1-50

/** Returns the inverse of the primary text color for media controls based on the scheme. */
internal fun textPrimaryInverseFromScheme(scheme: ColorScheme) = scheme.neutral1[10] // N1-900
internal fun textPrimaryInverseFromScheme(scheme: ColorScheme) = scheme.neutral1.s900 // N1-900

/** Returns the secondary text color for media controls based on the scheme. */
internal fun textSecondaryFromScheme(scheme: ColorScheme) = scheme.neutral2[3] // N2-200
internal fun textSecondaryFromScheme(scheme: ColorScheme) = scheme.neutral2.s200 // N2-200

/** Returns the tertiary text color for media controls based on the scheme. */
internal fun textTertiaryFromScheme(scheme: ColorScheme) = scheme.neutral2[5] // N2-400
internal fun textTertiaryFromScheme(scheme: ColorScheme) = scheme.neutral2.s400 // N2-400

/** Returns the color for the start of the background gradient based on the scheme. */
internal fun backgroundStartFromScheme(scheme: ColorScheme) = scheme.accent2[8] // A2-700
internal fun backgroundStartFromScheme(scheme: ColorScheme) = scheme.accent2.s700 // A2-700

/** Returns the color for the end of the background gradient based on the scheme. */
internal fun backgroundEndFromScheme(scheme: ColorScheme) = scheme.accent1[8] // A1-700
internal fun backgroundEndFromScheme(scheme: ColorScheme) = scheme.accent1.s700 // A1-700
+13 −13
Original line number Diff line number Diff line
@@ -489,20 +489,20 @@ public class MediaOutputController implements LocalMediaManager.DeviceCallback,
        ColorScheme mCurrentColorScheme = new ColorScheme(wallpaperColors,
                isDarkTheme);
        if (isDarkTheme) {
            mColorItemContent = mCurrentColorScheme.getAccent1().get(2); // A1-100
            mColorSeekbarProgress = mCurrentColorScheme.getAccent2().get(7); // A2-600
            mColorButtonBackground = mCurrentColorScheme.getAccent1().get(4); // A1-300
            mColorItemBackground = mCurrentColorScheme.getNeutral2().get(9); // N2-800
            mColorConnectedItemBackground = mCurrentColorScheme.getAccent2().get(9); // A2-800
            mColorPositiveButtonText = mCurrentColorScheme.getAccent2().get(9); // A2-800
            mColorDialogBackground = mCurrentColorScheme.getNeutral1().get(10); // N1-900
            mColorItemContent = mCurrentColorScheme.getAccent1().getS100(); // A1-100
            mColorSeekbarProgress = mCurrentColorScheme.getAccent2().getS600(); // A2-600
            mColorButtonBackground = mCurrentColorScheme.getAccent1().getS300(); // A1-300
            mColorItemBackground = mCurrentColorScheme.getNeutral2().getS800(); // N2-800
            mColorConnectedItemBackground = mCurrentColorScheme.getAccent2().getS800(); // A2-800
            mColorPositiveButtonText = mCurrentColorScheme.getAccent2().getS800(); // A2-800
            mColorDialogBackground = mCurrentColorScheme.getNeutral1().getS900(); // N1-900
        } else {
            mColorItemContent = mCurrentColorScheme.getAccent1().get(9); // A1-800
            mColorSeekbarProgress = mCurrentColorScheme.getAccent1().get(4); // A1-300
            mColorButtonBackground = mCurrentColorScheme.getAccent1().get(7); // A1-600
            mColorItemBackground = mCurrentColorScheme.getAccent2().get(1); // A2-50
            mColorConnectedItemBackground = mCurrentColorScheme.getAccent1().get(2); // A1-100
            mColorPositiveButtonText = mCurrentColorScheme.getNeutral1().get(1); // N1-50
            mColorItemContent = mCurrentColorScheme.getAccent1().getS800(); // A1-800
            mColorSeekbarProgress = mCurrentColorScheme.getAccent1().getS300(); // A1-300
            mColorButtonBackground = mCurrentColorScheme.getAccent1().getS600(); // A1-600
            mColorItemBackground = mCurrentColorScheme.getAccent2().getS50(); // A2-50
            mColorConnectedItemBackground = mCurrentColorScheme.getAccent1().getS100(); // A1-100
            mColorPositiveButtonText = mCurrentColorScheme.getNeutral1().getS50(); // N1-50
            mColorDialogBackground = mCurrentColorScheme.getBackgroundColor();
        }
    }
+30 −27
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_COLOR_INDEX
import static com.android.systemui.theme.ThemeOverlayApplier.OVERLAY_COLOR_SOURCE;
import static com.android.systemui.theme.ThemeOverlayApplier.TIMESTAMP_FIELD;

import android.annotation.Nullable;
import android.app.WallpaperColors;
import android.app.WallpaperManager;
import android.app.WallpaperManager.OnColorsChangedListener;
@@ -70,6 +69,7 @@ import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.WakefulnessLifecycle;
import com.android.systemui.monet.ColorScheme;
import com.android.systemui.monet.Style;
import com.android.systemui.monet.TonalPalette;
import com.android.systemui.settings.UserTracker;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
@@ -513,39 +513,42 @@ public class ThemeOverlayController implements CoreStartable, Dumpable {
    /**
     * Given a color candidate, return an overlay definition.
     */
    protected @Nullable FabricatedOverlay getOverlay(int color, int type, Style style) {
    protected FabricatedOverlay getOverlay(int color, int type, Style style) {
        boolean nightMode = (mResources.getConfiguration().uiMode
                & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES;

        mColorScheme = new ColorScheme(color, nightMode, style);
        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));

        if (type == ACCENT) {
            assignTonalPaletteToOverlay("accent1", overlay, mColorScheme.getAccent1());
            assignTonalPaletteToOverlay("accent2", overlay, mColorScheme.getAccent2());
            assignTonalPaletteToOverlay("accent3", overlay, mColorScheme.getAccent3());
        } else {
            assignTonalPaletteToOverlay("neutral1", overlay, mColorScheme.getNeutral1());
            assignTonalPaletteToOverlay("neutral2", overlay, mColorScheme.getNeutral2());
        }

        return overlay.build();
    }

    private void assignTonalPaletteToOverlay(String name,
            FabricatedOverlay.Builder overlay, TonalPalette tonalPalette) {

        String resourcePrefix = "android:color/system_" + name;
        int colorDataType = TypedValue.TYPE_INT_COLOR_ARGB8;

        tonalPalette.getAllShadesMapped().forEach((key, value) -> {
            String resourceName = resourcePrefix + "_" + key;
            int colorValue = ColorUtils.setAlphaComponent(value, 0xFF);
            overlay.setResourceValue(resourceName, colorDataType,
                    colorValue);
        });
    }

    /**
     * Checks if the color scheme in mColorScheme matches the current system palettes.
     * @param managedProfiles List of managed profiles for this user.
@@ -557,15 +560,15 @@ public class ThemeOverlayController implements CoreStartable, Dumpable {
            Resources res = userHandle.isSystem()
                    ? mResources : mContext.createContextAsUser(userHandle, 0).getResources();
            if (!(res.getColor(android.R.color.system_accent1_500, mContext.getTheme())
                    == mColorScheme.getAccent1().get(6)
                    == mColorScheme.getAccent1().getS500()
                    && res.getColor(android.R.color.system_accent2_500, mContext.getTheme())
                    == mColorScheme.getAccent2().get(6)
                    == mColorScheme.getAccent2().getS500()
                    && res.getColor(android.R.color.system_accent3_500, mContext.getTheme())
                    == mColorScheme.getAccent3().get(6)
                    == mColorScheme.getAccent3().getS500()
                    && res.getColor(android.R.color.system_neutral1_500, mContext.getTheme())
                    == mColorScheme.getNeutral1().get(6)
                    == mColorScheme.getNeutral1().getS500()
                    && res.getColor(android.R.color.system_neutral2_500, mContext.getTheme())
                    == mColorScheme.getNeutral2().get(6))) {
                    == mColorScheme.getNeutral2().getS500())) {
                return false;
            }
        }
Loading