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

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

Merge "Playing device entry haptics from the DevieEntryIcon." into main

parents ea21800b 156afbb6
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import com.android.systemui.log.dagger.LongPressTouchLog
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.res.R
import com.android.systemui.statusbar.VibratorHelper
import com.google.android.msdl.domain.MSDLPlayer
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
@@ -66,6 +67,7 @@ constructor(
    private val deviceEntryBackgroundViewModel: Lazy<DeviceEntryBackgroundViewModel>,
    private val falsingManager: Lazy<FalsingManager>,
    private val vibratorHelper: Lazy<VibratorHelper>,
    private val msdlPlayer: Lazy<MSDLPlayer>,
    @LongPressTouchLog private val logBuffer: LogBuffer,
) {
    @Composable
@@ -90,6 +92,7 @@ constructor(
                            deviceEntryBackgroundViewModel.get(),
                            falsingManager.get(),
                            vibratorHelper.get(),
                            msdlPlayer.get(),
                            overrideColor,
                        )
                    }
+14 −0
Original line number Diff line number Diff line
@@ -311,6 +311,20 @@ class DeviceEntryHapticsInteractorTest : SysuiTestCase() {
            assertThat(playSuccessHaptic).isNull()
        }

    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    fun playSuccessHaptic_onDeviceEntry_fromDeviceEntryIcon() =
        testScope.runTest {
            underTest = kosmos.deviceEntryHapticsInteractor
            val playSuccessHaptic by collectLastValue(underTest.playSuccessHapticOnDeviceEntry)

            kosmos.fakeKeyguardRepository.setKeyguardDismissible(true)
            runCurrent()
            kosmos.deviceEntrySourceInteractor.attemptEnterDeviceFromDeviceEntryIcon()

            assertThat(playSuccessHaptic).isNotNull()
        }

    // Mock dependencies for DeviceEntrySourceInteractor#deviceEntryFromBiometricSource
    private fun configureDeviceEntryFromBiometricSource(
        isFpUnlock: Boolean = false,
+12 −7
Original line number Diff line number Diff line
@@ -16,10 +16,12 @@
package com.android.systemui.deviceentry.domain.interactor

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
@@ -31,13 +33,19 @@ class AuthRippleInteractor
constructor(
    deviceEntrySourceInteractor: DeviceEntrySourceInteractor,
    deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
    keyguardInteractor: KeyguardInteractor,
) {
    private val successfulEntryFromDeviceEntryIcon: Flow<Unit> =
        deviceEntrySourceInteractor.attemptEnterDeviceFromDeviceEntryIcon
            .map { keyguardInteractor.isKeyguardDismissible.value }
            .filter { it } // only emit events if the keyguard is dismissible
            // map to Unit
            .map {}

    private val showUnlockRippleFromDeviceEntryIcon: Flow<BiometricUnlockSource> =
        deviceEntryUdfpsInteractor.isUdfpsSupported.flatMapLatest { isUdfpsSupported ->
            if (isUdfpsSupported) {
                deviceEntrySourceInteractor.deviceEntryFromDeviceEntryIcon.map {
                    BiometricUnlockSource.FINGERPRINT_SENSOR
                }
                successfulEntryFromDeviceEntryIcon.map { BiometricUnlockSource.FINGERPRINT_SENSOR }
            } else {
                emptyFlow()
            }
@@ -46,8 +54,5 @@ constructor(
    private val showUnlockRippleFromBiometricUnlock: Flow<BiometricUnlockSource> =
        deviceEntrySourceInteractor.deviceEntryFromBiometricSource
    val showUnlockRipple: Flow<BiometricUnlockSource> =
        merge(
            showUnlockRippleFromDeviceEntryIcon,
            showUnlockRippleFromBiometricUnlock,
        )
        merge(showUnlockRippleFromDeviceEntryIcon, showUnlockRippleFromBiometricUnlock)
}
+29 −7
Original line number Diff line number Diff line
@@ -16,12 +16,14 @@
package com.android.systemui.deviceentry.domain.interactor

import com.android.keyguard.logging.BiometricUnlockLogger
import com.android.systemui.Flags
import com.android.systemui.biometrics.data.repository.FingerprintPropertyRepository
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
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.KeyguardInteractor
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.util.kotlin.FlowDumperImpl
@@ -54,6 +56,7 @@ constructor(
    keyEventInteractor: KeyEventInteractor,
    private val logger: BiometricUnlockLogger,
    powerInteractor: PowerInteractor,
    keyguardInteractor: KeyguardInteractor,
    private val systemClock: SystemClock,
    dumpManager: DumpManager,
) : FlowDumperImpl(dumpManager) {
@@ -80,12 +83,7 @@ constructor(
                emit(recentPowerButtonPressThresholdMs * -1L - 1L)
            }

    /**
     * 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> =
    private val playSuccessHapticOnDeviceEntryFromBiometricSource: Flow<Unit> =
        deviceEntrySourceInteractor.deviceEntryFromBiometricSource
            .sample(
                combine(
@@ -108,7 +106,31 @@ constructor(
            }
            // map to Unit
            .map {}

    private val playSuccessHapticOnDeviceEntryFromDeviceEntryIcon: Flow<Unit> =
        deviceEntrySourceInteractor.attemptEnterDeviceFromDeviceEntryIcon
            .map { keyguardInteractor.isKeyguardDismissible.value }
            .filter { it } // only play if the keyguard is dismissible
            // map to Unit
            .map {}

    /**
     * Indicates when success haptics should play when the device is entered. When entering via a
     * biometric sources, 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> =
        if (Flags.msdlFeedback()) {
            merge(
                    playSuccessHapticOnDeviceEntryFromBiometricSource,
                    playSuccessHapticOnDeviceEntryFromDeviceEntryIcon,
                )
                .dumpWhileCollecting("playSuccessHaptic")
        } else {
            playSuccessHapticOnDeviceEntryFromBiometricSource.dumpWhileCollecting(
                "playSuccessHaptic"
            )
        }

    private val playErrorHapticForBiometricFailure: Flow<Unit> =
        merge(
+4 −7
Original line number Diff line number Diff line
@@ -254,15 +254,12 @@ constructor(
            }
            .dumpWhileCollecting("deviceEntryFromBiometricSource")

    private val attemptEnterDeviceFromDeviceEntryIcon: MutableSharedFlow<Unit> = MutableSharedFlow()
    val deviceEntryFromDeviceEntryIcon: Flow<Unit> =
        attemptEnterDeviceFromDeviceEntryIcon
            .sample(keyguardInteractor.isKeyguardDismissible)
            .filter { it } // only send events if the keyguard is dismissible
            .map {} // map to Unit
    private val _attemptEnterDeviceFromDeviceEntryIcon: MutableSharedFlow<Unit> =
        MutableSharedFlow()
    val attemptEnterDeviceFromDeviceEntryIcon = _attemptEnterDeviceFromDeviceEntryIcon

    suspend fun attemptEnterDeviceFromDeviceEntryIcon() {
        attemptEnterDeviceFromDeviceEntryIcon.emit(Unit)
        _attemptEnterDeviceFromDeviceEntryIcon.emit(Unit)
    }

    private fun biometricModeIntToObject(@WakeAndUnlockMode value: Int): BiometricUnlockMode {
Loading