summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author burakov <burakov@google.com> 2023-09-27 12:19:33 +0000
committer burakov <burakov@google.com> 2023-09-29 11:05:37 +0000
commitaf001916d68de16cd7ea5f2013240f40197020bc (patch)
treeb7c1408127a8a577480b3fb0ebc8e76c9d85457d
parent48d97faecfa9064d1d24a528d27b9f998bedd885 (diff)
[flexiglass] Add a DeviceEntry module.
This module hosts business logic and state related to device entry, i.e. when the user successfully dismisses (or bypasses) the lockscreen. This is distinct from the authentication module, which is specifically concerned with determining a user's identity. The names of certain state variables have changed, too: * `isLockscreenDismissed` is now `isDeviceEntered` * `canSwipeToDismiss` is now `canSwipeToEnter` * `isLockscreenEnabled` is now `isInsecureLockscreenEnabled` Bug: 301253588 Test: Existing unit tests still pass. Test: Added new unit tests. Test: Manually tested the 3 different bouncer auth methods, lockscreen bypass and swipe, and verified they still work as expected. Change-Id: I9596513b4319eb0a9b9a25bee3a1c1726396e4ca
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt33
-rw-r--r--packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt126
-rw-r--r--packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt4
-rw-r--r--packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/DeviceEntryModule.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt125
-rw-r--r--packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt110
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt55
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt26
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt14
-rw-r--r--packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt11
-rw-r--r--packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt12
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java4
-rw-r--r--packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt169
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt15
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt127
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt234
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt42
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt71
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt1
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt16
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt29
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt73
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt22
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt20
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt35
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt16
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt7
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt47
38 files changed, 941 insertions, 662 deletions
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
index b2287d876a48..51dafac7b421 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java
@@ -18,6 +18,7 @@ package com.android.keyguard;
import static android.app.StatusBarManager.SESSION_KEYGUARD;
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_BIOMETRIC;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_EXTENDED_ACCESS;
import static com.android.keyguard.KeyguardSecurityContainer.BOUNCER_DISMISS_NONE_SECURITY;
@@ -68,8 +69,6 @@ import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
import com.android.keyguard.dagger.KeyguardBouncerScope;
import com.android.settingslib.utils.ThreadUtils;
import com.android.systemui.Gefingerpoken;
-import com.android.systemui.res.R;
-import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor;
import com.android.systemui.biometrics.FaceAuthAccessibilityDelegate;
import com.android.systemui.biometrics.SideFpsController;
import com.android.systemui.biometrics.SideFpsUiRequestSource;
@@ -77,6 +76,7 @@ import com.android.systemui.bouncer.domain.interactor.BouncerMessageInteractor;
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
import com.android.systemui.classifier.FalsingA11yDelegate;
import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.domain.interactor.KeyguardFaceAuthInteractor;
@@ -84,6 +84,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.log.SessionTracker;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.res.R;
import com.android.systemui.scene.shared.flag.SceneContainerFlags;
import com.android.systemui.shared.system.SysUiStatsLog;
import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -420,7 +421,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
}
};
private final UserInteractor mUserInteractor;
- private final Provider<AuthenticationInteractor> mAuthenticationInteractor;
+ private final Provider<DeviceEntryInteractor> mDeviceEntryInteractor;
private final Provider<JavaAdapter> mJavaAdapter;
private final DeviceProvisionedController mDeviceProvisionedController;
private final Lazy<PrimaryBouncerInteractor> mPrimaryBouncerInteractor;
@@ -457,7 +458,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
FaceAuthAccessibilityDelegate faceAuthAccessibilityDelegate,
KeyguardTransitionInteractor keyguardTransitionInteractor,
Lazy<PrimaryBouncerInteractor> primaryBouncerInteractor,
- Provider<AuthenticationInteractor> authenticationInteractor
+ Provider<DeviceEntryInteractor> deviceEntryInteractor
) {
super(view);
view.setAccessibilityDelegate(faceAuthAccessibilityDelegate);
@@ -487,7 +488,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
mKeyguardFaceAuthInteractor = keyguardFaceAuthInteractor;
mBouncerMessageInteractor = bouncerMessageInteractor;
mUserInteractor = userInteractor;
- mAuthenticationInteractor = authenticationInteractor;
+ mDeviceEntryInteractor = deviceEntryInteractor;
mJavaAdapter = javaAdapter;
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
mDeviceProvisionedController = deviceProvisionedController;
@@ -519,9 +520,9 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
// When the scene framework says that the lockscreen has been dismissed, dismiss the
// keyguard here, revealing the underlying app or launcher:
mSceneTransitionCollectionJob = mJavaAdapter.get().alwaysCollectFlow(
- mAuthenticationInteractor.get().isLockscreenDismissed(),
- isLockscreenDismissed -> {
- if (isLockscreenDismissed) {
+ mDeviceEntryInteractor.get().isDeviceEntered(),
+ isDeviceEntered -> {
+ if (isDeviceEntered) {
final int selectedUserId = mUserInteractor.getSelectedUserId();
showNextSecurityScreenOrFinish(
/* authenticated= */ true,
@@ -1081,15 +1082,11 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
* one side).
*/
private boolean canUseOneHandedBouncer() {
- switch(mCurrentSecurityMode) {
- case PIN:
- case Pattern:
- case SimPin:
- case SimPuk:
- return getResources().getBoolean(R.bool.can_use_one_handed_bouncer);
- default:
- return false;
- }
+ return switch (mCurrentSecurityMode) {
+ case PIN, Pattern, SimPin, SimPuk -> getResources().getBoolean(
+ R.bool.can_use_one_handed_bouncer);
+ default -> false;
+ };
}
private boolean canDisplayUserSwitcher() {
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
index b2433d4832f4..80be008dbd3a 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
@@ -29,9 +29,9 @@ import com.android.systemui.authentication.data.model.AuthenticationMethodModel
import com.android.systemui.authentication.shared.model.AuthenticationResultModel
import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
import com.android.systemui.broadcast.BroadcastDispatcher
+import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.util.kotlin.pairwise
import com.android.systemui.util.time.SystemClock
@@ -59,18 +59,6 @@ import kotlinx.coroutines.withContext
/** Defines interface for classes that can access authentication-related application state. */
interface AuthenticationRepository {
-
- /**
- * Whether the device is unlocked.
- *
- * A device that is not yet unlocked requires unlocking by completing an authentication
- * challenge according to the current authentication method, unless in cases when the current
- * authentication method is not "secure" (for example, None); in such cases, the value of this
- * flow will always be `true`, even if the lockscreen is showing and still needs to be dismissed
- * by the user to proceed.
- */
- val isUnlocked: StateFlow<Boolean>
-
/**
* Whether the auto confirm feature is enabled for the currently-selected user.
*
@@ -129,14 +117,6 @@ interface AuthenticationRepository {
/** Returns the length of the PIN or `0` if the current auth method is not PIN. */
suspend fun getPinLength(): Int
- /**
- * Returns whether the lockscreen is enabled.
- *
- * When the lockscreen is not enabled, it shouldn't show in cases when the authentication method
- * is considered not secure (for example, "swipe" is considered to be "none").
- */
- suspend fun isLockscreenEnabled(): Boolean
-
/** Reports an authentication attempt. */
suspend fun reportAuthenticationAttempt(isSuccessful: Boolean)
@@ -167,6 +147,7 @@ interface AuthenticationRepository {
suspend fun checkCredential(credential: LockscreenCredential): AuthenticationResultModel
}
+@SysUISingleton
class AuthenticationRepositoryImpl
@Inject
constructor(
@@ -174,20 +155,10 @@ constructor(
private val getSecurityMode: Function<Int, KeyguardSecurityModel.SecurityMode>,
@Background private val backgroundDispatcher: CoroutineDispatcher,
private val userRepository: UserRepository,
- keyguardRepository: KeyguardRepository,
private val lockPatternUtils: LockPatternUtils,
broadcastDispatcher: BroadcastDispatcher,
) : AuthenticationRepository {
- override val isUnlocked = keyguardRepository.isKeyguardUnlocked
-
- override suspend fun isLockscreenEnabled(): Boolean {
- return withContext(backgroundDispatcher) {
- val selectedUserId = userRepository.selectedUserId
- !lockPatternUtils.isLockScreenDisabled(selectedUserId)
- }
- }
-
override val isAutoConfirmEnabled: StateFlow<Boolean> =
refreshingFlow(
initialValue = false,
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
index 4cfc6aaa2b50..453a7a6d3536 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
@@ -26,9 +26,7 @@ import com.android.systemui.authentication.shared.model.AuthenticationThrottling
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.scene.domain.interactor.SceneInteractor
-import com.android.systemui.scene.shared.model.SceneKey
+import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
@@ -42,15 +40,19 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
-/** Hosts application business logic related to authentication. */
+/**
+ * Hosts application business logic related to user authentication.
+ *
+ * Note: there is a distinction between authentication (determining a user's identity) and device
+ * entry (dismissing the lockscreen). For logic that is specific to device entry, please use
+ * `DeviceEntryInteractor` instead.
+ */
@SysUISingleton
class AuthenticationInteractor
@Inject
@@ -59,8 +61,7 @@ constructor(
private val repository: AuthenticationRepository,
@Background private val backgroundDispatcher: CoroutineDispatcher,
private val userRepository: UserRepository,
- private val keyguardRepository: KeyguardRepository,
- sceneInteractor: SceneInteractor,
+ private val deviceEntryRepository: DeviceEntryRepository,
private val clock: SystemClock,
) {
/**
@@ -77,76 +78,13 @@ constructor(
* Note: this layer adds the synthetic authentication method of "swipe" which is special. When
* the current authentication method is "swipe", the user does not need to complete any
* authentication challenge to unlock the device; they just need to dismiss the lockscreen to
- * get past it. This also means that the value of [isUnlocked] remains `false` even when the
- * lockscreen is showing and still needs to be dismissed by the user to proceed.
+ * get past it. This also means that the value of `DeviceEntryInteractor#isUnlocked` remains
+ * `true` even when the lockscreen is showing and still needs to be dismissed by the user to
+ * proceed.
*/
val authenticationMethod: Flow<DomainLayerAuthenticationMethodModel> =
repository.authenticationMethod.map { rawModel -> rawModel.toDomainLayer() }
- /**
- * Whether the device is unlocked.
- *
- * A device that is not yet unlocked requires unlocking by completing an authentication
- * challenge according to the current authentication method, unless in cases when the current
- * authentication method is not "secure" (for example, None and Swipe); in such cases, the value
- * of this flow will always be `true`, even if the lockscreen is showing and still needs to be
- * dismissed by the user to proceed.
- */
- val isUnlocked: StateFlow<Boolean> =
- combine(
- repository.isUnlocked,
- authenticationMethod,
- ) { isUnlocked, authenticationMethod ->
- !authenticationMethod.isSecure || isUnlocked
- }
- .stateIn(
- scope = applicationScope,
- started = SharingStarted.Eagerly,
- initialValue = false,
- )
-
- /**
- * Whether the lockscreen has been dismissed (by any method). This can be false even when the
- * device is unlocked, e.g. when swipe to unlock is enabled.
- *
- * Note:
- * - `false` doesn't mean the lockscreen is visible (it may be occluded or covered by other UI).
- * - `true` doesn't mean the lockscreen is invisible (since this state changes before the
- * transition occurs).
- */
- val isLockscreenDismissed: StateFlow<Boolean> =
- sceneInteractor.desiredScene
- .map { it.key }
- .filter { currentScene ->
- currentScene == SceneKey.Gone || currentScene == SceneKey.Lockscreen
- }
- .map { it == SceneKey.Gone }
- .stateIn(
- scope = applicationScope,
- started = SharingStarted.WhileSubscribed(),
- initialValue = false,
- )
-
- /**
- * Whether it's currently possible to swipe up to dismiss the lockscreen without requiring
- * authentication. This returns false whenever the lockscreen has been dismissed.
- *
- * Note: `true` doesn't mean the lockscreen is visible. It may be occluded or covered by other
- * UI.
- */
- val canSwipeToDismiss =
- combine(authenticationMethod, isLockscreenDismissed) {
- authenticationMethod,
- isLockscreenDismissed ->
- authenticationMethod is DomainLayerAuthenticationMethodModel.Swipe &&
- !isLockscreenDismissed
- }
- .stateIn(
- scope = applicationScope,
- started = SharingStarted.WhileSubscribed(),
- initialValue = false,
- )
-
/** The current authentication throttling state, only meaningful if [isThrottled] is `true`. */
val throttling: StateFlow<AuthenticationThrottlingModel> = repository.throttling
@@ -211,32 +149,15 @@ constructor(
* Note: this layer adds the synthetic authentication method of "swipe" which is special. When
* the current authentication method is "swipe", the user does not need to complete any
* authentication challenge to unlock the device; they just need to dismiss the lockscreen to
- * get past it. This also means that the value of [isUnlocked] remains `false` even when the
- * lockscreen is showing and still needs to be dismissed by the user to proceed.
+ * get past it. This also means that the value of `DeviceEntryInteractor#isUnlocked` remains
+ * `true` even when the lockscreen is showing and still needs to be dismissed by the user to
+ * proceed.
*/
suspend fun getAuthenticationMethod(): DomainLayerAuthenticationMethodModel {
return repository.getAuthenticationMethod().toDomainLayer()
}
/**
- * Returns `true` if the device currently requires authentication before content can be viewed;
- * `false` if content can be displayed without unlocking first.
- */
- suspend fun isAuthenticationRequired(): Boolean {
- return !isUnlocked.value && getAuthenticationMethod().isSecure
- }
-
- /**
- * Whether lock screen bypass is enabled. When enabled, the lock screen will be automatically
- * dismisses once the authentication challenge is completed. For example, completing a biometric
- * authentication challenge via face unlock or fingerprint sensor can automatically bypass the
- * lock screen.
- */
- fun isBypassEnabled(): Boolean {
- return keyguardRepository.isBypassEnabled()
- }
-
- /**
* Attempts to authenticate the user and unlock the device.
*
* If [tryAutoConfirm] is `true`, authentication is attempted if and only if the auth method
@@ -312,7 +233,7 @@ constructor(
/** Starts refreshing the throttling state every second. */
private suspend fun startThrottlingCountdown() {
- cancelCountdown()
+ cancelThrottlingCountdown()
throttlingCountdownJob =
applicationScope.launch {
while (refreshThrottling() > 0) {
@@ -322,14 +243,14 @@ constructor(
}
/** Cancels any throttling state countdown started in [startThrottlingCountdown]. */
- private fun cancelCountdown() {
+ private fun cancelThrottlingCountdown() {
throttlingCountdownJob?.cancel()
throttlingCountdownJob = null
}
/** Notifies that the currently-selected user has changed. */
private suspend fun onSelectedUserChanged() {
- cancelCountdown()
+ cancelThrottlingCountdown()
if (refreshThrottling() > 0) {
startThrottlingCountdown()
}
@@ -378,7 +299,7 @@ constructor(
DomainLayerAuthenticationMethodModel {
return when (this) {
is DataLayerAuthenticationMethodModel.None ->
- if (repository.isLockscreenEnabled()) {
+ if (deviceEntryRepository.isInsecureLockscreenEnabled()) {
DomainLayerAuthenticationMethodModel.Swipe
} else {
DomainLayerAuthenticationMethodModel.None
@@ -394,13 +315,10 @@ constructor(
/** Result of a user authentication attempt. */
enum class AuthenticationResult {
- /** Authentication succeeded and the device is now unlocked. */
+ /** Authentication succeeded. */
SUCCEEDED,
- /** Authentication failed and the device remains unlocked. */
+ /** Authentication failed. */
FAILED,
- /**
- * Authentication was not performed, e.g. due to insufficient input, and the device remains
- * unlocked.
- */
+ /** Authentication was not performed, e.g. due to insufficient input. */
SKIPPED,
}
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index f3a463ba44a4..0c0236999e39 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -26,6 +26,7 @@ import com.android.systemui.classifier.FalsingClassifier
import com.android.systemui.classifier.domain.interactor.FalsingInteractor
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.res.R
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlags
@@ -50,6 +51,7 @@ constructor(
@Application private val applicationScope: CoroutineScope,
@Application private val applicationContext: Context,
private val repository: BouncerRepository,
+ private val deviceEntryInteractor: DeviceEntryInteractor,
private val authenticationInteractor: AuthenticationInteractor,
private val sceneInteractor: SceneInteractor,
flags: SceneContainerFlags,
@@ -144,7 +146,7 @@ constructor(
message: String? = null,
) {
applicationScope.launch {
- if (authenticationInteractor.isAuthenticationRequired()) {
+ if (deviceEntryInteractor.isAuthenticationRequired()) {
repository.setMessage(
message ?: promptMessage(authenticationInteractor.getAuthenticationMethod())
)
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index 283a07b206b9..4b6ad6d9be03 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -48,6 +48,7 @@ import com.android.systemui.controls.dagger.ControlsModule;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.dagger.qualifiers.SystemUser;
import com.android.systemui.demomode.dagger.DemoModeModule;
+import com.android.systemui.deviceentry.DeviceEntryModule;
import com.android.systemui.display.DisplayModule;
import com.android.systemui.doze.dagger.DozeComponent;
import com.android.systemui.dreams.dagger.DreamModule;
@@ -173,6 +174,7 @@ import javax.inject.Named;
ControlsModule.class,
CoroutinesModule.class,
DemoModeModule.class,
+ DeviceEntryModule.class,
DisableFlagsModule.class,
DisplayModule.class,
DreamModule.class,
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/DeviceEntryModule.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/DeviceEntryModule.kt
new file mode 100644
index 000000000000..e7f835f7b858
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/DeviceEntryModule.kt
@@ -0,0 +1,12 @@
+package com.android.systemui.deviceentry
+
+import com.android.systemui.deviceentry.data.repository.DeviceEntryRepositoryModule
+import dagger.Module
+
+@Module(
+ includes =
+ [
+ DeviceEntryRepositoryModule::class,
+ ],
+)
+object DeviceEntryModule
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt
new file mode 100644
index 000000000000..5b85ad01301b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt
@@ -0,0 +1,125 @@
+package com.android.systemui.deviceentry.data.repository
+
+import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
+import com.android.systemui.common.coroutine.ConflatedCallbackFlow
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.user.data.repository.UserRepository
+import dagger.Binds
+import dagger.Module
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.withContext
+
+/** Interface for classes that can access device-entry-related application state. */
+interface DeviceEntryRepository {
+ /**
+ * Whether the device is unlocked.
+ *
+ * A device that is not yet unlocked requires unlocking by completing an authentication
+ * challenge according to the current authentication method, unless in cases when the current
+ * authentication method is not "secure" (for example, None); in such cases, the value of this
+ * flow will always be `true`, even if the lockscreen is showing and still needs to be dismissed
+ * by the user to proceed.
+ */
+ val isUnlocked: StateFlow<Boolean>
+
+ /**
+ * Whether the lockscreen should be shown when the authentication method is not secure (e.g.
+ * `None` or `Swipe`).
+ */
+ suspend fun isInsecureLockscreenEnabled(): Boolean
+
+ /**
+ * Whether lockscreen bypass is enabled. When enabled, the lockscreen will be automatically
+ * dismissed once the authentication challenge is completed.
+ *
+ * This is a setting that is specific to the face unlock authentication method, because the user
+ * intent to unlock is not known. On devices that don't support face unlock, this always returns
+ * `true`.
+ *
+ * When this is `false`, an automatically-triggered face unlock shouldn't automatically dismiss
+ * the lockscreen.
+ */
+ fun isBypassEnabled(): Boolean
+}
+
+/** Encapsulates application state for device entry. */
+@SysUISingleton
+class DeviceEntryRepositoryImpl
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ @Background private val backgroundDispatcher: CoroutineDispatcher,
+ private val userRepository: UserRepository,
+ private val lockPatternUtils: LockPatternUtils,
+ private val keyguardBypassController: KeyguardBypassController,
+ keyguardStateController: KeyguardStateController,
+) : DeviceEntryRepository {
+
+ override val isUnlocked =
+ ConflatedCallbackFlow.conflatedCallbackFlow {
+ val callback =
+ object : KeyguardStateController.Callback {
+ override fun onUnlockedChanged() {
+ trySendWithFailureLogging(
+ keyguardStateController.isUnlocked,
+ TAG,
+ "updated isUnlocked due to onUnlockedChanged"
+ )
+ }
+
+ override fun onKeyguardShowingChanged() {
+ trySendWithFailureLogging(
+ keyguardStateController.isUnlocked,
+ TAG,
+ "updated isUnlocked due to onKeyguardShowingChanged"
+ )
+ }
+ }
+
+ keyguardStateController.addCallback(callback)
+ // Adding the callback does not send an initial update.
+ trySendWithFailureLogging(
+ keyguardStateController.isUnlocked,
+ TAG,
+ "initial isKeyguardUnlocked"
+ )
+
+ awaitClose { keyguardStateController.removeCallback(callback) }
+ }
+ .distinctUntilChanged()
+ .stateIn(
+ applicationScope,
+ SharingStarted.Eagerly,
+ initialValue = false,
+ )
+
+ override suspend fun isInsecureLockscreenEnabled(): Boolean {
+ return withContext(backgroundDispatcher) {
+ val selectedUserId = userRepository.getSelectedUserInfo().id
+ !lockPatternUtils.isLockScreenDisabled(selectedUserId)
+ }
+ }
+
+ override fun isBypassEnabled() = keyguardBypassController.bypassEnabled
+
+ companion object {
+ private const val TAG = "DeviceEntryRepositoryImpl"
+ }
+}
+
+@Module
+interface DeviceEntryRepositoryModule {
+ @Binds fun repository(impl: DeviceEntryRepositoryImpl): DeviceEntryRepository
+}
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
new file mode 100644
index 000000000000..5612c9a488ff
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
@@ -0,0 +1,110 @@
+package com.android.systemui.deviceentry.domain.interactor
+
+import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
+import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Application
+import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
+import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.SceneKey
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.filter
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.flow.stateIn
+
+/**
+ * Hosts application business logic related to device entry.
+ *
+ * Device entry occurs when the user successfully dismisses (or bypasses) the lockscreen, regardless
+ * of the authentication method used.
+ */
+@SysUISingleton
+class DeviceEntryInteractor
+@Inject
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ private val repository: DeviceEntryRepository,
+ private val authenticationInteractor: AuthenticationInteractor,
+ sceneInteractor: SceneInteractor,
+) {
+ /**
+ * Whether the device is unlocked.
+ *
+ * A device that is not yet unlocked requires unlocking by completing an authentication
+ * challenge according to the current authentication method, unless in cases when the current
+ * authentication method is not "secure" (for example, None and Swipe); in such cases, the value
+ * of this flow will always be `true`, even if the lockscreen is showing and still needs to be
+ * dismissed by the user to proceed.
+ */
+ val isUnlocked: StateFlow<Boolean> =
+ combine(
+ repository.isUnlocked,
+ authenticationInteractor.authenticationMethod,
+ ) { isUnlocked, authenticationMethod ->
+ !authenticationMethod.isSecure || isUnlocked
+ }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.Eagerly,
+ initialValue = false,
+ )
+
+ /**
+ * Whether the device has been entered (i.e. the lockscreen has been dismissed, by any method).
+ * This can be `false` when the device is unlocked, e.g. when the user still needs to swipe away
+ * the non-secure lockscreen, even though they've already authenticated.
+ *
+ * Note: This does not imply that the lockscreen is visible or not.
+ */
+ val isDeviceEntered: StateFlow<Boolean> =
+ sceneInteractor.desiredScene
+ .map { it.key }
+ .filter { currentScene ->
+ currentScene == SceneKey.Gone || currentScene == SceneKey.Lockscreen
+ }
+ .map { it == SceneKey.Gone }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = false,
+ )
+
+ /**
+ * Whether it's currently possible to swipe up to enter the device without requiring
+ * authentication. This returns `false` whenever the lockscreen has been dismissed.
+ *
+ * Note: `true` doesn't mean the lockscreen is visible. It may be occluded or covered by other
+ * UI.
+ */
+ val canSwipeToEnter =
+ combine(authenticationInteractor.authenticationMethod, isDeviceEntered) {
+ authenticationMethod,
+ isDeviceEntered ->
+ authenticationMethod is AuthenticationMethodModel.Swipe && !isDeviceEntered
+ }
+ .stateIn(
+ scope = applicationScope,
+ started = SharingStarted.WhileSubscribed(),
+ initialValue = false,
+ )
+
+ /**
+ * Returns `true` if the device currently requires authentication before entry is granted;
+ * `false` if the device can be entered without authenticating first.
+ */
+ suspend fun isAuthenticationRequired(): Boolean {
+ return !isUnlocked.value && authenticationInteractor.getAuthenticationMethod().isSecure
+ }
+
+ /**
+ * Whether lock screen bypass is enabled. When enabled, the lock screen 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
+ * lock screen.
+ */
+ fun isBypassEnabled() = repository.isBypassEnabled()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index 2557e8112e1e..36b93cdf6217 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -47,7 +47,6 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.BiometricUnlockController.WakeAndUnlockMode
import com.android.systemui.statusbar.phone.DozeParameters
-import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.time.SystemClock
import javax.inject.Inject
@@ -97,9 +96,6 @@ interface KeyguardRepository {
*/
val isKeyguardShowing: Flow<Boolean>
- /** Is the keyguard in a unlocked state? */
- val isKeyguardUnlocked: StateFlow<Boolean>
-
/** Is an activity showing over the keyguard? */
val isKeyguardOccluded: Flow<Boolean>
@@ -206,14 +202,6 @@ interface KeyguardRepository {
*/
fun isKeyguardShowing(): Boolean
- /**
- * Whether lock screen bypass is enabled. When enabled, the lock screen 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
- * lock screen.
- */
- fun isBypassEnabled(): Boolean
-
/** Sets whether the bottom area UI should animate the transition out of doze state. */
fun setAnimateDozingTransitions(animate: Boolean)
@@ -265,7 +253,6 @@ constructor(
screenLifecycle: ScreenLifecycle,
biometricUnlockController: BiometricUnlockController,
private val keyguardStateController: KeyguardStateController,
- private val keyguardBypassController: KeyguardBypassController,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val dozeTransitionListener: DozeTransitionListener,
private val dozeParameters: DozeParameters,
@@ -370,44 +357,6 @@ constructor(
}
.distinctUntilChanged()
- override val isKeyguardUnlocked: StateFlow<Boolean> =
- conflatedCallbackFlow {
- val callback =
- object : KeyguardStateController.Callback {
- override fun onUnlockedChanged() {
- trySendWithFailureLogging(
- keyguardStateController.isUnlocked,
- TAG,
- "updated isKeyguardUnlocked due to onUnlockedChanged"
- )
- }
-
- override fun onKeyguardShowingChanged() {
- trySendWithFailureLogging(
- keyguardStateController.isUnlocked,
- TAG,
- "updated isKeyguardUnlocked due to onKeyguardShowingChanged"
- )
- }
- }
-
- keyguardStateController.addCallback(callback)
- // Adding the callback does not send an initial update.
- trySendWithFailureLogging(
- keyguardStateController.isUnlocked,
- TAG,
- "initial isKeyguardUnlocked"
- )
-
- awaitClose { keyguardStateController.removeCallback(callback) }
- }
- .distinctUntilChanged()
- .stateIn(
- scope,
- SharingStarted.Eagerly,
- initialValue = false,
- )
-
override val isKeyguardGoingAway: Flow<Boolean> = conflatedCallbackFlow {
val callback =
object : KeyguardStateController.Callback {
@@ -543,10 +492,6 @@ constructor(
return keyguardStateController.isShowing
}
- override fun isBypassEnabled(): Boolean {
- return keyguardBypassController.bypassEnabled
- }
-
// TODO(b/297345631): Expose this at the interactor level instead so that it can be powered by
// [SceneInteractor] when scenes are ready.
override val statusBarState: StateFlow<StatusBarState> =
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
index 338f9945f5db..80634682c8cf 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractor.kt
@@ -23,7 +23,6 @@ import android.app.StatusBarManager
import android.graphics.Point
import android.util.MathUtils
import com.android.app.animation.Interpolators
-import com.android.systemui.res.R
import com.android.systemui.bouncer.data.repository.KeyguardBouncerRepository
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -31,6 +30,7 @@ import com.android.systemui.common.shared.model.Position
import com.android.systemui.common.shared.model.SharedNotificationContainerPosition
import com.android.systemui.common.ui.data.repository.ConfigurationRepository
import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
import com.android.systemui.flags.FeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.KeyguardRepository
@@ -40,10 +40,10 @@ import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.KeyguardRootViewVisibilityState
-import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.ScreenModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
+import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlags
import com.android.systemui.scene.shared.model.SceneKey
@@ -79,6 +79,7 @@ constructor(
private val commandQueue: CommandQueue,
featureFlags: FeatureFlags,
sceneContainerFlags: SceneContainerFlags,
+ deviceEntryRepository: DeviceEntryRepository,
bouncerRepository: KeyguardBouncerRepository,
configurationRepository: ConfigurationRepository,
shadeRepository: ShadeRepository,
@@ -168,7 +169,7 @@ constructor(
val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
/** Whether the keyguard is unlocked or not. */
- val isKeyguardUnlocked: Flow<Boolean> = repository.isKeyguardUnlocked
+ val isKeyguardUnlocked: Flow<Boolean> = deviceEntryRepository.isUnlocked
/** Whether the keyguard is occluded (covered by an activity). */
val isKeyguardOccluded: Flow<Boolean> = repository.isKeyguardOccluded
@@ -323,26 +324,7 @@ constructor(
repository.setAnimateDozingTransitions(animate)
}
- fun isKeyguardDismissable(): Boolean {
- return repository.isKeyguardUnlocked.value
- }
-
companion object {
private const val TAG = "KeyguardInteractor"
-
- fun isKeyguardVisibleInState(state: KeyguardState): Boolean {
- return when (state) {
- KeyguardState.OFF -> true
- KeyguardState.DOZING -> true
- KeyguardState.DREAMING -> true
- KeyguardState.AOD -> true
- KeyguardState.ALTERNATE_BOUNCER -> true
- KeyguardState.PRIMARY_BOUNCER -> true
- KeyguardState.LOCKSCREEN -> true
- KeyguardState.GONE -> false
- KeyguardState.OCCLUDED -> true
- KeyguardState.DREAMING_LOCKSCREEN_HOSTED -> false
- }
- }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt
index 91b33572345d..c03e4d950cae 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModel.kt
@@ -16,10 +16,10 @@
package com.android.systemui.keyguard.ui.viewmodel
-import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.communal.domain.interactor.CommunalInteractor
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.scene.shared.model.SceneKey
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -34,26 +34,22 @@ class LockscreenSceneViewModel
@Inject
constructor(
@Application applicationScope: CoroutineScope,
- authenticationInteractor: AuthenticationInteractor,
+ deviceEntryInteractor: DeviceEntryInteractor,
communalInteractor: CommunalInteractor,
val longPress: KeyguardLongPressViewModel,
) {
/** The key of the scene we should switch to when swiping up. */
val upDestinationSceneKey: StateFlow<SceneKey> =
- authenticationInteractor.isUnlocked
+ deviceEntryInteractor.isUnlocked
.map { isUnlocked -> upDestinationSceneKey(isUnlocked) }
.stateIn(
scope = applicationScope,
started = SharingStarted.WhileSubscribed(),
- initialValue = upDestinationSceneKey(authenticationInteractor.isUnlocked.value),
+ initialValue = upDestinationSceneKey(deviceEntryInteractor.isUnlocked.value),
)
private fun upDestinationSceneKey(isUnlocked: Boolean): SceneKey {
- return if (isUnlocked) {
- SceneKey.Gone
- } else {
- SceneKey.Bouncer
- }
+ return if (isUnlocked) SceneKey.Gone else SceneKey.Bouncer
}
/** The key of the scene we should switch to when swiping left. */
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 722d3661d0ae..a3499bd5c264 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
@@ -26,6 +26,7 @@ import com.android.systemui.classifier.FalsingCollectorActual
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.DisplayId
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.model.SysUiState
@@ -63,6 +64,7 @@ class SceneContainerStartable
constructor(
@Application private val applicationScope: CoroutineScope,
private val sceneInteractor: SceneInteractor,
+ private val deviceEntryInteractor: DeviceEntryInteractor,
private val authenticationInteractor: AuthenticationInteractor,
private val keyguardInteractor: KeyguardInteractor,
private val flags: SceneContainerFlags,
@@ -119,7 +121,7 @@ constructor(
/** Switches between scenes based on ever-changing application state. */
private fun automaticallySwitchScenes() {
applicationScope.launch {
- authenticationInteractor.isUnlocked
+ deviceEntryInteractor.isUnlocked
.mapNotNull { isUnlocked ->
val renderedScenes =
when (val transitionState = sceneInteractor.transitionState.value) {
@@ -130,7 +132,6 @@ constructor(
transitionState.toScene,
)
}
- val isBypassEnabled = authenticationInteractor.isBypassEnabled()
when {
isUnlocked ->
when {
@@ -141,7 +142,7 @@ constructor(
// When the device becomes unlocked in Lockscreen, go to Gone if
// bypass is enabled.
renderedScenes.contains(SceneKey.Lockscreen) ->
- if (isBypassEnabled) {
+ if (deviceEntryInteractor.isBypassEnabled()) {
SceneKey.Gone to
"device unlocked in Lockscreen scene with bypass"
} else {
@@ -191,7 +192,7 @@ constructor(
}
WakefulnessState.STARTING_TO_WAKE -> {
val authMethod = authenticationInteractor.getAuthenticationMethod()
- val isUnlocked = authenticationInteractor.isUnlocked.value
+ val isUnlocked = deviceEntryInteractor.isUnlocked.value
when {
authMethod == AuthenticationMethodModel.None -> {
switchToScene(
@@ -241,7 +242,7 @@ constructor(
/** Collects and reports signals into the falsing system. */
private fun collectFalsingSignals() {
applicationScope.launch {
- authenticationInteractor.isLockscreenDismissed.collect { isLockscreenDismissed ->
+ deviceEntryInteractor.isDeviceEntered.collect { isLockscreenDismissed ->
if (isLockscreenDismissed) {
falsingCollector.onSuccessfulUnlock()
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
index 068d5a59ca2e..9c5a20189dd2 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
@@ -16,10 +16,10 @@
package com.android.systemui.shade.ui.viewmodel
-import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
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.scene.shared.model.SceneKey
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -34,15 +34,15 @@ class ShadeSceneViewModel
@Inject
constructor(
@Application private val applicationScope: CoroutineScope,
- authenticationInteractor: AuthenticationInteractor,
+ deviceEntryInteractor: DeviceEntryInteractor,
private val bouncerInteractor: BouncerInteractor,
val shadeHeaderViewModel: ShadeHeaderViewModel,
) {
/** The key of the scene we should switch to when swiping up. */
val upDestinationSceneKey: StateFlow<SceneKey> =
combine(
- authenticationInteractor.isUnlocked,
- authenticationInteractor.canSwipeToDismiss,
+ deviceEntryInteractor.isUnlocked,
+ deviceEntryInteractor.canSwipeToEnter,
) { isUnlocked, canSwipeToDismiss ->
upDestinationSceneKey(
isUnlocked = isUnlocked,
@@ -54,8 +54,8 @@ constructor(
started = SharingStarted.WhileSubscribed(),
initialValue =
upDestinationSceneKey(
- isUnlocked = authenticationInteractor.isUnlocked.value,
- canSwipeToDismiss = authenticationInteractor.canSwipeToDismiss.value,
+ isUnlocked = deviceEntryInteractor.isUnlocked.value,
+ canSwipeToDismiss = deviceEntryInteractor.canSwipeToEnter.value,
),
)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index 8d86d729d958..eedf35f1e9d4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import static android.view.WindowInsets.Type.navigationBars;
+
import static com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants.EXPANSION_HIDDEN;
import static com.android.systemui.plugins.ActivityStarter.OnDismissAction;
import static com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
@@ -66,7 +67,6 @@ import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.flags.Flags;
import com.android.systemui.keyguard.domain.interactor.KeyguardDismissActionInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
import com.android.systemui.keyguard.domain.interactor.WindowManagerLockscreenVisibilityInteractor;
import com.android.systemui.keyguard.shared.model.DismissAction;
@@ -134,7 +134,7 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb
// dranw its first frame.
private static final long KEYGUARD_DISMISS_DURATION_LOCKED = 2000;
- private static String TAG = "StatusBarKeyguardViewManager";
+ private static final String TAG = "StatusBarKeyguardViewManager";
private static final boolean DEBUG = false;
protected final Context mContext;
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
index f6649bdc9d3f..d54843d39d21 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSecurityContainerControllerTest.kt
@@ -36,10 +36,8 @@ import com.android.internal.logging.UiEventLogger
import com.android.internal.widget.LockPatternUtils
import com.android.keyguard.KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback
import com.android.keyguard.KeyguardSecurityModel.SecurityMode
-import com.android.systemui.res.R
import com.android.systemui.RoboPilotTest
import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
import com.android.systemui.biometrics.FaceAuthAccessibilityDelegate
import com.android.systemui.biometrics.SideFpsController
import com.android.systemui.biometrics.SideFpsUiRequestSource
@@ -47,6 +45,7 @@ import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.bouncer.shared.constants.KeyguardBouncerConstants
import com.android.systemui.classifier.FalsingA11yDelegate
import com.android.systemui.classifier.FalsingCollector
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
@@ -54,6 +53,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
import com.android.systemui.log.SessionTracker
import com.android.systemui.plugins.ActivityStarter.OnDismissAction
import com.android.systemui.plugins.FalsingManager
+import com.android.systemui.res.R
import com.android.systemui.scene.SceneTestUtils
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.ObservableTransitionState
@@ -157,7 +157,7 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
private lateinit var sceneTestUtils: SceneTestUtils
private lateinit var sceneInteractor: SceneInteractor
private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
- private lateinit var authenticationInteractor: AuthenticationInteractor
+ private lateinit var deviceEntryInteractor: DeviceEntryInteractor
@Mock private lateinit var primaryBouncerInteractor: Lazy<PrimaryBouncerInteractor>
private lateinit var sceneTransitionStateFlow: MutableStateFlow<ObservableTransitionState>
@@ -229,10 +229,10 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
sceneTransitionStateFlow =
MutableStateFlow(ObservableTransitionState.Idle(SceneKey.Lockscreen))
sceneInteractor.setTransitionState(sceneTransitionStateFlow)
- authenticationInteractor =
- sceneTestUtils.authenticationInteractor(
- repository = sceneTestUtils.authenticationRepository(),
- sceneInteractor = sceneInteractor
+ deviceEntryInteractor =
+ sceneTestUtils.deviceEntryInteractor(
+ authenticationInteractor = sceneTestUtils.authenticationInteractor(),
+ sceneInteractor = sceneInteractor,
)
underTest =
@@ -268,7 +268,7 @@ class KeyguardSecurityContainerControllerTest : SysuiTestCase() {
keyguardTransitionInteractor,
primaryBouncerInteractor,
) {
- authenticationInteractor
+ deviceEntryInteractor
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
index d3a2a73959dd..0283382d02be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
@@ -74,7 +74,6 @@ class AuthenticationRepositoryTest : SysuiTestCase() {
getSecurityMode = getSecurityMode,
backgroundDispatcher = testUtils.testDispatcher,
userRepository = userRepository,
- keyguardRepository = testUtils.keyguardRepository,
lockPatternUtils = lockPatternUtils,
broadcastDispatcher = fakeBroadcastDispatcher,
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
index 874053a83654..a102890db7b0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
@@ -20,15 +20,12 @@ import android.app.admin.DevicePolicyManager
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.model.AuthenticationMethodModel as DataLayerAuthenticationMethodModel
-import com.android.systemui.authentication.data.repository.AuthenticationRepository
import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
import com.android.systemui.authentication.domain.model.AuthenticationMethodModel as DomainLayerAuthenticationMethodModel
import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.scene.SceneTestUtils
-import com.android.systemui.scene.shared.model.SceneKey
-import com.android.systemui.scene.shared.model.SceneModel
import com.google.common.truth.Truth.assertThat
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.Duration.Companion.seconds
@@ -47,13 +44,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
- private val repository: AuthenticationRepository = utils.authenticationRepository()
- private val sceneInteractor = utils.sceneInteractor()
- private val underTest =
- utils.authenticationInteractor(
- repository = repository,
- sceneInteractor = sceneInteractor,
- )
+ private val underTest = utils.authenticationInteractor()
@Test
fun authenticationMethod() =
@@ -79,10 +70,10 @@ class AuthenticationInteractorTest : SysuiTestCase() {
val authMethod by collectLastValue(underTest.authenticationMethod)
runCurrent()
- utils.authenticationRepository.apply {
- setAuthenticationMethod(DataLayerAuthenticationMethodModel.None)
- setLockscreenEnabled(true)
- }
+ utils.authenticationRepository.setAuthenticationMethod(
+ DataLayerAuthenticationMethodModel.None
+ )
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
assertThat(authMethod).isEqualTo(DomainLayerAuthenticationMethodModel.Swipe)
assertThat(underTest.getAuthenticationMethod())
@@ -95,10 +86,10 @@ class AuthenticationInteractorTest : SysuiTestCase() {
val authMethod by collectLastValue(underTest.authenticationMethod)
runCurrent()
- utils.authenticationRepository.apply {
- setAuthenticationMethod(DataLayerAuthenticationMethodModel.None)
- setLockscreenEnabled(false)
- }
+ utils.authenticationRepository.setAuthenticationMethod(
+ DataLayerAuthenticationMethodModel.None
+ )
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(false)
assertThat(authMethod).isEqualTo(DomainLayerAuthenticationMethodModel.None)
assertThat(underTest.getAuthenticationMethod())
@@ -106,130 +97,6 @@ class AuthenticationInteractorTest : SysuiTestCase() {
}
@Test
- fun isUnlocked_whenAuthMethodIsNoneAndLockscreenDisabled_isTrue() =
- testScope.runTest {
- val isUnlocked by collectLastValue(underTest.isUnlocked)
- utils.authenticationRepository.apply {
- setAuthenticationMethod(DataLayerAuthenticationMethodModel.None)
- setLockscreenEnabled(false)
- // Toggle isUnlocked, twice.
- //
- // This is done because the underTest.isUnlocked flow doesn't receive values from
- // just changing the state above; the actual isUnlocked state needs to change to
- // cause the logic under test to "pick up" the current state again.
- //
- // It is done twice to make sure that we don't actually change the isUnlocked state
- // from what it originally was.
- setUnlocked(!utils.authenticationRepository.isUnlocked.value)
- runCurrent()
- setUnlocked(!utils.authenticationRepository.isUnlocked.value)
- runCurrent()
- }
-
- assertThat(isUnlocked).isTrue()
- }
-
- @Test
- fun isUnlocked_whenAuthMethodIsNoneAndLockscreenEnabled_isTrue() =
- testScope.runTest {
- utils.authenticationRepository.apply {
- setAuthenticationMethod(DataLayerAuthenticationMethodModel.None)
- setLockscreenEnabled(true)
- }
-
- val isUnlocked by collectLastValue(underTest.isUnlocked)
- assertThat(isUnlocked).isTrue()
- }
-
- @Test
- fun canSwipeToDismiss_onLockscreenWithSwipe_isTrue() =
- testScope.runTest {
- utils.authenticationRepository.apply {
- setAuthenticationMethod(DataLayerAuthenticationMethodModel.None)
- setLockscreenEnabled(true)
- }
- switchToScene(SceneKey.Lockscreen)
-
- val canSwipeToDismiss by collectLastValue(underTest.canSwipeToDismiss)
- assertThat(canSwipeToDismiss).isTrue()
- }
-
- @Test
- fun canSwipeToDismiss_onLockscreenWithPin_isFalse() =
- testScope.runTest {
- utils.authenticationRepository.apply {
- setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
- setLockscreenEnabled(true)
- }
- switchToScene(SceneKey.Lockscreen)
-
- val canSwipeToDismiss by collectLastValue(underTest.canSwipeToDismiss)
- assertThat(canSwipeToDismiss).isFalse()
- }
-
- @Test
- fun canSwipeToDismiss_afterLockscreenDismissedInSwipeMode_isFalse() =
- testScope.runTest {
- utils.authenticationRepository.apply {
- setAuthenticationMethod(DataLayerAuthenticationMethodModel.None)
- setLockscreenEnabled(true)
- }
- switchToScene(SceneKey.Lockscreen)
- switchToScene(SceneKey.Gone)
-
- val canSwipeToDismiss by collectLastValue(underTest.canSwipeToDismiss)
- assertThat(canSwipeToDismiss).isFalse()
- }
-
- @Test
- fun isAuthenticationRequired_lockedAndSecured_true() =
- testScope.runTest {
- utils.authenticationRepository.apply {
- setUnlocked(false)
- runCurrent()
- setAuthenticationMethod(DataLayerAuthenticationMethodModel.Password)
- }
-
- assertThat(underTest.isAuthenticationRequired()).isTrue()
- }
-
- @Test
- fun isAuthenticationRequired_lockedAndNotSecured_false() =
- testScope.runTest {
- utils.authenticationRepository.apply {
- setUnlocked(false)
- runCurrent()
- setAuthenticationMethod(DataLayerAuthenticationMethodModel.None)
- }
-
- assertThat(underTest.isAuthenticationRequired()).isFalse()
- }
-
- @Test
- fun isAuthenticationRequired_unlockedAndSecured_false() =
- testScope.runTest {
- utils.authenticationRepository.apply {
- setUnlocked(true)
- runCurrent()
- setAuthenticationMethod(DataLayerAuthenticationMethodModel.Password)
- }
-
- assertThat(underTest.isAuthenticationRequired()).isFalse()
- }
-
- @Test
- fun isAuthenticationRequired_unlockedAndNotSecured_false() =
- testScope.runTest {
- utils.authenticationRepository.apply {
- setUnlocked(true)
- runCurrent()
- setAuthenticationMethod(DataLayerAuthenticationMethodModel.None)
- }
-
- assertThat(underTest.isAuthenticationRequired()).isFalse()
- }
-
- @Test
fun authenticate_withCorrectPin_returnsTrue() =
testScope.runTest {
val isThrottled by collectLastValue(underTest.isThrottled)
@@ -366,7 +233,6 @@ class AuthenticationInteractorTest : SysuiTestCase() {
@Test
fun tryAutoConfirm_withAutoConfirmWrongPinCorrectLength_returnsFalseAndDoesNotUnlockDevice() =
testScope.runTest {
- val isUnlocked by collectLastValue(underTest.isUnlocked)
utils.authenticationRepository.apply {
setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
setAutoConfirmEnabled(true)
@@ -378,13 +244,13 @@ class AuthenticationInteractorTest : SysuiTestCase() {
)
)
.isEqualTo(AuthenticationResult.FAILED)
+ val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
assertThat(isUnlocked).isFalse()
}
@Test
fun tryAutoConfirm_withAutoConfirmLongerPin_returnsFalseAndDoesNotUnlockDevice() =
testScope.runTest {
- val isUnlocked by collectLastValue(underTest.isUnlocked)
utils.authenticationRepository.apply {
setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
setAutoConfirmEnabled(true)
@@ -396,13 +262,13 @@ class AuthenticationInteractorTest : SysuiTestCase() {
)
)
.isEqualTo(AuthenticationResult.FAILED)
+ val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
assertThat(isUnlocked).isFalse()
}
@Test
fun tryAutoConfirm_withAutoConfirmCorrectPin_returnsTrueAndUnlocksDevice() =
testScope.runTest {
- val isUnlocked by collectLastValue(underTest.isUnlocked)
utils.authenticationRepository.apply {
setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
setAutoConfirmEnabled(true)
@@ -414,13 +280,13 @@ class AuthenticationInteractorTest : SysuiTestCase() {
)
)
.isEqualTo(AuthenticationResult.SUCCEEDED)
+ val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
assertThat(isUnlocked).isTrue()
}
@Test
fun tryAutoConfirm_withoutAutoConfirmButCorrectPin_returnsNullAndHasNoEffects() =
testScope.runTest {
- val isUnlocked by collectLastValue(underTest.isUnlocked)
utils.authenticationRepository.apply {
setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
setAutoConfirmEnabled(false)
@@ -432,26 +298,27 @@ class AuthenticationInteractorTest : SysuiTestCase() {
)
)
.isEqualTo(AuthenticationResult.SKIPPED)
+ val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
assertThat(isUnlocked).isFalse()
}
@Test
fun tryAutoConfirm_withoutCorrectPassword_returnsNullAndHasNoEffects() =
testScope.runTest {
- val isUnlocked by collectLastValue(underTest.isUnlocked)
utils.authenticationRepository.setAuthenticationMethod(
DataLayerAuthenticationMethodModel.Password
)
assertThat(underTest.authenticate("password".toList(), tryAutoConfirm = true))
.isEqualTo(AuthenticationResult.SKIPPED)
+ val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
assertThat(isUnlocked).isFalse()
}
@Test
fun throttling() =
testScope.runTest {
- val isUnlocked by collectLastValue(underTest.isUnlocked)
+ val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
val throttling by collectLastValue(underTest.throttling)
val isThrottled by collectLastValue(underTest.isThrottled)
utils.authenticationRepository.setAuthenticationMethod(
@@ -462,7 +329,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
assertThat(isThrottled).isFalse()
assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
assertThat(isUnlocked).isFalse()
assertThat(isThrottled).isFalse()
assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
@@ -605,8 +472,4 @@ class AuthenticationInteractorTest : SysuiTestCase() {
assertThat(hintedPinLength).isNull()
}
-
- private fun switchToScene(sceneKey: SceneKey) {
- sceneInteractor.changeScene(SceneModel(sceneKey), "reason")
- }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
index 92c8a395a696..a9ba36a9fde4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
@@ -47,13 +47,16 @@ class BouncerInteractorTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
- private val authenticationInteractor =
- utils.authenticationInteractor(
- repository = utils.authenticationRepository(),
- )
+ private val authenticationInteractor = utils.authenticationInteractor()
private val sceneInteractor = utils.sceneInteractor()
+ private val deviceEntryInteractor =
+ utils.deviceEntryInteractor(
+ authenticationInteractor = authenticationInteractor,
+ sceneInteractor = sceneInteractor,
+ )
private val underTest =
utils.bouncerInteractor(
+ deviceEntryInteractor = deviceEntryInteractor,
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
)
@@ -76,7 +79,7 @@ class BouncerInteractorTest : SysuiTestCase() {
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
runCurrent()
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
underTest.showOrUnlockDevice()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
@@ -111,7 +114,7 @@ class BouncerInteractorTest : SysuiTestCase() {
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
runCurrent()
utils.authenticationRepository.setAutoConfirmEnabled(true)
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
underTest.showOrUnlockDevice()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
@@ -148,7 +151,7 @@ class BouncerInteractorTest : SysuiTestCase() {
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
runCurrent()
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
underTest.showOrUnlockDevice()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
underTest.clearMessage()
@@ -180,7 +183,7 @@ class BouncerInteractorTest : SysuiTestCase() {
AuthenticationMethodModel.Password
)
runCurrent()
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
underTest.showOrUnlockDevice()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PASSWORD)
@@ -215,7 +218,7 @@ class BouncerInteractorTest : SysuiTestCase() {
AuthenticationMethodModel.Pattern
)
runCurrent()
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
underTest.showOrUnlockDevice()
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PATTERN)
@@ -268,7 +271,7 @@ class BouncerInteractorTest : SysuiTestCase() {
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
- utils.authenticationRepository.setUnlocked(true)
+ utils.deviceEntryRepository.setUnlocked(true)
runCurrent()
underTest.showOrUnlockDevice()
@@ -281,8 +284,8 @@ class BouncerInteractorTest : SysuiTestCase() {
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
- utils.authenticationRepository.setLockscreenEnabled(true)
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+ utils.deviceEntryRepository.setUnlocked(false)
underTest.showOrUnlockDevice()
@@ -298,7 +301,7 @@ class BouncerInteractorTest : SysuiTestCase() {
AuthenticationMethodModel.Password
)
runCurrent()
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
val customMessage = "Hello there!"
underTest.showOrUnlockDevice(customMessage)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
index 2f7dde02fdce..b5177e1587ee 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
@@ -37,17 +37,20 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
- private val authenticationInteractor =
- utils.authenticationInteractor(
- utils.authenticationRepository(),
- )
+ private val authenticationInteractor = utils.authenticationInteractor()
private val sceneInteractor = utils.sceneInteractor()
+ private val deviceEntryInteractor =
+ utils.deviceEntryInteractor(
+ authenticationInteractor = authenticationInteractor,
+ sceneInteractor = sceneInteractor,
+ )
private val underTest =
PinBouncerViewModel(
applicationContext = context,
viewModelScope = testScope.backgroundScope,
interactor =
utils.bouncerInteractor(
+ deviceEntryInteractor = deviceEntryInteractor,
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
index da2534d6fb14..b75355a82406 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
@@ -44,12 +44,15 @@ class BouncerViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
- private val authenticationInteractor =
- utils.authenticationInteractor(
- repository = utils.authenticationRepository,
+ private val authenticationInteractor = utils.authenticationInteractor()
+ private val deviceEntryInteractor =
+ utils.deviceEntryInteractor(
+ authenticationInteractor = authenticationInteractor,
+ sceneInteractor = utils.sceneInteractor(),
)
private val bouncerInteractor =
utils.bouncerInteractor(
+ deviceEntryInteractor = deviceEntryInteractor,
authenticationInteractor = authenticationInteractor,
sceneInteractor = utils.sceneInteractor(),
)
@@ -223,6 +226,8 @@ class BouncerViewModelTest : SysuiTestCase() {
DataLayerAuthenticationMethodModel.Pattern
}
)
- setLockscreenEnabled(model !is DomainLayerAuthenticationMethodModel.None)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(
+ model !is DomainLayerAuthenticationMethodModel.None
+ )
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
index c1b33542267b..0926399a8617 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
@@ -44,13 +44,16 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
- private val authenticationInteractor =
- utils.authenticationInteractor(
- repository = utils.authenticationRepository(),
- )
+ private val authenticationInteractor = utils.authenticationInteractor()
private val sceneInteractor = utils.sceneInteractor()
+ private val deviceEntryInteractor =
+ utils.deviceEntryInteractor(
+ authenticationInteractor = authenticationInteractor,
+ sceneInteractor = utils.sceneInteractor(),
+ )
private val bouncerInteractor =
utils.bouncerInteractor(
+ deviceEntryInteractor = deviceEntryInteractor,
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
)
@@ -139,7 +142,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
utils.authenticationRepository.setAuthenticationMethod(
AuthenticationMethodModel.Password
)
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
@@ -207,7 +210,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
private fun TestScope.lockDeviceAndOpenPasswordBouncer() {
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Password)
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
index bf109d9b2b61..2e7c9aaa67e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
@@ -47,13 +47,16 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
- private val authenticationInteractor =
- utils.authenticationInteractor(
- repository = utils.authenticationRepository(),
- )
+ private val authenticationInteractor = utils.authenticationInteractor()
private val sceneInteractor = utils.sceneInteractor()
+ private val deviceEntryInteractor =
+ utils.deviceEntryInteractor(
+ authenticationInteractor = authenticationInteractor,
+ sceneInteractor = utils.sceneInteractor(),
+ )
private val bouncerInteractor =
utils.bouncerInteractor(
+ deviceEntryInteractor = deviceEntryInteractor,
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
)
@@ -378,7 +381,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
private fun TestScope.lockDeviceAndOpenPatternBouncer() {
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pattern)
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
assertThat(collectLastValue(sceneInteractor.desiredScene).invoke())
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
index 2576204c247f..255bbe3ae231 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
@@ -47,12 +47,15 @@ class PinBouncerViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
private val sceneInteractor = utils.sceneInteractor()
- private val authenticationInteractor =
- utils.authenticationInteractor(
- repository = utils.authenticationRepository(),
+ private val authenticationInteractor = utils.authenticationInteractor()
+ private val deviceEntryInteractor =
+ utils.deviceEntryInteractor(
+ authenticationInteractor = authenticationInteractor,
+ sceneInteractor = utils.sceneInteractor(),
)
private val bouncerInteractor =
utils.bouncerInteractor(
+ deviceEntryInteractor = deviceEntryInteractor,
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
)
@@ -81,7 +84,7 @@ class PinBouncerViewModelTest : SysuiTestCase() {
val currentScene by collectLastValue(sceneInteractor.desiredScene)
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
@@ -103,7 +106,7 @@ class PinBouncerViewModelTest : SysuiTestCase() {
val message by collectLastValue(bouncerViewModel.message)
val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
@@ -358,7 +361,7 @@ class PinBouncerViewModelTest : SysuiTestCase() {
private fun TestScope.lockDeviceAndOpenPinBouncer() {
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
new file mode 100644
index 000000000000..8e8cbe4a7cf2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
@@ -0,0 +1,127 @@
+package com.android.systemui.deviceentry.data.repository
+
+import android.content.pm.UserInfo
+import androidx.test.filters.SmallTest
+import com.android.internal.widget.LockPatternUtils
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.scene.SceneTestUtils
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.user.data.repository.FakeUserRepository
+import com.android.systemui.util.mockito.argumentCaptor
+import com.android.systemui.util.mockito.whenever
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.MockitoAnnotations
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class DeviceEntryRepositoryTest : SysuiTestCase() {
+
+ @Mock private lateinit var lockPatternUtils: LockPatternUtils
+ @Mock private lateinit var keyguardBypassController: KeyguardBypassController
+ @Mock private lateinit var keyguardStateController: KeyguardStateController
+
+ private val testUtils = SceneTestUtils(this)
+ private val testScope = testUtils.testScope
+ private val userRepository = FakeUserRepository()
+
+ private lateinit var underTest: DeviceEntryRepository
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ userRepository.setUserInfos(USER_INFOS)
+ runBlocking { userRepository.setSelectedUserInfo(USER_INFOS[0]) }
+
+ underTest =
+ DeviceEntryRepositoryImpl(
+ applicationScope = testScope.backgroundScope,
+ backgroundDispatcher = testUtils.testDispatcher,
+ userRepository = userRepository,
+ lockPatternUtils = lockPatternUtils,
+ keyguardBypassController = keyguardBypassController,
+ keyguardStateController = keyguardStateController,
+ )
+ }
+
+ @Test
+ fun isUnlocked() =
+ testScope.runTest {
+ whenever(keyguardStateController.isUnlocked).thenReturn(false)
+ val isUnlocked by collectLastValue(underTest.isUnlocked)
+
+ runCurrent()
+ assertThat(isUnlocked).isFalse()
+
+ val captor = argumentCaptor<KeyguardStateController.Callback>()
+ Mockito.verify(keyguardStateController, Mockito.atLeastOnce())
+ .addCallback(captor.capture())
+
+ whenever(keyguardStateController.isUnlocked).thenReturn(true)
+ captor.value.onUnlockedChanged()
+ runCurrent()
+ assertThat(isUnlocked).isTrue()
+
+ whenever(keyguardStateController.isUnlocked).thenReturn(false)
+ captor.value.onKeyguardShowingChanged()
+ runCurrent()
+ assertThat(isUnlocked).isFalse()
+ }
+
+ @Test
+ fun isInsecureLockscreenEnabled() =
+ testScope.runTest {
+ whenever(lockPatternUtils.isLockScreenDisabled(USER_INFOS[0].id)).thenReturn(false)
+ whenever(lockPatternUtils.isLockScreenDisabled(USER_INFOS[1].id)).thenReturn(true)
+
+ userRepository.setSelectedUserInfo(USER_INFOS[0])
+ assertThat(underTest.isInsecureLockscreenEnabled()).isTrue()
+
+ userRepository.setSelectedUserInfo(USER_INFOS[1])
+ assertThat(underTest.isInsecureLockscreenEnabled()).isFalse()
+ }
+
+ @Test
+ fun isBypassEnabled_disabledInController() =
+ testScope.runTest {
+ whenever(keyguardBypassController.isBypassEnabled).thenAnswer { false }
+ whenever(keyguardBypassController.bypassEnabled).thenAnswer { false }
+ assertThat(underTest.isBypassEnabled()).isFalse()
+ }
+
+ @Test
+ fun isBypassEnabled_enabledInController() =
+ testScope.runTest {
+ whenever(keyguardBypassController.isBypassEnabled).thenAnswer { true }
+ whenever(keyguardBypassController.bypassEnabled).thenAnswer { true }
+ assertThat(underTest.isBypassEnabled()).isTrue()
+ }
+
+ companion object {
+ private val USER_INFOS =
+ listOf(
+ UserInfo(
+ /* id= */ 100,
+ /* name= */ "First user",
+ /* flags= */ 0,
+ ),
+ UserInfo(
+ /* id= */ 101,
+ /* name= */ "Second user",
+ /* flags= */ 0,
+ ),
+ )
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
new file mode 100644
index 000000000000..55582e123969
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
@@ -0,0 +1,234 @@
+package com.android.systemui.deviceentry.domain.interactor
+
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.authentication.data.model.AuthenticationMethodModel
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
+import com.android.systemui.scene.SceneTestUtils
+import com.android.systemui.scene.shared.model.SceneKey
+import com.android.systemui.scene.shared.model.SceneModel
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(JUnit4::class)
+class DeviceEntryInteractorTest : SysuiTestCase() {
+
+ private val utils = SceneTestUtils(this)
+ private val testScope = utils.testScope
+ private val repository: FakeDeviceEntryRepository = utils.deviceEntryRepository
+ private val sceneInteractor = utils.sceneInteractor()
+ private val authenticationInteractor = utils.authenticationInteractor()
+ private val underTest =
+ utils.deviceEntryInteractor(
+ repository = repository,
+ authenticationInteractor = authenticationInteractor,
+ sceneInteractor = sceneInteractor,
+ )
+
+ @Test
+ fun isUnlocked_whenAuthMethodIsNoneAndLockscreenDisabled_isTrue() =
+ testScope.runTest {
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+ utils.deviceEntryRepository.apply {
+ setInsecureLockscreenEnabled(false)
+
+ // Toggle isUnlocked, twice.
+ //
+ // This is done because the underTest.isUnlocked flow doesn't receive values from
+ // just changing the state above; the actual isUnlocked state needs to change to
+ // cause the logic under test to "pick up" the current state again.
+ //
+ // It is done twice to make sure that we don't actually change the isUnlocked state
+ // from what it originally was.
+ setUnlocked(!isUnlocked.value)
+ runCurrent()
+ setUnlocked(!isUnlocked.value)
+ runCurrent()
+ }
+
+ val isUnlocked by collectLastValue(underTest.isUnlocked)
+ assertThat(isUnlocked).isTrue()
+ }
+
+ @Test
+ fun isUnlocked_whenAuthMethodIsNoneAndLockscreenEnabled_isTrue() =
+ testScope.runTest {
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+
+ val isUnlocked by collectLastValue(underTest.isUnlocked)
+ assertThat(isUnlocked).isTrue()
+ }
+
+ @Test
+ fun isDeviceEntered_onLockscreenWithSwipe_isFalse() =
+ testScope.runTest {
+ val isDeviceEntered by collectLastValue(underTest.isDeviceEntered)
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+ switchToScene(SceneKey.Lockscreen)
+
+ assertThat(isDeviceEntered).isFalse()
+ }
+
+ @Test
+ fun isDeviceEntered_onShadeBeforeDismissingLockscreenWithSwipe_isFalse() =
+ testScope.runTest {
+ val isDeviceEntered by collectLastValue(underTest.isDeviceEntered)
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+ switchToScene(SceneKey.Lockscreen)
+ runCurrent()
+ switchToScene(SceneKey.Shade)
+
+ assertThat(isDeviceEntered).isFalse()
+ }
+
+ @Test
+ fun isDeviceEntered_afterDismissingLockscreenWithSwipe_isTrue() =
+ testScope.runTest {
+ val isDeviceEntered by collectLastValue(underTest.isDeviceEntered)
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+ switchToScene(SceneKey.Lockscreen)
+ runCurrent()
+ switchToScene(SceneKey.Gone)
+
+ assertThat(isDeviceEntered).isTrue()
+ }
+
+ @Test
+ fun isDeviceEntered_onShadeAfterDismissingLockscreenWithSwipe_isTrue() =
+ testScope.runTest {
+ val isDeviceEntered by collectLastValue(underTest.isDeviceEntered)
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+ switchToScene(SceneKey.Lockscreen)
+ runCurrent()
+ switchToScene(SceneKey.Gone)
+ runCurrent()
+ switchToScene(SceneKey.Shade)
+
+ assertThat(isDeviceEntered).isTrue()
+ }
+
+ @Test
+ fun isDeviceEntered_onBouncer_isFalse() =
+ testScope.runTest {
+ utils.authenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.Pattern
+ )
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+ switchToScene(SceneKey.Lockscreen)
+ runCurrent()
+ switchToScene(SceneKey.Bouncer)
+
+ val isDeviceEntered by collectLastValue(underTest.isDeviceEntered)
+ assertThat(isDeviceEntered).isFalse()
+ }
+
+ @Test
+ fun canSwipeToEnter_onLockscreenWithSwipe_isTrue() =
+ testScope.runTest {
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+ switchToScene(SceneKey.Lockscreen)
+
+ val canSwipeToEnter by collectLastValue(underTest.canSwipeToEnter)
+ assertThat(canSwipeToEnter).isTrue()
+ }
+
+ @Test
+ fun canSwipeToEnter_onLockscreenWithPin_isFalse() =
+ testScope.runTest {
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+ switchToScene(SceneKey.Lockscreen)
+
+ val canSwipeToEnter by collectLastValue(underTest.canSwipeToEnter)
+ assertThat(canSwipeToEnter).isFalse()
+ }
+
+ @Test
+ fun canSwipeToEnter_afterLockscreenDismissedInSwipeMode_isFalse() =
+ testScope.runTest {
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+ switchToScene(SceneKey.Lockscreen)
+ runCurrent()
+ switchToScene(SceneKey.Gone)
+
+ val canSwipeToEnter by collectLastValue(underTest.canSwipeToEnter)
+ assertThat(canSwipeToEnter).isFalse()
+ }
+
+ @Test
+ fun isAuthenticationRequired_lockedAndSecured_true() =
+ testScope.runTest {
+ utils.deviceEntryRepository.setUnlocked(false)
+ runCurrent()
+ utils.authenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.Password
+ )
+
+ assertThat(underTest.isAuthenticationRequired()).isTrue()
+ }
+
+ @Test
+ fun isAuthenticationRequired_lockedAndNotSecured_false() =
+ testScope.runTest {
+ utils.deviceEntryRepository.setUnlocked(false)
+ runCurrent()
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+
+ assertThat(underTest.isAuthenticationRequired()).isFalse()
+ }
+
+ @Test
+ fun isAuthenticationRequired_unlockedAndSecured_false() =
+ testScope.runTest {
+ utils.deviceEntryRepository.setUnlocked(true)
+ runCurrent()
+ utils.authenticationRepository.setAuthenticationMethod(
+ AuthenticationMethodModel.Password
+ )
+
+ assertThat(underTest.isAuthenticationRequired()).isFalse()
+ }
+
+ @Test
+ fun isAuthenticationRequired_unlockedAndNotSecured_false() =
+ testScope.runTest {
+ utils.deviceEntryRepository.setUnlocked(true)
+ runCurrent()
+ utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+
+ assertThat(underTest.isAuthenticationRequired()).isFalse()
+ }
+
+ @Test
+ fun isBypassEnabled_enabledInRepository_true() =
+ testScope.runTest {
+ utils.deviceEntryRepository.setBypassEnabled(true)
+ assertThat(underTest.isBypassEnabled()).isTrue()
+ }
+
+ @Test
+ fun isBypassEnabled_disabledInRepository_false() =
+ testScope.runTest {
+ utils.deviceEntryRepository.setBypassEnabled(false)
+ assertThat(underTest.isBypassEnabled()).isFalse()
+ }
+
+ private fun switchToScene(sceneKey: SceneKey) {
+ sceneInteractor.changeScene(SceneModel(sceneKey), "reason")
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
index 2691860bc25b..f93051c41b61 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/KeyguardRepositoryImplTest.kt
@@ -44,7 +44,6 @@ import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.DozeParameters
-import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
@@ -81,7 +80,6 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var biometricUnlockController: BiometricUnlockController
@Mock private lateinit var dozeTransitionListener: DozeTransitionListener
@Mock private lateinit var authController: AuthController
- @Mock private lateinit var keyguardBypassController: KeyguardBypassController
@Mock private lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
@Mock private lateinit var dreamOverlayCallbackController: DreamOverlayCallbackController
@Mock private lateinit var dozeParameters: DozeParameters
@@ -103,7 +101,6 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
screenLifecycle,
biometricUnlockController,
keyguardStateController,
- keyguardBypassController,
keyguardUpdateMonitor,
dozeTransitionListener,
dozeParameters,
@@ -213,23 +210,9 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun isBypassEnabled_disabledInController() {
- whenever(keyguardBypassController.isBypassEnabled).thenReturn(false)
- whenever(keyguardBypassController.bypassEnabled).thenReturn(false)
- assertThat(underTest.isBypassEnabled()).isFalse()
- }
-
- @Test
- fun isBypassEnabled_enabledInController() {
- whenever(keyguardBypassController.isBypassEnabled).thenReturn(true)
- whenever(keyguardBypassController.bypassEnabled).thenReturn(true)
- assertThat(underTest.isBypassEnabled()).isTrue()
- }
-
- @Test
fun isAodAvailable() = runTest {
val flow = underTest.isAodAvailable
- var isAodAvailable = collectLastValue(flow)
+ val isAodAvailable = collectLastValue(flow)
runCurrent()
val callback =
@@ -273,29 +256,6 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
}
@Test
- fun isKeyguardUnlocked() =
- testScope.runTest {
- whenever(keyguardStateController.isUnlocked).thenReturn(false)
- val isKeyguardUnlocked by collectLastValue(underTest.isKeyguardUnlocked)
-
- runCurrent()
- assertThat(isKeyguardUnlocked).isFalse()
-
- val captor = argumentCaptor<KeyguardStateController.Callback>()
- verify(keyguardStateController, atLeastOnce()).addCallback(captor.capture())
-
- whenever(keyguardStateController.isUnlocked).thenReturn(true)
- captor.value.onUnlockedChanged()
- runCurrent()
- assertThat(isKeyguardUnlocked).isTrue()
-
- whenever(keyguardStateController.isUnlocked).thenReturn(false)
- captor.value.onKeyguardShowingChanged()
- runCurrent()
- assertThat(isKeyguardUnlocked).isFalse()
- }
-
- @Test
fun isDozing() =
testScope.runTest {
underTest.setIsDozing(true)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
index 90e217f3418c..82c7fa4c4d12 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorTest.kt
@@ -15,8 +15,6 @@
*
*/
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
package com.android.systemui.keyguard.domain.interactor
import android.app.StatusBarManager
@@ -27,13 +25,11 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.flags.FakeFeatureFlags
+import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
-import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.shared.model.CameraLaunchSourceModel
import com.android.systemui.scene.SceneTestUtils
-import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.ObservableTransitionState
import com.android.systemui.scene.shared.model.SceneKey
import com.android.systemui.shade.data.repository.FakeShadeRepository
@@ -42,62 +38,53 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.onCompletion
-import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-import org.mockito.MockitoAnnotations
+@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RoboPilotTest
@RunWith(AndroidJUnit4::class)
class KeyguardInteractorTest : SysuiTestCase() {
- private lateinit var commandQueue: FakeCommandQueue
- private lateinit var featureFlags: FakeFeatureFlags
- private lateinit var testScope: TestScope
-
- private lateinit var underTest: KeyguardInteractor
- private lateinit var repository: FakeKeyguardRepository
- private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
- private lateinit var configurationRepository: FakeConfigurationRepository
- private lateinit var shadeRepository: FakeShadeRepository
- private lateinit var sceneInteractor: SceneInteractor
- private lateinit var transitionState: MutableStateFlow<ObservableTransitionState>
+
+ private val testUtils = SceneTestUtils(this)
+ private val testScope = testUtils.testScope
+ private val repository = testUtils.keyguardRepository
+ private val sceneInteractor = testUtils.sceneInteractor()
+ private val commandQueue = FakeCommandQueue()
+ private val featureFlags = FakeFeatureFlagsClassic().apply { set(FACE_AUTH_REFACTOR, true) }
+ private val bouncerRepository = FakeKeyguardBouncerRepository()
+ private val configurationRepository = FakeConfigurationRepository()
+ private val shadeRepository = FakeShadeRepository()
+ private val transitionState: MutableStateFlow<ObservableTransitionState> =
+ MutableStateFlow(ObservableTransitionState.Idle(SceneKey.Gone))
+
+ private val underTest =
+ KeyguardInteractor(
+ repository = repository,
+ commandQueue = commandQueue,
+ featureFlags = featureFlags,
+ sceneContainerFlags = testUtils.sceneContainerFlags,
+ deviceEntryRepository = testUtils.deviceEntryRepository,
+ bouncerRepository = bouncerRepository,
+ configurationRepository = configurationRepository,
+ shadeRepository = shadeRepository,
+ sceneInteractorProvider = { sceneInteractor },
+ )
@Before
fun setUp() {
- MockitoAnnotations.initMocks(this)
- featureFlags = FakeFeatureFlags().apply { set(FACE_AUTH_REFACTOR, true) }
- commandQueue = FakeCommandQueue()
- val sceneTestUtils = SceneTestUtils(this)
- testScope = sceneTestUtils.testScope
- repository = sceneTestUtils.keyguardRepository
- bouncerRepository = FakeKeyguardBouncerRepository()
- configurationRepository = FakeConfigurationRepository()
- shadeRepository = FakeShadeRepository()
- sceneInteractor = sceneTestUtils.sceneInteractor()
- transitionState = MutableStateFlow(ObservableTransitionState.Idle(SceneKey.Gone))
sceneInteractor.setTransitionState(transitionState)
- underTest =
- KeyguardInteractor(
- repository = repository,
- commandQueue = commandQueue,
- featureFlags = featureFlags,
- sceneContainerFlags = sceneTestUtils.sceneContainerFlags,
- bouncerRepository = bouncerRepository,
- configurationRepository = configurationRepository,
- shadeRepository = shadeRepository,
- sceneInteractorProvider = { sceneInteractor },
- )
}
@Test
fun onCameraLaunchDetected() =
testScope.runTest {
val flow = underTest.onCameraLaunchDetected
- var cameraLaunchSource = collectLastValue(flow)
+ val cameraLaunchSource = collectLastValue(flow)
runCurrent()
commandQueue.doForEachCallback {
@@ -175,7 +162,7 @@ class KeyguardInteractorTest : SysuiTestCase() {
@Test
fun keyguardVisibilityIsDefinedAsKeyguardShowingButNotOccluded() = runTest {
- var isVisible = collectLastValue(underTest.isKeyguardVisible)
+ val isVisible = collectLastValue(underTest.isKeyguardVisible)
repository.setKeyguardShowing(true)
repository.setKeyguardOccluded(false)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
index f2636c543844..591653ee214f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionScenariosTest.kt
@@ -1226,7 +1226,6 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
// GIVEN the keyguard is showing locked
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
- keyguardRepository.setKeyguardUnlocked(false)
runCurrent()
shadeRepository.setShadeModel(
ShadeModel(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
index 1681cfdce822..6e94691d42a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
@@ -37,10 +37,6 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
private val sceneInteractor = utils.sceneInteractor()
- private val authenticationInteractor =
- utils.authenticationInteractor(
- repository = utils.authenticationRepository(),
- )
private val underTest = createLockscreenSceneViewModel()
@@ -49,8 +45,8 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
testScope.runTest {
val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
- utils.authenticationRepository.setLockscreenEnabled(true)
- utils.authenticationRepository.setUnlocked(true)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+ utils.deviceEntryRepository.setUnlocked(true)
sceneInteractor.changeScene(SceneModel(SceneKey.Lockscreen), "reason")
assertThat(upTransitionSceneKey).isEqualTo(SceneKey.Gone)
@@ -61,7 +57,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
testScope.runTest {
val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
sceneInteractor.changeScene(SceneModel(SceneKey.Lockscreen), "reason")
assertThat(upTransitionSceneKey).isEqualTo(SceneKey.Bouncer)
@@ -88,7 +84,11 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
private fun createLockscreenSceneViewModel(): LockscreenSceneViewModel {
return LockscreenSceneViewModel(
applicationScope = testScope.backgroundScope,
- authenticationInteractor = authenticationInteractor,
+ deviceEntryInteractor =
+ utils.deviceEntryInteractor(
+ authenticationInteractor = utils.authenticationInteractor(),
+ sceneInteractor = utils.sceneInteractor(),
+ ),
communalInteractor = utils.communalInteractor(),
longPress =
KeyguardLongPressViewModel(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index 8ae89304974d..f1c99d71b4e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -48,11 +48,6 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
private val sceneInteractor = utils.sceneInteractor()
- private val authenticationInteractor =
- utils.authenticationInteractor(
- repository = utils.authenticationRepository(),
- )
-
private val mobileIconsInteractor = FakeMobileIconsInteractor(FakeMobileMappingsProxy(), mock())
private var mobileIconsViewModel: MobileIconsViewModel =
@@ -85,10 +80,17 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() {
broadcastDispatcher = fakeBroadcastDispatcher,
)
+ val authenticationInteractor = utils.authenticationInteractor()
+
underTest =
QuickSettingsSceneViewModel(
bouncerInteractor =
utils.bouncerInteractor(
+ deviceEntryInteractor =
+ utils.deviceEntryInteractor(
+ authenticationInteractor = authenticationInteractor,
+ sceneInteractor = sceneInteractor,
+ ),
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
),
@@ -101,7 +103,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() {
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
- utils.authenticationRepository.setUnlocked(true)
+ utils.deviceEntryRepository.setUnlocked(true)
runCurrent()
underTest.onContentClicked()
@@ -114,7 +116,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() {
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
runCurrent()
underTest.onContentClicked()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index 85bd92bf3b12..5259013afc95 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -83,7 +83,6 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
-
private val sceneContainerConfig = utils.fakeSceneContainerConfig()
private val sceneRepository =
utils.fakeSceneContainerRepository(
@@ -93,14 +92,12 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
utils.sceneInteractor(
repository = sceneRepository,
)
-
- private val authenticationRepository = utils.authenticationRepository()
- private val authenticationInteractor =
- utils.authenticationInteractor(
- repository = authenticationRepository,
+ private val authenticationInteractor = utils.authenticationInteractor()
+ private val deviceEntryInteractor =
+ utils.deviceEntryInteractor(
+ authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
)
-
private val communalInteractor = utils.communalInteractor()
private val transitionState =
@@ -116,6 +113,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
private val bouncerInteractor =
utils.bouncerInteractor(
+ deviceEntryInteractor = deviceEntryInteractor,
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
)
@@ -128,7 +126,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
private val lockscreenSceneViewModel =
LockscreenSceneViewModel(
applicationScope = testScope.backgroundScope,
- authenticationInteractor = authenticationInteractor,
+ deviceEntryInteractor = deviceEntryInteractor,
communalInteractor = communalInteractor,
longPress =
KeyguardLongPressViewModel(
@@ -178,12 +176,12 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
shadeSceneViewModel =
ShadeSceneViewModel(
applicationScope = testScope.backgroundScope,
- authenticationInteractor = authenticationInteractor,
+ deviceEntryInteractor = deviceEntryInteractor,
bouncerInteractor = bouncerInteractor,
shadeHeaderViewModel = shadeHeaderViewModel,
)
- authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
val displayTracker = FakeDisplayTracker(context)
val sysUiState = SysUiState(displayTracker)
@@ -191,6 +189,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
SceneContainerStartable(
applicationScope = testScope.backgroundScope,
sceneInteractor = sceneInteractor,
+ deviceEntryInteractor = deviceEntryInteractor,
authenticationInteractor = authenticationInteractor,
keyguardInteractor = keyguardInteractor,
flags = utils.sceneContainerFlags,
@@ -417,13 +416,13 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
// Set the lockscreen enabled bit _before_ set the auth method as the code picks up on the
// lockscreen enabled bit _after_ the auth method is changed and the lockscreen enabled bit
// is not an observable that can trigger a new evaluation.
- authenticationRepository.setLockscreenEnabled(
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(
authMethod !is DomainLayerAuthenticationMethodModel.None
)
- authenticationRepository.setAuthenticationMethod(authMethod.toDataLayer())
+ utils.authenticationRepository.setAuthenticationMethod(authMethod.toDataLayer())
if (!authMethod.isSecure) {
// When the auth method is not secure, the device is never considered locked.
- authenticationRepository.setUnlocked(true)
+ utils.deviceEntryRepository.setUnlocked(true)
}
runCurrent()
}
@@ -528,14 +527,14 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
.that(authMethod.isSecure)
.isTrue()
- authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
runCurrent()
}
/** Unlocks the device by entering the correct PIN. Ends up in the Gone scene. */
private fun TestScope.unlockDevice() {
assertWithMessage("Cannot unlock a device that's already unlocked!")
- .that(authenticationInteractor.isUnlocked.value)
+ .that(deviceEntryInteractor.isUnlocked.value)
.isFalse()
emulateUserDrivenTransition(SceneKey.Bouncer)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index 16fdf8e40ed1..00a20ccc1c0d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -59,17 +59,13 @@ class SceneContainerStartableTest : SysuiTestCase() {
private val testScope = utils.testScope
private val sceneInteractor = utils.sceneInteractor()
private val sceneContainerFlags = utils.sceneContainerFlags
- private val authenticationRepository = utils.authenticationRepository()
- private val authenticationInteractor =
- utils.authenticationInteractor(
- repository = authenticationRepository,
+ private val authenticationInteractor = utils.authenticationInteractor()
+ private val deviceEntryInteractor =
+ utils.deviceEntryInteractor(
+ authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
)
- private val keyguardRepository = utils.keyguardRepository
- private val keyguardInteractor =
- utils.keyguardInteractor(
- repository = keyguardRepository,
- )
+ private val keyguardInteractor = utils.keyguardInteractor()
private val sysUiState: SysUiState = mock()
private val falsingCollector: FalsingCollector = mock()
@@ -77,6 +73,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
SceneContainerStartable(
applicationScope = testScope.backgroundScope,
sceneInteractor = sceneInteractor,
+ deviceEntryInteractor = deviceEntryInteractor,
authenticationInteractor = authenticationInteractor,
keyguardInteractor = keyguardInteractor,
flags = sceneContainerFlags,
@@ -141,7 +138,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
underTest.start()
- authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
}
@@ -157,7 +154,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
assertThat(currentSceneKey).isEqualTo(SceneKey.Bouncer)
underTest.start()
- authenticationRepository.setUnlocked(true)
+ utils.deviceEntryRepository.setUnlocked(true)
assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
}
@@ -173,7 +170,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
underTest.start()
- authenticationRepository.setUnlocked(true)
+ utils.deviceEntryRepository.setUnlocked(true)
assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
}
@@ -189,7 +186,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
underTest.start()
- authenticationRepository.setUnlocked(true)
+ utils.deviceEntryRepository.setUnlocked(true)
assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
}
@@ -205,7 +202,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
assertThat(currentSceneKey).isEqualTo(SceneKey.Shade)
underTest.start()
- keyguardRepository.setWakefulnessModel(STARTING_TO_SLEEP)
+ utils.keyguardRepository.setWakefulnessModel(STARTING_TO_SLEEP)
assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
}
@@ -251,7 +248,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
underTest.start()
- keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
+ utils.keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
}
@@ -267,7 +264,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
underTest.start()
- keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
+ utils.keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
}
@@ -283,7 +280,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
underTest.start()
- keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
+ utils.keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
}
@@ -300,9 +297,9 @@ class SceneContainerStartableTest : SysuiTestCase() {
assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
underTest.start()
- authenticationRepository.setUnlocked(true)
+ utils.deviceEntryRepository.setUnlocked(true)
runCurrent()
- keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
+ utils.keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
}
@@ -389,11 +386,11 @@ class SceneContainerStartableTest : SysuiTestCase() {
runCurrent()
verify(falsingCollector).setShowingAod(false)
- keyguardRepository.setIsDozing(true)
+ utils.keyguardRepository.setIsDozing(true)
runCurrent()
verify(falsingCollector).setShowingAod(true)
- keyguardRepository.setIsDozing(false)
+ utils.keyguardRepository.setIsDozing(false)
runCurrent()
verify(falsingCollector, times(2)).setShowingAod(false)
}
@@ -401,7 +398,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun collectFalsingSignals_screenOnAndOff_aodUnavailable() =
testScope.runTest {
- keyguardRepository.setAodAvailable(false)
+ utils.keyguardRepository.setAodAvailable(false)
runCurrent()
prepareState(
initialSceneKey = SceneKey.Lockscreen,
@@ -414,31 +411,31 @@ class SceneContainerStartableTest : SysuiTestCase() {
verify(falsingCollector, never()).onScreenOnFromTouch()
verify(falsingCollector, never()).onScreenOff()
- keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
+ utils.keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
runCurrent()
verify(falsingCollector, times(1)).onScreenTurningOn()
verify(falsingCollector, never()).onScreenOnFromTouch()
verify(falsingCollector, never()).onScreenOff()
- keyguardRepository.setWakefulnessModel(ASLEEP)
+ utils.keyguardRepository.setWakefulnessModel(ASLEEP)
runCurrent()
verify(falsingCollector, times(1)).onScreenTurningOn()
verify(falsingCollector, never()).onScreenOnFromTouch()
verify(falsingCollector, times(1)).onScreenOff()
- keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_TAP)
+ utils.keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_TAP)
runCurrent()
verify(falsingCollector, times(1)).onScreenTurningOn()
verify(falsingCollector, times(1)).onScreenOnFromTouch()
verify(falsingCollector, times(1)).onScreenOff()
- keyguardRepository.setWakefulnessModel(ASLEEP)
+ utils.keyguardRepository.setWakefulnessModel(ASLEEP)
runCurrent()
verify(falsingCollector, times(1)).onScreenTurningOn()
verify(falsingCollector, times(1)).onScreenOnFromTouch()
verify(falsingCollector, times(2)).onScreenOff()
- keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
+ utils.keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
runCurrent()
verify(falsingCollector, times(2)).onScreenTurningOn()
verify(falsingCollector, times(1)).onScreenOnFromTouch()
@@ -448,7 +445,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
@Test
fun collectFalsingSignals_screenOnAndOff_aodAvailable() =
testScope.runTest {
- keyguardRepository.setAodAvailable(true)
+ utils.keyguardRepository.setAodAvailable(true)
runCurrent()
prepareState(
initialSceneKey = SceneKey.Lockscreen,
@@ -461,31 +458,31 @@ class SceneContainerStartableTest : SysuiTestCase() {
verify(falsingCollector, never()).onScreenOnFromTouch()
verify(falsingCollector, never()).onScreenOff()
- keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
+ utils.keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
runCurrent()
verify(falsingCollector, never()).onScreenTurningOn()
verify(falsingCollector, never()).onScreenOnFromTouch()
verify(falsingCollector, never()).onScreenOff()
- keyguardRepository.setWakefulnessModel(ASLEEP)
+ utils.keyguardRepository.setWakefulnessModel(ASLEEP)
runCurrent()
verify(falsingCollector, never()).onScreenTurningOn()
verify(falsingCollector, never()).onScreenOnFromTouch()
verify(falsingCollector, never()).onScreenOff()
- keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_TAP)
+ utils.keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_TAP)
runCurrent()
verify(falsingCollector, never()).onScreenTurningOn()
verify(falsingCollector, never()).onScreenOnFromTouch()
verify(falsingCollector, never()).onScreenOff()
- keyguardRepository.setWakefulnessModel(ASLEEP)
+ utils.keyguardRepository.setWakefulnessModel(ASLEEP)
runCurrent()
verify(falsingCollector, never()).onScreenTurningOn()
verify(falsingCollector, never()).onScreenOnFromTouch()
verify(falsingCollector, never()).onScreenOff()
- keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
+ utils.keyguardRepository.setWakefulnessModel(STARTING_TO_WAKE_FROM_POWER_BUTTON)
runCurrent()
verify(falsingCollector, never()).onScreenTurningOn()
verify(falsingCollector, never()).onScreenOnFromTouch()
@@ -521,8 +518,8 @@ class SceneContainerStartableTest : SysuiTestCase() {
): MutableStateFlow<ObservableTransitionState> {
assumeTrue(Flags.SCENE_CONTAINER_ENABLED)
sceneContainerFlags.enabled = true
- authenticationRepository.setUnlocked(isDeviceUnlocked)
- keyguardRepository.setBypassEnabled(isBypassEnabled)
+ utils.deviceEntryRepository.setUnlocked(isDeviceUnlocked)
+ utils.deviceEntryRepository.setBypassEnabled(isBypassEnabled)
val transitionStateFlow =
MutableStateFlow<ObservableTransitionState>(
ObservableTransitionState.Idle(SceneKey.Lockscreen)
@@ -534,8 +531,10 @@ class SceneContainerStartableTest : SysuiTestCase() {
sceneInteractor.onSceneChanged(SceneModel(it), "reason")
}
authenticationMethod?.let {
- authenticationRepository.setAuthenticationMethod(authenticationMethod.toDataLayer())
- authenticationRepository.setLockscreenEnabled(
+ utils.authenticationRepository.setAuthenticationMethod(
+ authenticationMethod.toDataLayer()
+ )
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(
authenticationMethod != AuthenticationMethodModel.None
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index 5c75d9cff10a..602bd5fded3d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -47,9 +47,10 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
private val utils = SceneTestUtils(this)
private val testScope = utils.testScope
private val sceneInteractor = utils.sceneInteractor()
- private val authenticationInteractor =
- utils.authenticationInteractor(
- repository = utils.authenticationRepository(),
+ private val authenticationInteractor = utils.authenticationInteractor()
+ private val deviceEntryInteractor =
+ utils.deviceEntryInteractor(
+ authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
)
@@ -88,9 +89,10 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
underTest =
ShadeSceneViewModel(
applicationScope = testScope.backgroundScope,
- authenticationInteractor = authenticationInteractor,
+ deviceEntryInteractor = deviceEntryInteractor,
bouncerInteractor =
utils.bouncerInteractor(
+ deviceEntryInteractor = deviceEntryInteractor,
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
),
@@ -103,7 +105,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
testScope.runTest {
val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
assertThat(upTransitionSceneKey).isEqualTo(SceneKey.Lockscreen)
}
@@ -113,7 +115,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
testScope.runTest {
val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
- utils.authenticationRepository.setUnlocked(true)
+ utils.deviceEntryRepository.setUnlocked(true)
assertThat(upTransitionSceneKey).isEqualTo(SceneKey.Gone)
}
@@ -122,7 +124,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
fun upTransitionSceneKey_authMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
testScope.runTest {
val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey)
- utils.authenticationRepository.setLockscreenEnabled(true)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
sceneInteractor.changeScene(SceneModel(SceneKey.Lockscreen), "reason")
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Lockscreen), "reason")
@@ -134,7 +136,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
fun upTransitionSceneKey_authMethodSwipe_lockscreenDismissed_goesToGone() =
testScope.runTest {
val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey)
- utils.authenticationRepository.setLockscreenEnabled(true)
+ utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
sceneInteractor.changeScene(SceneModel(SceneKey.Gone), "reason")
sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone), "reason")
@@ -147,7 +149,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
- utils.authenticationRepository.setUnlocked(true)
+ utils.deviceEntryRepository.setUnlocked(true)
runCurrent()
underTest.onContentClicked()
@@ -160,7 +162,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
testScope.runTest {
val currentScene by collectLastValue(sceneInteractor.desiredScene)
utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
- utils.authenticationRepository.setUnlocked(false)
+ utils.deviceEntryRepository.setUnlocked(false)
runCurrent()
underTest.onContentClicked()
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
index f2e45281da93..4fc3e3f66e6d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
@@ -24,20 +24,19 @@ import com.android.systemui.authentication.data.model.AuthenticationMethodModel
import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
import com.android.systemui.authentication.shared.model.AuthenticationResultModel
import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
+import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
class FakeAuthenticationRepository(
+ private val deviceEntryRepository: FakeDeviceEntryRepository,
private val currentTime: () -> Long,
) : AuthenticationRepository {
private val _isAutoConfirmEnabled = MutableStateFlow(false)
override val isAutoConfirmEnabled: StateFlow<Boolean> = _isAutoConfirmEnabled.asStateFlow()
- private val _isUnlocked = MutableStateFlow(false)
- override val isUnlocked: StateFlow<Boolean> = _isUnlocked.asStateFlow()
-
override val hintedPinLength: Int = HINTING_PIN_LENGTH
private val _isPatternVisible = MutableStateFlow(true)
@@ -53,7 +52,6 @@ class FakeAuthenticationRepository(
override val minPatternLength: Int = 4
- private var isLockscreenEnabled = true
private var failedAttemptCount = 0
private var throttlingEndTimestamp = 0L
private var credentialOverride: List<Any>? = null
@@ -72,13 +70,9 @@ class FakeAuthenticationRepository(
credentialOverride = pin
}
- override suspend fun isLockscreenEnabled(): Boolean {
- return isLockscreenEnabled
- }
-
override suspend fun reportAuthenticationAttempt(isSuccessful: Boolean) {
failedAttemptCount = if (isSuccessful) 0 else failedAttemptCount + 1
- _isUnlocked.value = isSuccessful
+ deviceEntryRepository.setUnlocked(isSuccessful)
}
override suspend fun getPinLength(): Int {
@@ -97,18 +91,10 @@ class FakeAuthenticationRepository(
_throttling.value = throttlingModel
}
- fun setUnlocked(isUnlocked: Boolean) {
- _isUnlocked.value = isUnlocked
- }
-
fun setAutoConfirmEnabled(isEnabled: Boolean) {
_isAutoConfirmEnabled.value = isEnabled
}
- fun setLockscreenEnabled(isLockscreenEnabled: Boolean) {
- this.isLockscreenEnabled = isLockscreenEnabled
- }
-
override suspend fun setThrottleDuration(durationMs: Int) {
throttlingEndTimestamp = if (durationMs > 0) currentTime() + durationMs else 0
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
new file mode 100644
index 000000000000..5e60a09e006b
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
@@ -0,0 +1,35 @@
+package com.android.systemui.deviceentry.data.repository
+
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
+
+/** Fake implementation of [DeviceEntryRepository] */
+class FakeDeviceEntryRepository : DeviceEntryRepository {
+
+ private var isInsecureLockscreenEnabled = true
+ private var isBypassEnabled = false
+
+ private val _isUnlocked = MutableStateFlow(false)
+ override val isUnlocked: StateFlow<Boolean> = _isUnlocked.asStateFlow()
+
+ override fun isBypassEnabled(): Boolean {
+ return isBypassEnabled
+ }
+
+ override suspend fun isInsecureLockscreenEnabled(): Boolean {
+ return isInsecureLockscreenEnabled
+ }
+
+ fun setUnlocked(isUnlocked: Boolean) {
+ _isUnlocked.value = isUnlocked
+ }
+
+ fun setInsecureLockscreenEnabled(isLockscreenEnabled: Boolean) {
+ this.isInsecureLockscreenEnabled = isLockscreenEnabled
+ }
+
+ fun setBypassEnabled(isBypassEnabled: Boolean) {
+ this.isBypassEnabled = isBypassEnabled
+ }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index a5f5d52ef56c..aa52609d6d47 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -63,9 +63,6 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
private val _isKeyguardShowing = MutableStateFlow(false)
override val isKeyguardShowing: Flow<Boolean> = _isKeyguardShowing
- private val _isKeyguardUnlocked = MutableStateFlow(false)
- override val isKeyguardUnlocked: StateFlow<Boolean> = _isKeyguardUnlocked.asStateFlow()
-
private val _isKeyguardOccluded = MutableStateFlow(false)
override val isKeyguardOccluded: Flow<Boolean> = _isKeyguardOccluded
@@ -150,11 +147,6 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
return _isKeyguardShowing.value
}
- private var _isBypassEnabled = false
- override fun isBypassEnabled(): Boolean {
- return _isBypassEnabled
- }
-
override fun setAnimateDozingTransitions(animate: Boolean) {
_animateBottomAreaDozingTransitions.tryEmit(animate)
}
@@ -252,14 +244,6 @@ class FakeKeyguardRepository @Inject constructor() : KeyguardRepository {
_statusBarState.value = state
}
- fun setKeyguardUnlocked(isUnlocked: Boolean) {
- _isKeyguardUnlocked.value = isUnlocked
- }
-
- fun setBypassEnabled(isEnabled: Boolean) {
- _isBypassEnabled = isEnabled
- }
-
fun setScreenModel(screenModel: ScreenModel) {
_screenModel.value = screenModel
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
index 2e3bb2b545d8..1cae09b794b8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardInteractorFactory.kt
@@ -19,6 +19,7 @@ package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
+import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
@@ -42,6 +43,7 @@ object KeyguardInteractorFactory {
sceneContainerFlags: SceneContainerFlags = FakeSceneContainerFlags(),
repository: FakeKeyguardRepository = FakeKeyguardRepository(),
commandQueue: FakeCommandQueue = FakeCommandQueue(),
+ deviceEntryRepository: FakeDeviceEntryRepository = FakeDeviceEntryRepository(),
bouncerRepository: FakeKeyguardBouncerRepository = FakeKeyguardBouncerRepository(),
configurationRepository: FakeConfigurationRepository = FakeConfigurationRepository(),
shadeRepository: FakeShadeRepository = FakeShadeRepository(),
@@ -52,6 +54,7 @@ object KeyguardInteractorFactory {
commandQueue = commandQueue,
featureFlags = featureFlags,
sceneContainerFlags = sceneContainerFlags,
+ deviceEntryRepository = deviceEntryRepository,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
shadeRepository = shadeRepository,
@@ -60,6 +63,7 @@ object KeyguardInteractorFactory {
commandQueue = commandQueue,
featureFlags = featureFlags,
sceneContainerFlags = sceneContainerFlags,
+ deviceEntryRepository = deviceEntryRepository,
bouncerRepository = bouncerRepository,
configurationRepository = configurationRepository,
shadeRepository = shadeRepository,
@@ -69,7 +73,7 @@ object KeyguardInteractorFactory {
}
/** Provide defaults, otherwise tests will throw an error */
- fun createFakeFeatureFlags(): FakeFeatureFlags {
+ private fun createFakeFeatureFlags(): FakeFeatureFlags {
return FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, false) }
}
@@ -78,6 +82,7 @@ object KeyguardInteractorFactory {
val commandQueue: FakeCommandQueue,
val featureFlags: FakeFeatureFlags,
val sceneContainerFlags: SceneContainerFlags,
+ val deviceEntryRepository: FakeDeviceEntryRepository,
val bouncerRepository: FakeKeyguardBouncerRepository,
val configurationRepository: FakeConfigurationRepository,
val shadeRepository: FakeShadeRepository,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index 69c89e8f4af6..179206ff87b1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -34,6 +34,9 @@ import com.android.systemui.common.ui.data.repository.FakeConfigurationRepositor
import com.android.systemui.communal.data.repository.FakeCommunalRepository
import com.android.systemui.communal.data.repository.FakeCommunalWidgetRepository
import com.android.systemui.communal.domain.interactor.CommunalInteractor
+import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
+import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.flags.FakeFeatureFlagsClassic
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeCommandQueue
@@ -73,16 +76,10 @@ class SceneTestUtils(
val testScope = TestScope(testDispatcher)
val featureFlags = FakeFeatureFlagsClassic().apply { set(Flags.FACE_AUTH_REFACTOR, false) }
val sceneContainerFlags = FakeSceneContainerFlags().apply { enabled = true }
- private val userRepository: UserRepository by lazy {
- FakeUserRepository().apply {
- val users = listOf(UserInfo(/* id= */ 0, "name", /* flags= */ 0))
- setUserInfos(users)
- runBlocking { setSelectedUserInfo(users.first()) }
- }
- }
-
+ val deviceEntryRepository: FakeDeviceEntryRepository by lazy { FakeDeviceEntryRepository() }
val authenticationRepository: FakeAuthenticationRepository by lazy {
FakeAuthenticationRepository(
+ deviceEntryRepository = deviceEntryRepository,
currentTime = { testScope.currentTime },
)
}
@@ -103,6 +100,14 @@ class SceneTestUtils(
}
val powerRepository: FakePowerRepository by lazy { FakePowerRepository() }
+ private val userRepository: UserRepository by lazy {
+ FakeUserRepository().apply {
+ val users = listOf(UserInfo(/* id= */ 0, "name", /* flags= */ 0))
+ setUserInfos(users)
+ runBlocking { setSelectedUserInfo(users.first()) }
+ }
+ }
+
private val context = test.context
private val falsingCollectorFake: FalsingCollector by lazy { FalsingCollectorFake() }
@@ -145,31 +150,41 @@ class SceneTestUtils(
)
}
- fun authenticationRepository(): FakeAuthenticationRepository {
- return authenticationRepository
+ fun deviceEntryInteractor(
+ repository: DeviceEntryRepository = deviceEntryRepository,
+ authenticationInteractor: AuthenticationInteractor,
+ sceneInteractor: SceneInteractor,
+ ): DeviceEntryInteractor {
+ return DeviceEntryInteractor(
+ applicationScope = applicationScope(),
+ repository = repository,
+ authenticationInteractor = authenticationInteractor,
+ sceneInteractor = sceneInteractor,
+ )
}
fun authenticationInteractor(
- repository: AuthenticationRepository,
- sceneInteractor: SceneInteractor = sceneInteractor(),
+ repository: AuthenticationRepository = authenticationRepository,
): AuthenticationInteractor {
return AuthenticationInteractor(
applicationScope = applicationScope(),
repository = repository,
backgroundDispatcher = testDispatcher,
userRepository = userRepository,
- keyguardRepository = keyguardRepository,
- sceneInteractor = sceneInteractor,
+ deviceEntryRepository = deviceEntryRepository,
clock = mock { whenever(elapsedRealtime()).thenAnswer { testScope.currentTime } }
)
}
- fun keyguardInteractor(repository: KeyguardRepository): KeyguardInteractor {
+ fun keyguardInteractor(
+ repository: KeyguardRepository = keyguardRepository
+ ): KeyguardInteractor {
return KeyguardInteractor(
repository = repository,
commandQueue = FakeCommandQueue(),
featureFlags = featureFlags,
sceneContainerFlags = sceneContainerFlags,
+ deviceEntryRepository = FakeDeviceEntryRepository(),
bouncerRepository = FakeKeyguardBouncerRepository(),
configurationRepository = FakeConfigurationRepository(),
shadeRepository = FakeShadeRepository(),
@@ -185,6 +200,7 @@ class SceneTestUtils(
}
fun bouncerInteractor(
+ deviceEntryInteractor: DeviceEntryInteractor,
authenticationInteractor: AuthenticationInteractor,
sceneInteractor: SceneInteractor,
): BouncerInteractor {
@@ -192,6 +208,7 @@ class SceneTestUtils(
applicationScope = applicationScope(),
applicationContext = context,
repository = BouncerRepository(),
+ deviceEntryInteractor = deviceEntryInteractor,
authenticationInteractor = authenticationInteractor,
sceneInteractor = sceneInteractor,
flags = sceneContainerFlags,