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

Commit 7204034d authored by Juan Sebastian Martinez's avatar Juan Sebastian Martinez
Browse files

Playing face auth MSDL haptics when lockscreen does not dismiss.

If the user setting to dismiss the keyguard is turned off, we should
still play haptics when face authentication successfully unlocks the
device. This can be done via a combination of the power state button
state upon device entry, and the face authentication result and the
state of the bypass setting.

Test: DeviceEntryHapticsInteractorTest
Flag: com.android.systemui.msdl_feedback
Bug: 361165906

Change-Id: I99b6a3c3d36373e2a6a2f9b2bee414beb6228793
parent 2ff94617
Loading
Loading
Loading
Loading
+24 −4
Original line number Diff line number Diff line
@@ -254,6 +254,22 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
            assertThat(playSuccessHaptic).isNotNull()
        }

    @EnableSceneContainer
    @Test
    fun playSuccessHaptic_onFaceAuthSuccess_whenBypassDisabled_sceneContainer() =
        testScope.runTest {
            underTest = kosmos.deviceEntryHapticsInteractor
            val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic)

            enrollFace()
            kosmos.configureKeyguardBypass(isBypassAvailable = false)
            runCurrent()
            configureDeviceEntryFromBiometricSource(isFaceUnlock = true, bypassEnabled = false)
            kosmos.fakeDeviceEntryFaceAuthRepository.isAuthenticated.value = true

            assertThat(playSuccessHaptic).isNotNull()
        }

    @EnableSceneContainer
    @Test
    fun skipSuccessHaptic_onDeviceEntryFromSfps_whenPowerDown_sceneContainer() =
@@ -299,6 +315,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
    private fun configureDeviceEntryFromBiometricSource(
        isFpUnlock: Boolean = false,
        isFaceUnlock: Boolean = false,
        bypassEnabled: Boolean = true,
    ) {
        // Mock DeviceEntrySourceInteractor#deviceEntryBiometricAuthSuccessState
        if (isFpUnlock) {
@@ -314,12 +331,15 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
            )

            // Mock DeviceEntrySourceInteractor#faceWakeAndUnlockMode = MODE_UNLOCK_COLLAPSING
            // if the successful face authentication will bypass keyguard
            if (bypassEnabled) {
                kosmos.sceneInteractor.setTransitionState(
                    MutableStateFlow<ObservableTransitionState>(
                        ObservableTransitionState.Idle(Scenes.Lockscreen)
                    )
                )
            }
        }
        underTest = kosmos.deviceEntryHapticsInteractor
    }

+18 −3
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyevent.domain.interactor.KeyEventInteractor
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardBypassInteractor
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.util.kotlin.FlowDumperImpl
@@ -50,6 +51,8 @@ class DeviceEntryHapticsInteractor
constructor(
    biometricSettingsRepository: BiometricSettingsRepository,
    deviceEntryBiometricAuthInteractor: DeviceEntryBiometricAuthInteractor,
    deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor,
    keyguardBypassInteractor: KeyguardBypassInteractor,
    deviceEntryFingerprintAuthInteractor: DeviceEntryFingerprintAuthInteractor,
    deviceEntrySourceInteractor: DeviceEntrySourceInteractor,
    fingerprintPropertyRepository: FingerprintPropertyRepository,
@@ -82,7 +85,7 @@ constructor(
                emit(recentPowerButtonPressThresholdMs * -1L - 1L)
            }

    val playSuccessHaptic: Flow<Unit> =
    private val playHapticsOnDeviceEntry: Flow<Boolean> =
        deviceEntrySourceInteractor.deviceEntryFromBiometricSource
            .sample(
                combine(
@@ -92,17 +95,29 @@ constructor(
                    ::Triple,
                )
            )
            .filter { (sideFpsEnrolled, powerButtonDown, lastPowerButtonWakeup) ->
            .map { (sideFpsEnrolled, powerButtonDown, lastPowerButtonWakeup) ->
                val sideFpsAllowsHaptic =
                    !powerButtonDown &&
                        systemClock.uptimeMillis() - lastPowerButtonWakeup >
                            recentPowerButtonPressThresholdMs
                val allowHaptic = !sideFpsEnrolled || sideFpsAllowsHaptic
                if (!allowHaptic) {
                    logger.d("Skip success haptic. Recent power button press or button is down.")
                    logger.d(
                        "Skip success entry haptic from power button. Recent power button press or button is down."
                    )
                }
                allowHaptic
            }

    private val playHapticsOnFaceAuthSuccessAndBypassDisabled: Flow<Boolean> =
        deviceEntryFaceAuthInteractor.isAuthenticated
            .filter { it }
            .sample(keyguardBypassInteractor.isBypassAvailable)
            .map { !it }

    val playSuccessHaptic: Flow<Unit> =
        merge(playHapticsOnDeviceEntry, playHapticsOnFaceAuthSuccessAndBypassDisabled)
            .filter { it }
            // map to Unit
            .map {}
            .dumpWhileCollecting("playSuccessHaptic")
+3 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import com.android.systemui.biometrics.data.repository.fingerprintPropertyReposi
import com.android.systemui.dump.dumpManager
import com.android.systemui.keyevent.domain.interactor.keyEventInteractor
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
import com.android.systemui.keyguard.domain.interactor.keyguardBypassInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.util.time.systemClock
@@ -34,6 +35,8 @@ val Kosmos.deviceEntryHapticsInteractor by
        DeviceEntryHapticsInteractor(
            biometricSettingsRepository = biometricSettingsRepository,
            deviceEntryBiometricAuthInteractor = deviceEntryBiometricAuthInteractor,
            deviceEntryFaceAuthInteractor = deviceEntryFaceAuthInteractor,
            keyguardBypassInteractor = keyguardBypassInteractor,
            deviceEntryFingerprintAuthInteractor = deviceEntryFingerprintAuthInteractor,
            deviceEntrySourceInteractor = deviceEntrySourceInteractor,
            fingerprintPropertyRepository = fingerprintPropertyRepository,