summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jeff DeCew <jeffdq@google.com> 2021-11-24 14:24:18 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2021-11-24 14:24:18 +0000
commitcb9390f8726b049b99b21e124a8bcc1f52941e0f (patch)
tree2dc0e6713f82815aa2f520115735ab08557ed4b1
parentb06ff485a597b4d22cc783162f1c8f6fe9d73f4c (diff)
parent8639dd9756cddaac29c61d83dcdc666c7fea6a8c (diff)
Merge "Reduce hardware render sizes for ExpandableNotificationRow."
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFadeAware.java70
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java104
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java38
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapper.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationDecoratedCustomViewWrapper.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapper.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java21
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java29
12 files changed, 321 insertions, 14 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFadeAware.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFadeAware.java
new file mode 100644
index 000000000000..8d2e3c92c92a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationFadeAware.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2021 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;
+
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+/**
+ * Used to let views that have an alpha not apply the HARDWARE layer type directly, and instead
+ * delegate that to specific children. This is useful if we want to fake not having overlapping
+ * rendering to avoid layer trashing, when fading out a view that is also changing.
+ */
+public interface NotificationFadeAware {
+ /**
+ * Calls {@link View#setLayerType} with {@link View#LAYER_TYPE_HARDWARE} if faded and
+ * {@link View#LAYER_TYPE_NONE} otherwise.
+ */
+ static void setLayerTypeForFaded(@Nullable View view, boolean faded) {
+ if (view != null) {
+ int newLayerType = faded ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE;
+ view.setLayerType(newLayerType, null);
+ }
+ }
+
+ /**
+ * Used like {@link View#setLayerType} with {@link View#LAYER_TYPE_HARDWARE} or
+ * {@link View#LAYER_TYPE_NONE} except that instead of necessarily affecting this view
+ * specifically, this may delegate the call to child views.
+ *
+ * When set to <code>true</code>, the view has two possible paths:
+ * 1. If a hardware layer is required to ensure correct appearance of this view, then
+ * set that layer type.
+ * 2. Otherwise, delegate this call to children, who might make that call for themselves.
+ *
+ * When set to <code>false</code>, the view should undo the above, typically by calling
+ * {@link View#setLayerType} with {@link View#LAYER_TYPE_NONE} on itself and children, and
+ * delegating to this method on children where implemented.
+ *
+ * When this delegates to {@link View#setLayerType} on this view or a subview, `null` will be
+ * passed for the `paint` argument of that call.
+ */
+ void setNotificationFaded(boolean faded);
+
+ /**
+ * Interface for the top level notification view that fades and optimizes that through deep
+ * awareness of individual components.
+ */
+ interface FadeOptimizedNotification extends NotificationFadeAware {
+ /** Top-level feature switch */
+ boolean FADE_LAYER_OPTIMIZATION_ENABLED = true;
+
+ /** Determine if the notification is currently faded. */
+ boolean isNotificationFaded();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 9f10322b5fa3..4a8a4fe25eb1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -92,6 +92,7 @@ import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.AboveShelfChangedListener;
import com.android.systemui.statusbar.notification.ExpandAnimationParameters;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorController;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -131,7 +132,8 @@ import java.util.function.Consumer;
* the group summary (which contains 1 or more child notifications).
*/
public class ExpandableNotificationRow extends ActivatableNotificationView
- implements PluginListener<NotificationMenuRowPlugin>, SwipeableView {
+ implements PluginListener<NotificationMenuRowPlugin>, SwipeableView,
+ NotificationFadeAware.FadeOptimizedNotification {
private static final boolean DEBUG = false;
private static final int DEFAULT_DIVIDER_ALPHA = 0x29;
@@ -144,6 +146,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
private boolean mUpdateBackgroundOnUpdate;
private boolean mNotificationTranslationFinished = false;
private boolean mIsSnoozed;
+ private boolean mIsFaded;
/**
* Listener for when {@link ExpandableNotificationRow} is laid out.
@@ -2774,17 +2777,112 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
// alphas are reset
if (mChildrenContainer != null) {
mChildrenContainer.setAlpha(1.0f);
- mChildrenContainer.setLayerType(LAYER_TYPE_NONE, null);
}
for (NotificationContentView l : mLayouts) {
l.setAlpha(1.0f);
- l.setLayerType(LAYER_TYPE_NONE, null);
+ }
+ if (FADE_LAYER_OPTIMIZATION_ENABLED) {
+ setNotificationFaded(false);
+ } else {
+ setNotificationFadedOnChildren(false);
}
} else {
setHeadsUpAnimatingAway(false);
}
}
+ /** Gets the last value set with {@link #setNotificationFaded(boolean)} */
+ @Override
+ public boolean isNotificationFaded() {
+ return mIsFaded;
+ }
+
+ /**
+ * This class needs to delegate the faded state set on it by
+ * {@link com.android.systemui.statusbar.notification.stack.ViewState} to its children.
+ * Having each notification use layerType of HARDWARE anytime it fades in/out can result in
+ * extremely large layers (in the case of groups, it can even exceed the device height).
+ * Because these large renders can cause serious jank when rendering, we instead have
+ * notifications return false from {@link #hasOverlappingRendering()} and delegate the
+ * layerType to child views which really need it in order to render correctly, such as icon
+ * views or the conversation face pile.
+ *
+ * Another compounding factor for notifications is that we change clipping on each frame of the
+ * animation, so the hardware layer isn't able to do any caching at the top level, but the
+ * individual elements we render with hardware layers (e.g. icons) cache wonderfully because we
+ * never invalidate them.
+ */
+ @Override
+ public void setNotificationFaded(boolean faded) {
+ mIsFaded = faded;
+ if (childrenRequireOverlappingRendering()) {
+ // == Simple Scenario ==
+ // If a child (like remote input) needs this to have overlapping rendering, then set
+ // the layerType of this view and reset the children to render as if the notification is
+ // not fading.
+ NotificationFadeAware.setLayerTypeForFaded(this, faded);
+ setNotificationFadedOnChildren(false);
+ } else {
+ // == Delegating Scenario ==
+ // This is the new normal for alpha: Explicitly reset this view's layer type to NONE,
+ // and require that all children use their own hardware layer if they have bad
+ // overlapping rendering.
+ NotificationFadeAware.setLayerTypeForFaded(this, false);
+ setNotificationFadedOnChildren(faded);
+ }
+ }
+
+ /** Private helper for iterating over the layouts and children containers to set faded state */
+ private void setNotificationFadedOnChildren(boolean faded) {
+ delegateNotificationFaded(mChildrenContainer, faded);
+ for (NotificationContentView layout : mLayouts) {
+ delegateNotificationFaded(layout, faded);
+ }
+ }
+
+ private static void delegateNotificationFaded(@Nullable View view, boolean faded) {
+ if (FADE_LAYER_OPTIMIZATION_ENABLED && view instanceof NotificationFadeAware) {
+ ((NotificationFadeAware) view).setNotificationFaded(faded);
+ } else {
+ NotificationFadeAware.setLayerTypeForFaded(view, faded);
+ }
+ }
+
+ /**
+ * Only declare overlapping rendering if independent children of the view require it.
+ */
+ @Override
+ public boolean hasOverlappingRendering() {
+ return super.hasOverlappingRendering() && childrenRequireOverlappingRendering();
+ }
+
+ /**
+ * Because RemoteInputView is designed to be an opaque view that overlaps the Actions row, the
+ * row should require overlapping rendering to ensure that the overlapped view doesn't bleed
+ * through when alpha fading.
+ *
+ * Note that this currently works for top-level notifications which squish their height down
+ * while collapsing the shade, but does not work for children inside groups, because the
+ * accordion affect does not apply to those views, so super.hasOverlappingRendering() will
+ * always return false to avoid the clipping caused when the view's measured height is less than
+ * the 'actual height'.
+ */
+ private boolean childrenRequireOverlappingRendering() {
+ if (!FADE_LAYER_OPTIMIZATION_ENABLED) {
+ return true;
+ }
+ // The colorized background is another layer with which all other elements overlap
+ if (getEntry().getSbn().getNotification().isColorized()) {
+ return true;
+ }
+ // Check if the showing layout has a need for overlapping rendering.
+ // NOTE: We could check both public and private layouts here, but becuause these states
+ // don't animate well, there are bigger visual artifacts if we start changing the shown
+ // layout during shade expansion.
+ NotificationContentView showingLayout = getShowingLayout();
+ return showingLayout != null && showingLayout.requireRowToHaveOverlappingRendering();
+ }
+
@Override
public int getExtraBottomPadding() {
if (mIsSummaryWithChildren && isGroupExpanded()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
index caba3ac7e17b..c66140822d92 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridConversationNotificationView.java
@@ -28,6 +28,7 @@ import android.widget.TextView;
import com.android.internal.widget.ConversationLayout;
import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
/**
* A hybrid view which may contain information about one ore more conversations.
@@ -138,4 +139,14 @@ public class HybridConversationNotificationView extends HybridNotificationView {
lp.height = size;
view.setLayoutParams(lp);
}
+
+ /**
+ * Apply the faded state as a layer type change to the face pile view which needs to have
+ * overlapping contents render precisely.
+ */
+ @Override
+ public void setNotificationFaded(boolean faded) {
+ super.setNotificationFaded(faded);
+ NotificationFadeAware.setLayerTypeForFaded(mConversationFacePile, faded);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java
index bc2adac31d07..c0d85a6a16ef 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/HybridNotificationView.java
@@ -28,13 +28,14 @@ import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
import com.android.systemui.statusbar.ViewTransformationHelper;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
import com.android.systemui.statusbar.notification.TransformState;
/**
* A hybrid view which may contain information about one ore more notifications.
*/
public class HybridNotificationView extends AlphaOptimizedLinearLayout
- implements TransformableView {
+ implements TransformableView, NotificationFadeAware {
protected final ViewTransformationHelper mTransformationHelper = new ViewTransformationHelper();
protected TextView mTitleView;
@@ -148,4 +149,7 @@ public class HybridNotificationView extends AlphaOptimizedLinearLayout
setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
mTransformationHelper.setVisible(visible);
}
+
+ @Override
+ public void setNotificationFaded(boolean faded) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
index 727f0e55f58f..438992e22577 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java
@@ -46,6 +46,7 @@ import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
import com.android.systemui.statusbar.RemoteInputController;
import com.android.systemui.statusbar.SmartReplyController;
import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
@@ -73,7 +74,7 @@ import java.util.List;
* expanded and heads up layout. This class is responsible for clipping the content and and
* switching between the expanded, contracted and the heads up view depending on its clipped size.
*/
-public class NotificationContentView extends FrameLayout {
+public class NotificationContentView extends FrameLayout implements NotificationFadeAware {
private static final String TAG = "NotificationContentView";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
@@ -2045,6 +2046,41 @@ public class NotificationContentView extends FrameLayout {
return Notification.COLOR_INVALID;
}
+ /**
+ * Delegate the faded state to the notification content views which actually
+ * need to have overlapping contents render precisely.
+ */
+ @Override
+ public void setNotificationFaded(boolean faded) {
+ if (mContractedWrapper != null) {
+ mContractedWrapper.setNotificationFaded(faded);
+ }
+ if (mHeadsUpWrapper != null) {
+ mHeadsUpWrapper.setNotificationFaded(faded);
+ }
+ if (mExpandedWrapper != null) {
+ mExpandedWrapper.setNotificationFaded(faded);
+ }
+ if (mSingleLineView != null) {
+ mSingleLineView.setNotificationFaded(faded);
+ }
+ }
+
+ /**
+ * @return true if a visible view has a remote input active, as this requires that the entire
+ * row report that it has overlapping rendering.
+ */
+ public boolean requireRowToHaveOverlappingRendering() {
+ // This inexpensive check is done on both states to avoid state invalidating the result.
+ if (mHeadsUpRemoteInput != null && mHeadsUpRemoteInput.isActive()) {
+ return true;
+ }
+ if (mExpandedRemoteInput != null && mExpandedRemoteInput.isActive()) {
+ return true;
+ }
+ return false;
+ }
+
public void setRemoteInputViewSubcomponentFactory(RemoteInputViewSubcomponent.Factory factory) {
mRemoteInputSubcomponentFactory = factory;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt
index 12e94cbc1ab9..bb43b95357db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCallTemplateViewWrapper.kt
@@ -21,6 +21,7 @@ import android.view.View
import com.android.internal.widget.CachingIconView
import com.android.internal.widget.CallLayout
import com.android.systemui.R
+import com.android.systemui.statusbar.notification.NotificationFadeAware
import com.android.systemui.statusbar.notification.NotificationUtils
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
@@ -37,6 +38,7 @@ class NotificationCallTemplateViewWrapper constructor(
NotificationUtils.getFontScaledHeight(ctx, R.dimen.notification_max_height)
private val callLayout: CallLayout = view as CallLayout
+ private lateinit var conversationIconContainer: View
private lateinit var conversationIconView: CachingIconView
private lateinit var conversationBadgeBg: View
private lateinit var expandBtn: View
@@ -45,6 +47,8 @@ class NotificationCallTemplateViewWrapper constructor(
private fun resolveViews() {
with(callLayout) {
+ conversationIconContainer =
+ requireViewById(com.android.internal.R.id.conversation_icon_container)
conversationIconView = requireViewById(com.android.internal.R.id.conversation_icon)
conversationBadgeBg =
requireViewById(com.android.internal.R.id.conversation_icon_badge_bg)
@@ -82,4 +86,14 @@ class NotificationCallTemplateViewWrapper constructor(
}
override fun getMinLayoutHeight(): Int = minHeightWithActions
+
+ /**
+ * Apply the faded state as a layer type change to the face pile view which needs to have
+ * overlapping contents render precisely.
+ */
+ override fun setNotificationFaded(faded: Boolean) {
+ // Do not call super
+ NotificationFadeAware.setLayerTypeForFaded(expandBtn, faded)
+ NotificationFadeAware.setLayerTypeForFaded(conversationIconContainer, faded)
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
index 3ef5b665d778..e136055b80b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationConversationTemplateViewWrapper.kt
@@ -23,6 +23,7 @@ import com.android.internal.widget.CachingIconView
import com.android.internal.widget.ConversationLayout
import com.android.internal.widget.MessagingLinearLayout
import com.android.systemui.R
+import com.android.systemui.statusbar.notification.NotificationFadeAware
import com.android.systemui.statusbar.notification.NotificationUtils
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.wrapper.NotificationMessagingTemplateViewWrapper.setCustomImageMessageTransform
@@ -42,6 +43,7 @@ class NotificationConversationTemplateViewWrapper constructor(
)
private val conversationLayout: ConversationLayout = view as ConversationLayout
+ private lateinit var conversationIconContainer: View
private lateinit var conversationIconView: CachingIconView
private lateinit var conversationBadgeBg: View
private lateinit var expandBtn: View
@@ -59,6 +61,8 @@ class NotificationConversationTemplateViewWrapper constructor(
messagingLinearLayout = conversationLayout.messagingLinearLayout
imageMessageContainer = conversationLayout.imageMessageContainer
with(conversationLayout) {
+ conversationIconContainer =
+ requireViewById(com.android.internal.R.id.conversation_icon_container)
conversationIconView = requireViewById(com.android.internal.R.id.conversation_icon)
conversationBadgeBg =
requireViewById(com.android.internal.R.id.conversation_icon_badge_bg)
@@ -136,4 +140,10 @@ class NotificationConversationTemplateViewWrapper constructor(
minHeightWithActions
else
super.getMinLayoutHeight()
+
+ override fun setNotificationFaded(faded: Boolean) {
+ // Do not call super
+ NotificationFadeAware.setLayerTypeForFaded(expandBtn, faded)
+ NotificationFadeAware.setLayerTypeForFaded(conversationIconContainer, faded)
+ }
}
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 4c9c2f95b35c..fdff12d22354 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
@@ -22,6 +22,7 @@ import android.view.View;
import com.android.internal.graphics.ColorUtils;
import com.android.systemui.R;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
/**
@@ -86,4 +87,14 @@ public class NotificationCustomViewWrapper extends NotificationViewWrapper {
public boolean shouldClipToRounding(boolean topRounded, boolean bottomRounded) {
return true;
}
+
+ /**
+ * Apply the faded state as a layer type change to the custom view which needs to have
+ * overlapping contents render precisely.
+ */
+ @Override
+ public void setNotificationFaded(boolean faded) {
+ super.setNotificationFaded(faded);
+ NotificationFadeAware.setLayerTypeForFaded(mView, faded);
+ }
}
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 8c6fa023d92b..31595397b9b0 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
@@ -20,6 +20,7 @@ import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
/**
@@ -67,4 +68,14 @@ public class NotificationDecoratedCustomViewWrapper extends NotificationTemplate
}
super.onContentUpdated(row);
}
+
+ /**
+ * Apply the faded state as a layer type change to the custom view which needs to have
+ * overlapping contents render precisely.
+ */
+ @Override
+ public void setNotificationFaded(boolean faded) {
+ super.setNotificationFaded(faded);
+ NotificationFadeAware.setLayerTypeForFaded(mWrappedView, faded);
+ }
}
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 76301917b458..6c3e0d2f798b 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
@@ -42,6 +42,7 @@ import com.android.internal.widget.CachingIconView;
import com.android.settingslib.Utils;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.TransformableView;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
import com.android.systemui.statusbar.notification.TransformState;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -395,4 +396,13 @@ public abstract class NotificationViewWrapper implements TransformableView {
*/
public void setRecentlyAudiblyAlerted(boolean audiblyAlerted) {
}
+
+ /**
+ * Apply the faded state as a layer type change to the views which need to have overlapping
+ * contents render precisely.
+ */
+ public void setNotificationFaded(boolean faded) {
+ NotificationFadeAware.setLayerTypeForFaded(getIcon(), faded);
+ NotificationFadeAware.setLayerTypeForFaded(getExpandButton(), faded);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
index a4727106c5fa..a1aed46ca8a6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java
@@ -38,6 +38,7 @@ import com.android.internal.widget.NotificationExpandButton;
import com.android.systemui.R;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.NotificationGroupingUtil;
+import com.android.systemui.statusbar.notification.NotificationFadeAware;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
@@ -51,7 +52,8 @@ import java.util.List;
/**
* A container containing child notifications
*/
-public class NotificationChildrenContainer extends ViewGroup {
+public class NotificationChildrenContainer extends ViewGroup
+ implements NotificationFadeAware {
@VisibleForTesting
static final int NUMBER_OF_CHILDREN_WHEN_COLLAPSED = 2;
@@ -111,6 +113,7 @@ public class NotificationChildrenContainer extends ViewGroup {
private int mCurrentHeaderTranslation = 0;
private float mHeaderVisibleAmount = 1.0f;
private int mUntruncatedChildCount;
+ private boolean mContainingNotificationIsFaded = false;
public NotificationChildrenContainer(Context context) {
this(context, null);
@@ -277,6 +280,7 @@ public class NotificationChildrenContainer extends ViewGroup {
mDividers.add(newIndex, divider);
row.setContentTransformationAmount(0, false /* isLastChild */);
+ row.setNotificationFaded(mContainingNotificationIsFaded);
// It doesn't make sense to keep old animations around, lets cancel them!
ExpandableViewState viewState = row.getViewState();
if (viewState != null) {
@@ -301,6 +305,7 @@ public class NotificationChildrenContainer extends ViewGroup {
});
row.setSystemChildExpanded(false);
+ row.setNotificationFaded(false);
row.setUserLocked(false);
if (!row.isRemoved()) {
mGroupingUtil.restoreChildNotification(row);
@@ -1308,4 +1313,18 @@ public class NotificationChildrenContainer extends ViewGroup {
mNotificationHeaderWrapperLowPriority.setRecentlyAudiblyAlerted(audiblyAlertedRecently);
}
}
+
+ @Override
+ public void setNotificationFaded(boolean faded) {
+ mContainingNotificationIsFaded = faded;
+ if (mNotificationHeaderWrapper != null) {
+ mNotificationHeaderWrapper.setNotificationFaded(faded);
+ }
+ if (mNotificationHeaderWrapperLowPriority != null) {
+ mNotificationHeaderWrapperLowPriority.setNotificationFaded(faded);
+ }
+ for (ExpandableNotificationRow child : mAttachedChildren) {
+ child.setNotificationFaded(faded);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
index 6d82a45313d1..83bea84c8d33 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ViewState.java
@@ -29,6 +29,7 @@ import com.android.systemui.Dumpable;
import com.android.systemui.R;
import com.android.systemui.animation.Interpolators;
import com.android.systemui.statusbar.notification.AnimatableProperty;
+import com.android.systemui.statusbar.notification.NotificationFadeAware.FadeOptimizedNotification;
import com.android.systemui.statusbar.notification.PropertyAnimator;
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.policy.HeadsUpUtil;
@@ -206,14 +207,26 @@ public class ViewState implements Dumpable {
} else if (view.getAlpha() != this.alpha) {
// apply layer type
boolean becomesFullyVisible = this.alpha == 1.0f;
- boolean newLayerTypeIsHardware = !becomesInvisible && !becomesFullyVisible
- && view.hasOverlappingRendering();
- int layerType = view.getLayerType();
- int newLayerType = newLayerTypeIsHardware
- ? View.LAYER_TYPE_HARDWARE
- : View.LAYER_TYPE_NONE;
- if (layerType != newLayerType) {
- view.setLayerType(newLayerType, null);
+ boolean becomesFaded = !becomesInvisible && !becomesFullyVisible;
+ if (FadeOptimizedNotification.FADE_LAYER_OPTIMIZATION_ENABLED
+ && view instanceof FadeOptimizedNotification) {
+ // NOTE: A view that's going to utilize this interface to avoid having a hardware
+ // layer will have to return false from hasOverlappingRendering(), so we
+ // intentionally do not check that value in this if, even though we do in the else.
+ FadeOptimizedNotification fadeOptimizedView = (FadeOptimizedNotification) view;
+ boolean isFaded = fadeOptimizedView.isNotificationFaded();
+ if (isFaded != becomesFaded) {
+ fadeOptimizedView.setNotificationFaded(becomesFaded);
+ }
+ } else {
+ boolean newLayerTypeIsHardware = becomesFaded && view.hasOverlappingRendering();
+ int layerType = view.getLayerType();
+ int newLayerType = newLayerTypeIsHardware
+ ? View.LAYER_TYPE_HARDWARE
+ : View.LAYER_TYPE_NONE;
+ if (layerType != newLayerType) {
+ view.setLayerType(newLayerType, null);
+ }
}
// apply alpha