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

Commit 67ceebc0 authored by Chandru S's avatar Chandru S
Browse files

Navigating to the compose bouncer should trigger face auth

Use sceneInteractor as the source of truth for bouncer visibility when flexiglass is enabled.

Fixes: 361672949
Fixes: 357649556
Test: atest DeviceEntryFaceAuthInteractorTest
Flag: com.android.systemui.scene_container
Test: manually,
  lock device
  go to bouncer
  face auth should run
Change-Id: I0c319c40323ee1e3b4c81e5534c7d83cb44e5aaa
parent 266fc60f
Loading
Loading
Loading
Loading
+28 −14
Original line number Diff line number Diff line
@@ -46,6 +46,9 @@ import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.log.FaceAuthenticationLogger
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.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.user.data.model.SelectionStatus
import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.util.kotlin.pairwise
@@ -90,6 +93,7 @@ constructor(
    private val powerInteractor: PowerInteractor,
    private val biometricSettingsRepository: BiometricSettingsRepository,
    private val trustManager: TrustManager,
    private val sceneInteractor: Lazy<SceneInteractor>,
    deviceEntryFaceAuthStatusInteractor: DeviceEntryFaceAuthStatusInteractor,
) : DeviceEntryFaceAuthInteractor {

@@ -103,9 +107,7 @@ constructor(
        keyguardUpdateMonitor.setFaceAuthInteractor(this)
        observeFaceAuthStateUpdates()
        faceAuthenticationLogger.interactorStarted()
        primaryBouncerInteractor
            .get()
            .isShowing
        isBouncerVisible
            .whenItFlipsToTrue()
            .onEach {
                faceAuthenticationLogger.bouncerVisibilityChanged()
@@ -181,20 +183,24 @@ constructor(
        // auth so that the switched user can unlock the device with face auth.
        userRepository.selectedUser
            .pairwise()
            .onEach { (previous, curr) ->
            .filter { (previous, curr) ->
                val wasSwitching = previous.selectionStatus == SelectionStatus.SELECTION_IN_PROGRESS
                val isSwitching = curr.selectionStatus == SelectionStatus.SELECTION_IN_PROGRESS
                if (wasSwitching && !isSwitching) {
                    resetLockedOutState(curr.userInfo.id)
                // User switching was in progress and is complete now.
                wasSwitching && !isSwitching
            }
            .map { (_, curr) -> curr.userInfo.id }
            .sample(isBouncerVisible, ::Pair)
            .onEach { (userId, isBouncerCurrentlyVisible) ->
                resetLockedOutState(userId)
                yield()
                runFaceAuth(
                    FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING,
                    // Fallback to detection if bouncer is not showing so that we can detect a
                    // face and then show the bouncer to the user if face auth can't run
                        fallbackToDetect = !primaryBouncerInteractor.get().isBouncerShowing()
                    fallbackToDetect = !isBouncerCurrentlyVisible
                )
            }
            }
            .launchIn(applicationScope)

        facePropertyRepository.cameraInfo
@@ -210,6 +216,14 @@ constructor(
            .launchIn(applicationScope)
    }

    private val isBouncerVisible: Flow<Boolean> by lazy {
        if (SceneContainerFlag.isEnabled) {
            sceneInteractor.get().transitionState.map { it.isIdle(Scenes.Bouncer) }
        } else {
            primaryBouncerInteractor.get().isShowing
        }
    }

    private suspend fun resetLockedOutState(currentUserId: Int) {
        val lockoutMode = facePropertyRepository.getLockoutMode(currentUserId)
        repository.setLockedOut(
+22 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import android.hardware.biometrics.BiometricSourceType
import android.os.PowerManager
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.keyguard.keyguardUpdateMonitor
import com.android.keyguard.trustManager
import com.android.systemui.SysuiTestCase
@@ -37,6 +38,7 @@ import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.deviceentry.data.repository.fakeFaceWakeUpTriggersConfig
import com.android.systemui.deviceentry.shared.FaceAuthUiEvent
import com.android.systemui.deviceentry.shared.model.ErrorFaceAuthenticationStatus
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
@@ -52,12 +54,15 @@ import com.android.systemui.log.logcatLogBuffer
import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.testKosmos
import com.android.systemui.user.data.model.SelectionStatus
import com.android.systemui.user.data.repository.fakeUserRepository
import com.android.systemui.util.mockito.eq
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -113,6 +118,7 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() {
                powerInteractor,
                fakeBiometricSettingsRepository,
                trustManager,
                { kosmos.sceneInteractor },
                deviceEntryFaceAuthStatusInteractor,
            )
    }
@@ -278,6 +284,22 @@ class DeviceEntryFaceAuthInteractorTest : SysuiTestCase() {
                .isEqualTo(Pair(FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN, false))
        }

    @Test
    @EnableSceneContainer
    fun withSceneContainerEnabled_faceAuthIsRequestedWhenPrimaryBouncerIsVisible() =
        testScope.runTest {
            underTest.start()

            kosmos.sceneInteractor.changeScene(Scenes.Bouncer, "for-test")
            kosmos.sceneInteractor.setTransitionState(
                MutableStateFlow(ObservableTransitionState.Idle(Scenes.Bouncer))
            )

            runCurrent()
            assertThat(faceAuthRepository.runningAuthRequest.value)
                .isEqualTo(Pair(FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN, false))
        }

    @Test
    fun faceAuthIsRequestedWhenAlternateBouncerIsVisible() =
        testScope.runTest {
+2 −0
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.log.FaceAuthenticationLogger
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.user.data.repository.userRepository
import com.android.systemui.util.mockito.mock
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -57,6 +58,7 @@ val Kosmos.deviceEntryFaceAuthInteractor by
            powerInteractor = powerInteractor,
            biometricSettingsRepository = biometricSettingsRepository,
            trustManager = trustManager,
            sceneInteractor = { sceneInteractor },
            deviceEntryFaceAuthStatusInteractor = deviceEntryFaceAuthStatusInteractor,
        )
    }