summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yining Liu <liuyining@google.com> 2023-10-30 20:32:28 +0000
committer Yining Liu <liuyining@google.com> 2024-02-29 18:41:46 +0000
commit4ebf7432155bc8d704486a8e90ff9ea6b15b61a9 (patch)
tree648e4f18ec4ab5a5bd8b7dd9228598442d64c341
parente437c58869fffd9a192184a2d036ab42bbb372a5 (diff)
Move group notification summary header view inflation to the background thread
Move the group notification summary header view inflation to the background thread to reduce janks and improve the performance of System UI. Bug: 217799515 Test: atest NotificationChildrenContainerTest Flag: ACONFIG notification_async_group_header_inflation DEVELOPMENT Change-Id: I7124e909add1efa964f6b4d6f0effdc309fc1d1d
-rw-r--r--core/java/android/service/notification/StatusBarNotification.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java61
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java123
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterLogger.kt8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainer.java177
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt34
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java99
15 files changed, 545 insertions, 39 deletions
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 264b53c6ee40..d8210742e331 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -174,6 +174,23 @@ public class StatusBarNotification implements Parcelable {
return sbnKey;
}
+ /**
+ * @return Whether the Entry is a group child by the app or system
+ * @hide
+ */
+ public boolean isAppOrSystemGroupChild() {
+ return isGroup() && !getNotification().isGroupSummary();
+ }
+
+
+ /**
+ * @return Whether the Entry is a group summary by the app or system
+ * @hide
+ */
+ public boolean isAppOrSystemGroupSummary() {
+ return isGroup() && getNotification().isGroupSummary();
+ }
+
private String groupKey() {
if (overrideGroupKey != null) {
return user.getIdentifier() + "|" + pkg + "|" + "g:" + overrideGroupKey;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
index 143fc324f8c7..3cf61e211e42 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGroupingUtil.java
@@ -34,6 +34,8 @@ import com.android.internal.widget.ConversationLayout;
import com.android.internal.widget.ImageFloatingTextView;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationContentView;
+import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
+import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import java.util.ArrayList;
import java.util.HashSet;
@@ -253,7 +255,8 @@ public class NotificationGroupingUtil {
}
public void init() {
- View header = mParentRow.getNotificationViewWrapper().getNotificationHeader();
+ NotificationViewWrapper wrapper = mParentRow.getNotificationViewWrapper();
+ View header = wrapper == null ? null : wrapper.getNotificationHeader();
mParentView = header == null ? null : header.findViewById(mId);
mParentData = mExtractor == null ? null : mExtractor.extractData(mParentRow);
mApply = !mComparator.isEmpty(mParentView);
@@ -326,6 +329,9 @@ public class NotificationGroupingUtil {
@Override
public boolean isEmpty(View view) {
+ if (AsyncGroupHeaderViewInflation.isEnabled() && view == null) {
+ return true;
+ }
if (view instanceof ImageView) {
return ((ImageView) view).getDrawable() == null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
index 639e23ae0765..deaf1d1bc764 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinator.java
@@ -363,10 +363,11 @@ public class PreparationCoordinator implements Coordinator {
NotifInflater.Params getInflaterParams(NotifUiAdjustment adjustment, String reason) {
return new NotifInflater.Params(
- adjustment.isMinimized(),
- reason,
- adjustment.isSnoozeEnabled(),
- adjustment.isChildInGroup()
+ /* isLowPriority = */ adjustment.isMinimized(),
+ /* reason = */ reason,
+ /* showSnooze = */ adjustment.isSnoozeEnabled(),
+ /* isChildInGroup = */ adjustment.isChildInGroup(),
+ /* isGroupSummary = */ adjustment.isGroupSummary()
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
index c0b187be42f3..18460c3e3766 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifInflater.kt
@@ -60,5 +60,6 @@ interface NotifInflater {
val reason: String,
val showSnooze: Boolean,
val isChildInGroup: Boolean = false,
+ val isGroupSummary: Boolean = false,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt
index e1d2cdc65d5a..bab94b50018e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustment.kt
@@ -20,6 +20,7 @@ import android.app.Notification
import android.app.RemoteInput
import android.graphics.drawable.Icon
import android.text.TextUtils
+import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
/**
@@ -36,6 +37,7 @@ class NotifUiAdjustment internal constructor(
val isMinimized: Boolean,
val needsRedaction: Boolean,
val isChildInGroup: Boolean,
+ val isGroupSummary: Boolean,
) {
companion object {
@JvmStatic
@@ -55,6 +57,8 @@ class NotifUiAdjustment internal constructor(
// !oldAdjustment.isChildInGroup && newAdjustment.isChildInGroup -> true
AsyncHybridViewInflation.isEnabled &&
oldAdjustment.isChildInGroup != newAdjustment.isChildInGroup -> true
+ AsyncGroupHeaderViewInflation.isEnabled &&
+ !oldAdjustment.isGroupSummary && newAdjustment.isGroupSummary -> true
else -> false
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
index 6f44c13a3e71..0b9d19df3a75 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProvider.kt
@@ -123,6 +123,7 @@ class NotifUiAdjustmentProvider @Inject constructor(
isSnoozeEnabled = isSnoozeSettingsEnabled && !entry.isCanceled,
isMinimized = isEntryMinimized(entry),
needsRedaction = lockscreenUserManager.needsRedaction(entry),
- isChildInGroup = groupMembershipManager.isChildInGroup(entry),
+ isChildInGroup = entry.sbn.isAppOrSystemGroupChild,
+ isGroupSummary = entry.sbn.isAppOrSystemGroupSummary,
)
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
index 954e80505cbe..c5b55c7b1d9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/inflation/NotificationRowBinderImpl.java
@@ -21,6 +21,8 @@ import static com.android.systemui.statusbar.notification.row.NotificationRowCon
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_EXPANDED;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC;
import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_GROUP_SUMMARY_HEADER;
+import static com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER;
import static java.util.Objects.requireNonNull;
@@ -50,6 +52,7 @@ import com.android.systemui.statusbar.notification.row.RowContentBindParams;
import com.android.systemui.statusbar.notification.row.RowContentBindStage;
import com.android.systemui.statusbar.notification.row.RowInflaterTask;
import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
+import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation;
import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -271,6 +274,17 @@ public class NotificationRowBinderImpl implements NotificationRowBinder {
}
}
+ if (AsyncGroupHeaderViewInflation.isEnabled()) {
+ if (inflaterParams.isGroupSummary()) {
+ params.requireContentViews(FLAG_GROUP_SUMMARY_HEADER);
+ if (isLowPriority) {
+ params.requireContentViews(FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER);
+ }
+ } else {
+ params.markContentViewsFreeable(FLAG_GROUP_SUMMARY_HEADER);
+ params.markContentViewsFreeable(FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER);
+ }
+ }
params.rebindAllContentViews();
mLogger.logRequestingRebind(entry, inflaterParams);
mRowContentBindStage.requestRebind(entry, en -> {
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 decb244947ff..d987a278fc71 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
@@ -100,6 +100,7 @@ import com.android.systemui.statusbar.notification.collection.render.GroupMember
import com.android.systemui.statusbar.notification.logging.NotificationCounters;
import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
+import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
import com.android.systemui.statusbar.notification.stack.AmbientState;
import com.android.systemui.statusbar.notification.stack.AnimationProperties;
@@ -586,7 +587,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mMenuRow.setAppName(mAppName);
}
if (mIsSummaryWithChildren) {
- mChildrenContainer.recreateNotificationHeader(mExpandClickListener, isConversation());
+ if (!AsyncGroupHeaderViewInflation.isEnabled()) {
+ // We create the header from the background thread instead
+ mChildrenContainer.recreateNotificationHeader(mExpandClickListener,
+ isConversation());
+ }
mChildrenContainer.onNotificationUpdated();
}
if (mAnimationRunning) {
@@ -668,7 +673,9 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public int getOriginalIconColor() {
if (mIsSummaryWithChildren && !shouldShowPublic()) {
- return mChildrenContainer.getVisibleWrapper().getOriginalIconColor();
+ if (!AsyncGroupHeaderViewInflation.isEnabled()) {
+ return mChildrenContainer.getVisibleWrapper().getOriginalIconColor();
+ }
}
int color = getShowingLayout().getOriginalIconColor();
if (color != Notification.COLOR_INVALID) {
@@ -1513,6 +1520,40 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return mChildrenContainer;
}
+ /**
+ * @return An non-null instance of mChildrenContainer, inflate it if not yet.
+ */
+ public @NonNull NotificationChildrenContainer getChildrenContainerNonNull() {
+ if (mChildrenContainer == null) {
+ mChildrenContainerStub.inflate();
+ }
+ return mChildrenContainer;
+ }
+
+ /**
+ * Set the group notification header view
+ * @param headerView header view to set
+ */
+ public void setGroupHeader(NotificationHeaderView headerView) {
+ NotificationChildrenContainer childrenContainer = getChildrenContainerNonNull();
+ childrenContainer.setGroupHeader(
+ /* headerView= */ headerView,
+ /* onClickListener= */ mExpandClickListener
+ );
+ }
+
+ /**
+ * Set the low-priority group notification header view
+ * @param headerView header view to set
+ */
+ public void setLowPriorityGroupHeader(NotificationHeaderView headerView) {
+ NotificationChildrenContainer childrenContainer = getChildrenContainerNonNull();
+ childrenContainer.setLowPriorityGroupHeader(
+ /* headerViewLowPriority= */ headerView,
+ /* onClickListener= */ mExpandClickListener
+ );
+ }
+
public void setHeadsUpAnimatingAway(boolean headsUpAnimatingAway) {
boolean wasAboveShelf = isAboveShelf();
boolean changed = headsUpAnimatingAway != mHeadsupDisappearRunning;
@@ -1565,7 +1606,11 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
@Override
public View getShelfTransformationTarget() {
if (mIsSummaryWithChildren && !shouldShowPublic()) {
- return mChildrenContainer.getVisibleWrapper().getShelfTransformationTarget();
+ NotificationViewWrapper viewWrapper = mChildrenContainer.getVisibleWrapper();
+ if (AsyncGroupHeaderViewInflation.isEnabled() && viewWrapper == null) {
+ return null;
+ }
+ return viewWrapper.getShelfTransformationTarget();
}
return getShowingLayout().getShelfTransformationTarget();
}
@@ -2710,10 +2755,12 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
&& mChildrenContainer.getNotificationChildCount() > 0;
if (mIsSummaryWithChildren) {
Trace.beginSection("ExpNotRow#onChildCountChanged (summary)");
- NotificationViewWrapper wrapper = mChildrenContainer.getNotificationViewWrapper();
- if (wrapper == null || wrapper.getNotificationHeader() == null) {
- mChildrenContainer.recreateNotificationHeader(mExpandClickListener,
- isConversation());
+ if (!AsyncGroupHeaderViewInflation.isEnabled()) {
+ NotificationViewWrapper wrapper = mChildrenContainer.getNotificationViewWrapper();
+ if (wrapper == null || wrapper.getNotificationHeader() == null) {
+ mChildrenContainer.recreateNotificationHeader(mExpandClickListener,
+ isConversation());
+ }
}
}
if (!mIsSummaryWithChildren && wasSummary) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
index e288e857bf4a..d308fa583f71 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflater.java
@@ -37,7 +37,9 @@ import android.os.Trace;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.util.Log;
+import android.view.NotificationHeaderView;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.RemoteViews;
import com.android.internal.annotations.VisibleForTesting;
@@ -51,11 +53,13 @@ import com.android.systemui.statusbar.NotificationRemoteInputManager;
import com.android.systemui.statusbar.notification.ConversationNotificationProcessor;
import com.android.systemui.statusbar.notification.InflationException;
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation;
import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineConversationViewBinder;
import com.android.systemui.statusbar.notification.row.ui.viewbinder.SingleLineViewBinder;
import com.android.systemui.statusbar.notification.row.ui.viewmodel.SingleLineViewModel;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
+import com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer;
import com.android.systemui.statusbar.phone.CentralSurfaces;
import com.android.systemui.statusbar.policy.InflatedSmartReplyState;
import com.android.systemui.statusbar.policy.InflatedSmartReplyViewHolder;
@@ -387,6 +391,21 @@ public class NotificationContentInflater implements NotificationRowContentBinder
logger.logAsyncTaskProgress(entryForLogging, "creating public remote view");
result.newPublicView = builder.makePublicContentView(isLowPriority);
}
+
+ if (AsyncGroupHeaderViewInflation.isEnabled()) {
+ if ((reInflateFlags & FLAG_GROUP_SUMMARY_HEADER) != 0) {
+ logger.logAsyncTaskProgress(entryForLogging,
+ "creating group summary remote view");
+ result.mNewGroupHeaderView = builder.makeNotificationGroupHeader();
+ }
+
+ if ((reInflateFlags & FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER) != 0) {
+ logger.logAsyncTaskProgress(entryForLogging,
+ "creating low-priority group summary remote view");
+ result.mNewLowPriorityGroupHeaderView =
+ builder.makeLowPriorityContentView(true /* useRegularSubtext */);
+ }
+ }
setNotifsViewsInflaterFactory(result, row, notifLayoutInflaterFactoryProvider);
result.packageContext = packageContext;
result.headsUpStatusBarText = builder.getHeadsUpStatusBarText(false /* showingPublic */);
@@ -534,6 +553,67 @@ public class NotificationContentInflater implements NotificationRowContentBinder
runningInflations, applyCallback, logger);
}
+ if (AsyncGroupHeaderViewInflation.isEnabled()) {
+ NotificationChildrenContainer childrenContainer = row.getChildrenContainerNonNull();
+ if ((reInflateFlags & FLAG_GROUP_SUMMARY_HEADER) != 0) {
+ boolean isNewView =
+ !canReapplyRemoteView(
+ /* newView = */ result.mNewGroupHeaderView,
+ /* oldView = */ remoteViewCache
+ .getCachedView(entry, FLAG_GROUP_SUMMARY_HEADER));
+ ApplyCallback applyCallback = new ApplyCallback() {
+ @Override
+ public void setResultView(View v) {
+ logger.logAsyncTaskProgress(entry, "group header view applied");
+ result.mInflatedGroupHeaderView = (NotificationHeaderView) v;
+ }
+
+ @Override
+ public RemoteViews getRemoteView() {
+ return result.mNewGroupHeaderView;
+ }
+ };
+ logger.logAsyncTaskProgress(entry, "applying group header view");
+ applyRemoteView(inflationExecutor, inflateSynchronously, result, reInflateFlags,
+ /* inflationId = */ FLAG_GROUP_SUMMARY_HEADER,
+ remoteViewCache, entry, row, isNewView, remoteViewClickHandler, callback,
+ /* parentLayout = */ childrenContainer,
+ /* existingView = */ childrenContainer.getNotificationHeader(),
+ /* existingWrapper = */ childrenContainer.getNotificationHeaderWrapper(),
+ runningInflations, applyCallback, logger);
+ }
+
+ if ((reInflateFlags & FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER) != 0) {
+ boolean isNewView =
+ !canReapplyRemoteView(
+ /* newView = */ result.mNewLowPriorityGroupHeaderView,
+ /* oldView = */ remoteViewCache.getCachedView(
+ entry, FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER));
+ ApplyCallback applyCallback = new ApplyCallback() {
+ @Override
+ public void setResultView(View v) {
+ logger.logAsyncTaskProgress(entry,
+ "low-priority group header view applied");
+ result.mInflatedLowPriorityGroupHeaderView = (NotificationHeaderView) v;
+ }
+
+ @Override
+ public RemoteViews getRemoteView() {
+ return result.mNewLowPriorityGroupHeaderView;
+ }
+ };
+ logger.logAsyncTaskProgress(entry, "applying low priority group header view");
+ applyRemoteView(inflationExecutor, inflateSynchronously, result, reInflateFlags,
+ /* inflationId = */ FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER,
+ remoteViewCache, entry, row, isNewView, remoteViewClickHandler, callback,
+ /* parentLayout = */ childrenContainer,
+ /* existingView = */ childrenContainer.getNotificationHeaderLowPriority(),
+ /* existingWrapper = */ childrenContainer
+ .getLowPriorityViewWrapper(),
+ runningInflations, applyCallback, logger);
+ }
+ }
+
// Let's try to finish, maybe nobody is even inflating anything
finishIfDone(result, reInflateFlags, remoteViewCache, runningInflations, callback, entry,
row, logger);
@@ -560,7 +640,7 @@ public class NotificationContentInflater implements NotificationRowContentBinder
boolean isNewView,
RemoteViews.InteractionHandler remoteViewClickHandler,
@Nullable final InflationCallback callback,
- NotificationContentView parentLayout,
+ ViewGroup parentLayout,
View existingView,
NotificationViewWrapper existingWrapper,
final HashMap<Integer, CancellationSignal> runningInflations,
@@ -702,6 +782,10 @@ public class NotificationContentInflater implements NotificationRowContentBinder
return result;
}
+ /**
+ * Notifications with undecorated custom views need to satisfy a minimum height to avoid visual
+ * issues.
+ */
private static boolean requiresHeightCheck(NotificationEntry entry) {
// Undecorated custom views are disallowed from S onwards
if (entry.targetSdk >= Build.VERSION_CODES.S) {
@@ -845,6 +929,39 @@ public class NotificationContentInflater implements NotificationRowContentBinder
}
}
+ if (AsyncGroupHeaderViewInflation.isEnabled()) {
+ if ((reInflateFlags & FLAG_GROUP_SUMMARY_HEADER) != 0) {
+ if (result.mInflatedGroupHeaderView != null) {
+ row.setIsLowPriority(false);
+ row.setGroupHeader(/* headerView= */ result.mInflatedGroupHeaderView);
+ remoteViewCache.putCachedView(entry, FLAG_GROUP_SUMMARY_HEADER,
+ result.mNewGroupHeaderView);
+ } else if (remoteViewCache.hasCachedView(entry, FLAG_GROUP_SUMMARY_HEADER)) {
+ // Re-inflation case. Only update if it's still cached (i.e. view has not
+ // been freed while inflating).
+ remoteViewCache.putCachedView(entry, FLAG_GROUP_SUMMARY_HEADER,
+ result.mNewGroupHeaderView);
+ }
+ }
+
+ if ((reInflateFlags & FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER) != 0) {
+ if (result.mInflatedLowPriorityGroupHeaderView != null) {
+ // New view case, set row to low priority
+ row.setIsLowPriority(true);
+ row.setLowPriorityGroupHeader(
+ /* headerView= */ result.mInflatedLowPriorityGroupHeaderView);
+ remoteViewCache.putCachedView(entry, FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER,
+ result.mNewLowPriorityGroupHeaderView);
+ } else if (remoteViewCache.hasCachedView(entry,
+ FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER)) {
+ // Re-inflation case. Only update if it's still cached (i.e. view has not
+ // been freed while inflating).
+ remoteViewCache.putCachedView(entry, FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER,
+ result.mNewGroupHeaderView);
+ }
+ }
+ }
+
entry.headsUpStatusBarText = result.headsUpStatusBarText;
entry.headsUpStatusBarTextPublic = result.headsUpStatusBarTextPublic;
if (endListener != null) {
@@ -1147,6 +1264,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
private RemoteViews newHeadsUpView;
private RemoteViews newExpandedView;
private RemoteViews newPublicView;
+ private RemoteViews mNewGroupHeaderView;
+ private RemoteViews mNewLowPriorityGroupHeaderView;
@VisibleForTesting
Context packageContext;
@@ -1155,6 +1274,8 @@ public class NotificationContentInflater implements NotificationRowContentBinder
private View inflatedHeadsUpView;
private View inflatedExpandedView;
private View inflatedPublicView;
+ private NotificationHeaderView mInflatedGroupHeaderView;
+ private NotificationHeaderView mInflatedLowPriorityGroupHeaderView;
private CharSequence headsUpStatusBarText;
private CharSequence headsUpStatusBarTextPublic;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterLogger.kt
index ee9462c60674..15c705579bf7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterLogger.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationContentInflaterLogger.kt
@@ -27,6 +27,8 @@ import com.android.systemui.statusbar.notification.row.NotificationRowContentBin
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_HEADS_UP
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_PUBLIC
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_CONTENT_VIEW_SINGLE_LINE
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_GROUP_SUMMARY_HEADER
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER
import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag
import javax.inject.Inject
@@ -145,6 +147,12 @@ constructor(@NotifInflationLog private val buffer: LogBuffer) {
if (flag and FLAG_CONTENT_VIEW_SINGLE_LINE != 0) {
l.add("SINGLE_LINE")
}
+ if (flag and FLAG_GROUP_SUMMARY_HEADER != 0) {
+ l.add("GROUP_SUMMARY_HEADER")
+ }
+ if (flag and FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER != 0) {
+ l.add("LOW_PRIORITY_GROUP_SUMMARY_HEADER")
+ }
return l.joinToString("|")
}
}
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 374248252d1f..50bc3d31aa42 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
@@ -238,7 +238,10 @@ public class NotificationContentView extends FrameLayout implements Notification
mMinContractedHeight = getResources().getDimensionPixelSize(
R.dimen.min_notification_layout_height);
if (AsyncHybridViewInflation.isEnabled()) {
- //TODO: set the height with a more reasonable min single-line height
+ //TODO (b/217799515): single-line view height is the greater of two heights: text view
+ // height and icon height (when there's an icon). icon height is fixed to be
+ // conversation_single_line_face_pile_size (24dp), the text view's height is 16sp,
+ // its pixel height changes with the system's font scaling factor.
mMinSingleLineHeight = getResources().getDimensionPixelSize(
R.dimen.conversation_single_line_face_pile_size);
}
@@ -843,7 +846,7 @@ public class NotificationContentView extends FrameLayout implements Notification
if (mSingleLineView != null) {
return getViewHeight(VISIBLE_TYPE_SINGLELINE);
} else {
- Log.wtf(TAG, "getMinHeight: mSingleLineView == null");
+ //TODO(b/217799515): investigate the impact of min-height value
return mMinSingleLineHeight;
}
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
index 736140c44dfd..b0fd47587782 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationRowContentBinder.java
@@ -81,6 +81,8 @@ public interface NotificationRowContentBinder {
FLAG_CONTENT_VIEW_HEADS_UP,
FLAG_CONTENT_VIEW_PUBLIC,
FLAG_CONTENT_VIEW_SINGLE_LINE,
+ FLAG_GROUP_SUMMARY_HEADER,
+ FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER,
FLAG_CONTENT_VIEW_ALL})
@interface InflationFlag {}
/**
@@ -108,7 +110,17 @@ public interface NotificationRowContentBinder {
*/
int FLAG_CONTENT_VIEW_SINGLE_LINE = 1 << 4;
- int FLAG_CONTENT_VIEW_ALL = (1 << 5) - 1;
+ /**
+ * The notification group summary header view
+ */
+ int FLAG_GROUP_SUMMARY_HEADER = 1 << 5;
+
+ /**
+ * The notification low-priority group summary header view
+ */
+ int FLAG_LOW_PRIORITY_GROUP_SUMMARY_HEADER = 1 << 6;
+
+ int FLAG_CONTENT_VIEW_ALL = (1 << 7) - 1;
/**
* Parameters for content view binding
@@ -129,6 +141,11 @@ public interface NotificationRowContentBinder {
* Use increased height when binding heads up views.
*/
public boolean usesIncreasedHeadsUpHeight;
+
+ /**
+ * Is group summary notification
+ */
+ public boolean mIsGroupSummary;
}
/**
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 abf6c27c68ac..fa973001cec7 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
@@ -55,6 +55,7 @@ import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView;
import com.android.systemui.statusbar.notification.row.HybridGroupManager;
import com.android.systemui.statusbar.notification.row.HybridNotificationView;
+import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationViewWrapper;
@@ -131,6 +132,7 @@ public class NotificationChildrenContainer extends ViewGroup
private int mUntruncatedChildCount;
private boolean mContainingNotificationIsFaded = false;
private RoundableState mRoundableState;
+ private int mMinSingleLineHeight;
private NotificationChildrenContainerLogger mLogger;
@@ -183,6 +185,8 @@ public class NotificationChildrenContainer extends ViewGroup
com.android.internal.R.dimen.notification_content_margin)
- mNotificationHeaderMargin;
mHybridGroupManager.initDimens();
+ mMinSingleLineHeight = getResources().getDimensionPixelSize(
+ R.dimen.conversation_single_line_face_pile_size);
}
@NonNull
@@ -385,16 +389,31 @@ public class NotificationChildrenContainer extends ViewGroup
return mAttachedChildren.size();
}
- public void recreateNotificationHeader(OnClickListener listener, boolean isConversation) {
+ /**
+ * Re-create the Notification header view
+ * @param listener OnClickListener of the header view
+ * @param isConversation if the notification group is a conversation group
+ */
+ public void recreateNotificationHeader(
+ OnClickListener listener,
+ boolean isConversation
+ ) {
+ // We don't want to inflate headers from the main thread when async inflation enabled
+ AsyncGroupHeaderViewInflation.assertInLegacyMode();
+ // TODO(b/217799515): remove traces from this function in a follow-up change
Trace.beginSection("NotifChildCont#recreateHeader");
mHeaderClickListener = listener;
mIsConversation = isConversation;
StatusBarNotification notification = mContainingNotification.getEntry().getSbn();
final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
notification.getNotification());
+ Trace.beginSection("recreateHeader#makeNotificationGroupHeader");
RemoteViews header = builder.makeNotificationGroupHeader();
+ Trace.endSection();
if (mNotificationHeader == null) {
+ Trace.beginSection("recreateHeader#apply");
mNotificationHeader = (NotificationHeaderView) header.apply(getContext(), this);
+ Trace.endSection();
mNotificationHeader.findViewById(com.android.internal.R.id.expand_button)
.setVisibility(VISIBLE);
mNotificationHeader.setOnClickListener(mHeaderClickListener);
@@ -407,7 +426,9 @@ public class NotificationChildrenContainer extends ViewGroup
addView(mNotificationHeader, 0);
invalidate();
} else {
+ Trace.beginSection("recreateHeader#reapply");
header.reapply(getContext(), mNotificationHeader);
+ Trace.endSection();
}
mNotificationHeaderWrapper.setExpanded(mChildrenExpanded);
mNotificationHeaderWrapper.onContentUpdated(mContainingNotification);
@@ -417,12 +438,105 @@ public class NotificationChildrenContainer extends ViewGroup
Trace.endSection();
}
+ private void removeGroupHeader() {
+ if (mNotificationHeader == null) {
+ return;
+ }
+ removeView(mNotificationHeader);
+ mNotificationHeader = null;
+ mNotificationHeaderWrapper = null;
+ }
+
+ private void removeLowPriorityGroupHeader() {
+ if (mNotificationHeaderLowPriority == null) {
+ return;
+ }
+ removeView(mNotificationHeaderLowPriority);
+ mNotificationHeaderLowPriority = null;
+ mNotificationHeaderWrapperLowPriority = null;
+ }
+
+ /**
+ * Set the group header view
+ * @param headerView view to set
+ * @param onClickListener OnClickListener of the header view
+ */
+ public void setGroupHeader(
+ NotificationHeaderView headerView,
+ OnClickListener onClickListener
+ ) {
+ if (AsyncGroupHeaderViewInflation.isUnexpectedlyInLegacyMode()) return;
+ mHeaderClickListener = onClickListener;
+
+ removeGroupHeader();
+
+ if (headerView == null) {
+ return;
+ }
+
+ mNotificationHeader = headerView;
+ mNotificationHeader.findViewById(com.android.internal.R.id.expand_button)
+ .setVisibility(VISIBLE);
+ mNotificationHeader.setOnClickListener(mHeaderClickListener);
+ mNotificationHeaderWrapper =
+ (NotificationHeaderViewWrapper) NotificationViewWrapper.wrap(
+ getContext(),
+ mNotificationHeader,
+ mContainingNotification);
+ mNotificationHeaderWrapper.setOnRoundnessChangedListener(this::invalidate);
+ addView(mNotificationHeader, 0);
+ invalidate();
+
+ mNotificationHeaderWrapper.setExpanded(mChildrenExpanded);
+ mNotificationHeaderWrapper.onContentUpdated(mContainingNotification);
+
+ updateHeaderVisibility(false /* animate */);
+ updateChildrenAppearance();
+
+ Trace.endSection();
+ }
+
+ /**
+ * Set the low-priority group header view
+ * @param headerViewLowPriority header view to set
+ * @param onClickListener OnClickListener of the header view
+ */
+ public void setLowPriorityGroupHeader(
+ NotificationHeaderView headerViewLowPriority,
+ OnClickListener onClickListener
+ ) {
+ if (AsyncGroupHeaderViewInflation.isUnexpectedlyInLegacyMode()) return;
+ removeLowPriorityGroupHeader();
+ if (headerViewLowPriority == null) {
+ return;
+ }
+
+ mNotificationHeaderLowPriority = headerViewLowPriority;
+ mNotificationHeaderLowPriority.findViewById(com.android.internal.R.id.expand_button)
+ .setVisibility(VISIBLE);
+ mNotificationHeaderLowPriority.setOnClickListener(onClickListener);
+ mNotificationHeaderWrapperLowPriority =
+ (NotificationHeaderViewWrapper) NotificationViewWrapper.wrap(
+ getContext(),
+ mNotificationHeaderLowPriority,
+ mContainingNotification);
+ mNotificationHeaderWrapperLowPriority.setOnRoundnessChangedListener(this::invalidate);
+ addView(mNotificationHeaderLowPriority, 0);
+ invalidate();
+
+ mNotificationHeaderWrapperLowPriority.onContentUpdated(mContainingNotification);
+ updateHeaderVisibility(false /* animate */);
+ updateChildrenAppearance();
+ }
+
/**
* Recreate the low-priority header.
*
* @param builder a builder to reuse. Otherwise the builder will be recovered.
*/
- private void recreateLowPriorityHeader(Notification.Builder builder, boolean isConversation) {
+ @VisibleForTesting
+ void recreateLowPriorityHeader(Notification.Builder builder, boolean isConversation) {
+ AsyncGroupHeaderViewInflation.assertInLegacyMode();
RemoteViews header;
StatusBarNotification notification = mContainingNotification.getEntry().getSbn();
if (mIsLowPriority) {
@@ -527,8 +641,10 @@ public class NotificationChildrenContainer extends ViewGroup
* @param alpha alpha value to apply to the content
*/
public void setContentAlpha(float alpha) {
- for (int i = 0; i < mNotificationHeader.getChildCount(); i++) {
- mNotificationHeader.getChildAt(i).setAlpha(alpha);
+ if (mNotificationHeader != null) {
+ for (int i = 0; i < mNotificationHeader.getChildCount(); i++) {
+ mNotificationHeader.getChildAt(i).setAlpha(alpha);
+ }
}
for (ExpandableNotificationRow child : getAttachedChildren()) {
child.setContentAlpha(alpha);
@@ -564,7 +680,11 @@ public class NotificationChildrenContainer extends ViewGroup
*/
private int getIntrinsicHeight(float maxAllowedVisibleChildren) {
if (showingAsLowPriority()) {
- return mNotificationHeaderLowPriority.getHeight();
+ if (AsyncGroupHeaderViewInflation.isEnabled()) {
+ return mHeaderHeight;
+ } else {
+ return mNotificationHeaderLowPriority.getHeight();
+ }
}
int intrinsicHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation;
int visibleChildren = 0;
@@ -1023,6 +1143,14 @@ public class NotificationChildrenContainer extends ViewGroup
return mCurrentHeader;
}
+ public NotificationHeaderView getNotificationHeader() {
+ return mNotificationHeader;
+ }
+
+ public NotificationHeaderView getNotificationHeaderLowPriority() {
+ return mNotificationHeaderLowPriority;
+ }
+
private void updateHeaderVisibility(boolean animate) {
ViewGroup desiredHeader;
ViewGroup currentHeader = mCurrentHeader;
@@ -1032,6 +1160,10 @@ public class NotificationChildrenContainer extends ViewGroup
return;
}
+ if (AsyncGroupHeaderViewInflation.isEnabled() && desiredHeader == null) {
+ return;
+ }
+
if (animate) {
if (desiredHeader != null && currentHeader != null) {
currentHeader.setVisibility(VISIBLE);
@@ -1271,6 +1403,9 @@ public class NotificationChildrenContainer extends ViewGroup
boolean likeHighPriority,
int headerTranslation) {
if (!likeHighPriority && showingAsLowPriority()) {
+ if (AsyncGroupHeaderViewInflation.isEnabled()) {
+ return mHeaderHeight;
+ }
if (mNotificationHeaderLowPriority == null) {
Log.e(TAG, "getMinHeight: low priority header is null", new Exception());
return 0;
@@ -1295,8 +1430,12 @@ public class NotificationChildrenContainer extends ViewGroup
if (singleLineView != null) {
minExpandHeight += singleLineView.getHeight();
} else {
- Log.e(TAG, "getMinHeight: child " + child.getEntry().getKey()
- + " single line view is null", new Exception());
+ if (AsyncGroupHeaderViewInflation.isEnabled()) {
+ minExpandHeight += mMinSingleLineHeight;
+ } else {
+ Log.e(TAG, "getMinHeight: child " + child.getEntry().getKey()
+ + " single line view is null", new Exception());
+ }
}
visibleChildren++;
}
@@ -1309,15 +1448,19 @@ public class NotificationChildrenContainer extends ViewGroup
}
public void reInflateViews(OnClickListener listener, StatusBarNotification notification) {
- if (mNotificationHeader != null) {
- removeView(mNotificationHeader);
- mNotificationHeader = null;
- }
- if (mNotificationHeaderLowPriority != null) {
- removeView(mNotificationHeaderLowPriority);
- mNotificationHeaderLowPriority = null;
+ if (!AsyncGroupHeaderViewInflation.isEnabled()) {
+ // When Async header inflation is enabled, we do not reinflate headers because they are
+ // inflated from the background thread
+ if (mNotificationHeader != null) {
+ removeView(mNotificationHeader);
+ mNotificationHeader = null;
+ }
+ if (mNotificationHeaderLowPriority != null) {
+ removeView(mNotificationHeaderLowPriority);
+ mNotificationHeaderLowPriority = null;
+ }
+ recreateNotificationHeader(listener, mIsConversation);
}
- recreateNotificationHeader(listener, mIsConversation);
initDimens();
for (int i = 0; i < mDividers.size(); i++) {
View prevDivider = mDividers.get(i);
@@ -1395,7 +1538,9 @@ public class NotificationChildrenContainer extends ViewGroup
public void setIsLowPriority(boolean isLowPriority) {
mIsLowPriority = isLowPriority;
if (mContainingNotification != null) { /* we're not yet set up yet otherwise */
- recreateLowPriorityHeader(null /* existingBuilder */, mIsConversation);
+ if (!AsyncGroupHeaderViewInflation.isEnabled()) {
+ recreateLowPriorityHeader(null /* existingBuilder */, mIsConversation);
+ }
updateHeaderVisibility(false /* animate */);
}
if (mUserLocked) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
index 73c49c023dd5..115a0d367e87 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/inflation/NotifUiAdjustmentProviderTest.kt
@@ -31,6 +31,7 @@ import com.android.systemui.statusbar.notification.collection.NotificationEntryB
import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
import com.android.systemui.statusbar.notification.collection.provider.SectionStyleProvider
import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager
+import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation
import com.android.systemui.statusbar.notification.row.shared.AsyncHybridViewInflation
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.eq
@@ -46,6 +47,7 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.inOrder
+import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when` as whenever
@@ -141,12 +143,14 @@ class NotifUiAdjustmentProviderTest : SysuiTestCase() {
fun changeIsChildInGroup_asyncHybirdFlagEnabled_needReInflation() {
// Given: an Entry that is not child in group
// AsyncHybridViewInflation flag is enabled
- whenever(groupMembershipManager.isChildInGroup(entry)).thenReturn(false)
+ val spySbn = spy(entry.sbn)
+ entry.sbn = spySbn
+ whenever(spySbn.isAppOrSystemGroupChild).thenReturn(false)
val oldAdjustment = adjustmentProvider.calculateAdjustment(entry)
assertThat(oldAdjustment.isChildInGroup).isFalse()
// When: the Entry becomes a group child
- whenever(groupMembershipManager.isChildInGroup(entry)).thenReturn(true)
+ whenever(spySbn.isAppOrSystemGroupChild).thenReturn(true)
val newAdjustment = adjustmentProvider.calculateAdjustment(entry)
assertThat(newAdjustment.isChildInGroup).isTrue()
assertThat(newAdjustment).isNotEqualTo(oldAdjustment)
@@ -160,12 +164,14 @@ class NotifUiAdjustmentProviderTest : SysuiTestCase() {
fun changeIsChildInGroup_asyncHybirdFlagDisabled_noNeedForReInflation() {
// Given: an Entry that is not child in group
// AsyncHybridViewInflation flag is disabled
- whenever(groupMembershipManager.isChildInGroup(entry)).thenReturn(false)
+ val spySbn = spy(entry.sbn)
+ entry.sbn = spySbn
+ whenever(spySbn.isAppOrSystemGroupChild).thenReturn(false)
val oldAdjustment = adjustmentProvider.calculateAdjustment(entry)
assertThat(oldAdjustment.isChildInGroup).isFalse()
// When: the Entry becomes a group child
- whenever(groupMembershipManager.isChildInGroup(entry)).thenReturn(true)
+ whenever(spySbn.isAppOrSystemGroupChild).thenReturn(true)
val newAdjustment = adjustmentProvider.calculateAdjustment(entry)
assertThat(newAdjustment.isChildInGroup).isTrue()
assertThat(newAdjustment).isNotEqualTo(oldAdjustment)
@@ -173,4 +179,24 @@ class NotifUiAdjustmentProviderTest : SysuiTestCase() {
// Then: need no re-inflation
assertFalse(NotifUiAdjustment.needReinflate(oldAdjustment, newAdjustment))
}
+
+ @Test
+ @EnableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME)
+ fun changeIsGroupSummary_needReInflation() {
+ // Given: an Entry that is not a group summary
+ val spySbn = spy(entry.sbn)
+ entry.sbn = spySbn
+ whenever(spySbn.isAppOrSystemGroupSummary).thenReturn(false)
+ val oldAdjustment = adjustmentProvider.calculateAdjustment(entry)
+ assertThat(oldAdjustment.isGroupSummary).isFalse()
+
+ // When: the Entry becomes a group summary
+ whenever(spySbn.isAppOrSystemGroupSummary).thenReturn(true)
+ val newAdjustment = adjustmentProvider.calculateAdjustment(entry)
+ assertThat(newAdjustment.isGroupSummary).isTrue()
+ assertThat(newAdjustment).isNotEqualTo(oldAdjustment)
+
+ // Then: Need re-inflation
+ assertTrue(NotifUiAdjustment.needReinflate(oldAdjustment, newAdjustment))
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
index be976a1c9eaf..1f38a73020b2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
@@ -16,11 +16,17 @@
package com.android.systemui.statusbar.notification.stack;
+import static org.junit.Assert.assertNull;
+
+import android.app.Notification;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper;
import android.view.NotificationHeaderView;
import android.view.View;
+import android.widget.RemoteViews;
import androidx.test.filters.SmallTest;
@@ -28,6 +34,7 @@ import com.android.systemui.SysuiTestCase;
import com.android.systemui.statusbar.notification.SourceType;
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
+import com.android.systemui.statusbar.notification.row.shared.AsyncGroupHeaderViewInflation;
import com.android.systemui.statusbar.notification.row.wrapper.NotificationHeaderViewWrapper;
import org.junit.Assert;
@@ -40,6 +47,7 @@ import java.util.List;
@SmallTest
@RunWith(AndroidTestingRunner.class)
@RunWithLooper
+//@DisableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME)
public class NotificationChildrenContainerTest extends SysuiTestCase {
private ExpandableNotificationRow mGroup;
@@ -138,6 +146,7 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
}
@Test
+ @DisableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME)
public void testLowPriorityHeaderCleared() {
mGroup.setIsLowPriority(true);
NotificationHeaderView lowPriorityHeaderView =
@@ -145,11 +154,12 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
Assert.assertEquals(View.VISIBLE, lowPriorityHeaderView.getVisibility());
Assert.assertSame(mChildrenContainer, lowPriorityHeaderView.getParent());
mGroup.setIsLowPriority(false);
- Assert.assertNull(lowPriorityHeaderView.getParent());
- Assert.assertNull(mChildrenContainer.getLowPriorityViewWrapper());
+ assertNull(lowPriorityHeaderView.getParent());
+ assertNull(mChildrenContainer.getLowPriorityViewWrapper());
}
@Test
+ @DisableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME)
public void testRecreateNotificationHeader_hasHeader() {
mChildrenContainer.recreateNotificationHeader(null, false);
Assert.assertNotNull("Children container must have a header after recreation",
@@ -157,6 +167,76 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
}
@Test
+ @EnableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME)
+ public void testSetLowPriorityWithAsyncInflation_noHeaderReInflation() {
+ mChildrenContainer.setIsLowPriority(true);
+ assertNull("We don't inflate header from the main thread with Async "
+ + "Inflation enabled", mChildrenContainer.getCurrentHeaderView());
+ }
+
+ @Test
+ @EnableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME)
+ public void setLowPriorityBeforeLowPriorityHeaderSet() {
+
+ //Given: the children container does not have a low-priority header, and is not low-priority
+ assertNull(mChildrenContainer.getLowPriorityViewWrapper());
+ mGroup.setIsLowPriority(false);
+
+ //When: set the children container to be low-priority and set the low-priority header
+ mGroup.setIsLowPriority(true);
+ mGroup.setLowPriorityGroupHeader(createHeaderView(/* lowPriorityHeader= */ true));
+
+ //Then: the low-priority group header should be visible
+ NotificationHeaderView lowPriorityHeaderView =
+ mChildrenContainer.getLowPriorityViewWrapper().getNotificationHeader();
+ Assert.assertEquals(View.VISIBLE, lowPriorityHeaderView.getVisibility());
+ Assert.assertSame(mChildrenContainer, lowPriorityHeaderView.getParent());
+
+ //When: set the children container to be not low-priority and set the normal header
+ mGroup.setIsLowPriority(false);
+ mGroup.setGroupHeader(createHeaderView(/* lowPriorityHeader= */ false));
+
+ //Then: the low-priority group header should not be visible , normal header should be
+ // visible
+ Assert.assertEquals(View.INVISIBLE, lowPriorityHeaderView.getVisibility());
+ Assert.assertEquals(
+ View.VISIBLE,
+ mChildrenContainer.getNotificationHeaderWrapper().getNotificationHeader()
+ .getVisibility()
+ );
+ }
+
+ @Test
+ @EnableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME)
+ public void changeLowPriorityAfterHeaderSet() {
+
+ //Given: the children container does not have headers, and is not low-priority
+ assertNull(mChildrenContainer.getLowPriorityViewWrapper());
+ assertNull(mChildrenContainer.getNotificationHeaderWrapper());
+ mGroup.setIsLowPriority(false);
+
+ //When: set the set the normal header
+ mGroup.setGroupHeader(createHeaderView(/* lowPriorityHeader= */ false));
+
+ //Then: the group header should be visible
+ NotificationHeaderView headerView =
+ mChildrenContainer.getNotificationHeaderWrapper().getNotificationHeader();
+ Assert.assertEquals(View.VISIBLE, headerView.getVisibility());
+ Assert.assertSame(mChildrenContainer, headerView.getParent());
+
+ //When: set the set the row to be low priority, and set the low-priority header
+ mGroup.setIsLowPriority(true);
+ mGroup.setLowPriorityGroupHeader(createHeaderView(/* lowPriorityHeader= */ true));
+
+ //Then: the header view should not be visible, the low-priority group header should be
+ // visible
+ Assert.assertEquals(View.INVISIBLE, headerView.getVisibility());
+ NotificationHeaderView lowPriorityHeaderView =
+ mChildrenContainer.getLowPriorityViewWrapper().getNotificationHeader();
+ Assert.assertEquals(View.VISIBLE, lowPriorityHeaderView.getVisibility());
+ }
+
+ @Test
public void applyRoundnessAndInvalidate_should_be_immediately_applied_on_last_child() {
List<ExpandableNotificationRow> children = mChildrenContainer.getAttachedChildren();
ExpandableNotificationRow notificationRow = children.get(children.size() - 1);
@@ -170,6 +250,7 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
}
@Test
+ @DisableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME)
public void applyRoundnessAndInvalidate_should_be_immediately_applied_on_header() {
NotificationHeaderViewWrapper header = mChildrenContainer.getNotificationHeaderWrapper();
Assert.assertEquals(0f, header.getTopRoundness(), 0.001f);
@@ -180,6 +261,7 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
}
@Test
+ @DisableFlags(AsyncGroupHeaderViewInflation.FLAG_NAME)
public void applyRoundnessAndInvalidate_should_be_immediately_applied_on_headerLowPriority() {
mChildrenContainer.setIsLowPriority(true);
@@ -190,4 +272,17 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
Assert.assertEquals(1f, header.getTopRoundness(), 0.001f);
}
+
+ private NotificationHeaderView createHeaderView(boolean lowPriority) {
+ Notification notification = mNotificationTestHelper.createNotification();
+ final Notification.Builder builder = Notification.Builder.recoverBuilder(getContext(),
+ notification);
+ RemoteViews headerRemoteViews;
+ if (lowPriority) {
+ headerRemoteViews = builder.makeLowPriorityContentView(true);
+ } else {
+ headerRemoteViews = builder.makeNotificationGroupHeader();
+ }
+ return (NotificationHeaderView) headerRemoteViews.apply(getContext(), mChildrenContainer);
+ }
}