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

Commit ab7464dd authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Haptics on pulling down the shade also consider remote user input." into main

parents 9fea6f2c ebcd3083
Loading
Loading
Loading
Loading
+55 −3
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import com.android.compose.animation.scene.OverlayKey
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.Flags
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.haptics.msdl.fakeMSDLPlayer
import com.android.systemui.kosmos.testScope
@@ -39,9 +40,11 @@ import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.domain.interactor.disableDualShade
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.testKosmos
import com.google.android.msdl.data.model.MSDLToken
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
@@ -54,6 +57,7 @@ import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.verifyNoMoreInteractions

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
@EnableSceneContainer
@@ -209,7 +213,55 @@ class SceneContainerHapticsViewModelTest : SysuiTestCase() {
            verifyNoMoreInteractions(view)
        }

    private fun createTransitionState(from: SceneKey, to: ContentKey) =
    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
    @Test
    fun onRemoteUserInteraction_withValidSceneTransition_playsMSDLShadePullHaptics() =
        testScope.runTest {
            kosmos.disableDualShade()
            val isUserInteracting by collectLastValue(kosmos.shadeInteractor.isUserInteracting)

            // GIVEN a valid scene transition to play haptics that initiated remotely
            val validTransition =
                createTransitionState(from = Scenes.Gone, to = Scenes.Shade, byUser = false)
            sceneInteractor.onRemoteUserInputStarted("remote input")

            // WHEN the transition occurs
            sceneInteractor.setTransitionState(MutableStateFlow(validTransition))
            runCurrent()
            assertThat(isUserInteracting).isFalse()

            // THEN the expected token plays without interaction properties
            assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.SWIPE_THRESHOLD_INDICATOR)
            assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
        }

    @EnableFlags(Flags.FLAG_MSDL_FEEDBACK)
    @Test
    fun onRemoteUserInteraction_withValidOverlayTransition_playsMSDLShadePullHaptics() =
        testScope.runTest {
            kosmos.enableDualShade()
            val isUserInteracting by collectLastValue(kosmos.shadeInteractor.isUserInteracting)

            // GIVEN a valid scene transition to play haptics that initiated remotely
            val validTransition =
                createTransitionState(
                    from = Scenes.Gone,
                    to = Overlays.NotificationsShade,
                    byUser = false,
                )
            sceneInteractor.onRemoteUserInputStarted("remote input")

            // WHEN the transition occurs
            sceneInteractor.setTransitionState(MutableStateFlow(validTransition))
            runCurrent()
            assertThat(isUserInteracting).isFalse()

            // THEN the expected token plays without interaction properties
            assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.SWIPE_THRESHOLD_INDICATOR)
            assertThat(msdlPlayer.latestPropertiesPlayed).isNull()
        }

    private fun createTransitionState(from: SceneKey, to: ContentKey, byUser: Boolean = true) =
        when (to) {
            is SceneKey ->
                ObservableTransitionState.Transition(
@@ -217,7 +269,7 @@ class SceneContainerHapticsViewModelTest : SysuiTestCase() {
                    toScene = to,
                    currentScene = flowOf(from),
                    progress = MutableStateFlow(0.2f),
                    isInitiatedByUserInput = true,
                    isInitiatedByUserInput = byUser,
                    isUserInputOngoing = flowOf(true),
                )
            is OverlayKey ->
@@ -228,7 +280,7 @@ class SceneContainerHapticsViewModelTest : SysuiTestCase() {
                    currentScene = from,
                    currentOverlays = sceneInteractor.currentOverlays,
                    progress = MutableStateFlow(0.2f),
                    isInitiatedByUserInput = true,
                    isInitiatedByUserInput = byUser,
                    isUserInputOngoing = flowOf(true),
                    previewProgress = flowOf(0f),
                    isInPreviewStage = flowOf(false),
+7 −4
Original line number Diff line number Diff line
@@ -57,10 +57,13 @@ constructor(

    /** Should haptics be played by pulling down the shade */
    private val isShadePullHapticsRequired: Flow<Boolean> =
        combine(shadeInteractor.isUserInteracting, sceneInteractor.transitionState) {
                interacting,
                transitionState ->
                interacting && transitionState.isValidForShadePullHaptics()
        combine(
                shadeInteractor.isUserInteracting,
                sceneInteractor.transitionState,
                sceneInteractor.isRemoteUserInteractionOngoing,
            ) { interacting, transitionState, remoteInteractionGoing ->
                val validInteraction = interacting || remoteInteractionGoing
                validInteraction && transitionState.isValidForShadePullHaptics()
            }
            .distinctUntilChanged()