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

Commit 7c450c4a authored by Josh Tsuji's avatar Josh Tsuji
Browse files

Add KeyguardTransitionBootInteractor.

We previously always initialized with OFF -> LOCKSCREEN, however, there are various cases (including SUW) where this is not correct, and we should be in GONE. This uses the logic from KeyguardViewMediator#setupLocked to decide whether to start in LS or GONE.

Fixes: 327279527
Test: atest SystemUITests
Test: wipe device and confirm that we init in GONE; finish SUW/reboot/verify we're in LS
Flag: NA
Change-Id: I87d38a2db9c64b78ea677750ad83d9b6d0d14801
parent dc22ecf8
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -235,7 +235,13 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
                .isEqualTo(
                    listOf(
                        // The initial transition will also get sent when collect started
                        TransitionStep(OFF, LOCKSCREEN, 0f, STARTED),
                        TransitionStep(
                            OFF,
                            LOCKSCREEN,
                            0f,
                            STARTED,
                            ownerName = "KeyguardTransitionRepository(boot)"
                        ),
                        steps[0],
                        steps[3],
                        steps[6]
+9 −0
Original line number Diff line number Diff line
@@ -239,6 +239,15 @@ constructor(
            authenticationInteractor.getAuthenticationMethod().isSecure
    }

    /**
     * Whether the lockscreen is enabled for the current user. This is `true` whenever the user has
     * chosen any secure authentication method and even if they set the lockscreen to be dismissed
     * when the user swipes on it.
     */
    suspend fun isLockscreenEnabled(): Boolean {
        return repository.isLockscreenEnabled()
    }

    /**
     * Whether lockscreen bypass is enabled. When enabled, the lockscreen will be automatically
     * dismissed once the authentication challenge is completed. For example, completing a biometric
+39 −29
Original line number Diff line number Diff line
@@ -88,6 +88,12 @@ interface KeyguardTransitionRepository {
     */
    suspend fun startTransition(info: TransitionInfo): UUID?

    /**
     * Emits STARTED and FINISHED transition steps to the given state. This is used during boot to
     * seed the repository with the appropriate initial state.
     */
    suspend fun emitInitialStepsFromOff(to: KeyguardState)

    /**
     * Allows manual control of a transition. When calling [startTransition], the consumer must pass
     * in a null animator. In return, it will get a unique [UUID] that will be validated to allow
@@ -141,9 +147,17 @@ constructor(
    private var updateTransitionId: UUID? = null

    init {
        // Seed with transitions signaling a boot into lockscreen state. If updating this, please
        // also update FakeKeyguardTransitionRepository.
        initialTransitionSteps.forEach(::emitTransition)
        // Start with a FINISHED transition in OFF. KeyguardBootInteractor will transition from OFF
        // to either GONE or LOCKSCREEN once we're booted up and can determine which state we should
        // start in.
        emitTransition(
            TransitionStep(
                KeyguardState.OFF,
                KeyguardState.OFF,
                1f,
                TransitionState.FINISHED,
            )
        )
    }

    override suspend fun startTransition(info: TransitionInfo): UUID? {
@@ -251,6 +265,28 @@ constructor(
        lastStep = nextStep
    }

    override suspend fun emitInitialStepsFromOff(to: KeyguardState) {
        emitTransition(
            TransitionStep(
                KeyguardState.OFF,
                to,
                0f,
                TransitionState.STARTED,
                ownerName = "KeyguardTransitionRepository(boot)",
            )
        )

        emitTransition(
            TransitionStep(
                KeyguardState.OFF,
                to,
                1f,
                TransitionState.FINISHED,
                ownerName = "KeyguardTransitionRepository(boot)",
            ),
        )
    }

    private fun logAndTrace(step: TransitionStep, isManual: Boolean) {
        if (step.transitionState == TransitionState.RUNNING) {
            return
@@ -271,31 +307,5 @@ constructor(

    companion object {
        private const val TAG = "KeyguardTransitionRepository"

        /**
         * Transition steps to seed the repository with, so that all of the transition interactor
         * flows emit reasonable initial values.
         */
        val initialTransitionSteps: List<TransitionStep> =
            listOf(
                TransitionStep(
                    KeyguardState.OFF,
                    KeyguardState.OFF,
                    1f,
                    TransitionState.FINISHED,
                ),
                TransitionStep(
                    KeyguardState.OFF,
                    KeyguardState.LOCKSCREEN,
                    0f,
                    TransitionState.STARTED,
                ),
                TransitionStep(
                    KeyguardState.OFF,
                    KeyguardState.LOCKSCREEN,
                    1f,
                    TransitionState.FINISHED,
                ),
            )
    }
}
+5 −5
Original line number Diff line number Diff line
@@ -66,7 +66,7 @@ constructor(
        listenForTransitionToCamera(scope, keyguardInteractor)
    }

    private val canDismissLockScreen: Flow<Boolean> =
    private val canTransitionToGoneOnWake: Flow<Boolean> =
        combine(
            keyguardInteractor.isKeyguardShowing,
            keyguardInteractor.isKeyguardDismissible,
@@ -87,7 +87,7 @@ constructor(
                    keyguardInteractor.biometricUnlockState,
                    keyguardInteractor.isKeyguardOccluded,
                    communalInteractor.isIdleOnCommunal,
                    canDismissLockScreen,
                    canTransitionToGoneOnWake,
                    keyguardInteractor.primaryBouncerShowing,
                )
                .collect {
@@ -96,12 +96,12 @@ constructor(
                        biometricUnlockState,
                        occluded,
                        isIdleOnCommunal,
                        canDismissLockScreen,
                        canTransitionToGoneOnWake,
                        primaryBouncerShowing) ->
                    startTransitionTo(
                        if (isWakeAndUnlock(biometricUnlockState.mode)) {
                            KeyguardState.GONE
                        } else if (canDismissLockScreen) {
                        } else if (canTransitionToGoneOnWake) {
                            KeyguardState.GONE
                        } else if (primaryBouncerShowing) {
                            KeyguardState.PRIMARY_BOUNCER
@@ -129,7 +129,7 @@ constructor(
                .sample(
                    communalInteractor.isIdleOnCommunal,
                    keyguardInteractor.biometricUnlockState,
                    canDismissLockScreen,
                    canTransitionToGoneOnWake,
                    keyguardInteractor.primaryBouncerShowing,
                )
                .collect {
+81 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.keyguard.domain.interactor

import android.util.Log
import com.android.systemui.CoreStartable
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

/** Handles initialization of the KeyguardTransitionRepository on boot. */
@SysUISingleton
class KeyguardTransitionBootInteractor
@Inject
constructor(
    @Application val scope: CoroutineScope,
    val deviceEntryInteractor: DeviceEntryInteractor,
    val deviceProvisioningInteractor: DeviceProvisioningInteractor,
    val keyguardTransitionInteractor: KeyguardTransitionInteractor,
    val repository: KeyguardTransitionRepository,
) : CoreStartable {

    /**
     * Whether the lockscreen should be showing when the device starts up for the first time. If not
     * then we'll seed the repository with a transition from OFF -> GONE.
     */
    @OptIn(ExperimentalCoroutinesApi::class)
    private val showLockscreenOnBoot =
        deviceProvisioningInteractor.isDeviceProvisioned.map { provisioned ->
            (provisioned || deviceEntryInteractor.isAuthenticationRequired()) &&
                deviceEntryInteractor.isLockscreenEnabled()
        }

    override fun start() {
        scope.launch {
            val state =
                if (showLockscreenOnBoot.first()) {
                    KeyguardState.LOCKSCREEN
                } else {
                    KeyguardState.GONE
                }

            if (
                keyguardTransitionInteractor.currentTransitionInfoInternal.value.from !=
                    KeyguardState.OFF
            ) {
                Log.e(
                    "KeyguardTransitionInteractor",
                    "showLockscreenOnBoot emitted, but we've already " +
                        "transitioned to a state other than OFF. We'll respect that " +
                        "transition, but this should not happen."
                )
            } else {
                repository.emitInitialStepsFromOff(state)
            }
        }
    }
}
Loading