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

Commit 43ba03fd authored by Alejandro Nijamkin's avatar Alejandro Nijamkin
Browse files

[flexiglass] isDeviceEntered also checks back stack

isDeviceEntered should always reflect whether the user has "passed the
lockscreen". Up until this point, this has only happened if the user
visited the Gone scene. This CL changes that for cases when the
lockscreen is "passed" by the user but without yet visiting the Gone
scene.

For example, in the case of
unlocking while looking at the Shade scene (when clicking a notification
that requires unlocking to continue).

In cases like the one above, the current scene is Bouncer and the
back stack is (top to bottom): [Shade, Lockscreen].

This CL contains two main changes:
1. Replace the Lockscreen at the bottom of the back stack with Gone,
   when unlocking in this case
2. Make DeviceEntryInteractor.isDeviceEntered watch the bottom of the
   back stack for a Lockscreen -> Gone swap in addition to the classic
   visiting of the Gone or Lockscreen scenes as it did before

Bug: 359530769
Test: unit test added for the new case
Test: existing unit and integration tests modified to better model
what's going on and make them pass
Test: manually verified no harm done (a) normal unlock with pattern
bouncer + re-lock + visiting all scenes in both locked and unlocked
states (b) locked -> shade -> notification click -> unlock via alternate
bouncer / fingerprint (c) locked -> shade -> notification click ->
dismiss alternate bouncer -> bouncer -> unlock via bouncer (d) double
tap power to bring up camera app while locked -> click on gallery button
-> unlock via alternate bouncer / primary bouncer
Flag: com.android.systemui.scene_container

Change-Id: I9e8b6a34afd574352d01f25819b71e1702af3d15
parent 79e3576e
Loading
Loading
Loading
Loading
+40 −1
Original line number Original line Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.systemui.deviceentry.domain.interactor
import android.testing.TestableLooper
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
@@ -42,11 +43,16 @@ import com.android.systemui.keyguard.data.repository.fakeTrustRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.scene.domain.interactor.sceneBackInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.sysuiStatusBarStateController
import com.android.systemui.testKosmos
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Before
@@ -66,10 +72,14 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
    private val trustRepository by lazy { kosmos.fakeTrustRepository }
    private val trustRepository by lazy { kosmos.fakeTrustRepository }
    private val sceneInteractor by lazy { kosmos.sceneInteractor }
    private val sceneInteractor by lazy { kosmos.sceneInteractor }
    private val authenticationInteractor by lazy { kosmos.authenticationInteractor }
    private val authenticationInteractor by lazy { kosmos.authenticationInteractor }
    private val sceneBackInteractor by lazy { kosmos.sceneBackInteractor }
    private val sceneContainerStartable by lazy { kosmos.sceneContainerStartable }
    private val sysuiStatusBarStateController by lazy { kosmos.sysuiStatusBarStateController }
    private lateinit var underTest: DeviceEntryInteractor
    private lateinit var underTest: DeviceEntryInteractor


    @Before
    @Before
    fun setUp() {
    fun setUp() {
        sceneContainerStartable.start()
        underTest = kosmos.deviceEntryInteractor
        underTest = kosmos.deviceEntryInteractor
    }
    }


@@ -423,8 +433,37 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
            assertThat(isUnlocked).isTrue()
            assertThat(isUnlocked).isTrue()
        }
        }


    private fun switchToScene(sceneKey: SceneKey) {
    @Test
    fun isDeviceEntered_unlockedWhileOnShade_emitsTrue() =
        testScope.runTest {
            val isDeviceEntered by collectLastValue(underTest.isDeviceEntered)
            assertThat(isDeviceEntered).isFalse()
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)

            // Navigate to shade and bouncer:
            switchToScene(Scenes.Shade)
            assertThat(currentScene).isEqualTo(Scenes.Shade)
            // Simulating a "leave it open when the keyguard is hidden" which means the bouncer will
            // be
            // shown and successful authentication should take the user back to where they are, the
            // shade scene.
            sysuiStatusBarStateController.setLeaveOpenOnKeyguardHide(true)
            switchToScene(Scenes.Bouncer)
            assertThat(currentScene).isEqualTo(Scenes.Bouncer)

            assertThat(isDeviceEntered).isFalse()
            // Authenticate with PIN to unlock and dismiss the lockscreen:
            authenticationInteractor.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
            runCurrent()

            assertThat(isDeviceEntered).isTrue()
        }

    private fun TestScope.switchToScene(sceneKey: SceneKey) {
        sceneInteractor.changeScene(sceneKey, "reason")
        sceneInteractor.changeScene(sceneKey, "reason")
        sceneInteractor.setTransitionState(flowOf(ObservableTransitionState.Idle(sceneKey)))
        runCurrent()
    }
    }


    private suspend fun givenCanShowAlternateBouncer() {
    private suspend fun givenCanShowAlternateBouncer() {
+19 −30
Original line number Original line Diff line number Diff line
@@ -161,9 +161,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
            val upDestinationSceneKey =
            val upDestinationSceneKey =
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
            kosmos.emulateUserDrivenTransition(
            kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
                to = upDestinationSceneKey,
            )


            kosmos.fakeSceneDataSource.pause()
            kosmos.fakeSceneDataSource.pause()
            kosmos.enterPin()
            kosmos.enterPin()
@@ -226,16 +224,14 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
            assertThat(upDestinationSceneKey).isEqualTo(SceneFamilies.Home)
            assertThat(upDestinationSceneKey).isEqualTo(SceneFamilies.Home)
            assertThat(homeScene).isEqualTo(Scenes.Gone)
            assertThat(homeScene).isEqualTo(Scenes.Gone)
            kosmos.emulateUserDrivenTransition(
            kosmos.emulateUserDrivenTransition(to = homeScene)
                to = homeScene,
            )
        }
        }


    @Test
    @Test
    fun withAuthMethodNone_deviceWakeUp_skipsLockscreen() =
    fun withAuthMethodNone_deviceWakeUp_skipsLockscreen() =
        testScope.runTest {
        testScope.runTest {
            kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = false)
            kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = false)
            kosmos.putDeviceToSleep(instantlyLockDevice = false)
            kosmos.putDeviceToSleep()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
            kosmos.assertCurrentScene(Scenes.Lockscreen)


            kosmos.wakeUpDevice()
            kosmos.wakeUpDevice()
@@ -246,7 +242,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
    fun withAuthMethodSwipe_deviceWakeUp_doesNotSkipLockscreen() =
    fun withAuthMethodSwipe_deviceWakeUp_doesNotSkipLockscreen() =
        testScope.runTest {
        testScope.runTest {
            kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
            kosmos.setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
            kosmos.putDeviceToSleep(instantlyLockDevice = false)
            kosmos.putDeviceToSleep()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
            kosmos.assertCurrentScene(Scenes.Lockscreen)


            kosmos.wakeUpDevice()
            kosmos.wakeUpDevice()
@@ -302,7 +298,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
        testScope.runTest {
        testScope.runTest {
            kosmos.unlockDevice()
            kosmos.unlockDevice()
            kosmos.assertCurrentScene(Scenes.Gone)
            kosmos.assertCurrentScene(Scenes.Gone)
            kosmos.putDeviceToSleep(instantlyLockDevice = false)
            kosmos.putDeviceToSleep()
            kosmos.assertCurrentScene(Scenes.Lockscreen)
            kosmos.assertCurrentScene(Scenes.Lockscreen)


            // Pretend like the timeout elapsed and now lock the device.
            // Pretend like the timeout elapsed and now lock the device.
@@ -318,9 +314,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
            val upDestinationSceneKey =
            val upDestinationSceneKey =
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
                (actions?.get(Swipe.Up) as? UserActionResult.ChangeScene)?.toScene
            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Bouncer)
            kosmos.emulateUserDrivenTransition(
            kosmos.emulateUserDrivenTransition(to = upDestinationSceneKey)
                to = upDestinationSceneKey,
            )


            kosmos.fakeSceneDataSource.pause()
            kosmos.fakeSceneDataSource.pause()
            kosmos.dismissIme()
            kosmos.dismissIme()
@@ -388,7 +382,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
            kosmos.emulatePendingTransitionProgress(expectedVisible = true)
            kosmos.emulatePendingTransitionProgress(expectedVisible = true)
            kosmos.enterSimPin(
            kosmos.enterSimPin(
                authMethodAfterSimUnlock = AuthenticationMethodModel.None,
                authMethodAfterSimUnlock = AuthenticationMethodModel.None,
                enableLockscreen = false
                enableLockscreen = false,
            )
            )


            kosmos.assertCurrentScene(Scenes.Gone)
            kosmos.assertCurrentScene(Scenes.Gone)
@@ -434,7 +428,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
    /** Updates the current authentication method and related states in the data layer. */
    /** Updates the current authentication method and related states in the data layer. */
    private fun Kosmos.setAuthMethod(
    private fun Kosmos.setAuthMethod(
        authMethod: AuthenticationMethodModel,
        authMethod: AuthenticationMethodModel,
        enableLockscreen: Boolean = true
        enableLockscreen: Boolean = true,
    ) {
    ) {
        if (authMethod.isSecure) {
        if (authMethod.isSecure) {
            assert(enableLockscreen) {
            assert(enableLockscreen) {
@@ -538,24 +532,27 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
        kosmos.fakeSceneDataSource.pause()
        kosmos.fakeSceneDataSource.pause()
        sceneInteractor.changeScene(to, "reason")
        sceneInteractor.changeScene(to, "reason")


        emulatePendingTransitionProgress(
        emulatePendingTransitionProgress(expectedVisible = to != Scenes.Gone)
            expectedVisible = to != Scenes.Gone,
        )
    }
    }


    /**
    /**
     * Locks the device immediately (without delay).
     * Locks the device.
     *
     *
     * Asserts the device to be lockable (e.g. that the current authentication is secure).
     * Asserts the device to be lockable (e.g. that the current authentication is secure).
     *
     *
     * Not to be confused with [putDeviceToSleep], which may also instantly lock the device.
     * Internally emulates a power button press that puts the device to sleep, followed by another
     * power button press that wakes up the device but is then expected to be in the locked state.
     */
     */
    private suspend fun Kosmos.lockDevice() {
    private suspend fun Kosmos.lockDevice() {
        val authMethod = authenticationInteractor.getAuthenticationMethod()
        val authMethod = authenticationInteractor.getAuthenticationMethod()
        assertWithMessage("The authentication method of $authMethod is not secure, cannot lock!")
        assertWithMessage("The authentication method of $authMethod is not secure, cannot lock!")
            .that(authMethod.isSecure)
            .that(authMethod.isSecure)
            .isTrue()
            .isTrue()
        sceneInteractor.changeScene(Scenes.Lockscreen, "")

        powerInteractor.setAsleepForTest()
        testScope.runCurrent()

        powerInteractor.setAwakeForTest()
        testScope.runCurrent()
        testScope.runCurrent()
    }
    }


@@ -569,9 +566,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
        fakeSceneDataSource.pause()
        fakeSceneDataSource.pause()
        enterPin()
        enterPin()


        emulatePendingTransitionProgress(
        emulatePendingTransitionProgress(expectedVisible = false)
            expectedVisible = false,
        )
    }
    }


    /**
    /**
@@ -645,9 +640,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
    }
    }


    /** Changes device wakefulness state from awake to asleep, going through intermediary states. */
    /** Changes device wakefulness state from awake to asleep, going through intermediary states. */
    private suspend fun Kosmos.putDeviceToSleep(
    private suspend fun Kosmos.putDeviceToSleep() {
        instantlyLockDevice: Boolean = true,
    ) {
        val wakefulnessModel = powerInteractor.detailedWakefulness.value
        val wakefulnessModel = powerInteractor.detailedWakefulness.value
        assertWithMessage("Cannot put device to sleep as it's already asleep!")
        assertWithMessage("Cannot put device to sleep as it's already asleep!")
            .that(wakefulnessModel.isAwake())
            .that(wakefulnessModel.isAwake())
@@ -655,10 +648,6 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {


        powerInteractor.setAsleepForTest()
        powerInteractor.setAsleepForTest()
        testScope.runCurrent()
        testScope.runCurrent()

        if (instantlyLockDevice) {
            lockDevice()
        }
    }
    }


    /** Emulates the dismissal of the IME (soft keyboard). */
    /** Emulates the dismissal of the IME (soft keyboard). */
+22 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,8 @@ import com.android.systemui.authentication.domain.interactor.authenticationInter
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.kosmos.testScope
import com.android.systemui.kosmos.testScope
import com.android.systemui.scene.data.model.asIterable
import com.android.systemui.scene.data.model.sceneStackOf
import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.testKosmos
import com.android.systemui.testKosmos
@@ -173,12 +175,32 @@ class SceneBackInteractorTest : SysuiTestCase() {
            )
            )
        }
        }


    @Test
    @EnableSceneContainer
    fun updateBackStack() =
        testScope.runTest {
            underTest.onSceneChange(from = Scenes.Lockscreen, to = Scenes.Shade)
            underTest.onSceneChange(from = Scenes.Shade, to = Scenes.QuickSettings)
            underTest.onSceneChange(from = Scenes.QuickSettings, to = Scenes.Bouncer)
            assertThat(underTest.backStack.value.asIterable().toList())
                .isEqualTo(listOf(Scenes.QuickSettings, Scenes.Shade, Scenes.Lockscreen))

            underTest.updateBackStack { stack ->
                // Reverse the stack, just to see if it can be done:
                sceneStackOf(*stack.asIterable().reversed().toTypedArray())
            }

            assertThat(underTest.backStack.value.asIterable().toList())
                .isEqualTo(listOf(Scenes.Lockscreen, Scenes.Shade, Scenes.QuickSettings))
        }

    private suspend fun TestScope.assertRoute(vararg route: RouteNode) {
    private suspend fun TestScope.assertRoute(vararg route: RouteNode) {
        val currentScene by collectLastValue(sceneInteractor.currentScene)
        val currentScene by collectLastValue(sceneInteractor.currentScene)
        val backScene by collectLastValue(underTest.backScene)
        val backScene by collectLastValue(underTest.backScene)


        route.forEachIndexed { index, node ->
        route.forEachIndexed { index, node ->
            sceneInteractor.changeScene(node.changeSceneTo, "")
            sceneInteractor.changeScene(node.changeSceneTo, "")
            runCurrent()
            assertWithMessage("node at index $index currentScene mismatch")
            assertWithMessage("node at index $index currentScene mismatch")
                .that(currentScene)
                .that(currentScene)
                .isEqualTo(node.changeSceneTo)
                .isEqualTo(node.changeSceneTo)
+77 −107

File changed.

Preview size limit exceeded, changes collapsed.

+41 −17
Original line number Original line Diff line number Diff line
@@ -24,8 +24,11 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.scene.data.model.asIterable
import com.android.systemui.scene.domain.interactor.SceneBackInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.utils.coroutines.flow.mapLatestConflated
import com.android.systemui.utils.coroutines.flow.mapLatestConflated
import javax.inject.Inject
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineScope
@@ -34,6 +37,7 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.map
@@ -59,6 +63,7 @@ constructor(
    private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
    private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
    private val alternateBouncerInteractor: AlternateBouncerInteractor,
    private val alternateBouncerInteractor: AlternateBouncerInteractor,
    private val dismissCallbackRegistry: DismissCallbackRegistry,
    private val dismissCallbackRegistry: DismissCallbackRegistry,
    sceneBackInteractor: SceneBackInteractor,
) {
) {
    /**
    /**
     * Whether the device is unlocked.
     * Whether the device is unlocked.
@@ -86,19 +91,40 @@ constructor(
     * Note: This does not imply that the lockscreen is visible or not.
     * Note: This does not imply that the lockscreen is visible or not.
     */
     */
    val isDeviceEntered: StateFlow<Boolean> =
    val isDeviceEntered: StateFlow<Boolean> =
        combine(
                // This flow emits true when the currentScene switches to Gone for the first time
                // after having been on Lockscreen.
                sceneInteractor.currentScene
                sceneInteractor.currentScene
                    .filter { currentScene ->
                    .filter { currentScene ->
                        currentScene == Scenes.Gone || currentScene == Scenes.Lockscreen
                        currentScene == Scenes.Gone || currentScene == Scenes.Lockscreen
                    }
                    }
                    .mapLatestConflated { scene ->
                    .mapLatestConflated { scene ->
                        if (scene == Scenes.Gone) {
                        if (scene == Scenes.Gone) {
                    // Make sure device unlock status is definitely unlocked before we consider the
                            // Make sure device unlock status is definitely unlocked before we
                    // device "entered".
                            // consider the device "entered".
                            deviceUnlockedInteractor.deviceUnlockStatus.first { it.isUnlocked }
                            deviceUnlockedInteractor.deviceUnlockStatus.first { it.isUnlocked }
                            true
                            true
                        } else {
                        } else {
                            false
                            false
                        }
                        }
                    },
                // This flow emits true only if the bottom of the navigation back stack has been
                // switched from Lockscreen to Gone. In other words, only if the device was unlocked
                // while visiting at least one scene "above" the Lockscreen scene.
                sceneBackInteractor.backStack
                    // The bottom of the back stack, which is Lockscreen, Gone, or null if empty.
                    .map { it.asIterable().lastOrNull() }
                    // Filter out cases where the stack changes but the bottom remains unchanged.
                    .distinctUntilChanged()
                    // Detect changes of the bottom of the stack, start with null, so the first
                    // update emits a value and the logic doesn't need to wait for a second value
                    // before emitting something.
                    .pairwise(initialValue = null)
                    // Replacing a bottom of the stack that was Lockscreen with Gone constitutes a
                    // "device entered" event.
                    .map { (from, to) -> from == Scenes.Lockscreen && to == Scenes.Gone },
            ) { enteredDirectly, enteredOnBackStack ->
                enteredOnBackStack || enteredDirectly
            }
            }
            .stateIn(
            .stateIn(
                scope = applicationScope,
                scope = applicationScope,
@@ -129,7 +155,7 @@ constructor(
                },
                },
                isLockscreenEnabled,
                isLockscreenEnabled,
                deviceUnlockedInteractor.deviceUnlockStatus,
                deviceUnlockedInteractor.deviceUnlockStatus,
                isDeviceEntered
                isDeviceEntered,
            ) { isNoneAuthMethod, isLockscreenEnabled, deviceUnlockStatus, isDeviceEntered ->
            ) { isNoneAuthMethod, isLockscreenEnabled, deviceUnlockStatus, isDeviceEntered ->
                val isSwipeAuthMethod = isNoneAuthMethod && isLockscreenEnabled
                val isSwipeAuthMethod = isNoneAuthMethod && isLockscreenEnabled
                (isSwipeAuthMethod ||
                (isSwipeAuthMethod ||
@@ -155,9 +181,7 @@ constructor(
     *   canceled
     *   canceled
     */
     */
    @JvmOverloads
    @JvmOverloads
    fun attemptDeviceEntry(
    fun attemptDeviceEntry(callback: IKeyguardDismissCallback? = null) {
        callback: IKeyguardDismissCallback? = null,
    ) {
        callback?.let { dismissCallbackRegistry.addCallback(it) }
        callback?.let { dismissCallbackRegistry.addCallback(it) }


        // TODO (b/307768356),
        // TODO (b/307768356),
Loading