Loading packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt +16 −14 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import com.android.systemui.statusbar.phone.dozeScrimController import com.android.systemui.statusbar.phone.screenOffAnimationController import com.android.systemui.testKosmos 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.advanceTimeBy Loading Loading @@ -105,7 +106,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { @Test fun nonPowerButtonFPS_vibrateSuccess() = testScope.runTest { val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.UDFPS_ULTRASONIC) runCurrent() enterDeviceFromFingerprintUnlockLegacy() Loading @@ -116,7 +117,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { @Test fun powerButtonFPS_vibrateSuccess() = testScope.runTest { val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.POWER_BUTTON) kosmos.fakeKeyEventRepository.setPowerButtonDown(false) Loading @@ -133,7 +134,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { @Test fun powerButtonFPS_powerDown_doNotVibrateSuccess() = testScope.runTest { val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.POWER_BUTTON) kosmos.fakeKeyEventRepository.setPowerButtonDown(true) // power button is currently DOWN Loading @@ -150,7 +151,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { @Test fun powerButtonFPS_powerButtonRecentlyPressed_doNotVibrateSuccess() = testScope.runTest { val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.POWER_BUTTON) kosmos.fakeKeyEventRepository.setPowerButtonDown(false) Loading @@ -174,14 +175,14 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { } @Test fun nonPowerButtonFPS_coExFaceFailure_vibrateError() = fun nonPowerButtonFPS_coExFaceFailure_doNotVibrateError() = testScope.runTest { val playErrorHaptic by collectLastValue(underTest.playErrorHaptic) enrollFingerprint(FingerprintSensorType.UDFPS_ULTRASONIC) enrollFace() runCurrent() faceFailure() assertThat(playErrorHaptic).isNotNull() assertThat(playErrorHaptic).isNull() } @Test Loading Loading @@ -211,7 +212,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { testScope.runTest { kosmos.configureKeyguardBypass(isBypassAvailable = false) underTest = kosmos.deviceEntryHapticsInteractor val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.UDFPS_ULTRASONIC) runCurrent() configureDeviceEntryFromBiometricSource(isFpUnlock = true) Loading @@ -225,7 +226,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { testScope.runTest { kosmos.configureKeyguardBypass(isBypassAvailable = false) underTest = kosmos.deviceEntryHapticsInteractor val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.POWER_BUTTON) kosmos.fakeKeyEventRepository.setPowerButtonDown(false) Loading @@ -246,18 +247,19 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { enrollFace() kosmos.configureKeyguardBypass(isBypassAvailable = true) underTest = kosmos.deviceEntryHapticsInteractor val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) configureDeviceEntryFromBiometricSource(isFaceUnlock = true) verifyDeviceEntryFromFaceAuth() assertThat(playSuccessHaptic).isNotNull() } @OptIn(ExperimentalCoroutinesApi::class) @EnableSceneContainer @Test fun playSuccessHaptic_onFaceAuthSuccess_whenBypassDisabled_sceneContainer() = fun skipSuccessHaptic_onFaceAuthSuccess_whenBypassDisabled_sceneContainer() = testScope.runTest { underTest = kosmos.deviceEntryHapticsInteractor val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFace() kosmos.configureKeyguardBypass(isBypassAvailable = false) Loading @@ -265,7 +267,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { configureDeviceEntryFromBiometricSource(isFaceUnlock = true, bypassEnabled = false) kosmos.fakeDeviceEntryFaceAuthRepository.isAuthenticated.value = true assertThat(playSuccessHaptic).isNotNull() assertThat(playSuccessHaptic).isNull() } @EnableSceneContainer Loading @@ -274,7 +276,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { testScope.runTest { kosmos.configureKeyguardBypass(isBypassAvailable = false) underTest = kosmos.deviceEntryHapticsInteractor val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.POWER_BUTTON) // power button is currently DOWN kosmos.fakeKeyEventRepository.setPowerButtonDown(true) Loading @@ -295,7 +297,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { testScope.runTest { kosmos.configureKeyguardBypass(isBypassAvailable = false) underTest = kosmos.deviceEntryHapticsInteractor val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.POWER_BUTTON) kosmos.fakeKeyEventRepository.setPowerButtonDown(false) Loading packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +15 −17 Original line number Diff line number Diff line Loading @@ -863,7 +863,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasUdfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading @@ -885,7 +885,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasUdfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading @@ -907,7 +907,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasSfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading @@ -930,7 +930,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasSfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading Loading @@ -1033,7 +1033,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasSfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading @@ -1056,7 +1056,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasSfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading @@ -1079,7 +1079,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasSfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading @@ -1102,7 +1102,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasSfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading Loading @@ -1160,7 +1160,7 @@ class SceneContainerStartableTest : SysuiTestCase() { @Test @DisableFlags(Flags.FLAG_MSDL_FEEDBACK) fun playsFaceErrorHaptics_nonSfps_coEx() = fun skipsFaceErrorHaptics_nonSfps_coEx() = testScope.runTest { val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic) Loading @@ -1172,15 +1172,14 @@ class SceneContainerStartableTest : SysuiTestCase() { underTest.start() updateFaceAuthStatus(isSuccess = false) assertThat(playErrorHaptic).isNotNull() assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) verify(vibratorHelper).vibrateAuthError(anyString()) assertThat(playErrorHaptic).isNull() verify(vibratorHelper, never()).vibrateAuthError(anyString()) verify(vibratorHelper, never()).vibrateAuthSuccess(anyString()) } @Test @EnableFlags(Flags.FLAG_MSDL_FEEDBACK) fun playsMSDLFaceErrorHaptics_nonSfps_coEx() = fun skipsMSDLFaceErrorHaptics_nonSfps_coEx() = testScope.runTest { val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic) Loading @@ -1192,10 +1191,9 @@ class SceneContainerStartableTest : SysuiTestCase() { underTest.start() updateFaceAuthStatus(isSuccess = false) assertThat(playErrorHaptic).isNotNull() assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.FAILURE) assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties) assertThat(playErrorHaptic).isNull() assertThat(msdlPlayer.latestTokenPlayed).isNull() assertThat(msdlPlayer.latestPropertiesPlayed).isNull() } @Test Loading packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt +0 −6 Original line number Diff line number Diff line Loading @@ -68,10 +68,4 @@ constructor( emptyFlow() } } /** Triggered if a face failure occurs regardless of the mode. */ val faceFailure: Flow<FailedFaceAuthenticationStatus> = deviceEntryFaceAuthInteractor.authenticationStatus.filterIsInstance< FailedFaceAuthenticationStatus >() } packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt +9 −19 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ 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 Loading @@ -49,8 +48,6 @@ class DeviceEntryHapticsInteractor constructor( biometricSettingsRepository: BiometricSettingsRepository, deviceEntryBiometricAuthInteractor: DeviceEntryBiometricAuthInteractor, deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor, keyguardBypassInteractor: KeyguardBypassInteractor, deviceEntryFingerprintAuthInteractor: DeviceEntryFingerprintAuthInteractor, deviceEntrySourceInteractor: DeviceEntrySourceInteractor, fingerprintPropertyRepository: FingerprintPropertyRepository, Loading Loading @@ -83,7 +80,12 @@ constructor( emit(recentPowerButtonPressThresholdMs * -1L - 1L) } private val playHapticsOnDeviceEntry: Flow<Boolean> = /** * Indicates when success haptics should play when the device is entered. This always occurs on * successful fingerprint authentications. It also occurs on successful face authentication but * only if the lockscreen is bypassed. */ val playSuccessHapticOnDeviceEntry: Flow<Unit> = deviceEntrySourceInteractor.deviceEntryFromBiometricSource .sample( combine( Loading @@ -93,29 +95,17 @@ constructor( ::Triple, ) ) .map { (sideFpsEnrolled, powerButtonDown, lastPowerButtonWakeup) -> .filter { (sideFpsEnrolled, powerButtonDown, lastPowerButtonWakeup) -> val sideFpsAllowsHaptic = !powerButtonDown && systemClock.uptimeMillis() - lastPowerButtonWakeup > recentPowerButtonPressThresholdMs val allowHaptic = !sideFpsEnrolled || sideFpsAllowsHaptic if (!allowHaptic) { logger.d( "Skip success entry haptic from power button. Recent power button press or button is down." ) logger.d("Skip success haptic. 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") Loading @@ -123,7 +113,7 @@ constructor( private val playErrorHapticForBiometricFailure: Flow<Unit> = merge( deviceEntryFingerprintAuthInteractor.fingerprintFailure, deviceEntryBiometricAuthInteractor.faceFailure, deviceEntryBiometricAuthInteractor.faceOnlyFaceFailure, ) // map to Unit .map {} Loading packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt +1 −1 Original line number Diff line number Diff line Loading @@ -333,7 +333,7 @@ object KeyguardRootViewBinder { if (deviceEntryHapticsInteractor != null && vibratorHelper != null) { launch { deviceEntryHapticsInteractor.playSuccessHaptic.collect { deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry.collect { if (msdlFeedback()) { msdlPlayer?.playToken( MSDLToken.UNLOCK, Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractorTest.kt +16 −14 Original line number Diff line number Diff line Loading @@ -56,6 +56,7 @@ import com.android.systemui.statusbar.phone.dozeScrimController import com.android.systemui.statusbar.phone.screenOffAnimationController import com.android.systemui.testKosmos 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.advanceTimeBy Loading Loading @@ -105,7 +106,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { @Test fun nonPowerButtonFPS_vibrateSuccess() = testScope.runTest { val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.UDFPS_ULTRASONIC) runCurrent() enterDeviceFromFingerprintUnlockLegacy() Loading @@ -116,7 +117,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { @Test fun powerButtonFPS_vibrateSuccess() = testScope.runTest { val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.POWER_BUTTON) kosmos.fakeKeyEventRepository.setPowerButtonDown(false) Loading @@ -133,7 +134,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { @Test fun powerButtonFPS_powerDown_doNotVibrateSuccess() = testScope.runTest { val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.POWER_BUTTON) kosmos.fakeKeyEventRepository.setPowerButtonDown(true) // power button is currently DOWN Loading @@ -150,7 +151,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { @Test fun powerButtonFPS_powerButtonRecentlyPressed_doNotVibrateSuccess() = testScope.runTest { val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.POWER_BUTTON) kosmos.fakeKeyEventRepository.setPowerButtonDown(false) Loading @@ -174,14 +175,14 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { } @Test fun nonPowerButtonFPS_coExFaceFailure_vibrateError() = fun nonPowerButtonFPS_coExFaceFailure_doNotVibrateError() = testScope.runTest { val playErrorHaptic by collectLastValue(underTest.playErrorHaptic) enrollFingerprint(FingerprintSensorType.UDFPS_ULTRASONIC) enrollFace() runCurrent() faceFailure() assertThat(playErrorHaptic).isNotNull() assertThat(playErrorHaptic).isNull() } @Test Loading Loading @@ -211,7 +212,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { testScope.runTest { kosmos.configureKeyguardBypass(isBypassAvailable = false) underTest = kosmos.deviceEntryHapticsInteractor val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.UDFPS_ULTRASONIC) runCurrent() configureDeviceEntryFromBiometricSource(isFpUnlock = true) Loading @@ -225,7 +226,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { testScope.runTest { kosmos.configureKeyguardBypass(isBypassAvailable = false) underTest = kosmos.deviceEntryHapticsInteractor val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.POWER_BUTTON) kosmos.fakeKeyEventRepository.setPowerButtonDown(false) Loading @@ -246,18 +247,19 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { enrollFace() kosmos.configureKeyguardBypass(isBypassAvailable = true) underTest = kosmos.deviceEntryHapticsInteractor val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) configureDeviceEntryFromBiometricSource(isFaceUnlock = true) verifyDeviceEntryFromFaceAuth() assertThat(playSuccessHaptic).isNotNull() } @OptIn(ExperimentalCoroutinesApi::class) @EnableSceneContainer @Test fun playSuccessHaptic_onFaceAuthSuccess_whenBypassDisabled_sceneContainer() = fun skipSuccessHaptic_onFaceAuthSuccess_whenBypassDisabled_sceneContainer() = testScope.runTest { underTest = kosmos.deviceEntryHapticsInteractor val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFace() kosmos.configureKeyguardBypass(isBypassAvailable = false) Loading @@ -265,7 +267,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { configureDeviceEntryFromBiometricSource(isFaceUnlock = true, bypassEnabled = false) kosmos.fakeDeviceEntryFaceAuthRepository.isAuthenticated.value = true assertThat(playSuccessHaptic).isNotNull() assertThat(playSuccessHaptic).isNull() } @EnableSceneContainer Loading @@ -274,7 +276,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { testScope.runTest { kosmos.configureKeyguardBypass(isBypassAvailable = false) underTest = kosmos.deviceEntryHapticsInteractor val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.POWER_BUTTON) // power button is currently DOWN kosmos.fakeKeyEventRepository.setPowerButtonDown(true) Loading @@ -295,7 +297,7 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() { testScope.runTest { kosmos.configureKeyguardBypass(isBypassAvailable = false) underTest = kosmos.deviceEntryHapticsInteractor val playSuccessHaptic by collectLastValue(underTest.playSuccessHaptic) val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry) enrollFingerprint(FingerprintSensorType.POWER_BUTTON) kosmos.fakeKeyEventRepository.setPowerButtonDown(false) Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt +15 −17 Original line number Diff line number Diff line Loading @@ -863,7 +863,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasUdfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading @@ -885,7 +885,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasUdfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading @@ -907,7 +907,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasSfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading @@ -930,7 +930,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasSfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading Loading @@ -1033,7 +1033,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasSfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading @@ -1056,7 +1056,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasSfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading @@ -1079,7 +1079,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasSfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading @@ -1102,7 +1102,7 @@ class SceneContainerStartableTest : SysuiTestCase() { whenever(kosmos.keyguardUpdateMonitor.isDeviceInteractive).thenReturn(true) val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playSuccessHaptic by collectLastValue(deviceEntryHapticsInteractor.playSuccessHaptic) collectLastValue(deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry) setupBiometricAuth(hasSfps = true) assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) Loading Loading @@ -1160,7 +1160,7 @@ class SceneContainerStartableTest : SysuiTestCase() { @Test @DisableFlags(Flags.FLAG_MSDL_FEEDBACK) fun playsFaceErrorHaptics_nonSfps_coEx() = fun skipsFaceErrorHaptics_nonSfps_coEx() = testScope.runTest { val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic) Loading @@ -1172,15 +1172,14 @@ class SceneContainerStartableTest : SysuiTestCase() { underTest.start() updateFaceAuthStatus(isSuccess = false) assertThat(playErrorHaptic).isNotNull() assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) verify(vibratorHelper).vibrateAuthError(anyString()) assertThat(playErrorHaptic).isNull() verify(vibratorHelper, never()).vibrateAuthError(anyString()) verify(vibratorHelper, never()).vibrateAuthSuccess(anyString()) } @Test @EnableFlags(Flags.FLAG_MSDL_FEEDBACK) fun playsMSDLFaceErrorHaptics_nonSfps_coEx() = fun skipsMSDLFaceErrorHaptics_nonSfps_coEx() = testScope.runTest { val currentSceneKey by collectLastValue(sceneInteractor.currentScene) val playErrorHaptic by collectLastValue(deviceEntryHapticsInteractor.playErrorHaptic) Loading @@ -1192,10 +1191,9 @@ class SceneContainerStartableTest : SysuiTestCase() { underTest.start() updateFaceAuthStatus(isSuccess = false) assertThat(playErrorHaptic).isNotNull() assertThat(currentSceneKey).isEqualTo(Scenes.Lockscreen) assertThat(msdlPlayer.latestTokenPlayed).isEqualTo(MSDLToken.FAILURE) assertThat(msdlPlayer.latestPropertiesPlayed).isEqualTo(authInteractionProperties) assertThat(playErrorHaptic).isNull() assertThat(msdlPlayer.latestTokenPlayed).isNull() assertThat(msdlPlayer.latestPropertiesPlayed).isNull() } @Test Loading
packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricAuthInteractor.kt +0 −6 Original line number Diff line number Diff line Loading @@ -68,10 +68,4 @@ constructor( emptyFlow() } } /** Triggered if a face failure occurs regardless of the mode. */ val faceFailure: Flow<FailedFaceAuthenticationStatus> = deviceEntryFaceAuthInteractor.authenticationStatus.filterIsInstance< FailedFaceAuthenticationStatus >() }
packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryHapticsInteractor.kt +9 −19 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ 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 Loading @@ -49,8 +48,6 @@ class DeviceEntryHapticsInteractor constructor( biometricSettingsRepository: BiometricSettingsRepository, deviceEntryBiometricAuthInteractor: DeviceEntryBiometricAuthInteractor, deviceEntryFaceAuthInteractor: DeviceEntryFaceAuthInteractor, keyguardBypassInteractor: KeyguardBypassInteractor, deviceEntryFingerprintAuthInteractor: DeviceEntryFingerprintAuthInteractor, deviceEntrySourceInteractor: DeviceEntrySourceInteractor, fingerprintPropertyRepository: FingerprintPropertyRepository, Loading Loading @@ -83,7 +80,12 @@ constructor( emit(recentPowerButtonPressThresholdMs * -1L - 1L) } private val playHapticsOnDeviceEntry: Flow<Boolean> = /** * Indicates when success haptics should play when the device is entered. This always occurs on * successful fingerprint authentications. It also occurs on successful face authentication but * only if the lockscreen is bypassed. */ val playSuccessHapticOnDeviceEntry: Flow<Unit> = deviceEntrySourceInteractor.deviceEntryFromBiometricSource .sample( combine( Loading @@ -93,29 +95,17 @@ constructor( ::Triple, ) ) .map { (sideFpsEnrolled, powerButtonDown, lastPowerButtonWakeup) -> .filter { (sideFpsEnrolled, powerButtonDown, lastPowerButtonWakeup) -> val sideFpsAllowsHaptic = !powerButtonDown && systemClock.uptimeMillis() - lastPowerButtonWakeup > recentPowerButtonPressThresholdMs val allowHaptic = !sideFpsEnrolled || sideFpsAllowsHaptic if (!allowHaptic) { logger.d( "Skip success entry haptic from power button. Recent power button press or button is down." ) logger.d("Skip success haptic. 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") Loading @@ -123,7 +113,7 @@ constructor( private val playErrorHapticForBiometricFailure: Flow<Unit> = merge( deviceEntryFingerprintAuthInteractor.fingerprintFailure, deviceEntryBiometricAuthInteractor.faceFailure, deviceEntryBiometricAuthInteractor.faceOnlyFaceFailure, ) // map to Unit .map {} Loading
packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/KeyguardRootViewBinder.kt +1 −1 Original line number Diff line number Diff line Loading @@ -333,7 +333,7 @@ object KeyguardRootViewBinder { if (deviceEntryHapticsInteractor != null && vibratorHelper != null) { launch { deviceEntryHapticsInteractor.playSuccessHaptic.collect { deviceEntryHapticsInteractor.playSuccessHapticOnDeviceEntry.collect { if (msdlFeedback()) { msdlPlayer?.playToken( MSDLToken.UNLOCK, Loading