diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java index c8e9a687ad23f..c6883c89bd216 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java @@ -1075,7 +1075,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi private void handleSummaryDismissalInterception(NotificationEntry summary) { // current children in the row: - final List children = summary.getChildren(); + final List children = summary.getAttachedNotifChildren(); if (children != null) { for (int i = 0; i < children.size(); i++) { NotificationEntry child = children.get(i); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java index ba3db09374221..670a65f55844c 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationHeaderUtil.java @@ -148,7 +148,7 @@ public class NotificationHeaderUtil { } public void updateChildrenHeaderAppearance() { - List notificationChildren = mRow.getNotificationChildren(); + List notificationChildren = mRow.getAttachedChildren(); if (notificationChildren == null) { return; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java index 1297f996b7432..37fc13e2df5be 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationViewHierarchyManager.java @@ -307,17 +307,20 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle } ExpandableNotificationRow parent = (ExpandableNotificationRow) view; - List children = parent.getNotificationChildren(); + List children = parent.getAttachedChildren(); List orderedChildren = mTmpChildOrderMap.get(parent.getEntry()); - - for (int childIndex = 0; orderedChildren != null && childIndex < orderedChildren.size(); - childIndex++) { + if (orderedChildren == null) { + // Not a group + continue; + } + parent.setUntruncatedChildCount(orderedChildren.size()); + for (int childIndex = 0; childIndex < orderedChildren.size(); childIndex++) { ExpandableNotificationRow childView = orderedChildren.get(childIndex).getRow(); if (children == null || !children.contains(childView)) { if (childView.getParent() != null) { - Log.wtf(TAG, "trying to add a notification child that already has " + - "a parent. class:" + childView.getParent().getClass() + - "\n child: " + childView); + Log.wtf(TAG, "trying to add a notification child that already has " + + "a parent. class:" + childView.getParent().getClass() + + "\n child: " + childView); // This shouldn't happen. We can recover by removing it though. ((ViewGroup) childView.getParent()).removeView(childView); } @@ -349,7 +352,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle } ExpandableNotificationRow parent = (ExpandableNotificationRow) view; - List children = parent.getNotificationChildren(); + List children = parent.getAttachedChildren(); List orderedChildren = mTmpChildOrderMap.get(parent.getEntry()); if (children != null) { @@ -454,7 +457,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle } if (row.isSummaryWithChildren()) { List notificationChildren = - row.getNotificationChildren(); + row.getAttachedChildren(); int size = notificationChildren.size(); for (int i = size - 1; i >= 0; i--) { stack.push(notificationChildren.get(i)); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java index 75493f89993b1..12d190b26eba4 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java @@ -515,7 +515,7 @@ public class NotificationEntryManager implements // always cancelled. We only remove them if they were dismissed by the user. return; } - List childEntries = entry.getChildren(); + List childEntries = entry.getAttachedNotifChildren(); if (childEntries == null) { return; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java index 2c747bdcf7b69..81494eddd989b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/GroupEntry.java @@ -20,6 +20,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import com.android.internal.annotations.VisibleForTesting; +import com.android.systemui.statusbar.notification.collection.coordinator.PreparationCoordinator; import java.util.ArrayList; import java.util.Collections; @@ -36,6 +37,7 @@ public class GroupEntry extends ListEntry { private final List mUnmodifiableChildren = Collections.unmodifiableList(mChildren); + private int mUntruncatedChildCount; @VisibleForTesting public GroupEntry(String key) { @@ -62,6 +64,24 @@ public class GroupEntry extends ListEntry { mSummary = summary; } + /** + * @see #getUntruncatedChildCount() + */ + public void setUntruncatedChildCount(int childCount) { + mUntruncatedChildCount = childCount; + } + + /** + * Get the untruncated number of children from the data model, including those that will not + * have views bound. This includes children that {@link PreparationCoordinator} will filter out + * entirely when they are beyond the last visible child. + * + * TODO: This should move to some shared class between the model and view hierarchy + */ + public int getUntruncatedChildCount() { + return mUntruncatedChildCount; + } + void clearChildren() { mChildren.clear(); } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewManager.kt index cf670bd5a424a..339809e0770b9 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifViewManager.kt @@ -113,7 +113,7 @@ class NotifViewManager @Inject constructor( } else if (entries[idx] is GroupEntry) { // A top-level entry exists. If it's a group, diff the children val groupChildren = (entries[idx] as GroupEntry).children - listItem.notificationChildren?.forEach { listChild -> + listItem.attachedChildren?.forEach { listChild -> if (!groupChildren.contains(listChild.entry)) { listItem.removeChildNotification(listChild) @@ -155,8 +155,8 @@ class NotifViewManager @Inject constructor( for ((idx, childEntry) in entry.children.withIndex()) { val childListItem = rowRegistry.requireView(childEntry) // Child hasn't been added yet. add it! - if (listItem.notificationChildren == null || - !listItem.notificationChildren.contains(childListItem)) { + if (listItem.attachedChildren == null || + !listItem.attachedChildren.contains(childListItem)) { // TODO: old code here just Log.wtf()'d here. This might wreak havoc if (childListItem.view.parent != null) { throw IllegalStateException("trying to add a notification child that " + @@ -179,6 +179,7 @@ class NotifViewManager @Inject constructor( stabilityManager, null /*TODO: stability callback */ ) + listItem.setUntruncatedChildCount(entry.untruncatedChildCount) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java index 749c3e4c9d0d3..5236385b3716f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java @@ -434,13 +434,18 @@ public final class NotificationEntry extends ListEntry { mRowController = controller; } - @Nullable - public List getChildren() { + /** + * Get the children that are actually attached to this notification's row. + * + * TODO: Seems like most callers here should probably be using + * {@link com.android.systemui.statusbar.phone.NotificationGroupManager#getChildren} + */ + public @Nullable List getAttachedNotifChildren() { if (row == null) { return null; } - List rowChildren = row.getNotificationChildren(); + List rowChildren = row.getAttachedChildren(); if (rowChildren == null) { return null; } @@ -748,7 +753,7 @@ public final class NotificationEntry extends ListEntry { return false; } - List children = getChildren(); + List children = getAttachedNotifChildren(); if (children != null && children.size() > 0) { for (int i = 0; i < children.size(); i++) { NotificationEntry child = children.get(i); 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 0e8dd5e24e910..4159d43e34ec5 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 @@ -16,11 +16,15 @@ package com.android.systemui.statusbar.notification.collection.coordinator; +import static com.android.systemui.statusbar.notification.stack.NotificationChildrenContainer.NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED; + import android.annotation.IntDef; import android.os.RemoteException; import android.service.notification.StatusBarNotification; import android.util.ArrayMap; +import android.util.ArraySet; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.ListEntry; @@ -40,6 +44,7 @@ import java.lang.annotation.RetentionPolicy; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Set; import javax.inject.Inject; import javax.inject.Singleton; @@ -60,22 +65,47 @@ public class PreparationCoordinator implements Coordinator { private final NotifInflationErrorManager mNotifErrorManager; private final NotifViewBarn mViewBarn; private final Map mInflationStates = new ArrayMap<>(); + + /** + * The set of notifications that are currently inflating something. Note that this is + * separate from inflation state as a view could either be uninflated or inflated and still be + * inflating something. + */ + private final Set mInflatingNotifs = new ArraySet<>(); + private final IStatusBarService mStatusBarService; + /** + * The number of children in a group we actually keep inflated since we don't actually show + * all the children and don't need every child inflated at all times. + */ + private final int mChildBindCutoff; + @Inject public PreparationCoordinator( PreparationCoordinatorLogger logger, NotifInflaterImpl notifInflater, NotifInflationErrorManager errorManager, NotifViewBarn viewBarn, - IStatusBarService service - ) { + IStatusBarService service) { + this(logger, notifInflater, errorManager, viewBarn, service, CHILD_BIND_CUTOFF); + } + + @VisibleForTesting + PreparationCoordinator( + PreparationCoordinatorLogger logger, + NotifInflaterImpl notifInflater, + NotifInflationErrorManager errorManager, + NotifViewBarn viewBarn, + IStatusBarService service, + int childBindCutoff) { mLogger = logger; mNotifInflater = notifInflater; mNotifErrorManager = errorManager; mNotifErrorManager.addInflationErrorListener(mInflationErrorListener); mViewBarn = viewBarn; mStatusBarService = service; + mChildBindCutoff = childBindCutoff; } @Override @@ -96,6 +126,8 @@ public class PreparationCoordinator implements Coordinator { @Override public void onEntryUpdated(NotificationEntry entry) { + abortInflation(entry, "entryUpdated"); + mInflatingNotifs.remove(entry); @InflationState int state = getInflationState(entry); if (state == STATE_INFLATED) { mInflationStates.put(entry, STATE_INFLATED_INVALID); @@ -113,6 +145,7 @@ public class PreparationCoordinator implements Coordinator { @Override public void onEntryCleanUp(NotificationEntry entry) { mInflationStates.remove(entry); + mInflatingNotifs.remove(entry); mViewBarn.removeViewForEntry(entry); } }; @@ -133,23 +166,11 @@ public class PreparationCoordinator implements Coordinator { private final NotifFilter mNotifInflatingFilter = new NotifFilter(TAG + "Inflating") { /** - * Filters out notifications that haven't been inflated yet + * Filters out notifications that aren't inflated */ @Override public boolean shouldFilterOut(NotificationEntry entry, long now) { - @InflationState int state = getInflationState(entry); - return (state != STATE_INFLATED) && (state != STATE_INFLATED_INVALID); - } - }; - - private final NotifInflater.InflationCallback mInflationCallback = - new NotifInflater.InflationCallback() { - @Override - public void onInflationFinished(NotificationEntry entry) { - mLogger.logNotifInflated(entry.getKey()); - mViewBarn.registerViewForEntry(entry, entry.getRow()); - mInflationStates.put(entry, STATE_INFLATED); - mNotifInflatingFilter.invalidateList(); + return !isInflated(entry); } }; @@ -187,19 +208,42 @@ public class PreparationCoordinator implements Coordinator { ListEntry entry = entries.get(i); if (entry instanceof GroupEntry) { GroupEntry groupEntry = (GroupEntry) entry; - inflateNotifRequiredViews(groupEntry.getSummary()); - List children = groupEntry.getChildren(); - for (int j = 0, groupSize = children.size(); j < groupSize; j++) { - inflateNotifRequiredViews(children.get(j)); - } + groupEntry.setUntruncatedChildCount(groupEntry.getChildren().size()); + inflateRequiredGroupViews(groupEntry); } else { NotificationEntry notifEntry = (NotificationEntry) entry; - inflateNotifRequiredViews(notifEntry); + inflateRequiredNotifViews(notifEntry); } } } - private void inflateNotifRequiredViews(NotificationEntry entry) { + private void inflateRequiredGroupViews(GroupEntry groupEntry) { + NotificationEntry summary = groupEntry.getSummary(); + List children = groupEntry.getChildren(); + inflateRequiredNotifViews(summary); + for (int j = 0; j < children.size(); j++) { + NotificationEntry child = children.get(j); + boolean childShouldBeBound = j < mChildBindCutoff; + if (childShouldBeBound) { + inflateRequiredNotifViews(child); + } else { + if (mInflatingNotifs.contains(child)) { + abortInflation(child, "Past last visible group child"); + } + if (isInflated(child)) { + // TODO: May want to put an animation hint here so view manager knows to treat + // this differently from a regular removal animation + freeNotifViews(child); + } + } + } + } + + private void inflateRequiredNotifViews(NotificationEntry entry) { + if (mInflatingNotifs.contains(entry)) { + // Already inflating this entry + return; + } @InflationState int state = mInflationStates.get(entry); switch (state) { case STATE_UNINFLATED: @@ -217,16 +261,38 @@ public class PreparationCoordinator implements Coordinator { private void inflateEntry(NotificationEntry entry, String reason) { abortInflation(entry, reason); - mNotifInflater.inflateViews(entry, mInflationCallback); + mInflatingNotifs.add(entry); + mNotifInflater.inflateViews(entry, this::onInflationFinished); } private void rebind(NotificationEntry entry, String reason) { - mNotifInflater.rebindViews(entry, mInflationCallback); + mInflatingNotifs.add(entry); + mNotifInflater.rebindViews(entry, this::onInflationFinished); } private void abortInflation(NotificationEntry entry, String reason) { mLogger.logInflationAborted(entry.getKey(), reason); entry.abortTask(); + mInflatingNotifs.remove(entry); + } + + private void onInflationFinished(NotificationEntry entry) { + mLogger.logNotifInflated(entry.getKey()); + mInflatingNotifs.remove(entry); + mViewBarn.registerViewForEntry(entry, entry.getRow()); + mInflationStates.put(entry, STATE_INFLATED); + mNotifInflatingFilter.invalidateList(); + } + + private void freeNotifViews(NotificationEntry entry) { + mViewBarn.removeViewForEntry(entry); + entry.setRow(null); + mInflationStates.put(entry, STATE_UNINFLATED); + } + + private boolean isInflated(NotificationEntry entry) { + @InflationState int state = getInflationState(entry); + return (state == STATE_INFLATED) || (state == STATE_INFLATED_INVALID); } private @InflationState int getInflationState(NotificationEntry entry) { @@ -241,7 +307,7 @@ public class PreparationCoordinator implements Coordinator { value = {STATE_UNINFLATED, STATE_INFLATED_INVALID, STATE_INFLATED, STATE_ERROR}) @interface InflationState {} - /** The notification has never been inflated before. */ + /** The notification has no views attached. */ private static final int STATE_UNINFLATED = 0; /** The notification is inflated. */ @@ -255,4 +321,13 @@ public class PreparationCoordinator implements Coordinator { /** The notification errored out while inflating */ private static final int STATE_ERROR = -1; + + /** + * How big the buffer of extra views we keep around to be ready to show when we do need to + * dynamically inflate a row. + */ + private static final int EXTRA_VIEW_BUFFER_COUNT = 1; + + private static final int CHILD_BIND_CUTOFF = + NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED + EXTRA_VIEW_BUFFER_COUNT; } 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 85090dcbf748b..c613e64438820 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 @@ -411,7 +411,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView setIconAnimationRunningForChild(running, mChildrenContainer.getHeaderView()); setIconAnimationRunningForChild(running, mChildrenContainer.getLowPriorityHeaderView()); List notificationChildren = - mChildrenContainer.getNotificationChildren(); + mChildrenContainer.getAttachedChildren(); for (int i = 0; i < notificationChildren.size(); i++) { ExpandableNotificationRow child = notificationChildren.get(i); child.setIconAnimationRunning(running); @@ -560,7 +560,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView if (mNotificationParent != null) { mNotificationParent.updateChildrenHeaderAppearance(); } - onChildrenCountChanged(); + onAttachedChildrenCountChanged(); // The public layouts expand button is always visible mPublicLayout.updateExpandButtons(true); updateLimits(); @@ -770,6 +770,16 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mMustStayOnScreen = false; } + /** + * @see NotificationChildrenContainer#setUntruncatedChildCount(int) + */ + public void setUntruncatedChildCount(int childCount) { + if (mChildrenContainer == null) { + mChildrenContainerStub.inflate(); + } + mChildrenContainer.setUntruncatedChildCount(childCount); + } + /** * Add a child notification to this view. * @@ -781,7 +791,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mChildrenContainerStub.inflate(); } mChildrenContainer.addNotification(row, childIndex); - onChildrenCountChanged(); + onAttachedChildrenCountChanged(); row.setIsChildInGroup(true, this); } @@ -800,7 +810,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView if (mChildrenContainer != null) { mChildrenContainer.removeNotification(row); } - onChildrenCountChanged(); + onAttachedChildrenCountChanged(); row.setIsChildInGroup(false, null); row.setBottomRoundness(0.0f, false /* animate */); } @@ -894,15 +904,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return mChildrenExpanded; } - public List getNotificationChildren() { - return mChildrenContainer == null ? null : mChildrenContainer.getNotificationChildren(); - } - - public int getNumberOfNotificationChildren() { - if (mChildrenContainer == null) { - return 0; - } - return mChildrenContainer.getNotificationChildren().size(); + public List getAttachedChildren() { + return mChildrenContainer == null ? null : mChildrenContainer.getAttachedChildren(); } /** @@ -1036,7 +1039,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView setChronometerRunning(running, mPublicLayout); if (mChildrenContainer != null) { List notificationChildren = - mChildrenContainer.getNotificationChildren(); + mChildrenContainer.getAttachedChildren(); for (int i = 0; i < notificationChildren.size(); i++) { ExpandableNotificationRow child = notificationChildren.get(i); child.setChronometerRunning(running); @@ -1248,7 +1251,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mUpdateBackgroundOnUpdate = true; reInflateViews(); if (mChildrenContainer != null) { - for (ExpandableNotificationRow child : mChildrenContainer.getNotificationChildren()) { + for (ExpandableNotificationRow child : mChildrenContainer.getAttachedChildren()) { child.onUiModeChanged(); } } @@ -1306,8 +1309,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView } public void removeAllChildren() { - List notificationChildren - = mChildrenContainer.getNotificationChildren(); + List notificationChildren = + mChildrenContainer.getAttachedChildren(); ArrayList clonedList = new ArrayList<>(notificationChildren); for (int i = 0; i < clonedList.size(); i++) { ExpandableNotificationRow row = clonedList.get(i); @@ -1317,7 +1320,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mChildrenContainer.removeNotification(row); row.setIsChildInGroup(false, null); } - onChildrenCountChanged(); + onAttachedChildrenCountChanged(); } @Override @@ -1328,7 +1331,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView public void setForceUnlocked(boolean forceUnlocked) { mForceUnlocked = forceUnlocked; if (mIsSummaryWithChildren) { - List notificationChildren = getNotificationChildren(); + List notificationChildren = getAttachedChildren(); for (ExpandableNotificationRow child : notificationChildren) { child.setForceUnlocked(forceUnlocked); } @@ -1344,7 +1347,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mEntry.getIcons().getStatusBarIcon().setDismissed(); if (isChildInGroup()) { List notificationChildren = - mNotificationParent.getNotificationChildren(); + mNotificationParent.getAttachedChildren(); int i = notificationChildren.indexOf(this); if (i != -1 && i < notificationChildren.size() - 1) { mChildAfterViewWhenDismissed = notificationChildren.get(i + 1); @@ -2351,7 +2354,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView return mGroupManager.isGroupExpanded(mEntry.getSbn()); } - private void onChildrenCountChanged() { + private void onAttachedChildrenCountChanged() { mIsSummaryWithChildren = mChildrenContainer != null && mChildrenContainer.getNotificationChildCount() > 0; if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() == null) { @@ -2384,7 +2387,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView // If this is a summary, then add in the children notification channels for the // same user and pkg. if (mIsSummaryWithChildren) { - final List childrenRows = getNotificationChildren(); + final List childrenRows = getAttachedChildren(); final int numChildren = childrenRows.size(); for (int i = 0; i < numChildren; i++) { final ExpandableNotificationRow childRow = childrenRows.get(i); @@ -2491,7 +2494,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mHideSensitiveForIntrinsicHeight = hideSensitive; if (mIsSummaryWithChildren) { List notificationChildren = - mChildrenContainer.getNotificationChildren(); + mChildrenContainer.getAttachedChildren(); for (int i = 0; i < notificationChildren.size(); i++) { ExpandableNotificationRow child = notificationChildren.get(i); child.setHideSensitiveForIntrinsicHeight(hideSensitive); @@ -2829,7 +2832,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView updateBackgroundForGroupState(); if (mIsSummaryWithChildren) { List notificationChildren = - mChildrenContainer.getNotificationChildren(); + mChildrenContainer.getAttachedChildren(); for (int i = 0; i < notificationChildren.size(); i++) { ExpandableNotificationRow child = notificationChildren.get(i); child.updateBackgroundForGroupState(); @@ -2854,7 +2857,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView mShowNoBackground = !mShowGroupBackgroundWhenExpanded && isGroupExpanded() && !isGroupExpansionChanging() && !isUserLocked(); mChildrenContainer.updateHeaderForExpansion(mShowNoBackground); - List children = mChildrenContainer.getNotificationChildren(); + List children = mChildrenContainer.getAttachedChildren(); for (int i = 0; i < children.size(); i++) { children.get(i).updateBackgroundForGroupState(); } @@ -3264,7 +3267,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView pw.print(", alpha: " + mChildrenContainer.getAlpha()); pw.print(", translationY: " + mChildrenContainer.getTranslationY()); pw.println(); - List notificationChildren = getNotificationChildren(); + List notificationChildren = getAttachedChildren(); pw.println(" Children: " + notificationChildren.size()); pw.println(" {"); for(ExpandableNotificationRow child : notificationChildren) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java index ee3b753ab9265..5797944298d4b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java @@ -590,7 +590,7 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable { // handling reset for child notifications if (this instanceof ExpandableNotificationRow) { ExpandableNotificationRow row = (ExpandableNotificationRow) this; - List children = row.getNotificationChildren(); + List children = row.getAttachedChildren(); if (row.isSummaryWithChildren() && children != null) { for (ExpandableNotificationRow childRow : children) { childRow.resetViewState(); 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 400e794b820b2..351a3ef46decc 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 @@ -65,7 +65,7 @@ public class NotificationChildrenContainer extends ViewGroup { }.setDuration(200); private final List mDividers = new ArrayList<>(); - private final List mChildren = new ArrayList<>(); + private final List mAttachedChildren = new ArrayList<>(); private final HybridGroupManager mHybridGroupManager; private int mChildPadding; private int mDividerHeight; @@ -105,6 +105,7 @@ public class NotificationChildrenContainer extends ViewGroup { private int mTranslationForHeader; private int mCurrentHeaderTranslation = 0; private float mHeaderVisibleAmount = 1.0f; + private int mUntruncatedChildCount; public NotificationChildrenContainer(Context context) { this(context, null); @@ -153,9 +154,10 @@ public class NotificationChildrenContainer extends ViewGroup { @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { - int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED); + int childCount = + Math.min(mAttachedChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED); for (int i = 0; i < childCount; i++) { - View child = mChildren.get(i); + View child = mAttachedChildren.get(i); // We need to layout all children even the GONE ones, such that the heights are // calculated correctly as they are used to calculate how many we can fit on the screen child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight()); @@ -195,11 +197,12 @@ public class NotificationChildrenContainer extends ViewGroup { } int dividerHeightSpec = MeasureSpec.makeMeasureSpec(mDividerHeight, MeasureSpec.EXACTLY); int height = mNotificationHeaderMargin + mNotificatonTopPadding; - int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED); + int childCount = + Math.min(mAttachedChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED); int collapsedChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */); int overflowIndex = childCount > collapsedChildren ? collapsedChildren - 1 : -1; for (int i = 0; i < childCount; i++) { - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); // We need to measure all children even the GONE ones, such that the heights are // calculated correctly as they are used to calculate how many we can fit on the screen. boolean isOverflow = i == overflowIndex; @@ -241,6 +244,16 @@ public class NotificationChildrenContainer extends ViewGroup { localY < (mRealHeight + slop); } + /** + * Set the untruncated number of children in the group so that the view can update the UI + * appropriately. Note that this may differ from the number of views attached as truncated + * children will not have views. + */ + public void setUntruncatedChildCount(int childCount) { + mUntruncatedChildCount = childCount; + updateGroupOverflow(); + } + /** * Add a child notification to this view. * @@ -248,8 +261,8 @@ public class NotificationChildrenContainer extends ViewGroup { * @param childIndex the index to add it at, if -1 it will be added at the end */ public void addNotification(ExpandableNotificationRow row, int childIndex) { - int newIndex = childIndex < 0 ? mChildren.size() : childIndex; - mChildren.add(newIndex, row); + int newIndex = childIndex < 0 ? mAttachedChildren.size() : childIndex; + mAttachedChildren.add(newIndex, row); addView(row); row.setUserLocked(mUserLocked); @@ -257,7 +270,6 @@ public class NotificationChildrenContainer extends ViewGroup { addView(divider); mDividers.add(newIndex, divider); - updateGroupOverflow(); row.setContentTransformationAmount(0, false /* isLastChild */); // It doesn't make sense to keep old animations around, lets cancel them! ExpandableViewState viewState = row.getViewState(); @@ -268,8 +280,8 @@ public class NotificationChildrenContainer extends ViewGroup { } public void removeNotification(ExpandableNotificationRow row) { - int childIndex = mChildren.indexOf(row); - mChildren.remove(row); + int childIndex = mAttachedChildren.indexOf(row); + mAttachedChildren.remove(row); removeView(row); final View divider = mDividers.remove(childIndex); @@ -284,7 +296,6 @@ public class NotificationChildrenContainer extends ViewGroup { row.setSystemChildExpanded(false); row.setUserLocked(false); - updateGroupOverflow(); if (!row.isRemoved()) { mHeaderUtil.restoreNotificationHeader(row); } @@ -294,7 +305,7 @@ public class NotificationChildrenContainer extends ViewGroup { * @return The number of notification children in the container. */ public int getNotificationChildCount() { - return mChildren.size(); + return mAttachedChildren.size(); } public void recreateNotificationHeader(OnClickListener listener) { @@ -364,10 +375,9 @@ public class NotificationChildrenContainer extends ViewGroup { } public void updateGroupOverflow() { - int childCount = mChildren.size(); int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */); - if (childCount > maxAllowedVisibleChildren) { - int number = childCount - maxAllowedVisibleChildren; + if (mUntruncatedChildCount > maxAllowedVisibleChildren) { + int number = mUntruncatedChildCount - maxAllowedVisibleChildren; mOverflowNumber = mHybridGroupManager.bindOverflowNumber(mOverflowNumber, number); if (mGroupOverFlowState == null) { mGroupOverFlowState = new ViewState(); @@ -401,8 +411,11 @@ public class NotificationChildrenContainer extends ViewGroup { R.layout.notification_children_divider, this, false); } - public List getNotificationChildren() { - return mChildren; + /** + * Get notification children that are attached currently. + */ + public List getAttachedChildren() { + return mAttachedChildren; } /** @@ -420,13 +433,13 @@ public class NotificationChildrenContainer extends ViewGroup { return false; } boolean result = false; - for (int i = 0; i < mChildren.size() && i < childOrder.size(); i++) { - ExpandableNotificationRow child = mChildren.get(i); + for (int i = 0; i < mAttachedChildren.size() && i < childOrder.size(); i++) { + ExpandableNotificationRow child = mAttachedChildren.get(i); ExpandableNotificationRow desiredChild = (ExpandableNotificationRow) childOrder.get(i); if (child != desiredChild) { if (visualStabilityManager.canReorderNotification(desiredChild)) { - mChildren.remove(desiredChild); - mChildren.add(i, desiredChild); + mAttachedChildren.remove(desiredChild); + mAttachedChildren.add(i, desiredChild); result = true; } else { visualStabilityManager.addReorderingAllowedCallback(callback); @@ -442,9 +455,9 @@ public class NotificationChildrenContainer extends ViewGroup { // we don't modify it the group is expanded or if we are expanding it return; } - int size = mChildren.size(); + int size = mAttachedChildren.size(); for (int i = 0; i < size; i++) { - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); child.setSystemChildExpanded(i == 0 && size == 1); } } @@ -468,7 +481,7 @@ public class NotificationChildrenContainer extends ViewGroup { } int intrinsicHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation; int visibleChildren = 0; - int childCount = mChildren.size(); + int childCount = mAttachedChildren.size(); boolean firstChild = true; float expandFactor = 0; if (mUserLocked) { @@ -499,7 +512,7 @@ public class NotificationChildrenContainer extends ViewGroup { } firstChild = false; } - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); intrinsicHeight += child.getIntrinsicHeight(); visibleChildren++; } @@ -518,7 +531,7 @@ public class NotificationChildrenContainer extends ViewGroup { * @param ambientState the ambient state containing ambient information */ public void updateState(ExpandableViewState parentState, AmbientState ambientState) { - int childCount = mChildren.size(); + int childCount = mAttachedChildren.size(); int yPosition = mNotificationHeaderMargin + mCurrentHeaderTranslation; boolean firstChild = true; int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(); @@ -535,7 +548,7 @@ public class NotificationChildrenContainer extends ViewGroup { && !mContainingNotification.isGroupExpansionChanging(); int launchTransitionCompensation = 0; for (int i = 0; i < childCount; i++) { - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); if (!firstChild) { if (expandingToExpandedGroup) { yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight, @@ -586,7 +599,7 @@ public class NotificationChildrenContainer extends ViewGroup { } if (mOverflowNumber != null) { - ExpandableNotificationRow overflowView = mChildren.get(Math.min( + ExpandableNotificationRow overflowView = mAttachedChildren.get(Math.min( getMaxAllowedVisibleChildren(true /* likeCollapsed */), childCount) - 1); mGroupOverFlowState.copyFrom(overflowView.getViewState()); @@ -672,7 +685,7 @@ public class NotificationChildrenContainer extends ViewGroup { /** Applies state to children. */ public void applyState() { - int childCount = mChildren.size(); + int childCount = mAttachedChildren.size(); ViewState tmpState = new ViewState(); float expandFraction = 0.0f; if (mUserLocked) { @@ -683,7 +696,7 @@ public class NotificationChildrenContainer extends ViewGroup { || (mContainingNotification.isGroupExpansionChanging() && !mHideDividersDuringExpand); for (int i = 0; i < childCount; i++) { - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); ExpandableViewState viewState = child.getViewState(); viewState.applyToView(child); @@ -716,10 +729,10 @@ public class NotificationChildrenContainer extends ViewGroup { if (mContainingNotification.hasExpandingChild()) { return; } - int childCount = mChildren.size(); + int childCount = mAttachedChildren.size(); int layoutEnd = mContainingNotification.getActualHeight() - mClipBottomAmount; for (int i = 0; i < childCount; i++) { - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); if (child.getVisibility() == GONE) { continue; } @@ -754,7 +767,7 @@ public class NotificationChildrenContainer extends ViewGroup { /** Animate to a given state. */ public void startAnimationToState(AnimationProperties properties) { - int childCount = mChildren.size(); + int childCount = mAttachedChildren.size(); ViewState tmpState = new ViewState(); float expandFraction = getGroupExpandFraction(); final boolean dividersVisible = mUserLocked && !showingAsLowPriority() @@ -762,7 +775,7 @@ public class NotificationChildrenContainer extends ViewGroup { || (mContainingNotification.isGroupExpansionChanging() && !mHideDividersDuringExpand); for (int i = childCount - 1; i >= 0; i--) { - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); ExpandableViewState viewState = child.getViewState(); viewState.animateTo(child, properties); @@ -799,9 +812,9 @@ public class NotificationChildrenContainer extends ViewGroup { public ExpandableNotificationRow getViewAtPosition(float y) { // find the view under the pointer, accounting for GONE views - final int count = mChildren.size(); + final int count = mAttachedChildren.size(); for (int childIdx = 0; childIdx < count; childIdx++) { - ExpandableNotificationRow slidingChild = mChildren.get(childIdx); + ExpandableNotificationRow slidingChild = mAttachedChildren.get(childIdx); float childTop = slidingChild.getTranslationY(); float top = childTop + slidingChild.getClipTopAmount(); float bottom = childTop + slidingChild.getActualHeight(); @@ -818,9 +831,9 @@ public class NotificationChildrenContainer extends ViewGroup { if (mNotificationHeader != null) { mNotificationHeader.setExpanded(childrenExpanded); } - final int count = mChildren.size(); + final int count = mAttachedChildren.size(); for (int childIdx = 0; childIdx < count; childIdx++) { - ExpandableNotificationRow child = mChildren.get(childIdx); + ExpandableNotificationRow child = mAttachedChildren.get(childIdx); child.setChildrenExpanded(childrenExpanded, false); } updateHeaderTouchability(); @@ -919,12 +932,12 @@ public class NotificationChildrenContainer extends ViewGroup { private void startChildAlphaAnimations(boolean toVisible) { float target = toVisible ? 1.0f : 0.0f; float start = 1.0f - target; - int childCount = mChildren.size(); + int childCount = mAttachedChildren.size(); for (int i = 0; i < childCount; i++) { if (i >= NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED) { break; } - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); child.setAlpha(start); ViewState viewState = new ViewState(); viewState.initFrom(child); @@ -979,12 +992,12 @@ public class NotificationChildrenContainer extends ViewGroup { int maxContentHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation + mNotificatonTopPadding; int visibleChildren = 0; - int childCount = mChildren.size(); + int childCount = mAttachedChildren.size(); for (int i = 0; i < childCount; i++) { if (visibleChildren >= NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED) { break; } - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); float childHeight = child.isExpanded(true /* allowOnKeyguard */) ? child.getMaxExpandHeight() : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */); @@ -1006,9 +1019,9 @@ public class NotificationChildrenContainer extends ViewGroup { boolean showingLowPriority = showingAsLowPriority(); updateHeaderTransformation(); int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */); - int childCount = mChildren.size(); + int childCount = mAttachedChildren.size(); for (int i = 0; i < childCount; i++) { - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); float childHeight; if (showingLowPriority) { childHeight = child.getShowingLayout().getMinHeight(false /* likeGroupExpanded */); @@ -1042,13 +1055,13 @@ public class NotificationChildrenContainer extends ViewGroup { int intrinsicHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation + mNotificatonTopPadding + mDividerHeight; int visibleChildren = 0; - int childCount = mChildren.size(); + int childCount = mAttachedChildren.size(); int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */); for (int i = 0; i < childCount; i++) { if (visibleChildren >= maxAllowedVisibleChildren) { break; } - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); float childHeight = child.isExpanded(true /* allowOnKeyguard */) ? child.getMaxExpandHeight() : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */); @@ -1097,7 +1110,7 @@ public class NotificationChildrenContainer extends ViewGroup { int minExpandHeight = mNotificationHeaderMargin + headerTranslation; int visibleChildren = 0; boolean firstChild = true; - int childCount = mChildren.size(); + int childCount = mAttachedChildren.size(); for (int i = 0; i < childCount; i++) { if (visibleChildren >= maxAllowedVisibleChildren) { break; @@ -1107,7 +1120,7 @@ public class NotificationChildrenContainer extends ViewGroup { } else { firstChild = false; } - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); minExpandHeight += child.getSingleLineView().getHeight(); visibleChildren++; } @@ -1149,9 +1162,9 @@ public class NotificationChildrenContainer extends ViewGroup { if (!mUserLocked) { updateHeaderVisibility(false /* animate */); } - int childCount = mChildren.size(); + int childCount = mAttachedChildren.size(); for (int i = 0; i < childCount; i++) { - ExpandableNotificationRow child = mChildren.get(i); + ExpandableNotificationRow child = mAttachedChildren.get(i); child.setUserLocked(userLocked && !showingAsLowPriority()); } updateHeaderTouchability(); @@ -1172,8 +1185,8 @@ public class NotificationChildrenContainer extends ViewGroup { int position = mNotificationHeaderMargin + mCurrentHeaderTranslation + mNotificatonTopPadding; - for (int i = 0; i < mChildren.size(); i++) { - ExpandableNotificationRow child = mChildren.get(i); + for (int i = 0; i < mAttachedChildren.size(); i++) { + ExpandableNotificationRow child = mAttachedChildren.get(i); boolean notGone = child.getVisibility() != View.GONE; if (notGone) { position += mDividerHeight; @@ -1251,8 +1264,8 @@ public class NotificationChildrenContainer extends ViewGroup { public void setCurrentBottomRoundness(float currentBottomRoundness) { boolean last = true; - for (int i = mChildren.size() - 1; i >= 0; i--) { - ExpandableNotificationRow child = mChildren.get(i); + for (int i = mAttachedChildren.size() - 1; i >= 0; i--) { + ExpandableNotificationRow child = mAttachedChildren.get(i); if (child.getVisibility() == View.GONE) { continue; } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListItem.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListItem.java index 8991abe52ce1a..c2dd2296aa17b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListItem.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationListItem.java @@ -43,7 +43,7 @@ public interface NotificationListItem { // This generic is kind of ugly - we should change this once the old VHM is gone /** @return list of the children of this item */ - List getNotificationChildren(); + List getAttachedChildren(); /** remove all children from this list item */ void removeAllChildren(); @@ -54,6 +54,9 @@ public interface NotificationListItem { /** add an item as a child */ void addChildNotification(NotificationListItem child, int childIndex); + /** set the child count view should display */ + void setUntruncatedChildCount(int count); + /** Update the order of the children with the new list */ boolean applyChildOrder( List childOrderList, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java index 6054b507185e6..5655d8fd021b3 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java @@ -2377,7 +2377,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd ExpandableNotificationRow row = (ExpandableNotificationRow) child; if (row.isSummaryWithChildren() && row.areChildrenExpanded()) { List notificationChildren = - row.getNotificationChildren(); + row.getAttachedChildren(); for (int childIndex = 0; childIndex < notificationChildren.size(); childIndex++) { ExpandableNotificationRow rowChild = notificationChildren.get(childIndex); @@ -4638,7 +4638,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd ExpandableNotificationRow row = (ExpandableNotificationRow) view; row.setHeadsUpAnimatingAway(false); if (row.isSummaryWithChildren()) { - for (ExpandableNotificationRow child : row.getNotificationChildren()) { + for (ExpandableNotificationRow child : row.getAttachedChildren()) { child.setHeadsUpAnimatingAway(false); } } @@ -5598,7 +5598,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd && (!hasClipBounds || mTmpRect.height() > 0)) { parentVisible = true; } - List children = row.getNotificationChildren(); + List children = row.getAttachedChildren(); if (children != null) { for (ExpandableNotificationRow childRow : children) { if (includeChildInDismissAll(row, selection)) { @@ -6388,7 +6388,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd if (parent != null && parent.areChildrenExpanded() && (parent.areGutsExposed() || mSwipeHelper.getExposedMenuView() == parent - || (parent.getNotificationChildren().size() == 1 + || (parent.getAttachedChildren().size() == 1 && parent.getEntry().isClearable()))) { // In this case the group is expanded and showing the menu for the // group, further interaction should apply to the group, not any diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java index 9646c01c8c419..1a15377566e21 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java @@ -297,7 +297,7 @@ public class StackScrollAlgorithm { ExpandableNotificationRow row = (ExpandableNotificationRow) v; // handle the notgoneIndex for the children as well - List children = row.getNotificationChildren(); + List children = row.getAttachedChildren(); if (row.isSummaryWithChildren() && children != null) { for (ExpandableNotificationRow childRow : children) { if (childRow.getVisibility() != View.GONE) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java index 2f5ef00056fbf..9e18e61229c34 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java @@ -930,7 +930,7 @@ public class BubbleControllerTest extends SysuiTestCase { mBubbleController.handleDismissalInterception(groupSummary.getEntry()); // THEN only the NON-bubble children are dismissed - List childrenRows = groupSummary.getNotificationChildren(); + List childrenRows = groupSummary.getAttachedChildren(); verify(mNotificationEntryManager, times(1)).performRemoveNotification( childrenRows.get(0).getEntry().getSbn(), REASON_GROUP_SUMMARY_CANCELED); verify(mNotificationEntryManager, times(1)).performRemoveNotification( diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java index 9da160c3820c0..49236e0275e00 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java @@ -795,7 +795,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase { mBubbleController.handleDismissalInterception(groupSummary.getEntry()); // THEN only the NON-bubble children are dismissed - List childrenRows = groupSummary.getNotificationChildren(); + List childrenRows = groupSummary.getAttachedChildren(); verify(mNotifCallback, times(1)).removeNotification( childrenRows.get(0).getEntry(), REASON_GROUP_SUMMARY_CANCELED); verify(mNotifCallback, times(1)).removeNotification( diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryHelper.java new file mode 100644 index 0000000000000..038dd17a98142 --- /dev/null +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/GroupEntryHelper.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.statusbar.notification.collection; + +import java.util.List; + +/** + * Helper class to provide methods for test classes that need {@link GroupEntry}'s for their tests. + */ +public class GroupEntryHelper { + /** + * Create a group entry for testing purposes. + * @param groupKey group key for the group and all its entries + * @param summary summary notification for group + * @param children group's children notifications + */ + public static final GroupEntry createGroup( + String groupKey, + NotificationEntry summary, + List children) { + GroupEntry groupEntry = new GroupEntry(groupKey); + groupEntry.setSummary(summary); + for (NotificationEntry child : children) { + groupEntry.addChild(child); + } + return groupEntry; + } +} diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java index 35b31c01fd9cd..faf9da3aca8b4 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/PreparationCoordinatorTest.java @@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -32,6 +33,8 @@ import androidx.test.filters.SmallTest; import com.android.internal.statusbar.IStatusBarService; import com.android.systemui.SysuiTestCase; +import com.android.systemui.statusbar.notification.collection.GroupEntry; +import com.android.systemui.statusbar.notification.collection.GroupEntryHelper; import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl; import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotifViewBarn; @@ -50,6 +53,7 @@ import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; +import java.util.ArrayList; import java.util.List; @SmallTest @@ -57,6 +61,8 @@ import java.util.List; @TestableLooper.RunWithLooper public class PreparationCoordinatorTest extends SysuiTestCase { private static final String TEST_MESSAGE = "TEST_MESSAGE"; + private static final String TEST_GROUP_KEY = "TEST_GROUP_KEY"; + private static final int TEST_CHILD_BIND_CUTOFF = 9; private PreparationCoordinator mCoordinator; private NotifCollectionListener mCollectionListener; @@ -88,7 +94,8 @@ public class PreparationCoordinatorTest extends SysuiTestCase { mNotifInflater, mErrorManager, mock(NotifViewBarn.class), - mService); + mService, + TEST_CHILD_BIND_CUTOFF); ArgumentCaptor filterCaptor = ArgumentCaptor.forClass(NotifFilter.class); mCoordinator.attach(mNotifPipeline); @@ -175,4 +182,44 @@ public class PreparationCoordinatorTest extends SysuiTestCase { // THEN it isn't filtered from shade list assertFalse(mUninflatedFilter.shouldFilterOut(mEntry, 0)); } + + @Test + public void testCutoffGroupChildrenNotInflated() { + // WHEN there is a new notification group is posted + int id = 0; + NotificationEntry summary = new NotificationEntryBuilder() + .setOverrideGroupKey(TEST_GROUP_KEY) + .setId(id++) + .build(); + List children = new ArrayList<>(); + for (int i = 0; i < TEST_CHILD_BIND_CUTOFF + 1; i++) { + NotificationEntry child = new NotificationEntryBuilder() + .setOverrideGroupKey(TEST_GROUP_KEY) + .setId(id++) + .build(); + children.add(child); + } + GroupEntry groupEntry = GroupEntryHelper.createGroup(TEST_GROUP_KEY, summary, children); + + mCollectionListener.onEntryInit(summary); + for (NotificationEntry entry : children) { + mCollectionListener.onEntryInit(entry); + } + + mCollectionListener.onEntryAdded(summary); + for (NotificationEntry entry : children) { + mCollectionListener.onEntryAdded(entry); + } + + mBeforeFilterListener.onBeforeFinalizeFilter(List.of(groupEntry)); + + // THEN we inflate up to the cut-off only + for (int i = 0; i < children.size(); i++) { + if (i < TEST_CHILD_BIND_CUTOFF) { + verify(mNotifInflater).inflateViews(eq(children.get(i)), any()); + } else { + verify(mNotifInflater, never()).inflateViews(eq(children.get(i)), any()); + } + } + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java index 43dcbe30f3c33..2684cc29aa93e 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java @@ -41,7 +41,6 @@ import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.testing.TestableLooper.RunWithLooper; import android.util.ArraySet; -import android.view.NotificationHeaderView; import android.view.View; import androidx.test.filters.SmallTest; @@ -302,7 +301,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase { @Test public void testGetNumUniqueChildren_multiChannel() { List childRows = - mGroupRow.getChildrenContainer().getNotificationChildren(); + mGroupRow.getChildrenContainer().getAttachedChildren(); // Give each child a unique channel id/name. int i = 0; for (ExpandableNotificationRow childRow : childRows) { diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java index 7c8328d59a514..5aeb43fbd9590 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java @@ -143,7 +143,7 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase { public void testPerhapsShowBlockingHelper_notShownForMultiChannelGroup() throws Exception { ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10); int i = 0; - for (ExpandableNotificationRow childRow : groupRow.getNotificationChildren()) { + for (ExpandableNotificationRow childRow : groupRow.getAttachedChildren()) { modifyRanking(childRow.getEntry()) .setChannel( new NotificationChannel(