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

Commit 3dbb9db9 authored by Beverly's avatar Beverly
Browse files

Use KeyguardTransitions instead of PowerInteractor's wakefulness state

PowerInteractor#finishedGoingToSleep doesn't actually mean the
screen finished turning off. Instead, let's rely on KeyguardTransitions
which, when the current state is updated to AOD/off/dozing, the
screen has finished turning off.

Bug: 225183106
Flag: ACONFIG com.android.systemui.udfps_view_performance DEVELOPMENT
Test: atest UdfpsControllerOverlayTest
Change-Id: I74d30d83fb9e6e9cdb4fe26aa755638b924f0371
parent be0aeae3
Loading
Loading
Loading
Loading
+81 −9
Original line number Diff line number Diff line
@@ -46,7 +46,12 @@ import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.FromAodTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.power.data.repository.FakePowerRepository
import com.android.systemui.power.domain.interactor.PowerInteractor
@@ -127,7 +132,8 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
    @Mock private lateinit var defaultUdfpsTouchOverlayViewModel: DefaultUdfpsTouchOverlayViewModel
    @Mock
    private lateinit var udfpsKeyguardAccessibilityDelegate: UdfpsKeyguardAccessibilityDelegate
    @Mock private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
    private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository
    private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
    @Mock private lateinit var shadeInteractor: ShadeInteractor
    @Captor private lateinit var layoutParamsCaptor: ArgumentCaptor<WindowManager.LayoutParams>
    @Mock private lateinit var udfpsOverlayInteractor: UdfpsOverlayInteractor
@@ -150,6 +156,19 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
                mock(ScreenOffAnimationController::class.java),
                statusBarStateController,
            )
        keyguardTransitionRepository = FakeKeyguardTransitionRepository()
        keyguardTransitionInteractor =
            KeyguardTransitionInteractor(
                scope = testScope.backgroundScope,
                repository = keyguardTransitionRepository,
                fromLockscreenTransitionInteractor = {
                    mock(FromLockscreenTransitionInteractor::class.java)
                },
                fromPrimaryBouncerTransitionInteractor = {
                    mock(FromPrimaryBouncerTransitionInteractor::class.java)
                },
                fromAodTransitionInteractor = { mock(FromAodTransitionInteractor::class.java) },
            )
        whenever(inflater.inflate(R.layout.udfps_view, null, false)).thenReturn(udfpsView)
        whenever(inflater.inflate(R.layout.udfps_bp_view, null))
            .thenReturn(mock(UdfpsBpView::class.java))
@@ -159,11 +178,25 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
            .thenReturn(mock(UdfpsFpmEmptyView::class.java))
    }

    private suspend fun withReasonSuspend(
        @RequestReason reason: Int,
        isDebuggable: Boolean = false,
        enableDeviceEntryUdfpsRefactor: Boolean = false,
        block: suspend () -> Unit,
    ) {
        withReason(
            reason,
            isDebuggable,
            enableDeviceEntryUdfpsRefactor,
        )
        block()
    }

    private fun withReason(
        @RequestReason reason: Int,
        isDebuggable: Boolean = false,
        enableDeviceEntryUdfpsRefactor: Boolean = false,
        block: () -> Unit,
        block: () -> Unit = {},
    ) {
        if (enableDeviceEntryUdfpsRefactor) {
            mSetFlagsRule.enableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
@@ -312,6 +345,7 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
                    lastWakeReason = WakeSleepReason.POWER_BUTTON,
                    lastSleepReason = WakeSleepReason.OTHER,
                )
                runCurrent()
                controllerOverlay.show(udfpsController, overlayParams)
                runCurrent()
                verify(windowManager).addView(any(), any())
@@ -321,13 +355,19 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
    @Test
    fun showUdfpsOverlay_whileGoingToSleep() =
        testScope.runTest {
            withReason(REASON_AUTH_KEYGUARD) {
            withReasonSuspend(REASON_AUTH_KEYGUARD) {
                mSetFlagsRule.enableFlags(Flags.FLAG_UDFPS_VIEW_PERFORMANCE)
                keyguardTransitionRepository.sendTransitionSteps(
                    from = KeyguardState.OFF,
                    to = KeyguardState.GONE,
                    testScope = this,
                )
                powerRepository.updateWakefulness(
                    rawState = WakefulnessState.STARTING_TO_SLEEP,
                    lastWakeReason = WakeSleepReason.POWER_BUTTON,
                    lastSleepReason = WakeSleepReason.OTHER,
                )
                runCurrent()
                controllerOverlay.show(udfpsController, overlayParams)
                runCurrent()
                verify(windowManager, never()).addView(any(), any())
@@ -338,29 +378,61 @@ class UdfpsControllerOverlayTest : SysuiTestCase() {
        }

    @Test
    fun showUdfpsOverlay_afterFinishedGoingToSleep() =
    fun showUdfpsOverlay_whileAsleep() =
        testScope.runTest {
            withReason(REASON_AUTH_KEYGUARD) {
            withReasonSuspend(REASON_AUTH_KEYGUARD) {
                mSetFlagsRule.enableFlags(Flags.FLAG_UDFPS_VIEW_PERFORMANCE)
                keyguardTransitionRepository.sendTransitionSteps(
                    from = KeyguardState.OFF,
                    to = KeyguardState.GONE,
                    testScope = this,
                )
                powerRepository.updateWakefulness(
                    rawState = WakefulnessState.STARTING_TO_SLEEP,
                    rawState = WakefulnessState.ASLEEP,
                    lastWakeReason = WakeSleepReason.POWER_BUTTON,
                    lastSleepReason = WakeSleepReason.OTHER,
                )
                runCurrent()
                controllerOverlay.show(udfpsController, overlayParams)
                runCurrent()
                verify(windowManager, never()).addView(any(), any())

                // we hide to end the job that listens for the finishedGoingToSleep signal
                controllerOverlay.hide()
            }
        }

    @Test
    fun showUdfpsOverlay_afterFinishedTransitioningToAOD() =
        testScope.runTest {
            withReasonSuspend(REASON_AUTH_KEYGUARD) {
                mSetFlagsRule.enableFlags(Flags.FLAG_UDFPS_VIEW_PERFORMANCE)
                keyguardTransitionRepository.sendTransitionSteps(
                    from = KeyguardState.OFF,
                    to = KeyguardState.GONE,
                    testScope = this,
                )
                powerRepository.updateWakefulness(
                    rawState = WakefulnessState.ASLEEP,
                    rawState = WakefulnessState.STARTING_TO_SLEEP,
                    lastWakeReason = WakeSleepReason.POWER_BUTTON,
                    lastSleepReason = WakeSleepReason.OTHER,
                )
                runCurrent()
                controllerOverlay.show(udfpsController, overlayParams)
                runCurrent()
                verify(windowManager, never()).addView(any(), any())

                keyguardTransitionRepository.sendTransitionSteps(
                    from = KeyguardState.GONE,
                    to = KeyguardState.AOD,
                    testScope = this,
                )
            }

            runCurrent()
            verify(windowManager)
                .addView(eq(controllerOverlay.getTouchOverlay()), layoutParamsCaptor.capture())
        }
        }

    private fun showUdfpsOverlay() {
        val didShow = controllerOverlay.show(udfpsController, overlayParams)
+21 −12
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.hardware.biometrics.BiometricRequestConstants.RequestReason
import android.hardware.fingerprint.IUdfpsOverlayControllerCallback
import android.os.Build
import android.os.RemoteException
import android.os.Trace
import android.provider.Settings
import android.util.Log
import android.util.RotationUtils
@@ -58,9 +59,9 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.power.shared.model.WakefulnessState
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.LockscreenShadeTransitionController
@@ -125,11 +126,15 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
        private val powerInteractor: PowerInteractor,
        @Application private val scope: CoroutineScope,
) {
    private val isFinishedGoingToSleep: Flow<Unit> =
        powerInteractor.detailedWakefulness
            .filter { it.internalWakefulnessState == WakefulnessState.ASLEEP }
    private val currentStateUpdatedToOffAodOrDozing: Flow<Unit> =
        transitionInteractor.currentKeyguardState
            .filter {
                it == KeyguardState.OFF ||
                    it == KeyguardState.AOD ||
                    it == KeyguardState.DOZING
            }
            .map { } // map to Unit
    private var listenForAsleepJob: Job? = null
    private var listenForCurrentKeyguardState: Job? = null
    private var addViewRunnable: Runnable? = null
    private var overlayViewLegacy: UdfpsView? = null
        private set
@@ -280,18 +285,19 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
    private fun addViewNowOrLater(view: View, animation: UdfpsAnimationViewController<*>?) {
        if (udfpsViewPerformance()) {
            addViewRunnable = kotlinx.coroutines.Runnable {
                Trace.setCounter("UdfpsAddView", 1)
                windowManager.addView(
                        view,
                        coreLayoutParams.updateDimensions(animation)
                )
            }
            if (powerInteractor.detailedWakefulness.value.internalWakefulnessState
                    != WakefulnessState.STARTING_TO_SLEEP) {
            if (powerInteractor.detailedWakefulness.value.isAwake()) {
                // Device is awake, so we add the view immediately.
                addViewIfPending()
            } else {
                listenForAsleepJob?.cancel()
                listenForAsleepJob = scope.launch {
                    isFinishedGoingToSleep.collect {
                listenForCurrentKeyguardState?.cancel()
                listenForCurrentKeyguardState = scope.launch {
                    currentStateUpdatedToOffAodOrDozing.collect {
                        addViewIfPending()
                    }
                }
@@ -306,7 +312,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(

    private fun addViewIfPending() {
        addViewRunnable?.let {
            listenForAsleepJob?.cancel()
            listenForCurrentKeyguardState?.cancel()
            it.run()
        }
        addViewRunnable = null
@@ -413,6 +419,9 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
        }
        getTouchOverlay()?.apply {
            windowManager.removeView(this)
            if (udfpsViewPerformance()) {
                Trace.setCounter("UdfpsAddView", 0)
            }
            setOnTouchListener(null)
            setOnHoverListener(null)
            overlayTouchListener?.let {
@@ -423,7 +432,7 @@ class UdfpsControllerOverlay @JvmOverloads constructor(
        overlayViewLegacy = null
        overlayTouchView = null
        overlayTouchListener = null
        listenForAsleepJob?.cancel()
        listenForCurrentKeyguardState?.cancel()

        return wasShowing
    }