diff options
6 files changed, 113 insertions, 5 deletions
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index 80398cd2544d..df4407680cee 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -857,6 +857,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" description: "do not modify notification shade when handling bouncer expansion." diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalDreamStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalDreamStartableTest.kt index def63ec5b171..bfed33c54019 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalDreamStartableTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalDreamStartableTest.kt @@ -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, ) @@ -84,6 +89,32 @@ class CommunalDreamStartableTest : SysuiTestCase() { } @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 { keyguardRepository.setDreaming(false) diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt index 9e7fb4e73a29..153b7aa3e522 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt @@ -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 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 6b4cf79d59b1..06c83962df6b 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 @@ -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]. * diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt index e51ba8308a08..2a7178f5e24f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromOccludedTransitionInteractor.kt @@ -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 diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt index 687e91ad0b81..c3a806ba8d43 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt @@ -17,6 +17,7 @@ package com.android.systemui.keyguard.domain.interactor import android.app.StatusBarManager +import android.platform.test.annotations.EnableFlags import android.platform.test.flag.junit.FlagsParameterization import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState @@ -1424,6 +1425,39 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest } @Test + @BrokenWithSceneContainer(339465026) + @EnableFlags(Flags.FLAG_RESTART_DREAM_ON_UNOCCLUDE) + fun dreamingToOccludedToDreaming() = + testScope.runTest { + // GIVEN a device on lockscreen + keyguardRepository.setKeyguardShowing(true) + runCurrent() + + // Given a device that is dreaming + keyguardRepository.setDreaming(true) + + // GIVEN a prior transition has run to OCCLUDED + runTransitionAndSetWakefulness(KeyguardState.DREAMING, KeyguardState.OCCLUDED) + keyguardRepository.setKeyguardOccluded(true) + runCurrent() + + // WHEN occlusion ends + keyguardRepository.setKeyguardOccluded(false) + runCurrent() + + // THEN a transition to GLANCEABLE_HUB should occur + assertThat(transitionRepository) + .startedTransition( + ownerName = FromOccludedTransitionInteractor::class.simpleName, + from = KeyguardState.OCCLUDED, + to = KeyguardState.DREAMING, + animatorAssertion = { it.isNotNull() }, + ) + + coroutineContext.cancelChildren() + } + + @Test fun dreamingToPrimaryBouncer() = testScope.runTest { // GIVEN a prior transition has run to DREAMING |