diff options
3 files changed, 121 insertions, 20 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorTest.kt index 38ed22a1c410..f0d79bb83652 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorTest.kt @@ -33,6 +33,7 @@ import com.android.systemui.flags.fakeSystemPropertiesHelper import com.android.systemui.keyguard.data.repository.fakeBiometricSettingsRepository import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository +import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository import com.android.systemui.keyguard.data.repository.fakeTrustRepository import com.android.systemui.keyguard.shared.model.AuthenticationFlags import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus @@ -40,6 +41,8 @@ import com.android.systemui.kosmos.testScope import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest import com.android.systemui.power.domain.interactor.powerInteractor +import com.android.systemui.scene.domain.interactor.sceneInteractor +import com.android.systemui.scene.shared.model.Scenes import com.android.systemui.testKosmos import com.android.systemui.user.data.model.SelectionStatus import com.android.systemui.user.data.repository.fakeUserRepository @@ -47,6 +50,7 @@ import com.android.systemui.user.domain.interactor.selectedUserInteractor import com.android.systemui.util.settings.fakeSettings import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.map import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.advanceTimeBy import kotlinx.coroutines.test.runCurrent @@ -230,11 +234,7 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() { @Test fun deviceUnlockStatus_isResetToFalse_whenDeviceGoesToSleep() = testScope.runTest { - kosmos.fakeSettings.putIntForUser( - Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, - 0, - kosmos.selectedUserInteractor.getSelectedUserId(), - ) + setLockAfterScreenTimeout(0) kosmos.fakeAuthenticationRepository.powerButtonInstantlyLocks = false val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus) @@ -254,11 +254,7 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() { fun deviceUnlockStatus_isResetToFalse_whenDeviceGoesToSleep_afterDelay() = testScope.runTest { val delay = 5000 - kosmos.fakeSettings.putIntForUser( - Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, - delay, - kosmos.selectedUserInteractor.getSelectedUserId(), - ) + setLockAfterScreenTimeout(delay) kosmos.fakeAuthenticationRepository.powerButtonInstantlyLocks = false val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus) @@ -279,11 +275,7 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() { @Test fun deviceUnlockStatus_isResetToFalse_whenDeviceGoesToSleep_powerButtonLocksInstantly() = testScope.runTest { - kosmos.fakeSettings.putIntForUser( - Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, - 5000, - kosmos.selectedUserInteractor.getSelectedUserId(), - ) + setLockAfterScreenTimeout(5000) kosmos.fakeAuthenticationRepository.powerButtonInstantlyLocks = true val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus) @@ -304,11 +296,7 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() { @Test fun deviceUnlockStatus_becomesUnlocked_whenFingerprintUnlocked_whileDeviceAsleep() = testScope.runTest { - kosmos.fakeSettings.putIntForUser( - Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, - 0, - kosmos.selectedUserInteractor.getSelectedUserId(), - ) + setLockAfterScreenTimeout(0) val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus) assertThat(deviceUnlockStatus?.isUnlocked).isFalse() @@ -517,6 +505,98 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() { .isEqualTo(DeviceEntryRestrictionReason.DeviceNotUnlockedSinceMainlineUpdate) } + @Test + fun deviceUnlockStatus_locksImmediately_whenDreamStarts_noTimeout() = + testScope.runTest { + setLockAfterScreenTimeout(0) + val isUnlocked by collectLastValue(underTest.deviceUnlockStatus.map { it.isUnlocked }) + unlockDevice() + + startDreaming() + + assertThat(isUnlocked).isFalse() + } + + @Test + fun deviceUnlockStatus_locksWithDelay_afterDreamStarts_withTimeout() = + testScope.runTest { + val delay = 5000 + setLockAfterScreenTimeout(delay) + val isUnlocked by collectLastValue(underTest.deviceUnlockStatus.map { it.isUnlocked }) + unlockDevice() + + startDreaming() + assertThat(isUnlocked).isTrue() + + advanceTimeBy(delay - 1L) + assertThat(isUnlocked).isTrue() + + advanceTimeBy(1L) + assertThat(isUnlocked).isFalse() + } + + @Test + fun deviceUnlockStatus_doesNotLockWithDelay_whenDreamStopsBeforeTimeout() = + testScope.runTest { + val delay = 5000 + setLockAfterScreenTimeout(delay) + val isUnlocked by collectLastValue(underTest.deviceUnlockStatus.map { it.isUnlocked }) + unlockDevice() + + startDreaming() + assertThat(isUnlocked).isTrue() + + advanceTimeBy(delay - 1L) + assertThat(isUnlocked).isTrue() + + stopDreaming() + assertThat(isUnlocked).isTrue() + + advanceTimeBy(1L) + assertThat(isUnlocked).isTrue() + } + + @Test + fun deviceUnlockStatus_doesNotLock_whenDreamStarts_ifNotInteractive() = + testScope.runTest { + setLockAfterScreenTimeout(0) + val isUnlocked by collectLastValue(underTest.deviceUnlockStatus.map { it.isUnlocked }) + unlockDevice() + + startDreaming() + + assertThat(isUnlocked).isFalse() + } + + private fun TestScope.unlockDevice() { + val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus) + + kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus( + SuccessFingerprintAuthenticationStatus(0, true) + ) + assertThat(deviceUnlockStatus?.isUnlocked).isTrue() + kosmos.sceneInteractor.changeScene(Scenes.Gone, "reason") + runCurrent() + } + + private fun setLockAfterScreenTimeout(timeoutMs: Int) { + kosmos.fakeSettings.putIntForUser( + Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, + timeoutMs, + kosmos.selectedUserInteractor.getSelectedUserId(), + ) + } + + private fun TestScope.startDreaming() { + kosmos.fakeKeyguardRepository.setDreaming(true) + runCurrent() + } + + private fun TestScope.stopDreaming() { + kosmos.fakeKeyguardRepository.setDreaming(false) + runCurrent() + } + private fun TestScope.verifyRestrictionReasonsForAuthFlags( vararg authFlagToDeviceEntryRestriction: Pair<Int, DeviceEntryRestrictionReason?> ) { diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt index 67584a599e5c..b74ca035a229 100644 --- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt @@ -30,11 +30,13 @@ import com.android.systemui.deviceentry.shared.model.DeviceUnlockSource import com.android.systemui.deviceentry.shared.model.DeviceUnlockStatus import com.android.systemui.flags.SystemPropertiesHelper import com.android.systemui.keyguard.KeyguardViewMediator +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor import com.android.systemui.keyguard.domain.interactor.TrustInteractor import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.power.domain.interactor.PowerInteractor import com.android.systemui.power.shared.model.WakeSleepReason import com.android.systemui.util.settings.repository.UserAwareSecureSettingsRepository +import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated import javax.inject.Inject import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CoroutineScope @@ -49,6 +51,7 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChangedBy +import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map @@ -69,6 +72,7 @@ constructor( private val biometricSettingsInteractor: DeviceEntryBiometricSettingsInteractor, private val systemPropertiesHelper: SystemPropertiesHelper, private val userAwareSecureSettingsRepository: UserAwareSecureSettingsRepository, + private val keyguardInteractor: KeyguardInteractor, ) : ExclusiveActivatable() { private val deviceUnlockSource = @@ -236,6 +240,21 @@ constructor( .distinctUntilChanged() .filter { it } .map { LockImmediately("lockdown") }, + // Started dreaming + powerInteractor.isInteractive.flatMapLatestConflated { isInteractive -> + // Only respond to dream state changes while the device is interactive. + if (isInteractive) { + keyguardInteractor.isDreamingAny.distinctUntilChanged().map { isDreaming -> + if (isDreaming) { + LockWithDelay("started dreaming") + } else { + CancelDelayedLock("stopped dreaming") + } + } + } else { + emptyFlow() + } + }, ) .collectLatest(::onLockEvent) } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorKosmos.kt index b76fa356de33..e4c7df64fdc6 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorKosmos.kt @@ -19,6 +19,7 @@ package com.android.systemui.deviceentry.domain.interactor import com.android.systemui.authentication.domain.interactor.authenticationInteractor import com.android.systemui.deviceentry.data.repository.deviceEntryRepository import com.android.systemui.flags.fakeSystemPropertiesHelper +import com.android.systemui.keyguard.domain.interactor.keyguardInteractor import com.android.systemui.keyguard.domain.interactor.trustInteractor import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture @@ -38,6 +39,7 @@ val Kosmos.deviceUnlockedInteractor by Fixture { biometricSettingsInteractor = deviceEntryBiometricSettingsInteractor, systemPropertiesHelper = fakeSystemPropertiesHelper, userAwareSecureSettingsRepository = userAwareSecureSettingsRepository, + keyguardInteractor = keyguardInteractor, ) .apply { activateIn(testScope) } } |