summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractorTest.kt58
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt28
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt32
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceUnlockedInteractor.kt105
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt15
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt2
7 files changed, 170 insertions, 72 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 030233625027..39baa01e07d6 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
@@ -570,7 +570,7 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() {
unlockDevice()
assertThat(isUnlocked).isTrue()
- underTest.lockNow()
+ underTest.lockNow("test")
runCurrent()
assertThat(isUnlocked).isFalse()
@@ -597,6 +597,62 @@ class DeviceUnlockedInteractorTest : SysuiTestCase() {
assertThat(deviceUnlockStatus?.isUnlocked).isFalse()
}
+ @Test
+ fun deviceUnlockStatus_staysUnlocked_whenDeviceGoesToSleep_whileIsTrusted() =
+ testScope.runTest {
+ setLockAfterScreenTimeout(5000)
+ kosmos.fakeAuthenticationRepository.powerButtonInstantlyLocks = false
+ val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus)
+
+ kosmos.fakeTrustRepository.setCurrentUserTrusted(true)
+
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+ runCurrent()
+ assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
+
+ kosmos.powerInteractor.setAsleepForTest(
+ sleepReason = PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON
+ )
+ runCurrent()
+
+ assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
+ }
+
+ @Test
+ fun deviceUnlockStatus_staysUnlocked_whileIsTrusted() =
+ testScope.runTest {
+ val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus)
+ kosmos.fakeTrustRepository.setCurrentUserTrusted(true)
+ unlockDevice()
+
+ kosmos.powerInteractor.setAsleepForTest(
+ sleepReason = PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON
+ )
+ runCurrent()
+
+ assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
+ }
+
+ @Test
+ fun deviceUnlockStatus_becomesLocked_whenNoLongerTrusted_whileAsleep() =
+ testScope.runTest {
+ val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus)
+ kosmos.fakeTrustRepository.setCurrentUserTrusted(true)
+ unlockDevice()
+ kosmos.powerInteractor.setAsleepForTest(
+ sleepReason = PowerManager.GO_TO_SLEEP_REASON_SLEEP_BUTTON
+ )
+ runCurrent()
+ assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
+
+ kosmos.fakeTrustRepository.setCurrentUserTrusted(false)
+ runCurrent()
+
+ assertThat(deviceUnlockStatus?.isUnlocked).isFalse()
+ }
+
private fun TestScope.unlockDevice() {
val deviceUnlockStatus by collectLastValue(underTest.deviceUnlockStatus)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index af30e435da73..5648c62fb439 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -2697,6 +2697,34 @@ class SceneContainerStartableTest : SysuiTestCase() {
assertThat(isVisible).isFalse()
}
+ @Test
+ fun deviceLocks_whenNoLongerTrusted_whileDeviceNotEntered() =
+ testScope.runTest {
+ prepareState(isDeviceUnlocked = true, initialSceneKey = Scenes.Gone)
+ underTest.start()
+
+ val isDeviceEntered by collectLastValue(kosmos.deviceEntryInteractor.isDeviceEntered)
+ val deviceUnlockStatus by
+ collectLastValue(kosmos.deviceUnlockedInteractor.deviceUnlockStatus)
+ val currentScene by collectLastValue(kosmos.sceneInteractor.currentScene)
+ assertThat(isDeviceEntered).isTrue()
+ assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
+ assertThat(currentScene).isEqualTo(Scenes.Gone)
+ kosmos.fakeTrustRepository.setCurrentUserTrusted(true)
+ kosmos.sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
+ runCurrent()
+ assertThat(isDeviceEntered).isFalse()
+ assertThat(deviceUnlockStatus?.isUnlocked).isTrue()
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+
+ kosmos.fakeTrustRepository.setCurrentUserTrusted(false)
+ runCurrent()
+
+ assertThat(isDeviceEntered).isFalse()
+ assertThat(deviceUnlockStatus?.isUnlocked).isFalse()
+ assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
+ }
+
private fun TestScope.emulateSceneTransition(
transitionStateFlow: MutableStateFlow<ObservableTransitionState>,
toScene: SceneKey,
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
index 5b6859761705..5fc924b14814 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
@@ -16,7 +16,6 @@
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
@@ -36,11 +35,9 @@ import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.utils.coroutines.flow.mapLatestConflated
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
@@ -285,32 +282,7 @@ constructor(
}
/** Locks the device instantly. */
- fun lockNow() {
- deviceUnlockedInteractor.lockNow()
- }
-
- suspend fun hydrateTableLogBuffer(tableLogBuffer: TableLogBuffer) {
- coroutineScope {
- launch {
- isDeviceEntered
- .logDiffsForTable(
- tableLogBuffer = tableLogBuffer,
- columnName = "isDeviceEntered",
- initialValue = isDeviceEntered.value,
- )
- .collect()
- }
-
- launch {
- canSwipeToEnter
- .map { it?.toString() ?: "" }
- .logDiffsForTable(
- tableLogBuffer = tableLogBuffer,
- columnName = "canSwipeToEnter",
- initialValue = canSwipeToEnter.value?.toString() ?: "",
- )
- .collect()
- }
- }
+ fun lockNow(debuggingReason: String) {
+ deviceUnlockedInteractor.lockNow(debuggingReason)
}
}
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 b1be9a209a0a..c6ae35317c72 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
@@ -59,6 +59,7 @@ import kotlinx.coroutines.flow.distinctUntilChangedBy
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.receiveAsFlow
@@ -70,7 +71,7 @@ class DeviceUnlockedInteractor
constructor(
private val authenticationInteractor: AuthenticationInteractor,
private val repository: DeviceEntryRepository,
- trustInteractor: TrustInteractor,
+ private val trustInteractor: TrustInteractor,
faceAuthInteractor: DeviceEntryFaceAuthInteractor,
fingerprintAuthInteractor: DeviceEntryFingerprintAuthInteractor,
private val powerInteractor: PowerInteractor,
@@ -181,7 +182,8 @@ constructor(
val deviceUnlockStatus: StateFlow<DeviceUnlockStatus> =
repository.deviceUnlockStatus.asStateFlow()
- private val lockNowRequests = Channel<Unit>()
+ /** A [Channel] of "lock now" requests where the values are the debugging reasons. */
+ private val lockNowRequests = Channel<String>()
override suspend fun onActivated(): Nothing {
coroutineScope {
@@ -218,8 +220,8 @@ constructor(
}
/** Locks the device instantly. */
- fun lockNow() {
- lockNowRequests.trySend(Unit)
+ fun lockNow(debuggingReason: String) {
+ lockNowRequests.trySend(debuggingReason)
}
private suspend fun handleLockAndUnlockEvents() {
@@ -244,47 +246,70 @@ constructor(
private suspend fun handleLockEvents() {
merge(
- // Device wakefulness events.
- powerInteractor.detailedWakefulness
- .map { Pair(it.isAsleep(), it.lastSleepReason) }
- .distinctUntilChangedBy { it.first }
- .map { (isAsleep, lastSleepReason) ->
- if (isAsleep) {
- if (
- (lastSleepReason == WakeSleepReason.POWER_BUTTON) &&
- authenticationInteractor.getPowerButtonInstantlyLocks()
- ) {
- LockImmediately("locked instantly from power button")
- } else if (lastSleepReason == WakeSleepReason.SLEEP_BUTTON) {
- LockImmediately("locked instantly from sleep button")
- } else {
- LockWithDelay("entering sleep")
- }
- } else {
- CancelDelayedLock("waking up")
- }
- },
+ trustInteractor.isTrusted.flatMapLatestConflated { isTrusted ->
+ if (isTrusted) {
+ // When entering a trusted environment, power-related lock events are
+ // ignored.
+ Log.d(TAG, "In trusted environment, ignoring power-related lock events")
+ flowOf(CancelDelayedLock("in trusted environment"))
+ } else {
+ // When not in a trusted environment, power-related lock events are treated
+ // as normal.
+ Log.d(
+ TAG,
+ "Not in trusted environment, power-related lock events treated as" +
+ " normal",
+ )
+ merge(
+ // Device wakefulness events.
+ powerInteractor.detailedWakefulness
+ .map { Pair(it.isAsleep(), it.lastSleepReason) }
+ .distinctUntilChangedBy { it.first }
+ .map { (isAsleep, lastSleepReason) ->
+ if (isAsleep) {
+ if (
+ (lastSleepReason == WakeSleepReason.POWER_BUTTON) &&
+ authenticationInteractor
+ .getPowerButtonInstantlyLocks()
+ ) {
+ LockImmediately("locked instantly from power button")
+ } else if (
+ lastSleepReason == WakeSleepReason.SLEEP_BUTTON
+ ) {
+ LockImmediately("locked instantly from sleep button")
+ } else {
+ LockWithDelay("entering sleep")
+ }
+ } else {
+ CancelDelayedLock("waking up")
+ }
+ },
+ // 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()
+ }
+ },
+ )
+ }
+ },
// Device enters lockdown.
isInLockdown
.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()
- }
- },
- lockNowRequests.receiveAsFlow().map { LockImmediately("lockNow") },
+ lockNowRequests.receiveAsFlow().map { reason -> LockImmediately(reason) },
)
.collectLatest(::onLockEvent)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 1d36076347bf..c1a59f180225 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -671,7 +671,7 @@ public class KeyguardService extends Service {
checkPermission();
if (SceneContainerFlag.isEnabled()) {
- mDeviceEntryInteractorLazy.get().lockNow();
+ mDeviceEntryInteractorLazy.get().lockNow("doKeyguardTimeout");
} else if (KeyguardWmStateRefactor.isEnabled()) {
mKeyguardServiceLockNowInteractor.onKeyguardServiceDoKeyguardTimeout(options);
}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 2fd584176220..94e32fcb9ac6 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -44,6 +44,7 @@ import com.android.systemui.deviceentry.shared.model.DeviceUnlockSource
import com.android.systemui.keyguard.DismissCallbackRegistry
import com.android.systemui.keyguard.domain.interactor.KeyguardEnabledInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
+import com.android.systemui.keyguard.domain.interactor.TrustInteractor
import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor.Companion.keyguardScenes
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.model.SceneContainerPlugin
@@ -148,6 +149,7 @@ constructor(
private val activityTransitionAnimator: ActivityTransitionAnimator,
private val shadeModeInteractor: ShadeModeInteractor,
@SceneFrameworkTableLog private val tableLogBuffer: TableLogBuffer,
+ private val trustInteractor: TrustInteractor,
) : CoreStartable {
private val centralSurfaces: CentralSurfaces?
get() = centralSurfacesOptLazy.get().getOrNull()
@@ -173,6 +175,7 @@ constructor(
notifyKeyguardDismissCancelledCallbacks()
refreshLockscreenEnabled()
hydrateActivityTransitionAnimationState()
+ lockWhenDeviceBecomesUntrusted()
} else {
sceneLogger.logFrameworkEnabled(
isEnabled = false,
@@ -998,6 +1001,18 @@ constructor(
)
}
+ private fun lockWhenDeviceBecomesUntrusted() {
+ applicationScope.launch {
+ trustInteractor.isTrusted.pairwise().collect { (wasTrusted, isTrusted) ->
+ if (wasTrusted && !isTrusted && !deviceEntryInteractor.isDeviceEntered.value) {
+ deviceEntryInteractor.lockNow(
+ "Exited trusted environment while not device not entered"
+ )
+ }
+ }
+ }
+ }
+
companion object {
private const val TAG = "SceneContainerStartable"
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
index 65bfafbfa9b0..7a9b052481cb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/startable/SceneContainerStartableKosmos.kt
@@ -33,6 +33,7 @@ import com.android.systemui.haptics.vibratorHelper
import com.android.systemui.keyguard.dismissCallbackRegistry
import com.android.systemui.keyguard.domain.interactor.keyguardEnabledInteractor
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
import com.android.systemui.kosmos.testScope
@@ -91,5 +92,6 @@ val Kosmos.sceneContainerStartable by Fixture {
activityTransitionAnimator = activityTransitionAnimator,
shadeModeInteractor = shadeModeInteractor,
tableLogBuffer = logcatTableLogBuffer(this, "sceneFrameworkTableLogBuffer"),
+ trustInteractor = trustInteractor,
)
}