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

Commit f3e10f8b authored by William Xiao's avatar William Xiao
Browse files

Don't stop or restart hub timeout when dreaming state changes

While we only want to actually close the hub if the timeout is
triggered while the user is dreaming, we don't want starting or
stopping dreaming to affect the timer as it isn't a user interaction
and happens underneath the hub.

This means that if the screen timeout is 2 minutes, opening the hub
over the lock screen, spending 1 minute idle, docking the device to
start dreaming, then waiting another minute, will result in the hub
closing due to the timeout.

Bug: 323247392
Fixed: 323247392
Test: atest CommunalSceneStartableTest
      also manually verified on device
Flag: ACONFIG com.android.systemui.communal_hub TEAMFOOD
Change-Id: I3c6639035f579226d334ce96040ec03a631076e0
parent e78b2da8
Loading
Loading
Loading
Loading
+39 −2
Original line number Diff line number Diff line
@@ -256,7 +256,7 @@ class CommunalSceneStartableTest : SysuiTestCase() {
        }

    @Test
    fun hubTimeout_whenDreaming() =
    fun hubTimeout_whenDreaming_goesToBlank() =
        with(kosmos) {
            testScope.runTest {
                // Device is dreaming and on communal.
@@ -273,7 +273,22 @@ class CommunalSceneStartableTest : SysuiTestCase() {
        }

    @Test
    fun hubTimeout_dreamStopped() =
    fun hubTimeout_notDreaming_staysOnCommunal() =
        with(kosmos) {
            testScope.runTest {
                // Device is not dreaming and on communal.
                fakeKeyguardRepository.setDreaming(false)
                communalInteractor.onSceneChanged(CommunalScenes.Communal)

                // Scene stays as Communal
                advanceTimeBy(SCREEN_TIMEOUT.milliseconds)
                val scene by collectLastValue(communalInteractor.desiredScene)
                assertThat(scene).isEqualTo(CommunalScenes.Communal)
            }
        }

    @Test
    fun hubTimeout_dreamStopped_staysOnCommunal() =
        with(kosmos) {
            testScope.runTest {
                // Device is dreaming and on communal.
@@ -295,6 +310,28 @@ class CommunalSceneStartableTest : SysuiTestCase() {
            }
        }

    @Test
    fun hubTimeout_dreamStartedHalfway_goesToCommunal() =
        with(kosmos) {
            testScope.runTest {
                // Device is on communal, but not dreaming.
                fakeKeyguardRepository.setDreaming(false)
                communalInteractor.onSceneChanged(CommunalScenes.Communal)

                val scene by collectLastValue(communalInteractor.desiredScene)
                assertThat(scene).isEqualTo(CommunalScenes.Communal)

                // Wait a bit, but not long enough to timeout, then start dreaming.
                advanceTimeBy((SCREEN_TIMEOUT / 2).milliseconds)
                fakeKeyguardRepository.setDreaming(true)
                assertThat(scene).isEqualTo(CommunalScenes.Communal)

                // Device times out after one screen timeout interval, dream doesn't reset timeout.
                advanceTimeBy((SCREEN_TIMEOUT / 2).milliseconds)
                assertThat(scene).isEqualTo(CommunalScenes.Blank)
            }
        }

    @Test
    fun hubTimeout_userActivityTriggered_resetsTimeout() =
        with(kosmos) {
+14 −8
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.util.kotlin.emitOnStart
import com.android.systemui.util.kotlin.sample
import com.android.systemui.util.settings.SettingsProxyExt.observerFlow
import com.android.systemui.util.settings.SystemSettings
import javax.inject.Inject
@@ -38,7 +39,6 @@ import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.launchIn
@@ -108,26 +108,32 @@ constructor(
        bgScope.launch {
            combine(
                    communalInteractor.desiredScene,
                    keyguardInteractor.isDreaming,
                    // Emit a value on start so the combine starts.
                    communalInteractor.userActivity.emitOnStart()
                ) { scene, isDreaming, _ ->
                ) { scene, _ ->
                    // Time out should run whenever we're dreaming and the hub is open, even if not
                    // docked.
                    scene == CommunalScenes.Communal && isDreaming
                    scene == CommunalScenes.Communal
                }
                // collectLatest cancels the previous action block when new values arrive, so any
                // mapLatest cancels the previous action block when new values arrive, so any
                // already running timeout gets cancelled when conditions change or user interaction
                // is detected.
                .collectLatest { shouldTimeout ->
                .mapLatest { shouldTimeout ->
                    if (!shouldTimeout) {
                        return@collectLatest
                        return@mapLatest false
                    }

                    delay(screenTimeout.milliseconds)
                    true
                }
                .sample(keyguardInteractor.isDreaming, ::Pair)
                .collect { (shouldTimeout, isDreaming) ->
                    if (isDreaming && shouldTimeout) {
                        communalInteractor.onSceneChanged(CommunalScenes.Blank)
                    }
                }
        }
    }

    private suspend fun determineSceneAfterTransition(
        lastStartedTransition: TransitionStep,