summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
+ }
}