From 35fff40d1b90817fa7d3fad50ec69dfec0f15e6c Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Fri, 26 May 2023 02:33:00 -0700 Subject: [PATCH 1/2] Fix contrast levels of outline and outline_variant Downstreamed MCU to fix contrast levels of outline and outline_variant. Test: flash, switch themes Test: atest SystemPaletteTest Fixes: 284426073 Bug: 284421298 Change-Id: I68ea14f473b41c053235fc534844f8d07c1b5eb1 --- .../dynamiccolor/MaterialDynamicColors.java | 1008 +++++++++-------- .../android/systemui/theme/DynamicColors.kt | 3 +- .../theme/ThemeOverlayController.java | 11 +- 3 files changed, 538 insertions(+), 484 deletions(-) diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java index 21218a2dc8e22..bc1edee1c10b7 100644 --- a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java +++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java @@ -16,13 +16,15 @@ package com.android.systemui.monet.dynamiccolor; +import android.annotation.NonNull; + import com.android.systemui.monet.dislike.DislikeAnalyzer; import com.android.systemui.monet.hct.Hct; import com.android.systemui.monet.hct.ViewingConditions; import com.android.systemui.monet.scheme.DynamicScheme; import com.android.systemui.monet.scheme.Variant; -/** Named colors, otherwise known as tokens, or roles, in the Material Design system.*/ +/** Named colors, otherwise known as tokens, or roles, in the Material Design system. */ // Prevent lint for Function.apply not being available on Android before API level 14 (4.0.1). // "AndroidJdkLibsChecker" for Function, "NewApi" for Function.apply(). // A java_library Bazel rule with an Android constraint cannot skip these warnings without this @@ -32,54 +34,557 @@ import com.android.systemui.monet.scheme.Variant; public final class MaterialDynamicColors { private static final double CONTAINER_ACCENT_TONE_DELTA = 15.0; + public MaterialDynamicColors() {} - public MaterialDynamicColors() { + // Compatibility Keys Colors for Android + public DynamicColor primaryPaletteKeyColor() { + return DynamicColor.fromPalette( + (s) -> s.primaryPalette, (s) -> s.primaryPalette.getKeyColor().getTone()); + } + + public DynamicColor secondaryPaletteKeyColor() { + return DynamicColor.fromPalette( + (s) -> s.secondaryPalette, (s) -> s.secondaryPalette.getKeyColor().getTone()); + } + + public DynamicColor tertiaryPaletteKeyColor() { + return DynamicColor.fromPalette( + (s) -> s.tertiaryPalette, (s) -> s.tertiaryPalette.getKeyColor().getTone()); + } + + public DynamicColor neutralPaletteKeyColor() { + return DynamicColor.fromPalette( + (s) -> s.neutralPalette, (s) -> s.neutralPalette.getKeyColor().getTone()); + } + + public DynamicColor neutralVariantPaletteKeyColor() { + return DynamicColor.fromPalette( + (s) -> s.neutralVariantPalette, + (s) -> s.neutralVariantPalette.getKeyColor().getTone()); + } + + @NonNull + public DynamicColor highestSurface(@NonNull DynamicScheme s) { + return s.isDark ? surfaceBright() : surfaceDim(); + } + + @NonNull + public DynamicColor background() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 98.0); + } + + @NonNull + public DynamicColor onBackground() { + return DynamicColor.fromPalette( + (s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 10.0, (s) -> background()); + } + + @NonNull + public DynamicColor surface() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 98.0); + } + + @NonNull + public DynamicColor inverseSurface() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 20.0); + } + + @NonNull + public DynamicColor surfaceBright() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 24.0 : 98.0); + } + + @NonNull + public DynamicColor surfaceDim() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 87.0); + } + + @NonNull + public DynamicColor surfaceContainerLowest() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 4.0 : 100.0); + } + + @NonNull + public DynamicColor surfaceContainerLow() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 96.0); + } + + @NonNull + public DynamicColor surfaceContainer() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 12.0 : 94.0); + } + + @NonNull + public DynamicColor surfaceContainerHigh() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 17.0 : 92.0); + } + + @NonNull + public DynamicColor surfaceContainerHighest() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 22.0 : 90.0); + } + + @NonNull + public DynamicColor onSurface() { + return DynamicColor.fromPalette( + (s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 10.0, this::highestSurface); + } + + @NonNull + public DynamicColor inverseOnSurface() { + return DynamicColor.fromPalette( + (s) -> s.neutralPalette, (s) -> s.isDark ? 20.0 : 95.0, (s) -> inverseSurface()); + } + + @NonNull + public DynamicColor surfaceVariant() { + return DynamicColor.fromPalette((s) -> s.neutralVariantPalette, (s) -> s.isDark ? 30.0 : 90.0); + } + + @NonNull + public DynamicColor onSurfaceVariant() { + return DynamicColor.fromPalette( + (s) -> s.neutralVariantPalette, (s) -> s.isDark ? 80.0 : 30.0, (s) -> surfaceVariant()); + } + + @NonNull + public DynamicColor outline() { + return DynamicColor.fromPalette( + (s) -> s.neutralVariantPalette, (s) -> s.isDark ? 60.0 : 50.0, this::highestSurface); + } + + @NonNull + public DynamicColor outlineVariant() { + return DynamicColor.fromPalette( + (s) -> s.neutralVariantPalette, (s) -> s.isDark ? 30.0 : 80.0, this::highestSurface); + } + + @NonNull + public DynamicColor shadow() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> 0.0); + } + + @NonNull + public DynamicColor scrim() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> 0.0); + } + + @NonNull + public DynamicColor surfaceTint() { + return DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> s.isDark ? 80.0 : 40.0); + } + + @NonNull + public DynamicColor primaryContainer() { + return DynamicColor.fromPalette( + (s) -> s.primaryPalette, + (s) -> { + if (isFidelity(s)) { + return performAlbers(s.sourceColorHct, s); + } + if (isMonochrome(s)) { + return s.isDark ? 85.0 : 25.0; + } + return s.isDark ? 30.0 : 90.0; + }, + this::highestSurface); + } + + @NonNull + public DynamicColor onPrimaryContainer() { + return DynamicColor.fromPalette( + (s) -> s.primaryPalette, + (s) -> { + if (isFidelity(s)) { + return DynamicColor.contrastingTone(primaryContainer().tone.apply(s), 4.5); + } + if (isMonochrome(s)) { + return s.isDark ? 0.0 : 100.0; + } + return s.isDark ? 90.0 : 10.0; + }, + (s) -> primaryContainer(), + null); + } + + @NonNull + public DynamicColor primary() { + return DynamicColor.fromPalette( + (s) -> s.primaryPalette, + (s) -> { + if (isMonochrome(s)) { + return s.isDark ? 100.0 : 0.0; + } + return s.isDark ? 80.0 : 40.0; + }, + this::highestSurface, + (s) -> + new ToneDeltaConstraint( + CONTAINER_ACCENT_TONE_DELTA, + primaryContainer(), + s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER)); + } + + @NonNull + public DynamicColor inversePrimary() { + return DynamicColor.fromPalette( + (s) -> s.primaryPalette, (s) -> s.isDark ? 40.0 : 80.0, (s) -> inverseSurface()); + } + + @NonNull + public DynamicColor onPrimary() { + return DynamicColor.fromPalette( + (s) -> s.primaryPalette, + (s) -> { + if (isMonochrome(s)) { + return s.isDark ? 10.0 : 90.0; + } + return s.isDark ? 20.0 : 100.0; + }, + (s) -> primary()); + } + + @NonNull + public DynamicColor secondaryContainer() { + return DynamicColor.fromPalette( + (s) -> s.secondaryPalette, + (s) -> { + if (isMonochrome(s)) { + return s.isDark ? 30.0 : 85.0; + } + final double initialTone = s.isDark ? 30.0 : 90.0; + if (!isFidelity(s)) { + return initialTone; + } + double answer = + findDesiredChromaByTone( + s.secondaryPalette.getHue(), + s.secondaryPalette.getChroma(), + initialTone, + !s.isDark); + answer = performAlbers(s.secondaryPalette.getHct(answer), s); + return answer; + }, + this::highestSurface); + } + + @NonNull + public DynamicColor onSecondaryContainer() { + return DynamicColor.fromPalette( + (s) -> s.secondaryPalette, + (s) -> { + if (!isFidelity(s)) { + return s.isDark ? 90.0 : 10.0; + } + return DynamicColor.contrastingTone(secondaryContainer().tone.apply(s), 4.5); + }, + (s) -> secondaryContainer()); + } + + @NonNull + public DynamicColor secondary() { + return DynamicColor.fromPalette( + (s) -> s.secondaryPalette, + (s) -> s.isDark ? 80.0 : 40.0, + this::highestSurface, + (s) -> + new ToneDeltaConstraint( + CONTAINER_ACCENT_TONE_DELTA, + secondaryContainer(), + s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER)); + } + + @NonNull + public DynamicColor onSecondary() { + return DynamicColor.fromPalette( + (s) -> s.secondaryPalette, + (s) -> { + if (isMonochrome(s)) { + return s.isDark ? 10.0 : 100.0; + } + return s.isDark ? 20.0 : 100.0; + }, + (s) -> secondary()); + } + + @NonNull + public DynamicColor tertiaryContainer() { + return DynamicColor.fromPalette( + (s) -> s.tertiaryPalette, + (s) -> { + if (isMonochrome(s)) { + return s.isDark ? 60.0 : 49.0; + } + if (!isFidelity(s)) { + return s.isDark ? 30.0 : 90.0; + } + final double albersTone = + performAlbers(s.tertiaryPalette.getHct(s.sourceColorHct.getTone()), s); + final Hct proposedHct = s.tertiaryPalette.getHct(albersTone); + return DislikeAnalyzer.fixIfDisliked(proposedHct).getTone(); + }, + this::highestSurface); + } + + @NonNull + public DynamicColor onTertiaryContainer() { + return DynamicColor.fromPalette( + (s) -> s.tertiaryPalette, + (s) -> { + if (isMonochrome(s)) { + return s.isDark ? 0.0 : 100.0; + } + if (!isFidelity(s)) { + return s.isDark ? 90.0 : 10.0; + } + return DynamicColor.contrastingTone(tertiaryContainer().tone.apply(s), 4.5); + }, + (s) -> tertiaryContainer()); + } + + @NonNull + public DynamicColor tertiary() { + return DynamicColor.fromPalette( + (s) -> s.tertiaryPalette, + (s) -> { + if (isMonochrome(s)) { + return s.isDark ? 90.0 : 25.0; + } + return s.isDark ? 80.0 : 40.0; + }, + this::highestSurface, + (s) -> + new ToneDeltaConstraint( + CONTAINER_ACCENT_TONE_DELTA, + tertiaryContainer(), + s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER)); + } + + @NonNull + public DynamicColor onTertiary() { + return DynamicColor.fromPalette( + (s) -> s.tertiaryPalette, + (s) -> { + if (isMonochrome(s)) { + return s.isDark ? 10.0 : 90.0; + } + return s.isDark ? 20.0 : 100.0; + }, + (s) -> tertiary()); + } + + @NonNull + public DynamicColor errorContainer() { + return DynamicColor.fromPalette( + (s) -> s.errorPalette, (s) -> s.isDark ? 30.0 : 90.0, this::highestSurface); + } + + @NonNull + public DynamicColor onErrorContainer() { + return DynamicColor.fromPalette( + (s) -> s.errorPalette, (s) -> s.isDark ? 90.0 : 10.0, (s) -> errorContainer()); + } + + @NonNull + public DynamicColor error() { + return DynamicColor.fromPalette( + (s) -> s.errorPalette, + (s) -> s.isDark ? 80.0 : 40.0, + this::highestSurface, + (s) -> + new ToneDeltaConstraint( + CONTAINER_ACCENT_TONE_DELTA, + errorContainer(), + s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER)); + } + + @NonNull + public DynamicColor onError() { + return DynamicColor.fromPalette( + (s) -> s.errorPalette, (s) -> s.isDark ? 20.0 : 100.0, (s) -> error()); + } + + @NonNull + public DynamicColor primaryFixed() { + return DynamicColor.fromPalette( + (s) -> s.primaryPalette, + (s) -> { + if (isMonochrome(s)) { + return s.isDark ? 100.0 : 10.0; + } + return 90.0; + }, + this::highestSurface); + } + + @NonNull + public DynamicColor primaryFixedDim() { + return DynamicColor.fromPalette( + (s) -> s.primaryPalette, + (s) -> { + if (isMonochrome(s)) { + return s.isDark ? 90.0 : 20.0; + } + return 80.0; + }, + this::highestSurface); + } + + @NonNull + public DynamicColor onPrimaryFixed() { + return DynamicColor.fromPalette( + (s) -> s.primaryPalette, + (s) -> { + if (isMonochrome(s)) { + return s.isDark ? 10.0 : 90.0; + } + return 10.0; + }, + (s) -> primaryFixedDim()); + } + + @NonNull + public DynamicColor onPrimaryFixedVariant() { + return DynamicColor.fromPalette( + (s) -> s.primaryPalette, + (s) -> { + if (isMonochrome(s)) { + return s.isDark ? 30.0 : 70.0; + } + return 30.0; + }, + (s) -> primaryFixedDim()); + } + + @NonNull + public DynamicColor secondaryFixed() { + return DynamicColor.fromPalette( + (s) -> s.secondaryPalette, (s) -> isMonochrome(s) ? 80.0 : 90.0, this::highestSurface); + } + + @NonNull + public DynamicColor secondaryFixedDim() { + return DynamicColor.fromPalette( + (s) -> s.secondaryPalette, (s) -> isMonochrome(s) ? 70.0 : 80.0, this::highestSurface); + } + + @NonNull + public DynamicColor onSecondaryFixed() { + return DynamicColor.fromPalette( + (s) -> s.secondaryPalette, (s) -> 10.0, (s) -> secondaryFixedDim()); + } + + @NonNull + public DynamicColor onSecondaryFixedVariant() { + return DynamicColor.fromPalette( + (s) -> s.secondaryPalette, + (s) -> isMonochrome(s) ? 25.0 : 30.0, + (s) -> secondaryFixedDim()); + } + + @NonNull + public DynamicColor tertiaryFixed() { + return DynamicColor.fromPalette( + (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 40.0 : 90.0, this::highestSurface); + } + + @NonNull + public DynamicColor tertiaryFixedDim() { + return DynamicColor.fromPalette( + (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 30.0 : 80.0, this::highestSurface); + } + + @NonNull + public DynamicColor onTertiaryFixed() { + return DynamicColor.fromPalette( + (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 90.0 : 10.0, (s) -> tertiaryFixedDim()); + } + + @NonNull + public DynamicColor onTertiaryFixedVariant() { + return DynamicColor.fromPalette( + (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 70.0 : 30.0, (s) -> tertiaryFixedDim()); } /** - * These colors were present in Android framework before Android U, and used by MDC controls. - * They + * These colors were present in Android framework before Android U, and used by MDC controls. They * should be avoided, if possible. It's unclear if they're used on multiple backgrounds, and if * they are, they can't be adjusted for contrast.* For now, they will be set with no background, * and those won't adjust for contrast, avoiding issues. * - *

* For example, if the same color is on a white background _and_ black background, - * there's no + *

* For example, if the same color is on a white background _and_ black background, there's no * way to increase contrast with either without losing contrast with the other. */ // colorControlActivated documented as colorAccent in M3 & GM3. // colorAccent documented as colorSecondary in M3 and colorPrimary in GM3. // Android used Material's Container as Primary/Secondary/Tertiary at launch. // Therefore, this is a duplicated version of Primary Container. - public static DynamicColor controlActivated() { + @NonNull + public DynamicColor controlActivated() { return DynamicColor.fromPalette((s) -> s.primaryPalette, (s) -> s.isDark ? 30.0 : 90.0, null); } - // Compatibility Keys Colors for Android - public static DynamicColor primaryPaletteKeyColor() { - return DynamicColor.fromPalette( - (s) -> s.primaryPalette, (s) -> s.primaryPalette.getKeyColor().getTone()); + // colorControlNormal documented as textColorSecondary in M3 & GM3. + // In Material, textColorSecondary points to onSurfaceVariant in the non-disabled state, + // which is Neutral Variant T30/80 in light/dark. + @NonNull + public DynamicColor controlNormal() { + return DynamicColor.fromPalette((s) -> s.neutralVariantPalette, (s) -> s.isDark ? 80.0 : 30.0); } - public static DynamicColor secondaryPaletteKeyColor() { - return DynamicColor.fromPalette( - (s) -> s.secondaryPalette, (s) -> s.secondaryPalette.getKeyColor().getTone()); + // colorControlHighlight documented, in both M3 & GM3: + // Light mode: #1f000000 dark mode: #33ffffff. + // These are black and white with some alpha. + // 1F hex = 31 decimal; 31 / 255 = 12% alpha. + // 33 hex = 51 decimal; 51 / 255 = 20% alpha. + // DynamicColors do not support alpha currently, and _may_ not need it for this use case, + // depending on how MDC resolved alpha for the other cases. + // Returning black in dark mode, white in light mode. + @NonNull + public DynamicColor controlHighlight() { + return new DynamicColor( + s -> 0.0, + s -> 0.0, + s -> s.isDark ? 100.0 : 0.0, + s -> s.isDark ? 0.20 : 0.12, + null, + scheme -> + DynamicColor.toneMinContrastDefault((s) -> s.isDark ? 100.0 : 0.0, null, scheme, null), + scheme -> + DynamicColor.toneMaxContrastDefault((s) -> s.isDark ? 100.0 : 0.0, null, scheme, null), + null); } - public static DynamicColor tertiaryPaletteKeyColor() { - return DynamicColor.fromPalette( - (s) -> s.tertiaryPalette, (s) -> s.tertiaryPalette.getKeyColor().getTone()); + // textColorPrimaryInverse documented, in both M3 & GM3, documented as N10/N90. + @NonNull + public DynamicColor textPrimaryInverse() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0); } - public static DynamicColor neutralPaletteKeyColor() { - return DynamicColor.fromPalette( - (s) -> s.neutralPalette, (s) -> s.neutralPalette.getKeyColor().getTone()); + // textColorSecondaryInverse and textColorTertiaryInverse both documented, in both M3 & GM3, as + // NV30/NV80 + @NonNull + public DynamicColor textSecondaryAndTertiaryInverse() { + return DynamicColor.fromPalette((s) -> s.neutralVariantPalette, (s) -> s.isDark ? 30.0 : 80.0); } - public static DynamicColor neutralVariantPaletteKeyColor() { - return DynamicColor.fromPalette( - (s) -> s.neutralVariantPalette, - (s) -> s.neutralVariantPalette.getKeyColor().getTone()); + // textColorPrimaryInverseDisableOnly documented, in both M3 & GM3, as N10/N90 + @NonNull + public DynamicColor textPrimaryInverseDisableOnly() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0); + } + + // textColorSecondaryInverse and textColorTertiaryInverse in disabled state both documented, + // in both M3 & GM3, as N10/N90 + @NonNull + public DynamicColor textSecondaryAndTertiaryInverseDisabled() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0); + } + + // textColorHintInverse documented, in both M3 & GM3, as N10/N90 + @NonNull + public DynamicColor textHintInverse() { + return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0); } private static ViewingConditions viewingConditionsForAlbers(DynamicScheme scheme) { @@ -132,457 +637,4 @@ public final class MaterialDynamicColors { return DynamicColor.enableLightForeground(albersd.getTone()); } } - - public static DynamicColor highestSurface(DynamicScheme s) { - return s.isDark ? surfaceBright() : surfaceDim(); - } - - public static DynamicColor background() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 98.0); - } - - public static DynamicColor onBackground() { - return DynamicColor.fromPalette( - (s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 10.0, (s) -> background()); - } - - public static DynamicColor surface() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 98.0); - } - - public static DynamicColor inverseSurface() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 20.0); - } - - public static DynamicColor surfaceBright() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 24.0 : 98.0); - } - - public static DynamicColor surfaceDim() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 6.0 : 87.0); - } - - public static DynamicColor surfaceContainerLowest() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 4.0 : 100.0); - } - - public static DynamicColor surfaceContainerLow() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 96.0); - } - - public static DynamicColor surfaceContainer() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 12.0 : 94.0); - } - - public static DynamicColor surfaceContainerHigh() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 17.0 : 92.0); - } - - public static DynamicColor surfaceContainerHighest() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 22.0 : 90.0); - } - - public static DynamicColor onSurface() { - return DynamicColor.fromPalette( - (s) -> s.neutralPalette, (s) -> s.isDark ? 90.0 : 10.0, - MaterialDynamicColors::highestSurface); - } - - public static DynamicColor inverseOnSurface() { - return DynamicColor.fromPalette( - (s) -> s.neutralPalette, (s) -> s.isDark ? 20.0 : 95.0, (s) -> inverseSurface()); - } - - public static DynamicColor surfaceVariant() { - return DynamicColor.fromPalette((s) -> s.neutralVariantPalette, - (s) -> s.isDark ? 30.0 : 90.0); - } - - public static DynamicColor onSurfaceVariant() { - return DynamicColor.fromPalette( - (s) -> s.neutralVariantPalette, (s) -> s.isDark ? 80.0 : 30.0, - (s) -> surfaceVariant()); - } - - public static DynamicColor outline() { - return DynamicColor.fromPalette( - (s) -> s.neutralVariantPalette, (s) -> 50.0, MaterialDynamicColors::highestSurface); - } - - public static DynamicColor outlineVariant() { - return DynamicColor.fromPalette( - (s) -> s.neutralVariantPalette, (s) -> s.isDark ? 30.0 : 80.0, - MaterialDynamicColors::highestSurface); - } - - public static DynamicColor primaryContainer() { - return DynamicColor.fromPalette( - (s) -> s.primaryPalette, - (s) -> { - if (isFidelity(s)) { - return performAlbers(s.sourceColorHct, s); - } - if (isMonochrome(s)) { - return s.isDark ? 85.0 : 25.0; - } - return s.isDark ? 30.0 : 90.0; - }, - MaterialDynamicColors::highestSurface); - } - - public static DynamicColor onPrimaryContainer() { - return DynamicColor.fromPalette( - (s) -> s.primaryPalette, - (s) -> { - if (isFidelity(s)) { - return DynamicColor.contrastingTone(primaryContainer().tone.apply(s), 4.5); - } - if (isMonochrome(s)) { - return s.isDark ? 0.0 : 100.0; - } - return s.isDark ? 90.0 : 10.0; - }, - (s) -> primaryContainer(), - null); - } - - public static DynamicColor primary() { - return DynamicColor.fromPalette( - (s) -> s.primaryPalette, - (s) -> { - if (isMonochrome(s)) { - return s.isDark ? 100.0 : 0.0; - } - return s.isDark ? 80.0 : 40.0; - }, - MaterialDynamicColors::highestSurface, - (s) -> - new ToneDeltaConstraint( - CONTAINER_ACCENT_TONE_DELTA, - primaryContainer(), - s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER)); - } - - public static DynamicColor inversePrimary() { - return DynamicColor.fromPalette( - (s) -> s.primaryPalette, (s) -> s.isDark ? 40.0 : 80.0, (s) -> inverseSurface()); - } - - public static DynamicColor onPrimary() { - return DynamicColor.fromPalette( - (s) -> s.primaryPalette, - (s) -> { - if (isMonochrome(s)) { - return s.isDark ? 10.0 : 90.0; - } - return s.isDark ? 20.0 : 100.0; - }, - (s) -> primary()); - } - - public static DynamicColor secondaryContainer() { - return DynamicColor.fromPalette( - (s) -> s.secondaryPalette, - (s) -> { - if (isMonochrome(s)) { - return s.isDark ? 30.0 : 85.0; - } - final double initialTone = s.isDark ? 30.0 : 90.0; - if (!isFidelity(s)) { - return initialTone; - } - double answer = - findDesiredChromaByTone( - s.secondaryPalette.getHue(), - s.secondaryPalette.getChroma(), - initialTone, - !s.isDark); - answer = performAlbers(s.secondaryPalette.getHct(answer), s); - return answer; - }, - MaterialDynamicColors::highestSurface); - } - - public static DynamicColor onSecondaryContainer() { - return DynamicColor.fromPalette( - (s) -> s.secondaryPalette, - (s) -> { - if (!isFidelity(s)) { - return s.isDark ? 90.0 : 10.0; - } - return DynamicColor.contrastingTone(secondaryContainer().tone.apply(s), 4.5); - }, - (s) -> secondaryContainer()); - } - - public static DynamicColor secondary() { - return DynamicColor.fromPalette( - (s) -> s.secondaryPalette, - (s) -> s.isDark ? 80.0 : 40.0, - MaterialDynamicColors::highestSurface, - (s) -> - new ToneDeltaConstraint( - CONTAINER_ACCENT_TONE_DELTA, - secondaryContainer(), - s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER)); - } - - public static DynamicColor onSecondary() { - return DynamicColor.fromPalette( - (s) -> s.secondaryPalette, - (s) -> { - if (isMonochrome(s)) { - return s.isDark ? 10.0 : 100.0; - } - return s.isDark ? 20.0 : 100.0; - }, - (s) -> secondary()); - } - - public static DynamicColor tertiaryContainer() { - return DynamicColor.fromPalette( - (s) -> s.tertiaryPalette, - (s) -> { - if (isMonochrome(s)) { - return s.isDark ? 60.0 : 49.0; - } - if (!isFidelity(s)) { - return s.isDark ? 30.0 : 90.0; - } - final double albersTone = - performAlbers(s.tertiaryPalette.getHct(s.sourceColorHct.getTone()), s); - final Hct proposedHct = s.tertiaryPalette.getHct(albersTone); - return DislikeAnalyzer.fixIfDisliked(proposedHct).getTone(); - }, - MaterialDynamicColors::highestSurface); - } - - public static DynamicColor onTertiaryContainer() { - return DynamicColor.fromPalette( - (s) -> s.tertiaryPalette, - (s) -> { - if (isMonochrome(s)) { - return s.isDark ? 0.0 : 100.0; - } - if (!isFidelity(s)) { - return s.isDark ? 90.0 : 10.0; - } - return DynamicColor.contrastingTone(tertiaryContainer().tone.apply(s), 4.5); - }, - (s) -> tertiaryContainer()); - } - - public static DynamicColor tertiary() { - return DynamicColor.fromPalette( - (s) -> s.tertiaryPalette, - (s) -> { - if (isMonochrome(s)) { - return s.isDark ? 90.0 : 25.0; - } - return s.isDark ? 80.0 : 40.0; - }, - MaterialDynamicColors::highestSurface, - (s) -> - new ToneDeltaConstraint( - CONTAINER_ACCENT_TONE_DELTA, - tertiaryContainer(), - s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER)); - } - - public static DynamicColor onTertiary() { - return DynamicColor.fromPalette( - (s) -> s.tertiaryPalette, - (s) -> { - if (isMonochrome(s)) { - return s.isDark ? 10.0 : 90.0; - } - return s.isDark ? 20.0 : 100.0; - }, - (s) -> tertiary()); - } - - public static DynamicColor errorContainer() { - return DynamicColor.fromPalette( - (s) -> s.errorPalette, (s) -> s.isDark ? 30.0 : 90.0, - MaterialDynamicColors::highestSurface); - } - - public static DynamicColor onErrorContainer() { - return DynamicColor.fromPalette( - (s) -> s.errorPalette, (s) -> s.isDark ? 90.0 : 10.0, (s) -> errorContainer()); - } - - public static DynamicColor error() { - return DynamicColor.fromPalette( - (s) -> s.errorPalette, - (s) -> s.isDark ? 80.0 : 40.0, - MaterialDynamicColors::highestSurface, - (s) -> - new ToneDeltaConstraint( - CONTAINER_ACCENT_TONE_DELTA, - errorContainer(), - s.isDark ? TonePolarity.DARKER : TonePolarity.LIGHTER)); - } - - public static DynamicColor onError() { - return DynamicColor.fromPalette( - (s) -> s.errorPalette, (s) -> s.isDark ? 20.0 : 100.0, (s) -> error()); - } - - public static DynamicColor primaryFixed() { - return DynamicColor.fromPalette( - (s) -> s.primaryPalette, - (s) -> { - if (isMonochrome(s)) { - return s.isDark ? 100.0 : 10.0; - } - return 90.0; - }, - MaterialDynamicColors::highestSurface); - } - - public static DynamicColor primaryFixedDim() { - return DynamicColor.fromPalette( - (s) -> s.primaryPalette, - (s) -> { - if (isMonochrome(s)) { - return s.isDark ? 90.0 : 20.0; - } - return 80.0; - }, - MaterialDynamicColors::highestSurface); - } - - public static DynamicColor onPrimaryFixed() { - return DynamicColor.fromPalette( - (s) -> s.primaryPalette, - (s) -> { - if (isMonochrome(s)) { - return s.isDark ? 10.0 : 90.0; - } - return 10.0; - }, - (s) -> primaryFixedDim()); - } - - public static DynamicColor onPrimaryFixedVariant() { - return DynamicColor.fromPalette( - (s) -> s.primaryPalette, - (s) -> { - if (isMonochrome(s)) { - return s.isDark ? 30.0 : 70.0; - } - return 30.0; - }, - (s) -> primaryFixedDim()); - } - - public static DynamicColor secondaryFixed() { - return DynamicColor.fromPalette( - (s) -> s.secondaryPalette, (s) -> isMonochrome(s) ? 80.0 : 90.0, - MaterialDynamicColors::highestSurface); - } - - public static DynamicColor secondaryFixedDim() { - return DynamicColor.fromPalette( - (s) -> s.secondaryPalette, (s) -> isMonochrome(s) ? 70.0 : 80.0, - MaterialDynamicColors::highestSurface); - } - - public static DynamicColor onSecondaryFixed() { - return DynamicColor.fromPalette( - (s) -> s.secondaryPalette, (s) -> 10.0, (s) -> secondaryFixedDim()); - } - - public static DynamicColor onSecondaryFixedVariant() { - return DynamicColor.fromPalette( - (s) -> s.secondaryPalette, - (s) -> isMonochrome(s) ? 25.0 : 30.0, - (s) -> secondaryFixedDim()); - } - - public static DynamicColor tertiaryFixed() { - return DynamicColor.fromPalette( - (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 40.0 : 90.0, - MaterialDynamicColors::highestSurface); - } - - public static DynamicColor tertiaryFixedDim() { - return DynamicColor.fromPalette( - (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 30.0 : 80.0, - MaterialDynamicColors::highestSurface); - } - - public static DynamicColor onTertiaryFixed() { - return DynamicColor.fromPalette( - (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 90.0 : 10.0, - (s) -> tertiaryFixedDim()); - } - - public static DynamicColor onTertiaryFixedVariant() { - return DynamicColor.fromPalette( - (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 70.0 : 30.0, - (s) -> tertiaryFixedDim()); - } - - // colorControlNormal documented as textColorSecondary in M3 & GM3. - // In Material, textColorSecondary points to onSurfaceVariant in the non-disabled state, - // which is Neutral Variant T30/80 in light/dark. - public static DynamicColor controlNormal() { - return DynamicColor.fromPalette((s) -> s.neutralVariantPalette, - (s) -> s.isDark ? 80.0 : 30.0); - } - - // colorControlHighlight documented, in both M3 & GM3: - // Light mode: #1f000000 dark mode: #33ffffff. - // These are black and white with some alpha. - // 1F hex = 31 decimal; 31 / 255 = 12% alpha. - // 33 hex = 51 decimal; 51 / 255 = 20% alpha. - // DynamicColors do not support alpha currently, and _may_ not need it for this use case, - // depending on how MDC resolved alpha for the other cases. - // Returning black in dark mode, white in light mode. - public static DynamicColor controlHighlight() { - return new DynamicColor( - s -> 0.0, - s -> 0.0, - s -> s.isDark ? 100.0 : 0.0, - s -> s.isDark ? 0.20 : 0.12, - null, - scheme -> - - DynamicColor.toneMinContrastDefault((s) -> s.isDark ? 100.0 : 0.0, null, - scheme, null), - scheme -> - DynamicColor.toneMaxContrastDefault((s) -> s.isDark ? 100.0 : 0.0, null, - scheme, null), - null); - } - - // textColorPrimaryInverse documented, in both M3 & GM3, documented as N10/N90. - public static DynamicColor textPrimaryInverse() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0); - } - - // textColorSecondaryInverse and textColorTertiaryInverse both documented, in both M3 & GM3, as - // NV30/NV80 - public static DynamicColor textSecondaryAndTertiaryInverse() { - return DynamicColor.fromPalette((s) -> s.neutralVariantPalette, - (s) -> s.isDark ? 30.0 : 80.0); - } - - // textColorPrimaryInverseDisableOnly documented, in both M3 & GM3, as N10/N90 - public static DynamicColor textPrimaryInverseDisableOnly() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0); - } - - // textColorSecondaryInverse and textColorTertiaryInverse in disabled state both documented, - // in both M3 & GM3, as N10/N90 - public static DynamicColor textSecondaryAndTertiaryInverseDisabled() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0); - } - - // textColorHintInverse documented, in both M3 & GM3, as N10/N90 - public static DynamicColor textHintInverse() { - return DynamicColor.fromPalette((s) -> s.neutralPalette, (s) -> s.isDark ? 10.0 : 90.0); - } -} +} \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/theme/DynamicColors.kt b/packages/SystemUI/src/com/android/systemui/theme/DynamicColors.kt index 57b9f914d4d62..ae4820837ce5b 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/DynamicColors.kt +++ b/packages/SystemUI/src/com/android/systemui/theme/DynamicColors.kt @@ -18,10 +18,11 @@ package com.android.systemui.theme import android.util.Pair import com.android.systemui.monet.dynamiccolor.DynamicColor -import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors as MDC +import com.android.systemui.monet.dynamiccolor.MaterialDynamicColors class DynamicColors { companion object { + private val MDC = MaterialDynamicColors() @JvmField val ALL_DYNAMIC_COLORS_MAPPED: List> = arrayListOf( diff --git a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java index c1999b2845532..b78329cfa5aa1 100644 --- a/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java +++ b/packages/SystemUI/src/com/android/systemui/theme/ThemeOverlayController.java @@ -659,6 +659,7 @@ public class ThemeOverlayController implements CoreStartable, Dumpable { Resources res = userHandle.isSystem() ? mResources : mContext.createContextAsUser(userHandle, 0).getResources(); Resources.Theme theme = mContext.getTheme(); + MaterialDynamicColors dynamicColors = new MaterialDynamicColors(); if (!(res.getColor(android.R.color.system_accent1_500, theme) == mColorScheme.getAccent1().getS500() && res.getColor(android.R.color.system_accent2_500, theme) @@ -670,15 +671,15 @@ public class ThemeOverlayController implements CoreStartable, Dumpable { && res.getColor(android.R.color.system_neutral2_500, theme) == mColorScheme.getNeutral2().getS500() && res.getColor(android.R.color.system_outline_variant_dark, theme) - == MaterialDynamicColors.outlineVariant().getArgb(mDynamicSchemeDark) + == dynamicColors.outlineVariant().getArgb(mDynamicSchemeDark) && res.getColor(android.R.color.system_outline_variant_light, theme) - == MaterialDynamicColors.outlineVariant().getArgb(mDynamicSchemeLight) + == dynamicColors.outlineVariant().getArgb(mDynamicSchemeLight) && res.getColor(android.R.color.system_primary_container_dark, theme) - == MaterialDynamicColors.primaryContainer().getArgb(mDynamicSchemeDark) + == dynamicColors.primaryContainer().getArgb(mDynamicSchemeDark) && res.getColor(android.R.color.system_primary_container_light, theme) - == MaterialDynamicColors.primaryContainer().getArgb(mDynamicSchemeLight) + == dynamicColors.primaryContainer().getArgb(mDynamicSchemeLight) && res.getColor(android.R.color.system_primary_fixed, theme) - == MaterialDynamicColors.primaryFixed().getArgb(mDynamicSchemeLight))) { + == dynamicColors.primaryFixed().getArgb(mDynamicSchemeLight))) { return false; } } From 47e0803c71ac0cddc6fd7b891d24f5e5585f3c22 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Fri, 26 May 2023 07:43:25 -0700 Subject: [PATCH 2/2] Fix contrast of monochrome fixed colors Screenshots: https://screenshot.googleplex.com/4ddevTXDQpRwWPA https://screenshot.googleplex.com/8T4HVfrHHsR9cSD https://screenshot.googleplex.com/7Wp7k5njCE33n3z https://screenshot.googleplex.com/7Np6gEXU7utJFsm Bug: 282951509 Test: atest SystemPaletteTest Change-Id: I678aea8a09c7b9cf30b437f15c4518415e3de319 --- .../monet/dynamiccolor/MaterialDynamicColors.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java index bc1edee1c10b7..9f075e5211263 100644 --- a/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java +++ b/packages/SystemUI/monet/src/com/android/systemui/monet/dynamiccolor/MaterialDynamicColors.java @@ -410,7 +410,7 @@ public final class MaterialDynamicColors { (s) -> s.primaryPalette, (s) -> { if (isMonochrome(s)) { - return s.isDark ? 100.0 : 10.0; + return 40.0; } return 90.0; }, @@ -423,7 +423,7 @@ public final class MaterialDynamicColors { (s) -> s.primaryPalette, (s) -> { if (isMonochrome(s)) { - return s.isDark ? 90.0 : 20.0; + return 30.0; } return 80.0; }, @@ -436,7 +436,7 @@ public final class MaterialDynamicColors { (s) -> s.primaryPalette, (s) -> { if (isMonochrome(s)) { - return s.isDark ? 10.0 : 90.0; + return 100.0; } return 10.0; }, @@ -449,7 +449,7 @@ public final class MaterialDynamicColors { (s) -> s.primaryPalette, (s) -> { if (isMonochrome(s)) { - return s.isDark ? 30.0 : 70.0; + return 90.0; } return 30.0; }, @@ -497,13 +497,13 @@ public final class MaterialDynamicColors { @NonNull public DynamicColor onTertiaryFixed() { return DynamicColor.fromPalette( - (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 90.0 : 10.0, (s) -> tertiaryFixedDim()); + (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 100.0 : 10.0, (s) -> tertiaryFixedDim()); } @NonNull public DynamicColor onTertiaryFixedVariant() { return DynamicColor.fromPalette( - (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 70.0 : 30.0, (s) -> tertiaryFixedDim()); + (s) -> s.tertiaryPalette, (s) -> isMonochrome(s) ? 90.0 : 30.0, (s) -> tertiaryFixedDim()); } /**