Merge "Spit up FingerprintManagerInteractor 2/N" into main

This commit is contained in:
Joshua Mccloskey
2024-09-26 18:29:36 +00:00
committed by Android (Google) Code Review
12 changed files with 199 additions and 70 deletions

View File

@@ -58,6 +58,7 @@ import com.android.settings.biometrics.fingerprint2.domain.interactor.SensorInte
import com.android.settings.biometrics.fingerprint2.domain.interactor.TouchEventInteractor import com.android.settings.biometrics.fingerprint2.domain.interactor.TouchEventInteractor
import com.android.settings.biometrics.fingerprint2.domain.interactor.UdfpsEnrollInteractor import com.android.settings.biometrics.fingerprint2.domain.interactor.UdfpsEnrollInteractor
import com.android.settings.biometrics.fingerprint2.domain.interactor.UdfpsEnrollInteractorImpl import com.android.settings.biometrics.fingerprint2.domain.interactor.UdfpsEnrollInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.UserInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractor import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractor
import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractorImpl import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractorImpl
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.AuthenitcateInteractor import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.AuthenitcateInteractor
@@ -67,6 +68,7 @@ import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.Genera
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.RemoveFingerprintInteractor import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.RemoveFingerprintInteractor
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.RenameFingerprintInteractor import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.RenameFingerprintInteractor
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.SensorInteractor import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.SensorInteractor
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.UserInteractor
import com.android.settings.biometrics.fingerprint2.lib.model.Settings import com.android.settings.biometrics.fingerprint2.lib.model.Settings
import java.util.concurrent.Executors import java.util.concurrent.Executors
import kotlinx.coroutines.MainScope import kotlinx.coroutines.MainScope
@@ -97,11 +99,11 @@ class BiometricsEnvironment(
com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser
) )
) )
private val fingerprintEnrollmentRepository =
FingerprintEnrollmentRepositoryImpl(fingerprintManager, userRepo, fingerprintSettingsRepository,
backgroundDispatcher, applicationScope)
private val fingerprintSensorRepository: FingerprintSensorRepository = private val fingerprintSensorRepository: FingerprintSensorRepository =
FingerprintSensorRepositoryImpl(fingerprintManager, backgroundDispatcher, applicationScope) FingerprintSensorRepositoryImpl(fingerprintManager, backgroundDispatcher, applicationScope)
private val fingerprintEnrollmentRepository =
FingerprintEnrollmentRepositoryImpl(fingerprintManager, userRepo, fingerprintSettingsRepository,
backgroundDispatcher, applicationScope, fingerprintSensorRepository)
private val debuggingRepository: DebuggingRepository = DebuggingRepositoryImpl() private val debuggingRepository: DebuggingRepository = DebuggingRepositoryImpl()
private val udfpsDebugRepo = UdfpsEnrollDebugRepositoryImpl() private val udfpsDebugRepo = UdfpsEnrollDebugRepositoryImpl()
@@ -118,11 +120,13 @@ class BiometricsEnvironment(
EnrollFingerprintInteractorImpl(context.userId, fingerprintManager, Settings) EnrollFingerprintInteractorImpl(context.userId, fingerprintManager, Settings)
fun createFingerprintsEnrolledInteractor(): EnrolledFingerprintsInteractorImpl = fun createFingerprintsEnrolledInteractor(): EnrolledFingerprintsInteractorImpl =
EnrolledFingerprintsInteractorImpl(fingerprintManager, context.userId) EnrolledFingerprintsInteractorImpl(fingerprintEnrollmentRepository)
fun createAuthenticateInteractor(): AuthenitcateInteractor = fun createAuthenticateInteractor(): AuthenitcateInteractor =
AuthenticateInteractorImpl(fingerprintManager, context.userId) AuthenticateInteractorImpl(fingerprintManager, context.userId)
fun createUserInteractor(): UserInteractor = UserInteractorImpl(userRepo)
fun createRemoveFingerprintInteractor(): RemoveFingerprintInteractor = fun createRemoveFingerprintInteractor(): RemoveFingerprintInteractor =
RemoveFingerprintsInteractorImpl(fingerprintManager, context.userId) RemoveFingerprintsInteractorImpl(fingerprintManager, context.userId)

View File

@@ -23,14 +23,16 @@ import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.callbackFlow import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
/** Repository that contains information about fingerprint enrollments. */ /** Repository that contains information about fingerprint enrollments. */
@@ -38,20 +40,31 @@ interface FingerprintEnrollmentRepository {
/** The current enrollments of the user */ /** The current enrollments of the user */
val currentEnrollments: Flow<List<FingerprintData>?> val currentEnrollments: Flow<List<FingerprintData>?>
/** Indicates the maximum fingerprints that are enrollable * */
val maxFingerprintsEnrollable: Flow<Int>
/** Indicates if a user can enroll another fingerprint */ /** Indicates if a user can enroll another fingerprint */
val canEnrollUser: Flow<Boolean> val canEnrollUser: Flow<Boolean>
fun maxFingerprintsEnrollable(): Int /**
* Indicates if we should use the default settings for maximum enrollments or the sensor props
* from the fingerprint sensor
*/
fun setShouldUseSettingsMaxFingerprints(useSettings: Boolean)
} }
class FingerprintEnrollmentRepositoryImpl( class FingerprintEnrollmentRepositoryImpl(
fingerprintManager: FingerprintManager, private val fingerprintManager: FingerprintManager,
userRepo: UserRepo, userRepo: UserRepo,
private val settingsRepository: FingerprintSettingsRepository, settingsRepository: FingerprintSettingsRepository,
backgroundDispatcher: CoroutineDispatcher, backgroundDispatcher: CoroutineDispatcher,
applicationScope: CoroutineScope, applicationScope: CoroutineScope,
sensorRepo: FingerprintSensorRepository,
) : FingerprintEnrollmentRepository { ) : FingerprintEnrollmentRepository {
private val _shouldUseSettingsMaxFingerprints = MutableStateFlow(false)
val shouldUseSettingsMaxFingerprints = _shouldUseSettingsMaxFingerprints.asStateFlow()
private val enrollmentChangedFlow: Flow<Int?> = private val enrollmentChangedFlow: Flow<Int?> =
callbackFlow { callbackFlow {
val callback = val callback =
@@ -72,27 +85,34 @@ class FingerprintEnrollmentRepositoryImpl(
override val currentEnrollments: Flow<List<FingerprintData>> = override val currentEnrollments: Flow<List<FingerprintData>> =
userRepo.currentUser userRepo.currentUser
.distinctUntilChanged() .distinctUntilChanged()
.flatMapLatest { currentUser -> .combine(enrollmentChangedFlow) { currentUser, _ -> getFingerprintsForUser(currentUser) }
enrollmentChangedFlow.map { enrollmentChanged ->
if (enrollmentChanged == null || enrollmentChanged == currentUser) {
fingerprintManager
.getEnrolledFingerprints(currentUser)
?.map { (FingerprintData(it.name.toString(), it.biometricId, it.deviceId)) }
?.toList()
} else {
null
}
}
}
.filterNotNull() .filterNotNull()
.flowOn(backgroundDispatcher) .flowOn(backgroundDispatcher)
override val canEnrollUser: Flow<Boolean> = override val maxFingerprintsEnrollable: Flow<Int> =
currentEnrollments.map { shouldUseSettingsMaxFingerprints.combine(sensorRepo.fingerprintSensor) {
it?.size?.let { it < settingsRepository.maxEnrollableFingerprints() } ?: false shouldUseSettings,
sensor ->
if (shouldUseSettings) {
settingsRepository.maxEnrollableFingerprints()
} else {
sensor.maxEnrollmentsPerUser
}
} }
override fun maxFingerprintsEnrollable(): Int { override val canEnrollUser: Flow<Boolean> =
return settingsRepository.maxEnrollableFingerprints() currentEnrollments.combine(maxFingerprintsEnrollable) { enrollments, maxFingerprints ->
enrollments.size < maxFingerprints
}
override fun setShouldUseSettingsMaxFingerprints(useSettings: Boolean) {
_shouldUseSettingsMaxFingerprints.update { useSettings }
}
private fun getFingerprintsForUser(userId: Int): List<FingerprintData>? {
return fingerprintManager
.getEnrolledFingerprints(userId)
?.map { (FingerprintData(it.name.toString(), it.biometricId, it.deviceId)) }
?.toList()
} }
} }

View File

@@ -17,7 +17,10 @@
package com.android.settings.biometrics.fingerprint2.data.repository package com.android.settings.biometrics.fingerprint2.data.repository
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.update
/** /**
* A repository responsible for indicating the current user. * A repository responsible for indicating the current user.
@@ -27,8 +30,18 @@ interface UserRepo {
* This flow indicates the current user. * This flow indicates the current user.
*/ */
val currentUser: Flow<Int> val currentUser: Flow<Int>
/**
* Updates the current user.
*/
fun updateUser(user: Int)
} }
class UserRepoImpl(val currUser: Int): UserRepo { class UserRepoImpl(currUser: Int): UserRepo {
override val currentUser: Flow<Int> = flowOf(currUser) private val _currentUser = MutableStateFlow(currUser)
override val currentUser = _currentUser.asStateFlow()
override fun updateUser(user: Int) {
_currentUser.update { user }
}
} }

View File

@@ -21,11 +21,14 @@ import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.CanEnr
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
class CanEnrollFingerprintsInteractorImpl( class CanEnrollFingerprintsInteractorImpl(
val fingerprintEnrollmentRepository: FingerprintEnrollmentRepository private val fingerprintEnrollmentRepository: FingerprintEnrollmentRepository
) : CanEnrollFingerprintsInteractor { ) : CanEnrollFingerprintsInteractor {
override val canEnrollFingerprints: Flow<Boolean> = fingerprintEnrollmentRepository.canEnrollUser override val canEnrollFingerprints: Flow<Boolean> = fingerprintEnrollmentRepository.canEnrollUser
/** Indicates the maximum fingerprints enrollable for a given user */ /** Indicates the maximum fingerprints enrollable for a given user */
override fun maxFingerprintsEnrollable(): Int { override val maxFingerprintsEnrollable: Flow<Int> =
return fingerprintEnrollmentRepository.maxFingerprintsEnrollable() fingerprintEnrollmentRepository.maxFingerprintsEnrollable
override fun setShouldUseSettingsMaxFingerprints(useSettings: Boolean) {
fingerprintEnrollmentRepository.setShouldUseSettingsMaxFingerprints(useSettings)
} }
} }

View File

@@ -16,22 +16,14 @@
package com.android.settings.biometrics.fingerprint2.domain.interactor package com.android.settings.biometrics.fingerprint2.domain.interactor
import android.hardware.fingerprint.FingerprintManager import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintEnrollmentRepository
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.EnrolledFingerprintsInteractor import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.EnrolledFingerprintsInteractor
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
class EnrolledFingerprintsInteractorImpl( class EnrolledFingerprintsInteractorImpl(
private val fingerprintManager: FingerprintManager, private val fingerprintEnrollmentRepository: FingerprintEnrollmentRepository
userId: Int,
) : EnrolledFingerprintsInteractor { ) : EnrolledFingerprintsInteractor {
override val enrolledFingerprints: Flow<List<FingerprintData>?> = flow { override val enrolledFingerprints: Flow<List<FingerprintData>?> =
emit( fingerprintEnrollmentRepository.currentEnrollments
fingerprintManager
.getEnrolledFingerprints(userId)
?.map { (FingerprintData(it.name.toString(), it.biometricId, it.deviceId)) }
?.toList()
)
}
} }

View File

@@ -0,0 +1,27 @@
/*
* Copyright (C) 2024 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.settings.biometrics.fingerprint2.domain.interactor
import com.android.settings.biometrics.fingerprint2.data.repository.UserRepo
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.UserInteractor
import kotlinx.coroutines.flow.Flow
class UserInteractorImpl(private val userRepo: UserRepo) : UserInteractor {
override val currentUser: Flow<Int> = userRepo.currentUser
override fun updateUser(user: Int) = userRepo.updateUser(user)
}

View File

@@ -23,5 +23,17 @@ interface CanEnrollFingerprintsInteractor {
/** Returns true if a user can enroll a fingerprint false otherwise. */ /** Returns true if a user can enroll a fingerprint false otherwise. */
val canEnrollFingerprints: Flow<Boolean> val canEnrollFingerprints: Flow<Boolean>
/** Indicates the maximum fingerprints enrollable for a given user */ /** Indicates the maximum fingerprints enrollable for a given user */
fun maxFingerprintsEnrollable(): Int val maxFingerprintsEnrollable: Flow<Int>
/**
* Indicates if we should use the default settings for maximum enrollments or the sensor props
* from the fingerprint sensor. This can be useful if you are supporting HIDL & AIDL enrollment
* types from one code base. Prior to AIDL there was no way to determine how many
* fingerprints were enrollable, Settings relied on
* com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser.
*
* Typically Fingerprints with AIDL HAL's should not use this
* (setShouldUseSettingsMaxFingerprints(false))
*/
fun setShouldUseSettingsMaxFingerprints(useSettings: Boolean)
} }

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2024 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.settings.biometrics.fingerprint2.lib.domain.interactor
import kotlinx.coroutines.flow.Flow
interface UserInteractor {
/**
* This flow indicates the current user.
*/
val currentUser: Flow<Int>
/**
* Updates the current user.
*/
fun updateUser(user: Int)
}

View File

@@ -43,7 +43,6 @@ import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.sample import kotlinx.coroutines.flow.sample
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.flow.transformLatest import kotlinx.coroutines.flow.transformLatest
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@@ -72,10 +71,12 @@ class FingerprintSettingsViewModel(
/** Represents the stream of the information of "Add Fingerprint" preference. */ /** Represents the stream of the information of "Add Fingerprint" preference. */
val addFingerprintPrefInfo: Flow<Pair<Boolean, Int>> = val addFingerprintPrefInfo: Flow<Pair<Boolean, Int>> =
_enrolledFingerprints.filterOnlyWhenSettingsIsShown().combine( combine(
canEnrollFingerprintsInteractor.canEnrollFingerprints _enrolledFingerprints.filterOnlyWhenSettingsIsShown(),
) { _, canEnrollFingerprints -> canEnrollFingerprintsInteractor.canEnrollFingerprints,
Pair(canEnrollFingerprints, canEnrollFingerprintsInteractor.maxFingerprintsEnrollable()) canEnrollFingerprintsInteractor.maxFingerprintsEnrollable,
) { _, canEnrollFingerprints, maxFingerprints ->
Pair(canEnrollFingerprints, maxFingerprints)
} }
/** Represents the stream of visibility of sfps preference. */ /** Represents the stream of visibility of sfps preference. */

View File

@@ -38,8 +38,12 @@ import com.android.systemui.biometrics.shared.model.FingerprintSensor
import com.android.systemui.biometrics.shared.model.FingerprintSensorType import com.android.systemui.biometrics.shared.model.FingerprintSensorType
import com.android.systemui.biometrics.shared.model.toFingerprintSensor import com.android.systemui.biometrics.shared.model.toFingerprintSensor
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.transform
import kotlinx.coroutines.flow.update
/** Fake to be used by other classes to easily fake the FingerprintManager implementation. */ /** Fake to be used by other classes to easily fake the FingerprintManager implementation. */
class FakeFingerprintManagerInteractor : class FakeFingerprintManagerInteractor :
@@ -52,7 +56,7 @@ class FakeFingerprintManagerInteractor :
RenameFingerprintInteractor, RenameFingerprintInteractor,
SensorInteractor { SensorInteractor {
var enrollableFingerprints: Int = 5 private val enrollableFingerprints = MutableStateFlow(5)
var enrolledFingerprintsInternal: MutableList<FingerprintData> = mutableListOf() var enrolledFingerprintsInternal: MutableList<FingerprintData> = mutableListOf()
var challengeToGenerate: Pair<Long, ByteArray> = Pair(-1L, byteArrayOf()) var challengeToGenerate: Pair<Long, ByteArray> = Pair(-1L, byteArrayOf())
var authenticateAttempt = FingerprintAuthAttemptModel.Success(1) var authenticateAttempt = FingerprintAuthAttemptModel.Success(1)
@@ -82,13 +86,13 @@ class FakeFingerprintManagerInteractor :
override val enrolledFingerprints: Flow<List<FingerprintData>> = flow { override val enrolledFingerprints: Flow<List<FingerprintData>> = flow {
emit(enrolledFingerprintsInternal) emit(enrolledFingerprintsInternal)
} }
override val canEnrollFingerprints: Flow<Boolean> = flow { override val canEnrollFingerprints: Flow<Boolean> = enrollableFingerprints.transform {
emit(enrolledFingerprintsInternal.size < enrollableFingerprints) emit(enrolledFingerprintsInternal.size < it)
} }
override fun maxFingerprintsEnrollable(): Int { override val maxFingerprintsEnrollable: Flow<Int> = enrollableFingerprints.asStateFlow()
return enrollableFingerprints
} override fun setShouldUseSettingsMaxFingerprints(useSettings: Boolean) {}
override val sensorPropertiesInternal: Flow<FingerprintSensor?> = flow { emit(sensorProp) } override val sensorPropertiesInternal: Flow<FingerprintSensor?> = flow { emit(sensorProp) }
override val hasSideFps: Flow<Boolean> = override val hasSideFps: Flow<Boolean> =
@@ -110,4 +114,7 @@ class FakeFingerprintManagerInteractor :
} }
} }
fun setMaxEnrollableFingerprints(fingerprints: Int) {
enrollableFingerprints.update { fingerprints }
}
} }

View File

@@ -30,6 +30,7 @@ import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.os.CancellationSignal import android.os.CancellationSignal
import android.os.Handler import android.os.Handler
import com.android.settings.biometrics.GatekeeperPasswordProvider import com.android.settings.biometrics.GatekeeperPasswordProvider
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintEnrollmentRepository
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintEnrollmentRepositoryImpl import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintEnrollmentRepositoryImpl
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepository import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepository
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSettingsRepositoryImpl import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSettingsRepositoryImpl
@@ -61,7 +62,7 @@ import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.last import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.test.StandardTestDispatcher import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.TestScope
@@ -106,9 +107,14 @@ class FingerprintManagerInteractorTest {
private val flow: FingerprintFlow = Default private val flow: FingerprintFlow = Default
private val maxFingerprints = 5 private val maxFingerprints = 5
private val currUser = MutableStateFlow(0) private val currUser = MutableStateFlow(0)
private lateinit var fingerprintEnrollRepo: FingerprintEnrollmentRepository
private val userRepo = private val userRepo =
object : UserRepo { object : UserRepo {
override val currentUser: Flow<Int> = currUser override val currentUser: Flow<Int> = currUser
override fun updateUser(user: Int) {
currUser.update { user }
}
} }
@Before @Before
@@ -133,17 +139,18 @@ class FingerprintManagerInteractorTest {
} }
val settingsRepository = FingerprintSettingsRepositoryImpl(maxFingerprints) val settingsRepository = FingerprintSettingsRepositoryImpl(maxFingerprints)
val fingerprintEnrollmentRepository = fingerprintEnrollRepo =
FingerprintEnrollmentRepositoryImpl( FingerprintEnrollmentRepositoryImpl(
fingerprintManager, fingerprintManager,
userRepo, userRepo,
settingsRepository, settingsRepository,
backgroundDispatcher, backgroundDispatcher,
backgroundScope, backgroundScope,
fingerprintSensorRepository,
) )
enrolledFingerprintsInteractorUnderTest = enrolledFingerprintsInteractorUnderTest =
EnrolledFingerprintsInteractorImpl(fingerprintManager, userId) EnrolledFingerprintsInteractorImpl(fingerprintEnrollRepo)
generateChallengeInteractorUnderTest = generateChallengeInteractorUnderTest =
GenerateChallengeInteractorImpl(fingerprintManager, userId, gateKeeperPasswordProvider) GenerateChallengeInteractorImpl(fingerprintManager, userId, gateKeeperPasswordProvider)
removeFingerprintsInteractorUnderTest = removeFingerprintsInteractorUnderTest =
@@ -153,7 +160,7 @@ class FingerprintManagerInteractorTest {
authenticateInteractorImplUnderTest = AuthenticateInteractorImpl(fingerprintManager, userId) authenticateInteractorImplUnderTest = AuthenticateInteractorImpl(fingerprintManager, userId)
canEnrollFingerprintsInteractorUnderTest = canEnrollFingerprintsInteractorUnderTest =
CanEnrollFingerprintsInteractorImpl(fingerprintEnrollmentRepository) CanEnrollFingerprintsInteractorImpl(fingerprintEnrollRepo)
enrollInteractorUnderTest = EnrollFingerprintInteractorImpl(userId, fingerprintManager, flow) enrollInteractorUnderTest = EnrollFingerprintInteractorImpl(userId, fingerprintManager, flow)
} }
@@ -163,9 +170,16 @@ class FingerprintManagerInteractorTest {
testScope.runTest { testScope.runTest {
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(emptyList()) whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(emptyList())
val emptyFingerprintList: List<Fingerprint> = emptyList() var list: List<FingerprintData>? = null
assertThat(enrolledFingerprintsInteractorUnderTest.enrolledFingerprints.last()) val job =
.isEqualTo(emptyFingerprintList) testScope.launch {
enrolledFingerprintsInteractorUnderTest.enrolledFingerprints.collect { list = it }
}
runCurrent()
job.cancelAndJoin()
assertThat(list!!.isEmpty())
} }
@Test @Test
@@ -174,10 +188,19 @@ class FingerprintManagerInteractorTest {
val expected = Fingerprint("Finger 1,", 2, 3L) val expected = Fingerprint("Finger 1,", 2, 3L)
val fingerprintList: List<Fingerprint> = listOf(expected) val fingerprintList: List<Fingerprint> = listOf(expected)
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(fingerprintList) whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(fingerprintList)
// This causes the enrolled fingerprints to be updated
var list: List<FingerprintData>? = null
val job =
testScope.launch {
enrolledFingerprintsInteractorUnderTest.enrolledFingerprints.collect { list = it }
}
runCurrent()
job.cancelAndJoin()
val list = enrolledFingerprintsInteractorUnderTest.enrolledFingerprints.last()
assertThat(list!!.size).isEqualTo(fingerprintList.size) assertThat(list!!.size).isEqualTo(fingerprintList.size)
val actual = list[0] val actual = list!![0]
assertThat(actual.name).isEqualTo(expected.name) assertThat(actual.name).isEqualTo(expected.name)
assertThat(actual.fingerId).isEqualTo(expected.biometricId) assertThat(actual.fingerId).isEqualTo(expected.biometricId)
assertThat(actual.deviceId).isEqualTo(expected.deviceId) assertThat(actual.deviceId).isEqualTo(expected.deviceId)
@@ -220,11 +243,7 @@ class FingerprintManagerInteractorTest {
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(fingerprintList) whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(fingerprintList)
var result: Boolean? = null var result: Boolean? = null
val job = val job = testScope.launch { fingerprintEnrollRepo.canEnrollUser.collect { result = it } }
testScope.launch {
canEnrollFingerprintsInteractorUnderTest.canEnrollFingerprints.collect { result = it }
}
runCurrent() runCurrent()
job.cancelAndJoin() job.cancelAndJoin()

View File

@@ -112,7 +112,7 @@ class FingerprintEnrollConfirmationViewModelTest {
.toFingerprintSensor() .toFingerprintSensor()
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf() fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf()
fakeFingerprintManagerInteractor.enrollableFingerprints = 5 fakeFingerprintManagerInteractor.setMaxEnrollableFingerprints(5)
var canEnrollFingerprints: Boolean = false var canEnrollFingerprints: Boolean = false
val job = launch { val job = launch {