Merge "Trigger face auth whenever user switching has completed." into udc-qpr-dev
This commit is contained in:
@@ -109,6 +109,18 @@ interface DeviceEntryFaceAuthRepository {
|
||||
/** Set whether face authentication should be locked out or not */
|
||||
fun lockoutFaceAuth()
|
||||
|
||||
/**
|
||||
* Cancel current face authentication and prevent it from running until [resumeFaceAuth] is
|
||||
* invoked.
|
||||
*/
|
||||
fun pauseFaceAuth()
|
||||
|
||||
/**
|
||||
* Allow face auth paused using [pauseFaceAuth] to run again. The next invocation to
|
||||
* [authenticate] will run as long as other gating conditions don't stop it from running.
|
||||
*/
|
||||
fun resumeFaceAuth()
|
||||
|
||||
/**
|
||||
* Trigger face authentication.
|
||||
*
|
||||
@@ -186,6 +198,15 @@ constructor(
|
||||
override val isAuthRunning: StateFlow<Boolean>
|
||||
get() = _isAuthRunning
|
||||
|
||||
private val faceAuthPaused = MutableStateFlow(false)
|
||||
override fun pauseFaceAuth() {
|
||||
faceAuthPaused.value = true
|
||||
}
|
||||
|
||||
override fun resumeFaceAuth() {
|
||||
faceAuthPaused.value = false
|
||||
}
|
||||
|
||||
private val keyguardSessionId: InstanceId?
|
||||
get() = sessionTracker.getSessionId(StatusBarManager.SESSION_KEYGUARD)
|
||||
|
||||
@@ -329,11 +350,7 @@ constructor(
|
||||
"isFaceAuthenticationEnabled",
|
||||
tableLogBuffer
|
||||
),
|
||||
logAndObserve(
|
||||
userRepository.userSwitchingInProgress.isFalse(),
|
||||
"userSwitchingNotInProgress",
|
||||
tableLogBuffer
|
||||
),
|
||||
logAndObserve(faceAuthPaused.isFalse(), "faceAuthIsNotPaused", tableLogBuffer),
|
||||
logAndObserve(
|
||||
keyguardRepository.isKeyguardGoingAway.isFalse(),
|
||||
"keyguardNotGoingAway",
|
||||
@@ -454,7 +471,6 @@ constructor(
|
||||
}
|
||||
|
||||
private fun handleFaceCancellationError() {
|
||||
cancelNotReceivedHandlerJob?.cancel()
|
||||
applicationScope.launch {
|
||||
faceAuthRequestedWhileCancellation?.let {
|
||||
faceAuthLogger.launchingQueuedFaceAuthRequest(it)
|
||||
@@ -483,6 +499,7 @@ constructor(
|
||||
}
|
||||
|
||||
private fun onFaceAuthRequestCompleted() {
|
||||
cancelNotReceivedHandlerJob?.cancel()
|
||||
cancellationInProgress = false
|
||||
_isAuthRunning.value = false
|
||||
authCancellationSignal = null
|
||||
|
||||
@@ -56,6 +56,9 @@ class NoopDeviceEntryFaceAuthRepository @Inject constructor() : DeviceEntryFaceA
|
||||
get() = emptyFlow()
|
||||
|
||||
override fun lockoutFaceAuth() = Unit
|
||||
override fun pauseFaceAuth() = Unit
|
||||
|
||||
override fun resumeFaceAuth() = Unit
|
||||
|
||||
/**
|
||||
* Trigger face authentication.
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.android.systemui.keyguard.shared.model.ErrorFaceAuthenticationStatus
|
||||
import com.android.systemui.keyguard.shared.model.FaceAuthenticationStatus
|
||||
import com.android.systemui.keyguard.shared.model.TransitionState
|
||||
import com.android.systemui.log.FaceAuthenticationLogger
|
||||
import com.android.systemui.user.data.repository.UserRepository
|
||||
import com.android.systemui.util.kotlin.pairwise
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
@@ -49,6 +50,7 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* Encapsulates business logic related face authentication being triggered for device entry from
|
||||
@@ -69,6 +71,7 @@ constructor(
|
||||
private val faceAuthenticationLogger: FaceAuthenticationLogger,
|
||||
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
|
||||
private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
|
||||
private val userRepository: UserRepository,
|
||||
) : CoreStartable, KeyguardFaceAuthInteractor {
|
||||
|
||||
private val listeners: MutableList<FaceAuthenticationListener> = mutableListOf()
|
||||
@@ -128,6 +131,23 @@ constructor(
|
||||
}
|
||||
}
|
||||
.launchIn(applicationScope)
|
||||
|
||||
// User switching should stop face auth and then when it is complete we should trigger face
|
||||
// auth so that the switched user can unlock the device with face auth.
|
||||
userRepository.userSwitchingInProgress
|
||||
.pairwise(false)
|
||||
.onEach { (wasSwitching, isSwitching) ->
|
||||
if (!wasSwitching && isSwitching) {
|
||||
repository.pauseFaceAuth()
|
||||
} else if (wasSwitching && !isSwitching) {
|
||||
repository.resumeFaceAuth()
|
||||
runFaceAuth(
|
||||
FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING,
|
||||
fallbackToDetect = true
|
||||
)
|
||||
}
|
||||
}
|
||||
.launchIn(applicationScope)
|
||||
}
|
||||
|
||||
override fun onSwipeUpOnBouncer() {
|
||||
@@ -199,8 +219,10 @@ constructor(
|
||||
} else {
|
||||
faceAuthenticationStatusOverride.value = null
|
||||
applicationScope.launch {
|
||||
faceAuthenticationLogger.authRequested(uiEvent)
|
||||
repository.authenticate(uiEvent, fallbackToDetection = fallbackToDetect)
|
||||
withContext(mainDispatcher) {
|
||||
faceAuthenticationLogger.authRequested(uiEvent)
|
||||
repository.authenticate(uiEvent, fallbackToDetection = fallbackToDetect)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -541,10 +541,8 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun authenticateDoesNotRunIfUserIsCurrentlySwitching() =
|
||||
testScope.runTest {
|
||||
testGatingCheckForFaceAuth { fakeUserRepository.setUserSwitching(true) }
|
||||
}
|
||||
fun authenticateDoesNotRunIfFaceAuthIsCurrentlyPaused() =
|
||||
testScope.runTest { testGatingCheckForFaceAuth { underTest.pauseFaceAuth() } }
|
||||
|
||||
@Test
|
||||
fun authenticateDoesNotRunIfKeyguardIsNotShowing() =
|
||||
@@ -840,7 +838,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
|
||||
|
||||
@Test
|
||||
fun detectDoesNotRunWhenUserSwitchingInProgress() =
|
||||
testScope.runTest { testGatingCheckForDetect { fakeUserRepository.setUserSwitching(true) } }
|
||||
testScope.runTest { testGatingCheckForDetect { underTest.pauseFaceAuth() } }
|
||||
|
||||
@Test
|
||||
fun detectDoesNotRunWhenKeyguardGoingAway() =
|
||||
@@ -1130,7 +1128,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
|
||||
.addLockoutResetCallback(faceLockoutResetCallback.capture())
|
||||
biometricSettingsRepository.setFaceEnrolled(true)
|
||||
biometricSettingsRepository.setIsFaceAuthEnabled(true)
|
||||
fakeUserRepository.setUserSwitching(false)
|
||||
underTest.resumeFaceAuth()
|
||||
trustRepository.setCurrentUserTrusted(false)
|
||||
keyguardRepository.setKeyguardGoingAway(false)
|
||||
keyguardRepository.setWakefulnessModel(
|
||||
|
||||
@@ -48,6 +48,7 @@ import com.android.systemui.keyguard.shared.model.TransitionStep
|
||||
import com.android.systemui.log.FaceAuthenticationLogger
|
||||
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||
import com.android.systemui.user.data.repository.FakeUserRepository
|
||||
import com.android.systemui.util.time.FakeSystemClock
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
@@ -74,6 +75,7 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
|
||||
private lateinit var keyguardTransitionRepository: FakeKeyguardTransitionRepository
|
||||
private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
|
||||
private lateinit var faceAuthRepository: FakeDeviceEntryFaceAuthRepository
|
||||
private lateinit var fakeUserRepository: FakeUserRepository
|
||||
private lateinit var fakeDeviceEntryFingerprintAuthRepository:
|
||||
FakeDeviceEntryFingerprintAuthRepository
|
||||
|
||||
@@ -98,6 +100,7 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
|
||||
.keyguardTransitionInteractor
|
||||
|
||||
fakeDeviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
|
||||
fakeUserRepository = FakeUserRepository()
|
||||
underTest =
|
||||
SystemUIKeyguardFaceAuthInteractor(
|
||||
mContext,
|
||||
@@ -131,7 +134,8 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
|
||||
featureFlags,
|
||||
FaceAuthenticationLogger(logcatLogBuffer("faceAuthBuffer")),
|
||||
keyguardUpdateMonitor,
|
||||
fakeDeviceEntryFingerprintAuthRepository
|
||||
fakeDeviceEntryFingerprintAuthRepository,
|
||||
fakeUserRepository,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -211,6 +215,38 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun faceAuthIsPausedWhenUserSwitchingIsInProgress() =
|
||||
testScope.runTest {
|
||||
underTest.start()
|
||||
|
||||
fakeUserRepository.setUserSwitching(false)
|
||||
runCurrent()
|
||||
fakeUserRepository.setUserSwitching(true)
|
||||
runCurrent()
|
||||
|
||||
assertThat(faceAuthRepository.isFaceAuthPaused()).isTrue()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun faceAuthIsUnpausedWhenUserSwitchingIsInComplete() =
|
||||
testScope.runTest {
|
||||
underTest.start()
|
||||
|
||||
// previously running
|
||||
fakeUserRepository.setUserSwitching(true)
|
||||
runCurrent()
|
||||
fakeUserRepository.setUserSwitching(false)
|
||||
runCurrent()
|
||||
|
||||
assertThat(faceAuthRepository.isFaceAuthPaused()).isFalse()
|
||||
|
||||
runCurrent()
|
||||
assertThat(faceAuthRepository.runningAuthRequest.value!!.first)
|
||||
.isEqualTo(FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING)
|
||||
assertThat(faceAuthRepository.runningAuthRequest.value!!.second).isEqualTo(true)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun faceAuthIsRequestedWhenPrimaryBouncerIsVisible() =
|
||||
testScope.runTest {
|
||||
|
||||
@@ -61,6 +61,19 @@ class FakeDeviceEntryFaceAuthRepository : DeviceEntryFaceAuthRepository {
|
||||
_wasDisabled = true
|
||||
}
|
||||
|
||||
private val faceAuthPaused = MutableStateFlow(false)
|
||||
override fun pauseFaceAuth() {
|
||||
faceAuthPaused.value = true
|
||||
}
|
||||
|
||||
override fun resumeFaceAuth() {
|
||||
faceAuthPaused.value = false
|
||||
}
|
||||
|
||||
fun isFaceAuthPaused(): Boolean {
|
||||
return faceAuthPaused.value
|
||||
}
|
||||
|
||||
override suspend fun authenticate(uiEvent: FaceAuthUiEvent, fallbackToDetection: Boolean) {
|
||||
_runningAuthRequest.value = uiEvent to fallbackToDetection
|
||||
_isAuthRunning.value = true
|
||||
|
||||
Reference in New Issue
Block a user