Loading packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt +47 −35 Original line number Diff line number Diff line Loading @@ -31,17 +31,13 @@ import com.android.systemui.deviceStateManager 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.display.data.repository.fakeDeviceStateRepository import com.android.systemui.foldedDeviceStateList import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setScreenPowerState import com.android.systemui.power.domain.interactor.PowerInteractorFactory import com.android.systemui.power.shared.model.ScreenPowerState.SCREEN_OFF import com.android.systemui.power.shared.model.ScreenPowerState.SCREEN_ON import com.android.systemui.shared.system.SysUiStatsLog import com.android.systemui.testKosmos import com.android.systemui.unfold.DisplaySwitchLatencyTracker.Companion.FOLDABLE_DEVICE_STATE_CLOSED Loading Loading @@ -82,7 +78,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { private val testScope: TestScope = kosmos.testScope private val resources = mock<Resources>() private val deviceStateRepository = kosmos.fakeDeviceStateRepository private val powerInteractor = PowerInteractorFactory.create().powerInteractor private val keyguardInteractor = mock<KeyguardInteractor>() private val displaySwitchLatencyLogger = mock<DisplaySwitchLatencyLogger>() Loading @@ -106,7 +101,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { whenever(keyguardInteractor.isAodAvailable).thenReturn(isAodAvailable) whenever(screenTimeoutPolicyRepository.screenTimeoutActive).thenReturn(screenTimeoutActive) powerInteractor.setAwakeForTest() powerInteractor.setScreenPowerState(SCREEN_ON) setDisplaySwitchState(Idle(newDeviceState = FOLDED)) Loading Loading @@ -166,7 +160,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { setDisplaySwitchState(Idle(HALF_FOLDED)) setDisplaySwitchState(Switching(HALF_FOLDED)) powerInteractor.setScreenPowerState(SCREEN_ON) systemClock.advanceTime(200) setDisplaySwitchState(Idle(FOLDED)) Loading @@ -185,22 +178,13 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { testScope.runTest { isAodAvailable.emit(true) setDisplaySwitchState(Idle(HALF_FOLDED)) setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Switching(HALF_FOLDED)) powerInteractor.setAsleepForTest(sleepReason = GO_TO_SLEEP_REASON_DEVICE_FOLD) powerInteractor.setScreenPowerState(SCREEN_OFF) systemClock.advanceTime(200) setDisplaySwitchState(Idle(FOLDED)) val expectedLoggedEvent = successfulEvent( latencyMs = 200, fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN, toFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED, toState = SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__AOD, ) assertThat(capturedLogEvent()).isEqualTo(expectedLoggedEvent) assertThat(capturedLogEvent().toState) .isEqualTo(SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__AOD) } } Loading @@ -211,20 +195,54 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { isAodAvailable.emit(false) setDisplaySwitchState(Switching(HALF_FOLDED)) powerInteractor.setAsleepForTest(sleepReason = GO_TO_SLEEP_REASON_DEVICE_FOLD) powerInteractor.setScreenPowerState(SCREEN_OFF) setDisplaySwitchState(Idle(FOLDED)) assertThat(capturedLogEvent().toState) .isEqualTo(SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF) } } @Test fun foldingWhileScreenIsAlreadyOff_capturesToStateAsScreenOff() { testScope.runTest { setDisplaySwitchState(Idle(HALF_FOLDED)) powerInteractor.setAsleepForTest() setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Idle(FOLDED)) val expectedLoggedEvent = successfulEvent( latencyMs = 0, fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN, toFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED, toState = SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF, ) assertThat(capturedLogEvent()).isEqualTo(expectedLoggedEvent) assertThat(capturedLogEvent().toState) .isEqualTo(SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF) } } @Test fun foldingWhileScreenIsAlreadyOff_capturesFromStateAsScreenOff() { testScope.runTest { setDisplaySwitchState(Idle(HALF_FOLDED)) powerInteractor.setAsleepForTest() setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Idle(FOLDED)) assertThat(capturedLogEvent().fromState) .isEqualTo(SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__SCREEN_OFF) } } @Test fun foldingWhileAod_capturesFromStateAsAod() { testScope.runTest { setDisplaySwitchState(Idle(HALF_FOLDED)) powerInteractor.setAsleepForTest() isAodAvailable.value = true setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Idle(FOLDED)) assertThat(capturedLogEvent().fromState) .isEqualTo(SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__AOD) } } Loading @@ -237,7 +255,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { setDisplaySwitchState(Switching(HALF_FOLDED)) powerInteractor.setAsleepForTest(sleepReason = GO_TO_SLEEP_REASON_DEVICE_FOLD) powerInteractor.setScreenPowerState(SCREEN_OFF) setDisplaySwitchState(Idle(FOLDED)) Loading Loading @@ -303,7 +320,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { setDisplaySwitchState(Idle(HALF_FOLDED)) setDisplaySwitchState(Switching(FOLDED)) powerInteractor.setScreenPowerState(SCREEN_ON) setDisplaySwitchState(Idle(FOLDED)) verify(latencyTracker).onActionEnd(ACTION_SWITCH_DISPLAY_FOLD) Loading Loading @@ -349,7 +365,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Corrupted(HALF_FOLDED)) powerInteractor.setScreenPowerState(SCREEN_ON) setDisplaySwitchState(Idle(UNFOLDED)) verify(latencyTracker).onActionCancel(ACTION_SWITCH_DISPLAY_FOLD) Loading @@ -363,7 +378,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Corrupted(HALF_FOLDED)) setDisplaySwitchState(Idle(FOLDED)) powerInteractor.setScreenPowerState(SCREEN_ON) setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Idle(UNFOLDED)) Loading @@ -381,7 +395,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { setDisplaySwitchState(Idle(UNFOLDED)) setDisplaySwitchState(Switching(FOLDED)) powerInteractor.setScreenPowerState(SCREEN_ON) setDisplaySwitchState(Idle(FOLDED)) verify(latencyTracker, times(2)).onActionStart(ACTION_SWITCH_DISPLAY_FOLD) Loading Loading @@ -420,7 +433,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { fun displaySwitchTimedOut_foldTrackingCancelled() { testScope.runTest { setDisplaySwitchState(Switching(HALF_FOLDED)) powerInteractor.setScreenPowerState(SCREEN_ON) setDisplaySwitchState(Idle(FOLDED, timedOut = true)) Loading packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt +24 −13 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.power.shared.model.WakeSleepReason import com.android.systemui.shared.system.SysUiStatsLog import com.android.systemui.unfold.DisplaySwitchLatencyTracker.DisplaySwitchLatencyEvent import com.android.systemui.unfold.DisplaySwitchLatencyTracker.TrackingResult.CORRUPTED Loading Loading @@ -103,7 +102,7 @@ constructor( } else { latencyTracker.onActionEnd(ACTION_SWITCH_DISPLAY_UNFOLD) if (getCurrentState() if (getToState() != SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF ) { latencyTracker.onActionEnd(ACTION_SWITCH_DISPLAY_FOLD) Loading Loading @@ -150,8 +149,13 @@ constructor( else -> SUCCESS } val event = switchingUpdate.event ?: return val displaySwitchTimeMs = updatesChain.finalUpdate.elapsedTime - switchingUpdate.elapsedTime val toState = getCurrentState() val toState = getToState() val displaySwitchTimeMs = if (isStateScreenOff()) { LATENCY_UNDEFINED // we don't care about latency in this case } else { updatesChain.finalUpdate.elapsedTime - switchingUpdate.elapsedTime } log { "trackingResult=$trackingResult, " + "fromFoldableDeviceState=${startingIdleState.switchState.newDeviceState}" + Loading Loading @@ -232,23 +236,29 @@ constructor( TIMED_OUT -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TRACKING_RESULT__TIMED_OUT } private fun getCurrentState(): Int = private fun getToState(): Int = // not checking asleep/screen off reason means we misrepresent toState for case when user // folds and quickly puts device to sleep with power button. But still it seems better // than not putting SCREEN_OFF as reason when device is just asleep and user folds. when { isStateAod() -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__AOD isStateScreenOff() -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF else -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__UNKNOWN } private fun isStateAod(): Boolean = (isAsleepDueToFold() && isAodEnabled) private fun getFromState(): Int = when { isStateAod() -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__AOD isStateScreenOff() -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__SCREEN_OFF else -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__UNKNOWN } private fun isStateScreenOff(): Boolean = (isAsleepDueToFold() && !isAodEnabled) private fun isStateAod() = isAsleep() && isAodEnabled private fun isAsleepDueToFold(): Boolean { val lastWakefulnessEvent = powerInteractor.detailedWakefulness.value private fun isStateScreenOff() = isAsleep() && !isAodEnabled return (lastWakefulnessEvent.isAsleep() && (lastWakefulnessEvent.lastSleepReason == WakeSleepReason.FOLD)) } private fun isAsleep() = powerInteractor.detailedWakefulness.value.isAsleep() private inline fun log(msg: () -> String) { if (DEBUG) Log.d(TAG, msg()) Loading @@ -262,7 +272,7 @@ constructor( } else { HAS_SCREEN_WAKELOCKS } return copy(screenWakelockStatus = screenWakelockStatus) return copy(screenWakelockStatus = screenWakelockStatus, fromState = getFromState()) } /** Loading Loading @@ -310,6 +320,7 @@ constructor( companion object { private const val VALUE_UNKNOWN = -1 private const val LATENCY_UNDEFINED = -1 private const val TAG = "DisplaySwitchLatency" private val DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE) Loading packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/FoldableDisplaySwitchTrackingInteractor.kt +10 −6 Original line number Diff line number Diff line Loading @@ -72,20 +72,24 @@ sealed interface DisplaySwitchState { /** * Displays are in a stable state aka not in the process of switching. If we couldn't track * display switch properly because end event never arrived within [SCREEN_EVENT_TIMEOUT], * [timedOut] is set to true. * display switch properly because end event never arrived within * [FoldableDisplaySwitchTrackingInteractor.SCREEN_EVENT_TIMEOUT], [timedOut] is set to true. */ data class Idle(override val newDeviceState: DeviceState, val timedOut: Boolean = false) : DisplaySwitchState /** Displays are currently switching. This state can only come directly after [Idle] state. */ /** * Displays are currently switching. This state can only come directly after [Idle] state. * Switching might not be visible to the user, that is, folding device with screen off still * emits Switching event as we're swapping default displays. */ data class Switching(override val newDeviceState: DeviceState) : DisplaySwitchState /** * Switching displays happened multiple times before [Idle] state could settle. This state will * hold until no new display switch related events are sent within [COOL_DOWN_DURATION] window. * This event can only happen directly after [Switching] state and is always directly followed * by [Idle] state. * hold until no new display switch related events are sent within * [FoldableDisplaySwitchTrackingInteractor.COOL_DOWN_DURATION] window. This event can only * happen directly after [Switching] state and is always directly followed by [Idle] state. */ data class Corrupted(override val newDeviceState: DeviceState) : DisplaySwitchState Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/unfold/DisplaySwitchLatencyTrackerTest.kt +47 −35 Original line number Diff line number Diff line Loading @@ -31,17 +31,13 @@ import com.android.systemui.deviceStateManager 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.display.data.repository.fakeDeviceStateRepository import com.android.systemui.foldedDeviceStateList import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.kosmos.testScope import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setScreenPowerState import com.android.systemui.power.domain.interactor.PowerInteractorFactory import com.android.systemui.power.shared.model.ScreenPowerState.SCREEN_OFF import com.android.systemui.power.shared.model.ScreenPowerState.SCREEN_ON import com.android.systemui.shared.system.SysUiStatsLog import com.android.systemui.testKosmos import com.android.systemui.unfold.DisplaySwitchLatencyTracker.Companion.FOLDABLE_DEVICE_STATE_CLOSED Loading Loading @@ -82,7 +78,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { private val testScope: TestScope = kosmos.testScope private val resources = mock<Resources>() private val deviceStateRepository = kosmos.fakeDeviceStateRepository private val powerInteractor = PowerInteractorFactory.create().powerInteractor private val keyguardInteractor = mock<KeyguardInteractor>() private val displaySwitchLatencyLogger = mock<DisplaySwitchLatencyLogger>() Loading @@ -106,7 +101,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { whenever(keyguardInteractor.isAodAvailable).thenReturn(isAodAvailable) whenever(screenTimeoutPolicyRepository.screenTimeoutActive).thenReturn(screenTimeoutActive) powerInteractor.setAwakeForTest() powerInteractor.setScreenPowerState(SCREEN_ON) setDisplaySwitchState(Idle(newDeviceState = FOLDED)) Loading Loading @@ -166,7 +160,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { setDisplaySwitchState(Idle(HALF_FOLDED)) setDisplaySwitchState(Switching(HALF_FOLDED)) powerInteractor.setScreenPowerState(SCREEN_ON) systemClock.advanceTime(200) setDisplaySwitchState(Idle(FOLDED)) Loading @@ -185,22 +178,13 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { testScope.runTest { isAodAvailable.emit(true) setDisplaySwitchState(Idle(HALF_FOLDED)) setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Switching(HALF_FOLDED)) powerInteractor.setAsleepForTest(sleepReason = GO_TO_SLEEP_REASON_DEVICE_FOLD) powerInteractor.setScreenPowerState(SCREEN_OFF) systemClock.advanceTime(200) setDisplaySwitchState(Idle(FOLDED)) val expectedLoggedEvent = successfulEvent( latencyMs = 200, fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN, toFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED, toState = SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__AOD, ) assertThat(capturedLogEvent()).isEqualTo(expectedLoggedEvent) assertThat(capturedLogEvent().toState) .isEqualTo(SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__AOD) } } Loading @@ -211,20 +195,54 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { isAodAvailable.emit(false) setDisplaySwitchState(Switching(HALF_FOLDED)) powerInteractor.setAsleepForTest(sleepReason = GO_TO_SLEEP_REASON_DEVICE_FOLD) powerInteractor.setScreenPowerState(SCREEN_OFF) setDisplaySwitchState(Idle(FOLDED)) assertThat(capturedLogEvent().toState) .isEqualTo(SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF) } } @Test fun foldingWhileScreenIsAlreadyOff_capturesToStateAsScreenOff() { testScope.runTest { setDisplaySwitchState(Idle(HALF_FOLDED)) powerInteractor.setAsleepForTest() setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Idle(FOLDED)) val expectedLoggedEvent = successfulEvent( latencyMs = 0, fromFoldableDeviceState = FOLDABLE_DEVICE_STATE_HALF_OPEN, toFoldableDeviceState = FOLDABLE_DEVICE_STATE_CLOSED, toState = SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF, ) assertThat(capturedLogEvent()).isEqualTo(expectedLoggedEvent) assertThat(capturedLogEvent().toState) .isEqualTo(SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF) } } @Test fun foldingWhileScreenIsAlreadyOff_capturesFromStateAsScreenOff() { testScope.runTest { setDisplaySwitchState(Idle(HALF_FOLDED)) powerInteractor.setAsleepForTest() setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Idle(FOLDED)) assertThat(capturedLogEvent().fromState) .isEqualTo(SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__SCREEN_OFF) } } @Test fun foldingWhileAod_capturesFromStateAsAod() { testScope.runTest { setDisplaySwitchState(Idle(HALF_FOLDED)) powerInteractor.setAsleepForTest() isAodAvailable.value = true setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Idle(FOLDED)) assertThat(capturedLogEvent().fromState) .isEqualTo(SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__AOD) } } Loading @@ -237,7 +255,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { setDisplaySwitchState(Switching(HALF_FOLDED)) powerInteractor.setAsleepForTest(sleepReason = GO_TO_SLEEP_REASON_DEVICE_FOLD) powerInteractor.setScreenPowerState(SCREEN_OFF) setDisplaySwitchState(Idle(FOLDED)) Loading Loading @@ -303,7 +320,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { setDisplaySwitchState(Idle(HALF_FOLDED)) setDisplaySwitchState(Switching(FOLDED)) powerInteractor.setScreenPowerState(SCREEN_ON) setDisplaySwitchState(Idle(FOLDED)) verify(latencyTracker).onActionEnd(ACTION_SWITCH_DISPLAY_FOLD) Loading Loading @@ -349,7 +365,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Corrupted(HALF_FOLDED)) powerInteractor.setScreenPowerState(SCREEN_ON) setDisplaySwitchState(Idle(UNFOLDED)) verify(latencyTracker).onActionCancel(ACTION_SWITCH_DISPLAY_FOLD) Loading @@ -363,7 +378,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Corrupted(HALF_FOLDED)) setDisplaySwitchState(Idle(FOLDED)) powerInteractor.setScreenPowerState(SCREEN_ON) setDisplaySwitchState(Switching(HALF_FOLDED)) setDisplaySwitchState(Idle(UNFOLDED)) Loading @@ -381,7 +395,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { setDisplaySwitchState(Idle(UNFOLDED)) setDisplaySwitchState(Switching(FOLDED)) powerInteractor.setScreenPowerState(SCREEN_ON) setDisplaySwitchState(Idle(FOLDED)) verify(latencyTracker, times(2)).onActionStart(ACTION_SWITCH_DISPLAY_FOLD) Loading Loading @@ -420,7 +433,6 @@ class DisplaySwitchLatencyTrackerTest : SysuiTestCase() { fun displaySwitchTimedOut_foldTrackingCancelled() { testScope.runTest { setDisplaySwitchState(Switching(HALF_FOLDED)) powerInteractor.setScreenPowerState(SCREEN_ON) setDisplaySwitchState(Idle(FOLDED, timedOut = true)) Loading
packages/SystemUI/src/com/android/systemui/unfold/DisplaySwitchLatencyTracker.kt +24 −13 Original line number Diff line number Diff line Loading @@ -28,7 +28,6 @@ import com.android.systemui.dagger.SysUISingleton import com.android.systemui.display.data.repository.DeviceStateRepository.DeviceState import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.power.shared.model.WakeSleepReason import com.android.systemui.shared.system.SysUiStatsLog import com.android.systemui.unfold.DisplaySwitchLatencyTracker.DisplaySwitchLatencyEvent import com.android.systemui.unfold.DisplaySwitchLatencyTracker.TrackingResult.CORRUPTED Loading Loading @@ -103,7 +102,7 @@ constructor( } else { latencyTracker.onActionEnd(ACTION_SWITCH_DISPLAY_UNFOLD) if (getCurrentState() if (getToState() != SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF ) { latencyTracker.onActionEnd(ACTION_SWITCH_DISPLAY_FOLD) Loading Loading @@ -150,8 +149,13 @@ constructor( else -> SUCCESS } val event = switchingUpdate.event ?: return val displaySwitchTimeMs = updatesChain.finalUpdate.elapsedTime - switchingUpdate.elapsedTime val toState = getCurrentState() val toState = getToState() val displaySwitchTimeMs = if (isStateScreenOff()) { LATENCY_UNDEFINED // we don't care about latency in this case } else { updatesChain.finalUpdate.elapsedTime - switchingUpdate.elapsedTime } log { "trackingResult=$trackingResult, " + "fromFoldableDeviceState=${startingIdleState.switchState.newDeviceState}" + Loading Loading @@ -232,23 +236,29 @@ constructor( TIMED_OUT -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TRACKING_RESULT__TIMED_OUT } private fun getCurrentState(): Int = private fun getToState(): Int = // not checking asleep/screen off reason means we misrepresent toState for case when user // folds and quickly puts device to sleep with power button. But still it seems better // than not putting SCREEN_OFF as reason when device is just asleep and user folds. when { isStateAod() -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__AOD isStateScreenOff() -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__SCREEN_OFF else -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__TO_STATE__UNKNOWN } private fun isStateAod(): Boolean = (isAsleepDueToFold() && isAodEnabled) private fun getFromState(): Int = when { isStateAod() -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__AOD isStateScreenOff() -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__SCREEN_OFF else -> SysUiStatsLog.DISPLAY_SWITCH_LATENCY_TRACKED__FROM_STATE__UNKNOWN } private fun isStateScreenOff(): Boolean = (isAsleepDueToFold() && !isAodEnabled) private fun isStateAod() = isAsleep() && isAodEnabled private fun isAsleepDueToFold(): Boolean { val lastWakefulnessEvent = powerInteractor.detailedWakefulness.value private fun isStateScreenOff() = isAsleep() && !isAodEnabled return (lastWakefulnessEvent.isAsleep() && (lastWakefulnessEvent.lastSleepReason == WakeSleepReason.FOLD)) } private fun isAsleep() = powerInteractor.detailedWakefulness.value.isAsleep() private inline fun log(msg: () -> String) { if (DEBUG) Log.d(TAG, msg()) Loading @@ -262,7 +272,7 @@ constructor( } else { HAS_SCREEN_WAKELOCKS } return copy(screenWakelockStatus = screenWakelockStatus) return copy(screenWakelockStatus = screenWakelockStatus, fromState = getFromState()) } /** Loading Loading @@ -310,6 +320,7 @@ constructor( companion object { private const val VALUE_UNKNOWN = -1 private const val LATENCY_UNDEFINED = -1 private const val TAG = "DisplaySwitchLatency" private val DEBUG = Compile.IS_DEBUG && Log.isLoggable(TAG, Log.VERBOSE) Loading
packages/SystemUI/src/com/android/systemui/unfold/domain/interactor/FoldableDisplaySwitchTrackingInteractor.kt +10 −6 Original line number Diff line number Diff line Loading @@ -72,20 +72,24 @@ sealed interface DisplaySwitchState { /** * Displays are in a stable state aka not in the process of switching. If we couldn't track * display switch properly because end event never arrived within [SCREEN_EVENT_TIMEOUT], * [timedOut] is set to true. * display switch properly because end event never arrived within * [FoldableDisplaySwitchTrackingInteractor.SCREEN_EVENT_TIMEOUT], [timedOut] is set to true. */ data class Idle(override val newDeviceState: DeviceState, val timedOut: Boolean = false) : DisplaySwitchState /** Displays are currently switching. This state can only come directly after [Idle] state. */ /** * Displays are currently switching. This state can only come directly after [Idle] state. * Switching might not be visible to the user, that is, folding device with screen off still * emits Switching event as we're swapping default displays. */ data class Switching(override val newDeviceState: DeviceState) : DisplaySwitchState /** * Switching displays happened multiple times before [Idle] state could settle. This state will * hold until no new display switch related events are sent within [COOL_DOWN_DURATION] window. * This event can only happen directly after [Switching] state and is always directly followed * by [Idle] state. * hold until no new display switch related events are sent within * [FoldableDisplaySwitchTrackingInteractor.COOL_DOWN_DURATION] window. This event can only * happen directly after [Switching] state and is always directly followed by [Idle] state. */ data class Corrupted(override val newDeviceState: DeviceState) : DisplaySwitchState Loading