Loading core/java/android/app/Notification.java +31 −5 Original line number Diff line number Diff line Loading @@ -5387,8 +5387,8 @@ public class Notification implements Parcelable contentView.setInt(R.id.expand_button, "setDefaultPillColor", pillColor); // Use different highlighted colors for conversations' unread count if (p.mHighlightExpander) { pillColor = Colors.flattenAlpha(getPrimaryAccentColor(p), bgColor); textColor = Colors.flattenAlpha(bgColor, pillColor); pillColor = Colors.flattenAlpha(getColors(p).getTertiaryAccentColor(), bgColor); textColor = Colors.flattenAlpha(getColors(p).getOnAccentTextColor(), pillColor); } contentView.setInt(R.id.expand_button, "setHighlightTextColor", textColor); contentView.setInt(R.id.expand_button, "setHighlightPillColor", pillColor); Loading Loading @@ -12305,6 +12305,8 @@ public class Notification implements Parcelable private int mSecondaryTextColor = COLOR_INVALID; private int mPrimaryAccentColor = COLOR_INVALID; private int mSecondaryAccentColor = COLOR_INVALID; private int mTertiaryAccentColor = COLOR_INVALID; private int mOnAccentTextColor = COLOR_INVALID; private int mErrorColor = COLOR_INVALID; private int mContrastColor = COLOR_INVALID; private int mRippleAlpha = 0x33; Loading Loading @@ -12362,7 +12364,7 @@ public class Notification implements Parcelable if (isColorized) { if (rawColor == COLOR_DEFAULT) { int[] attrs = {R.attr.colorAccentTertiary}; int[] attrs = {R.attr.colorAccentSecondary}; try (TypedArray ta = obtainDayNightAttributes(ctx, attrs)) { mBackgroundColor = getColor(ta, 0, Color.WHITE); } Loading @@ -12379,6 +12381,8 @@ public class Notification implements Parcelable mContrastColor = mPrimaryTextColor; mPrimaryAccentColor = mPrimaryTextColor; mSecondaryAccentColor = mSecondaryTextColor; mTertiaryAccentColor = flattenAlpha(mPrimaryTextColor, mBackgroundColor); mOnAccentTextColor = mBackgroundColor; mErrorColor = mPrimaryTextColor; mRippleAlpha = 0x33; } else { Loading @@ -12389,6 +12393,8 @@ public class Notification implements Parcelable R.attr.textColorSecondary, R.attr.colorAccent, R.attr.colorAccentSecondary, R.attr.colorAccentTertiary, R.attr.textColorOnAccent, R.attr.colorError, R.attr.colorControlHighlight }; Loading @@ -12399,8 +12405,10 @@ public class Notification implements Parcelable mSecondaryTextColor = getColor(ta, 3, COLOR_INVALID); mPrimaryAccentColor = getColor(ta, 4, COLOR_INVALID); mSecondaryAccentColor = getColor(ta, 5, COLOR_INVALID); mErrorColor = getColor(ta, 6, COLOR_INVALID); mRippleAlpha = Color.alpha(getColor(ta, 7, 0x33ffffff)); mTertiaryAccentColor = getColor(ta, 6, COLOR_INVALID); mOnAccentTextColor = getColor(ta, 7, COLOR_INVALID); mErrorColor = getColor(ta, 8, COLOR_INVALID); mRippleAlpha = Color.alpha(getColor(ta, 9, 0x33ffffff)); } mContrastColor = calculateContrastColor(ctx, rawColor, mPrimaryAccentColor, mBackgroundColor, nightMode); Loading @@ -12420,6 +12428,14 @@ public class Notification implements Parcelable if (mSecondaryAccentColor == COLOR_INVALID) { 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) { mErrorColor = mPrimaryTextColor; } Loading Loading @@ -12485,6 +12501,16 @@ public class Notification implements Parcelable 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 * primary text color when colorized. Loading core/java/com/android/internal/util/ContrastColorUtil.java +10 −9 Original line number Diff line number Diff line Loading @@ -291,10 +291,10 @@ public class ContrastColorUtil { * Finds a suitable color such that there's enough contrast. * * @param color the color to start searching from. * @param other the color to ensure contrast against. Assumed to be lighter than {@param color} * @param findFg if true, we assume {@param color} is a foreground, otherwise a background. * @param other the color to ensure contrast against. Assumed to be lighter than {@code color} * @param findFg if true, we assume {@code color} is a foreground, otherwise a background. * @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. */ public static int findContrastColor(int color, int other, boolean findFg, double minRatio) { Loading Loading @@ -331,7 +331,7 @@ public class ContrastColorUtil { * @param color the color to start searching from. * @param backgroundColor the color to ensure contrast against. * @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) { int fg = color; Loading Loading @@ -361,10 +361,10 @@ public class ContrastColorUtil { * Finds a suitable color such that there's enough contrast. * * @param color the color to start searching from. * @param other the color to ensure contrast against. Assumed to be darker than {@param color} * @param findFg if true, we assume {@param color} is a foreground, otherwise a background. * @param other the color to ensure contrast against. Assumed to be darker than {@code color} * @param findFg if true, we assume {@code color} is a foreground, otherwise a background. * @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. */ public static int findContrastColorAgainstDark(int color, int other, boolean findFg, Loading Loading @@ -393,7 +393,8 @@ public class ContrastColorUtil { low = l; } } return findFg ? fg : bg; hsl[2] = high; return ColorUtilsFromCompat.HSLToColor(hsl); } public static int ensureTextContrastOnBlack(int color) { Loading Loading @@ -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) { if (color == Notification.COLOR_DEFAULT) { Loading core/tests/coretests/src/android/app/NotificationTest.java +10 −2 Original line number Diff line number Diff line Loading @@ -399,6 +399,8 @@ public class NotificationTest { assertEquals(cDay.getSecondaryTextColor(), cNight.getSecondaryTextColor()); assertEquals(cDay.getPrimaryAccentColor(), cNight.getPrimaryAccentColor()); assertEquals(cDay.getSecondaryAccentColor(), cNight.getSecondaryAccentColor()); assertEquals(cDay.getTertiaryAccentColor(), cNight.getTertiaryAccentColor()); assertEquals(cDay.getOnAccentTextColor(), cNight.getOnAccentTextColor()); assertEquals(cDay.getProtectionColor(), cNight.getProtectionColor()); assertEquals(cDay.getContrastColor(), cNight.getContrastColor()); assertEquals(cDay.getRippleAlpha(), cNight.getRippleAlpha()); Loading @@ -413,20 +415,26 @@ public class NotificationTest { assertThat(c.getSecondaryTextColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getPrimaryAccentColor()).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.getContrastColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getRippleAlpha()).isAtLeast(0x00); 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.getSecondaryTextColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getPrimaryAccentColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getErrorColor(), 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.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) { Loading core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java 0 → 100644 +99 −0 Original line number Diff line number Diff line /* * 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); } } } libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java +16 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.wm.shell.onehanded; import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Color; Loading Loading @@ -46,7 +48,7 @@ import java.util.concurrent.Executor; * the screen has entered one handed mode. */ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer implements OneHandedAnimationCallback { implements OneHandedAnimationCallback, OneHandedState.OnStateChangedListener { private static final String TAG = "OneHandedBackgroundPanelOrganizer"; private static final int THEME_COLOR_OFFSET = 10; private static final int ALPHA_ANIMATION_DURATION = 200; Loading @@ -56,6 +58,7 @@ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer private final OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory mTransactionFactory; private @OneHandedState.State int mCurrentState; private ValueAnimator mAlphaAnimator; private float mTranslationFraction; Loading Loading @@ -180,6 +183,9 @@ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer * Called when transition finished. */ public void onStopFinished() { if (mAlphaAnimator == null) { return; } mAlphaAnimator.start(); } Loading Loading @@ -224,6 +230,10 @@ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer */ public void onConfigurationChanged() { updateThemeColors(); if (mCurrentState != STATE_ACTIVE) { return; } showBackgroundPanelLayer(); } Loading @@ -242,6 +252,11 @@ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer return Math.max(origColor - THEME_COLOR_OFFSET, 0) / 255.0f; } @Override public void onStateChanged(int newState) { mCurrentState = newState; } void dump(@NonNull PrintWriter pw) { final String innerPrefix = " "; pw.println(TAG); Loading Loading
core/java/android/app/Notification.java +31 −5 Original line number Diff line number Diff line Loading @@ -5387,8 +5387,8 @@ public class Notification implements Parcelable contentView.setInt(R.id.expand_button, "setDefaultPillColor", pillColor); // Use different highlighted colors for conversations' unread count if (p.mHighlightExpander) { pillColor = Colors.flattenAlpha(getPrimaryAccentColor(p), bgColor); textColor = Colors.flattenAlpha(bgColor, pillColor); pillColor = Colors.flattenAlpha(getColors(p).getTertiaryAccentColor(), bgColor); textColor = Colors.flattenAlpha(getColors(p).getOnAccentTextColor(), pillColor); } contentView.setInt(R.id.expand_button, "setHighlightTextColor", textColor); contentView.setInt(R.id.expand_button, "setHighlightPillColor", pillColor); Loading Loading @@ -12305,6 +12305,8 @@ public class Notification implements Parcelable private int mSecondaryTextColor = COLOR_INVALID; private int mPrimaryAccentColor = COLOR_INVALID; private int mSecondaryAccentColor = COLOR_INVALID; private int mTertiaryAccentColor = COLOR_INVALID; private int mOnAccentTextColor = COLOR_INVALID; private int mErrorColor = COLOR_INVALID; private int mContrastColor = COLOR_INVALID; private int mRippleAlpha = 0x33; Loading Loading @@ -12362,7 +12364,7 @@ public class Notification implements Parcelable if (isColorized) { if (rawColor == COLOR_DEFAULT) { int[] attrs = {R.attr.colorAccentTertiary}; int[] attrs = {R.attr.colorAccentSecondary}; try (TypedArray ta = obtainDayNightAttributes(ctx, attrs)) { mBackgroundColor = getColor(ta, 0, Color.WHITE); } Loading @@ -12379,6 +12381,8 @@ public class Notification implements Parcelable mContrastColor = mPrimaryTextColor; mPrimaryAccentColor = mPrimaryTextColor; mSecondaryAccentColor = mSecondaryTextColor; mTertiaryAccentColor = flattenAlpha(mPrimaryTextColor, mBackgroundColor); mOnAccentTextColor = mBackgroundColor; mErrorColor = mPrimaryTextColor; mRippleAlpha = 0x33; } else { Loading @@ -12389,6 +12393,8 @@ public class Notification implements Parcelable R.attr.textColorSecondary, R.attr.colorAccent, R.attr.colorAccentSecondary, R.attr.colorAccentTertiary, R.attr.textColorOnAccent, R.attr.colorError, R.attr.colorControlHighlight }; Loading @@ -12399,8 +12405,10 @@ public class Notification implements Parcelable mSecondaryTextColor = getColor(ta, 3, COLOR_INVALID); mPrimaryAccentColor = getColor(ta, 4, COLOR_INVALID); mSecondaryAccentColor = getColor(ta, 5, COLOR_INVALID); mErrorColor = getColor(ta, 6, COLOR_INVALID); mRippleAlpha = Color.alpha(getColor(ta, 7, 0x33ffffff)); mTertiaryAccentColor = getColor(ta, 6, COLOR_INVALID); mOnAccentTextColor = getColor(ta, 7, COLOR_INVALID); mErrorColor = getColor(ta, 8, COLOR_INVALID); mRippleAlpha = Color.alpha(getColor(ta, 9, 0x33ffffff)); } mContrastColor = calculateContrastColor(ctx, rawColor, mPrimaryAccentColor, mBackgroundColor, nightMode); Loading @@ -12420,6 +12428,14 @@ public class Notification implements Parcelable if (mSecondaryAccentColor == COLOR_INVALID) { 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) { mErrorColor = mPrimaryTextColor; } Loading Loading @@ -12485,6 +12501,16 @@ public class Notification implements Parcelable 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 * primary text color when colorized. Loading
core/java/com/android/internal/util/ContrastColorUtil.java +10 −9 Original line number Diff line number Diff line Loading @@ -291,10 +291,10 @@ public class ContrastColorUtil { * Finds a suitable color such that there's enough contrast. * * @param color the color to start searching from. * @param other the color to ensure contrast against. Assumed to be lighter than {@param color} * @param findFg if true, we assume {@param color} is a foreground, otherwise a background. * @param other the color to ensure contrast against. Assumed to be lighter than {@code color} * @param findFg if true, we assume {@code color} is a foreground, otherwise a background. * @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. */ public static int findContrastColor(int color, int other, boolean findFg, double minRatio) { Loading Loading @@ -331,7 +331,7 @@ public class ContrastColorUtil { * @param color the color to start searching from. * @param backgroundColor the color to ensure contrast against. * @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) { int fg = color; Loading Loading @@ -361,10 +361,10 @@ public class ContrastColorUtil { * Finds a suitable color such that there's enough contrast. * * @param color the color to start searching from. * @param other the color to ensure contrast against. Assumed to be darker than {@param color} * @param findFg if true, we assume {@param color} is a foreground, otherwise a background. * @param other the color to ensure contrast against. Assumed to be darker than {@code color} * @param findFg if true, we assume {@code color} is a foreground, otherwise a background. * @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. */ public static int findContrastColorAgainstDark(int color, int other, boolean findFg, Loading Loading @@ -393,7 +393,8 @@ public class ContrastColorUtil { low = l; } } return findFg ? fg : bg; hsl[2] = high; return ColorUtilsFromCompat.HSLToColor(hsl); } public static int ensureTextContrastOnBlack(int color) { Loading Loading @@ -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) { if (color == Notification.COLOR_DEFAULT) { Loading
core/tests/coretests/src/android/app/NotificationTest.java +10 −2 Original line number Diff line number Diff line Loading @@ -399,6 +399,8 @@ public class NotificationTest { assertEquals(cDay.getSecondaryTextColor(), cNight.getSecondaryTextColor()); assertEquals(cDay.getPrimaryAccentColor(), cNight.getPrimaryAccentColor()); assertEquals(cDay.getSecondaryAccentColor(), cNight.getSecondaryAccentColor()); assertEquals(cDay.getTertiaryAccentColor(), cNight.getTertiaryAccentColor()); assertEquals(cDay.getOnAccentTextColor(), cNight.getOnAccentTextColor()); assertEquals(cDay.getProtectionColor(), cNight.getProtectionColor()); assertEquals(cDay.getContrastColor(), cNight.getContrastColor()); assertEquals(cDay.getRippleAlpha(), cNight.getRippleAlpha()); Loading @@ -413,20 +415,26 @@ public class NotificationTest { assertThat(c.getSecondaryTextColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getPrimaryAccentColor()).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.getContrastColor()).isNotEqualTo(Notification.COLOR_INVALID); assertThat(c.getRippleAlpha()).isAtLeast(0x00); 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.getSecondaryTextColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getPrimaryAccentColor(), c.getBackgroundColor(), 4.5); assertContrastIsAtLeast(c.getErrorColor(), 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.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) { Loading
core/tests/coretests/src/com/android/internal/util/ContrastColorUtilTest.java 0 → 100644 +99 −0 Original line number Diff line number Diff line /* * 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); } } }
libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedBackgroundPanelOrganizer.java +16 −1 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ package com.android.wm.shell.onehanded; import static com.android.wm.shell.onehanded.OneHandedState.STATE_ACTIVE; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Color; Loading Loading @@ -46,7 +48,7 @@ import java.util.concurrent.Executor; * the screen has entered one handed mode. */ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer implements OneHandedAnimationCallback { implements OneHandedAnimationCallback, OneHandedState.OnStateChangedListener { private static final String TAG = "OneHandedBackgroundPanelOrganizer"; private static final int THEME_COLOR_OFFSET = 10; private static final int ALPHA_ANIMATION_DURATION = 200; Loading @@ -56,6 +58,7 @@ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer private final OneHandedSurfaceTransactionHelper.SurfaceControlTransactionFactory mTransactionFactory; private @OneHandedState.State int mCurrentState; private ValueAnimator mAlphaAnimator; private float mTranslationFraction; Loading Loading @@ -180,6 +183,9 @@ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer * Called when transition finished. */ public void onStopFinished() { if (mAlphaAnimator == null) { return; } mAlphaAnimator.start(); } Loading Loading @@ -224,6 +230,10 @@ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer */ public void onConfigurationChanged() { updateThemeColors(); if (mCurrentState != STATE_ACTIVE) { return; } showBackgroundPanelLayer(); } Loading @@ -242,6 +252,11 @@ public class OneHandedBackgroundPanelOrganizer extends DisplayAreaOrganizer return Math.max(origColor - THEME_COLOR_OFFSET, 0) / 255.0f; } @Override public void onStateChanged(int newState) { mCurrentState = newState; } void dump(@NonNull PrintWriter pw) { final String innerPrefix = " "; pw.println(TAG); Loading