Loading packages/SystemUI/multivalentTests/src/com/android/systemui/actioncorner/data/repository/ActionCornerRepositoryTest.kt +36 −17 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import com.android.systemui.display.shared.model.DisplayWindowProperties import com.android.systemui.inputdevice.data.repository.FakePointerDeviceRepository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.advanceTimeBy import com.android.systemui.kosmos.backgroundScope import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.collectValues Loading @@ -44,6 +45,7 @@ import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlin.test.Test import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.filter import org.junit.Before Loading Loading @@ -85,7 +87,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { fun topLeftCursor_topLeftActionCornerEmitted() = kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) cursorPositionRepository.addCursorPosition(display.topLeftCursorPos) addCursorPosition(display.topLeftCursorPos) assertThat(model) .isEqualTo( ActiveActionCorner( Loading @@ -101,7 +103,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.topLeftCursorPos // Update x and y to make it just out of bound of action corner cursorPositionRepository.addCursorPosition( addCursorPosition( CursorPosition( x = actionCornerPos.x + 1, y = actionCornerPos.y + 1, Loading @@ -116,7 +118,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.topRightCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) addCursorPosition(actionCornerPos) assertThat(model) .isEqualTo( ActiveActionCorner(ActionCornerRegion.TOP_RIGHT, actionCornerPos.displayId) Loading @@ -128,7 +130,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.topRightCursorPos cursorPositionRepository.addCursorPosition( addCursorPosition( CursorPosition( x = actionCornerPos.x - 1, y = actionCornerPos.y + 1, Loading @@ -143,7 +145,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.bottomLeftCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) addCursorPosition(actionCornerPos) assertThat(model) .isEqualTo( ActiveActionCorner(ActionCornerRegion.BOTTOM_LEFT, actionCornerPos.displayId) Loading @@ -155,7 +157,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.bottomLeftCursorPos cursorPositionRepository.addCursorPosition( addCursorPosition( CursorPosition( x = actionCornerPos.x + 1, y = actionCornerPos.y - 1, Loading @@ -170,7 +172,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.bottomRightCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) addCursorPosition(actionCornerPos) assertThat(model) .isEqualTo( ActiveActionCorner(ActionCornerRegion.BOTTOM_RIGHT, actionCornerPos.displayId) Loading @@ -182,7 +184,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.bottomRightCursorPos cursorPositionRepository.addCursorPosition( addCursorPosition( CursorPosition( x = actionCornerPos.x - 1, y = actionCornerPos.y - 1, Loading @@ -201,11 +203,9 @@ class ActionCornerRepositoryTest : SysuiTestCase() { underTest.actionCornerState.filter { it != InactiveActionCorner } ) val actionCornerPos = display.bottomRightCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) cursorPositionRepository.addCursorPosition( CursorPosition(x = 1000f, y = 1000f, actionCornerPos.displayId) ) cursorPositionRepository.addCursorPosition(actionCornerPos) addCursorPosition(actionCornerPos) addCursorPosition(CursorPosition(x = 1000f, y = 1000f, actionCornerPos.displayId)) addCursorPosition(actionCornerPos) val bottomRightModel = ActiveActionCorner(ActionCornerRegion.BOTTOM_RIGHT, actionCornerPos.displayId) Loading @@ -217,16 +217,16 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val models by kosmos.collectValues(underTest.actionCornerState.drop(1)) val actionCornerPos = display.bottomRightCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) addCursorPosition(actionCornerPos) // Move within the same corner cursorPositionRepository.addCursorPosition( addCursorPosition( CursorPosition( actionCornerPos.x + 1, actionCornerPos.y + 1, actionCornerPos.displayId, ) ) cursorPositionRepository.addCursorPosition( addCursorPosition( CursorPosition( actionCornerPos.x + 2, actionCornerPos.y + 2, Loading @@ -240,15 +240,33 @@ class ActionCornerRepositoryTest : SysuiTestCase() { @Test fun activeActionCorner_pointerDeviceDisconnected_inactiveActionCorner() = kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.bottomRightCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) addCursorPosition(actionCornerPos) fakePointerRepository.setIsAnyPointerConnected(false) assertThat(model).isEqualTo(InactiveActionCorner) } @Test fun actionCornerState_remainsInactive_whenCursorMovesIntoActiveArea_butDebounceNotMet() = kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.bottomRightCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) // Debounce duration has not elapsed yet assertThat(model).isEqualTo(InactiveActionCorner) } private fun Kosmos.addCursorPosition(cursorPosition: CursorPosition) { cursorPositionRepository.addCursorPosition(cursorPosition) advanceTimeBy(DEBOUNCE_DELAY + 1.milliseconds) } private fun createDisplayWindowProperties() = DisplayWindowProperties( DEFAULT_DISPLAY, Loading @@ -261,6 +279,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { companion object { private val metrics = WindowMetrics(Rect(0, 0, 2560, 1600), mock<WindowInsets>(), 2f) private const val ACTION_CORNER_DP = 8f private val DEBOUNCE_DELAY = 200.milliseconds private val cornerSize = ACTION_CORNER_DP * metrics.density private val display = Loading packages/SystemUI/src/com/android/systemui/actioncorner/data/repository/ActionCornerRepository.kt +13 −0 Original line number Diff line number Diff line Loading @@ -31,9 +31,12 @@ import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.display.data.repository.DisplayWindowPropertiesRepository import com.android.systemui.inputdevice.data.repository.PointerDeviceRepository import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map Loading @@ -50,6 +53,7 @@ interface ActionCornerRepository { * and uses the window metrics from [DisplayWindowPropertiesRepository] to determine if the cursor * is in any action corner. */ @OptIn(kotlinx.coroutines.FlowPreview::class) class ActionCornerRepositoryImpl @Inject constructor( Loading @@ -70,6 +74,14 @@ constructor( flowOf(InactiveActionCorner) } } .distinctUntilChanged() .debounce { state -> if (state is ActiveActionCorner) { DEBOUNCE_DELAY } else { 0.milliseconds } } .stateIn(backgroundScope, SharingStarted.WhileSubscribed(), InactiveActionCorner) private fun mapToActionCornerState(cursorPos: CursorPosition?): ActionCornerState { Loading Loading @@ -130,5 +142,6 @@ constructor( companion object { private const val ACTION_CORNER_DP = 8f private val DEBOUNCE_DELAY = 200.milliseconds } } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/actioncorner/data/repository/ActionCornerRepositoryTest.kt +36 −17 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ import com.android.systemui.display.shared.model.DisplayWindowProperties import com.android.systemui.inputdevice.data.repository.FakePointerDeviceRepository import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.advanceTimeBy import com.android.systemui.kosmos.backgroundScope import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.collectValues Loading @@ -44,6 +45,7 @@ import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlin.test.Test import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.filter import org.junit.Before Loading Loading @@ -85,7 +87,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { fun topLeftCursor_topLeftActionCornerEmitted() = kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) cursorPositionRepository.addCursorPosition(display.topLeftCursorPos) addCursorPosition(display.topLeftCursorPos) assertThat(model) .isEqualTo( ActiveActionCorner( Loading @@ -101,7 +103,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.topLeftCursorPos // Update x and y to make it just out of bound of action corner cursorPositionRepository.addCursorPosition( addCursorPosition( CursorPosition( x = actionCornerPos.x + 1, y = actionCornerPos.y + 1, Loading @@ -116,7 +118,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.topRightCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) addCursorPosition(actionCornerPos) assertThat(model) .isEqualTo( ActiveActionCorner(ActionCornerRegion.TOP_RIGHT, actionCornerPos.displayId) Loading @@ -128,7 +130,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.topRightCursorPos cursorPositionRepository.addCursorPosition( addCursorPosition( CursorPosition( x = actionCornerPos.x - 1, y = actionCornerPos.y + 1, Loading @@ -143,7 +145,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.bottomLeftCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) addCursorPosition(actionCornerPos) assertThat(model) .isEqualTo( ActiveActionCorner(ActionCornerRegion.BOTTOM_LEFT, actionCornerPos.displayId) Loading @@ -155,7 +157,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.bottomLeftCursorPos cursorPositionRepository.addCursorPosition( addCursorPosition( CursorPosition( x = actionCornerPos.x + 1, y = actionCornerPos.y - 1, Loading @@ -170,7 +172,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.bottomRightCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) addCursorPosition(actionCornerPos) assertThat(model) .isEqualTo( ActiveActionCorner(ActionCornerRegion.BOTTOM_RIGHT, actionCornerPos.displayId) Loading @@ -182,7 +184,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.bottomRightCursorPos cursorPositionRepository.addCursorPosition( addCursorPosition( CursorPosition( x = actionCornerPos.x - 1, y = actionCornerPos.y - 1, Loading @@ -201,11 +203,9 @@ class ActionCornerRepositoryTest : SysuiTestCase() { underTest.actionCornerState.filter { it != InactiveActionCorner } ) val actionCornerPos = display.bottomRightCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) cursorPositionRepository.addCursorPosition( CursorPosition(x = 1000f, y = 1000f, actionCornerPos.displayId) ) cursorPositionRepository.addCursorPosition(actionCornerPos) addCursorPosition(actionCornerPos) addCursorPosition(CursorPosition(x = 1000f, y = 1000f, actionCornerPos.displayId)) addCursorPosition(actionCornerPos) val bottomRightModel = ActiveActionCorner(ActionCornerRegion.BOTTOM_RIGHT, actionCornerPos.displayId) Loading @@ -217,16 +217,16 @@ class ActionCornerRepositoryTest : SysuiTestCase() { kosmos.runTest { val models by kosmos.collectValues(underTest.actionCornerState.drop(1)) val actionCornerPos = display.bottomRightCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) addCursorPosition(actionCornerPos) // Move within the same corner cursorPositionRepository.addCursorPosition( addCursorPosition( CursorPosition( actionCornerPos.x + 1, actionCornerPos.y + 1, actionCornerPos.displayId, ) ) cursorPositionRepository.addCursorPosition( addCursorPosition( CursorPosition( actionCornerPos.x + 2, actionCornerPos.y + 2, Loading @@ -240,15 +240,33 @@ class ActionCornerRepositoryTest : SysuiTestCase() { @Test fun activeActionCorner_pointerDeviceDisconnected_inactiveActionCorner() = kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.bottomRightCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) addCursorPosition(actionCornerPos) fakePointerRepository.setIsAnyPointerConnected(false) assertThat(model).isEqualTo(InactiveActionCorner) } @Test fun actionCornerState_remainsInactive_whenCursorMovesIntoActiveArea_butDebounceNotMet() = kosmos.runTest { val model by collectLastValue(underTest.actionCornerState) val actionCornerPos = display.bottomRightCursorPos cursorPositionRepository.addCursorPosition(actionCornerPos) // Debounce duration has not elapsed yet assertThat(model).isEqualTo(InactiveActionCorner) } private fun Kosmos.addCursorPosition(cursorPosition: CursorPosition) { cursorPositionRepository.addCursorPosition(cursorPosition) advanceTimeBy(DEBOUNCE_DELAY + 1.milliseconds) } private fun createDisplayWindowProperties() = DisplayWindowProperties( DEFAULT_DISPLAY, Loading @@ -261,6 +279,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() { companion object { private val metrics = WindowMetrics(Rect(0, 0, 2560, 1600), mock<WindowInsets>(), 2f) private const val ACTION_CORNER_DP = 8f private val DEBOUNCE_DELAY = 200.milliseconds private val cornerSize = ACTION_CORNER_DP * metrics.density private val display = Loading
packages/SystemUI/src/com/android/systemui/actioncorner/data/repository/ActionCornerRepository.kt +13 −0 Original line number Diff line number Diff line Loading @@ -31,9 +31,12 @@ import com.android.systemui.dagger.qualifiers.Background import com.android.systemui.display.data.repository.DisplayWindowPropertiesRepository import com.android.systemui.inputdevice.data.repository.PointerDeviceRepository import javax.inject.Inject import kotlin.time.Duration.Companion.milliseconds import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map Loading @@ -50,6 +53,7 @@ interface ActionCornerRepository { * and uses the window metrics from [DisplayWindowPropertiesRepository] to determine if the cursor * is in any action corner. */ @OptIn(kotlinx.coroutines.FlowPreview::class) class ActionCornerRepositoryImpl @Inject constructor( Loading @@ -70,6 +74,14 @@ constructor( flowOf(InactiveActionCorner) } } .distinctUntilChanged() .debounce { state -> if (state is ActiveActionCorner) { DEBOUNCE_DELAY } else { 0.milliseconds } } .stateIn(backgroundScope, SharingStarted.WhileSubscribed(), InactiveActionCorner) private fun mapToActionCornerState(cursorPos: CursorPosition?): ActionCornerState { Loading Loading @@ -130,5 +142,6 @@ constructor( companion object { private const val ACTION_CORNER_DP = 8f private val DEBOUNCE_DELAY = 200.milliseconds } }