Loading packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java +10 −0 Original line number Diff line number Diff line Loading @@ -285,6 +285,15 @@ class Bubble implements BubbleViewProvider { mInflateSynchronously = inflateSynchronously; } /** * Sets whether this bubble is considered visually interruptive. Normally pulled from the * {@link NotificationEntry}, this method is purely for testing. */ @VisibleForTesting void setVisuallyInterruptiveForTest(boolean visuallyInterruptive) { mIsVisuallyInterruptive = visuallyInterruptive; } /** * Starts a task to inflate & load any necessary information to display a bubble. * Loading Loading @@ -411,6 +420,7 @@ class Bubble implements BubbleViewProvider { } else if (mIntent != null && entry.getBubbleMetadata().getIntent() == null) { // Was an intent bubble now it's a shortcut bubble... still unregister the listener mIntent.unregisterCancelListener(mIntentCancelListener); mIntentActive = false; mIntent = null; } mDeleteIntent = entry.getBubbleMetadata().getDeleteIntent(); Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +13 −4 Original line number Diff line number Diff line Loading @@ -82,7 +82,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.Dumpable; import com.android.systemui.bubbles.animation.StackAnimationController; import com.android.systemui.bubbles.dagger.BubbleModule; import com.android.systemui.dump.DumpManager; import com.android.systemui.model.SysUiState; Loading Loading @@ -407,7 +406,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (bubble.getBubbleIntent() == null) { return; } if (bubble.isIntentActive()) { if (bubble.isIntentActive() || mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { bubble.setPendingIntentCanceled(); return; } Loading Loading @@ -1120,9 +1120,18 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (notif.getImportance() >= NotificationManager.IMPORTANCE_HIGH) { notif.setInterruption(); } if (!notif.getRanking().visuallyInterruptive() && (notif.getBubbleMetadata() != null && !notif.getBubbleMetadata().getAutoExpandBubble()) && mBubbleData.hasOverflowBubbleWithKey(notif.getKey())) { // Update the bubble but don't promote it out of overflow Bubble b = mBubbleData.getOverflowBubbleWithKey(notif.getKey()); b.setEntry(notif); } else { Bubble bubble = mBubbleData.getOrCreateBubble(notif, null /* persistedBubble */); inflateAndAdd(bubble, suppressFlyout, showInShade); } } void inflateAndAdd(Bubble bubble, boolean suppressFlyout, boolean showInShade) { // Lazy init stack view when a bubble is created Loading packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +4 −3 Original line number Diff line number Diff line Loading @@ -277,7 +277,8 @@ public class BubbleData { } else { // Updates an existing bubble bubble.setSuppressFlyout(suppressFlyout); doUpdate(bubble); // If there is no flyout, we probably shouldn't show the bubble at the top doUpdate(bubble, !suppressFlyout /* reorder */); } if (bubble.shouldAutoExpand()) { Loading Loading @@ -431,12 +432,12 @@ public class BubbleData { } } private void doUpdate(Bubble bubble) { private void doUpdate(Bubble bubble, boolean reorder) { if (DEBUG_BUBBLE_DATA) { Log.d(TAG, "doUpdate: " + bubble); } mStateChange.updatedBubble = bubble; if (!isExpanded()) { if (!isExpanded() && reorder) { int prevPos = mBubbles.indexOf(bubble); mBubbles.remove(bubble); mBubbles.add(0, bubble); Loading packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +23 −0 Original line number Diff line number Diff line Loading @@ -999,6 +999,29 @@ public class BubbleControllerTest extends SysuiTestCase { verify(mNotificationGroupManager, times(1)).onEntryRemoved(groupSummary.getEntry()); } /** * Verifies that when a non visually interruptive update occurs for a bubble in the overflow, * the that bubble does not get promoted from the overflow. */ @Test public void test_notVisuallyInterruptive_updateOverflowBubble_notAdded() { // Setup mBubbleController.updateBubble(mRow.getEntry()); mBubbleController.updateBubble(mRow2.getEntry()); assertTrue(mBubbleController.hasBubbles()); // Overflow it mBubbleData.dismissBubbleWithKey(mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); assertThat(mBubbleData.hasBubbleInStackWithKey(mRow.getEntry().getKey())).isFalse(); assertThat(mBubbleData.hasOverflowBubbleWithKey(mRow.getEntry().getKey())).isTrue(); // Test mBubbleController.updateBubble(mRow.getEntry()); assertThat(mBubbleData.hasBubbleInStackWithKey(mRow.getEntry().getKey())).isFalse(); } /** * Sets the bubble metadata flags for this entry. These ]flags are normally set by * NotificationManagerService when the notification is sent, however, these tests do not Loading packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java +26 −0 Original line number Diff line number Diff line Loading @@ -512,6 +512,26 @@ public class BubbleDataTest extends SysuiTestCase { assertSelectionChangedTo(mBubbleA1); } /** * Verifies that when a non visually interruptive update occurs, that the selection does not * change. */ @Test public void test_notVisuallyInterruptive_updateBubble_selectionDoesntChange() { // Setup sendUpdatedEntryAtTime(mEntryA1, 1000); sendUpdatedEntryAtTime(mEntryB1, 2000); sendUpdatedEntryAtTime(mEntryB2, 3000); sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1] mBubbleData.setListener(mListener); assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA2); // Test sendUpdatedEntryAtTime(mEntryB1, 5000, false /* isVisuallyInterruptive */); assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA2); } /** * Verifies that a request to expand the stack has no effect if there are no bubbles. */ Loading Loading @@ -883,9 +903,15 @@ public class BubbleDataTest extends SysuiTestCase { } private void sendUpdatedEntryAtTime(NotificationEntry entry, long postTime) { sendUpdatedEntryAtTime(entry, postTime, true /* visuallyInterruptive */); } private void sendUpdatedEntryAtTime(NotificationEntry entry, long postTime, boolean visuallyInterruptive) { setPostTime(entry, postTime); // BubbleController calls this: Bubble b = mBubbleData.getOrCreateBubble(entry, null /* persistedBubble */); b.setVisuallyInterruptiveForTest(visuallyInterruptive); // And then this mBubbleData.notificationEntryUpdated(b, false /* suppressFlyout*/, true /* showInShade */); Loading Loading
packages/SystemUI/src/com/android/systemui/bubbles/Bubble.java +10 −0 Original line number Diff line number Diff line Loading @@ -285,6 +285,15 @@ class Bubble implements BubbleViewProvider { mInflateSynchronously = inflateSynchronously; } /** * Sets whether this bubble is considered visually interruptive. Normally pulled from the * {@link NotificationEntry}, this method is purely for testing. */ @VisibleForTesting void setVisuallyInterruptiveForTest(boolean visuallyInterruptive) { mIsVisuallyInterruptive = visuallyInterruptive; } /** * Starts a task to inflate & load any necessary information to display a bubble. * Loading Loading @@ -411,6 +420,7 @@ class Bubble implements BubbleViewProvider { } else if (mIntent != null && entry.getBubbleMetadata().getIntent() == null) { // Was an intent bubble now it's a shortcut bubble... still unregister the listener mIntent.unregisterCancelListener(mIntentCancelListener); mIntentActive = false; mIntent = null; } mDeleteIntent = entry.getBubbleMetadata().getDeleteIntent(); Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleController.java +13 −4 Original line number Diff line number Diff line Loading @@ -82,7 +82,6 @@ import com.android.internal.annotations.VisibleForTesting; import com.android.internal.statusbar.IStatusBarService; import com.android.internal.statusbar.NotificationVisibility; import com.android.systemui.Dumpable; import com.android.systemui.bubbles.animation.StackAnimationController; import com.android.systemui.bubbles.dagger.BubbleModule; import com.android.systemui.dump.DumpManager; import com.android.systemui.model.SysUiState; Loading Loading @@ -407,7 +406,8 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (bubble.getBubbleIntent() == null) { return; } if (bubble.isIntentActive()) { if (bubble.isIntentActive() || mBubbleData.hasBubbleInStackWithKey(bubble.getKey())) { bubble.setPendingIntentCanceled(); return; } Loading Loading @@ -1120,9 +1120,18 @@ public class BubbleController implements ConfigurationController.ConfigurationLi if (notif.getImportance() >= NotificationManager.IMPORTANCE_HIGH) { notif.setInterruption(); } if (!notif.getRanking().visuallyInterruptive() && (notif.getBubbleMetadata() != null && !notif.getBubbleMetadata().getAutoExpandBubble()) && mBubbleData.hasOverflowBubbleWithKey(notif.getKey())) { // Update the bubble but don't promote it out of overflow Bubble b = mBubbleData.getOverflowBubbleWithKey(notif.getKey()); b.setEntry(notif); } else { Bubble bubble = mBubbleData.getOrCreateBubble(notif, null /* persistedBubble */); inflateAndAdd(bubble, suppressFlyout, showInShade); } } void inflateAndAdd(Bubble bubble, boolean suppressFlyout, boolean showInShade) { // Lazy init stack view when a bubble is created Loading
packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java +4 −3 Original line number Diff line number Diff line Loading @@ -277,7 +277,8 @@ public class BubbleData { } else { // Updates an existing bubble bubble.setSuppressFlyout(suppressFlyout); doUpdate(bubble); // If there is no flyout, we probably shouldn't show the bubble at the top doUpdate(bubble, !suppressFlyout /* reorder */); } if (bubble.shouldAutoExpand()) { Loading Loading @@ -431,12 +432,12 @@ public class BubbleData { } } private void doUpdate(Bubble bubble) { private void doUpdate(Bubble bubble, boolean reorder) { if (DEBUG_BUBBLE_DATA) { Log.d(TAG, "doUpdate: " + bubble); } mStateChange.updatedBubble = bubble; if (!isExpanded()) { if (!isExpanded() && reorder) { int prevPos = mBubbles.indexOf(bubble); mBubbles.remove(bubble); mBubbles.add(0, bubble); Loading
packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java +23 −0 Original line number Diff line number Diff line Loading @@ -999,6 +999,29 @@ public class BubbleControllerTest extends SysuiTestCase { verify(mNotificationGroupManager, times(1)).onEntryRemoved(groupSummary.getEntry()); } /** * Verifies that when a non visually interruptive update occurs for a bubble in the overflow, * the that bubble does not get promoted from the overflow. */ @Test public void test_notVisuallyInterruptive_updateOverflowBubble_notAdded() { // Setup mBubbleController.updateBubble(mRow.getEntry()); mBubbleController.updateBubble(mRow2.getEntry()); assertTrue(mBubbleController.hasBubbles()); // Overflow it mBubbleData.dismissBubbleWithKey(mRow.getEntry().getKey(), BubbleController.DISMISS_USER_GESTURE); assertThat(mBubbleData.hasBubbleInStackWithKey(mRow.getEntry().getKey())).isFalse(); assertThat(mBubbleData.hasOverflowBubbleWithKey(mRow.getEntry().getKey())).isTrue(); // Test mBubbleController.updateBubble(mRow.getEntry()); assertThat(mBubbleData.hasBubbleInStackWithKey(mRow.getEntry().getKey())).isFalse(); } /** * Sets the bubble metadata flags for this entry. These ]flags are normally set by * NotificationManagerService when the notification is sent, however, these tests do not Loading
packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleDataTest.java +26 −0 Original line number Diff line number Diff line Loading @@ -512,6 +512,26 @@ public class BubbleDataTest extends SysuiTestCase { assertSelectionChangedTo(mBubbleA1); } /** * Verifies that when a non visually interruptive update occurs, that the selection does not * change. */ @Test public void test_notVisuallyInterruptive_updateBubble_selectionDoesntChange() { // Setup sendUpdatedEntryAtTime(mEntryA1, 1000); sendUpdatedEntryAtTime(mEntryB1, 2000); sendUpdatedEntryAtTime(mEntryB2, 3000); sendUpdatedEntryAtTime(mEntryA2, 4000); // [A2, B2, B1, A1] mBubbleData.setListener(mListener); assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA2); // Test sendUpdatedEntryAtTime(mEntryB1, 5000, false /* isVisuallyInterruptive */); assertThat(mBubbleData.getSelectedBubble()).isEqualTo(mBubbleA2); } /** * Verifies that a request to expand the stack has no effect if there are no bubbles. */ Loading Loading @@ -883,9 +903,15 @@ public class BubbleDataTest extends SysuiTestCase { } private void sendUpdatedEntryAtTime(NotificationEntry entry, long postTime) { sendUpdatedEntryAtTime(entry, postTime, true /* visuallyInterruptive */); } private void sendUpdatedEntryAtTime(NotificationEntry entry, long postTime, boolean visuallyInterruptive) { setPostTime(entry, postTime); // BubbleController calls this: Bubble b = mBubbleData.getOrCreateBubble(entry, null /* persistedBubble */); b.setVisuallyInterruptiveForTest(visuallyInterruptive); // And then this mBubbleData.notificationEntryUpdated(b, false /* suppressFlyout*/, true /* showInShade */); Loading