Loading packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt +23 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,9 @@ import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.coroutines.collectLastValue import com.android.systemui.dock.dockManager import com.android.systemui.dock.fakeDockManager import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.flags.featureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.keyguardInteractor Loading Loading @@ -66,6 +69,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fun setUp() { with(kosmos) { fakeSettings.putInt(Settings.System.SCREEN_OFF_TIMEOUT, SCREEN_TIMEOUT) kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true) underTest = CommunalSceneStartable( Loading @@ -76,6 +80,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { keyguardInteractor = keyguardInteractor, systemSettings = fakeSettings, notificationShadeWindowController = notificationShadeWindowController, featureFlagsClassic = kosmos.fakeFeatureFlagsClassic, applicationScope = applicationCoroutineScope, bgScope = applicationCoroutineScope, mainDispatcher = testDispatcher, Loading Loading @@ -451,6 +456,24 @@ class CommunalSceneStartableTest : SysuiTestCase() { } } @Test fun transitionFromDozingToGlanceableHub_forcesCommunal() = with(kosmos) { testScope.runTest { val scene by collectLastValue(communalSceneInteractor.currentScene) communalSceneInteractor.changeScene(CommunalScenes.Blank) assertThat(scene).isEqualTo(CommunalScenes.Blank) fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.DOZING, to = KeyguardState.GLANCEABLE_HUB, testScope = this ) assertThat(scene).isEqualTo(CommunalScenes.Communal) } } private fun TestScope.updateDocked(docked: Boolean) = with(kosmos) { runCurrent() Loading packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt +64 −0 Original line number Diff line number Diff line Loading @@ -34,12 +34,14 @@ package com.android.systemui.keyguard.domain.interactor import android.os.PowerManager 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.compose.animation.scene.ObservableTransitionState import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository import com.android.systemui.communal.domain.interactor.setCommunalAvailable import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository Loading @@ -64,8 +66,10 @@ import kotlinx.coroutines.test.runTest import org.junit.Before 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 @OptIn(ExperimentalCoroutinesApi::class) @SmallTest Loading Loading @@ -118,6 +122,66 @@ class FromDozingTransitionInteractorTest : SysuiTestCase() { ) } @Test @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) fun testTransitionToLockscreen_onPowerButtonPress_canDream_glanceableHubAvailable() = testScope.runTest { whenever(kosmos.dreamManager.canStartDreaming(anyBoolean())).thenReturn(true) kosmos.setCommunalAvailable(true) runCurrent() powerInteractor.setAwakeForTest(reason = PowerManager.WAKE_REASON_POWER_BUTTON) runCurrent() // If dreaming is possible and communal is available, then we should transition to // GLANCEABLE_HUB when waking up due to power button press. assertThat(transitionRepository) .startedTransition( from = KeyguardState.DOZING, to = KeyguardState.GLANCEABLE_HUB, ) } @Test @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) fun testTransitionToLockscreen_onPowerButtonPress_canNotDream_glanceableHubAvailable() = testScope.runTest { whenever(kosmos.dreamManager.canStartDreaming(anyBoolean())).thenReturn(false) kosmos.setCommunalAvailable(true) runCurrent() powerInteractor.setAwakeForTest(reason = PowerManager.WAKE_REASON_POWER_BUTTON) runCurrent() // If dreaming is NOT possible but communal is available, then we should transition to // LOCKSCREEN when waking up due to power button press. assertThat(transitionRepository) .startedTransition( from = KeyguardState.DOZING, to = KeyguardState.LOCKSCREEN, ) } @Test @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) fun testTransitionToLockscreen_onPowerButtonPress_canNDream_glanceableHubNotAvailable() = testScope.runTest { whenever(kosmos.dreamManager.canStartDreaming(anyBoolean())).thenReturn(true) kosmos.setCommunalAvailable(false) runCurrent() powerInteractor.setAwakeForTest(reason = PowerManager.WAKE_REASON_POWER_BUTTON) runCurrent() // If dreaming is possible but communal is NOT available, then we should transition to // LOCKSCREEN when waking up due to power button press. assertThat(transitionRepository) .startedTransition( from = KeyguardState.DOZING, to = KeyguardState.LOCKSCREEN, ) } @Test @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) fun testTransitionToGlanceableHub_onWakeup_ifIdleOnCommunal_noOccludingActivity() = Loading packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt +25 −7 Original line number Diff line number Diff line Loading @@ -18,7 +18,9 @@ package com.android.systemui.communal import android.provider.Settings import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.TransitionKey import com.android.systemui.CoreStartable import com.android.systemui.Flags.communalHub import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.shared.model.CommunalScenes Loading @@ -28,6 +30,8 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dock.DockManager import com.android.systemui.flags.FeatureFlagsClassic import com.android.systemui.flags.Flags import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState Loading Loading @@ -74,6 +78,7 @@ constructor( private val systemSettings: SystemSettings, centralSurfacesOpt: Optional<CentralSurfaces>, private val notificationShadeWindowController: NotificationShadeWindowController, private val featureFlagsClassic: FeatureFlagsClassic, @Application private val applicationScope: CoroutineScope, @Background private val bgScope: CoroutineScope, @Main private val mainDispatcher: CoroutineDispatcher, Loading @@ -86,13 +91,21 @@ constructor( private val centralSurfaces: CentralSurfaces? by centralSurfacesOpt private val flagEnabled: Boolean by lazy { featureFlagsClassic.isEnabled(Flags.COMMUNAL_SERVICE_ENABLED) && communalHub() } override fun start() { if (!flagEnabled) { return } // Handle automatically switching based on keyguard state. keyguardTransitionInteractor.startedKeyguardTransitionStep .mapLatest(::determineSceneAfterTransition) .filterNotNull() .onEach { nextScene -> communalSceneInteractor.changeScene(nextScene, CommunalTransitionKeys.SimpleFade) .onEach { (nextScene, nextTransition) -> communalSceneInteractor.changeScene(nextScene, nextTransition) } .launchIn(applicationScope) Loading Loading @@ -188,7 +201,7 @@ constructor( private suspend fun determineSceneAfterTransition( lastStartedTransition: TransitionStep, ): SceneKey? { ): Pair<SceneKey, TransitionKey>? { val to = lastStartedTransition.to val from = lastStartedTransition.from val docked = dockManager.isDocked Loading @@ -201,22 +214,27 @@ constructor( // underneath the hub is shown. When launching activities over lockscreen, we only // change scenes once the activity launch animation is finished, so avoid // changing the scene here. CommunalScenes.Blank Pair(CommunalScenes.Blank, CommunalTransitionKeys.SimpleFade) } to == KeyguardState.GLANCEABLE_HUB && from == KeyguardState.OCCLUDED -> { // When transitioning to the hub from an occluded state, fade out the hub without // doing any translation. CommunalScenes.Communal Pair(CommunalScenes.Communal, CommunalTransitionKeys.SimpleFade) } // Transitioning to Blank scene when entering the edit mode will be handled separately // with custom animations. to == KeyguardState.GONE && !communalInteractor.editModeOpen.value -> CommunalScenes.Blank Pair(CommunalScenes.Blank, CommunalTransitionKeys.SimpleFade) !docked && !KeyguardState.deviceIsAwakeInState(to) -> { // If the user taps the screen and wakes the device within this timeout, we don't // want to dismiss the hub delay(AWAKE_DEBOUNCE_DELAY) CommunalScenes.Blank Pair(CommunalScenes.Blank, CommunalTransitionKeys.SimpleFade) } from == KeyguardState.DOZING && to == KeyguardState.GLANCEABLE_HUB -> { // Make sure the communal hub is showing (immediately, not fading in) when // transitioning from dozing to hub. Pair(CommunalScenes.Communal, CommunalTransitionKeys.Immediately) } else -> null } Loading packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt +44 −2 Original line number Diff line number Diff line Loading @@ -17,8 +17,11 @@ 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.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main Loading @@ -28,6 +31,7 @@ import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositor import com.android.systemui.keyguard.shared.model.BiometricUnlockMode.Companion.isWakeAndUnlock import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.power.shared.model.WakeSleepReason import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.util.kotlin.Utils.Companion.sample import com.android.systemui.util.kotlin.sample Loading @@ -53,9 +57,11 @@ constructor( keyguardInteractor: KeyguardInteractor, powerInteractor: PowerInteractor, private val communalInteractor: CommunalInteractor, private val communalSceneInteractor: CommunalSceneInteractor, keyguardOcclusionInteractor: KeyguardOcclusionInteractor, val deviceEntryRepository: DeviceEntryRepository, private val wakeToGoneInteractor: KeyguardWakeDirectlyToGoneInteractor, private val dreamManager: DreamManager, ) : TransitionInteractor( fromState = KeyguardState.DOZING, Loading Loading @@ -115,6 +121,7 @@ constructor( } } @SuppressLint("MissingPermission") private fun listenForDozingToAny() { if (KeyguardWmStateRefactor.isEnabled) { return Loading @@ -126,7 +133,8 @@ constructor( .filterRelevantKeyguardStateAnd { isAwake -> isAwake } .sample( keyguardInteractor.isKeyguardOccluded, communalInteractor.isIdleOnCommunal, communalInteractor.isCommunalAvailable, communalSceneInteractor.isIdleOnCommunal, canTransitionToGoneOnWake, keyguardInteractor.primaryBouncerShowing, ) Loading @@ -134,6 +142,7 @@ constructor( ( _, occluded, isCommunalAvailable, isIdleOnCommunal, canTransitionToGoneOnWake, primaryBouncerShowing) -> Loading Loading @@ -163,6 +172,19 @@ constructor( } else { startTransitionTo(KeyguardState.GLANCEABLE_HUB) } } else if ( powerInteractor.detailedWakefulness.value.lastWakeReason == WakeSleepReason.POWER_BUTTON && isCommunalAvailable && dreamManager.canStartDreaming(true) ) { // This case handles tapping the power button to transition through // dream -> off -> hub. if (SceneContainerFlag.isEnabled) { // TODO(b/336576536): Check if adaptation for scene framework is needed } else { startTransitionTo(KeyguardState.GLANCEABLE_HUB) } } else { startTransitionTo(KeyguardState.LOCKSCREEN) } Loading @@ -171,6 +193,7 @@ constructor( } /** Figure out what state to transition to when we awake from DOZING. */ @SuppressLint("MissingPermission") private fun listenForWakeFromDozing() { if (!KeyguardWmStateRefactor.isEnabled) { return Loading @@ -180,7 +203,8 @@ constructor( powerInteractor.detailedWakefulness .filterRelevantKeyguardStateAnd { it.isAwake() } .sample( communalInteractor.isIdleOnCommunal, communalInteractor.isCommunalAvailable, communalSceneInteractor.isIdleOnCommunal, keyguardInteractor.biometricUnlockState, wakeToGoneInteractor.canWakeDirectlyToGone, keyguardInteractor.primaryBouncerShowing, Loading @@ -188,6 +212,7 @@ constructor( .collect { ( _, isCommunalAvailable, isIdleOnCommunal, biometricUnlockState, canWakeDirectlyToGone, Loading Loading @@ -227,6 +252,23 @@ constructor( ownerReason = "waking from dozing" ) } } else if ( powerInteractor.detailedWakefulness.value.lastWakeReason == WakeSleepReason.POWER_BUTTON && isCommunalAvailable && dreamManager.canStartDreaming(true) ) { // This case handles tapping the power button to transition through // dream -> off -> hub. if (SceneContainerFlag.isEnabled) { // TODO(b/336576536): Check if adaptation for scene framework is // needed } else { startTransitionTo( KeyguardState.GLANCEABLE_HUB, ownerReason = "waking from dozing" ) } } else { startTransitionTo( KeyguardState.LOCKSCREEN, Loading packages/SystemUI/tests/utils/src/com/android/systemui/TestMocksModule.kt +4 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui import android.app.ActivityManager import android.app.DreamManager import android.app.admin.DevicePolicyManager import android.app.trust.TrustManager import android.hardware.fingerprint.FingerprintManager Loading @@ -33,6 +34,7 @@ import com.android.systemui.animation.DialogTransitionAnimator import com.android.systemui.biometrics.AuthController import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.demomode.DemoModeController import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.ScreenLifecycle Loading Loading @@ -94,6 +96,7 @@ data class TestMocksModule( @get:Provides val demoModeController: DemoModeController = mock(), @get:Provides val deviceProvisionedController: DeviceProvisionedController = mock(), @get:Provides val dozeParameters: DozeParameters = mock(), @get:Provides val dreamManager: DreamManager = mock(), @get:Provides val dumpManager: DumpManager = mock(), @get:Provides val fingerprintManager: FingerprintManager = mock(), @get:Provides val headsUpManager: HeadsUpManager = mock(), Loading Loading @@ -132,6 +135,7 @@ data class TestMocksModule( @get:Provides val systemUIDialogManager: SystemUIDialogManager = mock(), @get:Provides val deviceEntryIconTransitions: Set<DeviceEntryIconTransition> = emptySet(), @get:Provides val communalInteractor: CommunalInteractor = mock(), @get:Provides val communalSceneInteractor: CommunalSceneInteractor = mock(), @get:Provides val sceneLogger: SceneLogger = mock(), @get:Provides val trustManager: TrustManager = mock(), @get:Provides val primaryBouncerInteractor: PrimaryBouncerInteractor = mock(), Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/communal/CommunalSceneStartableTest.kt +23 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,9 @@ import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.coroutines.collectLastValue import com.android.systemui.dock.dockManager import com.android.systemui.dock.fakeDockManager import com.android.systemui.flags.Flags.COMMUNAL_SERVICE_ENABLED import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.flags.featureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.domain.interactor.keyguardInteractor Loading Loading @@ -66,6 +69,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { fun setUp() { with(kosmos) { fakeSettings.putInt(Settings.System.SCREEN_OFF_TIMEOUT, SCREEN_TIMEOUT) kosmos.fakeFeatureFlagsClassic.set(COMMUNAL_SERVICE_ENABLED, true) underTest = CommunalSceneStartable( Loading @@ -76,6 +80,7 @@ class CommunalSceneStartableTest : SysuiTestCase() { keyguardInteractor = keyguardInteractor, systemSettings = fakeSettings, notificationShadeWindowController = notificationShadeWindowController, featureFlagsClassic = kosmos.fakeFeatureFlagsClassic, applicationScope = applicationCoroutineScope, bgScope = applicationCoroutineScope, mainDispatcher = testDispatcher, Loading Loading @@ -451,6 +456,24 @@ class CommunalSceneStartableTest : SysuiTestCase() { } } @Test fun transitionFromDozingToGlanceableHub_forcesCommunal() = with(kosmos) { testScope.runTest { val scene by collectLastValue(communalSceneInteractor.currentScene) communalSceneInteractor.changeScene(CommunalScenes.Blank) assertThat(scene).isEqualTo(CommunalScenes.Blank) fakeKeyguardTransitionRepository.sendTransitionSteps( from = KeyguardState.DOZING, to = KeyguardState.GLANCEABLE_HUB, testScope = this ) assertThat(scene).isEqualTo(CommunalScenes.Communal) } } private fun TestScope.updateDocked(docked: Boolean) = with(kosmos) { runCurrent() Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorTest.kt +64 −0 Original line number Diff line number Diff line Loading @@ -34,12 +34,14 @@ package com.android.systemui.keyguard.domain.interactor import android.os.PowerManager 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.compose.animation.scene.ObservableTransitionState import com.android.systemui.Flags import com.android.systemui.SysuiTestCase import com.android.systemui.communal.data.repository.fakeCommunalSceneRepository import com.android.systemui.communal.domain.interactor.setCommunalAvailable import com.android.systemui.communal.shared.model.CommunalScenes import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository Loading @@ -64,8 +66,10 @@ import kotlinx.coroutines.test.runTest import org.junit.Before 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 @OptIn(ExperimentalCoroutinesApi::class) @SmallTest Loading Loading @@ -118,6 +122,66 @@ class FromDozingTransitionInteractorTest : SysuiTestCase() { ) } @Test @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) fun testTransitionToLockscreen_onPowerButtonPress_canDream_glanceableHubAvailable() = testScope.runTest { whenever(kosmos.dreamManager.canStartDreaming(anyBoolean())).thenReturn(true) kosmos.setCommunalAvailable(true) runCurrent() powerInteractor.setAwakeForTest(reason = PowerManager.WAKE_REASON_POWER_BUTTON) runCurrent() // If dreaming is possible and communal is available, then we should transition to // GLANCEABLE_HUB when waking up due to power button press. assertThat(transitionRepository) .startedTransition( from = KeyguardState.DOZING, to = KeyguardState.GLANCEABLE_HUB, ) } @Test @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) fun testTransitionToLockscreen_onPowerButtonPress_canNotDream_glanceableHubAvailable() = testScope.runTest { whenever(kosmos.dreamManager.canStartDreaming(anyBoolean())).thenReturn(false) kosmos.setCommunalAvailable(true) runCurrent() powerInteractor.setAwakeForTest(reason = PowerManager.WAKE_REASON_POWER_BUTTON) runCurrent() // If dreaming is NOT possible but communal is available, then we should transition to // LOCKSCREEN when waking up due to power button press. assertThat(transitionRepository) .startedTransition( from = KeyguardState.DOZING, to = KeyguardState.LOCKSCREEN, ) } @Test @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) fun testTransitionToLockscreen_onPowerButtonPress_canNDream_glanceableHubNotAvailable() = testScope.runTest { whenever(kosmos.dreamManager.canStartDreaming(anyBoolean())).thenReturn(true) kosmos.setCommunalAvailable(false) runCurrent() powerInteractor.setAwakeForTest(reason = PowerManager.WAKE_REASON_POWER_BUTTON) runCurrent() // If dreaming is possible but communal is NOT available, then we should transition to // LOCKSCREEN when waking up due to power button press. assertThat(transitionRepository) .startedTransition( from = KeyguardState.DOZING, to = KeyguardState.LOCKSCREEN, ) } @Test @EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR) fun testTransitionToGlanceableHub_onWakeup_ifIdleOnCommunal_noOccludingActivity() = Loading
packages/SystemUI/src/com/android/systemui/communal/CommunalSceneStartable.kt +25 −7 Original line number Diff line number Diff line Loading @@ -18,7 +18,9 @@ package com.android.systemui.communal import android.provider.Settings import com.android.compose.animation.scene.SceneKey import com.android.compose.animation.scene.TransitionKey import com.android.systemui.CoreStartable import com.android.systemui.Flags.communalHub import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.communal.shared.model.CommunalScenes Loading @@ -28,6 +30,8 @@ import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.dock.DockManager import com.android.systemui.flags.FeatureFlagsClassic import com.android.systemui.flags.Flags import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState Loading Loading @@ -74,6 +78,7 @@ constructor( private val systemSettings: SystemSettings, centralSurfacesOpt: Optional<CentralSurfaces>, private val notificationShadeWindowController: NotificationShadeWindowController, private val featureFlagsClassic: FeatureFlagsClassic, @Application private val applicationScope: CoroutineScope, @Background private val bgScope: CoroutineScope, @Main private val mainDispatcher: CoroutineDispatcher, Loading @@ -86,13 +91,21 @@ constructor( private val centralSurfaces: CentralSurfaces? by centralSurfacesOpt private val flagEnabled: Boolean by lazy { featureFlagsClassic.isEnabled(Flags.COMMUNAL_SERVICE_ENABLED) && communalHub() } override fun start() { if (!flagEnabled) { return } // Handle automatically switching based on keyguard state. keyguardTransitionInteractor.startedKeyguardTransitionStep .mapLatest(::determineSceneAfterTransition) .filterNotNull() .onEach { nextScene -> communalSceneInteractor.changeScene(nextScene, CommunalTransitionKeys.SimpleFade) .onEach { (nextScene, nextTransition) -> communalSceneInteractor.changeScene(nextScene, nextTransition) } .launchIn(applicationScope) Loading Loading @@ -188,7 +201,7 @@ constructor( private suspend fun determineSceneAfterTransition( lastStartedTransition: TransitionStep, ): SceneKey? { ): Pair<SceneKey, TransitionKey>? { val to = lastStartedTransition.to val from = lastStartedTransition.from val docked = dockManager.isDocked Loading @@ -201,22 +214,27 @@ constructor( // underneath the hub is shown. When launching activities over lockscreen, we only // change scenes once the activity launch animation is finished, so avoid // changing the scene here. CommunalScenes.Blank Pair(CommunalScenes.Blank, CommunalTransitionKeys.SimpleFade) } to == KeyguardState.GLANCEABLE_HUB && from == KeyguardState.OCCLUDED -> { // When transitioning to the hub from an occluded state, fade out the hub without // doing any translation. CommunalScenes.Communal Pair(CommunalScenes.Communal, CommunalTransitionKeys.SimpleFade) } // Transitioning to Blank scene when entering the edit mode will be handled separately // with custom animations. to == KeyguardState.GONE && !communalInteractor.editModeOpen.value -> CommunalScenes.Blank Pair(CommunalScenes.Blank, CommunalTransitionKeys.SimpleFade) !docked && !KeyguardState.deviceIsAwakeInState(to) -> { // If the user taps the screen and wakes the device within this timeout, we don't // want to dismiss the hub delay(AWAKE_DEBOUNCE_DELAY) CommunalScenes.Blank Pair(CommunalScenes.Blank, CommunalTransitionKeys.SimpleFade) } from == KeyguardState.DOZING && to == KeyguardState.GLANCEABLE_HUB -> { // Make sure the communal hub is showing (immediately, not fading in) when // transitioning from dozing to hub. Pair(CommunalScenes.Communal, CommunalTransitionKeys.Immediately) } else -> null } Loading
packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt +44 −2 Original line number Diff line number Diff line Loading @@ -17,8 +17,11 @@ 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.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.dagger.qualifiers.Main Loading @@ -28,6 +31,7 @@ import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositor import com.android.systemui.keyguard.shared.model.BiometricUnlockMode.Companion.isWakeAndUnlock import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.power.shared.model.WakeSleepReason import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.util.kotlin.Utils.Companion.sample import com.android.systemui.util.kotlin.sample Loading @@ -53,9 +57,11 @@ constructor( keyguardInteractor: KeyguardInteractor, powerInteractor: PowerInteractor, private val communalInteractor: CommunalInteractor, private val communalSceneInteractor: CommunalSceneInteractor, keyguardOcclusionInteractor: KeyguardOcclusionInteractor, val deviceEntryRepository: DeviceEntryRepository, private val wakeToGoneInteractor: KeyguardWakeDirectlyToGoneInteractor, private val dreamManager: DreamManager, ) : TransitionInteractor( fromState = KeyguardState.DOZING, Loading Loading @@ -115,6 +121,7 @@ constructor( } } @SuppressLint("MissingPermission") private fun listenForDozingToAny() { if (KeyguardWmStateRefactor.isEnabled) { return Loading @@ -126,7 +133,8 @@ constructor( .filterRelevantKeyguardStateAnd { isAwake -> isAwake } .sample( keyguardInteractor.isKeyguardOccluded, communalInteractor.isIdleOnCommunal, communalInteractor.isCommunalAvailable, communalSceneInteractor.isIdleOnCommunal, canTransitionToGoneOnWake, keyguardInteractor.primaryBouncerShowing, ) Loading @@ -134,6 +142,7 @@ constructor( ( _, occluded, isCommunalAvailable, isIdleOnCommunal, canTransitionToGoneOnWake, primaryBouncerShowing) -> Loading Loading @@ -163,6 +172,19 @@ constructor( } else { startTransitionTo(KeyguardState.GLANCEABLE_HUB) } } else if ( powerInteractor.detailedWakefulness.value.lastWakeReason == WakeSleepReason.POWER_BUTTON && isCommunalAvailable && dreamManager.canStartDreaming(true) ) { // This case handles tapping the power button to transition through // dream -> off -> hub. if (SceneContainerFlag.isEnabled) { // TODO(b/336576536): Check if adaptation for scene framework is needed } else { startTransitionTo(KeyguardState.GLANCEABLE_HUB) } } else { startTransitionTo(KeyguardState.LOCKSCREEN) } Loading @@ -171,6 +193,7 @@ constructor( } /** Figure out what state to transition to when we awake from DOZING. */ @SuppressLint("MissingPermission") private fun listenForWakeFromDozing() { if (!KeyguardWmStateRefactor.isEnabled) { return Loading @@ -180,7 +203,8 @@ constructor( powerInteractor.detailedWakefulness .filterRelevantKeyguardStateAnd { it.isAwake() } .sample( communalInteractor.isIdleOnCommunal, communalInteractor.isCommunalAvailable, communalSceneInteractor.isIdleOnCommunal, keyguardInteractor.biometricUnlockState, wakeToGoneInteractor.canWakeDirectlyToGone, keyguardInteractor.primaryBouncerShowing, Loading @@ -188,6 +212,7 @@ constructor( .collect { ( _, isCommunalAvailable, isIdleOnCommunal, biometricUnlockState, canWakeDirectlyToGone, Loading Loading @@ -227,6 +252,23 @@ constructor( ownerReason = "waking from dozing" ) } } else if ( powerInteractor.detailedWakefulness.value.lastWakeReason == WakeSleepReason.POWER_BUTTON && isCommunalAvailable && dreamManager.canStartDreaming(true) ) { // This case handles tapping the power button to transition through // dream -> off -> hub. if (SceneContainerFlag.isEnabled) { // TODO(b/336576536): Check if adaptation for scene framework is // needed } else { startTransitionTo( KeyguardState.GLANCEABLE_HUB, ownerReason = "waking from dozing" ) } } else { startTransitionTo( KeyguardState.LOCKSCREEN, Loading
packages/SystemUI/tests/utils/src/com/android/systemui/TestMocksModule.kt +4 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.systemui import android.app.ActivityManager import android.app.DreamManager import android.app.admin.DevicePolicyManager import android.app.trust.TrustManager import android.hardware.fingerprint.FingerprintManager Loading @@ -33,6 +34,7 @@ import com.android.systemui.animation.DialogTransitionAnimator import com.android.systemui.biometrics.AuthController import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.communal.domain.interactor.CommunalInteractor import com.android.systemui.communal.domain.interactor.CommunalSceneInteractor import com.android.systemui.demomode.DemoModeController import com.android.systemui.dump.DumpManager import com.android.systemui.keyguard.ScreenLifecycle Loading Loading @@ -94,6 +96,7 @@ data class TestMocksModule( @get:Provides val demoModeController: DemoModeController = mock(), @get:Provides val deviceProvisionedController: DeviceProvisionedController = mock(), @get:Provides val dozeParameters: DozeParameters = mock(), @get:Provides val dreamManager: DreamManager = mock(), @get:Provides val dumpManager: DumpManager = mock(), @get:Provides val fingerprintManager: FingerprintManager = mock(), @get:Provides val headsUpManager: HeadsUpManager = mock(), Loading Loading @@ -132,6 +135,7 @@ data class TestMocksModule( @get:Provides val systemUIDialogManager: SystemUIDialogManager = mock(), @get:Provides val deviceEntryIconTransitions: Set<DeviceEntryIconTransition> = emptySet(), @get:Provides val communalInteractor: CommunalInteractor = mock(), @get:Provides val communalSceneInteractor: CommunalSceneInteractor = mock(), @get:Provides val sceneLogger: SceneLogger = mock(), @get:Provides val trustManager: TrustManager = mock(), @get:Provides val primaryBouncerInteractor: PrimaryBouncerInteractor = mock(), Loading