Loading core/java/android/app/Notification.java +9 −18 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -4825,7 +4824,7 @@ public class Notification implements Parcelable private void resetNotificationHeader(RemoteViews contentView) { // Small icon doesn't need to be reset, as it's always set. Resetting would prevent // re-using the drawable when the notification is updated. contentView.setBoolean(R.id.notification_header, "setExpanded", false); contentView.setBoolean(R.id.expand_button, "setExpanded", false); contentView.setTextViewText(R.id.app_name_text, null); contentView.setViewVisibility(R.id.chronometer, View.GONE); contentView.setViewVisibility(R.id.header_text, View.GONE); Loading Loading @@ -5569,7 +5568,7 @@ public class Notification implements Parcelable */ public static void makeHeaderExpanded(RemoteViews result) { if (result != null) { result.setBoolean(R.id.notification_header, "setExpanded", true); result.setBoolean(R.id.expand_button, "setExpanded", true); } } Loading Loading @@ -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); } /** Loading @@ -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); } } Loading core/java/android/view/NotificationHeaderView.java +0 −32 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -56,7 +54,6 @@ public class NotificationHeaderView extends ViewGroup { private CachingIconView mIcon; private View mProfileBadge; private View mFeedbackIcon; private boolean mExpanded; private boolean mShowExpandButtonAtEnd; private boolean mShowWorkBadgeAtEnd; private int mHeaderTextMarginEnd; Loading Loading @@ -295,35 +292,6 @@ public class NotificationHeaderView extends ViewGroup { updateTouchListener(); } public int getOriginalIconColor() { return mIcon.getOriginalIconColor(); } public int getOriginalNotificationColor() { return mExpandButton.getOriginalNotificationColor(); } @RemotableViewMethod public void setExpanded(boolean expanded) { mExpanded = expanded; updateExpandButton(); } private void updateExpandButton() { int drawableId; int contentDescriptionId; if (mExpanded) { drawableId = R.drawable.ic_collapse_notification; contentDescriptionId = R.string.expand_button_content_description_expanded; } else { drawableId = R.drawable.ic_expand_notification; contentDescriptionId = R.string.expand_button_content_description_collapsed; } mExpandButton.setImageDrawable(getContext().getDrawable(drawableId)); mExpandButton.setColorFilter(getOriginalNotificationColor()); mExpandButton.setContentDescription(mContext.getText(contentDescriptionId)); } public void setShowWorkBadgeAtEnd(boolean showWorkBadgeAtEnd) { if (showWorkBadgeAtEnd != mShowWorkBadgeAtEnd) { setClipToPadding(!showWorkBadgeAtEnd); Loading core/java/com/android/internal/widget/CachingIconView.java +50 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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() { Loading core/java/com/android/internal/widget/ColoredIconHelper.java 0 → 100644 +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); } } } core/java/com/android/internal/widget/NotificationExpandButton.java +37 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -26,12 +28,15 @@ import android.widget.Button; import android.widget.ImageView; import android.widget.RemoteViews; import com.android.internal.R; /** * An expand button in a notification */ @RemoteViews.RemoteView public class NotificationExpandButton extends ImageView { private boolean mExpanded; private int mOriginalNotificationColor; public NotificationExpandButton(Context context) { Loading Loading @@ -67,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 @@ -80,4 +93,28 @@ public class NotificationExpandButton extends ImageView { super.onInitializeAccessibilityNodeInfo(info); info.setClassName(Button.class.getName()); } /** * Update the button's drawable, content description, and color for the given expanded state. */ @RemotableViewMethod public void setExpanded(boolean expanded) { mExpanded = expanded; updateExpandButton(); } private void updateExpandButton() { int drawableId; int contentDescriptionId; if (mExpanded) { drawableId = R.drawable.ic_collapse_notification; contentDescriptionId = R.string.expand_button_content_description_expanded; } else { drawableId = R.drawable.ic_expand_notification; contentDescriptionId = R.string.expand_button_content_description_collapsed; } setImageDrawable(getContext().getDrawable(drawableId)); setColorFilter(mOriginalNotificationColor); setContentDescription(mContext.getText(contentDescriptionId)); } } Loading
core/java/android/app/Notification.java +9 −18 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -4825,7 +4824,7 @@ public class Notification implements Parcelable private void resetNotificationHeader(RemoteViews contentView) { // Small icon doesn't need to be reset, as it's always set. Resetting would prevent // re-using the drawable when the notification is updated. contentView.setBoolean(R.id.notification_header, "setExpanded", false); contentView.setBoolean(R.id.expand_button, "setExpanded", false); contentView.setTextViewText(R.id.app_name_text, null); contentView.setViewVisibility(R.id.chronometer, View.GONE); contentView.setViewVisibility(R.id.header_text, View.GONE); Loading Loading @@ -5569,7 +5568,7 @@ public class Notification implements Parcelable */ public static void makeHeaderExpanded(RemoteViews result) { if (result != null) { result.setBoolean(R.id.notification_header, "setExpanded", true); result.setBoolean(R.id.expand_button, "setExpanded", true); } } Loading Loading @@ -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); } /** Loading @@ -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); } } Loading
core/java/android/view/NotificationHeaderView.java +0 −32 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading @@ -56,7 +54,6 @@ public class NotificationHeaderView extends ViewGroup { private CachingIconView mIcon; private View mProfileBadge; private View mFeedbackIcon; private boolean mExpanded; private boolean mShowExpandButtonAtEnd; private boolean mShowWorkBadgeAtEnd; private int mHeaderTextMarginEnd; Loading Loading @@ -295,35 +292,6 @@ public class NotificationHeaderView extends ViewGroup { updateTouchListener(); } public int getOriginalIconColor() { return mIcon.getOriginalIconColor(); } public int getOriginalNotificationColor() { return mExpandButton.getOriginalNotificationColor(); } @RemotableViewMethod public void setExpanded(boolean expanded) { mExpanded = expanded; updateExpandButton(); } private void updateExpandButton() { int drawableId; int contentDescriptionId; if (mExpanded) { drawableId = R.drawable.ic_collapse_notification; contentDescriptionId = R.string.expand_button_content_description_expanded; } else { drawableId = R.drawable.ic_expand_notification; contentDescriptionId = R.string.expand_button_content_description_collapsed; } mExpandButton.setImageDrawable(getContext().getDrawable(drawableId)); mExpandButton.setColorFilter(getOriginalNotificationColor()); mExpandButton.setContentDescription(mContext.getText(contentDescriptionId)); } public void setShowWorkBadgeAtEnd(boolean showWorkBadgeAtEnd) { if (showWorkBadgeAtEnd != mShowWorkBadgeAtEnd) { setClipToPadding(!showWorkBadgeAtEnd); Loading
core/java/com/android/internal/widget/CachingIconView.java +50 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 Loading Loading @@ -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() { Loading
core/java/com/android/internal/widget/ColoredIconHelper.java 0 → 100644 +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); } } }
core/java/com/android/internal/widget/NotificationExpandButton.java +37 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -26,12 +28,15 @@ import android.widget.Button; import android.widget.ImageView; import android.widget.RemoteViews; import com.android.internal.R; /** * An expand button in a notification */ @RemoteViews.RemoteView public class NotificationExpandButton extends ImageView { private boolean mExpanded; private int mOriginalNotificationColor; public NotificationExpandButton(Context context) { Loading Loading @@ -67,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 @@ -80,4 +93,28 @@ public class NotificationExpandButton extends ImageView { super.onInitializeAccessibilityNodeInfo(info); info.setClassName(Button.class.getName()); } /** * Update the button's drawable, content description, and color for the given expanded state. */ @RemotableViewMethod public void setExpanded(boolean expanded) { mExpanded = expanded; updateExpandButton(); } private void updateExpandButton() { int drawableId; int contentDescriptionId; if (mExpanded) { drawableId = R.drawable.ic_collapse_notification; contentDescriptionId = R.string.expand_button_content_description_expanded; } else { drawableId = R.drawable.ic_expand_notification; contentDescriptionId = R.string.expand_button_content_description_collapsed; } setImageDrawable(getContext().getDrawable(drawableId)); setColorFilter(mOriginalNotificationColor); setContentDescription(mContext.getText(contentDescriptionId)); } }