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

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

Merge "Resolve race condition when requesting bouncer from AOD/dozing" into main

parents c6d55854 e40f3736
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -60,9 +60,12 @@ import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractor
import com.android.systemui.biometrics.domain.interactor.DisplayStateInteractorImpl
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
import com.android.systemui.display.data.repository.FakeDisplayRepository
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.res.R
import com.android.systemui.shared.Flags.FLAG_SIDEFPS_CONTROLLER_REFACTOR
@@ -158,6 +161,9 @@ class SideFpsControllerTest : SysuiTestCase() {
                FakeBiometricSettingsRepository(),
                FakeSystemClock(),
                mock(KeyguardUpdateMonitor::class.java),
                { mock(DeviceEntryFingerprintAuthInteractor::class.java) },
                { mock(KeyguardInteractor::class.java) },
                { mock(KeyguardTransitionInteractor::class.java) },
                testScope.backgroundScope,
            )
        displayStateInteractor =
+14 −0
Original line number Diff line number Diff line
@@ -24,14 +24,18 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.biometrics.data.repository.FakeFingerprintPropertyRepository
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepositoryImpl
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.keyguard.data.repository.FakeBiometricSettingsRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
import com.android.systemui.util.time.SystemClock
import dagger.Lazy
import kotlinx.coroutines.test.TestScope
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
@@ -39,6 +43,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.MockitoAnnotations

@SmallTest
@@ -81,10 +86,19 @@ class AlternateBouncerInteractorTest : SysuiTestCase() {
                biometricSettingsRepository,
                systemClock,
                keyguardUpdateMonitor,
                Lazy { mock(DeviceEntryFingerprintAuthInteractor::class.java) },
                Lazy { mock(KeyguardInteractor::class.java) },
                Lazy { mock(KeyguardTransitionInteractor::class.java) },
                TestScope().backgroundScope,
            )
    }

    @Test(expected = IllegalStateException::class)
    fun enableUdfpsRefactor_deprecatedShowMethod_throwsIllegalStateException() {
        mSetFlagsRule.enableFlags(Flags.FLAG_DEVICE_ENTRY_UDFPS_REFACTOR)
        underTest.show()
    }

    @Test
    fun canShowAlternateBouncerForFingerprint_givenCanShow() {
        givenCanShowAlternateBouncer()
+84 −0
Original line number Diff line number Diff line
@@ -21,16 +21,27 @@ import com.android.systemui.biometrics.data.repository.FingerprintPropertyReposi
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
import com.android.systemui.deviceentry.shared.DeviceEntryUdfpsRefactor
import com.android.systemui.keyguard.data.repository.BiometricSettingsRepository
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.time.SystemClock
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn

@@ -46,6 +57,9 @@ constructor(
    private val biometricSettingsRepository: BiometricSettingsRepository,
    private val systemClock: SystemClock,
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    private val deviceEntryFingerprintAuthInteractor: Lazy<DeviceEntryFingerprintAuthInteractor>,
    private val keyguardInteractor: Lazy<KeyguardInteractor>,
    keyguardTransitionInteractor: Lazy<KeyguardTransitionInteractor>,
    @Application scope: CoroutineScope,
) {
    var receivedDownTouch = false
@@ -63,13 +77,80 @@ constructor(
        } else {
            bouncerRepository.alternateBouncerUIAvailable
        }
    private val isDozingOrAod: Flow<Boolean> =
        keyguardTransitionInteractor
            .get()
            .transitions
            .map {
                it.to == KeyguardState.DOZING ||
                    it.to == KeyguardState.AOD ||
                    ((it.from == KeyguardState.DOZING || it.from == KeyguardState.AOD) &&
                        it.transitionState != TransitionState.FINISHED)
            }
            .distinctUntilChanged()

    /**
     * Whether the current biometric, bouncer, and keyguard states allow the alternate bouncer to
     * show.
     */
    val canShowAlternateBouncer: StateFlow<Boolean> =
        alternateBouncerSupported
            .flatMapLatest { alternateBouncerSupported ->
                if (alternateBouncerSupported) {
                    keyguardTransitionInteractor.get().currentKeyguardState.flatMapLatest {
                        currentKeyguardState ->
                        if (currentKeyguardState == KeyguardState.GONE) {
                            flowOf(false)
                        } else {
                            combine(
                                deviceEntryFingerprintAuthInteractor
                                    .get()
                                    .isFingerprintAuthCurrentlyAllowed,
                                keyguardInteractor.get().isKeyguardDismissible,
                                bouncerRepository.primaryBouncerShow,
                                isDozingOrAod
                            ) {
                                fingerprintAllowed,
                                keyguardDismissible,
                                primaryBouncerShowing,
                                dozing ->
                                fingerprintAllowed &&
                                    !keyguardDismissible &&
                                    !primaryBouncerShowing &&
                                    !dozing
                            }
                        }
                    }
                } else {
                    flowOf(false)
                }
            }
            .stateIn(
                scope = scope,
                started = WhileSubscribed(),
                initialValue = false,
            )

    /**
     * Always shows the alternate bouncer. Requesters must check [canShowAlternateBouncer]` before
     * calling this.
     */
    fun forceShow() {
        if (DeviceEntryUdfpsRefactor.isUnexpectedlyInLegacyMode()) {
            show()
            return
        }
        bouncerRepository.setAlternateVisible(true)
    }

    /**
     * Sets the correct bouncer states to show the alternate bouncer if it can show.
     *
     * @return whether alternateBouncer is visible
     * @deprecated use [forceShow] and manually check [canShowAlternateBouncer] beforehand
     */
    fun show(): Boolean {
        DeviceEntryUdfpsRefactor.assertInLegacyMode()
        bouncerRepository.setAlternateVisible(canShowAlternateBouncerForFingerprint())
        return isVisibleState()
    }
@@ -105,6 +186,9 @@ constructor(
    }

    fun canShowAlternateBouncerForFingerprint(): Boolean {
        if (DeviceEntryUdfpsRefactor.isEnabled) {
            return canShowAlternateBouncer.value
        }
        return alternateBouncerSupported.value &&
            biometricSettingsRepository.isFingerprintAuthCurrentlyAllowed.value &&
            !keyguardUpdateMonitor.isFingerprintLockedOut &&
+31 −1
Original line number Diff line number Diff line
@@ -169,6 +169,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb

    private Job mListenForAlternateBouncerTransitionSteps = null;
    private Job mListenForKeyguardAuthenticatedBiometricsHandled = null;
    private Job mListenForCanShowAlternateBouncer = null;

    // Local cache of expansion events, to avoid duplicates
    private float mFraction = -1f;
@@ -506,6 +507,10 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
            mListenForKeyguardAuthenticatedBiometricsHandled.cancel(null);
        }
        mListenForKeyguardAuthenticatedBiometricsHandled = null;
        if (mListenForCanShowAlternateBouncer != null) {
            mListenForCanShowAlternateBouncer.cancel(null);
        }
        mListenForCanShowAlternateBouncer = null;
        if (!DeviceEntryUdfpsRefactor.isEnabled()) {
            mListenForAlternateBouncerTransitionSteps = mJavaAdapter.alwaysCollectFlow(
                    mKeyguardTransitionInteractor.transitionStepsFromState(
@@ -517,6 +522,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
                    mPrimaryBouncerInteractor.getKeyguardAuthenticatedBiometricsHandled(),
                    this::consumeKeyguardAuthenticatedBiometricsHandled
            );
        } else {
            mListenForCanShowAlternateBouncer = mJavaAdapter.alwaysCollectFlow(
                    mAlternateBouncerInteractor.getCanShowAlternateBouncer(),
                    this::consumeCanShowAlternateBouncer
            );
        }

        if (KeyguardWmStateRefactor.isEnabled()) {
@@ -558,6 +568,11 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
        }
    }

    private void consumeCanShowAlternateBouncer(boolean canShow) {
        // do nothing, we only are registering for the flow to ensure that there's at least
        // one subscriber that will update AlternateBouncerInteractor.canShowAlternateBouncer.value
    }

    /** Register a callback, to be invoked by the Predictive Back system. */
    private void registerBackCallback() {
        if (!mIsBackCallbackRegistered) {
@@ -723,6 +738,16 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
     *                 {@see KeyguardBouncer#show(boolean, boolean)}
     */
    public void showBouncer(boolean scrimmed) {
        if (DeviceEntryUdfpsRefactor.isEnabled()) {
            if (mAlternateBouncerInteractor.canShowAlternateBouncerForFingerprint()) {
                mAlternateBouncerInteractor.forceShow();
                updateAlternateBouncerShowing(mAlternateBouncerInteractor.isVisibleState());
            } else {
                showPrimaryBouncer(scrimmed);
            }
            return;
        }

        if (!mAlternateBouncerInteractor.show()) {
            showPrimaryBouncer(scrimmed);
        } else {
@@ -834,7 +859,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
                        mKeyguardGoneCancelAction = null;
                    }

                    if (DeviceEntryUdfpsRefactor.isEnabled()) {
                        mAlternateBouncerInteractor.forceShow();
                        updateAlternateBouncerShowing(mAlternateBouncerInteractor.isVisibleState());
                    } else {
                        updateAlternateBouncerShowing(mAlternateBouncerInteractor.show());
                    }
                    setKeyguardMessage(message, null, null);
                    return;
                }
+6 −0
Original line number Diff line number Diff line
@@ -58,6 +58,7 @@ import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.ui.BouncerView
import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFaceAuthInteractor
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryFingerprintAuthInteractor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryFingerprintAuthInteractor
import com.android.systemui.display.data.repository.FakeDisplayRepository
import com.android.systemui.keyguard.DismissCallbackRegistry
@@ -66,6 +67,8 @@ import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFingerprintA
import com.android.systemui.keyguard.data.repository.FakeTrustRepository
import com.android.systemui.keyguard.data.repository.biometricSettingsRepository
import com.android.systemui.keyguard.domain.interactor.DeviceEntrySideFpsOverlayInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.ui.viewmodel.SideFpsProgressBarViewModel
@@ -193,6 +196,9 @@ class SideFpsOverlayViewBinderTest : SysuiTestCase() {
                biometricSettingsRepository,
                FakeSystemClock(),
                keyguardUpdateMonitor,
                { mock(DeviceEntryFingerprintAuthInteractor::class.java) },
                { mock(KeyguardInteractor::class.java) },
                { mock(KeyguardTransitionInteractor::class.java) },
                testScope.backgroundScope,
            )

Loading