Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57578901 authored by burakov's avatar burakov
Browse files

[Dual Shade] Fix ScrimStartableTest for Dual Shade on.

This ensures these unit tests do not fail when Dual Shade is the default
shade experience in scene container.

BONUS: Remove the unused isOnKeyguard precondition, as only
isDeviceEntered is used to determine the keyguard state.

Bug: 376411622
Test: Updated unit tests.
Flag: com.android.systemui.scene_container
Change-Id: I1fbbbdeba086ddcafb0a944516d1009174325b70
parent 18a28c36
Loading
Loading
Loading
Loading
+143 −91
Original line number Diff line number Diff line
@@ -22,7 +22,6 @@ import com.android.compose.animation.scene.OverlayKey
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
@@ -31,12 +30,17 @@ import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.scene.data.repository.setSceneTransition
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.settings.brightness.domain.interactor.brightnessMirrorShowingInteractor
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.enableSingleShade
import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.ScrimState
@@ -47,10 +51,8 @@ import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertWithMessage
import kotlin.reflect.full.memberProperties
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.Before
import org.junit.BeforeClass
import org.junit.Test
@@ -63,6 +65,7 @@ import platform.test.runner.parameterized.Parameters

@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
@OptIn(ExperimentalCoroutinesApi::class)
@EnableSceneContainer
class ScrimStartableTest : SysuiTestCase() {

@@ -75,7 +78,7 @@ class ScrimStartableTest : SysuiTestCase() {
                    id = 0,
                    expectedState = ScrimState.KEYGUARD,
                    Preconditions(
                        isOnKeyguard = true,
                        isDeviceEntered = false,
                        isAlternateBouncerVisible = true,
                        isTransitioningAwayFromKeyguard = true,
                    ),
@@ -84,90 +87,104 @@ class ScrimStartableTest : SysuiTestCase() {
                    id = 1,
                    expectedState = null,
                    Preconditions(
                        isOnKeyguard = true,
                        isDeviceEntered = false,
                        isAlternateBouncerVisible = true,
                        isTransitioningToShade = true,
                        isTransitioningToShadeScene = true,
                    ),
                ),
                TestSpec(
                    id = 2,
                    expectedState = ScrimState.BOUNCER,
                    Preconditions(isOnKeyguard = true, isIdleOnBouncer = true),
                    expectedState = null,
                    Preconditions(
                        isDeviceEntered = false,
                        isAlternateBouncerVisible = true,
                        isTransitioningToShadeOverlay = true,
                    ),
                ),
                TestSpec(
                    id = 3,
                    expectedState = ScrimState.BOUNCER,
                    Preconditions(isDeviceEntered = false, isIdleOnBouncer = true),
                ),
                TestSpec(
                    id = 4,
                    expectedState = ScrimState.BOUNCER_SCRIMMED,
                    Preconditions(
                        isOnKeyguard = true,
                        isDeviceEntered = false,
                        isIdleOnBouncer = true,
                        isBouncerScrimmingNeeded = true,
                    ),
                ),
                TestSpec(
                    id = 4,
                    id = 5,
                    expectedState = ScrimState.BRIGHTNESS_MIRROR,
                    Preconditions(isOnKeyguard = true, isBrightnessMirrorVisible = true),
                    Preconditions(isDeviceEntered = false, isBrightnessMirrorVisible = true),
                ),
                TestSpec(
                    id = 5,
                    id = 6,
                    expectedState = ScrimState.BRIGHTNESS_MIRROR,
                    Preconditions(
                        isOnKeyguard = true,
                        isDeviceEntered = false,
                        isIdleOnBouncer = true,
                        isBiometricWakeAndUnlock = true,
                        isBrightnessMirrorVisible = true,
                    ),
                ),
                TestSpec(
                    id = 6,
                    id = 7,
                    expectedState = ScrimState.SHADE_LOCKED,
                    Preconditions(isOnKeyguard = true, isCurrentSceneShade = true),
                    Preconditions(isDeviceEntered = false, isIdleOnShadeScene = true),
                ),
                TestSpec(
                    id = 7,
                    id = 8,
                    expectedState = ScrimState.SHADE_LOCKED,
                    Preconditions(isDeviceEntered = false, isIdleOnShadeOverlay = true),
                ),
                TestSpec(
                    id = 9,
                    expectedState = ScrimState.PULSING,
                    Preconditions(isOnKeyguard = true, isDozing = true, isPulsing = true),
                    Preconditions(isDeviceEntered = false, isDozing = true, isPulsing = true),
                ),
                TestSpec(
                    id = 8,
                    id = 10,
                    expectedState = ScrimState.OFF,
                    Preconditions(isOnKeyguard = true, hasPendingScreenOffCallback = true),
                    Preconditions(isDeviceEntered = false, hasPendingScreenOffCallback = true),
                ),
                TestSpec(
                    id = 9,
                    id = 11,
                    expectedState = ScrimState.AOD,
                    Preconditions(isOnKeyguard = true, isDozing = true),
                    Preconditions(isDeviceEntered = false, isDozing = true),
                ),
                TestSpec(
                    id = 10,
                    id = 12,
                    expectedState = ScrimState.GLANCEABLE_HUB,
                    Preconditions(isIdleOnCommunal = true),
                ),
                TestSpec(
                    id = 11,
                    id = 13,
                    expectedState = ScrimState.GLANCEABLE_HUB_OVER_DREAM,
                    Preconditions(isIdleOnCommunal = true, isDreaming = true),
                ),
                TestSpec(
                    id = 12,
                    id = 14,
                    expectedState = ScrimState.UNLOCKED,
                    Preconditions(isDeviceEntered = true),
                ),
                TestSpec(
                    id = 13,
                    id = 15,
                    expectedState = ScrimState.UNLOCKED,
                    Preconditions(isOnKeyguard = true, isBiometricWakeAndUnlock = true),
                    Preconditions(isBiometricWakeAndUnlock = true),
                ),
                TestSpec(id = 14, expectedState = ScrimState.KEYGUARD, Preconditions()),
                TestSpec(id = 16, expectedState = ScrimState.KEYGUARD, Preconditions()),
                TestSpec(
                    id = 15,
                    id = 17,
                    expectedState = ScrimState.DREAMING,
                    Preconditions(isOnKeyguard = true, isOccluded = true, isDreaming = true),
                    Preconditions(isOccluded = true, isDreaming = true),
                ),
                TestSpec(
                    id = 16,
                    id = 18,
                    expectedState = ScrimState.UNLOCKED,
                    Preconditions(isOnKeyguard = true, isOccluded = true),
                    Preconditions(isOccluded = true),
                ),
            )
        }
@@ -185,10 +202,9 @@ class ScrimStartableTest : SysuiTestCase() {
        }
    }

    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val kosmos = testKosmos().useUnconfinedTestDispatcher()

    private val underTest = kosmos.scrimStartable
    private val underTest: ScrimStartable by lazy { kosmos.scrimStartable }

    @JvmField @Parameter(0) var testSpec: TestSpec? = null

@@ -205,94 +221,101 @@ class ScrimStartableTest : SysuiTestCase() {

    @Test
    fun test() =
        testScope.runTest {
        kosmos.runTest {
            val observedState by collectLastValue(underTest.scrimState)
            val preconditions = checkNotNull(testSpec).preconditions
            preconditions.assertValid()

            setUpWith(preconditions)

            runCurrent()

            assertThat(observedState).isEqualTo(checkNotNull(testSpec).expectedState)
        }

    /** Sets up the state to match what's specified in the given [preconditions]. */
    private fun TestScope.setUpWith(preconditions: Preconditions) {
        kosmos.fakeKeyguardBouncerRepository.setAlternateVisible(
            preconditions.isAlternateBouncerVisible
        )
    private fun Kosmos.setUpWith(preconditions: Preconditions) {
        whenever(statusBarKeyguardViewManager.primaryBouncerNeedsScrimming())
            .thenReturn(preconditions.isBouncerScrimmingNeeded)

        fakeKeyguardBouncerRepository.setAlternateVisible(preconditions.isAlternateBouncerVisible)

        if (preconditions.isDeviceEntered) {
            kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
            fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
                SuccessFingerprintAuthenticationStatus(0, true)
            )
            whenIdle(on = Scenes.Gone)
        } else {
            whenIdle(on = Scenes.Lockscreen)
        }
        runCurrent()

        when {
            preconditions.isTransitioningToShade ->
            preconditions.isTransitioningToShadeScene -> {
                enableSingleShade()
                whenTransitioning(from = Scenes.Lockscreen, to = Scenes.Shade)
            }
            preconditions.isTransitioningToShadeOverlay -> {
                enableDualShade()
                whenTransitioning(from = Scenes.Lockscreen, to = Overlays.NotificationsShade)
            }
            preconditions.isTransitioningAwayFromKeyguard ->
                whenTransitioning(from = Scenes.Lockscreen, to = Scenes.Gone)
            preconditions.isCurrentSceneShade -> whenIdle(on = Scenes.Shade)
            preconditions.isIdleOnShadeScene -> {
                enableSingleShade()
                whenIdle(on = Scenes.Shade)
            }
            preconditions.isIdleOnShadeOverlay -> {
                enableDualShade()
                whenIdle(
                    on = if (preconditions.isDeviceEntered) Scenes.Gone else Scenes.Lockscreen,
                    overlays = setOf(Overlays.NotificationsShade),
                )
            }
            preconditions.isIdleOnBouncer ->
                whenIdle(on = Scenes.Lockscreen, overlays = setOf(Overlays.Bouncer))
            preconditions.isIdleOnCommunal -> whenIdle(on = Scenes.Communal)
        }

        kosmos.keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(
        keyguardOcclusionInteractor.setWmNotifiedShowWhenLockedActivityOnTop(
            showWhenLockedActivityOnTop = preconditions.isOccluded,
            taskInfo = if (preconditions.isOccluded) mock() else null,
        )

        if (preconditions.isBiometricWakeAndUnlock) {
            kosmos.biometricUnlockInteractor.setBiometricUnlockState(
            biometricUnlockInteractor.setBiometricUnlockState(
                BiometricUnlockController.MODE_WAKE_AND_UNLOCK,
                BiometricUnlockSource.FINGERPRINT_SENSOR,
            )
        }

        kosmos.brightnessMirrorShowingInteractor.setMirrorShowing(
            preconditions.isBrightnessMirrorVisible
        )
        brightnessMirrorShowingInteractor.setMirrorShowing(preconditions.isBrightnessMirrorVisible)

        if (preconditions.hasPendingScreenOffCallback) {
            kosmos.dozeServiceHost.prepareForGentleSleep {}
            dozeServiceHost.prepareForGentleSleep {}
        } else {
            kosmos.dozeServiceHost.cancelGentleSleep()
            dozeServiceHost.cancelGentleSleep()
        }

        kosmos.fakeKeyguardRepository.setIsDozing(preconditions.isDozing)
        fakeKeyguardRepository.setIsDozing(preconditions.isDozing)
        if (preconditions.isPulsing) {
            kosmos.fakeKeyguardRepository.setDozeTransitionModel(
            fakeKeyguardRepository.setDozeTransitionModel(
                DozeTransitionModel(to = DozeStateModel.DOZE_PULSING)
            )
        }
        kosmos.fakeKeyguardRepository.setDreaming(preconditions.isDreaming)

        whenever(kosmos.statusBarKeyguardViewManager.primaryBouncerNeedsScrimming())
            .thenReturn(preconditions.isBouncerScrimmingNeeded)

        runCurrent()
        fakeKeyguardRepository.setDreaming(preconditions.isDreaming)
    }

    /** Sets up an idle state on the given [on] scene. */
    private fun whenIdle(on: SceneKey, overlays: Set<OverlayKey> = emptySet()) {
        kosmos.setSceneTransition(ObservableTransitionState.Idle(on, overlays))
        kosmos.sceneInteractor.changeScene(on, "")
    private fun Kosmos.whenIdle(on: SceneKey, overlays: Set<OverlayKey> = emptySet()) {
        setSceneTransition(ObservableTransitionState.Idle(on, overlays))
        sceneInteractor.changeScene(on, "")
        for (overlay in overlays) {
            kosmos.sceneInteractor.showOverlay(overlay, "")
            sceneInteractor.showOverlay(overlay, "")
        }
    }

    /** Sets up a transitioning state between the [given] and [to] scenes. */
    private fun whenTransitioning(from: SceneKey, to: SceneKey, progress: Float = 0.5f) {
    /** Sets up a transitioning state between the given [from] and [to] scenes. */
    private fun Kosmos.whenTransitioning(from: SceneKey, to: SceneKey, progress: Float = 0.5f) {
        val currentScene = if (progress > 0.5f) to else from
        kosmos.setSceneTransition(
        setSceneTransition(
            ObservableTransitionState.Transition(
                fromScene = from,
                toScene = to,
@@ -302,15 +325,31 @@ class ScrimStartableTest : SysuiTestCase() {
                isUserInputOngoing = flowOf(false),
            )
        )
        kosmos.sceneInteractor.changeScene(currentScene, "")
        sceneInteractor.changeScene(currentScene, "")
    }

    /** Sets up a transitioning state between the [from] scene and [to] overlay. */
    private fun Kosmos.whenTransitioning(from: SceneKey, to: OverlayKey, progress: Float = 0.5f) {
        val currentOverlays = if (progress > 0.5f) setOf(to) else emptySet()
        setSceneTransition(
            ObservableTransitionState.Transition.showOverlay(
                overlay = to,
                fromScene = from,
                progress = flowOf(progress),
                currentOverlays = flowOf(currentOverlays),
                isInitiatedByUserInput = true,
                isUserInputOngoing = flowOf(false),
            )
        )
        sceneInteractor.showOverlay(to, "")
    }

    data class Preconditions(
        /** Whether bouncer or lockscreen scene is in the nav stack. */
        val isOnKeyguard: Boolean = false,
        val isAlternateBouncerVisible: Boolean = false,
        /** Whether any non-shade nor QS scene is transitioning to a shade or QS scene. */
        val isTransitioningToShade: Boolean = false,
        val isTransitioningToShadeScene: Boolean = false,
        /** Whether any non-shade nor QS scene is transitioning to a shade or QS overlay. */
        val isTransitioningToShadeOverlay: Boolean = false,
        val isOccluded: Boolean = false,
        val isIdleOnBouncer: Boolean = false,
        val isBiometricWakeAndUnlock: Boolean = false,
@@ -318,7 +357,9 @@ class ScrimStartableTest : SysuiTestCase() {
        val isTransitioningAwayFromKeyguard: Boolean = false,
        val isBrightnessMirrorVisible: Boolean = false,
        /** Whether the current scene is a shade or QS scene. */
        val isCurrentSceneShade: Boolean = false,
        val isIdleOnShadeScene: Boolean = false,
        /** Whether the notifications shade or QS shade overlay is in the current overlays. */
        val isIdleOnShadeOverlay: Boolean = false,
        val isDeviceEntered: Boolean = false,
        val isPulsing: Boolean = false,
        val hasPendingScreenOffCallback: Boolean = false,
@@ -342,47 +383,58 @@ class ScrimStartableTest : SysuiTestCase() {
        }

        fun assertValid() {
            assertWithMessage("isOccluded cannot be true without isOnKeyguard also being true")
                .that(!isOccluded || isOnKeyguard)
            assertWithMessage("isOccluded cannot be true at the same time as isDeviceEntered")
                .that(!isOccluded || !isDeviceEntered)
                .isTrue()

            assertWithMessage(
                    "isCurrentSceneBouncer cannot be true without isOnKeyguard also being true"
                )
                .that(!isIdleOnBouncer || isOnKeyguard)
            assertWithMessage("isIdleOnBouncer cannot be true at the same time as isDeviceEntered")
                .that(!isIdleOnBouncer || !isDeviceEntered)
                .isTrue()

            assertWithMessage("isIdleOnBouncer cannot be true at the same time as isIdleOnCommunal")
                .that(!isIdleOnBouncer || !isIdleOnCommunal)
                .isTrue()

            assertWithMessage(
                    "isTransitioningAwayFromKeyguard cannot be true without isOnKeyguard being true"
                    "isIdleOnShadeScene cannot be true at the same time as isIdleOnCommunal"
                )
                .that(!isTransitioningAwayFromKeyguard || isOnKeyguard)
                .that(!isIdleOnShadeScene || !isIdleOnCommunal)
                .isTrue()

            assertWithMessage(
                    "isCurrentSceneBouncer cannot be true at the same time as isCurrentSceneShade"
                    "isIdleOnShadeOverlay cannot be true at the same time as isIdleOnCommunal"
                )
                .that(!isIdleOnBouncer || !isCurrentSceneShade)
                .that(!isIdleOnShadeOverlay || !isIdleOnCommunal)
                .isTrue()

            assertWithMessage(
                    "isCurrentSceneBouncer cannot be true at the same time as isIdleOnCommunal"
                    "isIdleOnShadeScene cannot be true at the same time as isIdleOnShadeOverlay"
                )
                .that(!isIdleOnBouncer || !isIdleOnCommunal)
                .that(!isIdleOnShadeScene || !isIdleOnShadeOverlay)
                .isTrue()

            assertWithMessage(
                    "isCurrentSceneShade cannot be true at the same time as isIdleOnCommunal"
                    "isTransitioningToShadeScene cannot be true at the same time as " +
                        "isTransitioningToShadeOverlay"
                )
                .that(!isCurrentSceneShade || !isIdleOnCommunal)
                .that(!isTransitioningToShadeScene || !isTransitioningToShadeOverlay)
                .isTrue()

            assertWithMessage("isDeviceEntered cannot be true at the same time as isOnKeyguard")
                .that(!isDeviceEntered || !isOnKeyguard)
            assertWithMessage(
                    "isTransitioningToShadeScene cannot be true at the same time as " +
                        "isIdleOnShadeOverlay"
                )
                .that(!isTransitioningToShadeScene || !isIdleOnShadeOverlay)
                .isTrue()

            assertWithMessage(
                    "isDeviceEntered cannot be true at the same time as isCurrentSceneBouncer"
                    "isTransitioningToShadeOverlay cannot be true at the same time as " +
                        "isIdleOnShadeScene"
                )
                .that(!isTransitioningToShadeOverlay || !isIdleOnShadeScene)
                .isTrue()

            assertWithMessage("isDeviceEntered cannot be true at the same time as isIdleOnBouncer")
                .that(!isDeviceEntered || !isIdleOnBouncer)
                .isTrue()