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

Commit ac37a85b authored by Michal Brzezinski's avatar Michal Brzezinski Committed by Michał Brzeziński
Browse files

Excluding non-folding related states from tracking

Because we only check if new/old state is FOLD, we handle all state transitions, even if they are not folding related. That can negatively affect our display switch tracking.
Let's focus only on folding states until we figure out what to do with other states.

Bug: 395087032
Test: FoldableDisplaySwitchTrackingInteractorTest
Flag: EXEMPT bugfix
Change-Id: If1e71e144743286823bc07cf8bf450bf7c6b8e79
parent 8c4f5b3f
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -43,6 +43,7 @@ import com.android.systemui.unfold.data.repository.UnfoldTransitionRepositoryImp
import com.android.systemui.unfold.domain.interactor.DisplaySwitchState.Corrupted
import com.android.systemui.unfold.domain.interactor.DisplaySwitchState.Idle
import com.android.systemui.unfold.domain.interactor.DisplaySwitchState.Switching
import com.android.systemui.unfold.domain.interactor.DisplaySwitchState.Unknown
import com.android.systemui.unfold.domain.interactor.FoldableDisplaySwitchTrackingInteractor.Companion.COOL_DOWN_DURATION
import com.android.systemui.unfold.domain.interactor.FoldableDisplaySwitchTrackingInteractor.Companion.SCREEN_EVENT_TIMEOUT
import com.android.systemui.util.animation.data.repository.fakeAnimationStatusRepository
@@ -204,6 +205,42 @@ class FoldableDisplaySwitchTrackingInteractorTest : SysuiTestCase() {
        }
    }

    @Test
    fun switchingToNonFoldingRelatedStates_isIgnored() {
        testScope.runTest {
            val emittedStates by collectValues(displaySwitchInteractor.displaySwitchState)
            val startingStates = listOf(UNFOLDED, FOLDED, HALF_FOLDED)
            val targetStates = DeviceState.entries - startingStates

            startingStates.forEach { startingState ->
                targetStates.forEach { targetState ->
                    setDeviceState(startingState)
                    setDeviceState(targetState)
                }
            }

            assertThat(emittedStates).containsExactly(Unknown, Idle(UNFOLDED))
        }
    }

    @Test
    fun switchingFromNonFoldingRelatedStates_isIgnored() {
        testScope.runTest {
            val emittedStates by collectValues(displaySwitchInteractor.displaySwitchState)

            val targetStates = listOf(UNFOLDED, FOLDED, HALF_FOLDED)
            val startingStates = DeviceState.entries - targetStates
            startingStates.forEach { startingState ->
                targetStates.forEach { targetState ->
                    setDeviceState(startingState)
                    setDeviceState(targetState)
                }
            }

            assertThat(emittedStates).containsExactly(Unknown, Idle(UNFOLDED))
        }
    }

    @Test
    fun folding_screenTurnsOn_emitsIdle() {
        testScope.runTest {
+10 −6
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.display.data.repository.DeviceStateRepository
import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState
import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState.FOLDED
import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState.HALF_FOLDED
import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState.UNFOLDED
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.shared.model.ScreenPowerState
@@ -118,14 +121,15 @@ constructor(
    override val displaySwitchState: StateFlow<DisplaySwitchState> = _displaySwitchState

    private val displaySwitchStarted =
        deviceStateRepository.state.pairwise().filter {
        deviceStateRepository.state.pairwise().filter { (previousState, newState) ->
            // React only when the foldable device is
            // folding(UNFOLDED/HALF_FOLDED -> FOLDED) or unfolding(FOLDED -> HALF_FOLD/UNFOLDED)
            foldableDeviceState ->
            foldableDeviceState.previousValue == DeviceState.FOLDED ||
                foldableDeviceState.newValue == DeviceState.FOLDED
            (previousState == FOLDED && newState.isUnfoldingState()) ||
                (newState == FOLDED && previousState.isUnfoldingState())
        }

    private fun DeviceState.isUnfoldingState() = this == HALF_FOLDED || this == UNFOLDED

    private val startOrEndEvent: Flow<Any> = merge(displaySwitchStarted, anyEndEventFlow())

    private var isCoolingDown = false
@@ -133,7 +137,7 @@ constructor(
    override fun start() {
        scope.launch {
            _displaySwitchState.value =
                Idle(deviceStateRepository.state.first { it != DeviceState.UNKNOWN })
                Idle(deviceStateRepository.state.first { it == FOLDED || it.isUnfoldingState() })
            displaySwitchStarted.collectLatest { (previousState, newState) ->
                if (isCoolingDown) return@collectLatest
                log { "received previousState=$previousState, newState=$newState" }
@@ -203,7 +207,7 @@ constructor(
    private fun shouldWaitForTransitionStart(
        toFoldableDeviceState: DeviceState,
        isTransitionEnabled: Boolean,
    ): Boolean = (toFoldableDeviceState != DeviceState.FOLDED && isTransitionEnabled)
    ): Boolean = (toFoldableDeviceState != FOLDED && isTransitionEnabled)

    private suspend fun waitForScreenTurnedOn() {
        traceAsync(TAG, "waitForScreenTurnedOn()") {