summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Chandru S <chandruis@google.com> 2023-08-23 19:41:53 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-08-23 19:41:53 +0000
commiteff111674be0f81a45cb52b853dbd918deb7d4bf (patch)
tree892cbcbdd7275ef24bd7177f49a1095c469b220a
parent0e42a651973b4ed78c644ec65fc4dc5571a3a136 (diff)
parentab25d9379168bcc132592a8c38cb9695ddccaaac (diff)
Merge "Set the default state of canFaceAuth run to false." into main
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt73
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/shared/model/LockoutMode.kt35
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt10
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt24
-rw-r--r--packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt37
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt41
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt11
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt40
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt29
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt14
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt8
11 files changed, 200 insertions, 122 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt
index d2cb84945252..5b0bd959d902 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/data/repository/FacePropertyRepository.kt
@@ -20,7 +20,10 @@ package com.android.systemui.biometrics.data.repository
import android.hardware.face.FaceManager
import android.hardware.face.FaceSensorPropertiesInternal
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback
+import android.util.Log
+import com.android.systemui.biometrics.shared.model.LockoutMode
import com.android.systemui.biometrics.shared.model.SensorStrength
+import com.android.systemui.biometrics.shared.model.toLockoutMode
import com.android.systemui.biometrics.shared.model.toSensorStrength
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow
@@ -29,16 +32,18 @@ import com.android.systemui.dagger.qualifiers.Application
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose
-import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
-import kotlinx.coroutines.flow.flowOf
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.shareIn
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.stateIn
/** A repository for the global state of Face sensor. */
interface FacePropertyRepository {
/** Face sensor information, null if it is not available. */
- val sensorInfo: Flow<FaceSensorInfo?>
+ val sensorInfo: StateFlow<FaceSensorInfo?>
+
+ /** Get the current lockout mode for the user. This makes a binder based service call. */
+ suspend fun getLockoutMode(userId: Int): LockoutMode
}
/** Describes a biometric sensor */
@@ -49,33 +54,39 @@ private const val TAG = "FaceSensorPropertyRepositoryImpl"
@SysUISingleton
class FacePropertyRepositoryImpl
@Inject
-constructor(@Application private val applicationScope: CoroutineScope, faceManager: FaceManager?) :
- FacePropertyRepository {
+constructor(
+ @Application private val applicationScope: CoroutineScope,
+ private val faceManager: FaceManager?
+) : FacePropertyRepository {
- private val sensorProps: Flow<List<FaceSensorPropertiesInternal>> =
- faceManager?.let {
- ConflatedCallbackFlow.conflatedCallbackFlow {
- val callback =
- object : IFaceAuthenticatorsRegisteredCallback.Stub() {
- override fun onAllAuthenticatorsRegistered(
- sensors: List<FaceSensorPropertiesInternal>
- ) {
- trySendWithFailureLogging(
- sensors,
- TAG,
- "onAllAuthenticatorsRegistered"
- )
- }
+ override val sensorInfo: StateFlow<FaceSensorInfo?> =
+ ConflatedCallbackFlow.conflatedCallbackFlow {
+ val callback =
+ object : IFaceAuthenticatorsRegisteredCallback.Stub() {
+ override fun onAllAuthenticatorsRegistered(
+ sensors: List<FaceSensorPropertiesInternal>,
+ ) {
+ if (sensors.isEmpty()) return
+ trySendWithFailureLogging(
+ FaceSensorInfo(
+ sensors.first().sensorId,
+ sensors.first().sensorStrength.toSensorStrength()
+ ),
+ TAG,
+ "onAllAuthenticatorsRegistered"
+ )
}
- it.addAuthenticatorsRegisteredCallback(callback)
- awaitClose {}
- }
- .shareIn(applicationScope, SharingStarted.Eagerly)
- }
- ?: flowOf(emptyList())
+ }
+ faceManager?.addAuthenticatorsRegisteredCallback(callback)
+ awaitClose {}
+ }
+ .onEach { Log.d(TAG, "sensorProps changed: $it") }
+ .stateIn(applicationScope, SharingStarted.Eagerly, null)
- override val sensorInfo: Flow<FaceSensorInfo?> =
- sensorProps
- .map { it.firstOrNull() }
- .map { it?.let { FaceSensorInfo(it.sensorId, it.sensorStrength.toSensorStrength()) } }
+ override suspend fun getLockoutMode(userId: Int): LockoutMode {
+ if (sensorInfo.value == null || faceManager == null) {
+ return LockoutMode.NONE
+ }
+ return faceManager.getLockoutModeForUser(sensorInfo.value!!.id, userId).toLockoutMode()
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/LockoutMode.kt b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/LockoutMode.kt
new file mode 100644
index 000000000000..68bba32537b0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/shared/model/LockoutMode.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+package com.android.systemui.biometrics.shared.model
+
+import android.hardware.biometrics.BiometricConstants
+
+/** Lockout mode. Represents [BiometricConstants.LockoutMode]. */
+enum class LockoutMode {
+ NONE,
+ TIMED,
+ PERMANENT,
+}
+
+/** Convert [this] to corresponding [LockoutMode] */
+fun Int.toLockoutMode(): LockoutMode =
+ when (this) {
+ BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT -> LockoutMode.PERMANENT
+ BiometricConstants.BIOMETRIC_LOCKOUT_TIMED -> LockoutMode.TIMED
+ else -> LockoutMode.NONE
+ }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
index 93eb103d74e1..8064cc1cce88 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepository.kt
@@ -52,6 +52,7 @@ import com.android.systemui.log.SessionTracker
import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.log.table.logDiffsForTable
import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.user.data.model.SelectionStatus
import com.android.systemui.user.data.repository.UserRepository
import java.io.PrintWriter
import java.util.Arrays
@@ -71,6 +72,7 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
@@ -200,7 +202,7 @@ constructor(
private val keyguardSessionId: InstanceId?
get() = sessionTracker.getSessionId(StatusBarManager.SESSION_KEYGUARD)
- private val _canRunFaceAuth = MutableStateFlow(true)
+ private val _canRunFaceAuth = MutableStateFlow(false)
override val canRunFaceAuth: StateFlow<Boolean>
get() = _canRunFaceAuth
@@ -281,7 +283,9 @@ constructor(
} else {
keyguardRepository.isKeyguardGoingAway
},
- userRepository.userSwitchingInProgress,
+ userRepository.selectedUser.map {
+ it.selectionStatus == SelectionStatus.SELECTION_IN_PROGRESS
+ },
)
.onEach { anyOfThemIsTrue ->
if (anyOfThemIsTrue) {
@@ -325,6 +329,7 @@ constructor(
cancelDetection()
}
}
+ .flowOn(mainDispatcher)
.logDiffsForTable(faceDetectLog, "", "canFaceDetectRun", false)
.launchIn(applicationScope)
}
@@ -410,6 +415,7 @@ constructor(
cancel()
}
}
+ .flowOn(mainDispatcher)
.logDiffsForTable(faceAuthLog, "", "canFaceAuthRun", false)
.launchIn(applicationScope)
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
index 2a3f8520a63c..4b8171f60203 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/SystemUIKeyguardFaceAuthInteractor.kt
@@ -22,6 +22,8 @@ import com.android.keyguard.FaceAuthUiEvent
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.CoreStartable
import com.android.systemui.R
+import com.android.systemui.biometrics.data.repository.FacePropertyRepository
+import com.android.systemui.biometrics.shared.model.LockoutMode
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor
import com.android.systemui.dagger.SysUISingleton
@@ -35,6 +37,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.model.SelectionStatus
import com.android.systemui.user.data.repository.UserRepository
import com.android.systemui.util.kotlin.pairwise
import javax.inject.Inject
@@ -51,6 +54,7 @@ import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
+import kotlinx.coroutines.yield
/**
* Encapsulates business logic related face authentication being triggered for device entry from
@@ -72,6 +76,7 @@ constructor(
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
private val deviceEntryFingerprintAuthRepository: DeviceEntryFingerprintAuthRepository,
private val userRepository: UserRepository,
+ private val facePropertyRepository: FacePropertyRepository,
) : CoreStartable, KeyguardFaceAuthInteractor {
private val listeners: MutableList<FaceAuthenticationListener> = mutableListOf()
@@ -92,7 +97,7 @@ constructor(
faceAuthenticationLogger.bouncerVisibilityChanged()
runFaceAuth(
FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN,
- fallbackToDetect = true
+ fallbackToDetect = false
)
}
.launchIn(applicationScope)
@@ -134,16 +139,25 @@ constructor(
// 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) ->
+ userRepository.selectedUser
+ .pairwise()
+ .onEach { (previous, curr) ->
+ val wasSwitching = previous.selectionStatus == SelectionStatus.SELECTION_IN_PROGRESS
+ val isSwitching = curr.selectionStatus == SelectionStatus.SELECTION_IN_PROGRESS
if (!wasSwitching && isSwitching) {
repository.pauseFaceAuth()
} else if (wasSwitching && !isSwitching) {
+ val lockoutMode = facePropertyRepository.getLockoutMode(curr.userInfo.id)
+ if (lockoutMode == LockoutMode.PERMANENT || lockoutMode == LockoutMode.TIMED) {
+ repository.lockoutFaceAuth()
+ }
repository.resumeFaceAuth()
+ yield()
runFaceAuth(
FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING,
- fallbackToDetect = true
+ // Fallback to detection if bouncer is not showing so that we can detect a
+ // face and then show the bouncer to the user if face auth can't run
+ fallbackToDetect = !primaryBouncerInteractor.isBouncerShowing()
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
index 954765c4581d..8cfa55570723 100644
--- a/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/user/data/repository/UserRepository.kt
@@ -31,7 +31,6 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlags
-import com.android.systemui.flags.Flags.FACE_AUTH_REFACTOR
import com.android.systemui.settings.UserTracker
import com.android.systemui.user.data.model.SelectedUserModel
import com.android.systemui.user.data.model.SelectionStatus
@@ -49,7 +48,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.filterNotNull
-import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
@@ -77,9 +75,6 @@ interface UserRepository {
/** [UserInfo] of the currently-selected user. */
val selectedUserInfo: Flow<UserInfo>
- /** Whether user switching is currently in progress. */
- val userSwitchingInProgress: Flow<Boolean>
-
/** User ID of the main user. */
val mainUserId: Int
@@ -162,10 +157,6 @@ constructor(
private var _isGuestUserResetting: Boolean = false
override var isGuestUserResetting: Boolean = _isGuestUserResetting
- private val _isUserSwitchingInProgress = MutableStateFlow(false)
- override val userSwitchingInProgress: Flow<Boolean>
- get() = _isUserSwitchingInProgress
-
override val isGuestUserCreationScheduled = AtomicBoolean()
override val isStatusBarUserChipEnabled: Boolean =
@@ -175,12 +166,6 @@ constructor(
override var isRefreshUsersPaused: Boolean = false
- init {
- if (featureFlags.isEnabled(FACE_AUTH_REFACTOR)) {
- observeUserSwitching()
- }
- }
-
override val selectedUser: StateFlow<SelectedUserModel> = run {
// Some callbacks don't modify the selection status, so maintain the current value.
var currentSelectionStatus = SelectionStatus.SELECTION_COMPLETE
@@ -259,28 +244,6 @@ constructor(
return _userSwitcherSettings.value.isUserSwitcherEnabled
}
- private fun observeUserSwitching() {
- conflatedCallbackFlow {
- val callback =
- object : UserTracker.Callback {
- override fun onUserChanging(newUser: Int, userContext: Context) {
- trySendWithFailureLogging(true, TAG, "userSwitching started")
- }
-
- override fun onUserChanged(newUserId: Int, userContext: Context) {
- trySendWithFailureLogging(false, TAG, "userSwitching completed")
- }
- }
- tracker.addCallback(callback, mainDispatcher.asExecutor())
- trySendWithFailureLogging(false, TAG, "initial value defaulting to false")
- awaitClose { tracker.removeCallback(callback) }
- }
- .onEach { _isUserSwitchingInProgress.value = it }
- // TODO (b/262838215), Make this stateIn and initialize directly in field declaration
- // once the flag is launched
- .launchIn(applicationScope)
- }
-
private suspend fun getSettings(): UserSwitcherSettingsModel {
return withContext(backgroundDispatcher) {
val isSimpleUserSwitcher =
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt
index fcc40404bf7d..0da7b4ac88f8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/data/repository/FacePropertyRepositoryImplTest.kt
@@ -17,14 +17,19 @@
package com.android.systemui.biometrics.data.repository
+import android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_NONE
+import android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_PERMANENT
+import android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_TIMED
import android.hardware.biometrics.SensorProperties
import android.hardware.face.FaceManager
import android.hardware.face.FaceSensorPropertiesInternal
import android.hardware.face.IFaceAuthenticatorsRegisteredCallback
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.shared.model.LockoutMode
import com.android.systemui.biometrics.shared.model.SensorStrength
import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
@@ -74,18 +79,52 @@ class FacePropertyRepositoryImplTest : SysuiTestCase() {
@Test
fun providesTheValuePassedToTheAuthenticatorsRegisteredCallback() {
testScope.runTest {
- val sensor by collectLastValue(underTest.sensorInfo)
runCurrent()
verify(faceManager).addAuthenticatorsRegisteredCallback(callback.capture())
callback.value.onAllAuthenticatorsRegistered(
listOf(createSensorProperties(1, SensorProperties.STRENGTH_STRONG))
)
+ runCurrent()
+ val sensor by collectLastValue(underTest.sensorInfo)
assertThat(sensor).isEqualTo(FaceSensorInfo(1, SensorStrength.STRONG))
}
}
+ @Test
+ fun providesTheNoneLockoutModeWhenFaceManagerIsNotAvailable() =
+ testScope.runTest {
+ underTest = createRepository(null)
+
+ assertThat(underTest.getLockoutMode(-1)).isEqualTo(LockoutMode.NONE)
+ }
+
+ @Test
+ fun providesTheLockoutModeFromFaceManager() =
+ testScope.runTest {
+ val sensorId = 99
+ val userId = 999
+ runCurrent()
+ verify(faceManager).addAuthenticatorsRegisteredCallback(callback.capture())
+ callback.value.onAllAuthenticatorsRegistered(
+ listOf(createSensorProperties(sensorId, SensorProperties.STRENGTH_STRONG))
+ )
+ runCurrent()
+
+ whenever(faceManager.getLockoutModeForUser(sensorId, userId))
+ .thenReturn(BIOMETRIC_LOCKOUT_TIMED)
+ assertThat(underTest.getLockoutMode(userId)).isEqualTo(LockoutMode.TIMED)
+
+ whenever(faceManager.getLockoutModeForUser(sensorId, userId))
+ .thenReturn(BIOMETRIC_LOCKOUT_PERMANENT)
+ assertThat(underTest.getLockoutMode(userId)).isEqualTo(LockoutMode.PERMANENT)
+
+ whenever(faceManager.getLockoutModeForUser(sensorId, userId))
+ .thenReturn(BIOMETRIC_LOCKOUT_NONE)
+ assertThat(underTest.getLockoutMode(userId)).isEqualTo(LockoutMode.NONE)
+ }
+
private fun createSensorProperties(id: Int, strength: Int) =
FaceSensorPropertiesInternal(id, strength, 0, emptyList(), 1, false, false, false)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
index 64b94707da57..f0dbaf1aeaf3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/data/repository/DeviceEntryFaceAuthRepositoryTest.kt
@@ -71,6 +71,7 @@ import com.android.systemui.log.table.TableLogBuffer
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.FakeKeyguardStateController
import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.user.data.model.SelectionStatus
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.mockito.KotlinArgumentCaptor
import com.android.systemui.util.mockito.captureMany
@@ -295,6 +296,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
fun faceAuthDoesNotRunWhileItIsAlreadyRunning() =
testScope.runTest {
initCollectors()
+ allPreconditionsToRunFaceAuthAreTrue()
underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
faceAuthenticateIsCalled()
@@ -311,6 +313,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
testScope.runTest {
initCollectors()
verify(faceManager).addLockoutResetCallback(faceLockoutResetCallback.capture())
+ allPreconditionsToRunFaceAuthAreTrue()
underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
faceAuthenticateIsCalled()
@@ -364,6 +367,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
fun cancelStopsFaceAuthentication() =
testScope.runTest {
initCollectors()
+ allPreconditionsToRunFaceAuthAreTrue()
underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
faceAuthenticateIsCalled()
@@ -417,6 +421,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
fun faceAuthShouldWaitAndRunIfTriggeredWhileCancelling() =
testScope.runTest {
initCollectors()
+ allPreconditionsToRunFaceAuthAreTrue()
underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
faceAuthenticateIsCalled()
@@ -492,6 +497,7 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
)
underTest = createDeviceEntryFaceAuthRepositoryImpl()
initCollectors()
+ allPreconditionsToRunFaceAuthAreTrue()
underTest.authenticate(FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER)
faceAuthenticateIsCalled()
@@ -803,7 +809,10 @@ class DeviceEntryFaceAuthRepositoryTest : SysuiTestCase() {
assertThat(authenticated()).isTrue()
- fakeUserRepository.setUserSwitching(true)
+ fakeUserRepository.setSelectedUserInfo(
+ primaryUser,
+ SelectionStatus.SELECTION_IN_PROGRESS
+ )
assertThat(authenticated()).isFalse()
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
index 93f208ee14f5..ec115738df8b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardFaceAuthInteractorTest.kt
@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
+import android.content.pm.UserInfo
import android.hardware.biometrics.BiometricFaceConstants
import android.os.Handler
import androidx.test.ext.junit.runners.AndroidJUnit4
@@ -25,6 +26,8 @@ import com.android.keyguard.FaceAuthUiEvent
import com.android.keyguard.KeyguardSecurityModel
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.systemui.SysuiTestCase
+import com.android.systemui.biometrics.data.repository.FakeFacePropertyRepository
+import com.android.systemui.biometrics.shared.model.LockoutMode
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor
import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerCallbackInteractor
@@ -48,6 +51,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.model.SelectionStatus
import com.android.systemui.user.data.repository.FakeUserRepository
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
@@ -76,6 +80,7 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
private lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
private lateinit var faceAuthRepository: FakeDeviceEntryFaceAuthRepository
private lateinit var fakeUserRepository: FakeUserRepository
+ private lateinit var facePropertyRepository: FakeFacePropertyRepository
private lateinit var fakeDeviceEntryFingerprintAuthRepository:
FakeDeviceEntryFingerprintAuthRepository
@@ -101,6 +106,8 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
fakeDeviceEntryFingerprintAuthRepository = FakeDeviceEntryFingerprintAuthRepository()
fakeUserRepository = FakeUserRepository()
+ fakeUserRepository.setUserInfos(listOf(primaryUser, secondaryUser))
+ facePropertyRepository = FakeFacePropertyRepository()
underTest =
SystemUIKeyguardFaceAuthInteractor(
mContext,
@@ -136,6 +143,7 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
keyguardUpdateMonitor,
fakeDeviceEntryFingerprintAuthRepository,
fakeUserRepository,
+ facePropertyRepository,
)
}
@@ -220,9 +228,12 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
testScope.runTest {
underTest.start()
- fakeUserRepository.setUserSwitching(false)
+ fakeUserRepository.setSelectedUserInfo(primaryUser, SelectionStatus.SELECTION_COMPLETE)
runCurrent()
- fakeUserRepository.setUserSwitching(true)
+ fakeUserRepository.setSelectedUserInfo(
+ secondaryUser,
+ SelectionStatus.SELECTION_IN_PROGRESS
+ )
runCurrent()
assertThat(faceAuthRepository.isFaceAuthPaused()).isTrue()
@@ -234,17 +245,27 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
underTest.start()
// previously running
- fakeUserRepository.setUserSwitching(true)
+ fakeUserRepository.setSelectedUserInfo(
+ primaryUser,
+ SelectionStatus.SELECTION_IN_PROGRESS
+ )
runCurrent()
- fakeUserRepository.setUserSwitching(false)
+ bouncerRepository.setPrimaryShow(true)
+
+ facePropertyRepository.setLockoutMode(secondaryUser.id, LockoutMode.TIMED)
+ fakeUserRepository.setSelectedUserInfo(
+ secondaryUser,
+ SelectionStatus.SELECTION_COMPLETE
+ )
runCurrent()
assertThat(faceAuthRepository.isFaceAuthPaused()).isFalse()
+ assertThat(faceAuthRepository.wasDisabled).isTrue()
runCurrent()
assertThat(faceAuthRepository.runningAuthRequest.value!!.first)
.isEqualTo(FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING)
- assertThat(faceAuthRepository.runningAuthRequest.value!!.second).isEqualTo(true)
+ assertThat(faceAuthRepository.runningAuthRequest.value!!.second).isEqualTo(false)
}
@Test
@@ -259,7 +280,7 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
runCurrent()
assertThat(faceAuthRepository.runningAuthRequest.value)
- .isEqualTo(Pair(FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN, true))
+ .isEqualTo(Pair(FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN, false))
}
@Test
@@ -387,4 +408,11 @@ class KeyguardFaceAuthInteractorTest : SysuiTestCase() {
assertThat(faceAuthRepository.wasDisabled).isTrue()
}
+
+ companion object {
+ private const val primaryUserId = 1
+ private val primaryUser = UserInfo(primaryUserId, "test user", UserInfo.FLAG_PRIMARY)
+
+ private val secondaryUser = UserInfo(2, "secondary user", 0)
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
index 0c28cbb52831..e249cece5a1e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/user/data/repository/UserRepositoryImplTest.kt
@@ -259,35 +259,6 @@ class UserRepositoryImplTest : SysuiTestCase() {
assertThat(selectedUser!!.selectionStatus).isEqualTo(SelectionStatus.SELECTION_IN_PROGRESS)
}
- @Test
- fun userSwitchingInProgress_registersUserTrackerCallback() = runSelfCancelingTest {
- underTest = create(this)
-
- underTest.userSwitchingInProgress.launchIn(this)
- underTest.userSwitchingInProgress.launchIn(this)
- underTest.userSwitchingInProgress.launchIn(this)
-
- // Two callbacks registered - one for observing user switching and one for observing the
- // selected user
- assertThat(tracker.callbacks.size).isEqualTo(2)
- }
-
- @Test
- fun userSwitchingInProgress_propagatesStateFromUserTracker() = runSelfCancelingTest {
- underTest = create(this)
- assertThat(tracker.callbacks.size).isEqualTo(2)
-
- tracker.onUserChanging(0)
-
- var mostRecentSwitchingValue = false
- underTest.userSwitchingInProgress.onEach { mostRecentSwitchingValue = it }.launchIn(this)
-
- assertThat(mostRecentSwitchingValue).isTrue()
-
- tracker.onUserChanged(0)
- assertThat(mostRecentSwitchingValue).isFalse()
- }
-
private fun createUserInfo(
id: Int,
isGuest: Boolean,
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt
index 2ef1be70000f..51ce9f00a709 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/biometrics/data/repository/FakeFacePropertyRepository.kt
@@ -17,14 +17,24 @@
package com.android.systemui.biometrics.data.repository
-import kotlinx.coroutines.flow.Flow
+import com.android.systemui.biometrics.shared.model.LockoutMode
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
class FakeFacePropertyRepository : FacePropertyRepository {
private val faceSensorInfo = MutableStateFlow<FaceSensorInfo?>(null)
- override val sensorInfo: Flow<FaceSensorInfo?>
+ override val sensorInfo: StateFlow<FaceSensorInfo?>
get() = faceSensorInfo
+ private val lockoutModesForUser = mutableMapOf<Int, LockoutMode>()
+
+ fun setLockoutMode(userId: Int, mode: LockoutMode) {
+ lockoutModesForUser[userId] = mode
+ }
+ override suspend fun getLockoutMode(userId: Int): LockoutMode {
+ return lockoutModesForUser[userId]!!
+ }
+
fun setSensorInfo(value: FaceSensorInfo?) {
faceSensorInfo.value = value
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
index 51ee0c00cb0d..5ad19eed18b8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/user/data/repository/FakeUserRepository.kt
@@ -56,10 +56,6 @@ class FakeUserRepository : UserRepository {
)
override val selectedUserInfo: Flow<UserInfo> = selectedUser.map { it.userInfo }
- private val _userSwitchingInProgress = MutableStateFlow(false)
- override val userSwitchingInProgress: Flow<Boolean>
- get() = _userSwitchingInProgress
-
override var mainUserId: Int = MAIN_USER_ID
override var lastSelectedNonGuestUserId: Int = mainUserId
@@ -120,8 +116,4 @@ class FakeUserRepository : UserRepository {
fun setGuestUserAutoCreated(value: Boolean) {
_isGuestUserAutoCreated = value
}
-
- fun setUserSwitching(value: Boolean) {
- _userSwitchingInProgress.value = value
- }
}