Merge changes I60bc5899,I97696070 into rvc-dev am: ed1adb192f am: 14940bd78c

Change-Id: I45c25c7966cc3a83d73a40b4073566ba47cf0888
This commit is contained in:
TreeHugger Robot
2020-04-17 19:57:20 +00:00
committed by Automerger Merge Worker
20 changed files with 349 additions and 138 deletions

View File

@@ -1075,7 +1075,7 @@ public class BubbleController implements ConfigurationController.ConfigurationLi
private void handleSummaryDismissalInterception(NotificationEntry summary) { private void handleSummaryDismissalInterception(NotificationEntry summary) {
// current children in the row: // current children in the row:
final List<NotificationEntry> children = summary.getChildren(); final List<NotificationEntry> children = summary.getAttachedNotifChildren();
if (children != null) { if (children != null) {
for (int i = 0; i < children.size(); i++) { for (int i = 0; i < children.size(); i++) {
NotificationEntry child = children.get(i); NotificationEntry child = children.get(i);

View File

@@ -148,7 +148,7 @@ public class NotificationHeaderUtil {
} }
public void updateChildrenHeaderAppearance() { public void updateChildrenHeaderAppearance() {
List<ExpandableNotificationRow> notificationChildren = mRow.getNotificationChildren(); List<ExpandableNotificationRow> notificationChildren = mRow.getAttachedChildren();
if (notificationChildren == null) { if (notificationChildren == null) {
return; return;
} }

View File

@@ -307,17 +307,20 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
} }
ExpandableNotificationRow parent = (ExpandableNotificationRow) view; ExpandableNotificationRow parent = (ExpandableNotificationRow) view;
List<ExpandableNotificationRow> children = parent.getNotificationChildren(); List<ExpandableNotificationRow> children = parent.getAttachedChildren();
List<NotificationEntry> orderedChildren = mTmpChildOrderMap.get(parent.getEntry()); List<NotificationEntry> orderedChildren = mTmpChildOrderMap.get(parent.getEntry());
if (orderedChildren == null) {
for (int childIndex = 0; orderedChildren != null && childIndex < orderedChildren.size(); // Not a group
childIndex++) { continue;
}
parent.setUntruncatedChildCount(orderedChildren.size());
for (int childIndex = 0; childIndex < orderedChildren.size(); childIndex++) {
ExpandableNotificationRow childView = orderedChildren.get(childIndex).getRow(); ExpandableNotificationRow childView = orderedChildren.get(childIndex).getRow();
if (children == null || !children.contains(childView)) { if (children == null || !children.contains(childView)) {
if (childView.getParent() != null) { if (childView.getParent() != null) {
Log.wtf(TAG, "trying to add a notification child that already has " + Log.wtf(TAG, "trying to add a notification child that already has "
"a parent. class:" + childView.getParent().getClass() + + "a parent. class:" + childView.getParent().getClass()
"\n child: " + childView); + "\n child: " + childView);
// This shouldn't happen. We can recover by removing it though. // This shouldn't happen. We can recover by removing it though.
((ViewGroup) childView.getParent()).removeView(childView); ((ViewGroup) childView.getParent()).removeView(childView);
} }
@@ -349,7 +352,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
} }
ExpandableNotificationRow parent = (ExpandableNotificationRow) view; ExpandableNotificationRow parent = (ExpandableNotificationRow) view;
List<ExpandableNotificationRow> children = parent.getNotificationChildren(); List<ExpandableNotificationRow> children = parent.getAttachedChildren();
List<NotificationEntry> orderedChildren = mTmpChildOrderMap.get(parent.getEntry()); List<NotificationEntry> orderedChildren = mTmpChildOrderMap.get(parent.getEntry());
if (children != null) { if (children != null) {
@@ -454,7 +457,7 @@ public class NotificationViewHierarchyManager implements DynamicPrivacyControlle
} }
if (row.isSummaryWithChildren()) { if (row.isSummaryWithChildren()) {
List<ExpandableNotificationRow> notificationChildren = List<ExpandableNotificationRow> notificationChildren =
row.getNotificationChildren(); row.getAttachedChildren();
int size = notificationChildren.size(); int size = notificationChildren.size();
for (int i = size - 1; i >= 0; i--) { for (int i = size - 1; i >= 0; i--) {
stack.push(notificationChildren.get(i)); stack.push(notificationChildren.get(i));

View File

@@ -515,7 +515,7 @@ public class NotificationEntryManager implements
// always cancelled. We only remove them if they were dismissed by the user. // always cancelled. We only remove them if they were dismissed by the user.
return; return;
} }
List<NotificationEntry> childEntries = entry.getChildren(); List<NotificationEntry> childEntries = entry.getAttachedNotifChildren();
if (childEntries == null) { if (childEntries == null) {
return; return;
} }

View File

@@ -20,6 +20,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.systemui.statusbar.notification.collection.coordinator.PreparationCoordinator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@@ -36,6 +37,7 @@ public class GroupEntry extends ListEntry {
private final List<NotificationEntry> mUnmodifiableChildren = private final List<NotificationEntry> mUnmodifiableChildren =
Collections.unmodifiableList(mChildren); Collections.unmodifiableList(mChildren);
private int mUntruncatedChildCount;
@VisibleForTesting @VisibleForTesting
public GroupEntry(String key) { public GroupEntry(String key) {
@@ -62,6 +64,24 @@ public class GroupEntry extends ListEntry {
mSummary = summary; 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() { void clearChildren() {
mChildren.clear(); mChildren.clear();
} }

View File

@@ -113,7 +113,7 @@ class NotifViewManager @Inject constructor(
} else if (entries[idx] is GroupEntry) { } else if (entries[idx] is GroupEntry) {
// A top-level entry exists. If it's a group, diff the children // A top-level entry exists. If it's a group, diff the children
val groupChildren = (entries[idx] as GroupEntry).children val groupChildren = (entries[idx] as GroupEntry).children
listItem.notificationChildren?.forEach { listChild -> listItem.attachedChildren?.forEach { listChild ->
if (!groupChildren.contains(listChild.entry)) { if (!groupChildren.contains(listChild.entry)) {
listItem.removeChildNotification(listChild) listItem.removeChildNotification(listChild)
@@ -155,8 +155,8 @@ class NotifViewManager @Inject constructor(
for ((idx, childEntry) in entry.children.withIndex()) { for ((idx, childEntry) in entry.children.withIndex()) {
val childListItem = rowRegistry.requireView(childEntry) val childListItem = rowRegistry.requireView(childEntry)
// Child hasn't been added yet. add it! // Child hasn't been added yet. add it!
if (listItem.notificationChildren == null || if (listItem.attachedChildren == null ||
!listItem.notificationChildren.contains(childListItem)) { !listItem.attachedChildren.contains(childListItem)) {
// TODO: old code here just Log.wtf()'d here. This might wreak havoc // TODO: old code here just Log.wtf()'d here. This might wreak havoc
if (childListItem.view.parent != null) { if (childListItem.view.parent != null) {
throw IllegalStateException("trying to add a notification child that " + throw IllegalStateException("trying to add a notification child that " +
@@ -179,6 +179,7 @@ class NotifViewManager @Inject constructor(
stabilityManager, stabilityManager,
null /*TODO: stability callback */ null /*TODO: stability callback */
) )
listItem.setUntruncatedChildCount(entry.untruncatedChildCount)
} }
} }

View File

@@ -434,13 +434,18 @@ public final class NotificationEntry extends ListEntry {
mRowController = controller; mRowController = controller;
} }
@Nullable /**
public List<NotificationEntry> 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<NotificationEntry> getAttachedNotifChildren() {
if (row == null) { if (row == null) {
return null; return null;
} }
List<ExpandableNotificationRow> rowChildren = row.getNotificationChildren(); List<ExpandableNotificationRow> rowChildren = row.getAttachedChildren();
if (rowChildren == null) { if (rowChildren == null) {
return null; return null;
} }
@@ -748,7 +753,7 @@ public final class NotificationEntry extends ListEntry {
return false; return false;
} }
List<NotificationEntry> children = getChildren(); List<NotificationEntry> children = getAttachedNotifChildren();
if (children != null && children.size() > 0) { if (children != null && children.size() > 0) {
for (int i = 0; i < children.size(); i++) { for (int i = 0; i < children.size(); i++) {
NotificationEntry child = children.get(i); NotificationEntry child = children.get(i);

View File

@@ -16,11 +16,15 @@
package com.android.systemui.statusbar.notification.collection.coordinator; 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.annotation.IntDef;
import android.os.RemoteException; import android.os.RemoteException;
import android.service.notification.StatusBarNotification; import android.service.notification.StatusBarNotification;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.ArraySet;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.statusbar.notification.collection.GroupEntry; import com.android.systemui.statusbar.notification.collection.GroupEntry;
import com.android.systemui.statusbar.notification.collection.ListEntry; import com.android.systemui.statusbar.notification.collection.ListEntry;
@@ -40,6 +44,7 @@ import java.lang.annotation.RetentionPolicy;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@@ -60,22 +65,47 @@ public class PreparationCoordinator implements Coordinator {
private final NotifInflationErrorManager mNotifErrorManager; private final NotifInflationErrorManager mNotifErrorManager;
private final NotifViewBarn mViewBarn; private final NotifViewBarn mViewBarn;
private final Map<NotificationEntry, Integer> mInflationStates = new ArrayMap<>(); private final Map<NotificationEntry, Integer> 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<NotificationEntry> mInflatingNotifs = new ArraySet<>();
private final IStatusBarService mStatusBarService; 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 @Inject
public PreparationCoordinator( public PreparationCoordinator(
PreparationCoordinatorLogger logger, PreparationCoordinatorLogger logger,
NotifInflaterImpl notifInflater, NotifInflaterImpl notifInflater,
NotifInflationErrorManager errorManager, NotifInflationErrorManager errorManager,
NotifViewBarn viewBarn, 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; mLogger = logger;
mNotifInflater = notifInflater; mNotifInflater = notifInflater;
mNotifErrorManager = errorManager; mNotifErrorManager = errorManager;
mNotifErrorManager.addInflationErrorListener(mInflationErrorListener); mNotifErrorManager.addInflationErrorListener(mInflationErrorListener);
mViewBarn = viewBarn; mViewBarn = viewBarn;
mStatusBarService = service; mStatusBarService = service;
mChildBindCutoff = childBindCutoff;
} }
@Override @Override
@@ -96,6 +126,8 @@ public class PreparationCoordinator implements Coordinator {
@Override @Override
public void onEntryUpdated(NotificationEntry entry) { public void onEntryUpdated(NotificationEntry entry) {
abortInflation(entry, "entryUpdated");
mInflatingNotifs.remove(entry);
@InflationState int state = getInflationState(entry); @InflationState int state = getInflationState(entry);
if (state == STATE_INFLATED) { if (state == STATE_INFLATED) {
mInflationStates.put(entry, STATE_INFLATED_INVALID); mInflationStates.put(entry, STATE_INFLATED_INVALID);
@@ -113,6 +145,7 @@ public class PreparationCoordinator implements Coordinator {
@Override @Override
public void onEntryCleanUp(NotificationEntry entry) { public void onEntryCleanUp(NotificationEntry entry) {
mInflationStates.remove(entry); mInflationStates.remove(entry);
mInflatingNotifs.remove(entry);
mViewBarn.removeViewForEntry(entry); mViewBarn.removeViewForEntry(entry);
} }
}; };
@@ -133,23 +166,11 @@ public class PreparationCoordinator implements Coordinator {
private final NotifFilter mNotifInflatingFilter = new NotifFilter(TAG + "Inflating") { 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 @Override
public boolean shouldFilterOut(NotificationEntry entry, long now) { public boolean shouldFilterOut(NotificationEntry entry, long now) {
@InflationState int state = getInflationState(entry); return !isInflated(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();
} }
}; };
@@ -187,19 +208,42 @@ public class PreparationCoordinator implements Coordinator {
ListEntry entry = entries.get(i); ListEntry entry = entries.get(i);
if (entry instanceof GroupEntry) { if (entry instanceof GroupEntry) {
GroupEntry groupEntry = (GroupEntry) entry; GroupEntry groupEntry = (GroupEntry) entry;
inflateNotifRequiredViews(groupEntry.getSummary()); groupEntry.setUntruncatedChildCount(groupEntry.getChildren().size());
List<NotificationEntry> children = groupEntry.getChildren(); inflateRequiredGroupViews(groupEntry);
for (int j = 0, groupSize = children.size(); j < groupSize; j++) {
inflateNotifRequiredViews(children.get(j));
}
} else { } else {
NotificationEntry notifEntry = (NotificationEntry) entry; NotificationEntry notifEntry = (NotificationEntry) entry;
inflateNotifRequiredViews(notifEntry); inflateRequiredNotifViews(notifEntry);
} }
} }
} }
private void inflateNotifRequiredViews(NotificationEntry entry) { private void inflateRequiredGroupViews(GroupEntry groupEntry) {
NotificationEntry summary = groupEntry.getSummary();
List<NotificationEntry> 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); @InflationState int state = mInflationStates.get(entry);
switch (state) { switch (state) {
case STATE_UNINFLATED: case STATE_UNINFLATED:
@@ -217,16 +261,38 @@ public class PreparationCoordinator implements Coordinator {
private void inflateEntry(NotificationEntry entry, String reason) { private void inflateEntry(NotificationEntry entry, String reason) {
abortInflation(entry, reason); abortInflation(entry, reason);
mNotifInflater.inflateViews(entry, mInflationCallback); mInflatingNotifs.add(entry);
mNotifInflater.inflateViews(entry, this::onInflationFinished);
} }
private void rebind(NotificationEntry entry, String reason) { 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) { private void abortInflation(NotificationEntry entry, String reason) {
mLogger.logInflationAborted(entry.getKey(), reason); mLogger.logInflationAborted(entry.getKey(), reason);
entry.abortTask(); 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) { 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}) value = {STATE_UNINFLATED, STATE_INFLATED_INVALID, STATE_INFLATED, STATE_ERROR})
@interface InflationState {} @interface InflationState {}
/** The notification has never been inflated before. */ /** The notification has no views attached. */
private static final int STATE_UNINFLATED = 0; private static final int STATE_UNINFLATED = 0;
/** The notification is inflated. */ /** The notification is inflated. */
@@ -255,4 +321,13 @@ public class PreparationCoordinator implements Coordinator {
/** The notification errored out while inflating */ /** The notification errored out while inflating */
private static final int STATE_ERROR = -1; 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;
} }

View File

@@ -411,7 +411,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
setIconAnimationRunningForChild(running, mChildrenContainer.getHeaderView()); setIconAnimationRunningForChild(running, mChildrenContainer.getHeaderView());
setIconAnimationRunningForChild(running, mChildrenContainer.getLowPriorityHeaderView()); setIconAnimationRunningForChild(running, mChildrenContainer.getLowPriorityHeaderView());
List<ExpandableNotificationRow> notificationChildren = List<ExpandableNotificationRow> notificationChildren =
mChildrenContainer.getNotificationChildren(); mChildrenContainer.getAttachedChildren();
for (int i = 0; i < notificationChildren.size(); i++) { for (int i = 0; i < notificationChildren.size(); i++) {
ExpandableNotificationRow child = notificationChildren.get(i); ExpandableNotificationRow child = notificationChildren.get(i);
child.setIconAnimationRunning(running); child.setIconAnimationRunning(running);
@@ -560,7 +560,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
if (mNotificationParent != null) { if (mNotificationParent != null) {
mNotificationParent.updateChildrenHeaderAppearance(); mNotificationParent.updateChildrenHeaderAppearance();
} }
onChildrenCountChanged(); onAttachedChildrenCountChanged();
// The public layouts expand button is always visible // The public layouts expand button is always visible
mPublicLayout.updateExpandButtons(true); mPublicLayout.updateExpandButtons(true);
updateLimits(); updateLimits();
@@ -770,6 +770,16 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mMustStayOnScreen = false; 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. * Add a child notification to this view.
* *
@@ -781,7 +791,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mChildrenContainerStub.inflate(); mChildrenContainerStub.inflate();
} }
mChildrenContainer.addNotification(row, childIndex); mChildrenContainer.addNotification(row, childIndex);
onChildrenCountChanged(); onAttachedChildrenCountChanged();
row.setIsChildInGroup(true, this); row.setIsChildInGroup(true, this);
} }
@@ -800,7 +810,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
if (mChildrenContainer != null) { if (mChildrenContainer != null) {
mChildrenContainer.removeNotification(row); mChildrenContainer.removeNotification(row);
} }
onChildrenCountChanged(); onAttachedChildrenCountChanged();
row.setIsChildInGroup(false, null); row.setIsChildInGroup(false, null);
row.setBottomRoundness(0.0f, false /* animate */); row.setBottomRoundness(0.0f, false /* animate */);
} }
@@ -894,15 +904,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return mChildrenExpanded; return mChildrenExpanded;
} }
public List<ExpandableNotificationRow> getNotificationChildren() { public List<ExpandableNotificationRow> getAttachedChildren() {
return mChildrenContainer == null ? null : mChildrenContainer.getNotificationChildren(); return mChildrenContainer == null ? null : mChildrenContainer.getAttachedChildren();
}
public int getNumberOfNotificationChildren() {
if (mChildrenContainer == null) {
return 0;
}
return mChildrenContainer.getNotificationChildren().size();
} }
/** /**
@@ -1036,7 +1039,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
setChronometerRunning(running, mPublicLayout); setChronometerRunning(running, mPublicLayout);
if (mChildrenContainer != null) { if (mChildrenContainer != null) {
List<ExpandableNotificationRow> notificationChildren = List<ExpandableNotificationRow> notificationChildren =
mChildrenContainer.getNotificationChildren(); mChildrenContainer.getAttachedChildren();
for (int i = 0; i < notificationChildren.size(); i++) { for (int i = 0; i < notificationChildren.size(); i++) {
ExpandableNotificationRow child = notificationChildren.get(i); ExpandableNotificationRow child = notificationChildren.get(i);
child.setChronometerRunning(running); child.setChronometerRunning(running);
@@ -1248,7 +1251,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mUpdateBackgroundOnUpdate = true; mUpdateBackgroundOnUpdate = true;
reInflateViews(); reInflateViews();
if (mChildrenContainer != null) { if (mChildrenContainer != null) {
for (ExpandableNotificationRow child : mChildrenContainer.getNotificationChildren()) { for (ExpandableNotificationRow child : mChildrenContainer.getAttachedChildren()) {
child.onUiModeChanged(); child.onUiModeChanged();
} }
} }
@@ -1306,8 +1309,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
} }
public void removeAllChildren() { public void removeAllChildren() {
List<ExpandableNotificationRow> notificationChildren List<ExpandableNotificationRow> notificationChildren =
= mChildrenContainer.getNotificationChildren(); mChildrenContainer.getAttachedChildren();
ArrayList<ExpandableNotificationRow> clonedList = new ArrayList<>(notificationChildren); ArrayList<ExpandableNotificationRow> clonedList = new ArrayList<>(notificationChildren);
for (int i = 0; i < clonedList.size(); i++) { for (int i = 0; i < clonedList.size(); i++) {
ExpandableNotificationRow row = clonedList.get(i); ExpandableNotificationRow row = clonedList.get(i);
@@ -1317,7 +1320,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mChildrenContainer.removeNotification(row); mChildrenContainer.removeNotification(row);
row.setIsChildInGroup(false, null); row.setIsChildInGroup(false, null);
} }
onChildrenCountChanged(); onAttachedChildrenCountChanged();
} }
@Override @Override
@@ -1328,7 +1331,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
public void setForceUnlocked(boolean forceUnlocked) { public void setForceUnlocked(boolean forceUnlocked) {
mForceUnlocked = forceUnlocked; mForceUnlocked = forceUnlocked;
if (mIsSummaryWithChildren) { if (mIsSummaryWithChildren) {
List<ExpandableNotificationRow> notificationChildren = getNotificationChildren(); List<ExpandableNotificationRow> notificationChildren = getAttachedChildren();
for (ExpandableNotificationRow child : notificationChildren) { for (ExpandableNotificationRow child : notificationChildren) {
child.setForceUnlocked(forceUnlocked); child.setForceUnlocked(forceUnlocked);
} }
@@ -1344,7 +1347,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mEntry.getIcons().getStatusBarIcon().setDismissed(); mEntry.getIcons().getStatusBarIcon().setDismissed();
if (isChildInGroup()) { if (isChildInGroup()) {
List<ExpandableNotificationRow> notificationChildren = List<ExpandableNotificationRow> notificationChildren =
mNotificationParent.getNotificationChildren(); mNotificationParent.getAttachedChildren();
int i = notificationChildren.indexOf(this); int i = notificationChildren.indexOf(this);
if (i != -1 && i < notificationChildren.size() - 1) { if (i != -1 && i < notificationChildren.size() - 1) {
mChildAfterViewWhenDismissed = notificationChildren.get(i + 1); mChildAfterViewWhenDismissed = notificationChildren.get(i + 1);
@@ -2351,7 +2354,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
return mGroupManager.isGroupExpanded(mEntry.getSbn()); return mGroupManager.isGroupExpanded(mEntry.getSbn());
} }
private void onChildrenCountChanged() { private void onAttachedChildrenCountChanged() {
mIsSummaryWithChildren = mChildrenContainer != null mIsSummaryWithChildren = mChildrenContainer != null
&& mChildrenContainer.getNotificationChildCount() > 0; && mChildrenContainer.getNotificationChildCount() > 0;
if (mIsSummaryWithChildren && mChildrenContainer.getHeaderView() == null) { 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 // If this is a summary, then add in the children notification channels for the
// same user and pkg. // same user and pkg.
if (mIsSummaryWithChildren) { if (mIsSummaryWithChildren) {
final List<ExpandableNotificationRow> childrenRows = getNotificationChildren(); final List<ExpandableNotificationRow> childrenRows = getAttachedChildren();
final int numChildren = childrenRows.size(); final int numChildren = childrenRows.size();
for (int i = 0; i < numChildren; i++) { for (int i = 0; i < numChildren; i++) {
final ExpandableNotificationRow childRow = childrenRows.get(i); final ExpandableNotificationRow childRow = childrenRows.get(i);
@@ -2491,7 +2494,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mHideSensitiveForIntrinsicHeight = hideSensitive; mHideSensitiveForIntrinsicHeight = hideSensitive;
if (mIsSummaryWithChildren) { if (mIsSummaryWithChildren) {
List<ExpandableNotificationRow> notificationChildren = List<ExpandableNotificationRow> notificationChildren =
mChildrenContainer.getNotificationChildren(); mChildrenContainer.getAttachedChildren();
for (int i = 0; i < notificationChildren.size(); i++) { for (int i = 0; i < notificationChildren.size(); i++) {
ExpandableNotificationRow child = notificationChildren.get(i); ExpandableNotificationRow child = notificationChildren.get(i);
child.setHideSensitiveForIntrinsicHeight(hideSensitive); child.setHideSensitiveForIntrinsicHeight(hideSensitive);
@@ -2829,7 +2832,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
updateBackgroundForGroupState(); updateBackgroundForGroupState();
if (mIsSummaryWithChildren) { if (mIsSummaryWithChildren) {
List<ExpandableNotificationRow> notificationChildren = List<ExpandableNotificationRow> notificationChildren =
mChildrenContainer.getNotificationChildren(); mChildrenContainer.getAttachedChildren();
for (int i = 0; i < notificationChildren.size(); i++) { for (int i = 0; i < notificationChildren.size(); i++) {
ExpandableNotificationRow child = notificationChildren.get(i); ExpandableNotificationRow child = notificationChildren.get(i);
child.updateBackgroundForGroupState(); child.updateBackgroundForGroupState();
@@ -2854,7 +2857,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
mShowNoBackground = !mShowGroupBackgroundWhenExpanded && isGroupExpanded() mShowNoBackground = !mShowGroupBackgroundWhenExpanded && isGroupExpanded()
&& !isGroupExpansionChanging() && !isUserLocked(); && !isGroupExpansionChanging() && !isUserLocked();
mChildrenContainer.updateHeaderForExpansion(mShowNoBackground); mChildrenContainer.updateHeaderForExpansion(mShowNoBackground);
List<ExpandableNotificationRow> children = mChildrenContainer.getNotificationChildren(); List<ExpandableNotificationRow> children = mChildrenContainer.getAttachedChildren();
for (int i = 0; i < children.size(); i++) { for (int i = 0; i < children.size(); i++) {
children.get(i).updateBackgroundForGroupState(); children.get(i).updateBackgroundForGroupState();
} }
@@ -3264,7 +3267,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
pw.print(", alpha: " + mChildrenContainer.getAlpha()); pw.print(", alpha: " + mChildrenContainer.getAlpha());
pw.print(", translationY: " + mChildrenContainer.getTranslationY()); pw.print(", translationY: " + mChildrenContainer.getTranslationY());
pw.println(); pw.println();
List<ExpandableNotificationRow> notificationChildren = getNotificationChildren(); List<ExpandableNotificationRow> notificationChildren = getAttachedChildren();
pw.println(" Children: " + notificationChildren.size()); pw.println(" Children: " + notificationChildren.size());
pw.println(" {"); pw.println(" {");
for(ExpandableNotificationRow child : notificationChildren) { for(ExpandableNotificationRow child : notificationChildren) {

View File

@@ -590,7 +590,7 @@ public abstract class ExpandableView extends FrameLayout implements Dumpable {
// handling reset for child notifications // handling reset for child notifications
if (this instanceof ExpandableNotificationRow) { if (this instanceof ExpandableNotificationRow) {
ExpandableNotificationRow row = (ExpandableNotificationRow) this; ExpandableNotificationRow row = (ExpandableNotificationRow) this;
List<ExpandableNotificationRow> children = row.getNotificationChildren(); List<ExpandableNotificationRow> children = row.getAttachedChildren();
if (row.isSummaryWithChildren() && children != null) { if (row.isSummaryWithChildren() && children != null) {
for (ExpandableNotificationRow childRow : children) { for (ExpandableNotificationRow childRow : children) {
childRow.resetViewState(); childRow.resetViewState();

View File

@@ -65,7 +65,7 @@ public class NotificationChildrenContainer extends ViewGroup {
}.setDuration(200); }.setDuration(200);
private final List<View> mDividers = new ArrayList<>(); private final List<View> mDividers = new ArrayList<>();
private final List<ExpandableNotificationRow> mChildren = new ArrayList<>(); private final List<ExpandableNotificationRow> mAttachedChildren = new ArrayList<>();
private final HybridGroupManager mHybridGroupManager; private final HybridGroupManager mHybridGroupManager;
private int mChildPadding; private int mChildPadding;
private int mDividerHeight; private int mDividerHeight;
@@ -105,6 +105,7 @@ public class NotificationChildrenContainer extends ViewGroup {
private int mTranslationForHeader; private int mTranslationForHeader;
private int mCurrentHeaderTranslation = 0; private int mCurrentHeaderTranslation = 0;
private float mHeaderVisibleAmount = 1.0f; private float mHeaderVisibleAmount = 1.0f;
private int mUntruncatedChildCount;
public NotificationChildrenContainer(Context context) { public NotificationChildrenContainer(Context context) {
this(context, null); this(context, null);
@@ -153,9 +154,10 @@ public class NotificationChildrenContainer extends ViewGroup {
@Override @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) { 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++) { 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 // 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 // calculated correctly as they are used to calculate how many we can fit on the screen
child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight()); 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 dividerHeightSpec = MeasureSpec.makeMeasureSpec(mDividerHeight, MeasureSpec.EXACTLY);
int height = mNotificationHeaderMargin + mNotificatonTopPadding; 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 collapsedChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
int overflowIndex = childCount > collapsedChildren ? collapsedChildren - 1 : -1; int overflowIndex = childCount > collapsedChildren ? collapsedChildren - 1 : -1;
for (int i = 0; i < childCount; i++) { 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 // 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. // calculated correctly as they are used to calculate how many we can fit on the screen.
boolean isOverflow = i == overflowIndex; boolean isOverflow = i == overflowIndex;
@@ -241,6 +244,16 @@ public class NotificationChildrenContainer extends ViewGroup {
localY < (mRealHeight + slop); 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. * 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 * @param childIndex the index to add it at, if -1 it will be added at the end
*/ */
public void addNotification(ExpandableNotificationRow row, int childIndex) { public void addNotification(ExpandableNotificationRow row, int childIndex) {
int newIndex = childIndex < 0 ? mChildren.size() : childIndex; int newIndex = childIndex < 0 ? mAttachedChildren.size() : childIndex;
mChildren.add(newIndex, row); mAttachedChildren.add(newIndex, row);
addView(row); addView(row);
row.setUserLocked(mUserLocked); row.setUserLocked(mUserLocked);
@@ -257,7 +270,6 @@ public class NotificationChildrenContainer extends ViewGroup {
addView(divider); addView(divider);
mDividers.add(newIndex, divider); mDividers.add(newIndex, divider);
updateGroupOverflow();
row.setContentTransformationAmount(0, false /* isLastChild */); row.setContentTransformationAmount(0, false /* isLastChild */);
// It doesn't make sense to keep old animations around, lets cancel them! // It doesn't make sense to keep old animations around, lets cancel them!
ExpandableViewState viewState = row.getViewState(); ExpandableViewState viewState = row.getViewState();
@@ -268,8 +280,8 @@ public class NotificationChildrenContainer extends ViewGroup {
} }
public void removeNotification(ExpandableNotificationRow row) { public void removeNotification(ExpandableNotificationRow row) {
int childIndex = mChildren.indexOf(row); int childIndex = mAttachedChildren.indexOf(row);
mChildren.remove(row); mAttachedChildren.remove(row);
removeView(row); removeView(row);
final View divider = mDividers.remove(childIndex); final View divider = mDividers.remove(childIndex);
@@ -284,7 +296,6 @@ public class NotificationChildrenContainer extends ViewGroup {
row.setSystemChildExpanded(false); row.setSystemChildExpanded(false);
row.setUserLocked(false); row.setUserLocked(false);
updateGroupOverflow();
if (!row.isRemoved()) { if (!row.isRemoved()) {
mHeaderUtil.restoreNotificationHeader(row); mHeaderUtil.restoreNotificationHeader(row);
} }
@@ -294,7 +305,7 @@ public class NotificationChildrenContainer extends ViewGroup {
* @return The number of notification children in the container. * @return The number of notification children in the container.
*/ */
public int getNotificationChildCount() { public int getNotificationChildCount() {
return mChildren.size(); return mAttachedChildren.size();
} }
public void recreateNotificationHeader(OnClickListener listener) { public void recreateNotificationHeader(OnClickListener listener) {
@@ -364,10 +375,9 @@ public class NotificationChildrenContainer extends ViewGroup {
} }
public void updateGroupOverflow() { public void updateGroupOverflow() {
int childCount = mChildren.size();
int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */); int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
if (childCount > maxAllowedVisibleChildren) { if (mUntruncatedChildCount > maxAllowedVisibleChildren) {
int number = childCount - maxAllowedVisibleChildren; int number = mUntruncatedChildCount - maxAllowedVisibleChildren;
mOverflowNumber = mHybridGroupManager.bindOverflowNumber(mOverflowNumber, number); mOverflowNumber = mHybridGroupManager.bindOverflowNumber(mOverflowNumber, number);
if (mGroupOverFlowState == null) { if (mGroupOverFlowState == null) {
mGroupOverFlowState = new ViewState(); mGroupOverFlowState = new ViewState();
@@ -401,8 +411,11 @@ public class NotificationChildrenContainer extends ViewGroup {
R.layout.notification_children_divider, this, false); R.layout.notification_children_divider, this, false);
} }
public List<ExpandableNotificationRow> getNotificationChildren() { /**
return mChildren; * Get notification children that are attached currently.
*/
public List<ExpandableNotificationRow> getAttachedChildren() {
return mAttachedChildren;
} }
/** /**
@@ -420,13 +433,13 @@ public class NotificationChildrenContainer extends ViewGroup {
return false; return false;
} }
boolean result = false; boolean result = false;
for (int i = 0; i < mChildren.size() && i < childOrder.size(); i++) { for (int i = 0; i < mAttachedChildren.size() && i < childOrder.size(); i++) {
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
ExpandableNotificationRow desiredChild = (ExpandableNotificationRow) childOrder.get(i); ExpandableNotificationRow desiredChild = (ExpandableNotificationRow) childOrder.get(i);
if (child != desiredChild) { if (child != desiredChild) {
if (visualStabilityManager.canReorderNotification(desiredChild)) { if (visualStabilityManager.canReorderNotification(desiredChild)) {
mChildren.remove(desiredChild); mAttachedChildren.remove(desiredChild);
mChildren.add(i, desiredChild); mAttachedChildren.add(i, desiredChild);
result = true; result = true;
} else { } else {
visualStabilityManager.addReorderingAllowedCallback(callback); 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 // we don't modify it the group is expanded or if we are expanding it
return; return;
} }
int size = mChildren.size(); int size = mAttachedChildren.size();
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
child.setSystemChildExpanded(i == 0 && size == 1); child.setSystemChildExpanded(i == 0 && size == 1);
} }
} }
@@ -468,7 +481,7 @@ public class NotificationChildrenContainer extends ViewGroup {
} }
int intrinsicHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation; int intrinsicHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation;
int visibleChildren = 0; int visibleChildren = 0;
int childCount = mChildren.size(); int childCount = mAttachedChildren.size();
boolean firstChild = true; boolean firstChild = true;
float expandFactor = 0; float expandFactor = 0;
if (mUserLocked) { if (mUserLocked) {
@@ -499,7 +512,7 @@ public class NotificationChildrenContainer extends ViewGroup {
} }
firstChild = false; firstChild = false;
} }
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
intrinsicHeight += child.getIntrinsicHeight(); intrinsicHeight += child.getIntrinsicHeight();
visibleChildren++; visibleChildren++;
} }
@@ -518,7 +531,7 @@ public class NotificationChildrenContainer extends ViewGroup {
* @param ambientState the ambient state containing ambient information * @param ambientState the ambient state containing ambient information
*/ */
public void updateState(ExpandableViewState parentState, AmbientState ambientState) { public void updateState(ExpandableViewState parentState, AmbientState ambientState) {
int childCount = mChildren.size(); int childCount = mAttachedChildren.size();
int yPosition = mNotificationHeaderMargin + mCurrentHeaderTranslation; int yPosition = mNotificationHeaderMargin + mCurrentHeaderTranslation;
boolean firstChild = true; boolean firstChild = true;
int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(); int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren();
@@ -535,7 +548,7 @@ public class NotificationChildrenContainer extends ViewGroup {
&& !mContainingNotification.isGroupExpansionChanging(); && !mContainingNotification.isGroupExpansionChanging();
int launchTransitionCompensation = 0; int launchTransitionCompensation = 0;
for (int i = 0; i < childCount; i++) { for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
if (!firstChild) { if (!firstChild) {
if (expandingToExpandedGroup) { if (expandingToExpandedGroup) {
yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight, yPosition += NotificationUtils.interpolate(mChildPadding, mDividerHeight,
@@ -586,7 +599,7 @@ public class NotificationChildrenContainer extends ViewGroup {
} }
if (mOverflowNumber != null) { if (mOverflowNumber != null) {
ExpandableNotificationRow overflowView = mChildren.get(Math.min( ExpandableNotificationRow overflowView = mAttachedChildren.get(Math.min(
getMaxAllowedVisibleChildren(true /* likeCollapsed */), childCount) - 1); getMaxAllowedVisibleChildren(true /* likeCollapsed */), childCount) - 1);
mGroupOverFlowState.copyFrom(overflowView.getViewState()); mGroupOverFlowState.copyFrom(overflowView.getViewState());
@@ -672,7 +685,7 @@ public class NotificationChildrenContainer extends ViewGroup {
/** Applies state to children. */ /** Applies state to children. */
public void applyState() { public void applyState() {
int childCount = mChildren.size(); int childCount = mAttachedChildren.size();
ViewState tmpState = new ViewState(); ViewState tmpState = new ViewState();
float expandFraction = 0.0f; float expandFraction = 0.0f;
if (mUserLocked) { if (mUserLocked) {
@@ -683,7 +696,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|| (mContainingNotification.isGroupExpansionChanging() || (mContainingNotification.isGroupExpansionChanging()
&& !mHideDividersDuringExpand); && !mHideDividersDuringExpand);
for (int i = 0; i < childCount; i++) { for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
ExpandableViewState viewState = child.getViewState(); ExpandableViewState viewState = child.getViewState();
viewState.applyToView(child); viewState.applyToView(child);
@@ -716,10 +729,10 @@ public class NotificationChildrenContainer extends ViewGroup {
if (mContainingNotification.hasExpandingChild()) { if (mContainingNotification.hasExpandingChild()) {
return; return;
} }
int childCount = mChildren.size(); int childCount = mAttachedChildren.size();
int layoutEnd = mContainingNotification.getActualHeight() - mClipBottomAmount; int layoutEnd = mContainingNotification.getActualHeight() - mClipBottomAmount;
for (int i = 0; i < childCount; i++) { for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
if (child.getVisibility() == GONE) { if (child.getVisibility() == GONE) {
continue; continue;
} }
@@ -754,7 +767,7 @@ public class NotificationChildrenContainer extends ViewGroup {
/** Animate to a given state. */ /** Animate to a given state. */
public void startAnimationToState(AnimationProperties properties) { public void startAnimationToState(AnimationProperties properties) {
int childCount = mChildren.size(); int childCount = mAttachedChildren.size();
ViewState tmpState = new ViewState(); ViewState tmpState = new ViewState();
float expandFraction = getGroupExpandFraction(); float expandFraction = getGroupExpandFraction();
final boolean dividersVisible = mUserLocked && !showingAsLowPriority() final boolean dividersVisible = mUserLocked && !showingAsLowPriority()
@@ -762,7 +775,7 @@ public class NotificationChildrenContainer extends ViewGroup {
|| (mContainingNotification.isGroupExpansionChanging() || (mContainingNotification.isGroupExpansionChanging()
&& !mHideDividersDuringExpand); && !mHideDividersDuringExpand);
for (int i = childCount - 1; i >= 0; i--) { for (int i = childCount - 1; i >= 0; i--) {
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
ExpandableViewState viewState = child.getViewState(); ExpandableViewState viewState = child.getViewState();
viewState.animateTo(child, properties); viewState.animateTo(child, properties);
@@ -799,9 +812,9 @@ public class NotificationChildrenContainer extends ViewGroup {
public ExpandableNotificationRow getViewAtPosition(float y) { public ExpandableNotificationRow getViewAtPosition(float y) {
// find the view under the pointer, accounting for GONE views // 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++) { for (int childIdx = 0; childIdx < count; childIdx++) {
ExpandableNotificationRow slidingChild = mChildren.get(childIdx); ExpandableNotificationRow slidingChild = mAttachedChildren.get(childIdx);
float childTop = slidingChild.getTranslationY(); float childTop = slidingChild.getTranslationY();
float top = childTop + slidingChild.getClipTopAmount(); float top = childTop + slidingChild.getClipTopAmount();
float bottom = childTop + slidingChild.getActualHeight(); float bottom = childTop + slidingChild.getActualHeight();
@@ -818,9 +831,9 @@ public class NotificationChildrenContainer extends ViewGroup {
if (mNotificationHeader != null) { if (mNotificationHeader != null) {
mNotificationHeader.setExpanded(childrenExpanded); mNotificationHeader.setExpanded(childrenExpanded);
} }
final int count = mChildren.size(); final int count = mAttachedChildren.size();
for (int childIdx = 0; childIdx < count; childIdx++) { for (int childIdx = 0; childIdx < count; childIdx++) {
ExpandableNotificationRow child = mChildren.get(childIdx); ExpandableNotificationRow child = mAttachedChildren.get(childIdx);
child.setChildrenExpanded(childrenExpanded, false); child.setChildrenExpanded(childrenExpanded, false);
} }
updateHeaderTouchability(); updateHeaderTouchability();
@@ -919,12 +932,12 @@ public class NotificationChildrenContainer extends ViewGroup {
private void startChildAlphaAnimations(boolean toVisible) { private void startChildAlphaAnimations(boolean toVisible) {
float target = toVisible ? 1.0f : 0.0f; float target = toVisible ? 1.0f : 0.0f;
float start = 1.0f - target; float start = 1.0f - target;
int childCount = mChildren.size(); int childCount = mAttachedChildren.size();
for (int i = 0; i < childCount; i++) { for (int i = 0; i < childCount; i++) {
if (i >= NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED) { if (i >= NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED) {
break; break;
} }
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
child.setAlpha(start); child.setAlpha(start);
ViewState viewState = new ViewState(); ViewState viewState = new ViewState();
viewState.initFrom(child); viewState.initFrom(child);
@@ -979,12 +992,12 @@ public class NotificationChildrenContainer extends ViewGroup {
int maxContentHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation int maxContentHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation
+ mNotificatonTopPadding; + mNotificatonTopPadding;
int visibleChildren = 0; int visibleChildren = 0;
int childCount = mChildren.size(); int childCount = mAttachedChildren.size();
for (int i = 0; i < childCount; i++) { for (int i = 0; i < childCount; i++) {
if (visibleChildren >= NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED) { if (visibleChildren >= NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED) {
break; break;
} }
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
float childHeight = child.isExpanded(true /* allowOnKeyguard */) float childHeight = child.isExpanded(true /* allowOnKeyguard */)
? child.getMaxExpandHeight() ? child.getMaxExpandHeight()
: child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */); : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
@@ -1006,9 +1019,9 @@ public class NotificationChildrenContainer extends ViewGroup {
boolean showingLowPriority = showingAsLowPriority(); boolean showingLowPriority = showingAsLowPriority();
updateHeaderTransformation(); updateHeaderTransformation();
int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */); int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
int childCount = mChildren.size(); int childCount = mAttachedChildren.size();
for (int i = 0; i < childCount; i++) { for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
float childHeight; float childHeight;
if (showingLowPriority) { if (showingLowPriority) {
childHeight = child.getShowingLayout().getMinHeight(false /* likeGroupExpanded */); childHeight = child.getShowingLayout().getMinHeight(false /* likeGroupExpanded */);
@@ -1042,13 +1055,13 @@ public class NotificationChildrenContainer extends ViewGroup {
int intrinsicHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation int intrinsicHeight = mNotificationHeaderMargin + mCurrentHeaderTranslation
+ mNotificatonTopPadding + mDividerHeight; + mNotificatonTopPadding + mDividerHeight;
int visibleChildren = 0; int visibleChildren = 0;
int childCount = mChildren.size(); int childCount = mAttachedChildren.size();
int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */); int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
for (int i = 0; i < childCount; i++) { for (int i = 0; i < childCount; i++) {
if (visibleChildren >= maxAllowedVisibleChildren) { if (visibleChildren >= maxAllowedVisibleChildren) {
break; break;
} }
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
float childHeight = child.isExpanded(true /* allowOnKeyguard */) float childHeight = child.isExpanded(true /* allowOnKeyguard */)
? child.getMaxExpandHeight() ? child.getMaxExpandHeight()
: child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */); : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
@@ -1097,7 +1110,7 @@ public class NotificationChildrenContainer extends ViewGroup {
int minExpandHeight = mNotificationHeaderMargin + headerTranslation; int minExpandHeight = mNotificationHeaderMargin + headerTranslation;
int visibleChildren = 0; int visibleChildren = 0;
boolean firstChild = true; boolean firstChild = true;
int childCount = mChildren.size(); int childCount = mAttachedChildren.size();
for (int i = 0; i < childCount; i++) { for (int i = 0; i < childCount; i++) {
if (visibleChildren >= maxAllowedVisibleChildren) { if (visibleChildren >= maxAllowedVisibleChildren) {
break; break;
@@ -1107,7 +1120,7 @@ public class NotificationChildrenContainer extends ViewGroup {
} else { } else {
firstChild = false; firstChild = false;
} }
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
minExpandHeight += child.getSingleLineView().getHeight(); minExpandHeight += child.getSingleLineView().getHeight();
visibleChildren++; visibleChildren++;
} }
@@ -1149,9 +1162,9 @@ public class NotificationChildrenContainer extends ViewGroup {
if (!mUserLocked) { if (!mUserLocked) {
updateHeaderVisibility(false /* animate */); updateHeaderVisibility(false /* animate */);
} }
int childCount = mChildren.size(); int childCount = mAttachedChildren.size();
for (int i = 0; i < childCount; i++) { for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
child.setUserLocked(userLocked && !showingAsLowPriority()); child.setUserLocked(userLocked && !showingAsLowPriority());
} }
updateHeaderTouchability(); updateHeaderTouchability();
@@ -1172,8 +1185,8 @@ public class NotificationChildrenContainer extends ViewGroup {
int position = mNotificationHeaderMargin + mCurrentHeaderTranslation int position = mNotificationHeaderMargin + mCurrentHeaderTranslation
+ mNotificatonTopPadding; + mNotificatonTopPadding;
for (int i = 0; i < mChildren.size(); i++) { for (int i = 0; i < mAttachedChildren.size(); i++) {
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
boolean notGone = child.getVisibility() != View.GONE; boolean notGone = child.getVisibility() != View.GONE;
if (notGone) { if (notGone) {
position += mDividerHeight; position += mDividerHeight;
@@ -1251,8 +1264,8 @@ public class NotificationChildrenContainer extends ViewGroup {
public void setCurrentBottomRoundness(float currentBottomRoundness) { public void setCurrentBottomRoundness(float currentBottomRoundness) {
boolean last = true; boolean last = true;
for (int i = mChildren.size() - 1; i >= 0; i--) { for (int i = mAttachedChildren.size() - 1; i >= 0; i--) {
ExpandableNotificationRow child = mChildren.get(i); ExpandableNotificationRow child = mAttachedChildren.get(i);
if (child.getVisibility() == View.GONE) { if (child.getVisibility() == View.GONE) {
continue; continue;
} }

View File

@@ -43,7 +43,7 @@ public interface NotificationListItem {
// This generic is kind of ugly - we should change this once the old VHM is gone // This generic is kind of ugly - we should change this once the old VHM is gone
/** @return list of the children of this item */ /** @return list of the children of this item */
List<? extends NotificationListItem> getNotificationChildren(); List<? extends NotificationListItem> getAttachedChildren();
/** remove all children from this list item */ /** remove all children from this list item */
void removeAllChildren(); void removeAllChildren();
@@ -54,6 +54,9 @@ public interface NotificationListItem {
/** add an item as a child */ /** add an item as a child */
void addChildNotification(NotificationListItem child, int childIndex); 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 */ /** Update the order of the children with the new list */
boolean applyChildOrder( boolean applyChildOrder(
List<? extends NotificationListItem> childOrderList, List<? extends NotificationListItem> childOrderList,

View File

@@ -2377,7 +2377,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
ExpandableNotificationRow row = (ExpandableNotificationRow) child; ExpandableNotificationRow row = (ExpandableNotificationRow) child;
if (row.isSummaryWithChildren() && row.areChildrenExpanded()) { if (row.isSummaryWithChildren() && row.areChildrenExpanded()) {
List<ExpandableNotificationRow> notificationChildren = List<ExpandableNotificationRow> notificationChildren =
row.getNotificationChildren(); row.getAttachedChildren();
for (int childIndex = 0; childIndex < notificationChildren.size(); for (int childIndex = 0; childIndex < notificationChildren.size();
childIndex++) { childIndex++) {
ExpandableNotificationRow rowChild = notificationChildren.get(childIndex); ExpandableNotificationRow rowChild = notificationChildren.get(childIndex);
@@ -4638,7 +4638,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
ExpandableNotificationRow row = (ExpandableNotificationRow) view; ExpandableNotificationRow row = (ExpandableNotificationRow) view;
row.setHeadsUpAnimatingAway(false); row.setHeadsUpAnimatingAway(false);
if (row.isSummaryWithChildren()) { if (row.isSummaryWithChildren()) {
for (ExpandableNotificationRow child : row.getNotificationChildren()) { for (ExpandableNotificationRow child : row.getAttachedChildren()) {
child.setHeadsUpAnimatingAway(false); child.setHeadsUpAnimatingAway(false);
} }
} }
@@ -5598,7 +5598,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
&& (!hasClipBounds || mTmpRect.height() > 0)) { && (!hasClipBounds || mTmpRect.height() > 0)) {
parentVisible = true; parentVisible = true;
} }
List<ExpandableNotificationRow> children = row.getNotificationChildren(); List<ExpandableNotificationRow> children = row.getAttachedChildren();
if (children != null) { if (children != null) {
for (ExpandableNotificationRow childRow : children) { for (ExpandableNotificationRow childRow : children) {
if (includeChildInDismissAll(row, selection)) { if (includeChildInDismissAll(row, selection)) {
@@ -6388,7 +6388,7 @@ public class NotificationStackScrollLayout extends ViewGroup implements ScrollAd
if (parent != null && parent.areChildrenExpanded() if (parent != null && parent.areChildrenExpanded()
&& (parent.areGutsExposed() && (parent.areGutsExposed()
|| mSwipeHelper.getExposedMenuView() == parent || mSwipeHelper.getExposedMenuView() == parent
|| (parent.getNotificationChildren().size() == 1 || (parent.getAttachedChildren().size() == 1
&& parent.getEntry().isClearable()))) { && parent.getEntry().isClearable()))) {
// In this case the group is expanded and showing the menu for the // In this case the group is expanded and showing the menu for the
// group, further interaction should apply to the group, not any // group, further interaction should apply to the group, not any

View File

@@ -297,7 +297,7 @@ public class StackScrollAlgorithm {
ExpandableNotificationRow row = (ExpandableNotificationRow) v; ExpandableNotificationRow row = (ExpandableNotificationRow) v;
// handle the notgoneIndex for the children as well // handle the notgoneIndex for the children as well
List<ExpandableNotificationRow> children = row.getNotificationChildren(); List<ExpandableNotificationRow> children = row.getAttachedChildren();
if (row.isSummaryWithChildren() && children != null) { if (row.isSummaryWithChildren() && children != null) {
for (ExpandableNotificationRow childRow : children) { for (ExpandableNotificationRow childRow : children) {
if (childRow.getVisibility() != View.GONE) { if (childRow.getVisibility() != View.GONE) {

View File

@@ -930,7 +930,7 @@ public class BubbleControllerTest extends SysuiTestCase {
mBubbleController.handleDismissalInterception(groupSummary.getEntry()); mBubbleController.handleDismissalInterception(groupSummary.getEntry());
// THEN only the NON-bubble children are dismissed // THEN only the NON-bubble children are dismissed
List<ExpandableNotificationRow> childrenRows = groupSummary.getNotificationChildren(); List<ExpandableNotificationRow> childrenRows = groupSummary.getAttachedChildren();
verify(mNotificationEntryManager, times(1)).performRemoveNotification( verify(mNotificationEntryManager, times(1)).performRemoveNotification(
childrenRows.get(0).getEntry().getSbn(), REASON_GROUP_SUMMARY_CANCELED); childrenRows.get(0).getEntry().getSbn(), REASON_GROUP_SUMMARY_CANCELED);
verify(mNotificationEntryManager, times(1)).performRemoveNotification( verify(mNotificationEntryManager, times(1)).performRemoveNotification(

View File

@@ -795,7 +795,7 @@ public class NewNotifPipelineBubbleControllerTest extends SysuiTestCase {
mBubbleController.handleDismissalInterception(groupSummary.getEntry()); mBubbleController.handleDismissalInterception(groupSummary.getEntry());
// THEN only the NON-bubble children are dismissed // THEN only the NON-bubble children are dismissed
List<ExpandableNotificationRow> childrenRows = groupSummary.getNotificationChildren(); List<ExpandableNotificationRow> childrenRows = groupSummary.getAttachedChildren();
verify(mNotifCallback, times(1)).removeNotification( verify(mNotifCallback, times(1)).removeNotification(
childrenRows.get(0).getEntry(), REASON_GROUP_SUMMARY_CANCELED); childrenRows.get(0).getEntry(), REASON_GROUP_SUMMARY_CANCELED);
verify(mNotifCallback, times(1)).removeNotification( verify(mNotifCallback, times(1)).removeNotification(

View File

@@ -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<NotificationEntry> children) {
GroupEntry groupEntry = new GroupEntry(groupKey);
groupEntry.setSummary(summary);
for (NotificationEntry child : children) {
groupEntry.addChild(child);
}
return groupEntry;
}
}

View File

@@ -21,6 +21,7 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock; import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times; import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -32,6 +33,8 @@ import androidx.test.filters.SmallTest;
import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.IStatusBarService;
import com.android.systemui.SysuiTestCase; 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.NotifInflaterImpl;
import com.android.systemui.statusbar.notification.collection.NotifPipeline; import com.android.systemui.statusbar.notification.collection.NotifPipeline;
import com.android.systemui.statusbar.notification.collection.NotifViewBarn; import com.android.systemui.statusbar.notification.collection.NotifViewBarn;
@@ -50,6 +53,7 @@ import org.mockito.Captor;
import org.mockito.Mock; import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.List; import java.util.List;
@SmallTest @SmallTest
@@ -57,6 +61,8 @@ import java.util.List;
@TestableLooper.RunWithLooper @TestableLooper.RunWithLooper
public class PreparationCoordinatorTest extends SysuiTestCase { public class PreparationCoordinatorTest extends SysuiTestCase {
private static final String TEST_MESSAGE = "TEST_MESSAGE"; 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 PreparationCoordinator mCoordinator;
private NotifCollectionListener mCollectionListener; private NotifCollectionListener mCollectionListener;
@@ -88,7 +94,8 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
mNotifInflater, mNotifInflater,
mErrorManager, mErrorManager,
mock(NotifViewBarn.class), mock(NotifViewBarn.class),
mService); mService,
TEST_CHILD_BIND_CUTOFF);
ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class); ArgumentCaptor<NotifFilter> filterCaptor = ArgumentCaptor.forClass(NotifFilter.class);
mCoordinator.attach(mNotifPipeline); mCoordinator.attach(mNotifPipeline);
@@ -175,4 +182,44 @@ public class PreparationCoordinatorTest extends SysuiTestCase {
// THEN it isn't filtered from shade list // THEN it isn't filtered from shade list
assertFalse(mUninflatedFilter.shouldFilterOut(mEntry, 0)); 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<NotificationEntry> 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());
}
}
}
} }

View File

@@ -41,7 +41,6 @@ import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper; import android.testing.TestableLooper;
import android.testing.TestableLooper.RunWithLooper; import android.testing.TestableLooper.RunWithLooper;
import android.util.ArraySet; import android.util.ArraySet;
import android.view.NotificationHeaderView;
import android.view.View; import android.view.View;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
@@ -302,7 +301,7 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
@Test @Test
public void testGetNumUniqueChildren_multiChannel() { public void testGetNumUniqueChildren_multiChannel() {
List<ExpandableNotificationRow> childRows = List<ExpandableNotificationRow> childRows =
mGroupRow.getChildrenContainer().getNotificationChildren(); mGroupRow.getChildrenContainer().getAttachedChildren();
// Give each child a unique channel id/name. // Give each child a unique channel id/name.
int i = 0; int i = 0;
for (ExpandableNotificationRow childRow : childRows) { for (ExpandableNotificationRow childRow : childRows) {

View File

@@ -143,7 +143,7 @@ public class NotificationBlockingHelperManagerTest extends SysuiTestCase {
public void testPerhapsShowBlockingHelper_notShownForMultiChannelGroup() throws Exception { public void testPerhapsShowBlockingHelper_notShownForMultiChannelGroup() throws Exception {
ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10); ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10);
int i = 0; int i = 0;
for (ExpandableNotificationRow childRow : groupRow.getNotificationChildren()) { for (ExpandableNotificationRow childRow : groupRow.getAttachedChildren()) {
modifyRanking(childRow.getEntry()) modifyRanking(childRow.getEntry())
.setChannel( .setChannel(
new NotificationChannel( new NotificationChannel(