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

Commit a115fde3 authored by Helen Cheuk's avatar Helen Cheuk Committed by Android (Google) Code Review
Browse files

Merge "[Action Corner] Not subscribe to cursor position when no action is...

Merge "[Action Corner] Not subscribe to cursor position when no action is configured for corners" into main
parents 191d5d3b 3430be78
Loading
Loading
Loading
Loading
+130 −125
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
package com.android.systemui.actioncorner.data.repository

import android.graphics.Rect
import android.provider.Settings.Secure.ACTION_CORNER_ACTION_HOME
import android.provider.Settings.Secure.ACTION_CORNER_TOP_LEFT_ACTION
import android.view.Display.DEFAULT_DISPLAY
import android.view.WindowInsets
import android.view.WindowManager
@@ -41,8 +43,11 @@ import com.android.systemui.kosmos.backgroundScope
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.collectValues
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.useUnconfinedTestDispatcher
import com.android.systemui.testKosmos
import com.android.systemui.util.settings.data.repository.userAwareSecureSettingsRepository
import com.google.common.truth.Truth.assertThat
import kotlin.test.Test
import kotlin.time.Duration.Companion.milliseconds
@@ -63,11 +68,18 @@ class ActionCornerRepositoryTest : SysuiTestCase() {
    @get:Rule val mockitoRule: MockitoRule = MockitoJUnit.rule()
    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
    private val Kosmos.fakePointerRepository by Fixture { FakePointerDeviceRepository() }
    private val settingsRepository = kosmos.userAwareSecureSettingsRepository

    private val Kosmos.underTest by Fixture {
        ActionCornerRepositoryImpl(
            cursorPositionRepository,
            kosmos.fakeDisplayWindowPropertiesRepository,
            kosmos.fakePointerRepository,
            ActionCornerSettingRepository(
                settingsRepository,
                testScope.backgroundScope,
                testDispatcher,
            ),
            kosmos.backgroundScope,
        )
    }
@@ -84,22 +96,17 @@ class ActionCornerRepositoryTest : SysuiTestCase() {
    }

    @Test
    fun topLeftCursor_topLeftActionCornerEmitted() =
        kosmos.runTest {
    fun topLeftCursor_topLeftActionCornerEmitted() = setUpAndRunTest {
        val model by collectLastValue(underTest.actionCornerState)
        addCursorPosition(display.topLeftCursorPos)
        assertThat(model)
            .isEqualTo(
                    ActiveActionCorner(
                        ActionCornerRegion.TOP_LEFT,
                        display.topLeftCursorPos.displayId,
                    )
                ActiveActionCorner(ActionCornerRegion.TOP_LEFT, display.topLeftCursorPos.displayId)
            )
    }

    @Test
    fun outOfBoundTopLeftCursor_noActionCornerEmitted() =
        kosmos.runTest {
    fun outOfBoundTopLeftCursor_noActionCornerEmitted() = setUpAndRunTest {
        val model by collectLastValue(underTest.actionCornerState)
        val actionCornerPos = display.topLeftCursorPos
        // Update x and y to make it just out of bound of action corner
@@ -114,20 +121,16 @@ class ActionCornerRepositoryTest : SysuiTestCase() {
    }

    @Test
    fun topRightCursor_topRightActionCornerEmitted() =
        kosmos.runTest {
    fun topRightCursor_topRightActionCornerEmitted() = setUpAndRunTest {
        val model by collectLastValue(underTest.actionCornerState)
        val actionCornerPos = display.topRightCursorPos
        addCursorPosition(actionCornerPos)
        assertThat(model)
                .isEqualTo(
                    ActiveActionCorner(ActionCornerRegion.TOP_RIGHT, actionCornerPos.displayId)
                )
            .isEqualTo(ActiveActionCorner(ActionCornerRegion.TOP_RIGHT, actionCornerPos.displayId))
    }

    @Test
    fun outOfBoundTopRightCursor_noActionCornerEmitted() =
        kosmos.runTest {
    fun outOfBoundTopRightCursor_noActionCornerEmitted() = setUpAndRunTest {
        val model by collectLastValue(underTest.actionCornerState)
        val actionCornerPos = display.topRightCursorPos
        addCursorPosition(
@@ -141,8 +144,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() {
    }

    @Test
    fun bottomLeftCursor_bottomLeftActionCornerEmitted() =
        kosmos.runTest {
    fun bottomLeftCursor_bottomLeftActionCornerEmitted() = setUpAndRunTest {
        val model by collectLastValue(underTest.actionCornerState)
        val actionCornerPos = display.bottomLeftCursorPos
        addCursorPosition(actionCornerPos)
@@ -153,8 +155,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() {
    }

    @Test
    fun outOfBoundBottomLeftCursor_noActionCornerEmitted() =
        kosmos.runTest {
    fun outOfBoundBottomLeftCursor_noActionCornerEmitted() = setUpAndRunTest {
        val model by collectLastValue(underTest.actionCornerState)
        val actionCornerPos = display.bottomLeftCursorPos
        addCursorPosition(
@@ -168,8 +169,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() {
    }

    @Test
    fun bottomRightCursor_bottomRightActionCornerEmitted() =
        kosmos.runTest {
    fun bottomRightCursor_bottomRightActionCornerEmitted() = setUpAndRunTest {
        val model by collectLastValue(underTest.actionCornerState)
        val actionCornerPos = display.bottomRightCursorPos
        addCursorPosition(actionCornerPos)
@@ -180,8 +180,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() {
    }

    @Test
    fun outOfBoundBottomRightCursor_noActionCornerEmitted() =
        kosmos.runTest {
    fun outOfBoundBottomRightCursor_noActionCornerEmitted() = setUpAndRunTest {
        val model by collectLastValue(underTest.actionCornerState)
        val actionCornerPos = display.bottomRightCursorPos
        addCursorPosition(
@@ -196,12 +195,10 @@ class ActionCornerRepositoryTest : SysuiTestCase() {

    @Test
    fun actionCornerCursor_moveOutOfBound_reEnterActionCorner_secondActiveActionCornerEmitted() =
        kosmos.runTest {
        setUpAndRunTest {
            // Filter out InactiveActionCorner for test readability
            val models by
                kosmos.collectValues(
                    underTest.actionCornerState.filter { it != InactiveActionCorner }
                )
                collectValues(underTest.actionCornerState.filter { it != InactiveActionCorner })
            val actionCornerPos = display.bottomRightCursorPos
            addCursorPosition(actionCornerPos)
            addCursorPosition(CursorPosition(x = 1000f, y = 1000f, actionCornerPos.displayId))
@@ -213,33 +210,23 @@ class ActionCornerRepositoryTest : SysuiTestCase() {
        }

    @Test
    fun actionCornerCursor_moveInsideSameCorner_OneActionCornerEmitted() =
        kosmos.runTest {
            val models by kosmos.collectValues(underTest.actionCornerState.drop(1))
    fun actionCornerCursor_moveInsideSameCorner_OneActionCornerEmitted() = setUpAndRunTest {
        val models by collectValues(underTest.actionCornerState.drop(1))
        val actionCornerPos = display.bottomRightCursorPos
        addCursorPosition(actionCornerPos)
        // Move within the same corner
        addCursorPosition(
                CursorPosition(
                    actionCornerPos.x + 1,
                    actionCornerPos.y + 1,
                    actionCornerPos.displayId,
                )
            CursorPosition(actionCornerPos.x + 1, actionCornerPos.y + 1, actionCornerPos.displayId)
        )
        addCursorPosition(
                CursorPosition(
                    actionCornerPos.x + 2,
                    actionCornerPos.y + 2,
                    actionCornerPos.displayId,
                )
            CursorPosition(actionCornerPos.x + 2, actionCornerPos.y + 2, actionCornerPos.displayId)
        )

        assertThat(models.size).isEqualTo(1)
    }

    @Test
    fun activeActionCorner_pointerDeviceDisconnected_inactiveActionCorner() =
        kosmos.runTest {
    fun activeActionCorner_pointerDeviceDisconnected_inactiveActionCorner() = setUpAndRunTest {
        val model by collectLastValue(underTest.actionCornerState)

        val actionCornerPos = display.bottomRightCursorPos
@@ -252,7 +239,7 @@ class ActionCornerRepositoryTest : SysuiTestCase() {

    @Test
    fun actionCornerState_remainsInactive_whenCursorMovesIntoActiveArea_butDebounceNotMet() =
        kosmos.runTest {
        setUpAndRunTest {
            val model by collectLastValue(underTest.actionCornerState)

            val actionCornerPos = display.bottomRightCursorPos
@@ -262,11 +249,29 @@ class ActionCornerRepositoryTest : SysuiTestCase() {
            assertThat(model).isEqualTo(InactiveActionCorner)
        }

    @Test
    fun noActionConfigured_cursorMovesIntoActiveArea_remainInactiveActionCorner() =
        kosmos.runTest {
            // No action configured to corners by default
            val model by collectLastValue(underTest.actionCornerState)

            val actionCornerPos = display.bottomRightCursorPos
            addCursorPosition(actionCornerPos)

            assertThat(model).isEqualTo(InactiveActionCorner)
        }

    private fun Kosmos.addCursorPosition(cursorPosition: CursorPosition) {
        cursorPositionRepository.addCursorPosition(cursorPosition)
        advanceTimeBy(DEBOUNCE_DELAY + 1.milliseconds)
    }

    private fun setUpAndRunTest(testBody: suspend Kosmos.() -> Unit) =
        kosmos.runTest {
            settingsRepository.setInt(ACTION_CORNER_TOP_LEFT_ACTION, ACTION_CORNER_ACTION_HOME)
            testBody()
        }

    private fun createDisplayWindowProperties() =
        DisplayWindowProperties(
            DEFAULT_DISPLAY,
+10 −5
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import kotlin.time.Duration.Companion.milliseconds
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
@@ -60,17 +61,21 @@ constructor(
    cursorRepository: MultiDisplayCursorPositionRepository,
    private val displayWindowPropertiesRepository: DisplayWindowPropertiesRepository,
    pointerDeviceRepository: PointerDeviceRepository,
    actionCornerSettingRepository: ActionCornerSettingRepository,
    @Background private val backgroundScope: CoroutineScope,
) : ActionCornerRepository {

    override val actionCornerState: StateFlow<ActionCornerState> =
        pointerDeviceRepository.isAnyPointerDeviceConnected
            .flatMapLatest { isConnected ->
                if (isConnected) {
        combine(
                pointerDeviceRepository.isAnyPointerDeviceConnected,
                actionCornerSettingRepository.isAnyActionConfigured,
            ) { isConnected, isAnyActionConfigured ->
                isConnected && isAnyActionConfigured
            }
            .flatMapLatest { shouldMonitorCursorPosition ->
                if (shouldMonitorCursorPosition) {
                    cursorRepository.cursorPositions.map(::mapToActionCornerState)
                } else {
                    // When not connected, emit an InactiveActionCorner state and then complete this
                    // inner flow.
                    flowOf(InactiveActionCorner)
                }
            }
+14 −0
Original line number Diff line number Diff line
@@ -36,8 +36,11 @@ import com.android.systemui.util.settings.repository.UserAwareSecureSettingsRepo
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
@@ -65,6 +68,17 @@ constructor(
    val bottomRightCornerAction: StateFlow<ActionType> =
        getCornerActionFlow(ACTION_CORNER_BOTTOM_RIGHT_ACTION)

    val isAnyActionConfigured: Flow<Boolean> =
        combine(
                topLeftCornerAction,
                topRightCornerAction,
                bottomLeftCornerAction,
                bottomRightCornerAction,
            ) { topLeft, topRight, bottomLeft, bottomRight ->
                listOf(topLeft, topRight, bottomLeft, bottomRight).any { action -> action != NONE }
            }
            .distinctUntilChanged()

    private fun getCornerActionFlow(settingName: String): StateFlow<ActionType> {
        return settingsRepository
            .intSetting(name = settingName)