Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 07ce7a6b authored by Andreas Miko's avatar Andreas Miko
Browse files

Transform and consolidate transitionValue() API

TransitionValue can now accept scenes or states.

Test: None
Bug: b/330311871
Flag: com.android.systemui.scene_container
Change-Id: I951e568d44f3a54ddf94dc1cb0363a348d930a02
parent b44a5d6c
Loading
Loading
Loading
Loading
+9 −3
Original line number Diff line number Diff line
@@ -39,7 +39,9 @@ import com.android.systemui.keyguard.shared.model.KeyguardState
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.scene.data.repository.Idle
import com.android.systemui.scene.data.repository.sceneContainerRepository
import com.android.systemui.scene.data.repository.setSceneTransition
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.shadeTestUtil
@@ -290,6 +292,7 @@ class KeyguardRootViewModelTest(flags: FlagsParameterization) : SysuiTestCase()
                testScope,
            )

            kosmos.setSceneTransition(Idle(Scenes.Gone))
            // Make sure the value hasn't changed since we're GONE
            keyguardRepository.topClippingBounds.value = 5
            assertThat(topClippingBounds).isEqualTo(1000)
@@ -518,12 +521,15 @@ class KeyguardRootViewModelTest(flags: FlagsParameterization) : SysuiTestCase()
                to = KeyguardState.GONE,
                testScope = testScope,
            )
            kosmos.setSceneTransition(Idle(Scenes.Gone))
            assertThat(alpha).isEqualTo(0f)

            if (!SceneContainerFlag.isEnabled) {
                // Try pulling down shade and ensure the value doesn't change
                shadeTestUtil.setQsExpansion(0.5f)
                assertThat(alpha).isEqualTo(0f)
            }
        }

    @Test
    fun alpha_idleOnDream_isZero() =
+57 −79
Original line number Diff line number Diff line
@@ -21,16 +21,19 @@ package com.android.systemui.scene.domain.interactor
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
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.sceneContainerRepository
import com.android.systemui.scene.data.repository.setSceneTransition
import com.android.systemui.scene.sceneContainerConfig
import com.android.systemui.scene.sceneKeys
import com.android.systemui.scene.shared.model.SceneContainerConfig
import com.android.systemui.scene.shared.model.SceneFamilies
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
@@ -54,48 +57,27 @@ class SceneInteractorTest : SysuiTestCase() {
    private val testScope = kosmos.testScope
    private val fakeSceneDataSource = kosmos.fakeSceneDataSource

    private lateinit var underTest: SceneInteractor
    private val underTest = kosmos.sceneInteractor

    @Test
    fun allSceneKeys() {
        underTest = kosmos.sceneInteractor
        assertThat(underTest.allSceneKeys()).isEqualTo(kosmos.sceneKeys)
    }

    @Test
    fun changeScene_toUnknownScene_doesNothing() =
        testScope.runTest {
            val sceneKeys =
                listOf(
                    Scenes.QuickSettings,
                    Scenes.Shade,
                    Scenes.Lockscreen,
                    Scenes.Gone,
                    Scenes.Communal,
                )
            val navigationDistances =
                mapOf(
                    Scenes.Gone to 0,
                    Scenes.Lockscreen to 0,
                    Scenes.Communal to 1,
                    Scenes.Shade to 2,
                    Scenes.QuickSettings to 3,
                )
            kosmos.sceneContainerConfig =
                SceneContainerConfig(sceneKeys, Scenes.Lockscreen, navigationDistances)
            underTest = kosmos.sceneInteractor
            val currentScene by collectLastValue(underTest.currentScene)
            val unknownScene = SceneKey("UNKNOWN")
            val previousScene = currentScene
            assertThat(previousScene).isNotEqualTo(Scenes.Bouncer)
            underTest.changeScene(Scenes.Bouncer, "reason")
            assertThat(previousScene).isNotEqualTo(unknownScene)
            underTest.changeScene(unknownScene, "reason")
            assertThat(currentScene).isEqualTo(previousScene)
        }

    @Test
    fun changeScene() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor

            val currentScene by collectLastValue(underTest.currentScene)
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)

@@ -106,8 +88,6 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun changeScene_toGoneWhenUnl_doesNotThrow() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor

            val currentScene by collectLastValue(underTest.currentScene)
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)

@@ -122,15 +102,11 @@ class SceneInteractorTest : SysuiTestCase() {

    @Test(expected = IllegalStateException::class)
    fun changeScene_toGoneWhenStillLocked_throws() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            underTest.changeScene(Scenes.Gone, "reason")
        }
        testScope.runTest { underTest.changeScene(Scenes.Gone, "reason") }

    @Test
    fun changeScene_toGoneWhenTransitionToLockedFromGone() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            val currentScene by collectLastValue(underTest.currentScene)
            val transitionTo by collectLastValue(underTest.transitioningTo)
            kosmos.sceneContainerRepository.setTransitionState(
@@ -155,7 +131,6 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun changeScene_toHomeSceneFamily() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            val currentScene by collectLastValue(underTest.currentScene)

            underTest.changeScene(SceneFamilies.Home, "reason")
@@ -167,37 +142,17 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun snapToScene_toUnknownScene_doesNothing() =
        testScope.runTest {
            val sceneKeys =
                listOf(
                    Scenes.QuickSettings,
                    Scenes.Shade,
                    Scenes.Lockscreen,
                    Scenes.Gone,
                    Scenes.Communal,
                )
            val navigationDistances =
                mapOf(
                    Scenes.Gone to 0,
                    Scenes.Lockscreen to 0,
                    Scenes.Communal to 1,
                    Scenes.Shade to 2,
                    Scenes.QuickSettings to 3,
                )
            kosmos.sceneContainerConfig =
                SceneContainerConfig(sceneKeys, Scenes.Lockscreen, navigationDistances)
            underTest = kosmos.sceneInteractor
            val currentScene by collectLastValue(underTest.currentScene)
            val previousScene = currentScene
            assertThat(previousScene).isNotEqualTo(Scenes.Bouncer)
            underTest.snapToScene(Scenes.Bouncer, "reason")
            val unknownScene = SceneKey("UNKNOWN")
            assertThat(previousScene).isNotEqualTo(unknownScene)
            underTest.snapToScene(unknownScene, "reason")
            assertThat(currentScene).isEqualTo(previousScene)
        }

    @Test
    fun snapToScene() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor

            val currentScene by collectLastValue(underTest.currentScene)
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)

@@ -208,8 +163,6 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun snapToScene_toGoneWhenUnl_doesNotThrow() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor

            val currentScene by collectLastValue(underTest.currentScene)
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)

@@ -224,15 +177,11 @@ class SceneInteractorTest : SysuiTestCase() {

    @Test(expected = IllegalStateException::class)
    fun snapToScene_toGoneWhenStillLocked_throws() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            underTest.snapToScene(Scenes.Gone, "reason")
        }
        testScope.runTest { underTest.snapToScene(Scenes.Gone, "reason") }

    @Test
    fun snapToScene_toHomeSceneFamily() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            val currentScene by collectLastValue(underTest.currentScene)

            underTest.snapToScene(SceneFamilies.Home, "reason")
@@ -244,7 +193,6 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun sceneChanged_inDataSource() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            val currentScene by collectLastValue(underTest.currentScene)
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)

@@ -256,14 +204,14 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun transitionState() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            val underTest = kosmos.sceneContainerRepository
            val sceneContainerRepository = kosmos.sceneContainerRepository
            val transitionState =
                MutableStateFlow<ObservableTransitionState>(
                    ObservableTransitionState.Idle(Scenes.Lockscreen)
                )
            underTest.setTransitionState(transitionState)
            val reflectedTransitionState by collectLastValue(underTest.transitionState)
            sceneContainerRepository.setTransitionState(transitionState)
            val reflectedTransitionState by
                collectLastValue(sceneContainerRepository.transitionState)
            assertThat(reflectedTransitionState).isEqualTo(transitionState.value)

            val progress = MutableStateFlow(1f)
@@ -284,7 +232,7 @@ class SceneInteractorTest : SysuiTestCase() {
            progress.value = 0.9f
            assertThat(reflectedTransitionState).isEqualTo(transitionState.value)

            underTest.setTransitionState(null)
            sceneContainerRepository.setTransitionState(null)
            assertThat(reflectedTransitionState)
                .isEqualTo(
                    ObservableTransitionState.Idle(kosmos.sceneContainerConfig.initialSceneKey)
@@ -294,7 +242,6 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun transitioningTo() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            val transitionState =
                MutableStateFlow<ObservableTransitionState>(
                    ObservableTransitionState.Idle(underTest.currentScene.value)
@@ -332,7 +279,6 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun isTransitionUserInputOngoing_idle_false() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            val transitionState =
                MutableStateFlow<ObservableTransitionState>(
                    ObservableTransitionState.Idle(Scenes.Shade)
@@ -347,7 +293,6 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun isTransitionUserInputOngoing_transition_true() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            val transitionState =
                MutableStateFlow<ObservableTransitionState>(
                    ObservableTransitionState.Transition(
@@ -369,7 +314,6 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun isTransitionUserInputOngoing_updateMidTransition_false() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            val transitionState =
                MutableStateFlow<ObservableTransitionState>(
                    ObservableTransitionState.Transition(
@@ -403,7 +347,6 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun isTransitionUserInputOngoing_updateOnIdle_false() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            val transitionState =
                MutableStateFlow<ObservableTransitionState>(
                    ObservableTransitionState.Transition(
@@ -429,7 +372,6 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun isVisible() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            val isVisible by collectLastValue(underTest.isVisible)
            assertThat(isVisible).isTrue()

@@ -443,7 +385,6 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun isVisible_duringRemoteUserInteraction_forcedVisible() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            underTest.setVisible(false, "reason")
            val isVisible by collectLastValue(underTest.isVisible)
            assertThat(isVisible).isFalse()
@@ -458,7 +399,6 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun resolveSceneFamily_home() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            assertThat(underTest.resolveSceneFamily(SceneFamilies.Home))
                .isEqualTo(kosmos.homeSceneFamilyResolver.resolvedScene)
        }
@@ -466,8 +406,46 @@ class SceneInteractorTest : SysuiTestCase() {
    @Test
    fun resolveSceneFamily_nonFamily() =
        testScope.runTest {
            underTest = kosmos.sceneInteractor
            val resolved = underTest.resolveSceneFamily(Scenes.Gone).toList()
            assertThat(resolved).containsExactly(Scenes.Gone).inOrder()
        }

    @Test
    fun transitionValue_test_idle() =
        testScope.runTest {
            val transitionValue by collectLastValue(underTest.transitionProgress(Scenes.Gone))

            kosmos.setSceneTransition(Idle(Scenes.Gone))
            assertThat(transitionValue).isEqualTo(1f)

            kosmos.setSceneTransition(Idle(Scenes.Lockscreen))
            assertThat(transitionValue).isEqualTo(0f)
        }

    @Test
    fun transitionValue_test_transitions() =
        testScope.runTest {
            val transitionValue by collectLastValue(underTest.transitionProgress(Scenes.Gone))
            val progress = MutableStateFlow(0f)

            kosmos.setSceneTransition(
                Transition(from = Scenes.Lockscreen, to = Scenes.Gone, progress = progress)
            )
            assertThat(transitionValue).isEqualTo(0f)

            progress.value = 0.4f
            assertThat(transitionValue).isEqualTo(0.4f)

            kosmos.setSceneTransition(
                Transition(from = Scenes.Gone, to = Scenes.Lockscreen, progress = progress)
            )
            progress.value = 0.7f
            assertThat(transitionValue).isEqualTo(0.3f)

            kosmos.setSceneTransition(
                Transition(from = Scenes.Lockscreen, to = Scenes.Shade, progress = progress)
            )
            progress.value = 0.9f
            assertThat(transitionValue).isEqualTo(0f)
        }
}
+5 −3
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.animation.ValueAnimator.AnimatorUpdateListener
import android.annotation.FloatRange
import android.annotation.SuppressLint
import android.os.Trace
import android.util.Log
import com.android.app.tracing.coroutines.withContext
@@ -117,10 +118,11 @@ class KeyguardTransitionRepositoryImpl
constructor(
    @Main val mainDispatcher: CoroutineDispatcher,
) : KeyguardTransitionRepository {
    /*
     * Each transition between [KeyguardState]s will have an associated Flow.
     * In order to collect these events, clients should call [transition].
    /**
     * Each transition between [KeyguardState]s will have an associated Flow. In order to collect
     * these events, clients should call [transition].
     */
    @SuppressLint("SharedFlowCreation")
    private val _transitions =
        MutableSharedFlow<TransitionStep>(
            replay = 2,
+11 −14
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.CommandQueue
import com.android.systemui.statusbar.notification.NotificationUtils.interpolate
import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine
import com.android.systemui.util.kotlin.Utils.Companion.sampleFilter
import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
@@ -77,6 +77,7 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import com.android.systemui.util.kotlin.Utils.Companion.sample as sampleCombine

/**
 * Encapsulates business-logic related to the keyguard but not to a more specific part within it.
@@ -91,7 +92,7 @@ constructor(
    bouncerRepository: KeyguardBouncerRepository,
    configurationInteractor: ConfigurationInteractor,
    shadeRepository: ShadeRepository,
    keyguardTransitionInteractor: KeyguardTransitionInteractor,
    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
    sceneInteractorProvider: Provider<SceneInteractor>,
    private val fromGoneTransitionInteractor: Provider<FromGoneTransitionInteractor>,
    private val fromLockscreenTransitionInteractor: Provider<FromLockscreenTransitionInteractor>,
@@ -248,21 +249,17 @@ constructor(
    val isKeyguardGoingAway: Flow<Boolean> = repository.isKeyguardGoingAway

    /** Keyguard can be clipped at the top as the shade is dragged */
    val topClippingBounds: Flow<Int?> =
        combineTransform(
                configurationInteractor.onAnyConfigurationChange,
                keyguardTransitionInteractor
                    .transitionValue(GONE)
                    .map { it == 1f }
                    .onStart { emit(false) }
                    .distinctUntilChanged(),
    val topClippingBounds: Flow<Int?> by lazy {
        repository.topClippingBounds
            ) { _, isGone, topClippingBounds ->
                if (!isGone) {
                    emit(topClippingBounds)
                }
            .sampleFilter(
                keyguardTransitionInteractor
                    .transitionValue(scene = Scenes.Gone, stateWithoutSceneContainer = GONE)
                    .onStart { emit(0f) }
            ) { goneValue ->
                goneValue != 1f
            }
            .distinctUntilChanged()
    }

    /** Last point that [KeyguardRootView] view was tapped */
    val lastRootViewTapPosition: Flow<Point?> = repository.lastRootViewTapPosition.asStateFlow()
+15 −0
Original line number Diff line number Diff line
@@ -223,6 +223,17 @@ constructor(
        }
    }

    fun transitionValue(
        scene: SceneKey,
        stateWithoutSceneContainer: KeyguardState,
    ): Flow<Float> {
        return if (SceneContainerFlag.isEnabled) {
            sceneInteractor.get().transitionProgress(scene)
        } else {
            transitionValue(stateWithoutSceneContainer)
        }
    }

    /**
     * The amount of transition into or out of the given [KeyguardState].
     *
@@ -232,6 +243,10 @@ constructor(
    fun transitionValue(
        state: KeyguardState,
    ): Flow<Float> {
        if (SceneContainerFlag.isEnabled && state != state.mapToSceneContainerState()) {
            Log.e(TAG, "SceneContainer is enabled but a deprecated state $state is used.")
            return transitionValue(state.mapToSceneContainerScene()!!, state)
        }
        return getTransitionValueFlow(state)
    }

Loading