From cc0fbf9c37644e8295bcaf08d9994444fc57f243 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Tue, 8 Dec 2020 19:07:11 -0800 Subject: [PATCH] use new theme colors on custom notifications Custom notifications are inflated using a different context, text colors should be replaced after infaltion, similarly to what we do on dark mode. Test: manual Test: atest com.android.systemui.statusbar.notification.row Fixes: 174763901 Change-Id: I009011a66056cb31c026b48217710c5f3d74b0b5 --- packages/SystemUI/res/values/styles.xml | 2 - .../NotificationCustomViewWrapper.java | 4 ++ ...otificationDecoratedCustomViewWrapper.java | 5 ++ .../row/wrapper/NotificationViewWrapper.java | 50 +++++++++++++++++++ .../row/NotificationContentViewTest.java | 6 +++ .../wrapper/NotificationViewWrapperTest.java | 2 + 6 files changed, 67 insertions(+), 2 deletions(-) diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml index 0697c5c0084c6..6c0635a3ce515 100644 --- a/packages/SystemUI/res/values/styles.xml +++ b/packages/SystemUI/res/values/styles.xml @@ -489,7 +489,6 @@ diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java index 4c9c2f95b35cb..414d62092ab23 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java @@ -47,6 +47,10 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper { public void onContentUpdated(ExpandableNotificationRow row) { super.onContentUpdated(row); + // Custom views will most likely use just white or black as their text color. + // We need to scan through and replace these colors by Material NEXT colors. + ensureThemeOnChildren(); + // Let's invert the notification colors when we're in night mode and // the notification background isn't colorized. if (needsInversion(mBackgroundColor, mView)) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java index 49a8d56e1e65d..79648457c521c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java @@ -43,6 +43,11 @@ public class NotificationDecoratedCustomViewWrapper extends NotificationTemplate if (childIndex != null && childIndex != -1) { mWrappedView = container.getChildAt(childIndex); } + + // Custom views will most likely use just white or black as their text color. + // We need to scan through and replace these colors by Material NEXT colors. + ensureThemeOnChildren(); + if (needsInversion(resolveBackgroundColor(), mWrappedView)) { invertViewLuminosity(mWrappedView); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java index 416c5af934008..2d706a48e90d0 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java @@ -29,11 +29,13 @@ import android.graphics.Rect; import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.os.Build; +import android.view.ContextThemeWrapper; import android.view.NotificationHeaderView; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.graphics.ColorUtils; import com.android.internal.util.ContrastColorUtil; @@ -55,6 +57,9 @@ public abstract class NotificationViewWrapper implements TransformableView { private final Rect mTmpRect = new Rect(); protected int mBackgroundColor = 0; + private int mLightTextColor; + private int mDarkTextColor; + private int mDefaultTextColor; public static NotificationViewWrapper wrap(Context ctx, View v, ExpandableNotificationRow row) { if (v.getId() == com.android.internal.R.id.status_bar_latest_event_content) { @@ -110,6 +115,15 @@ public abstract class NotificationViewWrapper implements TransformableView { mBackgroundColor = backgroundColor; mView.setBackground(new ColorDrawable(Color.TRANSPARENT)); } + mLightTextColor = mView.getContext().getColor( + com.android.internal.R.color.notification_primary_text_color_light); + mDarkTextColor = mView.getContext().getColor( + R.color.notification_primary_text_color_dark); + + Context themedContext = new ContextThemeWrapper(mView.getContext(), + R.style.Theme_DeviceDefault_DayNight); + mDefaultTextColor = Utils.getColorAttr(themedContext, R.attr.textColorPrimary) + .getDefaultColor(); } protected boolean needsInversion(int defaultBackgroundColor, View view) { @@ -187,6 +201,42 @@ public abstract class NotificationViewWrapper implements TransformableView { return false; } + protected void ensureThemeOnChildren() { + if (mView == null) { + return; + } + + // Notifications with custom backgrounds should not be adjusted + if (mBackgroundColor != Color.TRANSPARENT + || getBackgroundColor(mView) != Color.TRANSPARENT) { + return; + } + + // Now let's check if there's unprotected text somewhere, and apply the theme if we find it. + if (!(mView instanceof ViewGroup)) { + return; + } + processChildrenTextColor((ViewGroup) mView); + } + + private void processChildrenTextColor(ViewGroup viewGroup) { + if (viewGroup == null) { + return; + } + + for (int i = 0; i < viewGroup.getChildCount(); i++) { + View child = viewGroup.getChildAt(i); + if (child instanceof TextView) { + int foreground = ((TextView) child).getCurrentTextColor(); + if (foreground == mLightTextColor || foreground == mDarkTextColor) { + ((TextView) child).setTextColor(mDefaultTextColor); + } + } else if (child instanceof ViewGroup) { + processChildrenTextColor((ViewGroup) child); + } + } + } + protected int getBackgroundColor(View view) { if (view == null) { return Color.TRANSPARENT; diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java index d08b2b78d00b6..2101ea1766a18 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationContentViewTest.java @@ -81,12 +81,15 @@ public class NotificationContentViewTest extends SysuiTestCase { View mockContracted = mock(NotificationHeaderView.class); when(mockContracted.findViewById(com.android.internal.R.id.feedback)) .thenReturn(mockContracted); + when(mockContracted.getContext()).thenReturn(mContext); View mockExpanded = mock(NotificationHeaderView.class); when(mockExpanded.findViewById(com.android.internal.R.id.feedback)) .thenReturn(mockExpanded); + when(mockExpanded.getContext()).thenReturn(mContext); View mockHeadsUp = mock(NotificationHeaderView.class); when(mockHeadsUp.findViewById(com.android.internal.R.id.feedback)) .thenReturn(mockHeadsUp); + when(mockHeadsUp.getContext()).thenReturn(mContext); mView.setContractedChild(mockContracted); mView.setExpandedChild(mockExpanded); @@ -107,18 +110,21 @@ public class NotificationContentViewTest extends SysuiTestCase { when(mockContracted.animate()).thenReturn(mock(ViewPropertyAnimator.class)); when(mockContracted.findViewById(com.android.internal.R.id.expand_button)).thenReturn( mockContractedEB); + when(mockContracted.getContext()).thenReturn(mContext); View mockExpandedEB = mock(NotificationExpandButton.class); View mockExpanded = mock(NotificationHeaderView.class); when(mockExpanded.animate()).thenReturn(mock(ViewPropertyAnimator.class)); when(mockExpanded.findViewById(com.android.internal.R.id.expand_button)).thenReturn( mockExpandedEB); + when(mockExpanded.getContext()).thenReturn(mContext); View mockHeadsUpEB = mock(NotificationExpandButton.class); View mockHeadsUp = mock(NotificationHeaderView.class); when(mockHeadsUp.animate()).thenReturn(mock(ViewPropertyAnimator.class)); when(mockHeadsUp.findViewById(com.android.internal.R.id.expand_button)).thenReturn( mockHeadsUpEB); + when(mockHeadsUp.getContext()).thenReturn(mContext); // Set up all 3 child forms mView.setContractedChild(mockContracted); diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java index 085bd900debc9..93a9e597ca908 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java @@ -17,6 +17,7 @@ package com.android.systemui.statusbar.notification.row.wrapper; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import android.content.Context; import android.testing.AndroidTestingRunner; @@ -49,6 +50,7 @@ public class NotificationViewWrapperTest extends SysuiTestCase { public void setup() throws Exception { allowTestableLooperAsMainThread(); mView = mock(View.class); + when(mView.getContext()).thenReturn(mContext); NotificationTestHelper helper = new NotificationTestHelper( mContext, mDependency,