Merge "Revert^2 "[flexiglass] Fixes issue where user management settings didn't show"" into main
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
index 29035ce..d97909a1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardDismissActionInteractorTest.kt
@@ -19,17 +19,22 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
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.bouncer.data.repository.fakeKeyguardBouncerRepository
import com.android.systemui.bouncer.domain.interactor.alternateBouncerInteractor
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.DismissAction
import com.android.systemui.keyguard.shared.model.KeyguardDone
+import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
import com.android.systemui.power.data.repository.fakePowerRepository
import com.android.systemui.power.domain.interactor.powerInteractor
@@ -38,11 +43,13 @@
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.shade.domain.interactor.shadeInteractor
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -80,6 +87,7 @@
alternateBouncerInteractor = kosmos.alternateBouncerInteractor,
shadeInteractor = { kosmos.shadeInteractor },
keyguardInteractor = { kosmos.keyguardInteractor },
+ sceneInteractor = { kosmos.sceneInteractor },
)
}
@@ -178,7 +186,11 @@
)
assertThat(executeDismissAction).isNull()
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
kosmos.setSceneTransition(Idle(Scenes.Gone))
+ kosmos.sceneInteractor.changeScene(Scenes.Gone, "")
assertThat(executeDismissAction).isNotNull()
}
@@ -301,4 +313,78 @@
underTest.setKeyguardDone(KeyguardDone.IMMEDIATE)
assertThat(keyguardDoneTiming).isEqualTo(KeyguardDone.IMMEDIATE)
}
+
+ @Test
+ @EnableSceneContainer
+ fun dismissAction_executesBeforeItsReset_sceneContainerOn_swipeAuth_fromQsScene() =
+ testScope.runTest {
+ val canSwipeToEnter by collectLastValue(kosmos.deviceEntryInteractor.canSwipeToEnter)
+ val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene)
+ val transitionState =
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(currentScene!!)
+ )
+ kosmos.sceneInteractor.setTransitionState(transitionState)
+ val executeDismissAction by collectLastValue(underTest.executeDismissAction)
+ val resetDismissAction by collectLastValue(underTest.resetDismissAction)
+ assertThat(executeDismissAction).isNull()
+ assertThat(resetDismissAction).isNull()
+ kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.None
+ )
+ kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
+ assertThat(canSwipeToEnter).isTrue()
+ kosmos.sceneInteractor.changeScene(Scenes.QuickSettings, "")
+ transitionState.value = ObservableTransitionState.Idle(Scenes.QuickSettings)
+ assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
+
+ assertThat(executeDismissAction).isNull()
+ assertThat(resetDismissAction).isNull()
+
+ val dismissAction =
+ DismissAction.RunImmediately(
+ onDismissAction = { KeyguardDone.LATER },
+ onCancelAction = {},
+ message = "message",
+ willAnimateOnLockscreen = true,
+ )
+ underTest.setDismissAction(dismissAction)
+ // Should still be null because the transition to Gone has not yet happened.
+ assertThat(executeDismissAction).isNull()
+ assertThat(resetDismissAction).isNull()
+
+ transitionState.value =
+ ObservableTransitionState.Transition.ChangeScene(
+ fromScene = Scenes.QuickSettings,
+ toScene = Scenes.Gone,
+ currentScene = flowOf(Scenes.QuickSettings),
+ currentOverlays = emptySet(),
+ progress = flowOf(0.5f),
+ isInitiatedByUserInput = true,
+ isUserInputOngoing = flowOf(false),
+ previewProgress = flowOf(0f),
+ isInPreviewStage = flowOf(false),
+ )
+ runCurrent()
+ assertThat(executeDismissAction).isNull()
+ assertThat(resetDismissAction).isNull()
+
+ transitionState.value =
+ ObservableTransitionState.Transition.ChangeScene(
+ fromScene = Scenes.QuickSettings,
+ toScene = Scenes.Gone,
+ currentScene = flowOf(Scenes.Gone),
+ currentOverlays = emptySet(),
+ progress = flowOf(1f),
+ isInitiatedByUserInput = true,
+ isUserInputOngoing = flowOf(false),
+ previewProgress = flowOf(0f),
+ isInPreviewStage = flowOf(false),
+ )
+ kosmos.sceneInteractor.changeScene(Scenes.Gone, "")
+ assertThat(currentScene).isEqualTo(Scenes.Gone)
+ runCurrent()
+ assertThat(executeDismissAction).isNotNull()
+ assertThat(resetDismissAction).isNull()
+ }
}
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 18b1495..258232b 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
@@ -28,6 +28,7 @@
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.PRIMARY_BOUNCER
import com.android.systemui.power.domain.interactor.PowerInteractor
+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.shade.domain.interactor.ShadeInteractor
@@ -64,6 +65,7 @@
alternateBouncerInteractor: AlternateBouncerInteractor,
shadeInteractor: Lazy<ShadeInteractor>,
keyguardInteractor: Lazy<KeyguardInteractor>,
+ sceneInteractor: Lazy<SceneInteractor>,
) {
val dismissAction: Flow<DismissAction> = repository.dismissAction
@@ -125,7 +127,20 @@
val executeDismissAction: Flow<() -> KeyguardDone> =
merge(
- finishedTransitionToGone,
+ if (SceneContainerFlag.isEnabled) {
+ // Using currentScene instead of finishedTransitionToGone because of a race
+ // condition that forms between finishedTransitionToGone and
+ // isOnShadeWhileUnlocked where the latter emits false before the former emits
+ // true, causing the merge to not emit until it's too late.
+ sceneInteractor
+ .get()
+ .currentScene
+ .map { it == Scenes.Gone }
+ .distinctUntilChanged()
+ .filter { it }
+ } else {
+ finishedTransitionToGone
+ },
isOnShadeWhileUnlocked.filter { it }.map {},
dismissInteractor.dismissKeyguardRequestWithImmediateDismissAction,
)
@@ -135,10 +150,24 @@
val resetDismissAction: Flow<Unit> =
combine(
- transitionInteractor.isFinishedIn(
- scene = Scenes.Gone,
- stateWithoutSceneContainer = GONE,
- ),
+ if (SceneContainerFlag.isEnabled) {
+ // Using currentScene instead of isFinishedIn because of a race condition that
+ // forms between isFinishedIn(Gone) and isOnShadeWhileUnlocked where the latter
+ // emits false before the former emits true, causing the evaluation of the
+ // combine to come up with true, temporarily, before settling on false, which is
+ // a valid final state. That causes an incorrect reset of the dismiss action to
+ // occur before it gets executed.
+ sceneInteractor
+ .get()
+ .currentScene
+ .map { it == Scenes.Gone }
+ .distinctUntilChanged()
+ } else {
+ transitionInteractor.isFinishedIn(
+ scene = Scenes.Gone,
+ stateWithoutSceneContainer = GONE,
+ )
+ },
transitionInteractor.isFinishedIn(
scene = Scenes.Bouncer,
stateWithoutSceneContainer = PRIMARY_BOUNCER,
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 38bc758..2f13ba4 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
@@ -22,6 +22,7 @@
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.testScope
import com.android.systemui.power.domain.interactor.powerInteractor
+import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.shade.domain.interactor.shadeInteractor
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -38,5 +39,6 @@
alternateBouncerInteractor = alternateBouncerInteractor,
shadeInteractor = { shadeInteractor },
keyguardInteractor = { keyguardInteractor },
+ sceneInteractor = { sceneInteractor },
)
}