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 70b43713599bb..a9779663cc7c5 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 @@ -63,14 +63,6 @@ interface AuthenticationRepository { */ val isUnlocked: StateFlow - /** - * 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. - */ - val isBypassEnabled: StateFlow - /** * Whether the auto confirm feature is enabled for the currently-selected user. * @@ -113,9 +105,6 @@ interface AuthenticationRepository { */ suspend fun isLockscreenEnabled(): Boolean - /** See [isBypassEnabled]. */ - fun setBypassEnabled(isBypassEnabled: Boolean) - /** Reports an authentication attempt. */ suspend fun reportAuthenticationAttempt(isSuccessful: Boolean) @@ -157,7 +146,7 @@ constructor( private val lockPatternUtils: LockPatternUtils, ) : AuthenticationRepository { - override val isUnlocked: StateFlow = keyguardRepository.isKeyguardUnlocked + override val isUnlocked = keyguardRepository.isKeyguardUnlocked override suspend fun isLockscreenEnabled(): Boolean { return withContext(backgroundDispatcher) { @@ -166,9 +155,6 @@ constructor( } } - private val _isBypassEnabled = MutableStateFlow(false) - override val isBypassEnabled: StateFlow = _isBypassEnabled.asStateFlow() - override val isAutoConfirmEnabled: StateFlow = userRepository.selectedUserInfo .map { it.id } @@ -225,10 +211,6 @@ constructor( } } - override fun setBypassEnabled(isBypassEnabled: Boolean) { - _isBypassEnabled.value = isBypassEnabled - } - override suspend fun reportAuthenticationAttempt(isSuccessful: Boolean) { val selectedUserId = userRepository.selectedUserId withContext(backgroundDispatcher) { 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 3283e406ddb04..b482977bde679 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 @@ -24,6 +24,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.user.data.repository.UserRepository import com.android.systemui.util.time.SystemClock import javax.inject.Inject @@ -51,6 +52,7 @@ constructor( private val repository: AuthenticationRepository, @Background private val backgroundDispatcher: CoroutineDispatcher, private val userRepository: UserRepository, + private val keyguardRepository: KeyguardRepository, private val clock: SystemClock, ) { /** @@ -76,14 +78,6 @@ constructor( initialValue = true, ) - /** - * 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. - */ - val isBypassEnabled: StateFlow = repository.isBypassEnabled - /** The current authentication throttling state, only meaningful if [isThrottled] is `true`. */ val throttling: StateFlow = repository.throttling @@ -155,6 +149,16 @@ constructor( 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. * @@ -218,11 +222,6 @@ constructor( return authenticationResult.isSuccessful } - /** See [isBypassEnabled]. */ - fun toggleBypassEnabled() { - repository.setBypassEnabled(!repository.isBypassEnabled.value) - } - /** Starts refreshing the throttling state every second. */ private suspend fun startThrottlingCountdown() { cancelCountdown() 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 d119920e1a422..42bee4a3bdcd2 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 @@ -42,6 +42,7 @@ 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 javax.inject.Inject import kotlinx.coroutines.CoroutineDispatcher @@ -171,6 +172,14 @@ 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) @@ -206,6 +215,7 @@ constructor( wakefulnessLifecycle: WakefulnessLifecycle, biometricUnlockController: BiometricUnlockController, private val keyguardStateController: KeyguardStateController, + private val keyguardBypassController: KeyguardBypassController, private val keyguardUpdateMonitor: KeyguardUpdateMonitor, private val dozeTransitionListener: DozeTransitionListener, private val dozeParameters: DozeParameters, @@ -252,23 +262,17 @@ constructor( override val isAodAvailable: Flow = conflatedCallbackFlow { val callback = - object : DozeParameters.Callback { - override fun onAlwaysOnChange() { - trySendWithFailureLogging( - dozeParameters.getAlwaysOn(), - TAG, - "updated isAodAvailable" - ) - } + DozeParameters.Callback { + trySendWithFailureLogging( + dozeParameters.alwaysOn, + TAG, + "updated isAodAvailable" + ) } dozeParameters.addCallback(callback) // Adding the callback does not send an initial update. - trySendWithFailureLogging( - dozeParameters.getAlwaysOn(), - TAG, - "initial isAodAvailable" - ) + trySendWithFailureLogging(dozeParameters.alwaysOn, TAG, "initial isAodAvailable") awaitClose { dozeParameters.removeCallback(callback) } } @@ -464,6 +468,10 @@ constructor( return keyguardStateController.isShowing } + override fun isBypassEnabled(): Boolean { + return keyguardBypassController.bypassEnabled + } + override val statusBarState: Flow = conflatedCallbackFlow { val callback = object : StatusBarStateController.StateListener { diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt index 285ff74f8b2e2..b23c4ec9aa8bc 100644 --- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt +++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartable.kt @@ -77,7 +77,7 @@ constructor( authenticationInteractor.isUnlocked .map { isUnlocked -> val currentSceneKey = sceneInteractor.currentScene(CONTAINER_NAME).value.key - val isBypassEnabled = authenticationInteractor.isBypassEnabled.value + val isBypassEnabled = authenticationInteractor.isBypassEnabled() when { isUnlocked -> when (currentSceneKey) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt index ff1b31d8848f5..924aac4e70bef 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt @@ -50,12 +50,6 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr @DevicePostureInt private var postureState: Int = DEVICE_POSTURE_UNKNOWN private var pendingUnlock: PendingUnlock? = null private val listeners = mutableListOf() - private val postureCallback = DevicePostureController.Callback { posture -> - if (postureState != posture) { - postureState = posture - notifyListeners() - } - } private val faceAuthEnabledChangedCallback = object : KeyguardStateController.Callback { override fun onFaceAuthEnabledChanged() = notifyListeners() } @@ -162,10 +156,8 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr val dismissByDefault = if (context.resources.getBoolean( com.android.internal.R.bool.config_faceAuthDismissesKeyguard)) 1 else 0 - tunerService.addTunable(object : TunerService.Tunable { - override fun onTuningChanged(key: String?, newValue: String?) { - bypassEnabled = tunerService.getValue(key, dismissByDefault) != 0 - } + tunerService.addTunable({ key, _ -> + bypassEnabled = tunerService.getValue(key, dismissByDefault) != 0 }, Settings.Secure.FACE_UNLOCK_DISMISSES_KEYGUARD) lockscreenUserManager.addUserChangedListener( object : NotificationLockscreenUserManager.UserChangedListener { @@ -281,8 +273,6 @@ open class KeyguardBypassController : Dumpable, StackScrollAlgorithm.BypassContr } companion object { - const val BYPASS_FADE_DURATION = 67 - private const val FACE_UNLOCK_BYPASS_NO_OVERRIDE = 0 private const val FACE_UNLOCK_BYPASS_ALWAYS = 1 private const val FACE_UNLOCK_BYPASS_NEVER = 2 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 c223c5af6079c..a6ad4b24b63dd 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 @@ -102,19 +102,6 @@ class AuthenticationInteractorTest : SysuiTestCase() { assertThat(isUnlocked).isFalse() } - @Test - fun toggleBypassEnabled() = - testScope.runTest { - val isBypassEnabled by collectLastValue(underTest.isBypassEnabled) - assertThat(isBypassEnabled).isFalse() - - underTest.toggleBypassEnabled() - assertThat(isBypassEnabled).isTrue() - - underTest.toggleBypassEnabled() - assertThat(isBypassEnabled).isFalse() - } - @Test fun isAuthenticationRequired_lockedAndSecured_true() = testScope.runTest { 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 e9f0d561371c0..f541815d2711b 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 @@ -41,6 +41,7 @@ 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.argumentCaptor import com.android.systemui.util.mockito.whenever @@ -73,6 +74,7 @@ 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 @@ -92,6 +94,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { wakefulnessLifecycle, biometricUnlockController, keyguardStateController, + keyguardBypassController, keyguardUpdateMonitor, dozeTransitionListener, dozeParameters, @@ -185,6 +188,20 @@ class KeyguardRepositoryImplTest : SysuiTestCase() { job.cancel() } + @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 diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt index 3e9ddcb06389b..5638d708cf304 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SystemUiDefaultSceneContainerStartableTest.kt @@ -28,7 +28,6 @@ import com.android.systemui.scene.shared.model.SceneContainerNames 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.flow.map import kotlinx.coroutines.test.runTest import org.junit.Before @@ -36,7 +35,6 @@ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 -@OptIn(ExperimentalCoroutinesApi::class) @SmallTest @RunWith(JUnit4::class) class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() { @@ -385,7 +383,7 @@ class SystemUiDefaultSceneContainerStartableTest : SysuiTestCase() { ) { featureFlags.set(Flags.SCENE_CONTAINER, isFeatureEnabled) authenticationRepository.setUnlocked(isDeviceUnlocked) - authenticationRepository.setBypassEnabled(isBypassEnabled) + keyguardRepository.setBypassEnabled(isBypassEnabled) initialSceneKey?.let { sceneInteractor.setCurrentScene(SceneContainerNames.SYSTEM_UI_DEFAULT, SceneModel(it)) } 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 28892baec3c5c..c2e1ac70af80d 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 @@ -31,9 +31,6 @@ class FakeAuthenticationRepository( private val currentTime: () -> Long, ) : AuthenticationRepository { - private val _isBypassEnabled = MutableStateFlow(false) - override val isBypassEnabled: StateFlow = _isBypassEnabled - private val _isAutoConfirmEnabled = MutableStateFlow(false) override val isAutoConfirmEnabled: StateFlow = _isAutoConfirmEnabled.asStateFlow() @@ -85,10 +82,6 @@ class FakeAuthenticationRepository( return (credentialOverride ?: DEFAULT_PIN).size } - override fun setBypassEnabled(isBypassEnabled: Boolean) { - _isBypassEnabled.value = isBypassEnabled - } - override suspend fun getFailedAuthenticationAttemptCount(): Int { return failedAttemptCount } 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 63097401bc5a2..b9d098fe2851a 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 @@ -114,6 +114,11 @@ class FakeKeyguardRepository : KeyguardRepository { return _isKeyguardShowing.value } + private var _isBypassEnabled = false + override fun isBypassEnabled(): Boolean { + return _isBypassEnabled + } + override fun setAnimateDozingTransitions(animate: Boolean) { _animateBottomAreaDozingTransitions.tryEmit(animate) } @@ -198,6 +203,10 @@ class FakeKeyguardRepository : KeyguardRepository { _isKeyguardUnlocked.value = isUnlocked } + fun setBypassEnabled(isEnabled: Boolean) { + _isBypassEnabled = isEnabled + } + override fun isUdfpsSupported(): Boolean { return _isUdfpsSupported.value } 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 47e1daf4008c5..9317981304995 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 @@ -142,6 +142,7 @@ class SceneTestUtils( repository = repository, backgroundDispatcher = testDispatcher, userRepository = userRepository, + keyguardRepository = keyguardRepository, clock = mock { whenever(elapsedRealtime()).thenAnswer { testScope.currentTime } } ) }