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

Commit 94eea04e authored by Josh Tsuji's avatar Josh Tsuji
Browse files

Add WakeDirectlyToGoneInteractor.

This centralizes all of the logic used to determine whether we can go back to GONE, even if auth would normally be required, including:
- Waking before the lock timeout, after a screen timeout
- Waking before the lock timeout, when 'power button locks instantly' is disabled
- Wake and unlock
- Keyguard service is disabled
- Lockscreen is disabled via adb or by tests

Bug: 278086361
Test: atest KeyguardWakeDirectlyToGoneInteractorTest
Test: manual with various screen timeout/power button locks instantly settings
Flag: EXEMPT bugfix
Change-Id: I55a2f0518eb72469d41c41339ed6f4e5ef033f5c
parent c7aa0be4
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -81,6 +81,7 @@ import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.domain.interactor.KeyguardEnabledInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardWakeDirectlyToGoneInteractor;
import com.android.systemui.keyguard.ui.binder.KeyguardSurfaceBehindParamsApplier;
import com.android.systemui.keyguard.ui.binder.KeyguardSurfaceBehindViewBinder;
import com.android.systemui.keyguard.ui.binder.WindowManagerLockscreenVisibilityViewBinder;
@@ -317,7 +318,7 @@ public class KeyguardService extends Service {

    private final WindowManagerOcclusionManager mWmOcclusionManager;
    private final KeyguardEnabledInteractor mKeyguardEnabledInteractor;

    private final KeyguardWakeDirectlyToGoneInteractor mKeyguardWakeDirectlyToGoneInteractor;
    private final Lazy<FoldGracePeriodProvider> mFoldGracePeriodProvider = new Lazy<>() {
        @Override
        public FoldGracePeriodProvider get() {
@@ -344,7 +345,8 @@ public class KeyguardService extends Service {
            @Main Executor mainExecutor,
            KeyguardInteractor keyguardInteractor,
            KeyguardEnabledInteractor keyguardEnabledInteractor,
            Lazy<KeyguardStateCallbackStartable> keyguardStateCallbackStartableLazy) {
            Lazy<KeyguardStateCallbackStartable> keyguardStateCallbackStartableLazy,
            KeyguardWakeDirectlyToGoneInteractor keyguardWakeDirectlyToGoneInteractor) {
        super();
        mKeyguardViewMediator = keyguardViewMediator;
        mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher;
@@ -372,6 +374,7 @@ public class KeyguardService extends Service {

        mWmOcclusionManager = windowManagerOcclusionManager;
        mKeyguardEnabledInteractor = keyguardEnabledInteractor;
        mKeyguardWakeDirectlyToGoneInteractor = keyguardWakeDirectlyToGoneInteractor;
    }

    @Override
@@ -486,6 +489,7 @@ public class KeyguardService extends Service {
        public void onDreamingStarted() {
            trace("onDreamingStarted");
            checkPermission();
            mKeyguardWakeDirectlyToGoneInteractor.onDreamingStarted();
            mKeyguardInteractor.setDreaming(true);
            mKeyguardViewMediator.onDreamingStarted();
        }
@@ -494,6 +498,7 @@ public class KeyguardService extends Service {
        public void onDreamingStopped() {
            trace("onDreamingStopped");
            checkPermission();
            mKeyguardWakeDirectlyToGoneInteractor.onDreamingStopped();
            mKeyguardInteractor.setDreaming(false);
            mKeyguardViewMediator.onDreamingStopped();
        }
+31 −0
Original line number Diff line number Diff line
@@ -127,6 +127,30 @@ interface KeyguardRepository {
     */
    val isKeyguardEnabled: StateFlow<Boolean>

    /**
     * Whether we can transition directly back to GONE from AOD/DOZING without any authentication
     * events (such as a fingerprint wake and unlock), even though authentication would normally be
     * required. This means that if you tap the screen or press the power button, you'll return
     * directly to the unlocked app content without seeing the lockscreen, even if a secure
     * authentication method (PIN/password/biometrics) is set.
     *
     * This is true in these cases:
     * - The screen timed out, but the "lock after screen timeout" duration (default 5 seconds) has
     *   not yet elapsed.
     * - The power button was pressed, but "power button instantly locks" is not enabled, and the
     *   "lock after screen timeout" duration has not elapsed.
     *
     * Note that this value specifically tells us if we can *ignore* authentication that would
     * otherwise be required to transition from AOD/DOZING -> GONE. AOD/DOZING -> GONE is also
     * possible if keyguard is disabled, either from an app request or because security is set to
     * "none", but in that case, auth is not required so this boolean is not relevant.
     *
     * See [KeyguardWakeToGoneInteractor].
     */
    val canIgnoreAuthAndReturnToGone: StateFlow<Boolean>

    fun setCanIgnoreAuthAndReturnToGone(canWake: Boolean)

    /** Is the always-on display available to be used? */
    val isAodAvailable: StateFlow<Boolean>

@@ -386,6 +410,13 @@ constructor(
        MutableStateFlow(!lockPatternUtils.isLockScreenDisabled(userTracker.userId))
    override val isKeyguardEnabled: StateFlow<Boolean> = _isKeyguardEnabled.asStateFlow()

    private val _canIgnoreAuthAndReturnToGone = MutableStateFlow(false)
    override val canIgnoreAuthAndReturnToGone = _canIgnoreAuthAndReturnToGone.asStateFlow()

    override fun setCanIgnoreAuthAndReturnToGone(canWakeToGone: Boolean) {
        _canIgnoreAuthAndReturnToGone.value = canWakeToGone
    }

    private val _isDozing = MutableStateFlow(statusBarStateController.isDozing)
    override val isDozing: StateFlow<Boolean> = _isDozing.asStateFlow()

+4 −2
Original line number Diff line number Diff line
@@ -53,6 +53,7 @@ constructor(
    powerInteractor: PowerInteractor,
    keyguardOcclusionInteractor: KeyguardOcclusionInteractor,
    val deviceEntryRepository: DeviceEntryRepository,
    private val wakeToGoneInteractor: KeyguardWakeDirectlyToGoneInteractor,
) :
    TransitionInteractor(
        fromState = KeyguardState.AOD,
@@ -98,6 +99,7 @@ constructor(
                    keyguardInteractor.primaryBouncerShowing,
                    keyguardInteractor.isKeyguardOccluded,
                    canDismissLockscreen,
                    wakeToGoneInteractor.canWakeDirectlyToGone,
                )
                .collect {
                    (
@@ -107,6 +109,7 @@ constructor(
                        primaryBouncerShowing,
                        isKeyguardOccludedLegacy,
                        canDismissLockscreen,
                        canWakeDirectlyToGone,
                    ) ->
                    if (!maybeHandleInsecurePowerGesture()) {
                        val shouldTransitionToLockscreen =
@@ -131,8 +134,7 @@ constructor(

                        val shouldTransitionToGone =
                            (!KeyguardWmStateRefactor.isEnabled && canDismissLockscreen) ||
                                (KeyguardWmStateRefactor.isEnabled &&
                                    !deviceEntryRepository.isLockscreenEnabled())
                                (KeyguardWmStateRefactor.isEnabled && canWakeDirectlyToGone)

                        if (shouldTransitionToGone) {
                            startTransitionTo(
+4 −16
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ constructor(
    private val communalInteractor: CommunalInteractor,
    keyguardOcclusionInteractor: KeyguardOcclusionInteractor,
    val deviceEntryRepository: DeviceEntryRepository,
    private val wakeToGoneInteractor: KeyguardWakeDirectlyToGoneInteractor,
) :
    TransitionInteractor(
        fromState = KeyguardState.DOZING,
@@ -181,7 +182,7 @@ constructor(
                .sample(
                    communalInteractor.isIdleOnCommunal,
                    keyguardInteractor.biometricUnlockState,
                    canTransitionToGoneOnWake,
                    wakeToGoneInteractor.canWakeDirectlyToGone,
                    keyguardInteractor.primaryBouncerShowing,
                )
                .collect {
@@ -189,27 +190,14 @@ constructor(
                        _,
                        isIdleOnCommunal,
                        biometricUnlockState,
                        canDismissLockscreen,
                        canWakeDirectlyToGone,
                        primaryBouncerShowing) ->
                    if (
                        !maybeStartTransitionToOccludedOrInsecureCamera() &&
                            // Handled by dismissFromDozing().
                            !isWakeAndUnlock(biometricUnlockState.mode)
                    ) {
                        if (!KeyguardWmStateRefactor.isEnabled && canDismissLockscreen) {
                            if (SceneContainerFlag.isEnabled) {
                                // TODO(b/336576536): Check if adaptation for scene framework is
                                // needed
                            } else {
                                startTransitionTo(
                                    KeyguardState.GONE,
                                    ownerReason = "waking from dozing"
                                )
                            }
                        } else if (
                            KeyguardWmStateRefactor.isEnabled &&
                                !deviceEntryRepository.isLockscreenEnabled()
                        ) {
                        if (canWakeDirectlyToGone) {
                            if (SceneContainerFlag.isEnabled) {
                                // TODO(b/336576536): Check if adaptation for scene framework is
                                // needed
+33 −18
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import com.android.systemui.Flags.communalHub
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.keyguard.KeyguardWmStateRefactor
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
@@ -37,11 +38,14 @@ import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch

@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class FromDreamingTransitionInteractor
@Inject
@@ -56,6 +60,7 @@ constructor(
    private val glanceableHubTransitions: GlanceableHubTransitions,
    powerInteractor: PowerInteractor,
    keyguardOcclusionInteractor: KeyguardOcclusionInteractor,
    private val deviceEntryInteractor: DeviceEntryInteractor,
) :
    TransitionInteractor(
        fromState = KeyguardState.DREAMING,
@@ -72,7 +77,7 @@ constructor(
        listenForDreamingToOccluded()
        listenForDreamingToGoneWhenDismissable()
        listenForDreamingToGoneFromBiometricUnlock()
        listenForDreamingToLockscreen()
        listenForDreamingToLockscreenOrGone()
        listenForDreamingToAodOrDozing()
        listenForTransitionToCamera(scope, keyguardInteractor)
        listenForDreamingToGlanceableHub()
@@ -132,17 +137,7 @@ constructor(

    @OptIn(FlowPreview::class)
    private fun listenForDreamingToOccluded() {
        if (KeyguardWmStateRefactor.isEnabled) {
            scope.launch {
                combine(
                        keyguardInteractor.isDreaming,
                        keyguardOcclusionInteractor.isShowWhenLockedActivityOnTop,
                        ::Pair
                    )
                    .filterRelevantKeyguardStateAnd { (isDreaming, _) -> !isDreaming }
                    .collect { maybeStartTransitionToOccludedOrInsecureCamera() }
            }
        } else {
        if (!KeyguardWmStateRefactor.isEnabled) {
            scope.launch {
                combine(
                        keyguardInteractor.isKeyguardOccluded,
@@ -168,21 +163,41 @@ constructor(
        }
    }

    private fun listenForDreamingToLockscreen() {
    private fun listenForDreamingToLockscreenOrGone() {
        if (!KeyguardWmStateRefactor.isEnabled) {
            return
        }

        scope.launch {
            keyguardOcclusionInteractor.isShowWhenLockedActivityOnTop
                .filterRelevantKeyguardStateAnd { onTop -> !onTop }
                .collect { startTransitionTo(KeyguardState.LOCKSCREEN) }
            keyguardInteractor.isDreaming
                .filter { !it }
                .sample(deviceEntryInteractor.isUnlocked, ::Pair)
                .collect { (_, dismissable) ->
                    // TODO(b/349837588): Add check for -> OCCLUDED.
                    if (dismissable) {
                        startTransitionTo(
                            KeyguardState.GONE,
                            ownerReason = "No longer dreaming; dismissable"
                        )
                    } else {
                        startTransitionTo(
                            KeyguardState.LOCKSCREEN,
                            ownerReason = "No longer dreaming"
                        )
                    }
                }
        }
    }

    private fun listenForDreamingToGoneWhenDismissable() {
        // TODO(b/336576536): Check if adaptation for scene framework is needed
        if (SceneContainerFlag.isEnabled) return
        if (SceneContainerFlag.isEnabled) {
            return // TODO(b/336576536): Check if adaptation for scene framework is needed
        }

        if (KeyguardWmStateRefactor.isEnabled) {
            return
        }

        scope.launch {
            keyguardInteractor.isAbleToDream
                .sampleCombine(
Loading