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

Commit cdfbe009 authored by Coco Duan's avatar Coco Duan Committed by Android (Google) Code Review
Browse files

Merge changes from topic "hub-gesture-motion-depth-push" into main

* changes:
  Animate depth push scale for hub to AOD transition
  Motion update for swiping between lockscreen and hub
parents a59b570c 1ed88151
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -2057,6 +2057,16 @@ flag {
    }
}

flag {
    name: "gesture_between_hub_and_lockscreen_motion"
    namespace: "systemui"
    description: "Motion update when gestures into and out of glanceable hub from lockscreen."
    bug: "404535174"
    metadata {
      purpose: PURPOSE_BUGFIX
    }
}

flag {
   name: "clear_shortcut_icon_tint"
   namespace: "systemui"
+19 −8
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ import com.android.compose.animation.scene.MutableSceneTransitionLayoutState
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneTransitionLayout
import com.android.compose.animation.scene.Swipe
import com.android.compose.animation.scene.UserActionDistance
import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.observableTransitionState
import com.android.compose.animation.scene.rememberMutableSceneTransitionLayoutState
@@ -115,8 +116,16 @@ val sceneTransitionsV2 = transitions {
    to(CommunalScenes.Communal, key = CommunalTransitionKeys.Swipe) {
        spec = tween(durationMillis = TransitionDuration.TO_GLANCEABLE_HUB_DURATION_MS)
        translate(Communal.Elements.Grid, Edge.End)
        if (Flags.gestureBetweenHubAndLockscreenMotion()) {
            distance = UserActionDistance { fromContent, _, _ ->
                val fromContentSize = checkNotNull(fromContent.targetSize())
                fromContentSize.width * 0.5f
            }
            timestampRange(startMillis = 167, endMillis = 334) { fade(Communal.Elements.StatusBar) }
        } else {
            timestampRange(startMillis = 167, endMillis = 334) { fade(AllElements) }
        }
    }
    to(CommunalScenes.Blank) {
        spec = tween(durationMillis = TO_GONE_DURATION.toInt(DurationUnit.MILLISECONDS))
        fade(AllElements)
@@ -139,6 +148,7 @@ val sceneTransitionsV2 = transitions {
    to(CommunalScenes.Blank, key = CommunalTransitionKeys.Swipe) {
        spec = tween(durationMillis = TransitionDuration.TO_GLANCEABLE_HUB_DURATION_MS)
        translate(Communal.Elements.Grid, Edge.End)
        if (!Flags.gestureBetweenHubAndLockscreenMotion()) {
            timestampRange(endMillis = 167) {
                fade(Communal.Elements.Grid)
                fade(Communal.Elements.IndicationArea)
@@ -149,6 +159,7 @@ val sceneTransitionsV2 = transitions {
            }
            timestampRange(startMillis = 167, endMillis = 334) { fade(Communal.Elements.Scrim) }
        }
    }
    to(CommunalScenes.Blank, key = CommunalTransitionKeys.ToEditMode) {
        spec = tween(durationMillis = TransitionDuration.BETWEEN_HUB_AND_EDIT_MODE_MS)
        fade(AllElements)
+51 −0
Original line number Diff line number Diff line
@@ -296,6 +296,57 @@ class CommunalSceneInteractorTest(flags: FlagsParameterization) : SysuiTestCase(
            assertThat(isIdleOnCommunal).isEqualTo(false)
        }

    @DisableSceneContainer
    @Test
    fun isCommunalSceneTransitioning_isFalse_idleOnCommunalScene() =
        testScope.runTest {
            val isCommunalSceneTransitioning by
                collectLastValue(underTest.isCommunalSceneTransitioning)
            val transitionState: MutableStateFlow<ObservableTransitionState> =
                MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Communal))

            repository.setTransitionState(transitionState)

            assertThat(isCommunalSceneTransitioning).isEqualTo(false)
        }

    @DisableSceneContainer
    @Test
    fun isCommunalSceneTransitioning_isFalse_idleOnBlankScene() =
        testScope.runTest {
            val isCommunalSceneTransitioning by
                collectLastValue(underTest.isCommunalSceneTransitioning)
            val transitionState: MutableStateFlow<ObservableTransitionState> =
                MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Blank))

            repository.setTransitionState(transitionState)

            assertThat(isCommunalSceneTransitioning).isEqualTo(false)
        }

    @DisableSceneContainer
    @Test
    fun isCommunalSceneTransitioning_isTrue_userInitiatedTransition() =
        testScope.runTest {
            val isCommunalSceneTransitioning by
                collectLastValue(underTest.isCommunalSceneTransitioning)
            val transitionState: MutableStateFlow<ObservableTransitionState> =
                MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Blank))

            repository.setTransitionState(transitionState)
            transitionState.value =
                ObservableTransitionState.Transition(
                    fromScene = CommunalScenes.Blank,
                    toScene = CommunalScenes.Communal,
                    currentScene = flowOf(CommunalScenes.Blank),
                    progress = flowOf(0.1f),
                    isInitiatedByUserInput = true,
                    isUserInputOngoing = flowOf(false),
                )

            assertThat(isCommunalSceneTransitioning).isEqualTo(true)
        }

    @DisableSceneContainer
    @Test
    fun isTransitioningToOrIdleOnCommunal() =
+269 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ import android.platform.test.flag.junit.FlagsParameterization
import android.view.View
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.systemui.Flags.FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION
import com.android.systemui.Flags.FLAG_GLANCEABLE_HUB_V2
import com.android.systemui.SysuiTestCase
import com.android.systemui.communal.data.repository.communalSceneRepository
@@ -43,6 +44,8 @@ import com.android.systemui.keyguard.domain.interactor.pulseExpansionInteractor
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.keyguard.ui.viewmodel.KeyguardRootViewModel.Companion.DEPTH_PUSH_WALLPAPER_FROM_GLANCEABLE_HUB
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel.Companion.PUSHBACK_SCALE_FOR_LOCKSCREEN
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
@@ -53,6 +56,7 @@ 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
import com.android.systemui.shared.Flags
import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
@@ -66,6 +70,7 @@ import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.ui.isAnimating
import com.android.systemui.util.ui.stopAnimating
import com.android.systemui.util.ui.value
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.emptyFlow
@@ -546,6 +551,270 @@ class KeyguardRootViewModelTest(flags: FlagsParameterization) : SysuiTestCase()
            assertThat(alpha).isEqualTo(1.0f)
        }

    @Test
    @EnableFlags(FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION)
    @DisableSceneContainer
    fun wallpaperZoomOut_transitionFromLockscreenToHubAndBack() =
        testScope.runTest {
            val zoomOut by collectLastValue(underTest.wallpaperZoomOut)

            val transitionState: MutableStateFlow<ObservableTransitionState> =
                MutableStateFlow(
                    ObservableTransitionState.Transition(
                        fromScene = CommunalScenes.Blank,
                        toScene = CommunalScenes.Communal,
                        currentScene = flowOf(CommunalScenes.Communal),
                        progress = flowOf(0f),
                        isInitiatedByUserInput = true,
                        isUserInputOngoing = flowOf(false),
                    )
                )

            // Start transition to communal
            communalRepository.setTransitionState(transitionState)

            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.GLANCEABLE_HUB,
                testScope,
            )
            // Finish transition to communal
            transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal)

            assertThat(zoomOut).isEqualTo(DEPTH_PUSH_WALLPAPER_FROM_GLANCEABLE_HUB)

            // Start transitioning back.
            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.GLANCEABLE_HUB,
                to = KeyguardState.LOCKSCREEN,
                testScope,
            )
            transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank)

            assertThat(zoomOut).isEqualTo(0f)
        }

    @Test
    @DisableSceneContainer
    @EnableFlags(FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION)
    fun wallpaperZoomOut_reset_transitionedAwayFromHub() =
        testScope.runTest {
            val zoomOut by collectLastValue(underTest.wallpaperZoomOut)
            val transitionState: MutableStateFlow<ObservableTransitionState> =
                MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Blank))

            // Transition to the glanceable hub and then to bouncer.
            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.GLANCEABLE_HUB,
                testScope,
            )
            transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal)

            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.GLANCEABLE_HUB,
                to = KeyguardState.PRIMARY_BOUNCER,
                testScope,
            )
            transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank)

            assertThat(zoomOut).isEqualTo(0f)
        }

    @Test
    @DisableSceneContainer
    @EnableFlags(FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION)
    fun scaleFromGlanceableHub_transitionFromLockscreenToHubAndBack() =
        testScope.runTest {
            val scaleToApply by collectLastValue(underTest.scaleFromZoomOut)
            val transitionState: MutableStateFlow<ObservableTransitionState> =
                MutableStateFlow(
                    ObservableTransitionState.Transition(
                        fromScene = CommunalScenes.Blank,
                        toScene = CommunalScenes.Communal,
                        currentScene = flowOf(CommunalScenes.Blank),
                        progress = flowOf(0f),
                        isInitiatedByUserInput = true,
                        isUserInputOngoing = flowOf(false),
                    )
                )

            // Start transition to communal.
            communalRepository.setTransitionState(transitionState)

            // Transition to the glanceable hub and back.
            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.GLANCEABLE_HUB,
                testScope,
            )
            transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal)

            assertThat(scaleToApply).isEqualTo(1 - PUSHBACK_SCALE_FOR_LOCKSCREEN)

            // Start transitioning back.
            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.GLANCEABLE_HUB,
                to = KeyguardState.LOCKSCREEN,
                testScope,
            )
            transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank)

            assertThat(scaleToApply).isEqualTo(1f)
        }

    @Test
    @DisableSceneContainer
    @EnableFlags(FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION)
    fun scaleFromGlanceableHub_reset_transitionedAwayFromHub() =
        testScope.runTest {
            val scaleToApply by collectLastValue(underTest.scaleFromZoomOut)
            val transitionState: MutableStateFlow<ObservableTransitionState> =
                MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Blank))

            // Transition to the glanceable hub and then to bouncer.
            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.GLANCEABLE_HUB,
                testScope,
            )
            transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal)

            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.GLANCEABLE_HUB,
                to = KeyguardState.PRIMARY_BOUNCER,
                testScope,
            )
            transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank)

            assertThat(scaleToApply).isEqualTo(1f)
        }

    @Test
    @DisableSceneContainer
    @EnableFlags(FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION)
    fun scaleFromGlanceableHub_reset_whenTransitionedFromHubToAod() =
        testScope.runTest {
            val scaleToApply by collectLastValue(underTest.scaleFromZoomOut)

            // Start on communal scene.
            val transitionState: MutableStateFlow<ObservableTransitionState> =
                MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Communal))
            communalRepository.setTransitionState(transitionState)

            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
                to = KeyguardState.GLANCEABLE_HUB,
                testScope,
            )

            assertThat(scaleToApply).isEqualTo(1 - PUSHBACK_SCALE_FOR_LOCKSCREEN)

            // Start transition to AOD
            transitionState.value =
                ObservableTransitionState.Transition(
                    fromScene = CommunalScenes.Communal,
                    toScene = CommunalScenes.Blank,
                    currentScene = flowOf(CommunalScenes.Communal),
                    progress = flowOf(0f),
                    isInitiatedByUserInput = true,
                    isUserInputOngoing = flowOf(false),
                )
            keyguardTransitionRepository.sendTransitionSteps(
                listOf(
                    TransitionStep(
                        transitionState = TransitionState.STARTED,
                        from = KeyguardState.GLANCEABLE_HUB,
                        to = KeyguardState.AOD,
                    ),
                    TransitionStep(
                        transitionState = TransitionState.RUNNING,
                        from = KeyguardState.GLANCEABLE_HUB,
                        to = KeyguardState.AOD,
                        value = 0.6f,
                    ),
                ),
                testScope,
            )
            runCurrent()

            assertThat(scaleToApply).isIn(Range.open(1 - PUSHBACK_SCALE_FOR_LOCKSCREEN, 1f))

            keyguardTransitionRepository.sendTransitionStep(
                TransitionStep(
                    transitionState = TransitionState.FINISHED,
                    from = KeyguardState.GLANCEABLE_HUB,
                    to = KeyguardState.AOD,
                )
            )
            runCurrent()
            transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Blank)

            assertThat(scaleToApply).isEqualTo(1f)
        }

    @Test
    @DisableSceneContainer
    @EnableFlags(Flags.FLAG_AMBIENT_AOD, FLAG_GESTURE_BETWEEN_HUB_AND_LOCKSCREEN_MOTION)
    fun scaleFromGlanceableHub_whenTransitionedFromAodToHub() =
        testScope.runTest {
            val scaleToApply by collectLastValue(underTest.scaleFromZoomOut)

            // Start on blank scene.
            val transitionState: MutableStateFlow<ObservableTransitionState> =
                MutableStateFlow(ObservableTransitionState.Idle(CommunalScenes.Blank))
            communalRepository.setTransitionState(transitionState)

            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.GLANCEABLE_HUB,
                to = KeyguardState.AOD,
                testScope,
            )

            assertThat(scaleToApply).isEqualTo(1f)

            // Start transition to hub.
            transitionState.value =
                ObservableTransitionState.Transition(
                    fromScene = CommunalScenes.Blank,
                    toScene = CommunalScenes.Communal,
                    currentScene = flowOf(CommunalScenes.Blank),
                    progress = flowOf(0f),
                    isInitiatedByUserInput = true,
                    isUserInputOngoing = flowOf(false),
                )
            keyguardTransitionRepository.sendTransitionSteps(
                listOf(
                    TransitionStep(
                        transitionState = TransitionState.STARTED,
                        from = KeyguardState.AOD,
                        to = KeyguardState.GLANCEABLE_HUB,
                    ),
                    TransitionStep(
                        transitionState = TransitionState.RUNNING,
                        from = KeyguardState.AOD,
                        to = KeyguardState.GLANCEABLE_HUB,
                        value = 0.2f,
                    ),
                ),
                testScope,
            )

            assertThat(scaleToApply).isIn(Range.open(1 - PUSHBACK_SCALE_FOR_LOCKSCREEN, 1f))

            keyguardTransitionRepository.sendTransitionStep(
                TransitionStep(
                    transitionState = TransitionState.FINISHED,
                    from = KeyguardState.AOD,
                    to = KeyguardState.GLANCEABLE_HUB,
                )
            )
            runCurrent()
            transitionState.value = ObservableTransitionState.Idle(CommunalScenes.Communal)

            assertThat(scaleToApply).isEqualTo(1f - PUSHBACK_SCALE_FOR_LOCKSCREEN)
        }

    @Test
    fun alpha_emitsOnShadeExpansion() =
        testScope.runTest {
+6 −0
Original line number Diff line number Diff line
@@ -369,6 +369,12 @@ constructor(
                initialValue = false,
            )

    /** Flow that emits a boolean if user is swiping between two scenes. */
    val isCommunalSceneTransitioning: Flow<Boolean> =
        transitionState
            .map { it is ObservableTransitionState.Transition && it.isInitiatedByUserInput }
            .distinctUntilChanged()

    private companion object {
        const val TAG = "CommunalSceneInteractor"
    }
Loading