diff options
| author | 2024-05-02 15:19:26 +0000 | |
|---|---|---|
| committer | 2024-05-02 15:31:01 +0000 | |
| commit | 7a24648a02194972a62b24c358467d62bccbc62b (patch) | |
| tree | 74b4ea16dd83a22f860697066825ddca58a43d1e | |
| parent | a79d1accf999ae8406bd682af219499c89b8b5f3 (diff) | |
Fix keyguard y translation while swiping
The swipe up signal comes from legacy shade expansion,
which can be unreliable. It will emit values of 0f and 1f,
at certain times as it resets, which can cause confusion
in the code and result in janky transitions.
Test: atest KeyguardInteractorTest
Fixes: 330189292
Flag: ACONFIG com.android.systemui.migrate_clocks_to_blueprint
TEAMFOOD
Change-Id: If9611004ee4692a21988466a3aa2558f904ade1f
3 files changed, 112 insertions, 42 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt index 12f891835d0e..323087c801f1 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt @@ -24,23 +24,23 @@ import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR import com.android.systemui.SysuiTestCase -import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository -import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository -import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor +import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository +import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.coroutines.collectLastValue import com.android.systemui.flags.EnableSceneContainer -import com.android.systemui.keyguard.data.repository.FakeCommandQueue +import com.android.systemui.keyguard.data.repository.fakeCommandQueue import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.StatusBarState +import com.android.systemui.keyguard.shared.model.TransitionState +import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.kosmos.testScope -import com.android.systemui.power.domain.interactor.PowerInteractorFactory +import com.android.systemui.res.R import com.android.systemui.scene.domain.interactor.sceneInteractor import com.android.systemui.scene.shared.model.Scenes -import com.android.systemui.shade.data.repository.FakeShadeRepository -import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor +import com.android.systemui.shade.data.repository.shadeRepository import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -60,33 +60,17 @@ class KeyguardInteractorTest : SysuiTestCase() { private val kosmos = testKosmos() private val testScope = kosmos.testScope - private val repository by lazy { kosmos.fakeKeyguardRepository } - private val sceneInteractor by lazy { kosmos.sceneInteractor } - private val fromGoneTransitionInteractor by lazy { kosmos.fromGoneTransitionInteractor } - private val commandQueue by lazy { FakeCommandQueue() } - private val bouncerRepository = FakeKeyguardBouncerRepository() - private val shadeRepository = FakeShadeRepository() + private val repository = kosmos.fakeKeyguardRepository + private val sceneInteractor = kosmos.sceneInteractor + private val fromGoneTransitionInteractor = kosmos.fromGoneTransitionInteractor + private val commandQueue = kosmos.fakeCommandQueue + private val configRepository = kosmos.fakeConfigurationRepository + private val bouncerRepository = kosmos.keyguardBouncerRepository + private val shadeRepository = kosmos.shadeRepository private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository private val transitionState: MutableStateFlow<ObservableTransitionState> = MutableStateFlow(ObservableTransitionState.Idle(Scenes.Gone)) - - private val underTest by lazy { - KeyguardInteractor( - repository = repository, - commandQueue = commandQueue, - powerInteractor = PowerInteractorFactory.create().powerInteractor, - bouncerRepository = bouncerRepository, - configurationInteractor = ConfigurationInteractor(FakeConfigurationRepository()), - shadeRepository = shadeRepository, - keyguardTransitionInteractor = kosmos.keyguardTransitionInteractor, - sceneInteractorProvider = { sceneInteractor }, - fromGoneTransitionInteractor = { fromGoneTransitionInteractor }, - sharedNotificationContainerInteractor = { - kosmos.sharedNotificationContainerInteractor - }, - applicationScope = testScope, - ) - } + private val underTest = kosmos.keyguardInteractor @Before fun setUp() { @@ -247,6 +231,84 @@ class KeyguardInteractorTest : SysuiTestCase() { } @Test + fun keyguardTranslationY_whenGoneEmitsZero() = + testScope.runTest { + val keyguardTranslationY by collectLastValue(underTest.keyguardTranslationY) + + configRepository.setDimensionPixelSize( + R.dimen.keyguard_translate_distance_on_swipe_up, + 100 + ) + configRepository.onAnyConfigurationChange() + + shadeRepository.setLegacyShadeExpansion(0f) + + keyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.AOD, + to = KeyguardState.GONE, + testScope, + ) + + assertThat(keyguardTranslationY).isEqualTo(0f) + } + + @Test + fun keyguardTranslationY_whenNotGoneAndShadeIsFullyCollapsedEmitsZero() = + testScope.runTest { + val keyguardTranslationY by collectLastValue(underTest.keyguardTranslationY) + + configRepository.setDimensionPixelSize( + R.dimen.keyguard_translate_distance_on_swipe_up, + 100 + ) + configRepository.onAnyConfigurationChange() + + shadeRepository.setLegacyShadeExpansion(0f) + + keyguardTransitionRepository.sendTransitionSteps( + from = KeyguardState.AOD, + to = KeyguardState.LOCKSCREEN, + testScope, + ) + + assertThat(keyguardTranslationY).isEqualTo(0f) + } + + @Test + fun keyguardTranslationY_whenTransitioningToGoneAndShadeIsExpandingEmitsNonZero() = + testScope.runTest { + val keyguardTranslationY by collectLastValue(underTest.keyguardTranslationY) + + configRepository.setDimensionPixelSize( + R.dimen.keyguard_translate_distance_on_swipe_up, + 100 + ) + configRepository.onAnyConfigurationChange() + + shadeRepository.setLegacyShadeExpansion(0.5f) + + keyguardTransitionRepository.sendTransitionSteps( + listOf( + TransitionStep( + from = KeyguardState.AOD, + to = KeyguardState.GONE, + value = 0f, + transitionState = TransitionState.STARTED, + ), + TransitionStep( + from = KeyguardState.AOD, + to = KeyguardState.GONE, + value = 0.1f, + transitionState = TransitionState.RUNNING, + ), + ), + testScope, + ) + + assertThat(keyguardTranslationY).isGreaterThan(0f) + } + + @Test @EnableSceneContainer fun animationDozingTransitions() = testScope.runTest { 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 d19176853387..a4b4e7a0cf5f 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 @@ -307,19 +307,27 @@ constructor( configurationInteractor .dimensionPixelSize(R.dimen.keyguard_translate_distance_on_swipe_up) .flatMapLatest { translationDistance -> - combine( + combineTransform( shadeRepository.legacyShadeExpansion.onStart { emit(0f) }, keyguardTransitionInteractor.transitionValue(GONE).onStart { emit(0f) }, ) { legacyShadeExpansion, goneValue -> - if (goneValue == 1f || legacyShadeExpansion == 0f) { + if (goneValue == 1f || (goneValue == 0f && legacyShadeExpansion == 0f)) { // Reset the translation value - 0f - } else { - // On swipe up, translate the keyguard to reveal the bouncer - MathUtils.lerp( - translationDistance, - 0, - Interpolators.FAST_OUT_LINEAR_IN.getInterpolation(legacyShadeExpansion) + emit(0f) + } else if (legacyShadeExpansion > 0f && legacyShadeExpansion < 1f) { + // On swipe up, translate the keyguard to reveal the bouncer, OR a GONE + // transition is running, which means this is a swipe to dismiss. Values of + // 0f and 1f need to be ignored in the legacy shade expansion. These can + // flip arbitrarily as the legacy shade is reset, and would cause the + // translation value to jump around unexpectedly. + emit( + MathUtils.lerp( + translationDistance, + 0, + Interpolators.FAST_OUT_LINEAR_IN.getInterpolation( + legacyShadeExpansion + ), + ) ) } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt index 94267189e179..1674044bc8fd 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorKosmos.kt @@ -18,20 +18,20 @@ package com.android.systemui.keyguard.domain.interactor import com.android.systemui.bouncer.data.repository.keyguardBouncerRepository import com.android.systemui.common.ui.domain.interactor.configurationInteractor +import com.android.systemui.keyguard.data.repository.fakeCommandQueue import com.android.systemui.keyguard.data.repository.keyguardRepository 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.data.repository.shadeRepository -import com.android.systemui.statusbar.commandQueue import com.android.systemui.statusbar.notification.stack.domain.interactor.sharedNotificationContainerInteractor val Kosmos.keyguardInteractor: KeyguardInteractor by Kosmos.Fixture { KeyguardInteractor( repository = keyguardRepository, - commandQueue = commandQueue, + commandQueue = fakeCommandQueue, powerInteractor = powerInteractor, bouncerRepository = keyguardBouncerRepository, configurationInteractor = configurationInteractor, |