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

Commit 31986fe9 authored by Alejandro Nijamkin's avatar Alejandro Nijamkin
Browse files

[flexiglass] Adds support for "lock now" from KeyguardService

Bug: 378708150
Test: manually triggered the code path using "adb shell cmd
accessibility call-system-action 8" which triggers the call to
KeyguardService.doKeyguardTimeout and verified that it locks
immediately regardless of timeout
Test: added unit test case
Flag: com.android.systemui.scene_container

Change-Id: I782370024af222b24801fd23b03c89ba418f6a25
parent 18be59f9
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -568,6 +568,20 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() {
            assertThat(isUnlocked).isFalse()
        }

    @Test
    fun lockNow() =
        testScope.runTest {
            setLockAfterScreenTimeout(5000)
            val isUnlocked by collectLastValue(underTest.deviceUnlockStatus.map { it.isUnlocked })
            unlockDevice()
            assertThat(isUnlocked).isTrue()

            underTest.lockNow()
            runCurrent()

            assertThat(isUnlocked).isFalse()
        }

    private fun TestScope.unlockDevice() {
        val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus)

+13 −8
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.deviceentry.domain.interactor

import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.internal.policy.IKeyguardDismissCallback
import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
@@ -43,7 +44,6 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.stateIn
import com.android.app.tracing.coroutines.launchTraced as launch

/**
 * Hosts application business logic related to device entry.
@@ -173,6 +173,14 @@ constructor(
            )
    }

    /**
     * Whether lockscreen bypass is enabled. When enabled, the lockscreen will be automatically
     * dismissed once the authentication challenge is completed. For example, completing a biometric
     * authentication challenge via face unlock or fingerprint sensor can automatically bypass the
     * lockscreen.
     */
    val isBypassEnabled: StateFlow<Boolean> = repository.isBypassEnabled

    /**
     * Attempt to enter the device and dismiss the lockscreen. If authentication is required to
     * unlock the device it will transition to bouncer.
@@ -238,11 +246,8 @@ constructor(
        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
     * authentication challenge via face unlock or fingerprint sensor can automatically bypass the
     * lockscreen.
     */
    val isBypassEnabled: StateFlow<Boolean> = repository.isBypassEnabled
    /** Locks the device instantly. */
    fun lockNow() {
        deviceUnlockedInteractor.lockNow()
    }
}
+10 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
@@ -56,6 +57,7 @@ import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.receiveAsFlow
import kotlinx.coroutines.launch

@OptIn(ExperimentalCoroutinesApi::class)
@@ -177,6 +179,8 @@ constructor(
    val deviceUnlockStatus: StateFlow<DeviceUnlockStatus> =
        repository.deviceUnlockStatus.asStateFlow()

    private val lockNowRequests = Channel<Unit>()

    override suspend fun onActivated(): Nothing {
        authenticationInteractor.authenticationMethod.collectLatest { authMethod ->
            if (!authMethod.isSecure) {
@@ -195,6 +199,11 @@ constructor(
        awaitCancellation()
    }

    /** Locks the device instantly. */
    fun lockNow() {
        lockNowRequests.trySend(Unit)
    }

    private suspend fun handleLockAndUnlockEvents() {
        try {
            Log.d(TAG, "started watching for lock and unlock events")
@@ -255,6 +264,7 @@ constructor(
                        emptyFlow()
                    }
                },
                lockNowRequests.receiveAsFlow().map { LockImmediately("lockNow") },
            )
            .collectLatest(::onLockEvent)
    }
+3 −1
Original line number Diff line number Diff line
@@ -662,7 +662,9 @@ public class KeyguardService extends Service {
            trace("doKeyguardTimeout");
            checkPermission();

            if (KeyguardWmStateRefactor.isEnabled()) {
            if (SceneContainerFlag.isEnabled()) {
                mDeviceEntryInteractorLazy.get().lockNow();
            } else if (KeyguardWmStateRefactor.isEnabled()) {
                mKeyguardLockWhileAwakeInteractor.onKeyguardServiceDoKeyguardTimeout(options);
            }