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

Commit 10c7e2b8 authored by Jeff DeCew's avatar Jeff DeCew Committed by Android (Google) Code Review
Browse files

Merge changes I09b3999a,I590be0ba into sc-qpr1-dev

* changes:
  Use tertiary accent color for expander with unread count.
  Fix ContrastColorUtil.findContrastColorAgainstDark to return the valid color
parents 3d3db4b6 d8054270
Loading
Loading
Loading
Loading
+31 −5
Original line number Diff line number Diff line
@@ -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);
@@ -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;
@@ -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);
                    }
@@ -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 {
@@ -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
                };
@@ -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);
@@ -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;
                }
@@ -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.
+10 −9
Original line number Diff line number Diff line
@@ -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) {
@@ -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;
@@ -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,
@@ -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) {
@@ -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) {
+10 −2
Original line number Diff line number Diff line
@@ -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());
@@ -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) {
+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);
        }
    }

}