Reduce hardware render sizes for ExpandableNotificationRow.
Do not create a hardware layer for entire notifications during shade expand/collapse; instead just layer the elements with actually overlapping rendering. Bug: 191969252 Test: lots of shade expansion; use of perfetto to validate phone reaches rendering deadlines more often. Merged-In: I86b626fb61c5844b968be33d982e418bf8938de8 Change-Id: I86b626fb61c5844b968be33d982e418bf8938de8
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -87,6 +87,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;
|
||||
@@ -125,7 +126,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;
|
||||
@@ -138,6 +140,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.
|
||||
@@ -2753,17 +2756,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()) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
@@ -71,7 +72,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);
|
||||
@@ -1994,4 +1995,39 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user