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

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

Merge "[Action Corner] Only check lockscreen visibility when device is connected" into main

parents c6266cf3 e9cbccec
Loading
Loading
Loading
Loading
+0 −35
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ import com.android.systemui.cursorposition.data.model.CursorPosition
import com.android.systemui.cursorposition.domain.data.repository.multiDisplayCursorPositionRepository
import com.android.systemui.display.data.repository.fakeDisplayWindowPropertiesRepository
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
@@ -43,8 +42,6 @@ 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
@@ -67,19 +64,12 @@ import org.mockito.kotlin.whenever
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,
        )
    }
@@ -92,7 +82,6 @@ class ActionCornerRepositoryTest : SysuiTestCase() {
    fun setup() {
        whenever(windowManager.currentWindowMetrics).thenReturn(metrics)
        displayRepository.insert(createDisplayWindowProperties())
        kosmos.fakePointerRepository.setIsAnyPointerConnected(true)
    }

    @Test
@@ -225,18 +214,6 @@ class ActionCornerRepositoryTest : SysuiTestCase() {
        assertThat(models.size).isEqualTo(1)
    }

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

        val actionCornerPos = display.bottomRightCursorPos
        addCursorPosition(actionCornerPos)

        fakePointerRepository.setIsAnyPointerConnected(false)

        assertThat(model).isEqualTo(InactiveActionCorner)
    }

    @Test
    fun actionCornerState_remainsInactive_whenCursorMovesIntoActiveArea_butDebounceNotMet() =
        setUpAndRunTest {
@@ -249,18 +226,6 @@ 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)
+21 −1
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.systemui.actioncorner.data.model.ActionCornerRegion.BOTTOM_RI
import com.android.systemui.actioncorner.data.model.ActionCornerState.ActiveActionCorner
import com.android.systemui.actioncorner.data.repository.ActionCornerSettingRepository
import com.android.systemui.actioncorner.data.repository.FakeActionCornerRepository
import com.android.systemui.inputdevice.data.repository.FakePointerDeviceRepository
import com.android.systemui.keyguard.domain.interactor.windowManagerLockscreenVisibilityInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -74,14 +75,16 @@ class ActionCornerInteractorTest : SysuiTestCase() {

    private val Kosmos.launcherProxyService by Fixture { mock<LauncherProxyService>() }
    private val Kosmos.commandQueue by Fixture { mock<CommandQueue>() }
    private val Kosmos.fakePointerRepository by Fixture { FakePointerDeviceRepository() }

    private val Kosmos.underTest by Fixture {
        ActionCornerInteractor(
            actionCornerRepository,
            launcherProxyService,
            actionCornerSettingRepository,
            fakeUserSetupRepository,
            fakePointerRepository,
            windowManagerLockscreenVisibilityInteractor,
            fakeUserSetupRepository,
            commandQueue,
        )
    }
@@ -89,6 +92,7 @@ class ActionCornerInteractorTest : SysuiTestCase() {
    @Before
    fun setUp() {
        kosmos.fakeUserSetupRepository.setUserSetUp(true)
        kosmos.fakePointerRepository.setIsAnyPointerConnected(true)
        kosmos.underTest.activateIn(kosmos.testScope)
    }

@@ -165,6 +169,22 @@ class ActionCornerInteractorTest : SysuiTestCase() {
            verify(launcherProxyService, never()).onActionCornerActivated(OVERVIEW, DEFAULT_DISPLAY)
        }

    @Test
    fun noActionConfigured_cursorMovesIntoActiveArea_actionNotTriggered() = unlockScreenAndRunTest {
        // No action configured to corners by default
        actionCornerRepository.addState(ActiveActionCorner(BOTTOM_LEFT, DEFAULT_DISPLAY))
        verify(launcherProxyService, never()).onActionCornerActivated(OVERVIEW, DEFAULT_DISPLAY)
    }

    @Test
    fun activeActionCorner_pointerDeviceDisconnected_actionNotTriggered() = unlockScreenAndRunTest {
        settingsRepository.setInt(ACTION_CORNER_BOTTOM_LEFT_ACTION, ACTION_CORNER_ACTION_OVERVIEW)
        fakePointerRepository.setIsAnyPointerConnected(false)

        actionCornerRepository.addState(ActiveActionCorner(BOTTOM_LEFT, DEFAULT_DISPLAY))
        verify(launcherProxyService, never()).onActionCornerActivated(OVERVIEW, DEFAULT_DISPLAY)
    }

    private fun unlockScreenAndRunTest(testBody: suspend Kosmos.() -> Unit) =
        kosmos.runTest {
            setTransition(
+2 −19
Original line number Diff line number Diff line
@@ -29,17 +29,13 @@ import com.android.systemui.cursorposition.data.model.CursorPosition
import com.android.systemui.cursorposition.data.repository.MultiDisplayCursorPositionRepository
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.combine
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
import kotlinx.coroutines.flow.stateIn

@@ -60,25 +56,12 @@ class ActionCornerRepositoryImpl
constructor(
    cursorRepository: MultiDisplayCursorPositionRepository,
    private val displayWindowPropertiesRepository: DisplayWindowPropertiesRepository,
    pointerDeviceRepository: PointerDeviceRepository,
    actionCornerSettingRepository: ActionCornerSettingRepository,
    @Background private val backgroundScope: CoroutineScope,
) : ActionCornerRepository {

    override val actionCornerState: StateFlow<ActionCornerState> =
        combine(
                pointerDeviceRepository.isAnyPointerDeviceConnected,
                actionCornerSettingRepository.isAnyActionConfigured,
            ) { isConnected, isAnyActionConfigured ->
                isConnected && isAnyActionConfigured
            }
            .flatMapLatest { shouldMonitorCursorPosition ->
                if (shouldMonitorCursorPosition) {
                    cursorRepository.cursorPositions.map(::mapToActionCornerState)
                } else {
                    flowOf(InactiveActionCorner)
                }
            }
        cursorRepository.cursorPositions
            .map(::mapToActionCornerState)
            .distinctUntilChanged()
            .debounce { state ->
                if (state is ActiveActionCorner) {
+18 −6
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import com.android.systemui.actioncorner.data.model.ActionType.QUICK_SETTINGS
import com.android.systemui.actioncorner.data.repository.ActionCornerRepository
import com.android.systemui.actioncorner.data.repository.ActionCornerSettingRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.inputdevice.data.repository.PointerDeviceRepository
import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.shared.system.actioncorner.ActionCornerConstants
@@ -44,6 +45,8 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filterIsInstance
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map

@SysUISingleton
class ActionCornerInteractor
@@ -52,19 +55,28 @@ constructor(
    private val repository: ActionCornerRepository,
    private val launcherProxyService: LauncherProxyService,
    private val actionCornerSettingRepository: ActionCornerSettingRepository,
    private val userSetupRepository: UserSetupRepository,
    private val pointerDeviceRepository: PointerDeviceRepository,
    private val lockscreenVisibilityInteractor: WindowManagerLockscreenVisibilityInteractor,
    private val userSetupRepository: UserSetupRepository,
    private val commandQueue: CommandQueue,
) : ExclusiveActivatable() {

    override suspend fun onActivated(): Nothing {
        userSetupRepository.isUserSetUp
            .combine(lockscreenVisibilityInteractor.lockscreenVisibility) {
                isUserSetUp,
                isLockscreenVisible ->
                isUserSetUp && !isLockscreenVisible
        combine(
                pointerDeviceRepository.isAnyPointerDeviceConnected,
                actionCornerSettingRepository.isAnyActionConfigured,
                userSetupRepository.isUserSetUp,
            ) { isConnected, isAnyActionConfigured, isUserSetUp ->
                isConnected && isAnyActionConfigured && isUserSetUp
            }
            .distinctUntilChanged()
            .flatMapLatest { shouldCheckLockscreenVisibility ->
                if (shouldCheckLockscreenVisibility) {
                    lockscreenVisibilityInteractor.lockscreenVisibility.map { !it }
                } else {
                    flowOf(false)
                }
            }
            .flatMapLatest { shouldMonitorActionCorner ->
                if (shouldMonitorActionCorner) {
                    repository.actionCornerState.filterIsInstance<ActiveActionCorner>()