diff options
| author | 2020-05-13 17:24:53 -0400 | |
|---|---|---|
| committer | 2020-05-15 16:13:29 -0400 | |
| commit | 33d3b54639af8d8776244934329b3bd2e8045b03 (patch) | |
| tree | f6ac2aa3dff0c4b1752327efb9b33280a8b197b7 | |
| parent | 7c1333199152c5a687c5f75930040786eb783d9f (diff) | |
Rework Incoming section logic
We cannot assign notifications to the HUNing section during sort and
filter in NotifRankMan, because we don't know if those Notifications
can be placed there at that time. The VisStabMan can decide that they
cannot be moved, and so NotifSecMan can get confused when it sees
BUCKET_HEADS_UP in the middle of the shade.
In an ideal world, VisStabMan would inform the sort performed by
NotifRankMan, as opposed to "shooting it down" after the fact. The
main issue here is that NotifRankMan and NotifSecMan are logically
related (Notification ordering) but VisStabMan can throw a wrench in
that relationship.
Also I took the liberty of converting NotifSecMan to Kotlin. :-)
Fixes: 153554168
Test: atest, manual
Change-Id: I4d1d38eaf4eaac69542c7c115040e76ff95cc1c9
4 files changed, 304 insertions, 167 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt index 5475c2e062d7..cbf680c5b782 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt @@ -30,7 +30,6 @@ import com.android.systemui.statusbar.notification.people.PeopleNotificationIden import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING import com.android.systemui.statusbar.notification.stack.BUCKET_FOREGROUND_SERVICE -import com.android.systemui.statusbar.notification.stack.BUCKET_HEADS_UP import com.android.systemui.statusbar.notification.stack.BUCKET_PEOPLE import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT import com.android.systemui.statusbar.notification.stack.PriorityBucket @@ -138,23 +137,8 @@ open class NotificationRankingManager @Inject constructor( .filterNot(notifFilter::shouldFilterOut) .sortedWith(rankingComparator) .toList() - assignBuckets(filtered) - return filtered - } - - private fun assignBuckets(entries: List<NotificationEntry>) { entries.forEach { it.bucket = getBucketForEntry(it) } - if (!usePeopleFiltering) { - // If we don't have a Conversation section, just assign buckets normally based on the - // content. - return - } - // If HUNs are not continuous with the top section, break out into a new Incoming section. - entries.asReversed().asSequence().zipWithNext().forEach { (next, entry) -> - if (entry.isRowHeadsUp && entry.bucket > next.bucket) { - entry.bucket = BUCKET_HEADS_UP - } - } + return filtered } @PriorityBucket diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt index 92fdd6441539..17b414379f8d 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsLogger.kt @@ -52,14 +52,35 @@ class NotificationSectionsLogger @Inject constructor( { "$int1: other ($str1)" } ) - fun logHeadsUp(position: Int) = logPosition(position, "Heads Up") - fun logConversation(position: Int) = logPosition(position, "Conversation") - fun logAlerting(position: Int) = logPosition(position, "Alerting") - fun logSilent(position: Int) = logPosition(position, "Silent") - fun logForegroundService(position: Int) = logPosition(position, "Foreground Service") + fun logHeadsUp(position: Int, isHeadsUp: Boolean) = + logPosition(position, "Heads Up", isHeadsUp) + fun logConversation(position: Int, isHeadsUp: Boolean) = + logPosition(position, "Conversation", isHeadsUp) + fun logAlerting(position: Int, isHeadsUp: Boolean) = + logPosition(position, "Alerting", isHeadsUp) + fun logSilent(position: Int, isHeadsUp: Boolean) = + logPosition(position, "Silent", isHeadsUp) + fun logForegroundService(position: Int, isHeadsUp: Boolean) = + logPosition(position, "Foreground Service", isHeadsUp) fun logStr(str: String) = logBuffer.log(TAG, LogLevel.DEBUG, { str1 = str }, { "$str1" }) + private fun logPosition(position: Int, label: String, isHeadsUp: Boolean) { + val headsUpTag = if (isHeadsUp) " (HUN)" else "" + logBuffer.log( + TAG, + LogLevel.DEBUG, + { + int1 = position + str1 = label + str2 = headsUpTag + }, + { + "$int1: $str1$str2" + } + ) + } + private fun logPosition(position: Int, label: String) = logBuffer.log( TAG, LogLevel.DEBUG, diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt index a2daec15d90b..65633a2e209f 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt @@ -206,11 +206,14 @@ class NotificationSectionsManager @Inject internal constructor( child === alertingHeaderView -> logger.logAlertingHeader(i) child === silentHeaderView -> logger.logSilentHeader(i) child !is ExpandableNotificationRow -> logger.logOther(i, child.javaClass) - else -> when (child.entry.bucket) { - BUCKET_HEADS_UP -> logger.logHeadsUp(i) - BUCKET_PEOPLE -> logger.logConversation(i) - BUCKET_ALERTING -> logger.logAlerting(i) - BUCKET_SILENT -> logger.logSilent(i) + else -> { + val isHeadsUp = child.isHeadsUp + when (child.entry.bucket) { + BUCKET_HEADS_UP -> logger.logHeadsUp(i, isHeadsUp) + BUCKET_PEOPLE -> logger.logConversation(i, isHeadsUp) + BUCKET_ALERTING -> logger.logAlerting(i, isHeadsUp) + BUCKET_SILENT -> logger.logSilent(i, isHeadsUp) + } } } } @@ -242,7 +245,7 @@ class NotificationSectionsManager @Inject internal constructor( var peopleNotifsPresent = false var currentMediaControlsIdx = -1 - var mediaControlsTarget = if (usingMediaControls) 0 else -1 + val mediaControlsTarget = if (usingMediaControls) 0 else -1 var currentIncomingHeaderIdx = -1 var incomingHeaderTarget = -1 var currentPeopleHeaderIdx = -1 @@ -253,10 +256,12 @@ class NotificationSectionsManager @Inject internal constructor( var gentleHeaderTarget = -1 var lastNotifIndex = 0 + var lastIncomingIndex = -1 + var prev: ExpandableNotificationRow? = null - parent.children.forEachIndexed { i, child -> - // Track the existing positions of the headers + for ((i, child) in parent.children.withIndex()) { when { + // Track the existing positions of the headers child === incomingHeaderView -> { logger.logIncomingHeader(i) currentIncomingHeaderIdx = i @@ -280,41 +285,40 @@ class NotificationSectionsManager @Inject internal constructor( child !is ExpandableNotificationRow -> logger.logOther(i, child.javaClass) else -> { lastNotifIndex = i - when (child.entry.bucket) { - BUCKET_HEADS_UP -> { - logger.logHeadsUp(i) - if (showHeaders && incomingHeaderTarget == -1) { - incomingHeaderTarget = i - // Offset the target if there are other headers before this that - // will be moved. - if (currentIncomingHeaderIdx != -1) { - incomingHeaderTarget-- - } - if (currentMediaControlsIdx != -1) { - incomingHeaderTarget-- - } - if (currentPeopleHeaderIdx != -1) { - incomingHeaderTarget-- - } - if (currentAlertingHeaderIdx != -1) { - incomingHeaderTarget-- - } - if (currentGentleHeaderIdx != -1) { - incomingHeaderTarget-- - } + // Is there a section discontinuity? This usually occurs due to HUNs + if (prev?.entry?.bucket?.let { it > child.entry.bucket } == true) { + // Remove existing headers, and move the Incoming header if necessary + if (alertingHeaderTarget != -1) { + if (showHeaders && incomingHeaderTarget != -1) { + incomingHeaderTarget = alertingHeaderTarget } - if (mediaControlsTarget != -1) { - mediaControlsTarget++ + alertingHeaderTarget = -1 + } + if (peopleHeaderTarget != -1) { + if (showHeaders && incomingHeaderTarget != -1) { + incomingHeaderTarget = peopleHeaderTarget } + peopleHeaderTarget = -1 + } + if (showHeaders && incomingHeaderTarget == -1) { + incomingHeaderTarget = 0 } - BUCKET_FOREGROUND_SERVICE -> { - logger.logForegroundService(i) - if (mediaControlsTarget != -1) { - mediaControlsTarget++ + // Walk backwards changing all previous notifications to the Incoming + // section + for (j in i - 1 downTo lastIncomingIndex + 1) { + val prevChild = parent.getChildAt(j) + if (prevChild is ExpandableNotificationRow) { + prevChild.entry.bucket = BUCKET_HEADS_UP } } + // Track the new bottom of the Incoming section + lastIncomingIndex = i - 1 + } + val isHeadsUp = child.isHeadsUp + when (child.entry.bucket) { + BUCKET_FOREGROUND_SERVICE -> logger.logForegroundService(i, isHeadsUp) BUCKET_PEOPLE -> { - logger.logConversation(i) + logger.logConversation(i, isHeadsUp) peopleNotifsPresent = true if (showHeaders && peopleHeaderTarget == -1) { peopleHeaderTarget = i @@ -332,7 +336,7 @@ class NotificationSectionsManager @Inject internal constructor( } } BUCKET_ALERTING -> { - logger.logAlerting(i) + logger.logAlerting(i, isHeadsUp) if (showHeaders && usingPeopleFiltering && alertingHeaderTarget == -1) { alertingHeaderTarget = i // Offset the target if there are other headers before this that @@ -346,7 +350,7 @@ class NotificationSectionsManager @Inject internal constructor( } } BUCKET_SILENT -> { - logger.logSilent(i) + logger.logSilent(i, isHeadsUp) if (showHeaders && gentleHeaderTarget == -1) { gentleHeaderTarget = i // Offset the target if there are other headers before this that @@ -358,6 +362,8 @@ class NotificationSectionsManager @Inject internal constructor( } else -> throw IllegalStateException("Cannot find section bucket for view") } + + prev = child } } } @@ -393,12 +399,12 @@ class NotificationSectionsManager @Inject internal constructor( peopleHeaderView?.let { adjustHeaderVisibilityAndPosition(peopleHeaderTarget, it, currentPeopleHeaderIdx) } - mediaControlsView?.let { - adjustViewPosition(mediaControlsTarget, it, currentMediaControlsIdx) - } incomingHeaderView?.let { adjustHeaderVisibilityAndPosition(incomingHeaderTarget, it, currentIncomingHeaderIdx) } + mediaControlsView?.let { + adjustViewPosition(mediaControlsTarget, it, currentMediaControlsIdx) + } logger.logStr("Final order:") logShadeContents() @@ -575,14 +581,16 @@ class NotificationSectionsManager @Inject internal constructor( @IntDef( prefix = ["BUCKET_"], value = [ - BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE, BUCKET_MEDIA_CONTROLS, BUCKET_PEOPLE, - BUCKET_ALERTING, BUCKET_SILENT + BUCKET_UNKNOWN, BUCKET_MEDIA_CONTROLS, BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE, + BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT ] ) annotation class PriorityBucket -const val BUCKET_HEADS_UP = 0 -const val BUCKET_FOREGROUND_SERVICE = 1 -const val BUCKET_MEDIA_CONTROLS = 2 -const val BUCKET_PEOPLE = 3 -const val BUCKET_ALERTING = 4 -const val BUCKET_SILENT = 5 + +const val BUCKET_UNKNOWN = 0 +const val BUCKET_MEDIA_CONTROLS = 1 +const val BUCKET_HEADS_UP = 2 +const val BUCKET_FOREGROUND_SERVICE = 3 +const val BUCKET_PEOPLE = 4 +const val BUCKET_ALERTING = 5 +const val BUCKET_SILENT = 6 diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java index 02b6cbc0da9d..3dc941a0bd20 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java @@ -52,6 +52,7 @@ import com.android.systemui.media.KeyguardMediaController; import com.android.systemui.plugins.statusbar.StatusBarStateController; import com.android.systemui.statusbar.StatusBarState; import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager; +import com.android.systemui.statusbar.notification.collection.NotificationEntry; import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter; import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController; import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; @@ -135,7 +136,11 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { @Test public void testInsertHeader() { // GIVEN a stack with HI and LO rows but no section headers - setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.ALERTING, ChildType.GENTLE); + setStackState( + ALERTING, + ALERTING, + ALERTING, + GENTLE); // WHEN we update the section headers mSectionsManager.updateSectionBoundaries(); @@ -147,15 +152,18 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { @Test public void testRemoveHeader() { // GIVEN a stack that originally had a header between the HI and LO sections - setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.GENTLE); + setStackState( + ALERTING, + ALERTING, + GENTLE); mSectionsManager.updateSectionBoundaries(); // WHEN the last LO row is replaced with a HI row setStackState( - ChildType.ALERTING, - ChildType.ALERTING, - ChildType.GENTLE_HEADER, - ChildType.ALERTING); + ALERTING, + ALERTING, + GENTLE_HEADER, + ALERTING); clearInvocations(mNssl); mSectionsManager.updateSectionBoundaries(); @@ -166,7 +174,10 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { @Test public void testDoNothingIfHeaderAlreadyRemoved() { // GIVEN a stack with only HI rows - setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.ALERTING); + setStackState( + ALERTING, + ALERTING, + ALERTING); // WHEN we update the sections headers mSectionsManager.updateSectionBoundaries(); @@ -179,19 +190,19 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { public void testMoveHeaderForward() { // GIVEN a stack that originally had a header between the HI and LO sections setStackState( - ChildType.ALERTING, - ChildType.ALERTING, - ChildType.ALERTING, - ChildType.GENTLE); + ALERTING, + ALERTING, + ALERTING, + GENTLE); mSectionsManager.updateSectionBoundaries(); // WHEN the LO section moves forward setStackState( - ChildType.ALERTING, - ChildType.ALERTING, - ChildType.GENTLE, - ChildType.GENTLE_HEADER, - ChildType.GENTLE); + ALERTING, + ALERTING, + GENTLE, + GENTLE_HEADER, + GENTLE); mSectionsManager.updateSectionBoundaries(); // THEN the LO section header is also moved forward @@ -202,19 +213,19 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { public void testMoveHeaderBackward() { // GIVEN a stack that originally had a header between the HI and LO sections setStackState( - ChildType.ALERTING, - ChildType.GENTLE, - ChildType.GENTLE, - ChildType.GENTLE); + ALERTING, + GENTLE, + GENTLE, + GENTLE); mSectionsManager.updateSectionBoundaries(); // WHEN the LO section moves backward setStackState( - ChildType.ALERTING, - ChildType.GENTLE_HEADER, - ChildType.ALERTING, - ChildType.ALERTING, - ChildType.GENTLE); + ALERTING, + GENTLE_HEADER, + ALERTING, + ALERTING, + GENTLE); mSectionsManager.updateSectionBoundaries(); // THEN the LO section header is also moved backward (with appropriate index shifting) @@ -225,14 +236,8 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { public void testHeaderRemovedFromTransientParent() { // GIVEN a stack where the header is animating away setStackState( - ChildType.ALERTING, - ChildType.GENTLE, - ChildType.GENTLE, - ChildType.GENTLE); - mSectionsManager.updateSectionBoundaries(); - setStackState( - ChildType.ALERTING, - ChildType.GENTLE_HEADER); + ALERTING, + GENTLE_HEADER); mSectionsManager.updateSectionBoundaries(); clearInvocations(mNssl); @@ -241,8 +246,8 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { // WHEN the LO section reappears setStackState( - ChildType.ALERTING, - ChildType.GENTLE); + ALERTING, + GENTLE); mSectionsManager.updateSectionBoundaries(); // THEN the header is first removed from the transient parent before being added to the @@ -255,7 +260,11 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { public void testHeaderNotShownOnLockscreen() { // GIVEN a stack of HI and LO notifs on the lockscreen when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD); - setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.ALERTING, ChildType.GENTLE); + setStackState( + ALERTING, + ALERTING, + ALERTING, + GENTLE); // WHEN we update the section headers mSectionsManager.updateSectionBoundaries(); @@ -268,7 +277,11 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { public void testHeaderShownWhenEnterLockscreen() { // GIVEN a stack of HI and LO notifs on the lockscreen when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD); - setStackState(ChildType.ALERTING, ChildType.ALERTING, ChildType.ALERTING, ChildType.GENTLE); + setStackState( + ALERTING, + ALERTING, + ALERTING, + GENTLE); mSectionsManager.updateSectionBoundaries(); // WHEN we unlock @@ -282,7 +295,10 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { @Test public void testHeaderHiddenWhenEnterLockscreen() { // GIVEN a stack of HI and LO notifs on the shade - setStackState(ChildType.ALERTING, ChildType.GENTLE_HEADER, ChildType.GENTLE); + setStackState( + ALERTING, + GENTLE_HEADER, + GENTLE); // WHEN we go back to the keyguard when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD); @@ -297,10 +313,10 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { enablePeopleFiltering(); setStackState( - ChildType.GENTLE_HEADER, - ChildType.PERSON, - ChildType.ALERTING, - ChildType.GENTLE); + GENTLE_HEADER, + PERSON, + ALERTING, + GENTLE); mSectionsManager.updateSectionBoundaries(); verify(mNssl).changeViewPosition(mSectionsManager.getSilentHeaderView(), 2); @@ -313,9 +329,9 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { enablePeopleFiltering(); setStackState( - ChildType.PERSON, - ChildType.ALERTING, - ChildType.GENTLE); + PERSON, + ALERTING, + GENTLE); mSectionsManager.updateSectionBoundaries(); verify(mNssl).addView(mSectionsManager.getSilentHeaderView(), 2); @@ -328,12 +344,12 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { enablePeopleFiltering(); setStackState( - ChildType.PEOPLE_HEADER, - ChildType.ALERTING_HEADER, - ChildType.GENTLE_HEADER, - ChildType.PERSON, - ChildType.ALERTING, - ChildType.GENTLE); + PEOPLE_HEADER, + ALERTING_HEADER, + GENTLE_HEADER, + PERSON, + ALERTING, + GENTLE); mSectionsManager.updateSectionBoundaries(); verify(mNssl).changeViewPosition(mSectionsManager.getSilentHeaderView(), 4); @@ -347,12 +363,11 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { enablePeopleFiltering(); setStackState( - ChildType.PEOPLE_HEADER, - ChildType.ALERTING_HEADER, - ChildType.ALERTING, - ChildType.GENTLE_HEADER, - ChildType.GENTLE - ); + PEOPLE_HEADER, + ALERTING_HEADER, + ALERTING, + GENTLE_HEADER, + GENTLE); mSectionsManager.updateSectionBoundaries(); verify(mNssl, never()).removeView(mSectionsManager.getPeopleHeaderView()); @@ -360,41 +375,98 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { } @Test - public void testPeopleFiltering_HunWhilePeopleVisible() { + public void testPeopleFiltering_AlertingHunWhilePeopleVisible() { enablePeopleFiltering(); setupMockStack( - ChildType.PEOPLE_HEADER, + PEOPLE_HEADER, + ALERTING.headsUp(), + PERSON, + ALERTING_HEADER, + GENTLE_HEADER, + GENTLE + ); + mSectionsManager.updateSectionBoundaries(); + + verifyMockStack( + ChildType.INCOMING_HEADER, ChildType.HEADS_UP, + ChildType.PEOPLE_HEADER, ChildType.PERSON, - ChildType.ALERTING_HEADER, ChildType.GENTLE_HEADER, ChildType.GENTLE ); + } + + @Test + public void testPeopleFiltering_PersonHunWhileAlertingHunVisible() { + enablePeopleFiltering(); + + setupMockStack( + PERSON.headsUp(), + INCOMING_HEADER, + ALERTING.headsUp(), + PEOPLE_HEADER, + PERSON + ); mSectionsManager.updateSectionBoundaries(); verifyMockStack( ChildType.INCOMING_HEADER, ChildType.HEADS_UP, + ChildType.HEADS_UP, + ChildType.PEOPLE_HEADER, + ChildType.PERSON + ); + } + + @Test + public void testPeopleFiltering_PersonHun() { + enablePeopleFiltering(); + + setupMockStack( + PERSON.headsUp(), + PEOPLE_HEADER, + PERSON + ); + mSectionsManager.updateSectionBoundaries(); + + verifyMockStack( ChildType.PEOPLE_HEADER, ChildType.PERSON, - ChildType.GENTLE_HEADER, - ChildType.GENTLE + ChildType.PERSON ); } @Test - public void testPeopleFiltering_Fsn() { + public void testPeopleFiltering_AlertingHunWhilePersonHunning() { enablePeopleFiltering(); setupMockStack( + ALERTING.headsUp(), + PERSON.headsUp() + ); + mSectionsManager.updateSectionBoundaries(); + verifyMockStack( ChildType.INCOMING_HEADER, ChildType.HEADS_UP, ChildType.PEOPLE_HEADER, - ChildType.FSN, - ChildType.PERSON, - ChildType.ALERTING, - ChildType.GENTLE + ChildType.PERSON + ); + } + + @Test + public void testPeopleFiltering_Fsn() { + enablePeopleFiltering(); + + setupMockStack( + INCOMING_HEADER, + ALERTING.headsUp(), + PEOPLE_HEADER, + FSN, + PERSON, + ALERTING, + GENTLE ); mSectionsManager.updateSectionBoundaries(); @@ -416,7 +488,7 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { enableMediaControls(); // GIVEN a stack that doesn't include media controls - setStackState(ChildType.ALERTING, ChildType.GENTLE_HEADER, ChildType.GENTLE); + setStackState(ALERTING, GENTLE_HEADER, GENTLE); // WHEN we go back to the keyguard when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD); @@ -431,14 +503,20 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { enableMediaControls(); // GIVEN a stack that doesn't include media controls but includes HEADS_UP - setupMockStack(ChildType.HEADS_UP, ChildType.ALERTING, ChildType.GENTLE_HEADER, - ChildType.GENTLE); + setupMockStack( + ALERTING.headsUp(), + ALERTING, + GENTLE_HEADER, + GENTLE); // WHEN we go back to the keyguard when(mStatusBarStateController.getState()).thenReturn(StatusBarState.KEYGUARD); mSectionsManager.updateSectionBoundaries(); - verifyMockStack(ChildType.HEADS_UP, ChildType.MEDIA_CONTROLS, ChildType.ALERTING, + verifyMockStack( + ChildType.MEDIA_CONTROLS, + ChildType.ALERTING, + ChildType.ALERTING, ChildType.GENTLE); } @@ -455,11 +533,12 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { FSN, PERSON, ALERTING, GENTLE, OTHER } - private void setStackState(ChildType... children) { + private void setStackState(StackEntry... children) { when(mNssl.getChildCount()).thenReturn(children.length); for (int i = 0; i < children.length; i++) { View child; - switch (children[i]) { + StackEntry entry = children[i]; + switch (entry.mChildType) { case INCOMING_HEADER: child = mSectionsManager.getIncomingHeaderView(); break; @@ -475,20 +554,17 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { case GENTLE_HEADER: child = mSectionsManager.getSilentHeaderView(); break; - case HEADS_UP: - child = mockNotification(BUCKET_HEADS_UP); - break; case FSN: - child = mockNotification(BUCKET_FOREGROUND_SERVICE); + child = mockNotification(BUCKET_FOREGROUND_SERVICE, entry.mIsHeadsUp); break; case PERSON: - child = mockNotification(BUCKET_PEOPLE); + child = mockNotification(BUCKET_PEOPLE, entry.mIsHeadsUp); break; case ALERTING: - child = mockNotification(BUCKET_ALERTING); + child = mockNotification(BUCKET_ALERTING, entry.mIsHeadsUp); break; case GENTLE: - child = mockNotification(BUCKET_SILENT); + child = mockNotification(BUCKET_SILENT, entry.mIsHeadsUp); break; case OTHER: child = mock(View.class); @@ -503,12 +579,24 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { } } - private View mockNotification(int bucket) { - ExpandableNotificationRow notifRow = mock(ExpandableNotificationRow.class, - RETURNS_DEEP_STUBS); + private View mockNotification(int bucket, boolean headsUp) { + ExpandableNotificationRow notifRow = + mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS); when(notifRow.getVisibility()).thenReturn(View.VISIBLE); - when(notifRow.getEntry().getBucket()).thenReturn(bucket); when(notifRow.getParent()).thenReturn(mNssl); + + NotificationEntry mockEntry = mock(NotificationEntry.class); + when(notifRow.getEntry()).thenReturn(mockEntry); + + int[] bucketRef = new int[] { bucket }; + when(mockEntry.getBucket()).thenAnswer(invocation -> bucketRef[0]); + doAnswer(invocation -> { + bucketRef[0] = invocation.getArgument(0); + return null; + }).when(mockEntry).setBucket(anyInt()); + + when(notifRow.isHeadsUp()).thenReturn(headsUp); + when(mockEntry.isRowHeadsUp()).thenReturn(headsUp); return notifRow; } @@ -565,7 +653,7 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { assertThat(actual).containsExactly((Object[]) expected).inOrder(); } - private void setupMockStack(ChildType... childTypes) { + private void setupMockStack(StackEntry... entries) { final List<View> children = new ArrayList<>(); when(mNssl.getChildCount()).thenAnswer(invocation -> children.size()); when(mNssl.getChildAt(anyInt())) @@ -590,9 +678,9 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { children.add(newIndex, child); return null; }).when(mNssl).changeViewPosition(any(), anyInt()); - for (ChildType childType : childTypes) { + for (StackEntry entry : entries) { View child; - switch (childType) { + switch (entry.mChildType) { case INCOMING_HEADER: child = mSectionsManager.getIncomingHeaderView(); break; @@ -608,20 +696,17 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { case GENTLE_HEADER: child = mSectionsManager.getSilentHeaderView(); break; - case HEADS_UP: - child = mockNotification(BUCKET_HEADS_UP); - break; case FSN: - child = mockNotification(BUCKET_FOREGROUND_SERVICE); + child = mockNotification(BUCKET_FOREGROUND_SERVICE, entry.mIsHeadsUp); break; case PERSON: - child = mockNotification(BUCKET_PEOPLE); + child = mockNotification(BUCKET_PEOPLE, entry.mIsHeadsUp); break; case ALERTING: - child = mockNotification(BUCKET_ALERTING); + child = mockNotification(BUCKET_ALERTING, entry.mIsHeadsUp); break; case GENTLE: - child = mockNotification(BUCKET_SILENT); + child = mockNotification(BUCKET_SILENT, entry.mIsHeadsUp); break; case OTHER: child = mock(View.class); @@ -629,9 +714,48 @@ public class NotificationSectionsManagerTest extends SysuiTestCase { when(child.getParent()).thenReturn(mNssl); break; default: - throw new RuntimeException("Unknown ChildType: " + childType); + throw new RuntimeException("Unknown ChildType: " + entry.mChildType); } children.add(child); } } + + private static final StackEntry INCOMING_HEADER = new StackEntry(ChildType.INCOMING_HEADER); + private static final StackEntry MEDIA_CONTROLS = new StackEntry(ChildType.MEDIA_CONTROLS); + private static final StackEntry PEOPLE_HEADER = new StackEntry(ChildType.PEOPLE_HEADER); + private static final StackEntry ALERTING_HEADER = new StackEntry(ChildType.ALERTING_HEADER); + private static final StackEntry GENTLE_HEADER = new StackEntry(ChildType.GENTLE_HEADER); + private static final StackEntry FSN = new StackEntry(ChildType.FSN); + private static final StackEntry.Hunnable PERSON = new StackEntry.Hunnable(ChildType.PERSON); + private static final StackEntry.Hunnable ALERTING = new StackEntry.Hunnable(ChildType.ALERTING); + private static final StackEntry GENTLE = new StackEntry(ChildType.GENTLE); + + private static class StackEntry { + final ChildType mChildType; + final boolean mIsHeadsUp; + + StackEntry(ChildType childType) { + this(childType, false); + } + + StackEntry(ChildType childType, boolean isHeadsUp) { + mChildType = childType; + mIsHeadsUp = isHeadsUp; + } + + static class Hunnable extends StackEntry { + + Hunnable(ChildType childType) { + super(childType, false); + } + + Hunnable(ChildType childType, boolean isHeadsUp) { + super(childType, isHeadsUp); + } + + public Hunnable headsUp() { + return new Hunnable(mChildType, true); + } + } + } } |