Merge changes I09b3999a,I590be0ba into sc-qpr1-dev am: 10c7e2b811

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15549414

Change-Id: I9597ee3b59967386c95bb5aa2129ed5ea7b5e58d
This commit is contained in:
Jeff DeCew
2021-08-16 19:38:07 +00:00
committed by Automerger Merge Worker
4 changed files with 150 additions and 16 deletions

View File

@@ -5387,8 +5387,8 @@ public class Notification implements Parcelable
contentView.setInt(R.id.expand_button, "setDefaultPillColor", pillColor); contentView.setInt(R.id.expand_button, "setDefaultPillColor", pillColor);
// Use different highlighted colors for conversations' unread count // Use different highlighted colors for conversations' unread count
if (p.mHighlightExpander) { if (p.mHighlightExpander) {
pillColor = Colors.flattenAlpha(getPrimaryAccentColor(p), bgColor); pillColor = Colors.flattenAlpha(getColors(p).getTertiaryAccentColor(), bgColor);
textColor = Colors.flattenAlpha(bgColor, pillColor); textColor = Colors.flattenAlpha(getColors(p).getOnAccentTextColor(), pillColor);
} }
contentView.setInt(R.id.expand_button, "setHighlightTextColor", textColor); contentView.setInt(R.id.expand_button, "setHighlightTextColor", textColor);
contentView.setInt(R.id.expand_button, "setHighlightPillColor", pillColor); contentView.setInt(R.id.expand_button, "setHighlightPillColor", pillColor);
@@ -12305,6 +12305,8 @@ public class Notification implements Parcelable
private int mSecondaryTextColor = COLOR_INVALID; private int mSecondaryTextColor = COLOR_INVALID;
private int mPrimaryAccentColor = COLOR_INVALID; private int mPrimaryAccentColor = COLOR_INVALID;
private int mSecondaryAccentColor = COLOR_INVALID; private int mSecondaryAccentColor = COLOR_INVALID;
private int mTertiaryAccentColor = COLOR_INVALID;
private int mOnAccentTextColor = COLOR_INVALID;
private int mErrorColor = COLOR_INVALID; private int mErrorColor = COLOR_INVALID;
private int mContrastColor = COLOR_INVALID; private int mContrastColor = COLOR_INVALID;
private int mRippleAlpha = 0x33; private int mRippleAlpha = 0x33;
@@ -12362,7 +12364,7 @@ public class Notification implements Parcelable
if (isColorized) { if (isColorized) {
if (rawColor == COLOR_DEFAULT) { if (rawColor == COLOR_DEFAULT) {
int[] attrs = {R.attr.colorAccentTertiary}; int[] attrs = {R.attr.colorAccentSecondary};
try (TypedArray ta = obtainDayNightAttributes(ctx, attrs)) { try (TypedArray ta = obtainDayNightAttributes(ctx, attrs)) {
mBackgroundColor = getColor(ta, 0, Color.WHITE); mBackgroundColor = getColor(ta, 0, Color.WHITE);
} }
@@ -12379,6 +12381,8 @@ public class Notification implements Parcelable
mContrastColor = mPrimaryTextColor; mContrastColor = mPrimaryTextColor;
mPrimaryAccentColor = mPrimaryTextColor; mPrimaryAccentColor = mPrimaryTextColor;
mSecondaryAccentColor = mSecondaryTextColor; mSecondaryAccentColor = mSecondaryTextColor;
mTertiaryAccentColor = flattenAlpha(mPrimaryTextColor, mBackgroundColor);
mOnAccentTextColor = mBackgroundColor;
mErrorColor = mPrimaryTextColor; mErrorColor = mPrimaryTextColor;
mRippleAlpha = 0x33; mRippleAlpha = 0x33;
} else { } else {
@@ -12389,6 +12393,8 @@ public class Notification implements Parcelable
R.attr.textColorSecondary, R.attr.textColorSecondary,
R.attr.colorAccent, R.attr.colorAccent,
R.attr.colorAccentSecondary, R.attr.colorAccentSecondary,
R.attr.colorAccentTertiary,
R.attr.textColorOnAccent,
R.attr.colorError, R.attr.colorError,
R.attr.colorControlHighlight R.attr.colorControlHighlight
}; };
@@ -12399,8 +12405,10 @@ public class Notification implements Parcelable
mSecondaryTextColor = getColor(ta, 3, COLOR_INVALID); mSecondaryTextColor = getColor(ta, 3, COLOR_INVALID);
mPrimaryAccentColor = getColor(ta, 4, COLOR_INVALID); mPrimaryAccentColor = getColor(ta, 4, COLOR_INVALID);
mSecondaryAccentColor = getColor(ta, 5, COLOR_INVALID); mSecondaryAccentColor = getColor(ta, 5, COLOR_INVALID);
mErrorColor = getColor(ta, 6, COLOR_INVALID); mTertiaryAccentColor = getColor(ta, 6, COLOR_INVALID);
mRippleAlpha = Color.alpha(getColor(ta, 7, 0x33ffffff)); mOnAccentTextColor = getColor(ta, 7, COLOR_INVALID);
mErrorColor = getColor(ta, 8, COLOR_INVALID);
mRippleAlpha = Color.alpha(getColor(ta, 9, 0x33ffffff));
} }
mContrastColor = calculateContrastColor(ctx, rawColor, mPrimaryAccentColor, mContrastColor = calculateContrastColor(ctx, rawColor, mPrimaryAccentColor,
mBackgroundColor, nightMode); mBackgroundColor, nightMode);
@@ -12420,6 +12428,14 @@ public class Notification implements Parcelable
if (mSecondaryAccentColor == COLOR_INVALID) { if (mSecondaryAccentColor == COLOR_INVALID) {
mSecondaryAccentColor = mContrastColor; mSecondaryAccentColor = mContrastColor;
} }
if (mTertiaryAccentColor == COLOR_INVALID) {
mTertiaryAccentColor = mContrastColor;
}
if (mOnAccentTextColor == COLOR_INVALID) {
mOnAccentTextColor = ColorUtils.setAlphaComponent(
ContrastColorUtil.resolvePrimaryColor(
ctx, mTertiaryAccentColor, nightMode), 0xFF);
}
if (mErrorColor == COLOR_INVALID) { if (mErrorColor == COLOR_INVALID) {
mErrorColor = mPrimaryTextColor; mErrorColor = mPrimaryTextColor;
} }
@@ -12485,6 +12501,16 @@ public class Notification implements Parcelable
return mSecondaryAccentColor; return mSecondaryAccentColor;
} }
/** @return the theme's tertiary accent color for colored UI elements. */
public @ColorInt int getTertiaryAccentColor() {
return mTertiaryAccentColor;
}
/** @return the theme's text color to be used on the tertiary accent color. */
public @ColorInt int getOnAccentTextColor() {
return mOnAccentTextColor;
}
/** /**
* @return the contrast-adjusted version of the color provided by the app, or the * @return the contrast-adjusted version of the color provided by the app, or the
* primary text color when colorized. * primary text color when colorized.

View File

@@ -291,10 +291,10 @@ public class ContrastColorUtil {
* Finds a suitable color such that there's enough contrast. * Finds a suitable color such that there's enough contrast.
* *
* @param color the color to start searching from. * @param color the color to start searching from.
* @param other the color to ensure contrast against. Assumed to be lighter than {@param color} * @param other the color to ensure contrast against. Assumed to be lighter than {@code color}
* @param findFg if true, we assume {@param color} is a foreground, otherwise a background. * @param findFg if true, we assume {@code color} is a foreground, otherwise a background.
* @param minRatio the minimum contrast ratio required. * @param minRatio the minimum contrast ratio required.
* @return a color with the same hue as {@param color}, potentially darkened to meet the * @return a color with the same hue as {@code color}, potentially darkened to meet the
* contrast ratio. * contrast ratio.
*/ */
public static int findContrastColor(int color, int other, boolean findFg, double minRatio) { public static int findContrastColor(int color, int other, boolean findFg, double minRatio) {
@@ -331,7 +331,7 @@ public class ContrastColorUtil {
* @param color the color to start searching from. * @param color the color to start searching from.
* @param backgroundColor the color to ensure contrast against. * @param backgroundColor the color to ensure contrast against.
* @param minRatio the minimum contrast ratio required. * @param minRatio the minimum contrast ratio required.
* @return the same color as {@param color} with potentially modified alpha to meet contrast * @return the same color as {@code color} with potentially modified alpha to meet contrast
*/ */
public static int findAlphaToMeetContrast(int color, int backgroundColor, double minRatio) { public static int findAlphaToMeetContrast(int color, int backgroundColor, double minRatio) {
int fg = color; int fg = color;
@@ -361,10 +361,10 @@ public class ContrastColorUtil {
* Finds a suitable color such that there's enough contrast. * Finds a suitable color such that there's enough contrast.
* *
* @param color the color to start searching from. * @param color the color to start searching from.
* @param other the color to ensure contrast against. Assumed to be darker than {@param color} * @param other the color to ensure contrast against. Assumed to be darker than {@code color}
* @param findFg if true, we assume {@param color} is a foreground, otherwise a background. * @param findFg if true, we assume {@code color} is a foreground, otherwise a background.
* @param minRatio the minimum contrast ratio required. * @param minRatio the minimum contrast ratio required.
* @return a color with the same hue as {@param color}, potentially darkened to meet the * @return a color with the same hue as {@code color}, potentially lightened to meet the
* contrast ratio. * contrast ratio.
*/ */
public static int findContrastColorAgainstDark(int color, int other, boolean findFg, public static int findContrastColorAgainstDark(int color, int other, boolean findFg,
@@ -393,7 +393,8 @@ public class ContrastColorUtil {
low = l; low = l;
} }
} }
return findFg ? fg : bg; hsl[2] = high;
return ColorUtilsFromCompat.HSLToColor(hsl);
} }
public static int ensureTextContrastOnBlack(int color) { public static int ensureTextContrastOnBlack(int color) {
@@ -452,7 +453,7 @@ public class ContrastColorUtil {
} }
/** /**
* Resolves {@param color} to an actual color if it is {@link Notification#COLOR_DEFAULT} * Resolves {@code color} to an actual color if it is {@link Notification#COLOR_DEFAULT}
*/ */
public static int resolveColor(Context context, int color, boolean defaultBackgroundIsDark) { public static int resolveColor(Context context, int color, boolean defaultBackgroundIsDark) {
if (color == Notification.COLOR_DEFAULT) { if (color == Notification.COLOR_DEFAULT) {

View File

@@ -399,6 +399,8 @@ public class NotificationTest {
assertEquals(cDay.getSecondaryTextColor(), cNight.getSecondaryTextColor()); assertEquals(cDay.getSecondaryTextColor(), cNight.getSecondaryTextColor());
assertEquals(cDay.getPrimaryAccentColor(), cNight.getPrimaryAccentColor()); assertEquals(cDay.getPrimaryAccentColor(), cNight.getPrimaryAccentColor());
assertEquals(cDay.getSecondaryAccentColor(), cNight.getSecondaryAccentColor()); assertEquals(cDay.getSecondaryAccentColor(), cNight.getSecondaryAccentColor());
assertEquals(cDay.getTertiaryAccentColor(), cNight.getTertiaryAccentColor());
assertEquals(cDay.getOnAccentTextColor(), cNight.getOnAccentTextColor());
assertEquals(cDay.getProtectionColor(), cNight.getProtectionColor()); assertEquals(cDay.getProtectionColor(), cNight.getProtectionColor());
assertEquals(cDay.getContrastColor(), cNight.getContrastColor()); assertEquals(cDay.getContrastColor(), cNight.getContrastColor());
assertEquals(cDay.getRippleAlpha(), cNight.getRippleAlpha()); assertEquals(cDay.getRippleAlpha(), cNight.getRippleAlpha());
@@ -413,20 +415,26 @@ public class NotificationTest {
assertThat(c.getSecondaryTextColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getSecondaryTextColor()).isNotEqualTo(Notification.COLOR_INVALID);
assertThat(c.getPrimaryAccentColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getPrimaryAccentColor()).isNotEqualTo(Notification.COLOR_INVALID);
assertThat(c.getSecondaryAccentColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getSecondaryAccentColor()).isNotEqualTo(Notification.COLOR_INVALID);
assertThat(c.getTertiaryAccentColor()).isNotEqualTo(Notification.COLOR_INVALID);
assertThat(c.getOnAccentTextColor()).isNotEqualTo(Notification.COLOR_INVALID);
assertThat(c.getErrorColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getErrorColor()).isNotEqualTo(Notification.COLOR_INVALID);
assertThat(c.getContrastColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getContrastColor()).isNotEqualTo(Notification.COLOR_INVALID);
assertThat(c.getRippleAlpha()).isAtLeast(0x00); assertThat(c.getRippleAlpha()).isAtLeast(0x00);
assertThat(c.getRippleAlpha()).isAtMost(0xff); assertThat(c.getRippleAlpha()).isAtMost(0xff);
// Assert that various colors have sufficient contrast // Assert that various colors have sufficient contrast with the background
assertContrastIsAtLeast(c.getPrimaryTextColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getPrimaryTextColor(), c.getBackgroundColor(), 4.5);
assertContrastIsAtLeast(c.getSecondaryTextColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getSecondaryTextColor(), c.getBackgroundColor(), 4.5);
assertContrastIsAtLeast(c.getPrimaryAccentColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getPrimaryAccentColor(), c.getBackgroundColor(), 4.5);
assertContrastIsAtLeast(c.getErrorColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getErrorColor(), c.getBackgroundColor(), 4.5);
assertContrastIsAtLeast(c.getContrastColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getContrastColor(), c.getBackgroundColor(), 4.5);
// This accent color is only used for emphasized buttons // These colors are only used for emphasized buttons; they do not need contrast
assertContrastIsAtLeast(c.getSecondaryAccentColor(), c.getBackgroundColor(), 1); assertContrastIsAtLeast(c.getSecondaryAccentColor(), c.getBackgroundColor(), 1);
assertContrastIsAtLeast(c.getTertiaryAccentColor(), c.getBackgroundColor(), 1);
// The text that is used within the accent color DOES need to have contrast
assertContrastIsAtLeast(c.getOnAccentTextColor(), c.getTertiaryAccentColor(), 4.5);
} }
private void assertContrastIsAtLeast(int foreground, int background, double minContrast) { private void assertContrastIsAtLeast(int foreground, int background, double minContrast) {

View File

@@ -0,0 +1,99 @@
/*
* Copyright (C) 2016 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.internal.util;
import static androidx.core.graphics.ColorUtils.calculateContrast;
import static com.google.common.truth.Truth.assertThat;
import android.graphics.Color;
import androidx.test.filters.SmallTest;
import junit.framework.TestCase;
public class ContrastColorUtilTest extends TestCase {
@SmallTest
public void testEnsureTextContrastAgainstDark() {
int darkBg = 0xFF35302A;
int blueContrastColor = ContrastColorUtil.ensureTextContrast(Color.BLUE, darkBg, true);
assertContrastIsWithinRange(blueContrastColor, darkBg, 4.5, 4.75);
int redContrastColor = ContrastColorUtil.ensureTextContrast(Color.RED, darkBg, true);
assertContrastIsWithinRange(redContrastColor, darkBg, 4.5, 4.75);
final int darkGreen = 0xff008800;
int greenContrastColor = ContrastColorUtil.ensureTextContrast(darkGreen, darkBg, true);
assertContrastIsWithinRange(greenContrastColor, darkBg, 4.5, 4.75);
int grayContrastColor = ContrastColorUtil.ensureTextContrast(Color.DKGRAY, darkBg, true);
assertContrastIsWithinRange(grayContrastColor, darkBg, 4.5, 4.75);
int selfContrastColor = ContrastColorUtil.ensureTextContrast(darkBg, darkBg, true);
assertContrastIsWithinRange(selfContrastColor, darkBg, 4.5, 4.75);
}
@SmallTest
public void testEnsureTextContrastAgainstLight() {
int lightBg = 0xFFFFF8F2;
final int lightBlue = 0xff8888ff;
int blueContrastColor = ContrastColorUtil.ensureTextContrast(lightBlue, lightBg, false);
assertContrastIsWithinRange(blueContrastColor, lightBg, 4.5, 4.75);
int redContrastColor = ContrastColorUtil.ensureTextContrast(Color.RED, lightBg, false);
assertContrastIsWithinRange(redContrastColor, lightBg, 4.5, 4.75);
int greenContrastColor = ContrastColorUtil.ensureTextContrast(Color.GREEN, lightBg, false);
assertContrastIsWithinRange(greenContrastColor, lightBg, 4.5, 4.75);
int grayContrastColor = ContrastColorUtil.ensureTextContrast(Color.LTGRAY, lightBg, false);
assertContrastIsWithinRange(grayContrastColor, lightBg, 4.5, 4.75);
int selfContrastColor = ContrastColorUtil.ensureTextContrast(lightBg, lightBg, false);
assertContrastIsWithinRange(selfContrastColor, lightBg, 4.5, 4.75);
}
private void assertContrastIsWithinRange(int foreground, int background,
double minContrast, double maxContrast) {
assertContrastIsAtLeast(foreground, background, minContrast);
assertContrastIsAtMost(foreground, background, maxContrast);
}
private void assertContrastIsAtLeast(int foreground, int background, double minContrast) {
try {
assertThat(calculateContrast(foreground, background)).isAtLeast(minContrast);
} catch (AssertionError e) {
throw new AssertionError(
String.format("Insufficient contrast: foreground=#%08x background=#%08x",
foreground, background), e);
}
}
private void assertContrastIsAtMost(int foreground, int background, double maxContrast) {
try {
assertThat(calculateContrast(foreground, background)).isAtMost(maxContrast);
} catch (AssertionError e) {
throw new AssertionError(
String.format("Excessive contrast: foreground=#%08x background=#%08x",
foreground, background), e);
}
}
}