summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/Notification.java5
-rw-r--r--core/res/res/values/ids.xml3
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java122
6 files changed, 189 insertions, 45 deletions
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 028e3efc9fb8..dc4f3432b6bd 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -8243,6 +8243,7 @@ public class Notification implements Parcelable
private void buildIntoRemoteViewContent(RemoteViews remoteViews,
RemoteViews customContent, TemplateBindResult result) {
+ int childIndex = -1;
if (customContent != null) {
// Need to clone customContent before adding, because otherwise it can no longer be
// parceled independently of remoteViews.
@@ -8250,7 +8251,11 @@ public class Notification implements Parcelable
remoteViews.removeAllViewsExceptId(R.id.notification_main_column, R.id.progress);
remoteViews.addView(R.id.notification_main_column, customContent, 0 /* index */);
remoteViews.addFlags(RemoteViews.FLAG_REAPPLY_DISALLOWED);
+ childIndex = 0;
}
+ remoteViews.setIntTag(R.id.notification_main_column,
+ com.android.internal.R.id.notification_custom_view_index_tag,
+ childIndex);
// also update the end margin if there is an image
Resources resources = mBuilder.mContext.getResources();
int endMargin = resources.getDimensionPixelSize(
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index bbe3ff995ac3..ce7995a93f7f 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -193,4 +193,7 @@
<!-- A tag used to save the notification action object -->
<item type="id" name="notification_action_index_tag" />
+
+ <!-- A tag used to save the index where the custom view is stored -->
+ <item type="id" name="notification_custom_view_index_tag" />
</resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3f6362851f61..2ab89ef28f6f 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3593,6 +3593,7 @@
<java-symbol type="bool" name="config_useSmsAppService" />
<java-symbol type="id" name="transition_overlay_view_tag" />
+ <java-symbol type="id" name="notification_custom_view_index_tag" />
<java-symbol type="dimen" name="rounded_corner_radius" />
<java-symbol type="dimen" name="rounded_corner_radius_top" />
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 4bdc1705c5ff..4c9c2f95b35c 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
@@ -17,12 +17,7 @@
package com.android.systemui.statusbar.notification.row.wrapper;
import android.content.Context;
-import android.content.res.Configuration;
import android.graphics.Color;
-import android.graphics.ColorMatrix;
-import android.graphics.ColorMatrixColorFilter;
-import android.graphics.Paint;
-import android.os.Build;
import android.view.View;
import com.android.internal.graphics.ColorUtils;
@@ -49,43 +44,22 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper {
}
@Override
- public void onReinflated() {
- super.onReinflated();
-
- Configuration configuration = mView.getResources().getConfiguration();
- boolean nightMode = (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
- == Configuration.UI_MODE_NIGHT_YES;
-
- float[] hsl = new float[] {0f, 0f, 0f};
- ColorUtils.colorToHSL(mBackgroundColor, hsl);
- boolean backgroundIsDark = Color.alpha(mBackgroundColor) == 0
- || hsl[1] == 0 && hsl[2] < 0.5;
- boolean backgroundHasColor = hsl[1] > 0;
+ public void onContentUpdated(ExpandableNotificationRow row) {
+ super.onContentUpdated(row);
// Let's invert the notification colors when we're in night mode and
// the notification background isn't colorized.
- if (!backgroundIsDark && !backgroundHasColor && nightMode
- && mRow.getEntry().targetSdk < Build.VERSION_CODES.Q) {
- Paint paint = new Paint();
- ColorMatrix matrix = new ColorMatrix();
- ColorMatrix tmp = new ColorMatrix();
- // Inversion should happen on Y'UV space to conseve the colors and
- // only affect the luminosity.
- matrix.setRGB2YUV();
- tmp.set(new float[]{
- -1f, 0f, 0f, 0f, 255f,
- 0f, 1f, 0f, 0f, 0f,
- 0f, 0f, 1f, 0f, 0f,
- 0f, 0f, 0f, 1f, 0f
- });
- matrix.postConcat(tmp);
- tmp.setYUV2RGB();
- matrix.postConcat(tmp);
- paint.setColorFilter(new ColorMatrixColorFilter(matrix));
- mView.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
-
- hsl[2] = 1f - hsl[2];
- mBackgroundColor = ColorUtils.HSLToColor(hsl);
+ if (needsInversion(mBackgroundColor, mView)) {
+ invertViewLuminosity(mView);
+
+ // Also invert background color if necessary
+ // (Otherwise we'd end-up with white on white.)
+ float[] hsl = new float[] {0f, 0f, 0f};
+ ColorUtils.colorToHSL(mBackgroundColor, hsl);
+ if (mBackgroundColor != Color.TRANSPARENT && hsl[2] > 0.5) {
+ hsl[2] = 1f - hsl[2];
+ mBackgroundColor = ColorUtils.HSLToColor(hsl);
+ }
}
}
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
new file mode 100644
index 000000000000..49a8d56e1e65
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 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.systemui.statusbar.notification.row.wrapper;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+
+/**
+ * Wraps a notification containing a decorated custom view.
+ */
+public class NotificationDecoratedCustomViewWrapper extends NotificationTemplateViewWrapper {
+
+ private View mWrappedView = null;
+
+ protected NotificationDecoratedCustomViewWrapper(Context ctx, View view,
+ ExpandableNotificationRow row) {
+ super(ctx, view, row);
+ }
+
+ @Override
+ public void onContentUpdated(ExpandableNotificationRow row) {
+ ViewGroup container = mView.findViewById(
+ com.android.internal.R.id.notification_main_column);
+ Integer childIndex = (Integer) container.getTag(
+ com.android.internal.R.id.notification_custom_view_index_tag);
+ if (childIndex != null && childIndex != -1) {
+ mWrappedView = container.getChildAt(childIndex);
+ }
+ if (needsInversion(resolveBackgroundColor(), mWrappedView)) {
+ invertViewLuminosity(mWrappedView);
+ }
+ super.onContentUpdated(row);
+ }
+}
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 9258c9971451..4c06ff6f5e49 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
@@ -16,13 +16,22 @@
package com.android.systemui.statusbar.notification.row.wrapper;
+import android.annotation.ColorInt;
+import android.app.Notification;
import android.content.Context;
+import android.content.res.Configuration;
import android.graphics.Color;
+import android.graphics.ColorMatrix;
+import android.graphics.ColorMatrixColorFilter;
+import android.graphics.Paint;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.view.NotificationHeaderView;
import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import com.android.internal.graphics.ColorUtils;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.notification.TransformState;
@@ -50,6 +59,11 @@ public abstract class NotificationViewWrapper implements TransformableView {
} else if ("messaging".equals(v.getTag())) {
return new NotificationMessagingTemplateViewWrapper(ctx, v, row);
}
+ Class<? extends Notification.Style> style =
+ row.getEntry().notification.getNotification().getNotificationStyle();
+ if (Notification.DecoratedCustomViewStyle.class.equals(style)) {
+ return new NotificationDecoratedCustomViewWrapper(ctx, v, row);
+ }
return new NotificationTemplateViewWrapper(ctx, v, row);
} else if (v instanceof NotificationHeaderView) {
return new NotificationHeaderViewWrapper(ctx, v, row);
@@ -75,14 +89,110 @@ public abstract class NotificationViewWrapper implements TransformableView {
if (shouldClearBackgroundOnReapply()) {
mBackgroundColor = 0;
}
- Drawable background = mView.getBackground();
- if (background instanceof ColorDrawable) {
- int backgroundColor = ((ColorDrawable) background).getColor();
- if (backgroundColor != Color.TRANSPARENT) {
- mBackgroundColor = backgroundColor;
- mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
+ int backgroundColor = getBackgroundColor(mView);
+ if (backgroundColor != Color.TRANSPARENT) {
+ mBackgroundColor = backgroundColor;
+ mView.setBackground(new ColorDrawable(Color.TRANSPARENT));
+ }
+ }
+
+ protected boolean needsInversion(int defaultBackgroundColor, View view) {
+ if (view == null) {
+ return false;
+ }
+
+ Configuration configuration = mView.getResources().getConfiguration();
+ boolean nightMode = (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
+ == Configuration.UI_MODE_NIGHT_YES;
+ if (!nightMode) {
+ return false;
+ }
+
+ int background = getBackgroundColor(view);
+ if (background == Color.TRANSPARENT) {
+ background = defaultBackgroundColor;
+ }
+ if (background == Color.TRANSPARENT) {
+ background = resolveBackgroundColor();
+ }
+
+ float[] hsl = new float[] {0f, 0f, 0f};
+ ColorUtils.colorToHSL(background, hsl);
+
+ // Notifications with colored backgrounds should not be inverted
+ if (hsl[1] != 0) {
+ return false;
+ }
+
+ // Invert white or light gray backgrounds.
+ boolean isLightGrayOrWhite = hsl[1] == 0 && hsl[2] > 0.5;
+ if (isLightGrayOrWhite) {
+ return true;
+ }
+
+ // Now let's check if there's unprotected text somewhere, and invert if we find it.
+ if (view instanceof ViewGroup) {
+ return childrenNeedInversion(background, (ViewGroup) view);
+ } else {
+ return false;
+ }
+ }
+
+ private boolean childrenNeedInversion(@ColorInt int parentBackground, ViewGroup viewGroup) {
+ if (viewGroup == null) {
+ return false;
+ }
+
+ for (int i = 0; i < viewGroup.getChildCount(); i++) {
+ View child = viewGroup.getChildAt(i);
+ int backgroundColor = getBackgroundColor(viewGroup);
+ if (backgroundColor == Color.TRANSPARENT) {
+ backgroundColor = parentBackground;
}
+ if (child instanceof TextView) {
+ int foreground = ((TextView) child).getCurrentTextColor();
+ if (ColorUtils.calculateContrast(foreground, backgroundColor) < 3) {
+ return true;
+ }
+ } else if (child instanceof ViewGroup) {
+ if (childrenNeedInversion(backgroundColor, (ViewGroup) child)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ protected int getBackgroundColor(View view) {
+ if (view == null) {
+ return Color.TRANSPARENT;
}
+ Drawable background = view.getBackground();
+ if (background instanceof ColorDrawable) {
+ return ((ColorDrawable) background).getColor();
+ }
+ return Color.TRANSPARENT;
+ }
+
+ protected void invertViewLuminosity(View view) {
+ Paint paint = new Paint();
+ ColorMatrix matrix = new ColorMatrix();
+ ColorMatrix tmp = new ColorMatrix();
+ // Inversion should happen on Y'UV space to conserve the colors and
+ // only affect the luminosity.
+ matrix.setRGB2YUV();
+ tmp.set(new float[]{
+ -1f, 0f, 0f, 0f, 255f,
+ 0f, 1f, 0f, 0f, 0f,
+ 0f, 0f, 1f, 0f, 0f,
+ 0f, 0f, 0f, 1f, 0f
+ });
+ matrix.postConcat(tmp);
+ tmp.setYUV2RGB();
+ matrix.postConcat(tmp);
+ paint.setColorFilter(new ColorMatrixColorFilter(matrix));
+ view.setLayerType(View.LAYER_TYPE_HARDWARE, paint);
}
protected boolean shouldClearBackgroundOnReapply() {