summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt12
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/communal/util/ResizeUtilsTest.kt222
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt1107
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt5
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt9
-rw-r--r--packages/SystemUI/src/com/android/systemui/communal/util/ResizeUtils.kt71
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt23
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java5
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java40
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorKosmos.kt2
11 files changed, 992 insertions, 509 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
index 573e5ca5e2d5..6a9dfbd29092 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/communal/ui/compose/CommunalHub.kt
@@ -187,6 +187,7 @@ import com.android.systemui.communal.ui.viewmodel.CommunalViewModel
import com.android.systemui.communal.ui.viewmodel.ResizeInfo
import com.android.systemui.communal.ui.viewmodel.ResizeableItemFrameViewModel
import com.android.systemui.communal.util.DensityUtils.Companion.adjustedDp
+import com.android.systemui.communal.util.ResizeUtils.resizeOngoingItems
import com.android.systemui.communal.widgets.SmartspaceAppWidgetHostView
import com.android.systemui.communal.widgets.WidgetConfigurator
import com.android.systemui.lifecycle.rememberViewModel
@@ -834,8 +835,16 @@ private fun BoxScope.CommunalHubLazyGrid(
gridState = gridState,
contentPadding = contentPadding,
) { sizeInfo ->
+ /** Override spans based on the responsive grid size */
+ val finalizedList =
+ if (sizeInfo != null) {
+ resizeOngoingItems(list, sizeInfo.gridSize.height)
+ } else {
+ list
+ }
+
itemsIndexed(
- items = list,
+ items = finalizedList,
key = { _, item -> item.key },
contentType = { _, item -> item.key },
span = { _, item -> GridItemSpan(item.getSpanOrMax(sizeInfo?.gridSize?.height)) },
@@ -1193,6 +1202,7 @@ private fun CommunalContent(
is CommunalContentModel.Smartspace -> SmartspaceContent(interactionHandler, model, modifier)
is CommunalContentModel.Tutorial -> TutorialContent(modifier)
is CommunalContentModel.Umo -> Umo(viewModel, sceneScope, modifier)
+ is CommunalContentModel.Spacer -> Box(Modifier.fillMaxSize())
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/util/ResizeUtilsTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/util/ResizeUtilsTest.kt
new file mode 100644
index 000000000000..b0f48038877e
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/util/ResizeUtilsTest.kt
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.util
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.communal.domain.model.CommunalContentModel
+import com.android.systemui.communal.shared.model.CommunalContentSize
+import com.android.systemui.communal.util.ResizeUtils.resizeOngoingItems
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ResizeUtilsTest : SysuiTestCase() {
+ private val mockWidget =
+ mock<CommunalContentModel.WidgetContent.Widget> {
+ on { size } doReturn CommunalContentSize.Responsive(1)
+ }
+
+ @Test
+ fun noOngoingContent() {
+ val list = listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 2)
+
+ assertThat(resized).containsExactly(mockWidget)
+ }
+
+ @Test
+ fun singleOngoingContent_singleRowGrid() {
+ val list = createOngoingListWithSize(1) + listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 1)
+
+ assertThat(resized.map { it.size })
+ .containsExactly(CommunalContentSize.Responsive(1), mockWidget.size)
+ .inOrder()
+ }
+
+ @Test
+ fun singleOngoingContent_twoRowGrid() {
+ val list = createOngoingListWithSize(1) + listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 2)
+
+ assertThat(resized.map { it.size })
+ .containsExactly(CommunalContentSize.Responsive(2), mockWidget.size)
+ .inOrder()
+ }
+
+ @Test
+ fun singleOngoingContent_threeRowGrid() {
+ val list = createOngoingListWithSize(1) + listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 3)
+
+ assertThat(resized.map { it.size })
+ .containsExactly(
+ CommunalContentSize.Responsive(2),
+ CommunalContentSize.Responsive(1),
+ mockWidget.size,
+ )
+ .inOrder()
+ // A spacer should be added as the second element to avoid mixing widget content
+ // with ongoing content.
+ assertThat(resized[1]).isInstanceOf(CommunalContentModel.Spacer::class.java)
+ }
+
+ @Test
+ fun twoOngoingContent_singleRowGrid() {
+ val list = createOngoingListWithSize(2) + listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 1)
+
+ assertThat(resized.map { it.size })
+ .containsExactly(
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ mockWidget.size,
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun twoOngoingContent_twoRowGrid() {
+ val list = createOngoingListWithSize(2) + listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 2)
+
+ assertThat(resized.map { it.size })
+ .containsExactly(
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ mockWidget.size,
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun twoOngoingContent_threeRowGrid() {
+ val list = createOngoingListWithSize(2) + listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 3)
+
+ assertThat(resized.map { it.size })
+ .containsExactly(
+ CommunalContentSize.Responsive(2),
+ CommunalContentSize.Responsive(1),
+ mockWidget.size,
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun threeOngoingContent_singleRowGrid() {
+ val list = createOngoingListWithSize(3) + listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 1)
+
+ assertThat(resized.map { it.size })
+ .containsExactly(
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ mockWidget.size,
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun threeOngoingContent_twoRowGrid() {
+ val list = createOngoingListWithSize(3) + listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 2)
+
+ assertThat(resized.map { it.size })
+ .containsExactly(
+ CommunalContentSize.Responsive(2),
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ mockWidget.size,
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun threeOngoingContent_threeRowGrid() {
+ val list = createOngoingListWithSize(3) + listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 3)
+
+ assertThat(resized.map { it.size })
+ .containsExactly(
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ mockWidget.size,
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun fourOngoingContent_singleRowGrid() {
+ val list = createOngoingListWithSize(4) + listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 1)
+
+ assertThat(resized.map { it.size })
+ .containsExactly(
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ mockWidget.size,
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun fourOngoingContent_twoRowGrid() {
+ val list = createOngoingListWithSize(4) + listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 2)
+
+ assertThat(resized.map { it.size })
+ .containsExactly(
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(1),
+ mockWidget.size,
+ )
+ .inOrder()
+ }
+
+ @Test
+ fun fourOngoingContent_threeRowGrid() {
+ val list = createOngoingListWithSize(4) + listOf(mockWidget)
+ val resized = resizeOngoingItems(list = list, numRows = 3)
+
+ assertThat(resized.map { it.size })
+ .containsExactly(
+ CommunalContentSize.Responsive(2),
+ CommunalContentSize.Responsive(1),
+ CommunalContentSize.Responsive(2),
+ CommunalContentSize.Responsive(1),
+ mockWidget.size,
+ )
+ .inOrder()
+ }
+
+ private fun createOngoingListWithSize(size: Int): List<CommunalContentModel.Ongoing> {
+ return List(size) { CommunalContentModel.Umo(createdTimestampMillis = 100) }
+ }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
index 68798a88eecc..9e7befd3cf92 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorTest.kt
@@ -27,15 +27,28 @@ import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import android.service.notification.StatusBarNotification
import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.compose.animation.scene.SceneKey
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.keyguardUpdateMonitor
import com.android.server.notification.Flags.FLAG_SCREENSHARE_NOTIFICATION_HIDING
import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
+import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
+import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.andSceneContainer
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
+import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.statusbar.fakeStatusBarStateController
import com.android.systemui.plugins.statusbar.statusBarStateController
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
+import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.NotificationLockscreenUserManager
import com.android.systemui.statusbar.RankingBuilder
import com.android.systemui.statusbar.StatusBarState
@@ -60,11 +73,16 @@ import com.android.systemui.statusbar.policy.sensitiveNotificationProtectionCont
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.withArgCaptor
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.kotlin.any
+import org.mockito.kotlin.clearInvocations
import org.mockito.kotlin.eq
import org.mockito.kotlin.mock
import org.mockito.kotlin.never
@@ -86,6 +104,8 @@ class SensitiveContentCoordinatorTest(flags: FlagsParameterization) : SysuiTestC
statusBarStateController = fakeStatusBarStateController
}
+ val testScope = kosmos.testScope
+
val dynamicPrivacyController: DynamicPrivacyController = kosmos.mockDynamicPrivacyController
val lockscreenUserManager: NotificationLockscreenUserManager =
kosmos.notificationLockscreenUserManager
@@ -95,7 +115,12 @@ class SensitiveContentCoordinatorTest(flags: FlagsParameterization) : SysuiTestC
kosmos.fakeStatusBarStateController
val sensitiveNotificationProtectionController: SensitiveNotificationProtectionController =
kosmos.mockSensitiveNotificationProtectionController
- val sceneInteractor: SceneInteractor = kosmos.sceneInteractor
+ val deviceEntryInteractor: DeviceEntryInteractor
+ get() = kosmos.deviceEntryInteractor
+
+ val faceAuthRepository = kosmos.fakeDeviceEntryFaceAuthRepository
+ val sceneInteractor: SceneInteractor
+ get() = kosmos.sceneInteractor
val coordinator: SensitiveContentCoordinator by lazy { kosmos.sensitiveContentCoordinator }
@@ -112,592 +137,696 @@ class SensitiveContentCoordinatorTest(flags: FlagsParameterization) : SysuiTestC
}
@Test
- fun onDynamicPrivacyChanged_invokeInvalidationListener() {
- coordinator.attach(pipeline)
- val invalidator =
- withArgCaptor<Invalidator> { verify(pipeline).addPreRenderInvalidator(capture()) }
- val dynamicPrivacyListener =
- withArgCaptor<DynamicPrivacyController.Listener> {
- verify(dynamicPrivacyController).addListener(capture())
- }
-
- val invalidationListener = mock<Pluggable.PluggableListener<Invalidator>>()
- invalidator.setInvalidationListener(invalidationListener)
-
- dynamicPrivacyListener.onDynamicPrivacyChanged()
+ @EnableSceneContainer
+ fun onLockscreenDynamicallyUnlocked_invokeInvalidationListener() =
+ testScope.runTest {
+ // Setup
+ coordinator.attach(pipeline)
+ val invalidator =
+ withArgCaptor<Invalidator> { verify(pipeline).addPreRenderInvalidator(capture()) }
+ val invalidationListener = mock<Pluggable.PluggableListener<Invalidator>>()
+ invalidator.setInvalidationListener(invalidationListener)
+
+ // Given the lockscreen is shown
+ setupLockScreen(canSwipeUp = false)
+ clearInvocations(invalidationListener)
+
+ // When the device gets unlocked
+ faceAuthRepository.isAuthenticated.value = true
+ runCurrent()
+
+ // Then the invalidationListener is called
+ verify(invalidationListener).onPluggableInvalidated(eq(invalidator), any())
+ }
- verify(invalidationListener).onPluggableInvalidated(eq(invalidator), any())
- }
+ @Test
+ @DisableSceneContainer
+ fun onDynamicPrivacyChanged_invokeInvalidationListener() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val invalidator =
+ withArgCaptor<Invalidator> { verify(pipeline).addPreRenderInvalidator(capture()) }
+ val dynamicPrivacyListener =
+ withArgCaptor<DynamicPrivacyController.Listener> {
+ verify(dynamicPrivacyController).addListener(capture())
+ }
+
+ val invalidationListener = mock<Pluggable.PluggableListener<Invalidator>>()
+ invalidator.setInvalidationListener(invalidationListener)
+
+ dynamicPrivacyListener.onDynamicPrivacyChanged()
+
+ verify(invalidationListener).onPluggableInvalidated(eq(invalidator), any())
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun onSensitiveStateChanged_invokeInvalidationListener() {
- coordinator.attach(pipeline)
- val invalidator =
- withArgCaptor<Invalidator> { verify(pipeline).addPreRenderInvalidator(capture()) }
- val onSensitiveStateChangedListener =
- withArgCaptor<Runnable> {
- verify(sensitiveNotificationProtectionController)
- .registerSensitiveStateListener(capture())
- }
-
- val invalidationListener = mock<Pluggable.PluggableListener<Invalidator>>()
- invalidator.setInvalidationListener(invalidationListener)
-
- onSensitiveStateChangedListener.run()
-
- verify(invalidationListener).onPluggableInvalidated(eq(invalidator), any())
- }
+ fun onSensitiveStateChanged_invokeInvalidationListener() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val invalidator =
+ withArgCaptor<Invalidator> { verify(pipeline).addPreRenderInvalidator(capture()) }
+ val onSensitiveStateChangedListener =
+ withArgCaptor<Runnable> {
+ verify(sensitiveNotificationProtectionController)
+ .registerSensitiveStateListener(capture())
+ }
+
+ val invalidationListener = mock<Pluggable.PluggableListener<Invalidator>>()
+ invalidator.setInvalidationListener(invalidationListener)
+
+ onSensitiveStateChangedListener.run()
+
+ verify(invalidationListener).onPluggableInvalidated(eq(invalidator), any())
+ }
@Test
@DisableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun screenshareSecretFilter_flagDisabled_filterNoAdded() {
- coordinator.attach(pipeline)
+ fun screenshareSecretFilter_flagDisabled_filterNoAdded() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
- verify(pipeline, never()).addFinalizeFilter(any())
- }
+ verify(pipeline, never()).addFinalizeFilter(any())
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun screenshareSecretFilter_sensitiveInctive_noFiltersSecret() {
- whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(false)
-
- coordinator.attach(pipeline)
- val filter = withArgCaptor<NotifFilter> { verify(pipeline).addFinalizeFilter(capture()) }
-
- val defaultNotification = createNotificationEntry("test", false, false)
- val notificationWithSecretVisibility = createNotificationEntry("test", true, false)
- val notificationOnSecretChannel = createNotificationEntry("test", false, true)
-
- assertFalse(filter.shouldFilterOut(defaultNotification, 0))
- assertFalse(filter.shouldFilterOut(notificationWithSecretVisibility, 0))
- assertFalse(filter.shouldFilterOut(notificationOnSecretChannel, 0))
- }
+ fun screenshareSecretFilter_sensitiveInctive_noFiltersSecret() =
+ testScope.runTest {
+ whenever(sensitiveNotificationProtectionController.isSensitiveStateActive)
+ .thenReturn(false)
+
+ coordinator.attach(pipeline)
+ val filter =
+ withArgCaptor<NotifFilter> { verify(pipeline).addFinalizeFilter(capture()) }
+
+ val defaultNotification = createNotificationEntry("test", false, false)
+ val notificationWithSecretVisibility = createNotificationEntry("test", true, false)
+ val notificationOnSecretChannel = createNotificationEntry("test", false, true)
+
+ assertFalse(filter.shouldFilterOut(defaultNotification, 0))
+ assertFalse(filter.shouldFilterOut(notificationWithSecretVisibility, 0))
+ assertFalse(filter.shouldFilterOut(notificationOnSecretChannel, 0))
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun screenshareSecretFilter_sensitiveActive_filtersSecret() {
- whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
-
- coordinator.attach(pipeline)
- val filter = withArgCaptor<NotifFilter> { verify(pipeline).addFinalizeFilter(capture()) }
-
- val defaultNotification = createNotificationEntry("test", false, false)
- val notificationWithSecretVisibility = createNotificationEntry("test", true, false)
- val notificationOnSecretChannel = createNotificationEntry("test", false, true)
-
- assertFalse(filter.shouldFilterOut(defaultNotification, 0))
- assertTrue(filter.shouldFilterOut(notificationWithSecretVisibility, 0))
- assertTrue(filter.shouldFilterOut(notificationOnSecretChannel, 0))
- }
+ fun screenshareSecretFilter_sensitiveActive_filtersSecret() =
+ testScope.runTest {
+ whenever(sensitiveNotificationProtectionController.isSensitiveStateActive)
+ .thenReturn(true)
+
+ coordinator.attach(pipeline)
+ val filter =
+ withArgCaptor<NotifFilter> { verify(pipeline).addFinalizeFilter(capture()) }
+
+ val defaultNotification = createNotificationEntry("test", false, false)
+ val notificationWithSecretVisibility = createNotificationEntry("test", true, false)
+ val notificationOnSecretChannel = createNotificationEntry("test", false, true)
+
+ assertFalse(filter.shouldFilterOut(defaultNotification, 0))
+ assertTrue(filter.shouldFilterOut(notificationWithSecretVisibility, 0))
+ assertTrue(filter.shouldFilterOut(notificationOnSecretChannel, 0))
+ }
@Test
- fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, false)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(false, false)
- }
+ fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(true)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, false)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, false)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction_sensitiveActive() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, false)
- whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(false, true)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
- }
+ fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction_sensitiveActive() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(true)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, false)
+ whenever(sensitiveNotificationProtectionController.isSensitiveStateActive)
+ .thenReturn(true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, true)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction_shouldProtectNotification() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, false)
- whenever(
- sensitiveNotificationProtectionController.shouldProtectNotification(
- entry.getRepresentativeEntry()
+ fun onBeforeRenderList_deviceUnlocked_notifDoesNotNeedRedaction_shouldProtectNotification() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(true)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, false)
+ whenever(
+ sensitiveNotificationProtectionController.shouldProtectNotification(
+ entry.getRepresentativeEntry()
+ )
)
- )
- .thenReturn(true)
+ .thenReturn(true)
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
- verify(entry.representativeEntry!!).setSensitive(true, false)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
- }
+ verify(entry.representativeEntry!!).setSensitive(true, false)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
+ }
@Test
- fun onBeforeRenderList_deviceUnlocked_notifWouldNeedRedaction() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, true)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(false, false)
- }
+ fun onBeforeRenderList_deviceUnlocked_notifWouldNeedRedaction() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(true)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, false)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun onBeforeRenderList_deviceUnlocked_notifWouldNeedRedaction_sensitiveActive() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, true)
- whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(false, true)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
- }
+ fun onBeforeRenderList_deviceUnlocked_notifWouldNeedRedaction_sensitiveActive() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(true)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, true)
+ whenever(sensitiveNotificationProtectionController.isSensitiveStateActive)
+ .thenReturn(true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, true)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun onBeforeRenderList_deviceUnlocked_notifWouldNeedRedaction_shouldProtectNotification() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, true)
- whenever(
- sensitiveNotificationProtectionController.shouldProtectNotification(
- entry.getRepresentativeEntry()
+ fun onBeforeRenderList_deviceUnlocked_notifWouldNeedRedaction_shouldProtectNotification() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(false)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(true)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, true)
+ whenever(
+ sensitiveNotificationProtectionController.shouldProtectNotification(
+ entry.getRepresentativeEntry()
+ )
)
- )
- .thenReturn(true)
+ .thenReturn(true)
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
- verify(entry.representativeEntry!!).setSensitive(true, false)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
- }
+ verify(entry.representativeEntry!!).setSensitive(true, false)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
+ }
@Test
- fun onBeforeRenderList_deviceLocked_userAllowsPublicNotifs() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, false)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(false, false)
- }
+ fun onBeforeRenderList_deviceLocked_userAllowsPublicNotifs() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(true)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, false)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, false)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun onBeforeRenderList_deviceLocked_userAllowsPublicNotifs_sensitiveActive() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, false)
- whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(false, true)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
- }
+ fun onBeforeRenderList_deviceLocked_userAllowsPublicNotifs_sensitiveActive() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(true)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, false)
+ whenever(sensitiveNotificationProtectionController.isSensitiveStateActive)
+ .thenReturn(true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, true)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun onBeforeRenderList_deviceLocked_userAllowsPublicNotifs_shouldProtectNotification() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(true)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, false)
- whenever(
- sensitiveNotificationProtectionController.shouldProtectNotification(
- entry.getRepresentativeEntry()
+ fun onBeforeRenderList_deviceLocked_userAllowsPublicNotifs_shouldProtectNotification() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(true)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, false)
+ whenever(
+ sensitiveNotificationProtectionController.shouldProtectNotification(
+ entry.getRepresentativeEntry()
+ )
)
- )
- .thenReturn(true)
+ .thenReturn(true)
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
- verify(entry.representativeEntry!!).setSensitive(true, false)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
- }
+ verify(entry.representativeEntry!!).setSensitive(true, false)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
+ }
@Test
- fun onBeforeRenderList_deviceLocked_userDisallowsPublicNotifs_notifDoesNotNeedRedaction() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, false)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(false, true)
- }
+ fun onBeforeRenderList_deviceLocked_userDisallowsPublicNotifs_notifDoesNotNeedRedaction() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, false)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, true)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
@Suppress("ktlint:standard:max-line-length")
- fun onBeforeRenderList_deviceLocked_userDisallowsPublicNotifs_notifDoesNotNeedRedaction_sensitiveActive() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, false)
- whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(false, true)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
- }
+ fun onBeforeRenderList_deviceLocked_userDisallowsPublicNotifs_notifDoesNotNeedRedaction_sensitiveActive() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, false)
+ whenever(sensitiveNotificationProtectionController.isSensitiveStateActive)
+ .thenReturn(true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, true)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
@Suppress("ktlint:standard:max-line-length")
- fun onBeforeRenderList_deviceLocked_userDisallowsPublicNotifs_notifDoesNotNeedRedaction_shouldProtectNotification() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, false)
- whenever(
- sensitiveNotificationProtectionController.shouldProtectNotification(
- entry.getRepresentativeEntry()
+ fun onBeforeRenderList_deviceLocked_userDisallowsPublicNotifs_notifDoesNotNeedRedaction_shouldProtectNotification() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, false)
+ whenever(
+ sensitiveNotificationProtectionController.shouldProtectNotification(
+ entry.getRepresentativeEntry()
+ )
)
- )
- .thenReturn(true)
+ .thenReturn(true)
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
- verify(entry.representativeEntry!!).setSensitive(true, true)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
- }
+ verify(entry.representativeEntry!!).setSensitive(true, true)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
+ }
@Test
- fun onBeforeRenderList_deviceLocked_notifNeedsRedaction() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, true)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(true, true)
- }
+ fun onBeforeRenderList_deviceLocked_notifNeedsRedaction() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(true, true)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun onBeforeRenderList_deviceLocked_notifNeedsRedaction_sensitiveActive() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, true)
- whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(true, true)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
- }
+ fun onBeforeRenderList_deviceLocked_notifNeedsRedaction_sensitiveActive() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, true)
+ whenever(sensitiveNotificationProtectionController.isSensitiveStateActive)
+ .thenReturn(true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(true, true)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun onBeforeRenderList_deviceLocked_notifNeedsRedaction_shouldProtectNotification() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(false)
- val entry = fakeNotification(1, true)
- whenever(
- sensitiveNotificationProtectionController.shouldProtectNotification(
- entry.getRepresentativeEntry()
+ fun onBeforeRenderList_deviceLocked_notifNeedsRedaction_shouldProtectNotification() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = false)
+ val entry = fakeNotification(1, true)
+ whenever(
+ sensitiveNotificationProtectionController.shouldProtectNotification(
+ entry.getRepresentativeEntry()
+ )
)
- )
- .thenReturn(true)
+ .thenReturn(true)
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
- verify(entry.representativeEntry!!).setSensitive(true, true)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
- }
+ verify(entry.representativeEntry!!).setSensitive(true, true)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
+ }
@Test
- fun onBeforeRenderList_deviceDynamicallyUnlocked_notifNeedsRedaction() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
- val entry = fakeNotification(1, true)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(false, true)
- }
+ fun onBeforeRenderList_deviceDynamicallyUnlocked_notifNeedsRedaction() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = true)
+ val entry = fakeNotification(1, true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, true)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun onBeforeRenderList_deviceDynamicallyUnlocked_notifNeedsRedaction_sensitiveActive() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
- val entry = fakeNotification(1, true)
- whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(false, true)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
- }
+ fun onBeforeRenderList_deviceDynamicallyUnlocked_notifNeedsRedaction_sensitiveActive() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = true)
+ val entry = fakeNotification(1, true)
+ whenever(sensitiveNotificationProtectionController.isSensitiveStateActive)
+ .thenReturn(true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(false, true)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
@Suppress("ktlint:standard:max-line-length")
- fun onBeforeRenderList_deviceDynamicallyUnlocked_notifNeedsRedaction_shouldProtectNotification() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
- val entry = fakeNotification(1, true)
- whenever(
- sensitiveNotificationProtectionController.shouldProtectNotification(
- entry.getRepresentativeEntry()
+ fun onBeforeRenderList_deviceDynamicallyUnlocked_notifNeedsRedaction_shouldProtectNotification() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = true)
+ val entry = fakeNotification(1, true)
+ whenever(
+ sensitiveNotificationProtectionController.shouldProtectNotification(
+ entry.getRepresentativeEntry()
+ )
)
- )
- .thenReturn(true)
+ .thenReturn(true)
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
- verify(entry.representativeEntry!!).setSensitive(true, true)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
- }
+ verify(entry.representativeEntry!!).setSensitive(true, true)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
+ }
@Test
- fun onBeforeRenderList_deviceDynamicallyUnlocked_notifUserNeedsWorkChallenge() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
- whenever(lockscreenUserManager.needsSeparateWorkChallenge(2)).thenReturn(true)
- val entry = fakeNotification(2, true)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(true, true)
- }
+ fun onBeforeRenderList_deviceDynamicallyUnlocked_notifUserNeedsWorkChallenge() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = true)
+ whenever(lockscreenUserManager.needsSeparateWorkChallenge(2)).thenReturn(true)
+ val entry = fakeNotification(2, true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(true, true)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
- fun onBeforeRenderList_deviceDynamicallyUnlocked_notifUserNeedsWorkChallenge_sensitiveActive() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
- whenever(lockscreenUserManager.needsSeparateWorkChallenge(2)).thenReturn(true)
- val entry = fakeNotification(2, true)
- whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!).setSensitive(true, true)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
- }
+ fun onBeforeRenderList_deviceDynamicallyUnlocked_notifUserNeedsWorkChallenge_sensitiveActive() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = true)
+ whenever(lockscreenUserManager.needsSeparateWorkChallenge(2)).thenReturn(true)
+ val entry = fakeNotification(2, true)
+ whenever(sensitiveNotificationProtectionController.isSensitiveStateActive)
+ .thenReturn(true)
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!).setSensitive(true, true)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(true)
+ }
@Test
@EnableFlags(FLAG_SCREENSHARE_NOTIFICATION_HIDING)
@Suppress("ktlint:standard:max-line-length")
- fun onBeforeRenderList_deviceDynamicallyUnlocked_notifUserNeedsWorkChallenge_shouldProtectNotification() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
-
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
- whenever(lockscreenUserManager.needsSeparateWorkChallenge(2)).thenReturn(true)
- val entry = fakeNotification(2, true)
- whenever(
- sensitiveNotificationProtectionController.shouldProtectNotification(
- entry.getRepresentativeEntry()
+ fun onBeforeRenderList_deviceDynamicallyUnlocked_notifUserNeedsWorkChallenge_shouldProtectNotification() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = true)
+ whenever(lockscreenUserManager.needsSeparateWorkChallenge(2)).thenReturn(true)
+ val entry = fakeNotification(2, true)
+ whenever(
+ sensitiveNotificationProtectionController.shouldProtectNotification(
+ entry.getRepresentativeEntry()
+ )
)
- )
- .thenReturn(true)
+ .thenReturn(true)
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
- verify(entry.representativeEntry!!).setSensitive(true, true)
- verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
- }
+ verify(entry.representativeEntry!!).setSensitive(true, true)
+ verify(entry.representativeEntry!!.row!!).setPublicExpanderVisible(false)
+ }
@Test
- fun onBeforeRenderList_deviceDynamicallyUnlocked_deviceBiometricBypassingLockScreen() {
- coordinator.attach(pipeline)
- val onBeforeRenderListListener =
- withArgCaptor<OnBeforeRenderListListener> {
- verify(pipeline).addOnBeforeRenderListListener(capture())
- }
+ fun onBeforeRenderList_deviceDynamicallyUnlocked_deviceBiometricBypassingLockScreen() =
+ testScope.runTest {
+ coordinator.attach(pipeline)
+ val onBeforeRenderListListener =
+ withArgCaptor<OnBeforeRenderListListener> {
+ verify(pipeline).addOnBeforeRenderListListener(capture())
+ }
+
+ whenever(lockscreenUserManager.currentUserId).thenReturn(1)
+ whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
+ whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1))
+ .thenReturn(false)
+ setupLockScreen(canSwipeUp = true)
+ whenever(keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(any()))
+ .thenReturn(true)
+ val entry = fakeNotification(2, true)
+ whenever(sensitiveNotificationProtectionController.isSensitiveStateActive)
+ .thenReturn(true)
+ whenever(sensitiveNotificationProtectionController.shouldProtectNotification(any()))
+ .thenReturn(true)
+ statusBarStateController.state = StatusBarState.KEYGUARD
+
+ onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
+
+ verify(entry.representativeEntry!!, never()).setSensitive(any(), any())
+ verify(entry.representativeEntry!!.row!!, never()).setPublicExpanderVisible(any())
+ }
+
+ private fun TestScope.setupLockScreen(canSwipeUp: Boolean) {
+ if (SceneContainerFlag.isEnabled) {
+ val authMethod =
+ if (canSwipeUp) AuthenticationMethodModel.None
+ else AuthenticationMethodModel.Password
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(authMethod)
+ kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
+ switchToScene(Scenes.Lockscreen)
+ } else {
+ whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(canSwipeUp)
+ }
+ }
- whenever(lockscreenUserManager.currentUserId).thenReturn(1)
- whenever(lockscreenUserManager.isLockscreenPublicMode(1)).thenReturn(true)
- whenever(lockscreenUserManager.userAllowsPrivateNotificationsInPublic(1)).thenReturn(false)
- whenever(dynamicPrivacyController.isDynamicallyUnlocked).thenReturn(true)
- whenever(keyguardUpdateMonitor.getUserUnlockedWithBiometricAndIsBypassing(any()))
- .thenReturn(true)
- val entry = fakeNotification(2, true)
- whenever(sensitiveNotificationProtectionController.isSensitiveStateActive).thenReturn(true)
- whenever(sensitiveNotificationProtectionController.shouldProtectNotification(any()))
- .thenReturn(true)
- statusBarStateController.state = StatusBarState.KEYGUARD
-
- onBeforeRenderListListener.onBeforeRenderList(listOf(entry))
-
- verify(entry.representativeEntry!!, never()).setSensitive(any(), any())
- verify(entry.representativeEntry!!.row!!, never()).setPublicExpanderVisible(any())
+ private fun TestScope.switchToScene(sceneKey: SceneKey) {
+ sceneInteractor.changeScene(sceneKey, "reason")
+ sceneInteractor.setTransitionState(flowOf(ObservableTransitionState.Idle(sceneKey)))
+ runCurrent()
}
private fun fakeNotification(notifUserId: Int, needsRedaction: Boolean): ListEntry {
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
index f9b30c6c2ba1..ea428698e476 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalInteractor.kt
@@ -27,6 +27,7 @@ import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.TransitionKey
+import com.android.systemui.Flags.communalResponsiveGrid
import com.android.systemui.broadcast.BroadcastDispatcher
import com.android.systemui.communal.data.repository.CommunalMediaRepository
import com.android.systemui.communal.data.repository.CommunalSmartspaceRepository
@@ -535,7 +536,9 @@ constructor(
// Order by creation time descending.
ongoingContent.sortByDescending { it.createdTimestampMillis }
// Resize the items.
- ongoingContent.resizeItems()
+ if (!communalResponsiveGrid()) {
+ ongoingContent.resizeItems()
+ }
// Return the sorted and resized items.
ongoingContent
diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt
index da613f58dce8..c0456d5bb46e 100644
--- a/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/communal/domain/model/CommunalContentModel.kt
@@ -110,6 +110,11 @@ sealed interface CommunalContentModel {
get() = fixedHalfOrResponsiveSize()
}
+ /** An empty spacer to reserve space in the grid. */
+ data class Spacer(override val size: CommunalContentSize) : CommunalContentModel {
+ override val key: String = KEY.spacer()
+ }
+
/** A CTA tile in the glanceable hub view mode which can be dismissed. */
class CtaTileInViewMode : CommunalContentModel {
override val key: String = KEY.CTA_TILE_IN_VIEW_MODE_KEY
@@ -171,6 +176,10 @@ sealed interface CommunalContentModel {
fun umo(): String {
return "umo"
}
+
+ fun spacer(): String {
+ return "spacer_${UUID.randomUUID()}"
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/communal/util/ResizeUtils.kt b/packages/SystemUI/src/com/android/systemui/communal/util/ResizeUtils.kt
new file mode 100644
index 000000000000..36cc1c051336
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/communal/util/ResizeUtils.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.communal.util
+
+import com.android.systemui.communal.domain.model.CommunalContentModel
+import com.android.systemui.communal.shared.model.CommunalContentSize
+
+object ResizeUtils {
+ /**
+ * Resizes ongoing items such that we don't mix regular content with ongoing content.
+ *
+ * NOTE: This is *NOT* a pure function, as it modifies items in the input list.
+ *
+ * Assumptions:
+ * 1. Ongoing content is always at the start of the list.
+ * 2. The maximum size of ongoing content is 2 rows.
+ */
+ fun resizeOngoingItems(
+ list: List<CommunalContentModel>,
+ numRows: Int,
+ ): List<CommunalContentModel> {
+ val finalizedList = mutableListOf<CommunalContentModel>()
+ val numOngoing = list.count { it is CommunalContentModel.Ongoing }
+ // Calculate the number of extra rows we have if each ongoing item were to take up a single
+ // row. This is the number of rows we have to distribute across items.
+ var extraRows =
+ if (numOngoing % numRows == 0) {
+ 0
+ } else {
+ numRows - (numOngoing % numRows)
+ }
+ var remainingRows = numRows
+
+ for (item in list) {
+ if (item is CommunalContentModel.Ongoing) {
+ if (remainingRows == 0) {
+ // Start a new column.
+ remainingRows = numRows
+ }
+ val newSize = if (extraRows > 0 && remainingRows > 1) 2 else 1
+ item.size = CommunalContentSize.Responsive(newSize)
+ finalizedList.add(item)
+ extraRows -= (newSize - 1)
+ remainingRows -= newSize
+ } else {
+ if (numOngoing > 0 && remainingRows > 0) {
+ finalizedList.add(
+ CommunalContentModel.Spacer(CommunalContentSize.Responsive(remainingRows))
+ )
+ }
+ remainingRows = -1
+ finalizedList.add(item)
+ }
+ }
+ return finalizedList
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
index ef7b1c3d562e..04458f3a7168 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinator.kt
@@ -14,10 +14,13 @@
* limitations under the License.
*/
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
package com.android.systemui.statusbar.notification.collection.coordinator
import android.app.Notification
import android.os.UserHandle
+import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.server.notification.Flags.screenshareNotificationHiding
import com.android.systemui.dagger.qualifiers.Application
@@ -44,9 +47,9 @@ import dagger.Binds
import dagger.Module
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.mapNotNull
-import com.android.app.tracing.coroutines.launchTraced as launch
@Module(includes = [PrivateSensitiveContentCoordinatorModule::class])
interface SensitiveContentCoordinatorModule
@@ -80,6 +83,7 @@ constructor(
DynamicPrivacyController.Listener,
OnBeforeRenderListListener {
private var inTransitionFromLockedToGone = false
+ private var canSwipeToEnter = false
private val onSensitiveStateChanged = Runnable() { invalidateList("onSensitiveStateChanged") }
@@ -98,7 +102,9 @@ constructor(
}
override fun attach(pipeline: NotifPipeline) {
- dynamicPrivacyController.addListener(this)
+ if (!SceneContainerFlag.isEnabled) {
+ dynamicPrivacyController.addListener(this)
+ }
if (screenshareNotificationHiding()) {
sensitiveNotificationProtectionController.registerSensitiveStateListener(
onSensitiveStateChanged
@@ -128,6 +134,15 @@ constructor(
invalidateList("inTransitionFromLockedToGoneChanged")
}
}
+ scope.launch {
+ deviceEntryInteractor.canSwipeToEnter.collect {
+ val canSwipeToEnter = it ?: false
+ if (this@SensitiveContentCoordinatorImpl.canSwipeToEnter != canSwipeToEnter) {
+ this@SensitiveContentCoordinatorImpl.canSwipeToEnter = canSwipeToEnter
+ invalidateList("canSwipeToEnterChanged")
+ }
+ }
+ }
}
}
@@ -168,7 +183,9 @@ constructor(
(devicePublic &&
!lockscreenUserManager.userAllowsPrivateNotificationsInPublic(currentUserId)) ||
isSensitiveContentProtectionActive
- val dynamicallyUnlocked = dynamicPrivacyController.isDynamicallyUnlocked
+ val dynamicallyUnlocked =
+ if (SceneContainerFlag.isEnabled) canSwipeToEnter
+ else dynamicPrivacyController.isDynamicallyUnlocked
for (entry in extractAllRepresentativeEntries(entries).filter { it.rowExists() }) {
val notifUserId = entry.sbn.user.identifier
val userLockscreen =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index ba707a5cd0b1..245b1d29fb79 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -429,9 +429,10 @@ public class NotificationStackScrollLayoutController implements Dumpable {
};
/**
- * Recalculate sensitiveness without animation; called when waking up while keyguard occluded.
+ * Recalculate sensitiveness without animation; called when waking up while keyguard occluded,
+ * or whenever we update the Lockscreen public mode.
*/
- public void updateSensitivenessForOccludedWakeup() {
+ public void updateSensitivenessWithoutAnimation() {
updateSensitivenessWithAnimation(false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
index c6af3280eef1..7bea4800f7fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -2234,6 +2234,9 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
// If the state didn't change, we may still need to update public mode
mLockscreenUserManager.updatePublicMode();
+ if (SceneContainerFlag.isEnabled()) {
+ mStackScrollerController.updateSensitivenessWithoutAnimation();
+ }
}
if (mStatusBarStateController.leaveOpenOnKeyguardHide()) {
if (!mStatusBarStateController.isKeyguardRequested()) {
@@ -2681,7 +2684,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
// So if AOD is off or unsupported we need to trigger these updates at screen on
// when the keyguard is occluded.
mLockscreenUserManager.updatePublicMode();
- mStackScrollerController.updateSensitivenessForOccludedWakeup();
+ mStackScrollerController.updateSensitivenessWithoutAnimation();
}
if (mLaunchCameraWhenFinishedWaking) {
startLaunchTransitionTimeout();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 6912eda3c3d4..d157cf2d51e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -36,8 +36,6 @@ import static com.android.systemui.statusbar.phone.CentralSurfaces.MSG_DISMISS_K
import static com.google.common.truth.Truth.assertThat;
-import static kotlinx.coroutines.flow.FlowKt.flowOf;
-
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -56,6 +54,8 @@ import static org.mockito.Mockito.when;
import static java.util.Collections.emptySet;
+import static kotlinx.coroutines.flow.FlowKt.flowOf;
+
import android.app.ActivityManager;
import android.app.IWallpaperManager;
import android.app.NotificationManager;
@@ -138,6 +138,7 @@ import com.android.systemui.plugins.PluginDependencyProvider;
import com.android.systemui.plugins.PluginManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.power.domain.interactor.PowerInteractor;
+import com.android.systemui.qs.flags.QSComposeFragment;
import com.android.systemui.res.R;
import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor;
import com.android.systemui.scene.domain.startable.ScrimStartable;
@@ -181,6 +182,7 @@ import com.android.systemui.statusbar.notification.NotifPipelineFlags;
import com.android.systemui.statusbar.notification.NotificationActivityStarter;
import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.notification.init.NotificationsController;
import com.android.systemui.statusbar.notification.interruption.AvalancheProvider;
import com.android.systemui.statusbar.notification.interruption.KeyguardNotificationVisibilityProvider;
@@ -198,7 +200,6 @@ import com.android.systemui.statusbar.policy.BatteryController;
import com.android.systemui.statusbar.policy.ConfigurationController;
import com.android.systemui.statusbar.policy.DeviceProvisionedController;
import com.android.systemui.statusbar.policy.ExtensionController;
-import com.android.systemui.statusbar.notification.headsup.HeadsUpManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
import com.android.systemui.statusbar.window.StatusBarWindowController;
@@ -217,10 +218,6 @@ import com.android.systemui.volume.VolumeComponent;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.startingsurface.StartingSurface;
-import dagger.Lazy;
-
-import kotlinx.coroutines.test.TestScope;
-
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -237,6 +234,9 @@ import java.util.Set;
import javax.inject.Provider;
+import dagger.Lazy;
+import kotlinx.coroutines.test.TestScope;
+
@SmallTest
@RunWith(AndroidJUnit4.class)
@RunWithLooper(setAsMainLooper = true)
@@ -667,6 +667,9 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
mCentralSurfaces.startKeyguard();
mInitController.executePostInitTasks();
mCentralSurfaces.registerCallbacks();
+ // Clear first invocations caused by registering flows with JavaAdapter
+ mTestScope.getTestScheduler().runCurrent();
+ clearInvocations(mScrimController);
}
@Test
@@ -1159,8 +1162,7 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
@Test
@EnableSceneContainer
- public void brightnesShowingChanged_flagEnabled_ScrimControllerNotified() {
- mCentralSurfaces.registerCallbacks();
+ public void brightnesShowingChanged_sceneContainerFlagEnabled_ScrimControllerNotified() {
final ScrimStartable scrimStartable = mKosmos.getScrimStartable();
scrimStartable.start();
@@ -1178,9 +1180,25 @@ public class CentralSurfacesImplTest extends SysuiTestCase {
@Test
@DisableSceneContainer
- public void brightnesShowingChanged_flagDisabled_ScrimControllerNotified() {
- mCentralSurfaces.registerCallbacks();
+ @EnableFlags(QSComposeFragment.FLAG_NAME)
+ public void brightnesShowingChanged_qsUiRefactorFlagEnabled_ScrimControllerNotified() {
+ mBrightnessMirrorShowingInteractor.setMirrorShowing(true);
+ mTestScope.getTestScheduler().runCurrent();
+ verify(mScrimController, atLeastOnce()).legacyTransitionTo(ScrimState.BRIGHTNESS_MIRROR);
+ clearInvocations(mScrimController);
+
+ mBrightnessMirrorShowingInteractor.setMirrorShowing(false);
+ mTestScope.getTestScheduler().runCurrent();
+ ArgumentCaptor<ScrimState> captor = ArgumentCaptor.forClass(ScrimState.class);
+ // The default is to call the one with the callback argument
+ verify(mScrimController, atLeastOnce()).legacyTransitionTo(captor.capture(), any());
+ assertThat(captor.getValue()).isNotEqualTo(ScrimState.BRIGHTNESS_MIRROR);
+ }
+ @Test
+ @DisableSceneContainer
+ @DisableFlags(QSComposeFragment.FLAG_NAME)
+ public void brightnesShowingChanged_flagsDisabled_ScrimControllerNotified() {
mBrightnessMirrorShowingInteractor.setMirrorShowing(true);
mTestScope.getTestScheduler().runCurrent();
verify(mScrimController, never()).legacyTransitionTo(ScrimState.BRIGHTNESS_MIRROR);
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorKosmos.kt
index 4a249a8591e9..88bf9a5f2d5b 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/collection/coordinator/SensitiveContentCoordinatorKosmos.kt
@@ -42,6 +42,6 @@ var Kosmos.sensitiveContentCoordinator: SensitiveContentCoordinator by
sensitiveNotificationProtectionController,
deviceEntryInteractor,
sceneInteractor,
- testScope,
+ testScope.backgroundScope,
)
}