summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sherry Zhou <yuandizhou@google.com> 2024-10-18 23:25:39 +0000
committer Sherry Zhou <yuandizhou@google.com> 2024-10-24 01:10:10 +0000
commit12dcc650a078dfc9ca782da988dda712afcaff21 (patch)
tree78de1d28946994708ece55c42e402a689b9fce5e
parentd7e892095d61d765ed98389e27d795f9de33377d (diff)
Fix notification bottom sent from SysUI is inaccurate and refactor
Bug: 374382849 Test: atest SharedNotificationContainerViewModelTest Flag: com.android.systemui.magic_portrait_wallpapers Change-Id: I97ca05d891cd0bc00a16778657306d5fd8912e23
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt69
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt15
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt51
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt30
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt2
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractor.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt8
11 files changed, 169 insertions, 36 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
index 25670cb0bb0c..3827dfa533cb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt
@@ -1229,6 +1229,75 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S
assertThat(alpha).isEqualTo(1f)
}
+ @Test
+ @DisableSceneContainer
+ fun notificationAbsoluteBottom() =
+ testScope.runTest {
+ var notificationCount = 2
+ val calculateSpace = { _: Float, _: Boolean -> notificationCount }
+ val shelfHeight = 10F
+ val heightForNotification = 20F
+ val calculateHeight = { count: Int -> count * heightForNotification + shelfHeight }
+ val stackAbsoluteBottom by
+ collectLastValue(
+ underTest.getNotificationStackAbsoluteBottom(
+ calculateSpace,
+ calculateHeight,
+ shelfHeight,
+ )
+ )
+ advanceTimeBy(50L)
+ showLockscreen()
+
+ shadeTestUtil.setSplitShade(false)
+ keyguardInteractor.setNotificationContainerBounds(
+ NotificationContainerBounds(top = 100F, bottom = 300F)
+ )
+ configurationRepository.onAnyConfigurationChange()
+
+ assertThat(stackAbsoluteBottom).isEqualTo(150F)
+
+ // Also updates when directly requested (as it would from NotificationStackScrollLayout)
+ notificationCount = 3
+ sharedNotificationContainerInteractor.notificationStackChanged()
+ advanceTimeBy(50L)
+ assertThat(stackAbsoluteBottom).isEqualTo(170F)
+ }
+
+ @Test
+ @DisableSceneContainer
+ fun notificationAbsoluteBottom_maxNotificationIsZero_noShelfHeight() =
+ testScope.runTest {
+ var notificationCount = 2
+ val calculateSpace = { _: Float, _: Boolean -> notificationCount }
+ val shelfHeight = 10F
+ val heightForNotification = 20F
+ val calculateHeight = { count: Int -> count * heightForNotification + shelfHeight }
+ val stackAbsoluteBottom by
+ collectLastValue(
+ underTest.getNotificationStackAbsoluteBottom(
+ calculateSpace,
+ calculateHeight,
+ shelfHeight,
+ )
+ )
+ advanceTimeBy(50L)
+ showLockscreen()
+
+ shadeTestUtil.setSplitShade(false)
+ keyguardInteractor.setNotificationContainerBounds(
+ NotificationContainerBounds(top = 100F, bottom = 300F)
+ )
+ configurationRepository.onAnyConfigurationChange()
+
+ assertThat(stackAbsoluteBottom).isEqualTo(150F)
+
+ notificationCount = 0
+ sharedNotificationContainerInteractor.notificationStackChanged()
+ advanceTimeBy(50L)
+ assertThat(stackAbsoluteBottom).isEqualTo(100F)
+ }
+
private suspend fun TestScope.showLockscreen() {
shadeTestUtil.setQsExpansion(0f)
shadeTestUtil.setLockscreenShadeExpansion(0f)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt
index 59676ce126da..111c232280c3 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/wallpapers/data/repository/FakeWallpaperRepository.kt
@@ -25,9 +25,4 @@ class FakeWallpaperRepository : WallpaperRepository {
override val wallpaperInfo = MutableStateFlow<WallpaperInfo?>(null)
override val wallpaperSupportsAmbientMode = MutableStateFlow(false)
override var rootView: View? = null
- private val _notificationStackAbsoluteBottom = MutableStateFlow(0F)
-
- override fun setNotificationStackAbsoluteBottom(bottom: Float) {
- _notificationStackAbsoluteBottom.value = bottom
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 9e99a879be41..a6be5bc4ada0 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -269,6 +269,8 @@ interface KeyguardRepository {
/** The top of shortcut in screen, used by wallpaper to find remaining space in lockscreen */
val shortcutAbsoluteTop: StateFlow<Float>
+ val notificationStackAbsoluteBottom: StateFlow<Float>
+
/**
* Returns `true` if the keyguard is showing; `false` otherwise.
*
@@ -339,6 +341,12 @@ interface KeyguardRepository {
fun isShowKeyguardWhenReenabled(): Boolean
fun setShortcutAbsoluteTop(top: Float)
+
+ /**
+ * Set bottom of notifications from notification stack, and Magic Portrait will layout base on
+ * this value
+ */
+ fun setNotificationStackAbsoluteBottom(bottom: Float)
}
/** Encapsulates application state for the keyguard. */
@@ -635,6 +643,9 @@ constructor(
private val _shortcutAbsoluteTop = MutableStateFlow(0F)
override val shortcutAbsoluteTop = _shortcutAbsoluteTop.asStateFlow()
+ private val _notificationStackAbsoluteBottom = MutableStateFlow(0F)
+ override val notificationStackAbsoluteBottom = _notificationStackAbsoluteBottom.asStateFlow()
+
init {
val callback =
object : KeyguardStateController.Callback {
@@ -717,6 +728,10 @@ constructor(
_shortcutAbsoluteTop.value = top
}
+ override fun setNotificationStackAbsoluteBottom(bottom: Float) {
+ _notificationStackAbsoluteBottom.value = bottom
+ }
+
private fun dozeMachineStateToModel(state: DozeMachine.State): DozeStateModel {
return when (state) {
DozeMachine.State.UNINITIALIZED -> DozeStateModel.UNINITIALIZED
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 29c6d5aa5ea2..b24ca1a8d345 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -545,6 +545,10 @@ constructor(
repository.isKeyguardGoingAway.value = isGoingAway
}
+ fun setNotificationStackAbsoluteBottom(bottom: Float) {
+ repository.setNotificationStackAbsoluteBottom(bottom)
+ }
+
companion object {
private const val TAG = "KeyguardInteractor"
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 87b16efc64fc..1d4916c6cd82 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1200,7 +1200,6 @@ public class NotificationStackScrollLayout
if (!SceneContainerFlag.isEnabled()) {
setMaxLayoutHeight(getHeight());
updateContentHeight();
- mWallpaperInteractor.setNotificationStackAbsoluteBottom(mContentHeight);
}
clampScrollPosition();
requestChildrenUpdate();
@@ -1278,7 +1277,6 @@ public class NotificationStackScrollLayout
if (mAmbientState.getStackTop() != stackTop) {
mAmbientState.setStackTop(stackTop);
onTopPaddingChanged(/* animate = */ isAddOrRemoveAnimationPending());
- mWallpaperInteractor.setNotificationStackAbsoluteBottom((int) stackTop);
}
}
@@ -2648,6 +2646,7 @@ public class NotificationStackScrollLayout
// The topPadding can be bigger than the regular padding when qs is expanded, in that
// state the maxPanelHeight and the contentHeight should be bigger
+
mContentHeight =
(int) (height + Math.max(getIntrinsicPadding(), getTopPadding()) + mBottomPadding);
updateScrollability();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
index b22143f03b44..6f17455241ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
@@ -18,10 +18,12 @@ package com.android.systemui.statusbar.notification.stack.ui.viewbinder
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
+import com.android.systemui.Flags
import com.android.systemui.common.ui.view.onLayoutChanged
import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.scene.shared.flag.SceneContainerFlag
@@ -48,8 +50,19 @@ constructor(
private val notificationScrollViewBinder: NotificationScrollViewBinder,
private val communalSettingsInteractor: CommunalSettingsInteractor,
@Main private val mainImmediateDispatcher: CoroutineDispatcher,
+ val keyguardInteractor: KeyguardInteractor,
) {
+ private val calculateMaxNotifications: (Float, Boolean) -> Int = { space, extraShelfSpace ->
+ val shelfHeight = controller.getShelfHeight().toFloat()
+ notificationStackSizeCalculator.computeMaxKeyguardNotifications(
+ controller.view,
+ space,
+ if (extraShelfSpace) shelfHeight else 0f,
+ shelfHeight,
+ )
+ }
+
fun bind(
view: SharedNotificationContainer,
viewModel: SharedNotificationContainerViewModel,
@@ -107,17 +120,9 @@ constructor(
}
launch {
- viewModel
- .getMaxNotifications { space, extraShelfSpace ->
- val shelfHeight = controller.getShelfHeight().toFloat()
- notificationStackSizeCalculator.computeMaxKeyguardNotifications(
- controller.getView(),
- space,
- if (extraShelfSpace) shelfHeight else 0f,
- shelfHeight,
- )
- }
- .collect { controller.setMaxDisplayedNotifications(it) }
+ viewModel.getMaxNotifications(calculateMaxNotifications).collect {
+ controller.setMaxDisplayedNotifications(it)
+ }
}
if (!SceneContainerFlag.isEnabled) {
@@ -136,6 +141,30 @@ constructor(
}
}
+ if (!SceneContainerFlag.isEnabled) {
+ if (Flags.magicPortraitWallpapers()) {
+ launch {
+ viewModel
+ .getNotificationStackAbsoluteBottom(
+ calculateMaxNotifications = calculateMaxNotifications,
+ calculateHeight = { maxNotifications ->
+ notificationStackSizeCalculator.computeHeight(
+ maxNotifs = maxNotifications,
+ shelfHeight = controller.getShelfHeight().toFloat(),
+ stack = controller.view,
+ )
+ },
+ controller.getShelfHeight().toFloat(),
+ )
+ .collect { bottom ->
+ keyguardInteractor.setNotificationStackAbsoluteBottom(
+ bottom
+ )
+ }
+ }
+ }
+ }
+
launch { viewModel.translationX.collect { x -> controller.translationX = x } }
launch {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
index 9515029962ea..99e5fdad85bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt
@@ -672,6 +672,36 @@ constructor(
.dumpWhileCollecting("maxNotifications")
}
+ /**
+ * Wallpaper needs the absolute bottom of notification stack to avoid occlusion
+ *
+ * @param calculateMaxNotifications is required by getMaxNotifications as calculateSpace by
+ * calling computeMaxKeyguardNotifications in NotificationStackSizeCalculator
+ * @param calculateHeight is calling computeHeight in NotificationStackSizeCalculator The edge
+ * case is that when maxNotifications is 0, we won't take shelfHeight into account
+ */
+ fun getNotificationStackAbsoluteBottom(
+ calculateMaxNotifications: (Float, Boolean) -> Int,
+ calculateHeight: (Int) -> Float,
+ shelfHeight: Float,
+ ): Flow<Float> {
+ SceneContainerFlag.assertInLegacyMode()
+
+ return combine(
+ getMaxNotifications(calculateMaxNotifications).map {
+ val height = calculateHeight(it)
+ if (it == 0) {
+ height - shelfHeight
+ } else {
+ height
+ }
+ },
+ bounds.map { it.top },
+ ) { height, top ->
+ top + height
+ }
+ }
+
fun notificationStackChanged() {
interactor.notificationStackChanged()
}
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt
index 54953c9c2574..9055d18a9f55 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/NoopWallpaperRepository.kt
@@ -35,6 +35,4 @@ class NoopWallpaperRepository @Inject constructor() : WallpaperRepository {
override val wallpaperInfo: StateFlow<WallpaperInfo?> = MutableStateFlow(null).asStateFlow()
override val wallpaperSupportsAmbientMode = MutableStateFlow(false).asStateFlow()
override var rootView: View? = null
-
- override fun setNotificationStackAbsoluteBottom(bottom: Float) {}
}
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
index efdd98d5498a..4373a10f7a7d 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/data/repository/WallpaperRepository.kt
@@ -45,7 +45,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
-import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
@@ -64,12 +63,6 @@ interface WallpaperRepository {
/** Set rootView to get its windowToken afterwards */
var rootView: View?
-
- /**
- * Set bottom of notifications from notification stack, and Magic Portrait will layout base on
- * this value
- */
- fun setNotificationStackAbsoluteBottom(bottom: Float)
}
@SysUISingleton
@@ -106,7 +99,8 @@ constructor(
.filter { it.selectionStatus == SelectionStatus.SELECTION_COMPLETE }
/** The bottom of notification stack respect to the top of screen. */
- private val notificationStackAbsoluteBottom: MutableStateFlow<Float> = MutableStateFlow(0F)
+ private val notificationStackAbsoluteBottom: StateFlow<Float> =
+ keyguardRepository.notificationStackAbsoluteBottom
/** The top of shortcut respect to the top of screen. */
private val shortcutAbsoluteTop: StateFlow<Float> = keyguardRepository.shortcutAbsoluteTop
@@ -206,10 +200,6 @@ constructor(
initialValue = false,
)
- override fun setNotificationStackAbsoluteBottom(bottom: Float) {
- notificationStackAbsoluteBottom.value = bottom
- }
-
private suspend fun getWallpaper(selectedUser: SelectedUserModel): WallpaperInfo? {
return withContext(bgDispatcher) {
wallpaperManager.getWallpaperInfoForUser(selectedUser.userInfo.id)
diff --git a/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractor.kt b/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractor.kt
index fe6977c367b5..88795cada716 100644
--- a/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/wallpapers/domain/interactor/WallpaperInteractor.kt
@@ -21,10 +21,6 @@ import javax.inject.Inject
import kotlinx.coroutines.flow.StateFlow
class WallpaperInteractor @Inject constructor(val wallpaperRepository: WallpaperRepository) {
- fun setNotificationStackAbsoluteBottom(bottom: Float) {
- wallpaperRepository.setNotificationStackAbsoluteBottom(bottom)
- }
-
val wallpaperSupportsAmbientMode: StateFlow<Boolean> =
wallpaperRepository.wallpaperSupportsAmbientMode
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 08786495eca4..693ec7954d70 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -131,6 +131,10 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
override val shortcutAbsoluteTop: StateFlow<Float>
get() = _shortcutAbsoluteTop.asStateFlow()
+ private val _notificationStackAbsoluteBottom = MutableStateFlow(0F)
+ override val notificationStackAbsoluteBottom: StateFlow<Float>
+ get() = _notificationStackAbsoluteBottom.asStateFlow()
+
private val _isKeyguardEnabled = MutableStateFlow(true)
override val isKeyguardEnabled: StateFlow<Boolean> = _isKeyguardEnabled.asStateFlow()
@@ -294,6 +298,10 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
_shortcutAbsoluteTop.value = top
}
+ override fun setNotificationStackAbsoluteBottom(bottom: Float) {
+ _notificationStackAbsoluteBottom.value = bottom
+ }
+
override fun setCanIgnoreAuthAndReturnToGone(canWake: Boolean) {
_canIgnoreAuthAndReturnToGone.value = canWake
}