diff options
| author | 2024-09-23 16:44:58 +0000 | |
|---|---|---|
| committer | 2024-09-23 16:44:58 +0000 | |
| commit | 63108dfb0b66d88be54bd86d2e98984a9ab2141c (patch) | |
| tree | 7753ee8ca1a9fda2d21c8ecbdcb22dd248663233 | |
| parent | 7e0204e0a3db8d7c9746ddca0c9c5d5098039a23 (diff) | |
| parent | b0accc8eba54b5b78fd04f126fdf262399dec4b7 (diff) | |
Merge changes Ida1ee588,Ib5a356ad into main
* changes:
Fix misc issues for transition to hub when turning screen on
Fix glanceable hub not showing when waking from doze
16 files changed, 277 insertions, 64 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt index 2ba4bf930f3f..e25c1a71a5a6 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractorTest.kt @@ -34,8 +34,6 @@ import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository import com.android.systemui.keyguard.data.repository.realKeyguardTransitionRepository -import com.android.systemui.keyguard.shared.model.DozeStateModel -import com.android.systemui.keyguard.shared.model.DozeTransitionModel import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB @@ -50,8 +48,6 @@ import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING import com.android.systemui.keyguard.shared.model.TransitionState.STARTED import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.kosmos.testScope -import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest -import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlin.time.Duration.Companion.seconds @@ -220,15 +216,11 @@ class CommunalSceneTransitionInteractorTest : SysuiTestCase() { @Test fun transition_from_hub_end_in_dream() = testScope.runTest { - // Device is dreaming and not dozing. - kosmos.powerInteractor.setAwakeForTest() - kosmos.fakeKeyguardRepository.setDozeTransitionModel( - DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH) - ) + // Device is dreaming and occluded. kosmos.fakeKeyguardRepository.setKeyguardOccluded(true) kosmos.fakeKeyguardRepository.setDreaming(true) kosmos.fakeKeyguardRepository.setDreamingWithOverlay(true) - advanceTimeBy(600L) + runCurrent() sceneTransitions.value = hubToBlank @@ -663,7 +655,7 @@ class CommunalSceneTransitionInteractorTest : SysuiTestCase() { from = LOCKSCREEN, to = OCCLUDED, animator = null, - modeOnCanceled = TransitionModeOnCanceled.RESET + modeOnCanceled = TransitionModeOnCanceled.RESET, ) ) @@ -750,7 +742,7 @@ class CommunalSceneTransitionInteractorTest : SysuiTestCase() { from = LOCKSCREEN, to = OCCLUDED, animator = null, - modeOnCanceled = TransitionModeOnCanceled.RESET + modeOnCanceled = TransitionModeOnCanceled.RESET, ) ) @@ -852,8 +844,8 @@ class CommunalSceneTransitionInteractorTest : SysuiTestCase() { to = ALTERNATE_BOUNCER, animator = null, ownerName = "external", - modeOnCanceled = TransitionModeOnCanceled.RESET - ), + modeOnCanceled = TransitionModeOnCanceled.RESET, + ) ) val allSteps by collectValues(keyguardTransitionRepository.transitions) diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt index fac931273ac7..ff0a4a16fe2a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt @@ -26,8 +26,10 @@ import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.Flags.FLAG_COMMUNAL_HUB import com.android.systemui.Flags.FLAG_COMMUNAL_SCENE_KTF_REFACTOR import com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR +import com.android.systemui.Flags.FLAG_SCENE_CONTAINER import com.android.systemui.SysuiTestCase import com.android.systemui.communal.data.repository.FakeCommunalSceneRepository +import com.android.systemui.communal.data.repository.communalSceneRepository import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository import com.android.systemui.communal.domain.interactor.setCommunalAvailable import com.android.systemui.communal.shared.model.CommunalScenes @@ -50,10 +52,12 @@ import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.se import com.android.systemui.power.domain.interactor.powerInteractor import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.testKosmos +import com.google.common.truth.Truth import junit.framework.Assert.assertEquals import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import org.junit.Before @@ -219,6 +223,28 @@ class FromDozingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiT } @Test + @DisableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR, FLAG_SCENE_CONTAINER) + @EnableFlags(FLAG_COMMUNAL_SCENE_KTF_REFACTOR) + fun testTransitionToGlanceableHub_onWakeup_ifAvailable() = + testScope.runTest { + // Hub is available. + whenever(kosmos.dreamManager.canStartDreaming(anyBoolean())).thenReturn(true) + kosmos.setCommunalAvailable(true) + runCurrent() + + // Device turns on. + powerInteractor.setAwakeForTest() + advanceTimeBy(50L) + runCurrent() + + // We transition to the hub when waking up. + Truth.assertThat(kosmos.communalSceneRepository.currentScene.value) + .isEqualTo(CommunalScenes.Communal) + // No transitions are directly started by this interactor. + assertThat(transitionRepository).noTransitionsStarted() + } + + @Test @EnableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR) fun testTransitionToOccluded_onWakeup_whenOccludingActivityOnTop() = testScope.runTest { diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt index 638c957c9fa7..a08fbbf75805 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt @@ -16,12 +16,19 @@ package com.android.systemui.keyguard.domain.interactor +import android.platform.test.annotations.DisableFlags import android.platform.test.annotations.EnableFlags -import androidx.test.ext.junit.runners.AndroidJUnit4 +import android.platform.test.flag.junit.FlagsParameterization +import android.service.dream.dreamManager import androidx.test.filters.SmallTest import com.android.systemui.Flags +import com.android.systemui.Flags.FLAG_COMMUNAL_SCENE_KTF_REFACTOR import com.android.systemui.SysuiTestCase import com.android.systemui.bouncer.data.repository.fakeKeyguardBouncerRepository +import com.android.systemui.communal.data.repository.communalSceneRepository +import com.android.systemui.communal.domain.interactor.setCommunalAvailable +import com.android.systemui.communal.shared.model.CommunalScenes +import com.android.systemui.flags.andSceneContainer import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository @@ -36,6 +43,7 @@ import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInterac import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest @@ -43,26 +51,52 @@ import org.junit.Before import org.junit.Ignore import org.junit.Test import org.junit.runner.RunWith +import org.mockito.Mockito.anyBoolean import org.mockito.Mockito.reset import org.mockito.Mockito.spy +import org.mockito.kotlin.whenever +import platform.test.runner.parameterized.ParameterizedAndroidJunit4 +import platform.test.runner.parameterized.Parameters @OptIn(ExperimentalCoroutinesApi::class) @SmallTest -@RunWith(AndroidJUnit4::class) -class FromDreamingTransitionInteractorTest : SysuiTestCase() { +@RunWith(ParameterizedAndroidJunit4::class) +class FromDreamingTransitionInteractorTest(flags: FlagsParameterization?) : SysuiTestCase() { + companion object { + @JvmStatic + @Parameters(name = "{0}") + fun getParams(): List<FlagsParameterization> { + return FlagsParameterization.allCombinationsOf(FLAG_COMMUNAL_SCENE_KTF_REFACTOR) + .andSceneContainer() + } + } + + init { + mSetFlagsRule.setFlagsParameterization(flags!!) + } + private val kosmos = testKosmos().apply { this.fakeKeyguardTransitionRepository = spy(FakeKeyguardTransitionRepository()) } private val testScope = kosmos.testScope - private val underTest = kosmos.fromDreamingTransitionInteractor + private val underTest by lazy { kosmos.fromDreamingTransitionInteractor } private val powerInteractor = kosmos.powerInteractor private val transitionRepository = kosmos.fakeKeyguardTransitionRepository @Before fun setup() { + runBlocking { + transitionRepository.sendTransitionSteps( + from = KeyguardState.LOCKSCREEN, + to = KeyguardState.DREAMING, + testScope, + ) + reset(transitionRepository) + kosmos.setCommunalAvailable(true) + } underTest.start() } @@ -86,10 +120,7 @@ class FromDreamingTransitionInteractorTest : SysuiTestCase() { runCurrent() assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.DREAMING, - to = KeyguardState.OCCLUDED, - ) + .startedTransition(from = KeyguardState.DREAMING, to = KeyguardState.OCCLUDED) } @Test @@ -126,7 +157,7 @@ class FromDreamingTransitionInteractorTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.DREAMING, - testScope + testScope, ) kosmos.fakeKeyguardRepository.setBiometricUnlockState(BiometricUnlockMode.NONE) @@ -139,10 +170,7 @@ class FromDreamingTransitionInteractorTest : SysuiTestCase() { advanceTimeBy(60L) assertThat(transitionRepository) - .startedTransition( - from = KeyguardState.DREAMING, - to = KeyguardState.LOCKSCREEN, - ) + .startedTransition(from = KeyguardState.DREAMING, to = KeyguardState.LOCKSCREEN) } @Test @@ -164,4 +192,25 @@ class FromDreamingTransitionInteractorTest : SysuiTestCase() { to = KeyguardState.ALTERNATE_BOUNCER, ) } + + @Test + @EnableFlags(FLAG_COMMUNAL_SCENE_KTF_REFACTOR) + @DisableFlags(Flags.FLAG_SCENE_CONTAINER) + fun testTransitionToGlanceableHubOnWake() = + testScope.runTest { + whenever(kosmos.dreamManager.canStartDreaming(anyBoolean())).thenReturn(true) + kosmos.setCommunalAvailable(true) + runCurrent() + + // Device wakes up. + powerInteractor.setAwakeForTest() + advanceTimeBy(150L) + runCurrent() + + // We transition to the hub when waking up. + assertThat(kosmos.communalSceneRepository.currentScene.value) + .isEqualTo(CommunalScenes.Communal) + // No transitions are directly started by this interactor. + assertThat(transitionRepository).noTransitionsStarted() + } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt index 77106aec2fb4..a617484d7d94 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt @@ -1465,10 +1465,8 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest // WHEN the keyguard is occluded and device wakes up and is no longer dreaming keyguardRepository.setDreaming(false) - testScheduler.advanceTimeBy(150) // The dreaming signal is debounced. - runCurrent() keyguardRepository.setKeyguardOccluded(true) - powerInteractor.setAwakeForTest() + testScheduler.advanceTimeBy(150) // The dreaming and occluded signals are debounced. runCurrent() // THEN a transition to OCCLUDED should occur @@ -2059,12 +2057,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest fun glanceableHubToOccluded_communalKtfRefactor() = testScope.runTest { // GIVEN device is not dreaming - powerInteractor.setAwakeForTest() keyguardRepository.setDreaming(false) - keyguardRepository.setDozeTransitionModel( - DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH) - ) - advanceTimeBy(600.milliseconds) // GIVEN a prior transition has run to GLANCEABLE_HUB communalSceneInteractor.changeScene(CommunalScenes.Communal, "test") @@ -2073,6 +2066,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest // WHEN the keyguard is occluded keyguardRepository.setKeyguardOccluded(true) + advanceTimeBy(200.milliseconds) runCurrent() assertThat(transitionRepository) @@ -2218,6 +2212,7 @@ class KeyguardTransitionScenariosTest(flags: FlagsParameterization?) : SysuiTest advanceTimeBy(10.milliseconds) keyguardRepository.setKeyguardOccluded(true) advanceTimeBy(200.milliseconds) + runCurrent() assertThat(transitionRepository) .startedTransition( diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt index 425f16ec7da1..4adf6936b5ab 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelTest.kt @@ -44,6 +44,7 @@ import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.shared.model.BurnInModel import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER import com.android.systemui.keyguard.shared.model.KeyguardState.AOD +import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING import com.android.systemui.keyguard.shared.model.KeyguardState.GLANCEABLE_HUB import com.android.systemui.keyguard.shared.model.KeyguardState.GONE @@ -363,6 +364,69 @@ class SharedNotificationContainerViewModelTest(flags: FlagsParameterization) : S showLockscreen() assertThat(alpha).isEqualTo(1f) + // Go to dozing + keyguardTransitionRepository.sendTransitionSteps( + from = LOCKSCREEN, + to = DOZING, + testScope, + ) + assertThat(alpha).isEqualTo(1f) + + // Start transitioning to glanceable hub + val progress = 0.6f + kosmos.setTransition( + sceneTransition = Transition(from = Scenes.Lockscreen, to = Scenes.Communal), + stateTransition = + TransitionStep( + transitionState = TransitionState.STARTED, + from = DOZING, + to = GLANCEABLE_HUB, + value = 0f, + ), + ) + runCurrent() + kosmos.setTransition( + sceneTransition = + Transition( + from = Scenes.Lockscreen, + to = Scenes.Communal, + progress = flowOf(progress), + ), + stateTransition = + TransitionStep( + transitionState = TransitionState.RUNNING, + from = DOZING, + to = GLANCEABLE_HUB, + value = progress, + ), + ) + runCurrent() + // Keep notifications hidden during the transition from dream to hub + assertThat(alpha).isEqualTo(0) + + // Finish transition to glanceable hub + kosmos.setTransition( + sceneTransition = Idle(Scenes.Communal), + stateTransition = + TransitionStep( + transitionState = TransitionState.FINISHED, + from = DOZING, + to = GLANCEABLE_HUB, + value = 1f, + ), + ) + assertThat(alpha).isEqualTo(0f) + } + + @Test + fun glanceableHubAlpha_dozingToHub() = + testScope.runTest { + val alpha by collectLastValue(underTest.glanceableHubAlpha) + + // Start on lockscreen, notifications should be unhidden. + showLockscreen() + assertThat(alpha).isEqualTo(1f) + // Transition to dream, notifications should be hidden so that transition // from dream->hub doesn't cause notification flicker. showDream() diff --git a/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt b/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt index 04393feaae37..1bd541e1088a 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/CommunalDreamStartable.kt @@ -65,7 +65,9 @@ constructor( keyguardTransitionInteractor .transitionValue(Scenes.Communal, KeyguardState.GLANCEABLE_HUB) .map { it == 1f }, - not(keyguardInteractor.isDreaming), + // Use isDreamingAny because isDreaming is false in doze and doesn't change again + // when the screen turns on, which causes the dream to not start underneath the hub. + not(keyguardInteractor.isDreamingAny), // TODO(b/362830856): Remove this workaround. keyguardInteractor.isKeyguardShowing, not(communalSceneInteractor.isLaunchingWidget), diff --git a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt index c7538bb4f696..905eda14e2d5 100644 --- a/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/communal/domain/interactor/CommunalSceneTransitionInteractor.kt @@ -87,7 +87,9 @@ constructor( */ private val nextKeyguardStateInternal = combine( - keyguardInteractor.isAbleToDream, + // Don't use delayed dreaming signal as otherwise we might go to occluded or lock + // screen when closing hub if dream just started under the hub. + keyguardInteractor.isDreamingWithOverlay, keyguardInteractor.isKeyguardOccluded, keyguardInteractor.isKeyguardGoingAway, keyguardInteractor.isKeyguardShowing, @@ -156,7 +158,7 @@ constructor( private suspend fun handleIdle( prevTransition: ObservableTransitionState, - idle: ObservableTransitionState.Idle + idle: ObservableTransitionState.Idle, ) { if ( prevTransition is ObservableTransitionState.Transition && @@ -186,7 +188,7 @@ constructor( internalTransitionInteractor.updateTransition( currentTransitionId!!, 1f, - TransitionState.FINISHED + TransitionState.FINISHED, ) resetTransitionData() } @@ -204,7 +206,7 @@ constructor( internalTransitionInteractor.updateTransition( currentTransitionId!!, 1f, - TransitionState.FINISHED + TransitionState.FINISHED, ) resetTransitionData() } @@ -217,7 +219,7 @@ constructor( private suspend fun handleTransition( prevTransition: ObservableTransitionState, - transition: ObservableTransitionState.Transition + transition: ObservableTransitionState.Transition, ) { if ( prevTransition.isTransitioning(from = transition.fromContent, to = transition.toContent) @@ -295,7 +297,7 @@ constructor( internalTransitionInteractor.updateTransition( currentTransitionId!!, progress.coerceIn(0f, 1f), - TransitionState.RUNNING + TransitionState.RUNNING, ) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt index b0820a747e17..8c7fe5f87a3f 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt @@ -150,7 +150,9 @@ constructor( if (!SceneContainerFlag.isEnabled) { startTransitionTo(KeyguardState.GLANCEABLE_HUB) } - } else if (isCommunalAvailable && dreamManager.canStartDreaming(true)) { + } else if (isCommunalAvailable && dreamManager.canStartDreaming(false)) { + // Using false for isScreenOn as canStartDreaming returns false if any + // dream, including doze, is active. // This case handles tapping the power button to transition through // dream -> off -> hub. if (!SceneContainerFlag.isEnabled) { diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt index 2434b29c0cdd..9a0a85823929 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt @@ -17,9 +17,12 @@ package com.android.systemui.keyguard.domain.interactor import android.animation.ValueAnimator +import android.annotation.SuppressLint +import android.app.DreamManager import com.android.app.animation.Interpolators import com.android.app.tracing.coroutines.launch import com.android.systemui.Flags.communalSceneKtfRefactor +import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.domain.interactor.CommunalSettingsInteractor import com.android.systemui.communal.shared.model.CommunalScenes @@ -60,10 +63,12 @@ constructor( @Main mainDispatcher: CoroutineDispatcher, keyguardInteractor: KeyguardInteractor, private val glanceableHubTransitions: GlanceableHubTransitions, + private val communalInteractor: CommunalInteractor, private val communalSceneInteractor: CommunalSceneInteractor, private val communalSettingsInteractor: CommunalSettingsInteractor, powerInteractor: PowerInteractor, keyguardOcclusionInteractor: KeyguardOcclusionInteractor, + private val dreamManager: DreamManager, private val deviceEntryInteractor: DeviceEntryInteractor, ) : TransitionInteractor( @@ -76,6 +81,7 @@ constructor( keyguardInteractor = keyguardInteractor, ) { + @SuppressLint("MissingPermission") override fun start() { listenForDreamingToAlternateBouncer() listenForDreamingToOccluded() @@ -86,6 +92,8 @@ constructor( listenForTransitionToCamera(scope, keyguardInteractor) if (!communalSceneKtfRefactor()) { listenForDreamingToGlanceableHub() + } else { + listenForDreamingToGlanceableHubFromPowerButton() } listenForDreamingToPrimaryBouncer() } @@ -112,6 +120,34 @@ constructor( } } + /** + * Normally when pressing power button from the dream, the devices goes from DREAMING to DOZING, + * then [FromDozingTransitionInteractor] handles the transition to GLANCEABLE_HUB. However if + * the power button is pressed quickly, we may need to go directly from DREAMING to + * GLANCEABLE_HUB as the transition to DOZING has not occurred yet. + */ + @SuppressLint("MissingPermission") + private fun listenForDreamingToGlanceableHubFromPowerButton() { + if (!communalSettingsInteractor.isCommunalFlagEnabled()) return + if (SceneContainerFlag.isEnabled) return + scope.launch { + powerInteractor.isAwake + .debounce(50L) + .filterRelevantKeyguardStateAnd { isAwake -> isAwake } + .sample(communalInteractor.isCommunalAvailable) + .collect { isCommunalAvailable -> + if (isCommunalAvailable && dreamManager.canStartDreaming(false)) { + // This case handles tapping the power button to transition through + // dream -> off -> hub. + communalSceneInteractor.snapToScene( + newScene = CommunalScenes.Communal, + loggingReason = "from dreaming to hub", + ) + } + } + } + } + private fun listenForDreamingToPrimaryBouncer() { // TODO(b/336576536): Check if adaptation for scene framework is needed if (SceneContainerFlag.isEnabled) return @@ -144,7 +180,7 @@ constructor( } else { startTransitionTo( KeyguardState.LOCKSCREEN, - ownerReason = "Dream has ended and device is awake" + ownerReason = "Dream has ended and device is awake", ) } } @@ -158,15 +194,14 @@ constructor( scope.launch { combine( keyguardInteractor.isKeyguardOccluded, - keyguardInteractor.isAbleToDream - // Debounce the dreaming signal since there is a race condition between - // the occluded and dreaming signals. We therefore add a small delay - // to give enough time for occluded to flip to false when the dream - // ends, to avoid transitioning to OCCLUDED erroneously when exiting - // the dream. - .debounce(100.milliseconds), - ::Pair + keyguardInteractor.isDreaming, + ::Pair, ) + // Debounce signals since there is a race condition between the occluded and + // dreaming signals when starting or stopping dreaming. We therefore add a small + // delay to give enough time for occluded to flip to false when the dream + // ends, to avoid transitioning to OCCLUDED erroneously when exiting the dream. + .debounce(100.milliseconds) .filterRelevantKeyguardStateAnd { (isOccluded, isDreaming) -> isOccluded && !isDreaming } @@ -194,12 +229,12 @@ constructor( if (dismissable) { startTransitionTo( KeyguardState.GONE, - ownerReason = "No longer dreaming; dismissable" + ownerReason = "No longer dreaming; dismissable", ) } else { startTransitionTo( KeyguardState.LOCKSCREEN, - ownerReason = "No longer dreaming" + ownerReason = "No longer dreaming", ) } } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt index 7759298cb32a..6b6a3dce630a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromGlanceableHubTransitionInteractor.kt @@ -202,15 +202,15 @@ constructor( scope.launch { combine( keyguardInteractor.isKeyguardOccluded, - keyguardInteractor.isAbleToDream - // Debounce the dreaming signal since there is a race condition between - // the occluded and dreaming signals. We therefore add a small delay - // to give enough time for occluded to flip to false when the dream - // ends, to avoid transitioning to OCCLUDED erroneously when exiting - // the dream. - .debounce(100.milliseconds), + keyguardInteractor.isDreaming, ::Pair, ) + // Debounce signals since there is a race condition between the occluded and + // dreaming signals when starting or stopping dreaming. We therefore add a small + // delay to give enough time for occluded to flip to false when the dream + // ends, to avoid transitioning to OCCLUDED erroneously when exiting the dream + // or when the dream starts underneath the hub. + .debounce(200.milliseconds) .sampleFilter( // When launching activities from widgets on the hub, we have a // custom occlusion animation. diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt index 822ee9b3e48c..e6ee11215595 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt @@ -175,8 +175,8 @@ constructor( val isDreamingWithOverlay: Flow<Boolean> = repository.isDreamingWithOverlay /** - * Whether the system is dreaming. [isDreaming] will be always be true when [isDozing] is true, - * but not vice-versa. Also accounts for [isDreamingWithOverlay] + * Whether the system is dreaming. [KeyguardRepository.isDreaming] will be always be true when + * [isDozing] is true, but not vice-versa. Also accounts for [isDreamingWithOverlay]. */ val isDreaming: StateFlow<Boolean> = merge(repository.isDreaming, repository.isDreamingWithOverlay) @@ -186,6 +186,9 @@ constructor( initialValue = false, ) + /** Whether any dreaming is running, including the doze dream. */ + val isDreamingAny: Flow<Boolean> = repository.isDreaming + /** Whether the system is dreaming and the active dream is hosted in lockscreen */ val isActiveDreamLockscreenHosted: StateFlow<Boolean> = repository.isActiveDreamLockscreenHosted diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModel.kt index aee34e1e713b..1e42e196bbc7 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModel.kt @@ -26,6 +26,7 @@ import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition import com.android.systemui.scene.shared.model.Scenes import javax.inject.Inject import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.flowOf @SysUISingleton class DozingToGlanceableHubTransitionViewModel @@ -35,10 +36,16 @@ constructor(animationFlow: KeyguardTransitionAnimationFlow) : DeviceEntryIconTra animationFlow .setup( duration = TO_GLANCEABLE_HUB_DURATION, - edge = Edge.create(DOZING, Scenes.Communal) + edge = Edge.create(DOZING, Scenes.Communal), ) .setupWithoutSceneContainer(edge = Edge.create(DOZING, GLANCEABLE_HUB)) override val deviceEntryParentViewAlpha: Flow<Float> = transitionAnimation.immediatelyTransitionTo(1f) + + /** + * Hide notifications when transitioning directly from dozing to hub, such as when pressing + * power button when dozing and docked. + */ + val notificationAlpha: Flow<Float> = flowOf(0f) } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt index e34eb61c5cbd..8ca26bea9705 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModel.kt @@ -45,6 +45,7 @@ import com.android.systemui.keyguard.ui.viewmodel.AodToGoneTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.AodToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.AodToOccludedTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters +import com.android.systemui.keyguard.ui.viewmodel.DozingToGlanceableHubTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DozingToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DozingToOccludedTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel @@ -112,6 +113,7 @@ constructor( private val aodToGoneTransitionViewModel: AodToGoneTransitionViewModel, private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel, private val aodToOccludedTransitionViewModel: AodToOccludedTransitionViewModel, + dozingToGlanceableHubTransitionViewModel: DozingToGlanceableHubTransitionViewModel, private val dozingToLockscreenTransitionViewModel: DozingToLockscreenTransitionViewModel, private val dozingToOccludedTransitionViewModel: DozingToOccludedTransitionViewModel, private val dreamingToLockscreenTransitionViewModel: DreamingToLockscreenTransitionViewModel, @@ -506,6 +508,7 @@ constructor( merge( lockscreenToGlanceableHubTransitionViewModel.notificationAlpha, glanceableHubToLockscreenTransitionViewModel.notificationAlpha, + dozingToGlanceableHubTransitionViewModel.notificationAlpha, ) // Manually emit on start because [notificationAlpha] only starts emitting // when transitions start. diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt index 64ae05131b5a..e6c98cd83b5e 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt @@ -16,6 +16,8 @@ package com.android.systemui.keyguard.domain.interactor +import android.service.dream.dreamManager +import com.android.systemui.communal.domain.interactor.communalInteractor import com.android.systemui.communal.domain.interactor.communalSceneInteractor import com.android.systemui.communal.domain.interactor.communalSettingsInteractor import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor @@ -39,10 +41,12 @@ var Kosmos.fromDreamingTransitionInteractor by mainDispatcher = testDispatcher, keyguardInteractor = keyguardInteractor, glanceableHubTransitions = glanceableHubTransitions, + communalInteractor = communalInteractor, communalSceneInteractor = communalSceneInteractor, communalSettingsInteractor = communalSettingsInteractor, powerInteractor = powerInteractor, keyguardOcclusionInteractor = keyguardOcclusionInteractor, + dreamManager = dreamManager, deviceEntryInteractor = deviceEntryInteractor, ) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModelKosmos.kt new file mode 100644 index 000000000000..ef10459b45cb --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/DozingToGlanceableHubTransitionViewModelKosmos.kt @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.keyguard.ui.keyguardTransitionAnimationFlow +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.kosmos.Kosmos.Fixture +import kotlinx.coroutines.ExperimentalCoroutinesApi + +@ExperimentalCoroutinesApi +val Kosmos.dozingToGlanceableHubTransitionViewModel by Fixture { + DozingToGlanceableHubTransitionViewModel(animationFlow = keyguardTransitionAnimationFlow) +} diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt index ffd8aabdd964..a9e117affefb 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/SharedNotificationContainerViewModelKosmos.kt @@ -25,6 +25,7 @@ import com.android.systemui.keyguard.ui.viewmodel.aodBurnInViewModel import com.android.systemui.keyguard.ui.viewmodel.aodToGoneTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.aodToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.aodToOccludedTransitionViewModel +import com.android.systemui.keyguard.ui.viewmodel.dozingToGlanceableHubTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.dozingToLockscreenTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.dozingToOccludedTransitionViewModel import com.android.systemui.keyguard.ui.viewmodel.dreamingToLockscreenTransitionViewModel @@ -66,6 +67,7 @@ val Kosmos.sharedNotificationContainerViewModel by Fixture { aodToGoneTransitionViewModel = aodToGoneTransitionViewModel, aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel, aodToOccludedTransitionViewModel = aodToOccludedTransitionViewModel, + dozingToGlanceableHubTransitionViewModel = dozingToGlanceableHubTransitionViewModel, dozingToLockscreenTransitionViewModel = dozingToLockscreenTransitionViewModel, dozingToOccludedTransitionViewModel = dozingToOccludedTransitionViewModel, dreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel, |