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

Commit c3ce5d86 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "[Flexiglass] Add support for the Side FPS indicator in Flexiglass." into main

parents 8964d5f1 006d4c34
Loading
Loading
Loading
Loading
+30 −10
Original line number Diff line number Diff line
@@ -26,6 +26,9 @@ import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.keyguard.data.repository.BiometricType
import com.android.systemui.keyguard.data.repository.DeviceEntryFingerprintAuthRepository
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.model.Scenes
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
@@ -33,6 +36,7 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.launch
@@ -48,6 +52,8 @@ constructor(
    @Application private val applicationScope: CoroutineScope,
    @Application private val context: Context,
    deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
    private val sceneContainerFlags: SceneContainerFlags,
    private val sceneInteractor: SceneInteractor,
    private val primaryBouncerInteractor: PrimaryBouncerInteractor,
    alternateBouncerInteractor: AlternateBouncerInteractor,
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
@@ -65,16 +71,35 @@ constructor(
        }
    }

    private val isSideFpsIndicatorOnPrimaryBouncerEnabled: Boolean
        get() = context.resources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)

    private val isBouncerSceneActive: Flow<Boolean> =
        if (sceneContainerFlags.isEnabled()) {
            sceneInteractor.currentScene.map { it == Scenes.Bouncer }.distinctUntilChanged()
        } else {
            flowOf(false)
        }

    private val showIndicatorForPrimaryBouncer: Flow<Boolean> =
        merge(
                // Legacy bouncer visibility changes.
                primaryBouncerInteractor.isShowing,
                primaryBouncerInteractor.startingToHide,
                primaryBouncerInteractor.startingDisappearAnimation.filterNotNull(),
                // Bouncer scene visibility changes.
                isBouncerSceneActive,
                deviceEntryFingerprintAuthRepository.shouldUpdateIndicatorVisibility.filter { it }
            )
            .map { shouldShowIndicatorForPrimaryBouncer() }
            .map {
                isBouncerActive() &&
                    isSideFpsIndicatorOnPrimaryBouncerEnabled &&
                    keyguardUpdateMonitor.isFingerprintDetectionRunning &&
                    keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed
            }

    private val showIndicatorForAlternateBouncer: Flow<Boolean> =
        // Note: this interactor internally verifies that SideFPS is enabled and running.
        alternateBouncerInteractor.isVisible

    /**
@@ -89,16 +114,11 @@ constructor(
            }
            .distinctUntilChanged()

    private fun shouldShowIndicatorForPrimaryBouncer(): Boolean {
        val sfpsEnabled: Boolean =
            context.resources.getBoolean(R.bool.config_show_sidefps_hint_on_bouncer)
        val sfpsDetectionRunning = keyguardUpdateMonitor.isFingerprintDetectionRunning
        val isUnlockingWithFpAllowed = keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed

    private fun isBouncerActive(): Boolean {
        if (sceneContainerFlags.isEnabled()) {
            return sceneInteractor.currentScene.value == Scenes.Bouncer
        }
        return primaryBouncerInteractor.isBouncerShowing() &&
            sfpsEnabled &&
            sfpsDetectionRunning &&
            isUnlockingWithFpAllowed &&
            !primaryBouncerInteractor.isAnimatingAway()
    }

+4 −1
Original line number Diff line number Diff line
@@ -77,6 +77,8 @@ import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
import com.android.systemui.statusbar.phone.dozeServiceHost
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -85,7 +87,6 @@ import com.android.systemui.unfold.compat.ScreenSizeFoldProvider
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.concurrency.FakeExecutor
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import java.util.Optional
@@ -238,6 +239,8 @@ class SideFpsOverlayViewBinderTest : SysuiTestCase() {
                testScope.backgroundScope,
                mContext,
                deviceEntryFingerprintAuthRepository,
                kosmos.fakeSceneContainerFlags,
                kosmos.sceneInteractor,
                primaryBouncerInteractor,
                alternateBouncerInteractor,
                keyguardUpdateMonitor
+4 −0
Original line number Diff line number Diff line
@@ -75,6 +75,8 @@ import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
import com.android.systemui.statusbar.phone.dozeServiceHost
import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -233,6 +235,8 @@ class SideFpsOverlayViewModelTest : SysuiTestCase() {
                testScope.backgroundScope,
                mContext,
                deviceEntryFingerprintAuthRepository,
                kosmos.fakeSceneContainerFlags,
                kosmos.sceneInteractor,
                primaryBouncerInteractor,
                alternateBouncerInteractor,
                keyguardUpdateMonitor
+129 −10
Original line number Diff line number Diff line
@@ -36,16 +36,20 @@ import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.flag.fakeSceneContainerFlags
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.testKosmos
import com.android.systemui.user.domain.interactor.SelectedUserInteractor
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -69,6 +73,8 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {
    @Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
    @Mock private lateinit var mSelectedUserInteractor: SelectedUserInteractor

    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val bouncerRepository = FakeKeyguardBouncerRepository()
    private val biometricSettingsRepository = FakeBiometricSettingsRepository()
    private val deviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
@@ -78,11 +84,11 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {

    private lateinit var underTest: DeviceEntrySideFpsOverlayInteractor

    private val testScope = TestScope(StandardTestDispatcher())

    @Before
    fun setup() {
        mSetFlagsRule.enableFlags(FLAG_SIDEFPS_CONTROLLER_REFACTOR)
        kosmos.fakeSceneContainerFlags.enabled = false

        primaryBouncerInteractor =
            PrimaryBouncerInteractor(
                bouncerRepository,
@@ -100,6 +106,7 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {
                mSelectedUserInteractor,
                faceAuthInteractor
            )

        alternateBouncerInteractor =
            AlternateBouncerInteractor(
                mock(StatusBarStateController::class.java),
@@ -114,11 +121,14 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {
                { mock(KeyguardTransitionInteractor::class.java) },
                testScope.backgroundScope,
            )

        underTest =
            DeviceEntrySideFpsOverlayInteractor(
                testScope.backgroundScope,
                mContext,
                deviceEntryFingerprintAuthRepository,
                kosmos.fakeSceneContainerFlags,
                kosmos.sceneInteractor,
                primaryBouncerInteractor,
                alternateBouncerInteractor,
                keyguardUpdateMonitor
@@ -138,7 +148,7 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {
                fpsDetectionRunning = true,
                isUnlockingWithFpAllowed = true
            )
            assertThat(showIndicatorForDeviceEntry).isEqualTo(true)
            assertThat(showIndicatorForDeviceEntry).isTrue()
        }

    @Test
@@ -154,7 +164,63 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {
                fpsDetectionRunning = true,
                isUnlockingWithFpAllowed = true
            )
            assertThat(showIndicatorForDeviceEntry).isEqualTo(false)
            assertThat(showIndicatorForDeviceEntry).isFalse()
        }

    @Test
    fun updatesShowIndicatorForDeviceEntry_onBouncerSceneActive() =
        testScope.runTest {
            kosmos.fakeSceneContainerFlags.enabled = true
            underTest =
                DeviceEntrySideFpsOverlayInteractor(
                    testScope.backgroundScope,
                    mContext,
                    deviceEntryFingerprintAuthRepository,
                    kosmos.fakeSceneContainerFlags,
                    kosmos.sceneInteractor,
                    primaryBouncerInteractor,
                    alternateBouncerInteractor,
                    keyguardUpdateMonitor
                )

            val showIndicatorForDeviceEntry by
                collectLastValue(underTest.showIndicatorForDeviceEntry)
            runCurrent()

            updateBouncerScene(
                isActive = true,
                fpsDetectionRunning = true,
                isUnlockingWithFpAllowed = true
            )
            assertThat(showIndicatorForDeviceEntry).isTrue()
        }

    @Test
    fun updatesShowIndicatorForDeviceEntry_onBouncerSceneInactive() =
        testScope.runTest {
            kosmos.fakeSceneContainerFlags.enabled = true
            underTest =
                DeviceEntrySideFpsOverlayInteractor(
                    testScope.backgroundScope,
                    mContext,
                    deviceEntryFingerprintAuthRepository,
                    kosmos.fakeSceneContainerFlags,
                    kosmos.sceneInteractor,
                    primaryBouncerInteractor,
                    alternateBouncerInteractor,
                    keyguardUpdateMonitor
                )

            val showIndicatorForDeviceEntry by
                collectLastValue(underTest.showIndicatorForDeviceEntry)
            runCurrent()

            updateBouncerScene(
                isActive = false,
                fpsDetectionRunning = true,
                isUnlockingWithFpAllowed = true
            )
            assertThat(showIndicatorForDeviceEntry).isFalse()
        }

    @Test
@@ -170,7 +236,7 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {
                fpsDetectionRunning = false,
                isUnlockingWithFpAllowed = true
            )
            assertThat(showIndicatorForDeviceEntry).isEqualTo(false)
            assertThat(showIndicatorForDeviceEntry).isFalse()
        }
    }

@@ -187,7 +253,39 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {
                fpsDetectionRunning = true,
                isUnlockingWithFpAllowed = false
            )
            assertThat(showIndicatorForDeviceEntry).isEqualTo(false)
            assertThat(showIndicatorForDeviceEntry).isFalse()
        }
    }

    @Test
    fun updatesShowIndicatorForDeviceEntry_fromBouncerScene_whenFpsDetectionNotRunning() {
        testScope.runTest {
            val showIndicatorForDeviceEntry by
                collectLastValue(underTest.showIndicatorForDeviceEntry)
            runCurrent()

            updateBouncerScene(
                isActive = true,
                fpsDetectionRunning = false,
                isUnlockingWithFpAllowed = true
            )
            assertThat(showIndicatorForDeviceEntry).isFalse()
        }
    }

    @Test
    fun updatesShowIndicatorForDeviceEntry_fromBouncerScene_onUnlockingWithFpDisallowed() {
        testScope.runTest {
            val showIndicatorForDeviceEntry by
                collectLastValue(underTest.showIndicatorForDeviceEntry)
            runCurrent()

            updateBouncerScene(
                isActive = true,
                fpsDetectionRunning = true,
                isUnlockingWithFpAllowed = false
            )
            assertThat(showIndicatorForDeviceEntry).isFalse()
        }
    }

@@ -204,7 +302,7 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {
                fpsDetectionRunning = true,
                isUnlockingWithFpAllowed = true
            )
            assertThat(showIndicatorForDeviceEntry).isEqualTo(false)
            assertThat(showIndicatorForDeviceEntry).isFalse()
        }
    }

@@ -216,10 +314,10 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {
            runCurrent()

            bouncerRepository.setAlternateVisible(true)
            assertThat(showIndicatorForDeviceEntry).isEqualTo(true)
            assertThat(showIndicatorForDeviceEntry).isTrue()

            bouncerRepository.setAlternateVisible(false)
            assertThat(showIndicatorForDeviceEntry).isEqualTo(false)
            assertThat(showIndicatorForDeviceEntry).isFalse()
        }

    @Test
@@ -266,4 +364,25 @@ class DeviceEntrySideFpsOverlayInteractorTest : SysuiTestCase() {
            true
        )
    }

    private fun TestScope.updateBouncerScene(
        isActive: Boolean,
        fpsDetectionRunning: Boolean,
        isUnlockingWithFpAllowed: Boolean,
    ) {
        kosmos.sceneInteractor.changeScene(
            if (isActive) Scenes.Bouncer else Scenes.Lockscreen,
            "reason"
        )

        whenever(keyguardUpdateMonitor.isFingerprintDetectionRunning)
            .thenReturn(fpsDetectionRunning)
        whenever(keyguardUpdateMonitor.isUnlockingWithFingerprintAllowed)
            .thenReturn(isUnlockingWithFpAllowed)
        mContext.orCreateTestableResources.addOverride(
            R.bool.config_show_sidefps_hint_on_bouncer,
            true
        )
        runCurrent()
    }
}