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

Commit 858ad2ac authored by Jeff DeCew's avatar Jeff DeCew
Browse files

Minimize use of header in adjusting notification colors.

Also adds support for 'inverted' icons.

Test: atest SystemUITests
Test: manual testing of numerous notification configurations
Change-Id: I6fd9aeec9f5971495d514add2bbb30b50db7d3c1
parent 73e65d42
Loading
Loading
Loading
Loading
+7 −16
Original line number Diff line number Diff line
@@ -82,7 +82,6 @@ import android.util.Pair;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.Gravity;
import android.view.NotificationHeaderView;
import android.view.View;
import android.view.ViewGroup;
import android.view.contentcapture.ContentCaptureContext;
@@ -5862,24 +5861,16 @@ public class Notification implements Parcelable
        }

        /**
         * Apply any necessariy colors to the small icon
         * Apply any necessary colors to the small icon
         */
        private void processSmallIconColor(Icon smallIcon, RemoteViews contentView,
                StandardTemplateParams p) {
            boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon);
            int color;
            if (isColorized(p)) {
                color = getPrimaryTextColor(p);
            } else {
                color = resolveContrastColor(p);
            }
            if (colorable) {
                contentView.setDrawableTint(R.id.icon, false, color,
                        PorterDuff.Mode.SRC_ATOP);

            }
            int color = isColorized(p) ? getPrimaryTextColor(p) : resolveContrastColor(p);
            contentView.setInt(R.id.icon, "setBackgroundColor",
                    resolveBackgroundColor(p));
            contentView.setInt(R.id.icon, "setOriginalIconColor",
                    colorable ? color : NotificationHeaderView.NO_COLOR);
                    colorable ? color : COLOR_INVALID);
        }

        /**
@@ -5892,8 +5883,8 @@ public class Notification implements Parcelable
            if (largeIcon != null && isLegacy()
                    && getColorUtil().isGrayscaleIcon(mContext, largeIcon)) {
                // resolve color will fall back to the default when legacy
                contentView.setDrawableTint(R.id.icon, false, resolveContrastColor(p),
                        PorterDuff.Mode.SRC_ATOP);
                int color = resolveContrastColor(p);
                contentView.setInt(R.id.icon, "setOriginalIconColor", color);
            }
        }

+0 −10
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@
package android.view;

import android.annotation.Nullable;
import android.app.Notification;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Resources;
@@ -42,7 +41,6 @@ import java.util.ArrayList;
 */
@RemoteViews.RemoteView
public class NotificationHeaderView extends ViewGroup {
    public static final int NO_COLOR = Notification.COLOR_INVALID;
    private final int mChildMinWidth;
    private final int mContentEndMargin;
    private final int mGravity;
@@ -294,14 +292,6 @@ public class NotificationHeaderView extends ViewGroup {
        updateTouchListener();
    }

    public int getOriginalIconColor() {
        return mIcon.getOriginalIconColor();
    }

    public int getOriginalNotificationColor() {
        return mExpandButton.getOriginalNotificationColor();
    }

    public void setShowWorkBadgeAtEnd(boolean showWorkBadgeAtEnd) {
        if (showWorkBadgeAtEnd != mShowWorkBadgeAtEnd) {
            setClipToPadding(!showWorkBadgeAtEnd);
+50 −0
Original line number Diff line number Diff line
@@ -16,12 +16,15 @@

package com.android.internal.widget;

import static com.android.internal.widget.ColoredIconHelper.applyGrayTint;

import android.annotation.DrawableRes;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.Icon;
import android.net.Uri;
@@ -48,6 +51,7 @@ public class CachingIconView extends ImageView {
    private Consumer<Integer> mOnVisibilityChangedListener;
    private Consumer<Boolean> mOnForceHiddenChangedListener;
    private int mIconColor;
    private int mBackgroundColor;
    private boolean mWillBeForceHidden;

    @UnsupportedAppUsage
@@ -230,9 +234,55 @@ public class CachingIconView extends ImageView {
        return mForceHidden;
    }

    /**
     * Provides the notification's background color to the icon.  This is only used when the icon
     * is "inverted".  This should be called before calling {@link #setOriginalIconColor(int)}.
     */
    @RemotableViewMethod
    public void setBackgroundColor(int color) {
        mBackgroundColor = color;
    }

    /**
     * Sets the icon color. If COLOR_INVALID is set, the icon's color filter will
     * not be altered. If there is a background drawable, this method uses the value from
     * {@link #setBackgroundColor(int)} which must have been already called.
     */
    @RemotableViewMethod
    public void setOriginalIconColor(int color) {
        mIconColor = color;
        Drawable background = getBackground();
        Drawable icon = getDrawable();
        boolean hasColor = color != ColoredIconHelper.COLOR_INVALID;
        if (background == null) {
            // This is the pre-S style -- colored icon with no background.
            if (hasColor) {
                icon.mutate().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
            }
        } else {
            // When there is a background drawable, color it with the foreground color and
            // colorize the icon itself with the background color, creating an inverted effect.
            if (hasColor) {
                background.mutate().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
                icon.mutate().setColorFilter(mBackgroundColor, PorterDuff.Mode.SRC_ATOP);
            } else {
                background.mutate().setColorFilter(mBackgroundColor, PorterDuff.Mode.SRC_ATOP);
            }
        }
    }

    /**
     * Set the icon's color filter: to gray if true, otherwise colored.
     * If this icon has no original color, this has no effect.
     */
    public void setGrayedOut(boolean grayedOut) {
        // If there is a background drawable, then it has the foreground color and the image
        // drawable has the background color, creating an inverted efffect.
        Drawable drawable = getBackground();
        if (drawable == null) {
            drawable = getDrawable();
        }
        applyGrayTint(mContext, drawable, grayedOut, mIconColor);
    }

    public int getOriginalIconColor() {
+57 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2020 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.widget;

import android.annotation.ColorInt;
import android.app.Notification;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;

import com.android.internal.util.ContrastColorUtil;

/** Helpers for colored icons */
final class ColoredIconHelper {

    @ColorInt
    static final int COLOR_INVALID = Notification.COLOR_INVALID;

    private ColoredIconHelper() {
    }

    /**
     * Apply a gray tint or the original color to a drawable, accounting for the night mode in
     * selecting the gray.
     */
    static void applyGrayTint(Context ctx, Drawable drawable, boolean apply, int originalColor) {
        if (originalColor == COLOR_INVALID) {
            return;
        }
        if (apply) {
            // lets gray it out
            Configuration config = ctx.getResources().getConfiguration();
            boolean inNightMode = (config.uiMode & Configuration.UI_MODE_NIGHT_MASK)
                    == Configuration.UI_MODE_NIGHT_YES;
            int grey = ContrastColorUtil.resolveColor(ctx, Notification.COLOR_DEFAULT, inNightMode);
            drawable.mutate().setColorFilter(grey, PorterDuff.Mode.SRC_ATOP);
        } else {
            // lets reset it
            drawable.mutate().setColorFilter(originalColor, PorterDuff.Mode.SRC_ATOP);
        }
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.internal.widget;

import static com.android.internal.widget.ColoredIconHelper.applyGrayTint;

import android.annotation.Nullable;
import android.content.Context;
import android.graphics.Rect;
@@ -70,6 +72,14 @@ public class NotificationExpandButton extends ImageView {
        return mOriginalNotificationColor;
    }

    /**
     * Set the button's color filter: to gray if true, otherwise colored.
     * If this button has no original color, this has no effect.
     */
    public void setGrayedOut(boolean shouldApply) {
        applyGrayTint(mContext, getDrawable(), shouldApply, mOriginalNotificationColor);
    }

    private void extendRectToMinTouchSize(Rect rect) {
        int touchTargetSize = (int) (getResources().getDisplayMetrics().density * 48);
        rect.left = rect.centerX() - touchTargetSize / 2;
Loading