summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Beverly <beverlyt@google.com> 2024-07-19 15:46:31 +0000
committer Beverly <beverlyt@google.com> 2024-07-22 20:01:38 +0000
commitcab6bef41693fa9769badd472ed3c29e2c98a449 (patch)
treebef020fac5be4c905d216647cab0cf7312b118fe
parent0d4eb64ae4b1ba177cc971ff2bd07a533d8ad95c (diff)
[flexiglass] Handle dismiss actions from shade => primary bouncer => gone/shade
SceneContainerStartable: Check whether leaveOpenOnDismissKeyguard is true to determine whether to go to the GONE or SHADE scene. "Leave open" is referring to leaving the shade open. KeyguardDismissActionInteractor: When the device becomes unlocked on the SHADE, run any pending dismiss actions. Test: setup pin/pattern/password; pull down the shade on the lockscreen; tap on a notification; successfully authenticate; observe device transitions to the notification intent Test: setup pin/pattern/password; pull down the shade on the lockscreen; tap on the "edit qs" affordance; successfully authenticate; observe user is back on QS with the "edit QS" UI Test: setup pin/pattern/password; longpress on a QS tile; successfully authenticate; observe longpress action occurs Test: atest SceneContainerStartableTest KeyguardDismissActionInteractorTest Bug: 308819693 Flag: com.android.systemui.scene_container Change-Id: Iefe6fae0167407013f406093dd773b1039a5f691
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt37
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt34
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt63
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt4
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt3
7 files changed, 118 insertions, 38 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index 540a85aeb695..f26c39d0ba6d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -78,6 +78,7 @@ import com.android.systemui.statusbar.notificationShadeWindowController
import com.android.systemui.statusbar.phone.centralSurfaces
import com.android.systemui.statusbar.pipeline.mobile.data.repository.fakeMobileConnectionsRepository
import com.android.systemui.statusbar.policy.data.repository.fakeDeviceProvisioningRepository
+import com.android.systemui.statusbar.sysuiStatusBarStateController
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.mock
import com.google.common.truth.Truth.assertThat
@@ -274,9 +275,10 @@ class SceneContainerStartableTest : SysuiTestCase() {
}
@Test
- fun switchFromBouncerToQuickSettingsWhenDeviceUnlocked() =
+ fun switchFromBouncerToQuickSettingsWhenDeviceUnlocked_whenLeaveOpenShade() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ kosmos.sysuiStatusBarStateController.leaveOpen = true // leave shade open
val transitionState =
prepareState(
@@ -306,6 +308,39 @@ class SceneContainerStartableTest : SysuiTestCase() {
}
@Test
+ fun switchFromBouncerToGoneWhenDeviceUnlocked_whenDoNotLeaveOpenShade() =
+ testScope.runTest {
+ val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
+ kosmos.sysuiStatusBarStateController.leaveOpen = false // don't leave shade open
+
+ val transitionState =
+ prepareState(
+ authenticationMethod = AuthenticationMethodModel.Pin,
+ isDeviceUnlocked = false,
+ initialSceneKey = Scenes.Lockscreen,
+ )
+ assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen)
+ underTest.start()
+ runCurrent()
+
+ sceneInteractor.changeScene(Scenes.QuickSettings, "switching to qs for test")
+ transitionState.value = ObservableTransitionState.Idle(Scenes.QuickSettings)
+ runCurrent()
+ assertThat(currentSceneKey).isEqualTo(Scenes.QuickSettings)
+
+ sceneInteractor.changeScene(Scenes.Bouncer, "switching to bouncer for test")
+ transitionState.value = ObservableTransitionState.Idle(Scenes.Bouncer)
+ runCurrent()
+ assertThat(currentSceneKey).isEqualTo(Scenes.Bouncer)
+
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+
+ assertThat(currentSceneKey).isEqualTo(Scenes.Gone)
+ }
+
+ @Test
fun switchFromLockscreenToGoneWhenDeviceUnlocksWithBypassOn() =
testScope.runTest {
val currentSceneKey by collectLastValue(sceneInteractor.currentScene)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
index f4d82659971d..1152d7040a38 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractor.kt
@@ -19,12 +19,15 @@ package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.DismissAction
import com.android.systemui.keyguard.shared.model.KeyguardDone
import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.util.kotlin.Utils.Companion.sampleFilter
import com.android.systemui.util.kotlin.sample
@@ -35,6 +38,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNot
import kotlinx.coroutines.flow.map
@@ -51,6 +55,8 @@ constructor(
transitionInteractor: KeyguardTransitionInteractor,
val dismissInteractor: KeyguardDismissInteractor,
@Application private val applicationScope: CoroutineScope,
+ sceneInteractor: SceneInteractor,
+ deviceEntryInteractor: DeviceEntryInteractor,
) {
val dismissAction: Flow<DismissAction> = repository.dismissAction
@@ -80,9 +86,26 @@ constructor(
.filter { it }
.map {}
+ /**
+ * True if the any variation of the notification shade or quick settings is showing AND the
+ * device is unlocked. Else, false.
+ */
+ private val isOnShadeWhileUnlocked: Flow<Boolean> =
+ combine(
+ sceneInteractor.currentScene,
+ deviceEntryInteractor.isUnlocked,
+ ) { scene, isUnlocked ->
+ isUnlocked &&
+ (scene == Scenes.Shade ||
+ scene == Scenes.NotificationsShade ||
+ scene == Scenes.QuickSettings ||
+ scene == Scenes.QuickSettingsShade)
+ }
+ .distinctUntilChanged()
val executeDismissAction: Flow<() -> KeyguardDone> =
merge(
finishedTransitionToGone,
+ isOnShadeWhileUnlocked.filter { it }.map {},
dismissInteractor.dismissKeyguardRequestWithImmediateDismissAction
)
.sample(dismissAction)
@@ -99,9 +122,10 @@ constructor(
scene = Scenes.Bouncer,
stateWithoutSceneContainer = PRIMARY_BOUNCER
),
- transitionInteractor.isFinishedIn(state = ALTERNATE_BOUNCER)
- ) { isOnGone, isOnBouncer, isOnAltBouncer ->
- !isOnGone && !isOnBouncer && !isOnAltBouncer
+ transitionInteractor.isFinishedIn(state = ALTERNATE_BOUNCER),
+ isOnShadeWhileUnlocked,
+ ) { isOnGone, isOnBouncer, isOnAltBouncer, isOnShadeWhileUnlocked ->
+ !isOnGone && !isOnBouncer && !isOnAltBouncer && !isOnShadeWhileUnlocked
}
.filter { it }
.sampleFilter(dismissAction) { it !is DismissAction.None }
@@ -112,6 +136,7 @@ constructor(
}
fun runAfterKeyguardGone(runnable: Runnable) {
+ if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return
setDismissAction(
DismissAction.RunAfterKeyguardGone(
dismissAction = { runnable.run() },
@@ -123,15 +148,18 @@ constructor(
}
fun setDismissAction(dismissAction: DismissAction) {
+ if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return
repository.dismissAction.value.onCancelAction.run()
repository.setDismissAction(dismissAction)
}
fun handleDismissAction() {
+ if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return
repository.setDismissAction(DismissAction.None)
}
suspend fun setKeyguardDone(keyguardDoneTiming: KeyguardDone) {
+ if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) return
dismissInteractor.setKeyguardDone(keyguardDoneTiming)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
index b29302721253..74a7262d7889 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardDismissActionBinder.kt
@@ -23,6 +23,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInte
import com.android.systemui.log.core.LogLevel
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.util.kotlin.sample
+import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -34,7 +35,7 @@ import kotlinx.coroutines.launch
class KeyguardDismissActionBinder
@Inject
constructor(
- private val interactor: KeyguardDismissActionInteractor,
+ private val interactorLazy: Lazy<KeyguardDismissActionInteractor>,
@Application private val scope: CoroutineScope,
private val keyguardLogger: KeyguardLogger,
) : CoreStartable {
@@ -44,6 +45,7 @@ constructor(
return
}
+ val interactor = interactorLazy.get()
scope.launch {
interactor.executeDismissAction.collect {
log("executeDismissAction")
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 72f37fc98e17..3fca84efdd05 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -60,6 +60,7 @@ import com.android.systemui.scene.shared.logger.SceneLogger
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.NotificationShadeWindowController
+import com.android.systemui.statusbar.SysuiStatusBarStateController
import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
@@ -130,6 +131,7 @@ constructor(
private val windowMgrLockscreenVisInteractor: WindowManagerLockscreenVisibilityInteractor,
private val keyguardEnabledInteractor: KeyguardEnabledInteractor,
private val dismissCallbackRegistry: DismissCallbackRegistry,
+ private val statusBarStateController: SysuiStatusBarStateController,
) : CoreStartable {
private val centralSurfaces: CentralSurfaces?
get() = centralSurfacesOptLazy.get().getOrNull()
@@ -356,8 +358,13 @@ constructor(
isOnBouncer ->
// When the device becomes unlocked in Bouncer, go to previous scene,
// or Gone.
- if (previousScene.value == Scenes.Lockscreen) {
- Scenes.Gone to "device was unlocked in Bouncer scene"
+ if (
+ previousScene.value == Scenes.Lockscreen ||
+ !statusBarStateController.leaveOpenOnKeyguardHide()
+ ) {
+ Scenes.Gone to
+ "device was unlocked in Bouncer scene and shade" +
+ " didn't need to be left open"
} else {
val prevScene = previousScene.value
(prevScene ?: Scenes.Gone) to
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
index 8bc0a6040e12..a310520763e3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
@@ -20,21 +20,24 @@ package com.android.systemui.keyguard.domain.interactor
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.DisableSceneContainer
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.DismissAction
import com.android.systemui.keyguard.shared.model.KeyguardDone
-import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.kosmos.testScope
import com.android.systemui.scene.data.repository.Idle
+import com.android.systemui.scene.data.repository.Transition
import com.android.systemui.scene.data.repository.setSceneTransition
+import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -44,13 +47,12 @@ import org.mockito.MockitoAnnotations
@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
+@EnableSceneContainer
@RunWith(AndroidJUnit4::class)
class KeyguardDismissActionInteractorTest : SysuiTestCase() {
val kosmos = testKosmos()
private val keyguardRepository = kosmos.fakeKeyguardRepository
- private val transitionRepository = kosmos.fakeKeyguardTransitionRepository
-
private val testScope = kosmos.testScope
private lateinit var dismissInteractorWithDependencies:
@@ -74,6 +76,8 @@ class KeyguardDismissActionInteractorTest : SysuiTestCase() {
transitionInteractor = kosmos.keyguardTransitionInteractor,
dismissInteractor = dismissInteractorWithDependencies.interactor,
applicationScope = testScope.backgroundScope,
+ sceneInteractor = kosmos.sceneInteractor,
+ deviceEntryInteractor = kosmos.deviceEntryInteractor,
)
}
@@ -158,7 +162,6 @@ class KeyguardDismissActionInteractorTest : SysuiTestCase() {
}
@Test
- @DisableSceneContainer
fun executeDismissAction_dismissKeyguardRequestWithoutImmediateDismissAction() =
testScope.runTest {
val executeDismissAction by collectLastValue(underTest.executeDismissAction)
@@ -175,43 +178,37 @@ class KeyguardDismissActionInteractorTest : SysuiTestCase() {
)
assertThat(executeDismissAction).isNull()
- // WHEN the keyguard is GONE
- transitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.GONE,
- testScope,
- )
+ kosmos.setSceneTransition(Idle(Scenes.Gone))
+
assertThat(executeDismissAction).isNotNull()
}
@Test
- @EnableSceneContainer
- fun executeDismissAction_dismissKeyguardRequestWithoutImmediateDismissAction_scene_container() =
+ fun resetDismissAction() =
testScope.runTest {
- val executeDismissAction by collectLastValue(underTest.executeDismissAction)
-
- // WHEN a keyguard action will run after the keyguard is gone
- val onDismissAction = {}
+ kosmos.setSceneTransition(Idle(Scenes.Bouncer))
+ val resetDismissAction by collectLastValue(underTest.resetDismissAction)
keyguardRepository.setDismissAction(
DismissAction.RunAfterKeyguardGone(
- dismissAction = onDismissAction,
+ dismissAction = {},
onCancelAction = {},
message = "message",
willAnimateOnLockscreen = true,
)
)
- assertThat(executeDismissAction).isNull()
-
- kosmos.setSceneTransition(Idle(Scenes.Gone))
-
- assertThat(executeDismissAction).isNotNull()
+ assertThat(resetDismissAction).isNull()
+ kosmos.setSceneTransition(Idle(Scenes.Lockscreen))
+ assertThat(resetDismissAction).isEqualTo(Unit)
}
@Test
- fun resetDismissAction() =
+ fun doNotResetDismissActionOnUnlockedShade() =
testScope.runTest {
+ kosmos.setSceneTransition(Idle(Scenes.Bouncer))
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.None
+ )
val resetDismissAction by collectLastValue(underTest.resetDismissAction)
-
keyguardRepository.setDismissAction(
DismissAction.RunAfterKeyguardGone(
dismissAction = {},
@@ -220,12 +217,16 @@ class KeyguardDismissActionInteractorTest : SysuiTestCase() {
willAnimateOnLockscreen = true,
)
)
- transitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.AOD,
- testScope
+ assertThat(resetDismissAction).isNull()
+
+ kosmos.setSceneTransition(
+ Transition(
+ from = Scenes.Bouncer,
+ to = Scenes.NotificationsShade,
+ progress = flowOf(1f),
+ )
)
- assertThat(resetDismissAction).isEqualTo(Unit)
+ assertThat(resetDismissAction).isNull()
}
@Test
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt
index 2c6d44f10152..fe156e2037cf 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorKosmos.kt
@@ -16,9 +16,11 @@
package com.android.systemui.keyguard.domain.interactor
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.keyguard.data.repository.keyguardRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.sceneInteractor
import kotlinx.coroutines.ExperimentalCoroutinesApi
@ExperimentalCoroutinesApi
@@ -29,5 +31,7 @@ val Kosmos.keyguardDismissActionInteractor by
transitionInteractor = keyguardTransitionInteractor,
dismissInteractor = keyguardDismissInteractor,
applicationScope = testScope.backgroundScope,
+ sceneInteractor = sceneInteractor,
+ deviceEntryInteractor = deviceEntryInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
index 03a42bc4178e..8e76a0bf5a13 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
@@ -34,6 +34,7 @@ import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.testScope
import com.android.systemui.model.sysUiState
+import com.android.systemui.plugins.statusbar.statusBarStateController
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.domain.interactor.sceneBackInteractor
import com.android.systemui.scene.domain.interactor.sceneContainerOcclusionInteractor
@@ -46,6 +47,7 @@ import com.android.systemui.statusbar.notification.stack.domain.interactor.heads
import com.android.systemui.statusbar.notificationShadeWindowController
import com.android.systemui.statusbar.phone.centralSurfacesOptional
import com.android.systemui.statusbar.policy.domain.interactor.deviceProvisioningInteractor
+import com.android.systemui.statusbar.sysuiStatusBarStateController
val Kosmos.sceneContainerStartable by Fixture {
SceneContainerStartable(
@@ -77,5 +79,6 @@ val Kosmos.sceneContainerStartable by Fixture {
windowMgrLockscreenVisInteractor = windowManagerLockscreenVisibilityInteractor,
keyguardEnabledInteractor = keyguardEnabledInteractor,
dismissCallbackRegistry = dismissCallbackRegistry,
+ statusBarStateController = sysuiStatusBarStateController,
)
}