summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Juan Sebastian Martinez <juansmartinez@google.com> 2024-12-17 15:08:02 -0800
committer Juan Sebastian Martinez <juansmartinez@google.com> 2025-01-08 14:24:21 -0800
commit7204034dfa2aa9bb95dcd6f684737d94743a5b91 (patch)
tree7a1adb91eaa64b70af91bcb847df7c8d35efe229
parent2ff94617644f13fa18a12087a311a41647aed388 (diff)
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
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt21
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt3
3 files changed, 45 insertions, 7 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt
index 20d66155e5ca..6c955bf1818d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt
@@ -256,6 +256,22 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
@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() =
testScope.runTest {
kosmos.configureKeyguardBypass(isBypassAvailable = false)
@@ -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,11 +331,14 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
)
// Mock DeviceEntrySourceInteractor#faceWakeAndUnlockMode = MODE_UNLOCK_COLLAPSING
- kosmos.sceneInteractor.setTransitionState(
- MutableStateFlow<ObservableTransitionState>(
- ObservableTransitionState.Idle(Scenes.Lockscreen)
+ // if the successful face authentication will bypass keyguard
+ if (bypassEnabled) {
+ kosmos.sceneInteractor.setTransitionState(
+ MutableStateFlow<ObservableTransitionState>(
+ ObservableTransitionState.Idle(Scenes.Lockscreen)
+ )
)
- )
+ }
}
underTest = kosmos.deviceEntryHapticsInteractor
}
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt
index 41a59a959771..ae6238724042 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt
@@ -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")
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt
index 2a7e3e903737..490b89bf6b13 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorKosmos.kt
@@ -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,