Merge "Removing groups & ongoing from bubble ordering" into rvc-dev
This commit is contained in:
@@ -57,7 +57,6 @@ class Bubble implements BubbleViewProvider {
|
||||
|
||||
private NotificationEntry mEntry;
|
||||
private final String mKey;
|
||||
private final String mGroupId;
|
||||
|
||||
private long mLastUpdated;
|
||||
private long mLastAccessed;
|
||||
@@ -96,17 +95,10 @@ class Bubble implements BubbleViewProvider {
|
||||
private int mDotColor;
|
||||
private Path mDotPath;
|
||||
|
||||
|
||||
public static String groupId(NotificationEntry entry) {
|
||||
UserHandle user = entry.getSbn().getUser();
|
||||
return user.getIdentifier() + "|" + entry.getSbn().getPackageName();
|
||||
}
|
||||
|
||||
// TODO: Decouple Bubble from NotificationEntry and transform ShortcutInfo into Bubble
|
||||
Bubble(ShortcutInfo shortcutInfo) {
|
||||
mShortcutInfo = shortcutInfo;
|
||||
mKey = shortcutInfo.getId();
|
||||
mGroupId = shortcutInfo.getId();
|
||||
}
|
||||
|
||||
/** Used in tests when no UI is required. */
|
||||
@@ -116,7 +108,6 @@ class Bubble implements BubbleViewProvider {
|
||||
mEntry = e;
|
||||
mKey = e.getKey();
|
||||
mLastUpdated = e.getSbn().getPostTime();
|
||||
mGroupId = groupId(e);
|
||||
mSuppressionListener = listener;
|
||||
}
|
||||
|
||||
@@ -129,10 +120,6 @@ class Bubble implements BubbleViewProvider {
|
||||
return mEntry;
|
||||
}
|
||||
|
||||
public String getGroupId() {
|
||||
return mGroupId;
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return mEntry.getSbn().getPackageName();
|
||||
}
|
||||
@@ -297,19 +284,12 @@ class Bubble implements BubbleViewProvider {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the newer of {@link #getLastUpdateTime()} and {@link #getLastAccessTime()}
|
||||
* @return the last time this bubble was updated or accessed, whichever is most recent.
|
||||
*/
|
||||
long getLastActivity() {
|
||||
return Math.max(mLastUpdated, mLastAccessed);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the timestamp in milliseconds of the most recent notification entry for this bubble
|
||||
*/
|
||||
long getLastUpdateTime() {
|
||||
return mLastUpdated;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if the bubble was ever expanded
|
||||
*/
|
||||
@@ -411,15 +391,6 @@ class Bubble implements BubbleViewProvider {
|
||||
return mFlyoutMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the notification for this bubble is a foreground service. It shows that this
|
||||
* is an ongoing bubble.
|
||||
*/
|
||||
boolean isOngoing() {
|
||||
int flags = mEntry.getSbn().getNotification().flags;
|
||||
return (flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
|
||||
}
|
||||
|
||||
float getDesiredHeight(Context context) {
|
||||
Notification.BubbleMetadata data = mEntry.getBubbleMetadata();
|
||||
boolean useRes = data.getDesiredHeightResId() != 0;
|
||||
@@ -562,7 +533,7 @@ class Bubble implements BubbleViewProvider {
|
||||
normalX,
|
||||
normalY,
|
||||
this.showInShade(),
|
||||
this.isOngoing(),
|
||||
false /* isOngoing (unused) */,
|
||||
false /* isAppForeground (unused) */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,8 +21,6 @@ import static com.android.systemui.bubbles.BubbleDebugConfig.DEBUG_BUBBLE_DATA;
|
||||
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_BUBBLES;
|
||||
import static com.android.systemui.bubbles.BubbleDebugConfig.TAG_WITH_CLASS_NAME;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
import android.app.Notification;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
@@ -45,7 +43,6 @@ import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import javax.inject.Inject;
|
||||
@@ -62,9 +59,6 @@ public class BubbleData {
|
||||
private static final Comparator<Bubble> BUBBLES_BY_SORT_KEY_DESCENDING =
|
||||
Comparator.comparing(BubbleData::sortKey).reversed();
|
||||
|
||||
private static final Comparator<Map.Entry<String, Long>> GROUPS_BY_MAX_SORT_KEY_DESCENDING =
|
||||
Comparator.<Map.Entry<String, Long>, Long>comparing(Map.Entry::getValue).reversed();
|
||||
|
||||
/** Contains information about changes that have been made to the state of bubbles. */
|
||||
static final class Update {
|
||||
boolean expandedChanged;
|
||||
@@ -295,8 +289,6 @@ public class BubbleData {
|
||||
if (!mExpanded) {
|
||||
setExpandedInternal(true);
|
||||
}
|
||||
} else if (mSelectedBubble == null) {
|
||||
setSelectedBubbleInternal(bubble);
|
||||
}
|
||||
|
||||
boolean isBubbleExpandedAndSelected = mExpanded && mSelectedBubble == bubble;
|
||||
@@ -370,20 +362,11 @@ public class BubbleData {
|
||||
if (DEBUG_BUBBLE_DATA) {
|
||||
Log.d(TAG, "doAdd: " + bubble);
|
||||
}
|
||||
int minInsertPoint = 0;
|
||||
boolean newGroup = !hasBubbleWithGroupId(bubble.getGroupId());
|
||||
if (isExpanded()) {
|
||||
// first bubble of a group goes to the beginning, otherwise within the existing group
|
||||
minInsertPoint = newGroup ? 0 : findFirstIndexForGroup(bubble.getGroupId());
|
||||
}
|
||||
if (insertBubble(minInsertPoint, bubble) < mBubbles.size() - 1) {
|
||||
mStateChange.orderChanged = true;
|
||||
}
|
||||
mBubbles.add(0, bubble);
|
||||
mStateChange.addedBubble = bubble;
|
||||
|
||||
// Adding the first bubble doesn't change the order
|
||||
mStateChange.orderChanged = mBubbles.size() > 1;
|
||||
if (!isExpanded()) {
|
||||
mStateChange.orderChanged |= packGroup(findFirstIndexForGroup(bubble.getGroupId()));
|
||||
// Top bubble becomes selected.
|
||||
setSelectedBubbleInternal(mBubbles.get(0));
|
||||
}
|
||||
}
|
||||
@@ -406,14 +389,10 @@ public class BubbleData {
|
||||
}
|
||||
mStateChange.updatedBubble = bubble;
|
||||
if (!isExpanded()) {
|
||||
// while collapsed, update causes re-pack
|
||||
int prevPos = mBubbles.indexOf(bubble);
|
||||
mBubbles.remove(bubble);
|
||||
int newPos = insertBubble(0, bubble);
|
||||
if (prevPos != newPos) {
|
||||
packGroup(newPos);
|
||||
mStateChange.orderChanged = true;
|
||||
}
|
||||
mBubbles.add(0, bubble);
|
||||
mStateChange.orderChanged = prevPos != 0;
|
||||
setSelectedBubbleInternal(mBubbles.get(0));
|
||||
}
|
||||
}
|
||||
@@ -581,7 +560,6 @@ public class BubbleData {
|
||||
Log.e(TAG, "Attempt to expand stack without selected bubble!");
|
||||
return;
|
||||
}
|
||||
mSelectedBubble.markUpdatedAt(mTimeSource.currentTimeMillis());
|
||||
mSelectedBubble.markAsAccessedAt(mTimeSource.currentTimeMillis());
|
||||
mStateChange.orderChanged |= repackAll();
|
||||
} else if (!mBubbles.isEmpty()) {
|
||||
@@ -596,17 +574,11 @@ public class BubbleData {
|
||||
}
|
||||
if (mBubbles.indexOf(mSelectedBubble) > 0) {
|
||||
// Move the selected bubble to the top while collapsed.
|
||||
if (!mSelectedBubble.isOngoing() && mBubbles.get(0).isOngoing()) {
|
||||
// The selected bubble cannot be raised to the first position because
|
||||
// there is an ongoing bubble there. Instead, force the top ongoing bubble
|
||||
// to become selected.
|
||||
setSelectedBubbleInternal(mBubbles.get(0));
|
||||
} else {
|
||||
// Raise the selected bubble (and it's group) up to the front so the selected
|
||||
// bubble remains on top.
|
||||
int index = mBubbles.indexOf(mSelectedBubble);
|
||||
if (index != 0) {
|
||||
mBubbles.remove(mSelectedBubble);
|
||||
mBubbles.add(0, mSelectedBubble);
|
||||
mStateChange.orderChanged |= packGroup(0);
|
||||
mStateChange.orderChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -616,91 +588,12 @@ public class BubbleData {
|
||||
}
|
||||
|
||||
private static long sortKey(Bubble bubble) {
|
||||
long key = bubble.getLastUpdateTime();
|
||||
if (bubble.isOngoing()) {
|
||||
// Set 2nd highest bit (signed long int), to partition between ongoing and regular
|
||||
key |= 0x4000000000000000L;
|
||||
}
|
||||
return key;
|
||||
return bubble.getLastActivity();
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates and inserts the bubble into a sorted position. The is inserted
|
||||
* based on sort key, groupId is not considered. A call to {@link #packGroup(int)} may be
|
||||
* required to keep grouping intact.
|
||||
*
|
||||
* @param minPosition the first insert point to consider
|
||||
* @param newBubble the bubble to insert
|
||||
* @return the position where the bubble was inserted
|
||||
*/
|
||||
private int insertBubble(int minPosition, Bubble newBubble) {
|
||||
long newBubbleSortKey = sortKey(newBubble);
|
||||
String previousGroupId = null;
|
||||
|
||||
for (int pos = minPosition; pos < mBubbles.size(); pos++) {
|
||||
Bubble bubbleAtPos = mBubbles.get(pos);
|
||||
String groupIdAtPos = bubbleAtPos.getGroupId();
|
||||
boolean atStartOfGroup = !groupIdAtPos.equals(previousGroupId);
|
||||
|
||||
if (atStartOfGroup && newBubbleSortKey > sortKey(bubbleAtPos)) {
|
||||
// Insert before the start of first group which has older bubbles.
|
||||
mBubbles.add(pos, newBubble);
|
||||
return pos;
|
||||
}
|
||||
previousGroupId = groupIdAtPos;
|
||||
}
|
||||
mBubbles.add(newBubble);
|
||||
return mBubbles.size() - 1;
|
||||
}
|
||||
|
||||
private boolean hasBubbleWithGroupId(String groupId) {
|
||||
return mBubbles.stream().anyMatch(b -> b.getGroupId().equals(groupId));
|
||||
}
|
||||
|
||||
private int findFirstIndexForGroup(String appId) {
|
||||
for (int i = 0; i < mBubbles.size(); i++) {
|
||||
Bubble bubbleAtPos = mBubbles.get(i);
|
||||
if (bubbleAtPos.getGroupId().equals(appId)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starting at the given position, moves all bubbles with the same group id to follow. Bubbles
|
||||
* at positions lower than {@code position} are unchanged. Relative order within the group
|
||||
* unchanged. Relative order of any other bubbles are also unchanged.
|
||||
*
|
||||
* @param position the position of the first bubble for the group
|
||||
* @return true if the position of any bubbles has changed as a result
|
||||
*/
|
||||
private boolean packGroup(int position) {
|
||||
if (DEBUG_BUBBLE_DATA) {
|
||||
Log.d(TAG, "packGroup: position=" + position);
|
||||
}
|
||||
Bubble groupStart = mBubbles.get(position);
|
||||
final String groupAppId = groupStart.getGroupId();
|
||||
List<Bubble> moving = new ArrayList<>();
|
||||
|
||||
// Walk backward, collect bubbles within the group
|
||||
for (int i = mBubbles.size() - 1; i > position; i--) {
|
||||
if (mBubbles.get(i).getGroupId().equals(groupAppId)) {
|
||||
moving.add(0, mBubbles.get(i));
|
||||
}
|
||||
}
|
||||
if (moving.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
mBubbles.removeAll(moving);
|
||||
mBubbles.addAll(position + 1, moving);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This applies a full sort and group pass to all existing bubbles. The bubbles are grouped
|
||||
* by groupId. Each group is then sorted by the max(lastUpdated) time of its bubbles. Bubbles
|
||||
* within each group are then sorted by lastUpdated descending.
|
||||
* This applies a full sort and group pass to all existing bubbles.
|
||||
* Bubbles are sorted by lastUpdated descending.
|
||||
*
|
||||
* @return true if the position of any bubbles changed as a result
|
||||
*/
|
||||
@@ -711,31 +604,11 @@ public class BubbleData {
|
||||
if (mBubbles.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
Map<String, Long> groupLastActivity = new HashMap<>();
|
||||
for (Bubble bubble : mBubbles) {
|
||||
long maxSortKeyForGroup = groupLastActivity.getOrDefault(bubble.getGroupId(), 0L);
|
||||
long sortKeyForBubble = sortKey(bubble);
|
||||
if (sortKeyForBubble > maxSortKeyForGroup) {
|
||||
groupLastActivity.put(bubble.getGroupId(), sortKeyForBubble);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort groups by their most recently active bubble
|
||||
List<String> groupsByMostRecentActivity =
|
||||
groupLastActivity.entrySet().stream()
|
||||
.sorted(GROUPS_BY_MAX_SORT_KEY_DESCENDING)
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(toList());
|
||||
|
||||
List<Bubble> repacked = new ArrayList<>(mBubbles.size());
|
||||
|
||||
// For each group, add bubbles, freshest to oldest
|
||||
for (String appId : groupsByMostRecentActivity) {
|
||||
mBubbles.stream()
|
||||
.filter((b) -> b.getGroupId().equals(appId))
|
||||
.sorted(BUBBLES_BY_SORT_KEY_DESCENDING)
|
||||
.forEachOrdered(repacked::add);
|
||||
}
|
||||
// Add bubbles, freshest to oldest
|
||||
mBubbles.stream()
|
||||
.sorted(BUBBLES_BY_SORT_KEY_DESCENDING)
|
||||
.forEachOrdered(repacked::add);
|
||||
if (repacked.equals(mBubbles)) {
|
||||
return false;
|
||||
}
|
||||
@@ -778,11 +651,12 @@ public class BubbleData {
|
||||
public List<Bubble> getBubbles() {
|
||||
return Collections.unmodifiableList(mBubbles);
|
||||
}
|
||||
|
||||
/**
|
||||
* The set of bubbles in overflow.
|
||||
*/
|
||||
@VisibleForTesting(visibility = PRIVATE)
|
||||
public List<Bubble> getOverflowBubbles() {
|
||||
List<Bubble> getOverflowBubbles() {
|
||||
return Collections.unmodifiableList(mOverflowBubbles);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,10 +69,10 @@ public class BubbleDebugConfig {
|
||||
&& selected.getKey() != BubbleOverflow.KEY
|
||||
&& bubble == selected);
|
||||
String arrow = isSelected ? "=>" : " ";
|
||||
sb.append(String.format("%s Bubble{act=%12d, ongoing=%d, key=%s}\n",
|
||||
sb.append(String.format("%s Bubble{act=%12d, showInShade=%d, key=%s}\n",
|
||||
arrow,
|
||||
bubble.getLastActivity(),
|
||||
(bubble.isOngoing() ? 1 : 0),
|
||||
(bubble.showInShade() ? 1 : 0),
|
||||
bubble.getKey()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Region;
|
||||
import android.os.Bundle;
|
||||
import android.os.Vibrator;
|
||||
import android.provider.Settings;
|
||||
import android.service.notification.StatusBarNotification;
|
||||
import android.util.Log;
|
||||
@@ -188,7 +187,6 @@ public class BubbleStackView extends FrameLayout
|
||||
private final SpringAnimation mExpandedViewYAnim;
|
||||
private final BubbleData mBubbleData;
|
||||
|
||||
private final Vibrator mVibrator;
|
||||
private final ValueAnimator mDesaturateAndDarkenAnimator;
|
||||
private final Paint mDesaturateAndDarkenPaint = new Paint();
|
||||
|
||||
@@ -701,8 +699,6 @@ public class BubbleStackView extends FrameLayout
|
||||
// We use the real size & subtract screen decorations / window insets ourselves when needed
|
||||
wm.getDefaultDisplay().getRealSize(mDisplaySize);
|
||||
|
||||
mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
|
||||
|
||||
mExpandedViewPadding = res.getDimensionPixelSize(R.dimen.bubble_expanded_view_padding);
|
||||
int elevation = res.getDimensionPixelSize(R.dimen.bubble_elevation);
|
||||
|
||||
@@ -2334,7 +2330,7 @@ public class BubbleStackView extends FrameLayout
|
||||
getNormalizedXPosition(),
|
||||
getNormalizedYPosition(),
|
||||
bubble.showInShade(),
|
||||
bubble.isOngoing(),
|
||||
false /* isOngoing (unused) */,
|
||||
false /* isAppForeground (unused) */);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,11 +20,8 @@ import static com.android.systemui.statusbar.NotificationEntryHelper.modifyRanki
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.reset;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyZeroInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -258,14 +255,15 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
assertThat(update.updatedBubble.showFlyout()).isFalse();
|
||||
}
|
||||
|
||||
// COLLAPSED / ADD
|
||||
//
|
||||
// Overflow
|
||||
//
|
||||
|
||||
/**
|
||||
* Verifies that the number of bubbles is not allowed to exceed the maximum. The limit is
|
||||
* enforced by expiring the bubble which was least recently updated (lowest timestamp).
|
||||
* Verifies that when the bubble stack reaches its maximum, the oldest bubble is overflowed.
|
||||
*/
|
||||
@Test
|
||||
public void test_collapsed_addBubble_atMaxBubbles_overflowsOldest() {
|
||||
public void testOverflow_add_stackAtMaxBubbles_overflowsOldest() {
|
||||
// Setup
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 2000);
|
||||
@@ -288,8 +286,12 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
assertOverflowChangedTo(ImmutableList.of(mBubbleA2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that once the number of overflowed bubbles reaches its maximum, the oldest
|
||||
* overflow bubble is removed.
|
||||
*/
|
||||
@Test
|
||||
public void testOverflowBubble_maxReached_bubbleRemoved() {
|
||||
public void testOverflow_maxReached_bubbleRemoved() {
|
||||
// Setup
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 2000);
|
||||
@@ -308,16 +310,41 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that new bubbles insert to the left when collapsed, carrying along grouped bubbles.
|
||||
* <p>
|
||||
* Placement within the list is based on lastUpdate (post time of the notification), descending
|
||||
* order (with most recent first).
|
||||
*
|
||||
* @see #test_expanded_addBubble_sortAndGrouping_newGroup()
|
||||
* @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
|
||||
* Verifies that overflow bubbles are canceled on notif entry removal.
|
||||
*/
|
||||
@Test
|
||||
public void test_collapsed_addBubble_sortAndGrouping() {
|
||||
public void testOverflow_notifCanceled_removesOverflowBubble() {
|
||||
// Setup
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryA3, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryB1, 4000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 5000);
|
||||
sendUpdatedEntryAtTime(mEntryB3, 6000); // [A2, A3, B1, B2, B3], overflow: [A1]
|
||||
sendUpdatedEntryAtTime(mEntryC1, 7000); // [A3, B1, B2, B3, C1], overflow: [A2, A1]
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_NOTIF_CANCEL);
|
||||
verifyUpdateReceived();
|
||||
assertOverflowChangedTo(ImmutableList.of(mBubbleA2));
|
||||
|
||||
// Test
|
||||
mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_GROUP_CANCELLED);
|
||||
verifyUpdateReceived();
|
||||
assertOverflowChangedTo(ImmutableList.of());
|
||||
}
|
||||
|
||||
// COLLAPSED / ADD
|
||||
|
||||
/**
|
||||
* Verifies that new bubbles insert to the left when collapsed.
|
||||
* <p>
|
||||
* Placement within the list is based on {@link Bubble#getLastActivity()}, descending
|
||||
* order (with most recent first).
|
||||
*/
|
||||
@Test
|
||||
public void test_collapsed_addBubble() {
|
||||
// Setup
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
@@ -336,41 +363,7 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that new bubbles insert to the left when collapsed, carrying along grouped bubbles.
|
||||
* Additionally, any bubble which is ongoing is considered "newer" than any non-ongoing bubble.
|
||||
* <p>
|
||||
* Because of the ongoing bubble, the new bubble cannot be placed in the first position. This
|
||||
* causes the 'B' group to remain last, despite having a new button added.
|
||||
*
|
||||
* @see #test_expanded_addBubble_sortAndGrouping_newGroup()
|
||||
* @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
|
||||
*/
|
||||
@Test
|
||||
public void test_collapsed_addBubble_sortAndGrouping_withOngoing() {
|
||||
// Setup
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
setOngoing(mEntryA1, true);
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
verifyUpdateReceived();
|
||||
assertOrderNotChanged();
|
||||
|
||||
sendUpdatedEntryAtTime(mEntryB1, 2000);
|
||||
verifyUpdateReceived();
|
||||
assertOrderNotChanged();
|
||||
|
||||
sendUpdatedEntryAtTime(mEntryB2, 3000);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleA1, mBubbleB2, mBubbleB1);
|
||||
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleA1, mBubbleA2, mBubbleB2, mBubbleB1);
|
||||
assertOrderChangedTo(mBubbleA2, mBubbleB2, mBubbleB1, mBubbleA1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -378,7 +371,6 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
* the collapsed state.
|
||||
*
|
||||
* @see #test_collapsed_updateBubble_selectionChanges()
|
||||
* @see #test_collapsed_updateBubble_noSelectionChanges_withOngoing()
|
||||
*/
|
||||
@Test
|
||||
public void test_collapsed_addBubble_selectionChanges() {
|
||||
@@ -403,58 +395,27 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
assertSelectionChangedTo(mBubbleA2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that while collapsed, the selection will not change if the selected bubble is
|
||||
* ongoing. It remains the top bubble and as such remains selected.
|
||||
*
|
||||
* @see #test_collapsed_addBubble_selectionChanges()
|
||||
*/
|
||||
@Test
|
||||
public void test_collapsed_addBubble_noSelectionChanges_withOngoing() {
|
||||
// Setup
|
||||
setOngoing(mEntryA1, true);
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1);
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
sendUpdatedEntryAtTime(mEntryB1, 2000);
|
||||
verifyUpdateReceived();
|
||||
assertSelectionNotChanged();
|
||||
|
||||
sendUpdatedEntryAtTime(mEntryB2, 3000);
|
||||
verifyUpdateReceived();
|
||||
assertSelectionNotChanged();
|
||||
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000);
|
||||
verifyUpdateReceived();
|
||||
assertSelectionNotChanged();
|
||||
|
||||
assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA1); // selection unchanged
|
||||
}
|
||||
|
||||
// COLLAPSED / REMOVE
|
||||
|
||||
/**
|
||||
* Verifies that groups may reorder when bubbles are removed, while the stack is in the
|
||||
* collapsed state.
|
||||
* Verifies order of bubbles after a removal.
|
||||
*/
|
||||
@Test
|
||||
public void test_collapsed_removeBubble_sortAndGrouping() {
|
||||
public void test_collapsed_removeBubble_sort() {
|
||||
// Setup
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryB1, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1]
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_USER_GESTURE);
|
||||
verifyUpdateReceived();
|
||||
// TODO: this should fail if things work as I expect them to?
|
||||
assertOrderChangedTo(mBubbleB2, mBubbleB1, mBubbleA1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Verifies that onOrderChanged is not called when a bubble is removed if the removal does not
|
||||
* cause other bubbles to change position.
|
||||
@@ -465,61 +426,15 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryB1, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1]
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
mBubbleData.notificationEntryRemoved(mEntryB1, BubbleController.DISMISS_USER_GESTURE);
|
||||
mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
|
||||
verifyUpdateReceived();
|
||||
assertOrderNotChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that bubble ordering reverts to normal when an ongoing bubble is removed. A group
|
||||
* which has a newer bubble may move to the front after the ongoing bubble is removed.
|
||||
*/
|
||||
@Test
|
||||
public void test_collapsed_removeBubble_sortAndGrouping_withOngoing() {
|
||||
// Setup
|
||||
setOngoing(mEntryA1, true);
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryB1, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 4000); // [A1*, A2, B2, B1]
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_NOTIF_CANCEL);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleB2, mBubbleB1, mBubbleA2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that overflow bubbles are canceled on notif entry removal.
|
||||
*/
|
||||
@Test
|
||||
public void test_removeOverflowBubble_forCanceledNotif() {
|
||||
// Setup
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryA3, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryB1, 4000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 5000);
|
||||
sendUpdatedEntryAtTime(mEntryB3, 6000); // [A2, A3, B1, B2, B3], overflow: [A1]
|
||||
sendUpdatedEntryAtTime(mEntryC1, 7000); // [A3, B1, B2, B3, C1], overflow: [A2, A1]
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_NOTIF_CANCEL);
|
||||
verifyUpdateReceived();
|
||||
assertOverflowChangedTo(ImmutableList.of(mBubbleA2));
|
||||
|
||||
// Test
|
||||
mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_GROUP_CANCELLED);
|
||||
verifyUpdateReceived();
|
||||
assertOverflowChangedTo(ImmutableList.of());
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that when the selected bubble is removed with the stack in the collapsed state,
|
||||
* the selection moves to the next most-recently updated bubble.
|
||||
@@ -530,7 +445,7 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryB1, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1]
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
@@ -542,26 +457,26 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
// COLLAPSED / UPDATE
|
||||
|
||||
/**
|
||||
* Verifies that bubble and group ordering may change with updates while the stack is in the
|
||||
* Verifies that bubble ordering changes with updates while the stack is in the
|
||||
* collapsed state.
|
||||
*/
|
||||
@Test
|
||||
public void test_collapsed_updateBubble_orderAndGrouping() {
|
||||
public void test_collapsed_updateBubble() {
|
||||
// Setup
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryB1, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1]
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
sendUpdatedEntryAtTime(mEntryB1, 5000);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleB1, mBubbleB2, mBubbleA2, mBubbleA1);
|
||||
assertOrderChangedTo(mBubbleB1, mBubbleA2, mBubbleB2, mBubbleA1);
|
||||
|
||||
sendUpdatedEntryAtTime(mEntryA1, 6000);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleA1, mBubbleA2, mBubbleB1, mBubbleB2);
|
||||
assertOrderChangedTo(mBubbleA1, mBubbleB1, mBubbleA2, mBubbleB2);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -573,7 +488,7 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryB1, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, A1, B2, B1]
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1]
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
@@ -586,26 +501,6 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
assertSelectionChangedTo(mBubbleA1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that selection does not change in response to updates when collapsed, if the
|
||||
* selected bubble is ongoing.
|
||||
*/
|
||||
@Test
|
||||
public void test_collapsed_updateBubble_noSelectionChanges_withOngoing() {
|
||||
// Setup
|
||||
setOngoing(mEntryA1, true);
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryB1, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 4000); // [A1*, A2, B2, B1]
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
sendUpdatedEntryAtTime(mEntryB2, 5000); // [A1*, A2, B2, B1]
|
||||
verifyUpdateReceived();
|
||||
assertSelectionNotChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a request to expand the stack has no effect if there are no bubbles.
|
||||
*/
|
||||
@@ -618,6 +513,9 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
verifyZeroInteractions(mListener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that removing the last bubble clears the selected bubble and collapses the stack.
|
||||
*/
|
||||
@Test
|
||||
public void test_collapsed_removeLastBubble_clearsSelectedBubble() {
|
||||
// Setup
|
||||
@@ -629,23 +527,22 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
|
||||
// Verify the selection was cleared.
|
||||
verifyUpdateReceived();
|
||||
assertThat(mBubbleData.isExpanded()).isFalse();
|
||||
assertSelectionCleared();
|
||||
}
|
||||
|
||||
// EXPANDED / ADD
|
||||
// EXPANDED / ADD / UPDATE
|
||||
|
||||
/**
|
||||
* Verifies that bubbles added as part of a new group insert before existing groups while
|
||||
* expanded.
|
||||
* Verifies that bubbles are added at the front of the stack.
|
||||
* <p>
|
||||
* Placement within the list is based on lastUpdate (post time of the notification), descending
|
||||
* Placement within the list is based on {@link Bubble#getLastActivity()}, descending
|
||||
* order (with most recent first).
|
||||
*
|
||||
* @see #test_collapsed_addBubble_sortAndGrouping()
|
||||
* @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
|
||||
* @see #test_collapsed_addBubble()
|
||||
*/
|
||||
@Test
|
||||
public void test_expanded_addBubble_sortAndGrouping_newGroup() {
|
||||
public void test_expanded_addBubble() {
|
||||
// Setup
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 2000);
|
||||
@@ -656,65 +553,15 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
// Test
|
||||
sendUpdatedEntryAtTime(mEntryC1, 4000);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleB1, mBubbleC1, mBubbleA2, mBubbleA1);
|
||||
assertOrderChangedTo(mBubbleC1, mBubbleB1, mBubbleA2, mBubbleA1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that bubbles added as part of a new group insert before existing groups while
|
||||
* expanded, but not before any groups with ongoing bubbles.
|
||||
*
|
||||
* @see #test_collapsed_addBubble_sortAndGrouping_withOngoing()
|
||||
* @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
|
||||
*/
|
||||
@Test
|
||||
public void test_expanded_addBubble_sortAndGrouping_newGroup_withOngoing() {
|
||||
// Setup
|
||||
setOngoing(mEntryA1, true);
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryB1, 3000); // [A1*, A2, B1]
|
||||
changeExpandedStateAtTime(true, 4000L);
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
sendUpdatedEntryAtTime(mEntryC1, 4000);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleA1, mBubbleA2, mBubbleC1, mBubbleB1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that bubbles added as part of an existing group insert to the beginning of that
|
||||
* group. The order of groups within the list must not change while in the expanded state.
|
||||
*
|
||||
* @see #test_collapsed_addBubble_sortAndGrouping()
|
||||
* @see #test_expanded_addBubble_sortAndGrouping_newGroup()
|
||||
*/
|
||||
@Test
|
||||
public void test_expanded_addBubble_sortAndGrouping_existingGroup() {
|
||||
// Setup
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryB1, 3000); // [B1, A2, A1]
|
||||
changeExpandedStateAtTime(true, 4000L);
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
sendUpdatedEntryAtTime(mEntryA3, 4000);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleB1, mBubbleA3, mBubbleA2, mBubbleA1);
|
||||
}
|
||||
|
||||
// EXPANDED / UPDATE
|
||||
|
||||
/**
|
||||
* Verifies that updates to bubbles while expanded do not result in any change to sorting
|
||||
* or grouping of bubbles or sorting of groups.
|
||||
*
|
||||
* @see #test_collapsed_addBubble_sortAndGrouping()
|
||||
* @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
|
||||
* of bubbles.
|
||||
*/
|
||||
@Test
|
||||
public void test_expanded_updateBubble_sortAndGrouping_noChanges() {
|
||||
public void test_expanded_updateBubble_noChanges() {
|
||||
// Setup
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 2000);
|
||||
@@ -733,7 +580,6 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
* Verifies that updates to bubbles while expanded do not result in any change to selection.
|
||||
*
|
||||
* @see #test_collapsed_addBubble_selectionChanges()
|
||||
* @see #test_collapsed_updateBubble_noSelectionChanges_withOngoing()
|
||||
*/
|
||||
@Test
|
||||
public void test_expanded_updateBubble_noSelectionChanges() {
|
||||
@@ -762,26 +608,24 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
// EXPANDED / REMOVE
|
||||
|
||||
/**
|
||||
* Verifies that removing a bubble while expanded does not result in reordering of groups
|
||||
* or any of the remaining bubbles.
|
||||
* Verifies that removing a bubble while expanded does not result in reordering of bubbles.
|
||||
*
|
||||
* @see #test_collapsed_addBubble_sortAndGrouping()
|
||||
* @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
|
||||
* @see #test_collapsed_addBubble()
|
||||
*/
|
||||
@Test
|
||||
public void test_expanded_removeBubble_sortAndGrouping() {
|
||||
public void test_expanded_removeBubble() {
|
||||
// Setup
|
||||
sendUpdatedEntryAtTime(mEntryA1, 1000);
|
||||
sendUpdatedEntryAtTime(mEntryB1, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 4000); // [B2, B1, A2, A1]
|
||||
sendUpdatedEntryAtTime(mEntryB2, 4000); // [B2, A2, B1, A1]
|
||||
changeExpandedStateAtTime(true, 5000L);
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
mBubbleData.notificationEntryRemoved(mEntryB2, BubbleController.DISMISS_USER_GESTURE);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleB1, mBubbleA2, mBubbleA1);
|
||||
assertOrderChangedTo(mBubbleA2, mBubbleB1, mBubbleA1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -789,8 +633,7 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
* selected. The replacement selection is the bubble which appears at the same index as the
|
||||
* previous one, or the previous index if this was the last position.
|
||||
*
|
||||
* @see #test_collapsed_addBubble_sortAndGrouping()
|
||||
* @see #test_expanded_addBubble_sortAndGrouping_existingGroup()
|
||||
* @see #test_collapsed_addBubble()
|
||||
*/
|
||||
@Test
|
||||
public void test_expanded_removeBubble_selectionChanges_whenSelectedRemoved() {
|
||||
@@ -800,17 +643,17 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
sendUpdatedEntryAtTime(mEntryA2, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 4000);
|
||||
changeExpandedStateAtTime(true, 5000L);
|
||||
mBubbleData.setSelectedBubble(mBubbleA2); // [B2, B1, ^A2, A1]
|
||||
mBubbleData.setSelectedBubble(mBubbleA2); // [B2, A2^, B1, A1]
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_USER_GESTURE);
|
||||
verifyUpdateReceived();
|
||||
assertSelectionChangedTo(mBubbleA1);
|
||||
|
||||
mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE);
|
||||
verifyUpdateReceived();
|
||||
assertSelectionChangedTo(mBubbleB1);
|
||||
|
||||
mBubbleData.notificationEntryRemoved(mEntryB1, BubbleController.DISMISS_USER_GESTURE);
|
||||
verifyUpdateReceived();
|
||||
assertSelectionChangedTo(mBubbleA1);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -838,7 +681,6 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
* expanded.
|
||||
* <p>
|
||||
* When the stack transitions to the collapsed state, the selected bubble is brought to the top.
|
||||
* Bubbles within the same group should move up with it.
|
||||
* <p>
|
||||
* When the stack transitions back to the expanded state, this new order is kept as is.
|
||||
*/
|
||||
@@ -849,13 +691,13 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
sendUpdatedEntryAtTime(mEntryB1, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 4000);
|
||||
changeExpandedStateAtTime(true, 5000L); // [B2=4000, B1=2000, A2=3000, A1=1000]
|
||||
sendUpdatedEntryAtTime(mEntryB1, 6000); // [B2=4000, B1=6000*, A2=3000, A1=1000]
|
||||
changeExpandedStateAtTime(true, 5000L); // [B2=4000, A2=3000, B1=2000, A1=1000]
|
||||
sendUpdatedEntryAtTime(mEntryB1, 6000); // [B2=4000, A2=3000, B1=6000, A1=1000]
|
||||
setCurrentTime(7000);
|
||||
mBubbleData.setSelectedBubble(mBubbleA2);
|
||||
mBubbleData.setListener(mListener);
|
||||
assertThat(mBubbleData.getBubbles()).isEqualTo(
|
||||
ImmutableList.of(mBubbleB2, mBubbleB1, mBubbleA2, mBubbleA1));
|
||||
ImmutableList.of(mBubbleB2, mBubbleA2, mBubbleB1, mBubbleA1));
|
||||
|
||||
// Test
|
||||
|
||||
@@ -863,18 +705,17 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
// stack is expanded. When next collapsed, sorting will be applied and saved, just prior
|
||||
// to moving the selected bubble to the top (first).
|
||||
//
|
||||
// In this case, the expected re-expand state will be: [A2, A1, B1, B2]
|
||||
// In this case, the expected re-expand state will be: [A2^, B1, B2, A1]
|
||||
//
|
||||
// collapse -> selected bubble (A2) moves first.
|
||||
changeExpandedStateAtTime(false, 8000L);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleA2, mBubbleA1, mBubbleB1, mBubbleB2);
|
||||
assertOrderChangedTo(mBubbleA2, mBubbleB1, mBubbleB2, mBubbleA1);
|
||||
}
|
||||
|
||||
/**
|
||||
* When a change occurs while collapsed (any update, add, remove), the previous expanded
|
||||
* order and grouping becomes invalidated, and the order and grouping when next expanded will
|
||||
* remain the same as collapsed.
|
||||
* order becomes invalidated, the stack is resorted and will reflect that when next expanded.
|
||||
*/
|
||||
@Test
|
||||
public void test_expansionChanges_withUpdatesWhileCollapsed() {
|
||||
@@ -883,10 +724,10 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
sendUpdatedEntryAtTime(mEntryB1, 2000);
|
||||
sendUpdatedEntryAtTime(mEntryA2, 3000);
|
||||
sendUpdatedEntryAtTime(mEntryB2, 4000);
|
||||
changeExpandedStateAtTime(true, 5000L); // [B2=4000, B1=2000, A2=3000, A1=1000]
|
||||
sendUpdatedEntryAtTime(mEntryB1, 6000); // [B2=4000, B1=*6000, A2=3000, A1=1000]
|
||||
changeExpandedStateAtTime(true, 5000L); // [B2=4000, A2=3000, B1=2000, A1=1000]
|
||||
sendUpdatedEntryAtTime(mEntryB1, 6000); // [B2=4000, A2=3000, B1=6000, A1=1000]
|
||||
setCurrentTime(7000);
|
||||
mBubbleData.setSelectedBubble(mBubbleA2); // [B2, B1, ^A2, A1]
|
||||
mBubbleData.setSelectedBubble(mBubbleA2); // [B2, A2^, B1, A1]
|
||||
mBubbleData.setListener(mListener);
|
||||
|
||||
// Test
|
||||
@@ -895,7 +736,7 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
// stack is expanded. When next collapsed, sorting will be applied and saved, just prior
|
||||
// to moving the selected bubble to the top (first).
|
||||
//
|
||||
// In this case, the expected re-expand state will be: [B1, B2, A2*, A1]
|
||||
// In this case, the expected re-expand state will be: [A2^, B1, B2, A1]
|
||||
//
|
||||
// That state is restored as long as no changes occur (add/remove/update) while in
|
||||
// the collapsed state.
|
||||
@@ -903,11 +744,12 @@ public class BubbleDataTest extends SysuiTestCase {
|
||||
// collapse -> selected bubble (A2) moves first.
|
||||
changeExpandedStateAtTime(false, 8000L);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleA2, mBubbleA1, mBubbleB1, mBubbleB2);
|
||||
assertOrderChangedTo(mBubbleA2, mBubbleB1, mBubbleB2, mBubbleA1);
|
||||
|
||||
// An update occurs, which causes sorting, and this invalidates the previously saved order.
|
||||
sendUpdatedEntryAtTime(mEntryA2, 9000);
|
||||
sendUpdatedEntryAtTime(mEntryA1, 9000);
|
||||
verifyUpdateReceived();
|
||||
assertOrderChangedTo(mBubbleA1, mBubbleA2, mBubbleB1, mBubbleB2);
|
||||
|
||||
// No order changes when expanding because the new sorted order remains.
|
||||
changeExpandedStateAtTime(true, 10000L);
|
||||
|
||||
Reference in New Issue
Block a user