diff options
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); + } + } + } } |