Loading packages/SystemUI/res/values/dimens.xml +1 −1 Original line number Diff line number Diff line Loading @@ -386,7 +386,7 @@ <dimen name="split_shade_notifications_scrim_margin_bottom">0dp</dimen> <dimen name="shelf_and_lock_icon_overlap">5dp</dimen> <dimen name="shelf_and_lock_icon_overlap">@dimen/notification_shelf_height</dimen> <dimen name="notification_panel_margin_horizontal">0dp</dimen> Loading packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt +88 −20 Original line number Diff line number Diff line Loading @@ -39,7 +39,11 @@ private const val TAG = "NotifStackSizeCalc" private val DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG) private val SPEW = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE) /** Calculates number of notifications to display and the height of the notification stack. */ /** * Calculates number of notifications to display and the height of the notification stack. * "Notifications" refers to any ExpandableView that we show on lockscreen, which can include the * media player. */ @SysUISingleton class NotificationStackSizeCalculator @Inject Loading @@ -65,21 +69,60 @@ constructor( } /** * Given the [totalAvailableSpace] constraint, calculates how many notification to show. * * This number is only valid in keyguard. * Returns whether notifications and (shelf if visible) can fit in total space available. * [spaceForShelf] is extra vertical space allowed for the shelf to overlap the lock icon. */ private fun canStackFitInSpace( stackHeight: StackHeight, spaceForNotifications: Float, spaceForShelf: Float, ): Boolean { val (notificationsHeight, shelfHeightWithSpaceBefore) = stackHeight var canFit: Boolean if (shelfHeightWithSpaceBefore == 0f) { canFit = notificationsHeight <= spaceForNotifications log { "canStackFitInSpace[$canFit] = notificationsHeight[$notificationsHeight]" + " <= spaceForNotifications[$spaceForNotifications]" } } else { canFit = (notificationsHeight + shelfHeightWithSpaceBefore) <= (spaceForNotifications + spaceForShelf) log { "canStackFitInSpace[$canFit] = (notificationsHeight[$notificationsHeight]" + " + shelfHeightWithSpaceBefore[$shelfHeightWithSpaceBefore])" + " <= (spaceForNotifications[$spaceForNotifications] " + " + spaceForShelf[$spaceForShelf])" } } return canFit } /** * Given the [spaceForNotifications] and [spaceForShelf] constraints, calculate how many * notifications to show. This number is only valid in keyguard. * * @param totalAvailableSpace space for notifications. This includes the space for the shelf. */ fun computeMaxKeyguardNotifications( stack: NotificationStackScrollLayout, totalAvailableSpace: Float, spaceForNotifications: Float, spaceForShelf: Float, shelfIntrinsicHeight: Float ): Int { log { "\n" } val stackHeightSequence = computeHeightPerNotificationLimit(stack, shelfIntrinsicHeight) var maxNotifications = stackHeightSequence.lastIndexWhile { stackHeight -> stackHeight <= totalAvailableSpace } stackHeightSequence.lastIndexWhile { heightResult -> canStackFitInSpace( heightResult, spaceForNotifications = spaceForNotifications, spaceForShelf = spaceForShelf) } if (onLockscreen()) { maxNotifications = min(maxKeyguardNotifications, maxNotifications) Loading @@ -90,7 +133,8 @@ constructor( log { val sequence = if (SPEW) " stackHeightSequence=${stackHeightSequence.toList()}" else "" "computeMaxKeyguardNotifications(" + "availableSpace=$totalAvailableSpace" + " spaceForNotifications=$spaceForNotifications" + " spaceForShelf=$spaceForShelf" + " shelfHeight=$shelfIntrinsicHeight) -> $maxNotifications$sequence" } return maxNotifications Loading @@ -112,33 +156,51 @@ constructor( maxNotifications: Int, shelfIntrinsicHeight: Float ): Float { log { "\n" } val heightPerMaxNotifications = computeHeightPerNotificationLimit(stack, shelfIntrinsicHeight) val height = val (notificationsHeight, shelfHeightWithSpaceBefore) = heightPerMaxNotifications.elementAtOrElse(maxNotifications) { heightPerMaxNotifications.last() // Height with all notifications visible. } log { "computeHeight(maxNotifications=$maxNotifications) -> $height" } return height log { "computeHeight(maxNotifications=$maxNotifications," + "shelfIntrinsicHeight=$shelfIntrinsicHeight) -> " + "${notificationsHeight + shelfHeightWithSpaceBefore}" + " = ($notificationsHeight + $shelfHeightWithSpaceBefore)" } return notificationsHeight + shelfHeightWithSpaceBefore } /** The ith result in the sequence is the height with ith max notifications. */ private data class StackHeight( // Float height with ith max notifications (not including shelf) val notificationsHeight: Float, // Float height of shelf (0 if shelf is not showing), and space before the shelf that // changes during the lockscreen <=> full shade transition. val shelfHeightWithSpaceBefore: Float ) private fun computeHeightPerNotificationLimit( stack: NotificationStackScrollLayout, shelfIntrinsicHeight: Float ): Sequence<Float> = sequence { shelfHeight: Float ): Sequence<StackHeight> = sequence { log { "computeHeightPerNotificationLimit" } val children = stack.showableChildren().toList() var height = 0f var notifications = 0f var previous: ExpandableView? = null val onLockscreen = onLockscreen() yield(dividerHeight + shelfIntrinsicHeight) // Only shelf. // Only shelf. This should never happen, since we allow 1 view minimum (EmptyViewState). yield(StackHeight(notificationsHeight = 0f, shelfHeightWithSpaceBefore = shelfHeight)) children.forEachIndexed { i, currentNotification -> height += spaceNeeded(currentNotification, i, previous, stack, onLockscreen) notifications += spaceNeeded(currentNotification, i, previous, stack, onLockscreen) previous = currentNotification val shelfHeight = val shelfWithSpaceBefore = if (i == children.lastIndex) { 0f // No shelf needed. } else { Loading @@ -149,10 +211,16 @@ constructor( previous = currentNotification, current = children[firstViewInShelfIndex], currentIndex = firstViewInShelfIndex) spaceBeforeShelf + shelfIntrinsicHeight spaceBeforeShelf + shelfHeight } yield(height + shelfHeight) log { "i=$i notificationsHeight=$notifications " + "shelfHeightWithSpaceBefore=$shelfWithSpaceBefore" } yield( StackHeight( notificationsHeight = notifications, shelfHeightWithSpaceBefore = shelfWithSpaceBefore)) } } Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +59 −36 Original line number Diff line number Diff line Loading @@ -1520,50 +1520,77 @@ public class NotificationPanelViewController extends PanelViewController { return (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight; } /** * @return Space available to show notifications on lockscreen. */ @VisibleForTesting float getSpaceForLockscreenNotifications() { float staticTopPadding = mClockPositionAlgorithm.getLockscreenMinStackScrollerPadding() // getMinStackScrollerPadding is from the top of the screen, // but we need it from the top of the NSSL. - mNotificationStackScrollLayoutController.getTop(); // Space between bottom of notifications and top of lock icon or udfps background. float lockIconPadding = mLockIconViewController.getTop(); if (mLockIconViewController.getTop() != 0) { /** Returns space between top of lock icon and bottom of NotificationStackScrollLayout. */ private float getLockIconPadding() { float lockIconPadding = 0f; if (mLockIconViewController.getTop() != 0f) { lockIconPadding = mNotificationStackScrollLayoutController.getBottom() - mLockIconViewController.getTop() - mShelfAndLockIconOverlap; - mLockIconViewController.getTop(); } return lockIconPadding; } /** Returns space available to show notifications on lockscreen. */ @VisibleForTesting float getVerticalSpaceForLockscreenNotifications() { final float lockIconPadding = getLockIconPadding(); float bottomPadding = Math.max(lockIconPadding, Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding)); mKeyguardNotificationBottomPadding = bottomPadding; float staticTopPadding = mClockPositionAlgorithm.getLockscreenMinStackScrollerPadding() // getMinStackScrollerPadding is from the top of the screen, // but we need it from the top of the NSSL. - mNotificationStackScrollLayoutController.getTop(); mKeyguardNotificationTopPadding = staticTopPadding; // To debug the available space, enable debug lines in this class. If you change how the // available space is calculated, please also update those lines. float availableSpace = final float verticalSpace = mNotificationStackScrollLayoutController.getHeight() - staticTopPadding - bottomPadding; if (SPEW_LOGCAT) { Log.d(TAG, "getSpaceForLockscreenNotifications()" + " availableSpace=" + availableSpace + " NSSL.height=" + mNotificationStackScrollLayoutController.getHeight() + " NSSL.top=" + mNotificationStackScrollLayoutController.getTop() + " staticTopPadding=" + staticTopPadding + " bottomPadding=" + bottomPadding + " lockIconPadding=" + lockIconPadding + " mIndicationBottomPadding=" + mIndicationBottomPadding + " mAmbientIndicationBottomPadding=" + mAmbientIndicationBottomPadding Log.i(TAG, "\n"); Log.i(TAG, "staticTopPadding[" + staticTopPadding + "] = Clock.padding[" + mClockPositionAlgorithm.getLockscreenMinStackScrollerPadding() + "] - NSSLC.top[" + mNotificationStackScrollLayoutController.getTop() + "]" ); Log.i(TAG, "bottomPadding[" + bottomPadding + "] = max(ambientIndicationBottomPadding[" + mAmbientIndicationBottomPadding + "], mIndicationBottomPadding[" + mIndicationBottomPadding + "], lockIconPadding[" + lockIconPadding + "])" ); Log.i(TAG, "verticalSpaceForNotifications[" + verticalSpace + "] = NSSL.height[" + mNotificationStackScrollLayoutController.getHeight() + "] - staticTopPadding[" + staticTopPadding + "] - bottomPadding[" + bottomPadding + "]" ); } return availableSpace; return verticalSpace; } /** Returns extra space available to show the shelf on lockscreen */ @VisibleForTesting float getVerticalSpaceForLockscreenShelf() { final float lockIconPadding = getLockIconPadding(); final float noShelfOverlapBottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding); final float extraSpaceForShelf = lockIconPadding - noShelfOverlapBottomPadding; if (extraSpaceForShelf > 0f) { return Math.min(mNotificationShelfController.getIntrinsicHeight(), extraSpaceForShelf); } return 0f; } /** Loading @@ -1579,16 +1606,12 @@ public class NotificationPanelViewController extends PanelViewController { } return mMaxAllowedKeyguardNotifications; } final float shelfIntrinsicHeight = mNotificationShelfController.getVisibility() == View.GONE ? 0 : mNotificationShelfController.getIntrinsicHeight(); return mNotificationStackSizeCalculator.computeMaxKeyguardNotifications( mNotificationStackScrollLayoutController.getView(), getSpaceForLockscreenNotifications(), shelfIntrinsicHeight); getVerticalSpaceForLockscreenNotifications(), getVerticalSpaceForLockscreenShelf(), mNotificationShelfController.getIntrinsicHeight() ); } private void updateClock() { Loading Loading @@ -3812,7 +3835,7 @@ public class NotificationPanelViewController extends PanelViewController { public void setAmbientIndicationTop(int ambientIndicationTop, boolean ambientTextVisible) { int ambientIndicationBottomPadding = 0; if (ambientTextVisible) { int stackBottom = mNotificationStackScrollLayoutController.getView().getBottom(); int stackBottom = mNotificationStackScrollLayoutController.getBottom(); ambientIndicationBottomPadding = stackBottom - ambientIndicationTop; } if (mAmbientIndicationBottomPadding != ambientIndicationBottomPadding) { Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt +58 −30 Original line number Diff line number Diff line Loading @@ -46,7 +46,8 @@ import org.mockito.MockitoAnnotations class NotificationStackSizeCalculatorTest : SysuiTestCase() { @Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController @Mock private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController @Mock private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController @Mock private lateinit var stackLayout: NotificationStackScrollLayout private val testableResources = mContext.orCreateTestableResources Loading Loading @@ -74,7 +75,8 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { val rows = listOf(createMockRow(height = rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace = 0f, shelfHeight = 0f) computeMaxKeyguardNotifications( rows, spaceForNotifications = 0f, spaceForShelf = 0f, shelfHeight = 0f) assertThat(maxNotifications).isEqualTo(0) } Loading @@ -84,7 +86,12 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { val numberOfRows = 30 val rows = createLockscreenRows(numberOfRows) val maxNotifications = computeMaxKeyguardNotifications(rows, Float.MAX_VALUE) val maxNotifications = computeMaxKeyguardNotifications( rows, spaceForNotifications = Float.MAX_VALUE, spaceForShelf = Float.MAX_VALUE, shelfHeight) assertThat(maxNotifications).isEqualTo(numberOfRows) } Loading @@ -93,11 +100,12 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { fun computeMaxKeyguardNotifications_spaceForOneAndShelf_returnsOne() { setGapHeight(gapHeight) val shelfHeight = rowHeight / 2 // Shelf absence won't leave room for another row. val availableSpace = listOf(rowHeight + dividerHeight, gapHeight + dividerHeight + shelfHeight).sum() val spaceForNotifications = rowHeight + dividerHeight val spaceForShelf = gapHeight + dividerHeight + shelfHeight val rows = listOf(createMockRow(rowHeight), createMockRow(rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight) val maxNotifications = computeMaxKeyguardNotifications(rows, spaceForNotifications, spaceForShelf, shelfHeight) assertThat(maxNotifications).isEqualTo(1) } Loading @@ -106,16 +114,19 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { fun computeMaxKeyguardNotifications_spaceForTwo_returnsTwo() { setGapHeight(gapHeight) val shelfHeight = shelfHeight + dividerHeight val availableSpace = val spaceForNotifications = listOf( rowHeight + dividerHeight, gapHeight + rowHeight + dividerHeight, gapHeight + dividerHeight + shelfHeight) ) .sum() val spaceForShelf = gapHeight + dividerHeight + shelfHeight val rows = listOf(createMockRow(rowHeight), createMockRow(rowHeight), createMockRow(rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight) val maxNotifications = computeMaxKeyguardNotifications( rows, spaceForNotifications + 1, spaceForShelf, shelfHeight) assertThat(maxNotifications).isEqualTo(2) } Loading @@ -124,19 +135,25 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { fun computeHeight_gapBeforeShelf_returnsSpaceUsed() { // Each row in separate section. setGapHeight(gapHeight) val spaceUsed = listOf(rowHeight, val spaceForNotifications = listOf( rowHeight, dividerHeight + gapHeight + rowHeight, dividerHeight + gapHeight + shelfHeight) ) .sum() val availableSpace = spaceUsed + 1; val spaceForShelf = dividerHeight + gapHeight + shelfHeight val spaceUsed = spaceForNotifications + spaceForShelf val rows = listOf(createMockRow(rowHeight), createMockRow(rowHeight), createMockRow(rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight) val maxNotifications = computeMaxKeyguardNotifications(rows, spaceForNotifications, spaceForShelf, shelfHeight) assertThat(maxNotifications).isEqualTo(2) val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight) val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight) assertThat(height).isEqualTo(spaceUsed) } Loading @@ -145,19 +162,19 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { // Both rows are in the same section. setGapHeight(0f) val rowHeight = rowHeight val shelfHeight = shelfHeight val spaceUsed = listOf(rowHeight, dividerHeight + shelfHeight) .sum() val availableSpace = spaceUsed + 1 val spaceForNotifications = rowHeight val spaceForShelf = dividerHeight + shelfHeight val spaceUsed = spaceForNotifications + spaceForShelf val rows = listOf(createMockRow(rowHeight), createMockRow(rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight) // test that we only use space required val maxNotifications = computeMaxKeyguardNotifications( rows, spaceForNotifications + 1, spaceForShelf, shelfHeight) assertThat(maxNotifications).isEqualTo(1) val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight) val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight) assertThat(height).isEqualTo(spaceUsed) } Loading Loading @@ -191,8 +208,13 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { whenever(expandableView.getMinHeight(any())).thenReturn(5) whenever(expandableView.intrinsicHeight).thenReturn(10) val space = sizeCalculator.spaceNeeded(expandableView, visibleIndex = 0, previousView = null, stack = stackLayout, onLockscreen = true) val space = sizeCalculator.spaceNeeded( expandableView, visibleIndex = 0, previousView = null, stack = stackLayout, onLockscreen = true) assertThat(space).isEqualTo(5) } Loading @@ -205,19 +227,25 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { whenever(expandableView.getMinHeight(any())).thenReturn(5) whenever(expandableView.intrinsicHeight).thenReturn(10) val space = sizeCalculator.spaceNeeded(expandableView, visibleIndex = 0, previousView = null, stack = stackLayout, onLockscreen = false) val space = sizeCalculator.spaceNeeded( expandableView, visibleIndex = 0, previousView = null, stack = stackLayout, onLockscreen = false) assertThat(space).isEqualTo(10) } private fun computeMaxKeyguardNotifications( rows: List<ExpandableView>, availableSpace: Float, spaceForNotifications: Float, spaceForShelf: Float, shelfHeight: Float = this.shelfHeight ): Int { setupChildren(rows) return sizeCalculator.computeMaxKeyguardNotifications( stackLayout, availableSpace, shelfHeight) stackLayout, spaceForNotifications, spaceForShelf, shelfHeight) } private fun setupChildren(children: List<ExpandableView>) { Loading packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java +93 −16 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
packages/SystemUI/res/values/dimens.xml +1 −1 Original line number Diff line number Diff line Loading @@ -386,7 +386,7 @@ <dimen name="split_shade_notifications_scrim_margin_bottom">0dp</dimen> <dimen name="shelf_and_lock_icon_overlap">5dp</dimen> <dimen name="shelf_and_lock_icon_overlap">@dimen/notification_shelf_height</dimen> <dimen name="notification_panel_margin_horizontal">0dp</dimen> Loading
packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculator.kt +88 −20 Original line number Diff line number Diff line Loading @@ -39,7 +39,11 @@ private const val TAG = "NotifStackSizeCalc" private val DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.DEBUG) private val SPEW = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE) /** Calculates number of notifications to display and the height of the notification stack. */ /** * Calculates number of notifications to display and the height of the notification stack. * "Notifications" refers to any ExpandableView that we show on lockscreen, which can include the * media player. */ @SysUISingleton class NotificationStackSizeCalculator @Inject Loading @@ -65,21 +69,60 @@ constructor( } /** * Given the [totalAvailableSpace] constraint, calculates how many notification to show. * * This number is only valid in keyguard. * Returns whether notifications and (shelf if visible) can fit in total space available. * [spaceForShelf] is extra vertical space allowed for the shelf to overlap the lock icon. */ private fun canStackFitInSpace( stackHeight: StackHeight, spaceForNotifications: Float, spaceForShelf: Float, ): Boolean { val (notificationsHeight, shelfHeightWithSpaceBefore) = stackHeight var canFit: Boolean if (shelfHeightWithSpaceBefore == 0f) { canFit = notificationsHeight <= spaceForNotifications log { "canStackFitInSpace[$canFit] = notificationsHeight[$notificationsHeight]" + " <= spaceForNotifications[$spaceForNotifications]" } } else { canFit = (notificationsHeight + shelfHeightWithSpaceBefore) <= (spaceForNotifications + spaceForShelf) log { "canStackFitInSpace[$canFit] = (notificationsHeight[$notificationsHeight]" + " + shelfHeightWithSpaceBefore[$shelfHeightWithSpaceBefore])" + " <= (spaceForNotifications[$spaceForNotifications] " + " + spaceForShelf[$spaceForShelf])" } } return canFit } /** * Given the [spaceForNotifications] and [spaceForShelf] constraints, calculate how many * notifications to show. This number is only valid in keyguard. * * @param totalAvailableSpace space for notifications. This includes the space for the shelf. */ fun computeMaxKeyguardNotifications( stack: NotificationStackScrollLayout, totalAvailableSpace: Float, spaceForNotifications: Float, spaceForShelf: Float, shelfIntrinsicHeight: Float ): Int { log { "\n" } val stackHeightSequence = computeHeightPerNotificationLimit(stack, shelfIntrinsicHeight) var maxNotifications = stackHeightSequence.lastIndexWhile { stackHeight -> stackHeight <= totalAvailableSpace } stackHeightSequence.lastIndexWhile { heightResult -> canStackFitInSpace( heightResult, spaceForNotifications = spaceForNotifications, spaceForShelf = spaceForShelf) } if (onLockscreen()) { maxNotifications = min(maxKeyguardNotifications, maxNotifications) Loading @@ -90,7 +133,8 @@ constructor( log { val sequence = if (SPEW) " stackHeightSequence=${stackHeightSequence.toList()}" else "" "computeMaxKeyguardNotifications(" + "availableSpace=$totalAvailableSpace" + " spaceForNotifications=$spaceForNotifications" + " spaceForShelf=$spaceForShelf" + " shelfHeight=$shelfIntrinsicHeight) -> $maxNotifications$sequence" } return maxNotifications Loading @@ -112,33 +156,51 @@ constructor( maxNotifications: Int, shelfIntrinsicHeight: Float ): Float { log { "\n" } val heightPerMaxNotifications = computeHeightPerNotificationLimit(stack, shelfIntrinsicHeight) val height = val (notificationsHeight, shelfHeightWithSpaceBefore) = heightPerMaxNotifications.elementAtOrElse(maxNotifications) { heightPerMaxNotifications.last() // Height with all notifications visible. } log { "computeHeight(maxNotifications=$maxNotifications) -> $height" } return height log { "computeHeight(maxNotifications=$maxNotifications," + "shelfIntrinsicHeight=$shelfIntrinsicHeight) -> " + "${notificationsHeight + shelfHeightWithSpaceBefore}" + " = ($notificationsHeight + $shelfHeightWithSpaceBefore)" } return notificationsHeight + shelfHeightWithSpaceBefore } /** The ith result in the sequence is the height with ith max notifications. */ private data class StackHeight( // Float height with ith max notifications (not including shelf) val notificationsHeight: Float, // Float height of shelf (0 if shelf is not showing), and space before the shelf that // changes during the lockscreen <=> full shade transition. val shelfHeightWithSpaceBefore: Float ) private fun computeHeightPerNotificationLimit( stack: NotificationStackScrollLayout, shelfIntrinsicHeight: Float ): Sequence<Float> = sequence { shelfHeight: Float ): Sequence<StackHeight> = sequence { log { "computeHeightPerNotificationLimit" } val children = stack.showableChildren().toList() var height = 0f var notifications = 0f var previous: ExpandableView? = null val onLockscreen = onLockscreen() yield(dividerHeight + shelfIntrinsicHeight) // Only shelf. // Only shelf. This should never happen, since we allow 1 view minimum (EmptyViewState). yield(StackHeight(notificationsHeight = 0f, shelfHeightWithSpaceBefore = shelfHeight)) children.forEachIndexed { i, currentNotification -> height += spaceNeeded(currentNotification, i, previous, stack, onLockscreen) notifications += spaceNeeded(currentNotification, i, previous, stack, onLockscreen) previous = currentNotification val shelfHeight = val shelfWithSpaceBefore = if (i == children.lastIndex) { 0f // No shelf needed. } else { Loading @@ -149,10 +211,16 @@ constructor( previous = currentNotification, current = children[firstViewInShelfIndex], currentIndex = firstViewInShelfIndex) spaceBeforeShelf + shelfIntrinsicHeight spaceBeforeShelf + shelfHeight } yield(height + shelfHeight) log { "i=$i notificationsHeight=$notifications " + "shelfHeightWithSpaceBefore=$shelfWithSpaceBefore" } yield( StackHeight( notificationsHeight = notifications, shelfHeightWithSpaceBefore = shelfWithSpaceBefore)) } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +59 −36 Original line number Diff line number Diff line Loading @@ -1520,50 +1520,77 @@ public class NotificationPanelViewController extends PanelViewController { return (mQs != null ? mQs.getHeader().getHeight() : 0) + mQsPeekHeight; } /** * @return Space available to show notifications on lockscreen. */ @VisibleForTesting float getSpaceForLockscreenNotifications() { float staticTopPadding = mClockPositionAlgorithm.getLockscreenMinStackScrollerPadding() // getMinStackScrollerPadding is from the top of the screen, // but we need it from the top of the NSSL. - mNotificationStackScrollLayoutController.getTop(); // Space between bottom of notifications and top of lock icon or udfps background. float lockIconPadding = mLockIconViewController.getTop(); if (mLockIconViewController.getTop() != 0) { /** Returns space between top of lock icon and bottom of NotificationStackScrollLayout. */ private float getLockIconPadding() { float lockIconPadding = 0f; if (mLockIconViewController.getTop() != 0f) { lockIconPadding = mNotificationStackScrollLayoutController.getBottom() - mLockIconViewController.getTop() - mShelfAndLockIconOverlap; - mLockIconViewController.getTop(); } return lockIconPadding; } /** Returns space available to show notifications on lockscreen. */ @VisibleForTesting float getVerticalSpaceForLockscreenNotifications() { final float lockIconPadding = getLockIconPadding(); float bottomPadding = Math.max(lockIconPadding, Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding)); mKeyguardNotificationBottomPadding = bottomPadding; float staticTopPadding = mClockPositionAlgorithm.getLockscreenMinStackScrollerPadding() // getMinStackScrollerPadding is from the top of the screen, // but we need it from the top of the NSSL. - mNotificationStackScrollLayoutController.getTop(); mKeyguardNotificationTopPadding = staticTopPadding; // To debug the available space, enable debug lines in this class. If you change how the // available space is calculated, please also update those lines. float availableSpace = final float verticalSpace = mNotificationStackScrollLayoutController.getHeight() - staticTopPadding - bottomPadding; if (SPEW_LOGCAT) { Log.d(TAG, "getSpaceForLockscreenNotifications()" + " availableSpace=" + availableSpace + " NSSL.height=" + mNotificationStackScrollLayoutController.getHeight() + " NSSL.top=" + mNotificationStackScrollLayoutController.getTop() + " staticTopPadding=" + staticTopPadding + " bottomPadding=" + bottomPadding + " lockIconPadding=" + lockIconPadding + " mIndicationBottomPadding=" + mIndicationBottomPadding + " mAmbientIndicationBottomPadding=" + mAmbientIndicationBottomPadding Log.i(TAG, "\n"); Log.i(TAG, "staticTopPadding[" + staticTopPadding + "] = Clock.padding[" + mClockPositionAlgorithm.getLockscreenMinStackScrollerPadding() + "] - NSSLC.top[" + mNotificationStackScrollLayoutController.getTop() + "]" ); Log.i(TAG, "bottomPadding[" + bottomPadding + "] = max(ambientIndicationBottomPadding[" + mAmbientIndicationBottomPadding + "], mIndicationBottomPadding[" + mIndicationBottomPadding + "], lockIconPadding[" + lockIconPadding + "])" ); Log.i(TAG, "verticalSpaceForNotifications[" + verticalSpace + "] = NSSL.height[" + mNotificationStackScrollLayoutController.getHeight() + "] - staticTopPadding[" + staticTopPadding + "] - bottomPadding[" + bottomPadding + "]" ); } return availableSpace; return verticalSpace; } /** Returns extra space available to show the shelf on lockscreen */ @VisibleForTesting float getVerticalSpaceForLockscreenShelf() { final float lockIconPadding = getLockIconPadding(); final float noShelfOverlapBottomPadding = Math.max(mIndicationBottomPadding, mAmbientIndicationBottomPadding); final float extraSpaceForShelf = lockIconPadding - noShelfOverlapBottomPadding; if (extraSpaceForShelf > 0f) { return Math.min(mNotificationShelfController.getIntrinsicHeight(), extraSpaceForShelf); } return 0f; } /** Loading @@ -1579,16 +1606,12 @@ public class NotificationPanelViewController extends PanelViewController { } return mMaxAllowedKeyguardNotifications; } final float shelfIntrinsicHeight = mNotificationShelfController.getVisibility() == View.GONE ? 0 : mNotificationShelfController.getIntrinsicHeight(); return mNotificationStackSizeCalculator.computeMaxKeyguardNotifications( mNotificationStackScrollLayoutController.getView(), getSpaceForLockscreenNotifications(), shelfIntrinsicHeight); getVerticalSpaceForLockscreenNotifications(), getVerticalSpaceForLockscreenShelf(), mNotificationShelfController.getIntrinsicHeight() ); } private void updateClock() { Loading Loading @@ -3812,7 +3835,7 @@ public class NotificationPanelViewController extends PanelViewController { public void setAmbientIndicationTop(int ambientIndicationTop, boolean ambientTextVisible) { int ambientIndicationBottomPadding = 0; if (ambientTextVisible) { int stackBottom = mNotificationStackScrollLayoutController.getView().getBottom(); int stackBottom = mNotificationStackScrollLayoutController.getBottom(); ambientIndicationBottomPadding = stackBottom - ambientIndicationTop; } if (mAmbientIndicationBottomPadding != ambientIndicationBottomPadding) { Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackSizeCalculatorTest.kt +58 −30 Original line number Diff line number Diff line Loading @@ -46,7 +46,8 @@ import org.mockito.MockitoAnnotations class NotificationStackSizeCalculatorTest : SysuiTestCase() { @Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController @Mock private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController @Mock private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController @Mock private lateinit var stackLayout: NotificationStackScrollLayout private val testableResources = mContext.orCreateTestableResources Loading Loading @@ -74,7 +75,8 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { val rows = listOf(createMockRow(height = rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace = 0f, shelfHeight = 0f) computeMaxKeyguardNotifications( rows, spaceForNotifications = 0f, spaceForShelf = 0f, shelfHeight = 0f) assertThat(maxNotifications).isEqualTo(0) } Loading @@ -84,7 +86,12 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { val numberOfRows = 30 val rows = createLockscreenRows(numberOfRows) val maxNotifications = computeMaxKeyguardNotifications(rows, Float.MAX_VALUE) val maxNotifications = computeMaxKeyguardNotifications( rows, spaceForNotifications = Float.MAX_VALUE, spaceForShelf = Float.MAX_VALUE, shelfHeight) assertThat(maxNotifications).isEqualTo(numberOfRows) } Loading @@ -93,11 +100,12 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { fun computeMaxKeyguardNotifications_spaceForOneAndShelf_returnsOne() { setGapHeight(gapHeight) val shelfHeight = rowHeight / 2 // Shelf absence won't leave room for another row. val availableSpace = listOf(rowHeight + dividerHeight, gapHeight + dividerHeight + shelfHeight).sum() val spaceForNotifications = rowHeight + dividerHeight val spaceForShelf = gapHeight + dividerHeight + shelfHeight val rows = listOf(createMockRow(rowHeight), createMockRow(rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight) val maxNotifications = computeMaxKeyguardNotifications(rows, spaceForNotifications, spaceForShelf, shelfHeight) assertThat(maxNotifications).isEqualTo(1) } Loading @@ -106,16 +114,19 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { fun computeMaxKeyguardNotifications_spaceForTwo_returnsTwo() { setGapHeight(gapHeight) val shelfHeight = shelfHeight + dividerHeight val availableSpace = val spaceForNotifications = listOf( rowHeight + dividerHeight, gapHeight + rowHeight + dividerHeight, gapHeight + dividerHeight + shelfHeight) ) .sum() val spaceForShelf = gapHeight + dividerHeight + shelfHeight val rows = listOf(createMockRow(rowHeight), createMockRow(rowHeight), createMockRow(rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight) val maxNotifications = computeMaxKeyguardNotifications( rows, spaceForNotifications + 1, spaceForShelf, shelfHeight) assertThat(maxNotifications).isEqualTo(2) } Loading @@ -124,19 +135,25 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { fun computeHeight_gapBeforeShelf_returnsSpaceUsed() { // Each row in separate section. setGapHeight(gapHeight) val spaceUsed = listOf(rowHeight, val spaceForNotifications = listOf( rowHeight, dividerHeight + gapHeight + rowHeight, dividerHeight + gapHeight + shelfHeight) ) .sum() val availableSpace = spaceUsed + 1; val spaceForShelf = dividerHeight + gapHeight + shelfHeight val spaceUsed = spaceForNotifications + spaceForShelf val rows = listOf(createMockRow(rowHeight), createMockRow(rowHeight), createMockRow(rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight) val maxNotifications = computeMaxKeyguardNotifications(rows, spaceForNotifications, spaceForShelf, shelfHeight) assertThat(maxNotifications).isEqualTo(2) val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight) val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight) assertThat(height).isEqualTo(spaceUsed) } Loading @@ -145,19 +162,19 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { // Both rows are in the same section. setGapHeight(0f) val rowHeight = rowHeight val shelfHeight = shelfHeight val spaceUsed = listOf(rowHeight, dividerHeight + shelfHeight) .sum() val availableSpace = spaceUsed + 1 val spaceForNotifications = rowHeight val spaceForShelf = dividerHeight + shelfHeight val spaceUsed = spaceForNotifications + spaceForShelf val rows = listOf(createMockRow(rowHeight), createMockRow(rowHeight)) val maxNotifications = computeMaxKeyguardNotifications(rows, availableSpace, shelfHeight) // test that we only use space required val maxNotifications = computeMaxKeyguardNotifications( rows, spaceForNotifications + 1, spaceForShelf, shelfHeight) assertThat(maxNotifications).isEqualTo(1) val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight) val height = sizeCalculator.computeHeight(stackLayout, maxNotifications, this.shelfHeight) assertThat(height).isEqualTo(spaceUsed) } Loading Loading @@ -191,8 +208,13 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { whenever(expandableView.getMinHeight(any())).thenReturn(5) whenever(expandableView.intrinsicHeight).thenReturn(10) val space = sizeCalculator.spaceNeeded(expandableView, visibleIndex = 0, previousView = null, stack = stackLayout, onLockscreen = true) val space = sizeCalculator.spaceNeeded( expandableView, visibleIndex = 0, previousView = null, stack = stackLayout, onLockscreen = true) assertThat(space).isEqualTo(5) } Loading @@ -205,19 +227,25 @@ class NotificationStackSizeCalculatorTest : SysuiTestCase() { whenever(expandableView.getMinHeight(any())).thenReturn(5) whenever(expandableView.intrinsicHeight).thenReturn(10) val space = sizeCalculator.spaceNeeded(expandableView, visibleIndex = 0, previousView = null, stack = stackLayout, onLockscreen = false) val space = sizeCalculator.spaceNeeded( expandableView, visibleIndex = 0, previousView = null, stack = stackLayout, onLockscreen = false) assertThat(space).isEqualTo(10) } private fun computeMaxKeyguardNotifications( rows: List<ExpandableView>, availableSpace: Float, spaceForNotifications: Float, spaceForShelf: Float, shelfHeight: Float = this.shelfHeight ): Int { setupChildren(rows) return sizeCalculator.computeMaxKeyguardNotifications( stackLayout, availableSpace, shelfHeight) stackLayout, spaceForNotifications, spaceForShelf, shelfHeight) } private fun setupChildren(children: List<ExpandableView>) { Loading
packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java +93 −16 File changed.Preview size limit exceeded, changes collapsed. Show changes