Refactor legacy pipeline group alert transfer & group manager
This fixes cases where changes to Group.suppressed or Group.alertOverride were not correctly emitted when the parent was updated before the priority child. Bug: 185680162 Test: manual testing w/ telegram and whatsapp Test: atest NotificationGroupAlertTransferHelperTest Test: atest NotificationGroupManagerLegacyTest Change-Id: I0ee8e9cf6c17a287f7ecbba6318e154ee8889174
This commit is contained in:
@@ -24,6 +24,7 @@ import android.widget.ImageView;
|
||||
|
||||
import com.android.internal.util.ContrastColorUtil;
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
|
||||
/**
|
||||
* A util class for various reusable functions
|
||||
@@ -73,4 +74,20 @@ public class NotificationUtils {
|
||||
return (int) (dimensionPixelSize * factor);
|
||||
}
|
||||
|
||||
/** Get the notification key, reformatted for logging, for the (optional) entry */
|
||||
public static String logKey(NotificationEntry entry) {
|
||||
if (entry == null) {
|
||||
return "null";
|
||||
}
|
||||
return logKey(entry.getKey());
|
||||
}
|
||||
|
||||
/** Removes newlines from the notification key to prettify apps that have these in the tag */
|
||||
public static String logKey(String key) {
|
||||
if (key == null) {
|
||||
return "null";
|
||||
}
|
||||
return key.replace("\n", "");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,10 @@
|
||||
|
||||
package com.android.systemui.statusbar.notification.collection.legacy;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.NotificationUtils.logKey;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Notification;
|
||||
@@ -49,6 +53,7 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.TreeSet;
|
||||
import java.util.function.Function;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -79,10 +84,9 @@ public class NotificationGroupManagerLegacy implements
|
||||
private final HashMap<String, NotificationGroup> mGroupMap = new HashMap<>();
|
||||
private final ArraySet<OnGroupExpansionChangeListener> mExpansionChangeListeners =
|
||||
new ArraySet<>();
|
||||
private final ArraySet<OnGroupChangeListener> mGroupChangeListeners = new ArraySet<>();
|
||||
private final Lazy<PeopleNotificationIdentifier> mPeopleNotificationIdentifier;
|
||||
private final Optional<Bubbles> mBubblesOptional;
|
||||
private final EventBuffer mEventBuffer = new EventBuffer();
|
||||
private final GroupEventDispatcher mEventDispatcher = new GroupEventDispatcher(mGroupMap::get);
|
||||
private int mBarState = -1;
|
||||
private HashMap<String, StatusBarNotification> mIsolatedEntries = new HashMap<>();
|
||||
private HeadsUpManager mHeadsUpManager;
|
||||
@@ -105,7 +109,7 @@ public class NotificationGroupManagerLegacy implements
|
||||
* Add a listener for changes to groups.
|
||||
*/
|
||||
public void registerGroupChangeListener(OnGroupChangeListener listener) {
|
||||
mGroupChangeListeners.add(listener);
|
||||
mEventDispatcher.registerGroupChangeListener(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,13 +160,15 @@ public class NotificationGroupManagerLegacy implements
|
||||
*/
|
||||
public void onEntryRemoved(NotificationEntry removed) {
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "onEntryRemoved: entry=" + removed);
|
||||
Log.d(TAG, "onEntryRemoved: entry=" + logKey(removed));
|
||||
}
|
||||
mEventDispatcher.openBufferScope();
|
||||
onEntryRemovedInternal(removed, removed.getSbn());
|
||||
StatusBarNotification oldSbn = mIsolatedEntries.remove(removed.getKey());
|
||||
if (oldSbn != null) {
|
||||
updateSuppression(mGroupMap.get(oldSbn.getGroupKey()));
|
||||
}
|
||||
mEventDispatcher.closeBufferScope();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,7 +196,8 @@ public class NotificationGroupManagerLegacy implements
|
||||
return;
|
||||
}
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "onEntryRemovedInternal: entry=" + removed + " group=" + group.groupKey);
|
||||
Log.d(TAG, "onEntryRemovedInternal: entry=" + logKey(removed)
|
||||
+ " group=" + logGroupKey(group));
|
||||
}
|
||||
if (isGroupChild(removed.getKey(), isGroup, isGroupSummary)) {
|
||||
group.children.remove(removed.getKey());
|
||||
@@ -201,9 +208,7 @@ public class NotificationGroupManagerLegacy implements
|
||||
if (group.children.isEmpty()) {
|
||||
if (group.summary == null) {
|
||||
mGroupMap.remove(groupKey);
|
||||
for (OnGroupChangeListener listener : mGroupChangeListeners) {
|
||||
listener.onGroupRemoved(group, groupKey);
|
||||
}
|
||||
mEventDispatcher.notifyGroupRemoved(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -213,10 +218,12 @@ public class NotificationGroupManagerLegacy implements
|
||||
*/
|
||||
public void onEntryAdded(final NotificationEntry added) {
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "onEntryAdded: entry=" + added);
|
||||
Log.d(TAG, "onEntryAdded: entry=" + logKey(added));
|
||||
}
|
||||
mEventDispatcher.openBufferScope();
|
||||
updateIsolation(added);
|
||||
onEntryAddedInternal(added);
|
||||
mEventDispatcher.closeBufferScope();
|
||||
}
|
||||
|
||||
private void onEntryAddedInternal(final NotificationEntry added) {
|
||||
@@ -230,19 +237,17 @@ public class NotificationGroupManagerLegacy implements
|
||||
if (group == null) {
|
||||
group = new NotificationGroup(groupKey);
|
||||
mGroupMap.put(groupKey, group);
|
||||
|
||||
for (OnGroupChangeListener listener : mGroupChangeListeners) {
|
||||
listener.onGroupCreated(group, groupKey);
|
||||
}
|
||||
mEventDispatcher.notifyGroupCreated(group);
|
||||
}
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "onEntryAddedInternal: entry=" + added + " group=" + group.groupKey);
|
||||
Log.d(TAG, "onEntryAddedInternal: entry=" + logKey(added)
|
||||
+ " group=" + logGroupKey(group));
|
||||
}
|
||||
if (isGroupChild) {
|
||||
NotificationEntry existing = group.children.get(added.getKey());
|
||||
if (existing != null && existing != added) {
|
||||
Throwable existingThrowable = existing.getDebugThrowable();
|
||||
Log.wtf(TAG, "Inconsistent entries found with the same key " + added.getKey()
|
||||
Log.wtf(TAG, "Inconsistent entries found with the same key " + logKey(added)
|
||||
+ "existing removed: " + existing.isRowRemoved()
|
||||
+ (existingThrowable != null
|
||||
? Log.getStackTraceString(existingThrowable) + "\n" : "")
|
||||
@@ -262,9 +267,7 @@ public class NotificationGroupManagerLegacy implements
|
||||
for (NotificationEntry child : childrenCopy) {
|
||||
onEntryBecomingChild(child);
|
||||
}
|
||||
for (OnGroupChangeListener listener : mGroupChangeListeners) {
|
||||
listener.onGroupCreatedFromChildren(group);
|
||||
}
|
||||
mEventDispatcher.notifyGroupsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -323,30 +326,27 @@ public class NotificationGroupManagerLegacy implements
|
||||
boolean alertOverrideChanged = prevAlertOverride != group.alertOverride;
|
||||
boolean suppressionChanged = prevSuppressed != group.suppressed;
|
||||
if (alertOverrideChanged || suppressionChanged) {
|
||||
if (DEBUG && alertOverrideChanged) {
|
||||
Log.d(TAG, "updateSuppression: alertOverride was=" + prevAlertOverride
|
||||
+ " now=" + group.alertOverride + " group:\n" + group);
|
||||
}
|
||||
if (DEBUG && suppressionChanged) {
|
||||
Log.d(TAG,
|
||||
"updateSuppression: suppressed changed to " + group.suppressed
|
||||
+ " group:\n" + group);
|
||||
}
|
||||
if (!mIsUpdatingUnchangedGroup) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "updateSuppression:"
|
||||
+ " willNotifyListeners=" + !mIsUpdatingUnchangedGroup
|
||||
+ " changes for group:\n" + group);
|
||||
if (alertOverrideChanged) {
|
||||
mEventBuffer.notifyAlertOverrideChanged(group, prevAlertOverride);
|
||||
Log.d(TAG, "updateSuppression: alertOverride was=" + logKey(prevAlertOverride)
|
||||
+ " now=" + logKey(group.alertOverride));
|
||||
}
|
||||
if (suppressionChanged) {
|
||||
for (OnGroupChangeListener listener : mGroupChangeListeners) {
|
||||
listener.onGroupSuppressionChanged(group, group.suppressed);
|
||||
}
|
||||
}
|
||||
mEventBuffer.notifyGroupsChanged();
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, group + " did not notify listeners of above change(s)");
|
||||
Log.d(TAG, "updateSuppression: suppressed changed to " + group.suppressed);
|
||||
}
|
||||
}
|
||||
if (alertOverrideChanged) {
|
||||
mEventDispatcher.notifyAlertOverrideChanged(group, prevAlertOverride);
|
||||
}
|
||||
if (suppressionChanged) {
|
||||
mEventDispatcher.notifySuppressedChanged(group);
|
||||
}
|
||||
if (!mIsUpdatingUnchangedGroup) {
|
||||
mEventDispatcher.notifyGroupsChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -369,13 +369,15 @@ public class NotificationGroupManagerLegacy implements
|
||||
// but which should be alerting (because priority conversations are isolated), find it.
|
||||
if (group == null || group.summary == null) {
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride: null group or summary");
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride: null group or summary"
|
||||
+ " group=" + logGroupKey(group));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (isIsolated(group.summary.getKey())) {
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride: isolated group");
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride: isolated group"
|
||||
+ " group=" + logGroupKey(group));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -386,7 +388,8 @@ public class NotificationGroupManagerLegacy implements
|
||||
if (group.summary.getSbn().getNotification().getGroupAlertBehavior()
|
||||
== Notification.GROUP_ALERT_CHILDREN) {
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride: summary == GROUP_ALERT_CHILDREN");
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride: summary == GROUP_ALERT_CHILDREN"
|
||||
+ " group=" + logGroupKey(group));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -396,7 +399,8 @@ public class NotificationGroupManagerLegacy implements
|
||||
HashMap<String, NotificationEntry> children = getImportantConversations(group);
|
||||
if (children == null || children.isEmpty()) {
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride: no important conversations");
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride: no important conversations"
|
||||
+ " group=" + logGroupKey(group));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -408,8 +412,8 @@ public class NotificationGroupManagerLegacy implements
|
||||
if (child.getSbn().getNotification().getGroupAlertBehavior()
|
||||
!= Notification.GROUP_ALERT_SUMMARY) {
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride: "
|
||||
+ "child != GROUP_ALERT_SUMMARY");
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride: child != GROUP_ALERT_SUMMARY"
|
||||
+ " group=" + logGroupKey(group));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -450,13 +454,16 @@ public class NotificationGroupManagerLegacy implements
|
||||
}
|
||||
if (newestChild != null && importantChildKeys.contains(newestChild.getKey())) {
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride: result=" + newestChild);
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride:"
|
||||
+ " result=" + logKey(newestChild)
|
||||
+ " group=" + logGroupKey(group));
|
||||
}
|
||||
return newestChild;
|
||||
}
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride: result=null, newestChild="
|
||||
+ newestChild);
|
||||
Log.d(TAG, "getPriorityConversationAlertOverride:"
|
||||
+ " result=null newestChild=" + logKey(newestChild)
|
||||
+ " group=" + logGroupKey(group));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -500,7 +507,7 @@ public class NotificationGroupManagerLegacy implements
|
||||
*/
|
||||
public void onEntryUpdated(NotificationEntry entry, StatusBarNotification oldNotification) {
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "onEntryUpdated: entry=" + entry);
|
||||
Log.d(TAG, "onEntryUpdated: entry=" + logKey(entry));
|
||||
}
|
||||
onEntryUpdated(entry, oldNotification.getGroupKey(), oldNotification.isGroup(),
|
||||
oldNotification.getNotification().isGroupSummary());
|
||||
@@ -519,6 +526,7 @@ public class NotificationGroupManagerLegacy implements
|
||||
boolean groupKeysChanged = !oldGroupKey.equals(newGroupKey);
|
||||
boolean wasGroupChild = isGroupChild(entry.getKey(), oldIsGroup, oldIsGroupSummary);
|
||||
boolean isGroupChild = isGroupChild(entry.getSbn());
|
||||
mEventDispatcher.openBufferScope();
|
||||
mIsUpdatingUnchangedGroup = !groupKeysChanged && wasGroupChild == isGroupChild;
|
||||
if (mGroupMap.get(getGroupKey(entry.getKey(), oldGroupKey)) != null) {
|
||||
onEntryRemovedInternal(entry, oldGroupKey, oldIsGroup, oldIsGroupSummary);
|
||||
@@ -536,6 +544,7 @@ public class NotificationGroupManagerLegacy implements
|
||||
} else if (!wasGroupChild && isGroupChild) {
|
||||
onEntryBecomingChild(entry);
|
||||
}
|
||||
mEventDispatcher.closeBufferScope();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -798,7 +807,7 @@ public class NotificationGroupManagerLegacy implements
|
||||
*/
|
||||
private void isolateNotification(NotificationEntry entry) {
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "isolateNotification: entry=" + entry);
|
||||
Log.d(TAG, "isolateNotification: entry=" + logKey(entry));
|
||||
}
|
||||
// We will be isolated now, so lets update the groups
|
||||
onEntryRemovedInternal(entry, entry.getSbn());
|
||||
@@ -811,9 +820,7 @@ public class NotificationGroupManagerLegacy implements
|
||||
// When the notification gets added afterwards it is already isolated and therefore
|
||||
// it doesn't lead to an update.
|
||||
updateSuppression(mGroupMap.get(entry.getSbn().getGroupKey()));
|
||||
for (OnGroupChangeListener listener : mGroupChangeListeners) {
|
||||
listener.onGroupsChanged();
|
||||
}
|
||||
mEventDispatcher.notifyGroupsChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -827,7 +834,7 @@ public class NotificationGroupManagerLegacy implements
|
||||
// listener may be unable to correctly determine the true state of the group. By delaying
|
||||
// the alertOverride change until after the add phase, we can ensure that listeners only
|
||||
// have to handle a consistent state.
|
||||
mEventBuffer.startBuffering();
|
||||
mEventDispatcher.openBufferScope();
|
||||
boolean isIsolated = isIsolated(entry.getSbn().getKey());
|
||||
if (shouldIsolate(entry)) {
|
||||
if (!isIsolated) {
|
||||
@@ -836,7 +843,7 @@ public class NotificationGroupManagerLegacy implements
|
||||
} else if (isIsolated) {
|
||||
stopIsolatingNotification(entry);
|
||||
}
|
||||
mEventBuffer.flushAndStopBuffering();
|
||||
mEventDispatcher.closeBufferScope();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -846,15 +853,13 @@ public class NotificationGroupManagerLegacy implements
|
||||
*/
|
||||
private void stopIsolatingNotification(NotificationEntry entry) {
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "stopIsolatingNotification: entry=" + entry);
|
||||
Log.d(TAG, "stopIsolatingNotification: entry=" + logKey(entry));
|
||||
}
|
||||
// not isolated anymore, we need to update the groups
|
||||
onEntryRemovedInternal(entry, entry.getSbn());
|
||||
mIsolatedEntries.remove(entry.getKey());
|
||||
onEntryAddedInternal(entry);
|
||||
for (OnGroupChangeListener listener : mGroupChangeListeners) {
|
||||
listener.onGroupsChanged();
|
||||
}
|
||||
mEventDispatcher.notifyGroupsChanged();
|
||||
}
|
||||
|
||||
private boolean isGroupNotFullyVisible(NotificationGroup notificationGroup) {
|
||||
@@ -874,11 +879,11 @@ public class NotificationGroupManagerLegacy implements
|
||||
pw.println("GroupManagerLegacy state:");
|
||||
pw.println(" number of groups: " + mGroupMap.size());
|
||||
for (Map.Entry<String, NotificationGroup> entry : mGroupMap.entrySet()) {
|
||||
pw.println("\n key: " + entry.getKey()); pw.println(entry.getValue());
|
||||
pw.println("\n key: " + logKey(entry.getKey())); pw.println(entry.getValue());
|
||||
}
|
||||
pw.println("\n isolated entries: " + mIsolatedEntries.size());
|
||||
for (Map.Entry<String, StatusBarNotification> entry : mIsolatedEntries.entrySet()) {
|
||||
pw.print(" "); pw.print(entry.getKey());
|
||||
pw.print(" "); pw.print(logKey(entry.getKey()));
|
||||
pw.print(", "); pw.println(entry.getValue());
|
||||
}
|
||||
}
|
||||
@@ -888,6 +893,14 @@ public class NotificationGroupManagerLegacy implements
|
||||
setStatusBarState(newState);
|
||||
}
|
||||
|
||||
/** Get the group key, reformatted for logging, for the (optional) group */
|
||||
public static String logGroupKey(NotificationGroup group) {
|
||||
if (group == null) {
|
||||
return "null";
|
||||
}
|
||||
return logKey(group.groupKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* A record of a notification being posted, containing the time of the post and the key of the
|
||||
* notification entry. These are stored in a TreeSet by the NotificationGroup and used to
|
||||
@@ -977,18 +990,35 @@ public class NotificationGroupManagerLegacy implements
|
||||
* When buffering, instead of notifying the listeners it will set internal state that will allow
|
||||
* it to notify listeners of those events later
|
||||
*/
|
||||
private class EventBuffer {
|
||||
static class GroupEventDispatcher {
|
||||
private final Function<String, NotificationGroup> mGroupMapGetter;
|
||||
private final ArraySet<OnGroupChangeListener> mGroupChangeListeners = new ArraySet<>();
|
||||
private final HashMap<String, NotificationEntry> mOldAlertOverrideByGroup = new HashMap<>();
|
||||
private boolean mIsBuffering = false;
|
||||
private final HashMap<String, Boolean> mOldSuppressedByGroup = new HashMap<>();
|
||||
private int mBufferScopeDepth = 0;
|
||||
private boolean mDidGroupsChange = false;
|
||||
|
||||
GroupEventDispatcher(Function<String, NotificationGroup> groupMapGetter) {
|
||||
mGroupMapGetter = requireNonNull(groupMapGetter);
|
||||
}
|
||||
|
||||
void registerGroupChangeListener(OnGroupChangeListener listener) {
|
||||
mGroupChangeListeners.add(listener);
|
||||
}
|
||||
|
||||
private boolean isBuffering() {
|
||||
return mBufferScopeDepth > 0;
|
||||
}
|
||||
|
||||
void notifyAlertOverrideChanged(NotificationGroup group,
|
||||
NotificationEntry oldAlertOverride) {
|
||||
if (mIsBuffering) {
|
||||
if (isBuffering()) {
|
||||
// The value in this map is the override before the event. If there is an entry
|
||||
// already in the map, then we are effectively coalescing two events, which means
|
||||
// we need to preserve the original initial value.
|
||||
mOldAlertOverrideByGroup.putIfAbsent(group.groupKey, oldAlertOverride);
|
||||
if (!mOldAlertOverrideByGroup.containsKey(group.groupKey)) {
|
||||
mOldAlertOverrideByGroup.put(group.groupKey, oldAlertOverride);
|
||||
}
|
||||
} else {
|
||||
for (OnGroupChangeListener listener : mGroupChangeListeners) {
|
||||
listener.onGroupAlertOverrideChanged(group, oldAlertOverride,
|
||||
@@ -997,8 +1027,21 @@ public class NotificationGroupManagerLegacy implements
|
||||
}
|
||||
}
|
||||
|
||||
void notifySuppressedChanged(NotificationGroup group) {
|
||||
if (isBuffering()) {
|
||||
// The value in this map is the 'suppressed' before the event. If there is a value
|
||||
// already in the map, then we are effectively coalescing two events, which means
|
||||
// we need to preserve the original initial value.
|
||||
mOldSuppressedByGroup.putIfAbsent(group.groupKey, !group.suppressed);
|
||||
} else {
|
||||
for (OnGroupChangeListener listener : mGroupChangeListeners) {
|
||||
listener.onGroupSuppressionChanged(group, group.suppressed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void notifyGroupsChanged() {
|
||||
if (mIsBuffering) {
|
||||
if (isBuffering()) {
|
||||
mDidGroupsChange = true;
|
||||
} else {
|
||||
for (OnGroupChangeListener listener : mGroupChangeListeners) {
|
||||
@@ -1007,26 +1050,94 @@ public class NotificationGroupManagerLegacy implements
|
||||
}
|
||||
}
|
||||
|
||||
void startBuffering() {
|
||||
mIsBuffering = true;
|
||||
void notifyGroupCreated(NotificationGroup group) {
|
||||
// NOTE: given how this event is used, it doesn't need to be buffered right now
|
||||
final String groupKey = group.groupKey;
|
||||
for (OnGroupChangeListener listener : mGroupChangeListeners) {
|
||||
listener.onGroupCreated(group, groupKey);
|
||||
}
|
||||
}
|
||||
|
||||
void flushAndStopBuffering() {
|
||||
// stop buffering so that we can call our own helpers
|
||||
mIsBuffering = false;
|
||||
void notifyGroupRemoved(NotificationGroup group) {
|
||||
// NOTE: given how this event is used, it doesn't need to be buffered right now
|
||||
final String groupKey = group.groupKey;
|
||||
for (OnGroupChangeListener listener : mGroupChangeListeners) {
|
||||
listener.onGroupRemoved(group, groupKey);
|
||||
}
|
||||
}
|
||||
|
||||
void openBufferScope() {
|
||||
mBufferScopeDepth++;
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "openBufferScope: scopeDepth=" + mBufferScopeDepth);
|
||||
}
|
||||
}
|
||||
|
||||
void closeBufferScope() {
|
||||
mBufferScopeDepth--;
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "closeBufferScope: scopeDepth=" + mBufferScopeDepth);
|
||||
}
|
||||
// Flush buffered events if the last buffer scope has closed
|
||||
if (!isBuffering()) {
|
||||
flushBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
private void flushBuffer() {
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "flushBuffer: "
|
||||
+ " suppressed.size=" + mOldSuppressedByGroup.size()
|
||||
+ " alertOverride.size=" + mOldAlertOverrideByGroup.size()
|
||||
+ " mDidGroupsChange=" + mDidGroupsChange);
|
||||
}
|
||||
// alert all group suppressed changes for groups that were not removed
|
||||
for (Map.Entry<String, Boolean> entry : mOldSuppressedByGroup.entrySet()) {
|
||||
NotificationGroup group = mGroupMapGetter.apply(entry.getKey());
|
||||
if (group == null) {
|
||||
// The group can be null if this suppressed changed before the group was
|
||||
// permanently removed, meaning that there's no guarantee that listeners will
|
||||
// that field clear.
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "flushBuffer: suppressed:"
|
||||
+ " cannot report for removed group: " + logKey(entry.getKey()));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
boolean oldSuppressed = entry.getValue();
|
||||
if (group.suppressed == oldSuppressed) {
|
||||
// If the final suppressed equals the initial, it means we coalesced two
|
||||
// events which undid the change, so we can drop it entirely.
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "flushBuffer: suppressed:"
|
||||
+ " did not change for group: " + logKey(entry.getKey()));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
notifySuppressedChanged(group);
|
||||
}
|
||||
mOldSuppressedByGroup.clear();
|
||||
// alert all group alert override changes for groups that were not removed
|
||||
for (Map.Entry<String, NotificationEntry> entry : mOldAlertOverrideByGroup.entrySet()) {
|
||||
NotificationGroup group = mGroupMap.get(entry.getKey());
|
||||
NotificationGroup group = mGroupMapGetter.apply(entry.getKey());
|
||||
if (group == null) {
|
||||
// The group can be null if this alertOverride changed before the group was
|
||||
// permanently removed, meaning that there's no guarantee that listeners will
|
||||
// that field clear.
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "flushBuffer: alertOverride:"
|
||||
+ " cannot report for removed group: " + entry.getKey());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
NotificationEntry oldAlertOverride = entry.getValue();
|
||||
if (group.alertOverride == oldAlertOverride) {
|
||||
// If the final alertOverride equals the initial, it means we coalesced two
|
||||
// events which undid the change, so we can drop it entirely.
|
||||
if (SPEW) {
|
||||
Log.d(TAG, "flushBuffer: alertOverride:"
|
||||
+ " did not change for group: " + logKey(entry.getKey()));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
notifyAlertOverrideChanged(group, oldAlertOverride);
|
||||
@@ -1087,14 +1198,6 @@ public class NotificationGroupManagerLegacy implements
|
||||
@Nullable NotificationEntry oldAlertOverride,
|
||||
@Nullable NotificationEntry newAlertOverride) {}
|
||||
|
||||
/**
|
||||
* A group of children just received a summary notification and should therefore become
|
||||
* children of it.
|
||||
*
|
||||
* @param group the group created
|
||||
*/
|
||||
default void onGroupCreatedFromChildren(NotificationGroup group) {}
|
||||
|
||||
/**
|
||||
* The groups have changed. This can happen if the isolation of a child has changes or if a
|
||||
* group became suppressed / unsuppressed
|
||||
|
||||
@@ -93,7 +93,6 @@ import com.android.systemui.statusbar.notification.collection.NotifCollection;
|
||||
import com.android.systemui.statusbar.notification.collection.NotifPipeline;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.NotificationGroup;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.OnGroupChangeListener;
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
|
||||
import com.android.systemui.statusbar.notification.collection.notifcollection.DismissedByUserStats;
|
||||
@@ -688,11 +687,6 @@ public class NotificationStackScrollLayoutController {
|
||||
groupManager.registerGroupExpansionChangeListener(
|
||||
(changedRow, expanded) -> mView.onGroupExpandChanged(changedRow, expanded));
|
||||
legacyGroupManager.registerGroupChangeListener(new OnGroupChangeListener() {
|
||||
@Override
|
||||
public void onGroupCreatedFromChildren(NotificationGroup group) {
|
||||
mStatusBar.requestNotificationUpdate("onGroupCreatedFromChildren");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGroupsChanged() {
|
||||
mStatusBar.requestNotificationUpdate("onGroupsChanged");
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import static com.android.systemui.statusbar.notification.NotificationUtils.logKey;
|
||||
import static com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.logGroupKey;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Notification;
|
||||
@@ -148,7 +151,9 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
|
||||
@Override
|
||||
public void onGroupSuppressionChanged(NotificationGroup group, boolean suppressed) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "!! onGroupSuppressionChanged: group.summary=" + group.summary
|
||||
Log.d(TAG, "!! onGroupSuppressionChanged:"
|
||||
+ " group=" + logGroupKey(group)
|
||||
+ " group.summary=" + logKey(group.summary)
|
||||
+ " suppressed=" + suppressed);
|
||||
}
|
||||
NotificationEntry oldAlertOverride = group.alertOverride;
|
||||
@@ -160,9 +165,11 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
|
||||
@Nullable NotificationEntry oldAlertOverride,
|
||||
@Nullable NotificationEntry newAlertOverride) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "!! onGroupAlertOverrideChanged: group.summary=" + group.summary
|
||||
+ " oldAlertOverride=" + oldAlertOverride
|
||||
+ " newAlertOverride=" + newAlertOverride);
|
||||
Log.d(TAG, "!! onGroupAlertOverrideChanged:"
|
||||
+ " group=" + logGroupKey(group)
|
||||
+ " group.summary=" + logKey(group.summary)
|
||||
+ " oldAlertOverride=" + logKey(oldAlertOverride)
|
||||
+ " newAlertOverride=" + logKey(newAlertOverride));
|
||||
}
|
||||
onGroupChanged(group, oldAlertOverride);
|
||||
}
|
||||
@@ -208,7 +215,9 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
|
||||
@Override
|
||||
public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "!! onHeadsUpStateChanged: entry=" + entry + " isHeadsUp=" + isHeadsUp);
|
||||
Log.d(TAG, "!! onHeadsUpStateChanged:"
|
||||
+ " entry=" + logKey(entry)
|
||||
+ " isHeadsUp=" + isHeadsUp);
|
||||
}
|
||||
if (isHeadsUp && entry.getSbn().getNotification().isGroupSummary()) {
|
||||
// a group summary is alerting; trigger the forward transfer checks
|
||||
@@ -240,6 +249,9 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
|
||||
} else if (mGroupManager.isSummaryOfSuppressedGroup(summary.getSbn())) {
|
||||
handleSuppressedSummaryAlerted(summary, oldAlertOverride);
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "checkForForwardAlertTransfer: done");
|
||||
}
|
||||
}
|
||||
|
||||
private final NotificationEntryListener mNotificationEntryListener =
|
||||
@@ -249,7 +261,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
|
||||
@Override
|
||||
public void onPendingEntryAdded(NotificationEntry entry) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "!! onPendingEntryAdded: entry=" + entry);
|
||||
Log.d(TAG, "!! onPendingEntryAdded: entry=" + logKey(entry));
|
||||
}
|
||||
String groupKey = mGroupManager.getGroupKey(entry.getSbn());
|
||||
GroupAlertEntry groupAlertEntry = mGroupAlertEntries.get(groupKey);
|
||||
@@ -345,7 +357,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
|
||||
private void handleSuppressedSummaryAlerted(@NonNull NotificationEntry summary,
|
||||
NotificationEntry oldAlertOverride) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "handleSuppressedSummaryAlerted: summary=" + summary);
|
||||
Log.d(TAG, "handleSuppressedSummaryAlerted: summary=" + logKey(summary));
|
||||
}
|
||||
GroupAlertEntry groupAlertEntry =
|
||||
mGroupAlertEntries.get(mGroupManager.getGroupKey(summary.getSbn()));
|
||||
@@ -407,7 +419,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
|
||||
*/
|
||||
private void handleOverriddenSummaryAlerted(NotificationEntry summary) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "handleOverriddenSummaryAlerted: summary=" + summary);
|
||||
Log.d(TAG, "handleOverriddenSummaryAlerted: summary=" + logKey(summary));
|
||||
}
|
||||
GroupAlertEntry groupAlertEntry =
|
||||
mGroupAlertEntries.get(mGroupManager.getGroupKey(summary.getSbn()));
|
||||
@@ -481,7 +493,9 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
|
||||
groupAlertEntry.mLastAlertTransferTime = SystemClock.elapsedRealtime();
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "transferAlertState: fromEntry=" + fromEntry + " toEntry=" + toEntry);
|
||||
Log.d(TAG, "transferAlertState:"
|
||||
+ " fromEntry=" + logKey(fromEntry)
|
||||
+ " toEntry=" + logKey(toEntry));
|
||||
}
|
||||
transferAlertState(fromEntry, toEntry);
|
||||
}
|
||||
@@ -583,7 +597,8 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
|
||||
final RowContentBindParams params = mRowContentBindStage.getStageParams(entry);
|
||||
if ((params.getContentViews() & contentFlag) == 0) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "alertNotificationWhenPossible: async requestRebind entry=" + entry);
|
||||
Log.d(TAG, "alertNotificationWhenPossible:"
|
||||
+ " async requestRebind entry=" + logKey(entry));
|
||||
}
|
||||
mPendingAlerts.put(entry.getKey(), new PendingAlertInfo(entry));
|
||||
params.requireContentViews(contentFlag);
|
||||
@@ -593,6 +608,10 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
|
||||
if (alertInfo.isStillValid()) {
|
||||
alertNotificationWhenPossible(entry);
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "alertNotificationWhenPossible:"
|
||||
+ " markContentViewsFreeable entry=" + logKey(entry));
|
||||
}
|
||||
// The transfer is no longer valid. Free the content.
|
||||
mRowContentBindStage.getStageParams(entry).markContentViewsFreeable(
|
||||
contentFlag);
|
||||
@@ -604,12 +623,14 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
|
||||
}
|
||||
if (mHeadsUpManager.isAlerting(entry.getKey())) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "alertNotificationWhenPossible: continue alerting entry=" + entry);
|
||||
Log.d(TAG, "alertNotificationWhenPossible:"
|
||||
+ " continue alerting entry=" + logKey(entry));
|
||||
}
|
||||
mHeadsUpManager.updateNotification(entry.getKey(), true /* alert */);
|
||||
} else {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "alertNotificationWhenPossible: start alerting entry=" + entry);
|
||||
Log.d(TAG, "alertNotificationWhenPossible:"
|
||||
+ " start alerting entry=" + logKey(entry));
|
||||
}
|
||||
mHeadsUpManager.showNotification(entry);
|
||||
}
|
||||
@@ -657,7 +678,7 @@ public class NotificationGroupAlertTransferHelper implements OnHeadsUpChangedLis
|
||||
// Notification is aborted due to the transfer being explicitly cancelled
|
||||
return false;
|
||||
}
|
||||
if (mEntry.getSbn().getGroupKey() != mOriginalNotification.getGroupKey()) {
|
||||
if (!mEntry.getSbn().getGroupKey().equals(mOriginalNotification.getGroupKey())) {
|
||||
// Groups have changed
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.legacy
|
||||
|
||||
import android.testing.AndroidTestingRunner
|
||||
import android.testing.TestableLooper.RunWithLooper
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.GroupEventDispatcher
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.NotificationGroup
|
||||
import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy.OnGroupChangeListener
|
||||
import com.android.systemui.statusbar.phone.NotificationGroupTestHelper
|
||||
import com.android.systemui.util.mockito.mock
|
||||
import org.junit.Before
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mockito.verify
|
||||
import org.mockito.Mockito.verifyNoMoreInteractions
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidTestingRunner::class)
|
||||
@RunWithLooper
|
||||
class GroupEventDispatcherTest : SysuiTestCase() {
|
||||
val groupMap = mutableMapOf<String, NotificationGroup>()
|
||||
val groupTestHelper = NotificationGroupTestHelper(mContext)
|
||||
|
||||
private val dispatcher = GroupEventDispatcher(groupMap::get)
|
||||
private val listener: OnGroupChangeListener = mock()
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
dispatcher.registerGroupChangeListener(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnGroupsChangedUnbuffered() {
|
||||
dispatcher.notifyGroupsChanged()
|
||||
verify(listener).onGroupsChanged()
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnGroupsChangedBuffered() {
|
||||
dispatcher.openBufferScope()
|
||||
dispatcher.notifyGroupsChanged()
|
||||
verifyNoMoreInteractions(listener)
|
||||
dispatcher.closeBufferScope()
|
||||
verify(listener).onGroupsChanged()
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnGroupsChangedDoubleBuffered() {
|
||||
dispatcher.openBufferScope()
|
||||
dispatcher.notifyGroupsChanged()
|
||||
dispatcher.openBufferScope() // open a nested buffer scope
|
||||
dispatcher.notifyGroupsChanged()
|
||||
dispatcher.closeBufferScope() // should NOT flush events
|
||||
dispatcher.notifyGroupsChanged()
|
||||
verifyNoMoreInteractions(listener)
|
||||
dispatcher.closeBufferScope() // this SHOULD flush events
|
||||
verify(listener).onGroupsChanged()
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnGroupsChangedBufferCoalesces() {
|
||||
dispatcher.openBufferScope()
|
||||
dispatcher.notifyGroupsChanged()
|
||||
dispatcher.notifyGroupsChanged()
|
||||
verifyNoMoreInteractions(listener)
|
||||
dispatcher.closeBufferScope()
|
||||
verify(listener).onGroupsChanged()
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnGroupCreatedIsNeverBuffered() {
|
||||
val group = addGroup(1)
|
||||
|
||||
dispatcher.openBufferScope()
|
||||
dispatcher.notifyGroupCreated(group)
|
||||
verify(listener).onGroupCreated(group, group.groupKey)
|
||||
verifyNoMoreInteractions(listener)
|
||||
|
||||
dispatcher.closeBufferScope()
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testOnGroupRemovedIsNeverBuffered() {
|
||||
val group = addGroup(1)
|
||||
|
||||
dispatcher.openBufferScope()
|
||||
dispatcher.notifyGroupRemoved(group)
|
||||
verify(listener).onGroupRemoved(group, group.groupKey)
|
||||
verifyNoMoreInteractions(listener)
|
||||
|
||||
dispatcher.closeBufferScope()
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAlertOverrideAddedUnbuffered() {
|
||||
val group = addGroup(1)
|
||||
val newAlertEntry = groupTestHelper.createChildNotification()
|
||||
group.alertOverride = newAlertEntry
|
||||
dispatcher.notifyAlertOverrideChanged(group, null)
|
||||
verify(listener).onGroupAlertOverrideChanged(group, null, newAlertEntry)
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAlertOverrideRemovedUnbuffered() {
|
||||
val group = addGroup(1)
|
||||
val oldAlertEntry = groupTestHelper.createChildNotification()
|
||||
dispatcher.notifyAlertOverrideChanged(group, oldAlertEntry)
|
||||
verify(listener).onGroupAlertOverrideChanged(group, oldAlertEntry, null)
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAlertOverrideChangedUnbuffered() {
|
||||
val group = addGroup(1)
|
||||
val oldAlertEntry = groupTestHelper.createChildNotification()
|
||||
val newAlertEntry = groupTestHelper.createChildNotification()
|
||||
group.alertOverride = newAlertEntry
|
||||
dispatcher.notifyAlertOverrideChanged(group, oldAlertEntry)
|
||||
verify(listener).onGroupAlertOverrideChanged(group, oldAlertEntry, newAlertEntry)
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAlertOverrideChangedBuffered() {
|
||||
dispatcher.openBufferScope()
|
||||
val group = addGroup(1)
|
||||
val oldAlertEntry = groupTestHelper.createChildNotification()
|
||||
val newAlertEntry = groupTestHelper.createChildNotification()
|
||||
group.alertOverride = newAlertEntry
|
||||
dispatcher.notifyAlertOverrideChanged(group, oldAlertEntry)
|
||||
verifyNoMoreInteractions(listener)
|
||||
dispatcher.closeBufferScope()
|
||||
verify(listener).onGroupAlertOverrideChanged(group, oldAlertEntry, newAlertEntry)
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAlertOverrideIgnoredIfRemoved() {
|
||||
dispatcher.openBufferScope()
|
||||
val group = addGroup(1)
|
||||
val oldAlertEntry = groupTestHelper.createChildNotification()
|
||||
val newAlertEntry = groupTestHelper.createChildNotification()
|
||||
group.alertOverride = newAlertEntry
|
||||
dispatcher.notifyAlertOverrideChanged(group, oldAlertEntry)
|
||||
verifyNoMoreInteractions(listener)
|
||||
groupMap.clear()
|
||||
dispatcher.closeBufferScope()
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAlertOverrideMultipleChangesBuffered() {
|
||||
dispatcher.openBufferScope()
|
||||
val group = addGroup(1)
|
||||
val oldAlertEntry = groupTestHelper.createChildNotification()
|
||||
val newAlertEntry = groupTestHelper.createChildNotification()
|
||||
group.alertOverride = null
|
||||
dispatcher.notifyAlertOverrideChanged(group, oldAlertEntry)
|
||||
group.alertOverride = newAlertEntry
|
||||
dispatcher.notifyAlertOverrideChanged(group, null)
|
||||
verifyNoMoreInteractions(listener)
|
||||
dispatcher.closeBufferScope()
|
||||
verify(listener).onGroupAlertOverrideChanged(group, oldAlertEntry, newAlertEntry)
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAlertOverrideTemporaryValueSwallowed() {
|
||||
dispatcher.openBufferScope()
|
||||
val group = addGroup(1)
|
||||
val stableAlertEntry = groupTestHelper.createChildNotification()
|
||||
group.alertOverride = null
|
||||
dispatcher.notifyAlertOverrideChanged(group, stableAlertEntry)
|
||||
group.alertOverride = stableAlertEntry
|
||||
dispatcher.notifyAlertOverrideChanged(group, null)
|
||||
verifyNoMoreInteractions(listener)
|
||||
dispatcher.closeBufferScope()
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testAlertOverrideTemporaryNullSwallowed() {
|
||||
dispatcher.openBufferScope()
|
||||
val group = addGroup(1)
|
||||
val temporaryAlertEntry = groupTestHelper.createChildNotification()
|
||||
group.alertOverride = temporaryAlertEntry
|
||||
dispatcher.notifyAlertOverrideChanged(group, null)
|
||||
group.alertOverride = null
|
||||
dispatcher.notifyAlertOverrideChanged(group, temporaryAlertEntry)
|
||||
verifyNoMoreInteractions(listener)
|
||||
dispatcher.closeBufferScope()
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSuppressOnUnbuffered() {
|
||||
val group = addGroup(1)
|
||||
group.suppressed = true
|
||||
dispatcher.notifySuppressedChanged(group)
|
||||
verify(listener).onGroupSuppressionChanged(group, true)
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSuppressOffUnbuffered() {
|
||||
val group = addGroup(1)
|
||||
group.suppressed = false
|
||||
dispatcher.notifySuppressedChanged(group)
|
||||
verify(listener).onGroupSuppressionChanged(group, false)
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSuppressOnBuffered() {
|
||||
dispatcher.openBufferScope()
|
||||
val group = addGroup(1)
|
||||
group.suppressed = false
|
||||
dispatcher.notifySuppressedChanged(group)
|
||||
verifyNoMoreInteractions(listener)
|
||||
dispatcher.closeBufferScope()
|
||||
verify(listener).onGroupSuppressionChanged(group, false)
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSuppressOnIgnoredIfRemoved() {
|
||||
dispatcher.openBufferScope()
|
||||
val group = addGroup(1)
|
||||
group.suppressed = false
|
||||
dispatcher.notifySuppressedChanged(group)
|
||||
verifyNoMoreInteractions(listener)
|
||||
groupMap.clear()
|
||||
dispatcher.closeBufferScope()
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSuppressOnOffBuffered() {
|
||||
dispatcher.openBufferScope()
|
||||
val group = addGroup(1)
|
||||
group.suppressed = true
|
||||
dispatcher.notifySuppressedChanged(group)
|
||||
group.suppressed = false
|
||||
dispatcher.notifySuppressedChanged(group)
|
||||
verifyNoMoreInteractions(listener)
|
||||
dispatcher.closeBufferScope()
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testSuppressOnOffOnBuffered() {
|
||||
dispatcher.openBufferScope()
|
||||
val group = addGroup(1)
|
||||
group.suppressed = true
|
||||
dispatcher.notifySuppressedChanged(group)
|
||||
group.suppressed = false
|
||||
dispatcher.notifySuppressedChanged(group)
|
||||
group.suppressed = true
|
||||
dispatcher.notifySuppressedChanged(group)
|
||||
verifyNoMoreInteractions(listener)
|
||||
dispatcher.closeBufferScope()
|
||||
verify(listener).onGroupSuppressionChanged(group, true)
|
||||
verifyNoMoreInteractions(listener)
|
||||
}
|
||||
|
||||
private fun addGroup(id: Int): NotificationGroup {
|
||||
val group = NotificationGroup("group:$id")
|
||||
groupMap[group.groupKey] = group
|
||||
return group
|
||||
}
|
||||
}
|
||||
@@ -312,10 +312,11 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase {
|
||||
|
||||
@Test
|
||||
public void testUpdateChildToSummaryDoesNotTransfer() {
|
||||
final String tag = "fooTag";
|
||||
NotificationEntry summaryEntry =
|
||||
mGroupTestHelper.createSummaryNotification(Notification.GROUP_ALERT_SUMMARY);
|
||||
NotificationEntry childEntry =
|
||||
mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY, 47);
|
||||
mGroupTestHelper.createChildNotification(Notification.GROUP_ALERT_SUMMARY, 47, tag);
|
||||
mockHasHeadsUpContentView(childEntry, false);
|
||||
|
||||
mHeadsUpManager.showNotification(summaryEntry);
|
||||
@@ -327,7 +328,7 @@ public class NotificationGroupAlertTransferHelperTest extends SysuiTestCase {
|
||||
StatusBarNotification oldNotification = childEntry.getSbn();
|
||||
childEntry.setSbn(
|
||||
mGroupTestHelper.createSummaryNotification(
|
||||
Notification.GROUP_ALERT_SUMMARY, 47).getSbn());
|
||||
Notification.GROUP_ALERT_SUMMARY, 47, tag).getSbn());
|
||||
mGroupManager.onEntryUpdated(childEntry, oldNotification);
|
||||
|
||||
assertFalse(mGroupAlertTransferHelper.isAlertTransferPending(childEntry));
|
||||
|
||||
@@ -21,14 +21,19 @@ import static junit.framework.Assert.assertFalse;
|
||||
import static junit.framework.Assert.assertTrue;
|
||||
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoMoreInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.testing.AndroidTestingRunner;
|
||||
import android.testing.TestableLooper;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -64,8 +69,10 @@ public class NotificationGroupManagerLegacyTest extends SysuiTestCase {
|
||||
private final NotificationGroupTestHelper mGroupTestHelper =
|
||||
new NotificationGroupTestHelper(mContext);
|
||||
|
||||
@Mock PeopleNotificationIdentifier mPeopleNotificationIdentifier;
|
||||
@Mock HeadsUpManager mHeadsUpManager;
|
||||
@Mock
|
||||
PeopleNotificationIdentifier mPeopleNotificationIdentifier;
|
||||
@Mock
|
||||
HeadsUpManager mHeadsUpManager;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
@@ -177,15 +184,25 @@ public class NotificationGroupManagerLegacyTest extends SysuiTestCase {
|
||||
helpTestAlertOverrideWithSiblings(2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlertOverrideWithSiblings_3() {
|
||||
helpTestAlertOverrideWithSiblings(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlertOverrideWithSiblings_9() {
|
||||
helpTestAlertOverrideWithSiblings(9);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for testing various sibling counts
|
||||
*/
|
||||
private void helpTestAlertOverrideWithSiblings(int numSiblings) {
|
||||
helpTestAlertOverride(
|
||||
/* numSiblings */ numSiblings,
|
||||
/* summaryAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* childAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* siblingAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* summaryGroupAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* priorityGroupAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* siblingGroupAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* expectAlertOverride */ true);
|
||||
}
|
||||
|
||||
@@ -194,9 +211,9 @@ public class NotificationGroupManagerLegacyTest extends SysuiTestCase {
|
||||
// tests that summary can have GROUP_ALERT_ALL and this still works
|
||||
helpTestAlertOverride(
|
||||
/* numSiblings */ 1,
|
||||
/* summaryAlert */ Notification.GROUP_ALERT_ALL,
|
||||
/* childAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* siblingAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* summaryGroupAlert */ Notification.GROUP_ALERT_ALL,
|
||||
/* priorityGroupAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* siblingGroupAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* expectAlertOverride */ true);
|
||||
}
|
||||
|
||||
@@ -205,9 +222,9 @@ public class NotificationGroupManagerLegacyTest extends SysuiTestCase {
|
||||
// Tests that if the summary alerts CHILDREN, there's no alertOverride
|
||||
helpTestAlertOverride(
|
||||
/* numSiblings */ 1,
|
||||
/* summaryAlert */ Notification.GROUP_ALERT_CHILDREN,
|
||||
/* childAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* siblingAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* summaryGroupAlert */ Notification.GROUP_ALERT_CHILDREN,
|
||||
/* priorityGroupAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* siblingGroupAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* expectAlertOverride */ false);
|
||||
}
|
||||
|
||||
@@ -216,9 +233,9 @@ public class NotificationGroupManagerLegacyTest extends SysuiTestCase {
|
||||
// Tests that if the children alert ALL, there's no alertOverride
|
||||
helpTestAlertOverride(
|
||||
/* numSiblings */ 1,
|
||||
/* summaryAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* childAlert */ Notification.GROUP_ALERT_ALL,
|
||||
/* siblingAlert */ Notification.GROUP_ALERT_ALL,
|
||||
/* summaryGroupAlert */ Notification.GROUP_ALERT_SUMMARY,
|
||||
/* priorityGroupAlert */ Notification.GROUP_ALERT_ALL,
|
||||
/* siblingGroupAlert */ Notification.GROUP_ALERT_ALL,
|
||||
/* expectAlertOverride */ false);
|
||||
}
|
||||
|
||||
@@ -229,17 +246,19 @@ public class NotificationGroupManagerLegacyTest extends SysuiTestCase {
|
||||
* 3) when the priority entry is removed, these are reversed
|
||||
*/
|
||||
private void helpTestAlertOverride(int numSiblings,
|
||||
@Notification.GroupAlertBehavior int summaryAlert,
|
||||
@Notification.GroupAlertBehavior int childAlert,
|
||||
@Notification.GroupAlertBehavior int siblingAlert,
|
||||
@Notification.GroupAlertBehavior int summaryGroupAlert,
|
||||
@Notification.GroupAlertBehavior int priorityGroupAlert,
|
||||
@Notification.GroupAlertBehavior int siblingGroupAlert,
|
||||
boolean expectAlertOverride) {
|
||||
// Create entries in an order so that the priority entry can be deemed the newest child.
|
||||
NotificationEntry[] siblings = new NotificationEntry[numSiblings];
|
||||
for (int i = 0; i < numSiblings; i++) {
|
||||
siblings[i] = mGroupTestHelper.createChildNotification(siblingAlert);
|
||||
siblings[i] = mGroupTestHelper.createChildNotification(siblingGroupAlert, i, "sibling");
|
||||
}
|
||||
NotificationEntry priorityEntry = mGroupTestHelper.createChildNotification(childAlert);
|
||||
NotificationEntry summaryEntry = mGroupTestHelper.createSummaryNotification(summaryAlert);
|
||||
NotificationEntry priorityEntry =
|
||||
mGroupTestHelper.createChildNotification(priorityGroupAlert, 0, "priority");
|
||||
NotificationEntry summaryEntry =
|
||||
mGroupTestHelper.createSummaryNotification(summaryGroupAlert, 0, "summary");
|
||||
|
||||
// The priority entry is an important conversation.
|
||||
when(mPeopleNotificationIdentifier.getPeopleNotificationType(eq(priorityEntry)))
|
||||
@@ -263,11 +282,20 @@ public class NotificationGroupManagerLegacyTest extends SysuiTestCase {
|
||||
assertNull(summaryGroup.alertOverride);
|
||||
return;
|
||||
}
|
||||
int max2Siblings = Math.min(2, numSiblings);
|
||||
|
||||
// Verify that the summary group has the priority child as its alertOverride
|
||||
NotificationGroup summaryGroup = mGroupManager.getGroupForSummary(summaryEntry.getSbn());
|
||||
assertEquals(priorityEntry, summaryGroup.alertOverride);
|
||||
verify(groupChangeListener).onGroupAlertOverrideChanged(summaryGroup, null, priorityEntry);
|
||||
verify(groupChangeListener).onGroupSuppressionChanged(summaryGroup, true);
|
||||
if (numSiblings > 1) {
|
||||
verify(groupChangeListener).onGroupSuppressionChanged(summaryGroup, false);
|
||||
}
|
||||
verify(groupChangeListener).onGroupCreated(any(), eq(priorityEntry.getKey()));
|
||||
verify(groupChangeListener).onGroupCreated(any(), eq(summaryEntry.getSbn().getGroupKey()));
|
||||
verify(groupChangeListener, times(max2Siblings + 1)).onGroupsChanged();
|
||||
verifyNoMoreInteractions(groupChangeListener);
|
||||
|
||||
// Verify that only the priority notification is isolated from the group
|
||||
assertEquals(priorityEntry, mGroupManager.getGroupSummary(priorityEntry));
|
||||
@@ -283,6 +311,92 @@ public class NotificationGroupManagerLegacyTest extends SysuiTestCase {
|
||||
|
||||
// verify that the alertOverride is removed when the priority notification is
|
||||
assertNull(summaryGroup.alertOverride);
|
||||
verify(groupChangeListener).onGroupAlertOverrideChanged(summaryGroup, priorityEntry, null);
|
||||
verify(groupChangeListener).onGroupRemoved(any(), eq(priorityEntry.getKey()));
|
||||
verify(groupChangeListener, times(max2Siblings + 2)).onGroupsChanged();
|
||||
if (numSiblings == 0) {
|
||||
verify(groupChangeListener).onGroupSuppressionChanged(summaryGroup, false);
|
||||
}
|
||||
verifyNoMoreInteractions(groupChangeListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAlertOverrideWhenUpdatingSummaryAtEnd() {
|
||||
int numSiblings = 2;
|
||||
int groupAlert = Notification.GROUP_ALERT_SUMMARY;
|
||||
// Create entries in an order so that the priority entry can be deemed the newest child.
|
||||
NotificationEntry[] siblings = new NotificationEntry[numSiblings];
|
||||
for (int i = 0; i < numSiblings; i++) {
|
||||
siblings[i] = mGroupTestHelper.createChildNotification(groupAlert, i, "sibling");
|
||||
}
|
||||
NotificationEntry priorityEntry =
|
||||
mGroupTestHelper.createChildNotification(groupAlert, 0, "priority");
|
||||
NotificationEntry summaryEntry =
|
||||
mGroupTestHelper.createSummaryNotification(groupAlert, 0, "summary");
|
||||
|
||||
// The priority entry is an important conversation.
|
||||
when(mPeopleNotificationIdentifier.getPeopleNotificationType(eq(priorityEntry)))
|
||||
.thenReturn(PeopleNotificationIdentifier.TYPE_IMPORTANT_PERSON);
|
||||
|
||||
// Register a listener so we can verify that the event is sent.
|
||||
OnGroupChangeListener groupChangeListener = mock(OnGroupChangeListener.class);
|
||||
mGroupManager.registerGroupChangeListener(groupChangeListener);
|
||||
|
||||
// Add all the entries. The order here shouldn't matter.
|
||||
mGroupManager.onEntryAdded(summaryEntry);
|
||||
for (int i = 0; i < numSiblings; i++) {
|
||||
mGroupManager.onEntryAdded(siblings[i]);
|
||||
}
|
||||
mGroupManager.onEntryAdded(priorityEntry);
|
||||
|
||||
int max2Siblings = Math.min(2, numSiblings);
|
||||
|
||||
// Verify that the summary group has the priority child as its alertOverride
|
||||
NotificationGroup summaryGroup = mGroupManager.getGroupForSummary(summaryEntry.getSbn());
|
||||
assertEquals(priorityEntry, summaryGroup.alertOverride);
|
||||
verify(groupChangeListener).onGroupAlertOverrideChanged(summaryGroup, null, priorityEntry);
|
||||
verify(groupChangeListener).onGroupSuppressionChanged(summaryGroup, true);
|
||||
if (numSiblings > 1) {
|
||||
verify(groupChangeListener).onGroupSuppressionChanged(summaryGroup, false);
|
||||
}
|
||||
verify(groupChangeListener).onGroupCreated(any(), eq(priorityEntry.getKey()));
|
||||
verify(groupChangeListener).onGroupCreated(any(), eq(summaryEntry.getSbn().getGroupKey()));
|
||||
verify(groupChangeListener, times(max2Siblings + 1)).onGroupsChanged();
|
||||
verifyNoMoreInteractions(groupChangeListener);
|
||||
|
||||
// Verify that only the priority notification is isolated from the group
|
||||
assertEquals(priorityEntry, mGroupManager.getGroupSummary(priorityEntry));
|
||||
assertEquals(summaryEntry, mGroupManager.getLogicalGroupSummary(priorityEntry));
|
||||
// Verify that the siblings are NOT isolated from the group
|
||||
for (int i = 0; i < numSiblings; i++) {
|
||||
assertEquals(summaryEntry, mGroupManager.getGroupSummary(siblings[i]));
|
||||
assertEquals(summaryEntry, mGroupManager.getLogicalGroupSummary(siblings[i]));
|
||||
}
|
||||
|
||||
Log.d("NotificationGroupManagerLegacyTest",
|
||||
"testAlertOverrideWhenUpdatingSummaryAtEnd: About to update summary");
|
||||
|
||||
StatusBarNotification oldSummarySbn = mGroupTestHelper.incrementPost(summaryEntry, 10000);
|
||||
mGroupManager.onEntryUpdated(summaryEntry, oldSummarySbn);
|
||||
|
||||
verify(groupChangeListener, times(max2Siblings + 2)).onGroupsChanged();
|
||||
verify(groupChangeListener).onGroupAlertOverrideChanged(summaryGroup, priorityEntry, null);
|
||||
verifyNoMoreInteractions(groupChangeListener);
|
||||
|
||||
Log.d("NotificationGroupManagerLegacyTest",
|
||||
"testAlertOverrideWhenUpdatingSummaryAtEnd: About to update priority child");
|
||||
|
||||
StatusBarNotification oldPrioritySbn = mGroupTestHelper.incrementPost(priorityEntry, 10000);
|
||||
mGroupManager.onEntryUpdated(priorityEntry, oldPrioritySbn);
|
||||
|
||||
verify(groupChangeListener).onGroupRemoved(any(), eq(priorityEntry.getKey()));
|
||||
verify(groupChangeListener, times(2)).onGroupCreated(any(), eq(priorityEntry.getKey()));
|
||||
verify(groupChangeListener, times(2))
|
||||
.onGroupAlertOverrideChanged(summaryGroup, null, priorityEntry);
|
||||
verify(groupChangeListener, times(max2Siblings + 3)).onGroupsChanged();
|
||||
verifyNoMoreInteractions(groupChangeListener);
|
||||
|
||||
Log.d("NotificationGroupManagerLegacyTest",
|
||||
"testAlertOverrideWhenUpdatingSummaryAtEnd: Done");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.systemui.statusbar.phone;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@@ -23,8 +25,10 @@ import android.app.ActivityManager;
|
||||
import android.app.Notification;
|
||||
import android.content.Context;
|
||||
import android.os.UserHandle;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.statusbar.SbnBuilder;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry;
|
||||
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
|
||||
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
|
||||
@@ -44,15 +48,15 @@ public final class NotificationGroupTestHelper {
|
||||
}
|
||||
|
||||
public NotificationEntry createSummaryNotification() {
|
||||
return createSummaryNotification(Notification.GROUP_ALERT_ALL, mId++);
|
||||
return createSummaryNotification(Notification.GROUP_ALERT_ALL, mId++, null);
|
||||
}
|
||||
|
||||
public NotificationEntry createSummaryNotification(int groupAlertBehavior) {
|
||||
return createSummaryNotification(groupAlertBehavior, mId++);
|
||||
return createSummaryNotification(groupAlertBehavior, mId++, null);
|
||||
}
|
||||
|
||||
public NotificationEntry createSummaryNotification(int groupAlertBehavior, int id) {
|
||||
return createEntry(id, true, groupAlertBehavior);
|
||||
public NotificationEntry createSummaryNotification(int groupAlertBehavior, int id, String tag) {
|
||||
return createEntry(id, tag, true, groupAlertBehavior);
|
||||
}
|
||||
|
||||
public NotificationEntry createChildNotification() {
|
||||
@@ -60,14 +64,15 @@ public final class NotificationGroupTestHelper {
|
||||
}
|
||||
|
||||
public NotificationEntry createChildNotification(int groupAlertBehavior) {
|
||||
return createEntry(mId++, false, groupAlertBehavior);
|
||||
return createEntry(mId++, null, false, groupAlertBehavior);
|
||||
}
|
||||
|
||||
public NotificationEntry createChildNotification(int groupAlertBehavior, int id) {
|
||||
return createEntry(id, false, groupAlertBehavior);
|
||||
public NotificationEntry createChildNotification(int groupAlertBehavior, int id, String tag) {
|
||||
return createEntry(id, tag, false, groupAlertBehavior);
|
||||
}
|
||||
|
||||
public NotificationEntry createEntry(int id, boolean isSummary, int groupAlertBehavior) {
|
||||
public NotificationEntry createEntry(int id, String tag, boolean isSummary,
|
||||
int groupAlertBehavior) {
|
||||
Notification notif = new Notification.Builder(mContext, TEST_CHANNEL_ID)
|
||||
.setContentTitle("Title")
|
||||
.setSmallIcon(R.drawable.ic_person)
|
||||
@@ -80,6 +85,7 @@ public final class NotificationGroupTestHelper {
|
||||
.setOpPkg(TEST_PACKAGE_NAME)
|
||||
.setId(id)
|
||||
.setNotification(notif)
|
||||
.setTag(tag)
|
||||
.setUser(new UserHandle(ActivityManager.getCurrentUser()))
|
||||
.build();
|
||||
|
||||
@@ -88,4 +94,16 @@ public final class NotificationGroupTestHelper {
|
||||
when(row.getEntry()).thenReturn(entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
public StatusBarNotification incrementPost(NotificationEntry entry, int increment) {
|
||||
StatusBarNotification oldSbn = entry.getSbn();
|
||||
final long oldPostTime = oldSbn.getPostTime();
|
||||
final long newPostTime = oldPostTime + increment;
|
||||
entry.setSbn(new SbnBuilder(oldSbn)
|
||||
.setPostTime(newPostTime)
|
||||
.build());
|
||||
assertThat(oldSbn.getPostTime()).isEqualTo(oldPostTime);
|
||||
assertThat(entry.getSbn().getPostTime()).isEqualTo(newPostTime);
|
||||
return oldSbn;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user