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

Commit 9ac63b28 authored by Lucas Silva's avatar Lucas Silva
Browse files

Fix keyguard state when primary bouncer shown on hub while dreaming

If the primary bouncer is shown over the glanceable hub while dreaming,
we currently erronously transition back to occluded when the bouncer is
closed. This is because when in a dream state, the keyguard is occluded.
This fix adds a check to ensure we are occluded but not dreaming.

Test: atest KeyguardTransitionScenarioesTest
Bug: 325102385
Flag: ACONFIG com.android.systemui.communal_hub STAGING
Change-Id: I7420646cf513e830bf3cceb2a7798200c4a2d096
parent 2794bccf
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -134,8 +134,9 @@ constructor(
                    powerInteractor.isAwake,
                    startedKeyguardTransitionStep,
                    keyguardInteractor.isKeyguardOccluded,
                    keyguardInteractor.isDreaming,
                    keyguardInteractor.isActiveDreamLockscreenHosted,
                    communalInteractor.isIdleOnCommunal
                    communalInteractor.isIdleOnCommunal,
                )
                .collect {
                    (
@@ -143,6 +144,7 @@ constructor(
                        isAwake,
                        lastStartedTransitionStep,
                        occluded,
                        isDreaming,
                        isActiveDreamLockscreenHosted,
                        isIdleOnCommunal) ->
                    if (
@@ -152,10 +154,12 @@ constructor(
                            !isActiveDreamLockscreenHosted
                    ) {
                        val toState =
                            if (occluded) {
                            if (occluded && !isDreaming) {
                                KeyguardState.OCCLUDED
                            } else if (isIdleOnCommunal) {
                                KeyguardState.GLANCEABLE_HUB
                            } else if (isDreaming) {
                                KeyguardState.DREAMING
                            } else {
                                KeyguardState.LOCKSCREEN
                            }
+23 −0
Original line number Diff line number Diff line
@@ -245,6 +245,29 @@ fun <T> Flow<T>.throttle(periodMs: Long, clock: SystemClock = SystemClockImpl())
        }
    }

inline fun <T1, T2, T3, T4, T5, T6, R> combine(
        flow: Flow<T1>,
        flow2: Flow<T2>,
        flow3: Flow<T3>,
        flow4: Flow<T4>,
        flow5: Flow<T5>,
        flow6: Flow<T6>,
        crossinline transform: suspend (T1, T2, T3, T4, T5, T6) -> R
): Flow<R> {
    return kotlinx.coroutines.flow.combine(flow, flow2, flow3, flow4, flow5, flow6) {
        args: Array<*> ->
        @Suppress("UNCHECKED_CAST")
        transform(
                args[0] as T1,
                args[1] as T2,
                args[2] as T3,
                args[3] as T4,
                args[4] as T5,
                args[5] as T6,
        )
    }
}

inline fun <T1, T2, T3, T4, T5, T6, T7, R> combine(
    flow: Flow<T1>,
    flow2: Flow<T2>,
+39 −0
Original line number Diff line number Diff line
@@ -36,6 +36,17 @@ class Utils {
        fun <A, B, C, D, E, F> toSextuple(a: A, bcdef: Quint<B, C, D, E, F>) =
            Sextuple(a, bcdef.first, bcdef.second, bcdef.third, bcdef.fourth, bcdef.fifth)

        fun <A, B, C, D, E, F, G> toSeptuple(a: A, bcdefg: Sextuple<B, C, D, E, F, G>) =
            Septuple(
                a,
                bcdefg.first,
                bcdefg.second,
                bcdefg.third,
                bcdefg.fourth,
                bcdefg.fifth,
                bcdefg.sixth
            )

        /**
         * Samples the provided flows, emitting a tuple of the original flow's value as well as each
         * of the combined flows' values.
@@ -90,6 +101,24 @@ class Utils {
        ): Flow<Sextuple<A, B, C, D, E, F>> {
            return this.sample(combine(b, c, d, e, f, ::Quint), ::toSextuple)
        }

        /**
         * Samples the provided flows, emitting a tuple of the original flow's value as well as each
         * of the combined flows' values.
         *
         * Flow<A>.sample(Flow<B>, Flow<C>, Flow<D>, Flow<E>, Flow<F>, Flow<G>) -> (A, B, C, D, E,
         * F, G)
         */
        fun <A, B, C, D, E, F, G> Flow<A>.sample(
            b: Flow<B>,
            c: Flow<C>,
            d: Flow<D>,
            e: Flow<E>,
            f: Flow<F>,
            g: Flow<G>,
        ): Flow<Septuple<A, B, C, D, E, F, G>> {
            return this.sample(combine(b, c, d, e, f, g, ::Sextuple), ::toSeptuple)
        }
    }
}

@@ -112,6 +141,16 @@ data class Sextuple<A, B, C, D, E, F>(
    val sixth: F,
)

data class Septuple<A, B, C, D, E, F, G>(
    val first: A,
    val second: B,
    val third: C,
    val fourth: D,
    val fifth: E,
    val sixth: F,
    val seventh: G,
)

fun Int.toPx(context: Context): Int {
    return (this * context.resources.displayMetrics.density).toInt()
}
+35 −1
Original line number Diff line number Diff line
@@ -57,7 +57,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -1096,6 +1095,41 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
            coroutineContext.cancelChildren()
        }

    @Test
    fun primaryBouncerToGlanceableHubWhileDreaming() =
        testScope.runTest {
            // GIVEN a prior transition has run to PRIMARY_BOUNCER
            bouncerRepository.setPrimaryShow(true)
            runTransitionAndSetWakefulness(KeyguardState.LOCKSCREEN, KeyguardState.PRIMARY_BOUNCER)

            // GIVEN that we are dreaming and occluded
            keyguardRepository.setDreaming(true)
            keyguardRepository.setKeyguardOccluded(true)

            // GIVEN the device is idle on the glanceable hub
            val idleTransitionState =
                MutableStateFlow<ObservableCommunalTransitionState>(
                    ObservableCommunalTransitionState.Idle(CommunalSceneKey.Communal)
                )
            communalInteractor.setTransitionState(idleTransitionState)
            runCurrent()

            // WHEN the primaryBouncer stops showing
            bouncerRepository.setPrimaryShow(false)
            runCurrent()

            // THEN a transition to LOCKSCREEN should occur
            assertThat(transitionRepository)
                .startedTransition(
                    ownerName = FromPrimaryBouncerTransitionInteractor::class.simpleName,
                    from = KeyguardState.PRIMARY_BOUNCER,
                    to = KeyguardState.GLANCEABLE_HUB,
                    animatorAssertion = { it.isNotNull() },
                )

            coroutineContext.cancelChildren()
        }

    @Test
    fun primaryBouncerToDreamingLockscreenHosted() =
        testScope.runTest {