diff options
| author | 2020-05-27 00:06:33 +0000 | |
|---|---|---|
| committer | 2020-05-27 00:06:33 +0000 | |
| commit | 8ae715575631e5ea3739e323454767b7d581e7a1 (patch) | |
| tree | d2ccab407ab7c8a7c1036e41745b5a96163ada95 | |
| parent | c6d6c0b466cc8fd4c64ddba68f550cc6f00bfc4a (diff) | |
| parent | a55133daa73bbe5722762b1736518f17b7fb521e (diff) | |
Merge "Removing groups & ongoing from bubble ordering" into rvc-dev
5 files changed, 103 insertions, 420 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java index f1b401e77fbc..24ef324842d9 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java @@ -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,20 +284,13 @@ 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 */ boolean getWasAccessed() { @@ -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) */); } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java index 65d5bebc625d..43f65ded29cb 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java @@ -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; - } - - /** - * 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; + return bubble.getLastActivity(); } /** - * 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); } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDebugConfig.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDebugConfig.java index 19733a5f895c..d98fee399470 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDebugConfig.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleDebugConfig.java @@ -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())); } } diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java index bdfcb35f7df2..418cc505daa8 100644 --- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java +++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java @@ -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) */); } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java index 66f119a082a6..eca78ec38a88 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java @@ -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,69 +310,60 @@ 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 - sendUpdatedEntryAtTime(mEntryA1, 1000); - verifyUpdateReceived(); - assertOrderNotChanged(); - - sendUpdatedEntryAtTime(mEntryB1, 2000); - verifyUpdateReceived(); - assertOrderChangedTo(mBubbleB1, mBubbleA1); - - sendUpdatedEntryAtTime(mEntryB2, 3000); + mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_NOTIF_CANCEL); verifyUpdateReceived(); - assertOrderChangedTo(mBubbleB2, mBubbleB1, mBubbleA1); + assertOverflowChangedTo(ImmutableList.of(mBubbleA2)); - sendUpdatedEntryAtTime(mEntryA2, 4000); + // Test + mBubbleData.notificationEntryRemoved(mEntryA2, BubbleController.DISMISS_GROUP_CANCELLED); verifyUpdateReceived(); - assertOrderChangedTo(mBubbleA2, mBubbleA1, mBubbleB2, mBubbleB1); + assertOverflowChangedTo(ImmutableList.of()); } + // COLLAPSED / ADD + /** - * 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. + * Verifies that new bubbles insert to the left when collapsed. * <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() + * Placement within the list is based on {@link Bubble#getLastActivity()}, descending + * order (with most recent first). */ @Test - public void test_collapsed_addBubble_sortAndGrouping_withOngoing() { + public void test_collapsed_addBubble() { // Setup mBubbleData.setListener(mListener); // Test - setOngoing(mEntryA1, true); sendUpdatedEntryAtTime(mEntryA1, 1000); verifyUpdateReceived(); assertOrderNotChanged(); sendUpdatedEntryAtTime(mEntryB1, 2000); verifyUpdateReceived(); - assertOrderNotChanged(); + assertOrderChangedTo(mBubbleB1, mBubbleA1); sendUpdatedEntryAtTime(mEntryB2, 3000); verifyUpdateReceived(); - assertOrderChangedTo(mBubbleA1, mBubbleB2, mBubbleB1); + assertOrderChangedTo(mBubbleB2, mBubbleB1, mBubbleA1); 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,62 +426,16 @@ 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 @@ -587,26 +502,6 @@ public class BubbleDataTest extends SysuiTestCase { } /** - * 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. */ @Test @@ -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); - } - - /** - * 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); + assertOrderChangedTo(mBubbleC1, mBubbleB1, mBubbleA2, mBubbleA1); } /** - * 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); + assertSelectionChangedTo(mBubbleB1); - mBubbleData.notificationEntryRemoved(mEntryA1, BubbleController.DISMISS_USER_GESTURE); + mBubbleData.notificationEntryRemoved(mEntryB1, BubbleController.DISMISS_USER_GESTURE); verifyUpdateReceived(); - assertSelectionChangedTo(mBubbleB1); + 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); |