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

Commit a320f566 authored by Bryce Lee's avatar Bryce Lee
Browse files

Return to dream from occlusion.

This changelist tracks the dream state when the lockscreen is occluded
and then returns to that state on unocclusion.

Test: atest KeyguardTransitionScenariosTest#dreamingToOccludedToDreaming
Test: atest CommunalDreamStartableTest#CommunalDreamStartableTest#restartDreamingWhenTransitioningFromDreamingToOccludedToDreaming
Fixes: 338051457
Flag: ACONFIG com.android.systemui.restart_dream_on_unocclude disabled
Change-Id: If075685b466aa4a4ccfd77a757a7d715ccf5d3e3
parent 281bd529
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -856,6 +856,16 @@ flag {
  }
}

flag {
   name: "restart_dream_on_unocclude"
   namespace: "systemui"
   description: "re-enters dreaming upon unocclude when dreaming when originally occluding"
   bug: "338051457"
   metadata {
     purpose: PURPOSE_BUGFIX
   }
}

flag {
  name: "communal_bouncer_do_not_modify_plugin_open"
  namespace: "systemui"
+31 −0
Original line number Diff line number Diff line
@@ -16,12 +16,16 @@

package com.android.systemui.communal

import android.platform.test.annotations.EnableFlags
import android.service.dream.dreamManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.domain.interactor.communalInteractor
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.keyguardRepository
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -62,6 +66,7 @@ class CommunalDreamStartableTest : SysuiTestCase() {
                    powerInteractor = kosmos.powerInteractor,
                    keyguardInteractor = kosmos.keyguardInteractor,
                    keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor,
                    communalInteractor = kosmos.communalInteractor,
                    dreamManager = dreamManager,
                    bgScope = kosmos.applicationCoroutineScope,
                )
@@ -83,6 +88,32 @@ class CommunalDreamStartableTest : SysuiTestCase() {
            verify(dreamManager).startDream()
        }

    @Test
    @EnableFlags(Flags.FLAG_RESTART_DREAM_ON_UNOCCLUDE)
    fun restartDreamingWhenTransitioningFromDreamingToOccludedToDreaming() =
        testScope.runTest {
            keyguardRepository.setDreaming(false)
            powerRepository.setScreenPowerState(ScreenPowerState.SCREEN_ON)
            whenever(dreamManager.canStartDreaming(/* isScreenOn = */ true)).thenReturn(true)
            runCurrent()

            verify(dreamManager, never()).startDream()

            kosmos.fakeKeyguardRepository.setKeyguardOccluded(true)
            kosmos.fakeKeyguardRepository.setDreaming(true)
            runCurrent()

            transition(from = KeyguardState.DREAMING, to = KeyguardState.OCCLUDED)
            kosmos.fakeKeyguardRepository.setKeyguardOccluded(false)
            kosmos.fakeKeyguardRepository.setDreaming(false)
            runCurrent()

            transition(from = KeyguardState.OCCLUDED, to = KeyguardState.DREAMING)
            runCurrent()

            verify(dreamManager).startDream()
        }

    @Test
    fun shouldNotStartDreamWhenIneligibleToDream() =
        testScope.runTest {
+18 −0
Original line number Diff line number Diff line
@@ -20,6 +20,8 @@ import android.annotation.SuppressLint
import android.app.DreamManager
import com.android.systemui.CoreStartable
import com.android.systemui.Flags.communalHub
import com.android.systemui.Flags.restartDreamOnUnocclude
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
@@ -27,8 +29,10 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.util.kotlin.Utils.Companion.sample
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach

@@ -43,6 +47,7 @@ constructor(
    private val powerInteractor: PowerInteractor,
    private val keyguardInteractor: KeyguardInteractor,
    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
    private val communalInteractor: CommunalInteractor,
    private val dreamManager: DreamManager,
    @Background private val bgScope: CoroutineScope,
) : CoreStartable {
@@ -52,6 +57,19 @@ constructor(
            return
        }

        // Return to dream from occluded when not already dreaming.
        if (restartDreamOnUnocclude()) {
            keyguardTransitionInteractor.startedKeyguardTransitionStep
                .sample(keyguardInteractor.isDreaming, ::Pair)
                .filter {
                    it.first.from == KeyguardState.OCCLUDED &&
                        it.first.to == KeyguardState.DREAMING &&
                        !it.second
                }
                .onEach { dreamManager.startDream() }
                .launchIn(bgScope)
        }

        // Restart the dream underneath the hub in order to support the ability to swipe
        // away the hub to enter the dream.
        keyguardTransitionInteractor.finishedKeyguardState
+7 −0
Original line number Diff line number Diff line
@@ -163,6 +163,13 @@ constructor(
                initialValue = false,
            )

    /** Whether to start dreaming when returning from occluded */
    val dreamFromOccluded: Flow<Boolean> =
        keyguardTransitionInteractor
            .transitionStepsToState(KeyguardState.OCCLUDED)
            .map { it.from == KeyguardState.DREAMING }
            .stateIn(scope = applicationScope, SharingStarted.Eagerly, false)

    /**
     * Target scene as requested by the underlying [SceneTransitionLayout] or through [changeScene].
     *
+13 −5
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.systemui.keyguard.domain.interactor

import android.animation.ValueAnimator
import com.android.app.animation.Interpolators
import com.android.systemui.Flags.restartDreamOnUnocclude
import com.android.systemui.communal.domain.interactor.CommunalInteractor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
@@ -90,12 +91,15 @@ constructor(
                    .sample(
                        communalInteractor.isIdleOnCommunal,
                        communalInteractor.showCommunalFromOccluded,
                        communalInteractor.dreamFromOccluded
                    )
                    .collect { (_, isIdleOnCommunal, showCommunalFromOccluded) ->
                    .collect { (_, isIdleOnCommunal, showCommunalFromOccluded, dreamFromOccluded) ->
                        // Occlusion signals come from the framework, and should interrupt any
                        // existing transition
                        val to =
                            if (isIdleOnCommunal || showCommunalFromOccluded) {
                            if (restartDreamOnUnocclude() && dreamFromOccluded) {
                                KeyguardState.DREAMING
                            } else if (isIdleOnCommunal || showCommunalFromOccluded) {
                                KeyguardState.GLANCEABLE_HUB
                            } else {
                                KeyguardState.LOCKSCREEN
@@ -110,15 +114,19 @@ constructor(
                        keyguardInteractor.isKeyguardShowing,
                        communalInteractor.isIdleOnCommunal,
                        communalInteractor.showCommunalFromOccluded,
                        communalInteractor.dreamFromOccluded,
                    )
                    .filterRelevantKeyguardStateAnd { (isOccluded, isShowing, _, _) ->
                    .filterRelevantKeyguardStateAnd { (isOccluded, isShowing, _, _, _) ->
                        !isOccluded && isShowing
                    }
                    .collect { (_, _, isIdleOnCommunal, showCommunalFromOccluded) ->
                    .collect { (_, _, isIdleOnCommunal, showCommunalFromOccluded, dreamFromOccluded)
                        ->
                        // Occlusion signals come from the framework, and should interrupt any
                        // existing transition
                        val to =
                            if (isIdleOnCommunal || showCommunalFromOccluded) {
                            if (restartDreamOnUnocclude() && dreamFromOccluded) {
                                KeyguardState.DREAMING
                            } else if (isIdleOnCommunal || showCommunalFromOccluded) {
                                KeyguardState.GLANCEABLE_HUB
                            } else {
                                KeyguardState.LOCKSCREEN
Loading