Split up FingerprintManagerInteractor

Test: atest, screenshot tests passed
Flag: com.android.settings.flags.fingerprint_v2_enrollment
Change-Id: I70833d5d9888f730233a9757589ce7faa45eccc9
This commit is contained in:
Joshua McCloskey
2024-08-07 23:52:11 +00:00
parent 59f11d9377
commit 882e1c3621
51 changed files with 1231 additions and 523 deletions

View File

@@ -16,7 +16,6 @@
package com.android.settings.fingerprint2.domain.interactor
import android.content.Context
import android.content.Intent
import android.hardware.biometrics.ComponentInfoInternal
import android.hardware.biometrics.SensorLocationInternal
@@ -30,23 +29,37 @@ import android.hardware.fingerprint.FingerprintSensorProperties
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
import android.os.CancellationSignal
import android.os.Handler
import androidx.test.core.app.ApplicationProvider
import com.android.settings.biometrics.GatekeeperPasswordProvider
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintEnrollmentRepositoryImpl
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepository
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintEnrollInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSettingsRepositoryImpl
import com.android.settings.biometrics.fingerprint2.data.repository.UserRepo
import com.android.settings.biometrics.fingerprint2.domain.interactor.AuthenticateInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.CanEnrollFingerprintsInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrollFingerprintInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrolledFingerprintsInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.GenerateChallengeInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.RemoveFingerprintsInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.RenameFingerprintsInteractorImpl
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.CanEnrollFingerprintsInteractor
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.EnrollFingerprintInteractor
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.EnrolledFingerprintsInteractor
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.GenerateChallengeInteractor
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.model.Default
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintFlow
import com.android.settings.password.ChooseLockSettingsHelper
import com.android.systemui.biometrics.shared.model.FingerprintSensor
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.last
import kotlinx.coroutines.launch
@@ -75,13 +88,28 @@ import org.mockito.stubbing.OngoingStubbing
class FingerprintManagerInteractorTest {
@JvmField @Rule var rule = MockitoJUnit.rule()
private lateinit var underTest: FingerprintManagerInteractor
private var context: Context = ApplicationProvider.getApplicationContext()
private lateinit var enrolledFingerprintsInteractorUnderTest: EnrolledFingerprintsInteractor
private lateinit var generateChallengeInteractorUnderTest: GenerateChallengeInteractor
private lateinit var removeFingerprintsInteractorUnderTest: RemoveFingerprintInteractor
private lateinit var renameFingerprintsInteractorUnderTest: RenameFingerprintInteractor
private lateinit var authenticateInteractorImplUnderTest: AuthenticateInteractorImpl
private lateinit var canEnrollFingerprintsInteractorUnderTest: CanEnrollFingerprintsInteractor
private lateinit var enrollInteractorUnderTest: EnrollFingerprintInteractor
private val userId = 0
private var backgroundDispatcher = StandardTestDispatcher()
@Mock private lateinit var fingerprintManager: FingerprintManager
@Mock private lateinit var gateKeeperPasswordProvider: GatekeeperPasswordProvider
private var testScope = TestScope(backgroundDispatcher)
private var backgroundScope = testScope.backgroundScope
private val flow: FingerprintFlow = Default
private val maxFingerprints = 5
private val currUser = MutableStateFlow(0)
private val userRepo =
object : UserRepo {
override val currentUser: Flow<Int> = currUser
}
@Before
fun setup() {
@@ -89,7 +117,7 @@ class FingerprintManagerInteractorTest {
FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5 /* maxEnrollmentsPerUser */,
maxFingerprints,
listOf<ComponentInfoInternal>(),
FingerprintSensorProperties.TYPE_POWER_BUTTON,
false /* halControlsIllumination */,
@@ -97,20 +125,37 @@ class FingerprintManagerInteractorTest {
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
)
.toFingerprintSensor()
val fingerprintSensorRepository =
object : FingerprintSensorRepository {
override val fingerprintSensor: Flow<FingerprintSensor> = flowOf(sensor)
override val hasSideFps: Flow<Boolean> = flowOf(false)
}
underTest =
FingerprintManagerInteractorImpl(
context,
backgroundDispatcher,
val settingsRepository = FingerprintSettingsRepositoryImpl(maxFingerprints)
val fingerprintEnrollmentRepository =
FingerprintEnrollmentRepositoryImpl(
fingerprintManager,
fingerprintSensorRepository,
gateKeeperPasswordProvider,
FingerprintEnrollInteractorImpl(context, fingerprintManager, Default),
userRepo,
settingsRepository,
backgroundDispatcher,
backgroundScope,
)
enrolledFingerprintsInteractorUnderTest =
EnrolledFingerprintsInteractorImpl(fingerprintManager, userId)
generateChallengeInteractorUnderTest =
GenerateChallengeInteractorImpl(fingerprintManager, userId, gateKeeperPasswordProvider)
removeFingerprintsInteractorUnderTest =
RemoveFingerprintsInteractorImpl(fingerprintManager, userId)
renameFingerprintsInteractorUnderTest =
RenameFingerprintsInteractorImpl(fingerprintManager, userId, backgroundDispatcher)
authenticateInteractorImplUnderTest = AuthenticateInteractorImpl(fingerprintManager, userId)
canEnrollFingerprintsInteractorUnderTest =
CanEnrollFingerprintsInteractorImpl(fingerprintEnrollmentRepository)
enrollInteractorUnderTest = EnrollFingerprintInteractorImpl(userId, fingerprintManager, flow)
}
@Test
@@ -119,7 +164,8 @@ class FingerprintManagerInteractorTest {
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(emptyList())
val emptyFingerprintList: List<Fingerprint> = emptyList()
assertThat(underTest.enrolledFingerprints.last()).isEqualTo(emptyFingerprintList)
assertThat(enrolledFingerprintsInteractorUnderTest.enrolledFingerprints.last())
.isEqualTo(emptyFingerprintList)
}
@Test
@@ -129,7 +175,7 @@ class FingerprintManagerInteractorTest {
val fingerprintList: List<Fingerprint> = listOf(expected)
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(fingerprintList)
val list = underTest.enrolledFingerprints.last()
val list = enrolledFingerprintsInteractorUnderTest.enrolledFingerprints.last()
assertThat(list!!.size).isEqualTo(fingerprintList.size)
val actual = list[0]
assertThat(actual.name).isEqualTo(expected.name)
@@ -138,24 +184,51 @@ class FingerprintManagerInteractorTest {
}
@Test
fun testCanEnrollFingerprint() =
fun testCanEnrollFingerprintSucceeds() =
testScope.runTest {
val fingerprintList1: List<Fingerprint> =
val fingerprintList: List<Fingerprint> =
listOf(
Fingerprint("Finger 1,", 2, 3L),
Fingerprint("Finger 2,", 3, 3L),
Fingerprint("Finger 3,", 4, 3L),
Fingerprint("Finger 1", 2, 3L),
Fingerprint("Finger 2", 3, 3L),
Fingerprint("Finger 3", 4, 3L),
)
val fingerprintList2: List<Fingerprint> =
fingerprintList1.plus(
listOf(Fingerprint("Finger 4,", 5, 3L), Fingerprint("Finger 5,", 6, 3L))
)
whenever(fingerprintManager.getEnrolledFingerprints(anyInt()))
.thenReturn(fingerprintList1)
.thenReturn(fingerprintList2)
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(fingerprintList)
assertThat(underTest.canEnrollFingerprints.last()).isTrue()
assertThat(underTest.canEnrollFingerprints.last()).isFalse()
var result: Boolean? = null
val job =
testScope.launch {
canEnrollFingerprintsInteractorUnderTest.canEnrollFingerprints.collect { result = it }
}
runCurrent()
job.cancelAndJoin()
assertThat(result).isTrue()
}
@Test
fun testCanEnrollFingerprintFails() =
testScope.runTest {
val fingerprintList: List<Fingerprint> =
listOf(
Fingerprint("Finger 1", 2, 3L),
Fingerprint("Finger 2", 3, 3L),
Fingerprint("Finger 3", 4, 3L),
Fingerprint("Finger 4", 5, 3L),
Fingerprint("Finger 5", 6, 3L),
)
whenever(fingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(fingerprintList)
var result: Boolean? = null
val job =
testScope.launch {
canEnrollFingerprintsInteractorUnderTest.canEnrollFingerprints.collect { result = it }
}
runCurrent()
job.cancelAndJoin()
assertThat(result).isFalse()
}
@Test
@@ -178,7 +251,8 @@ class FingerprintManagerInteractorTest {
argumentCaptor()
var result: Pair<Long, ByteArray?>? = null
val job = testScope.launch { result = underTest.generateChallenge(1L) }
val job =
testScope.launch { result = generateChallengeInteractorUnderTest.generateChallenge(1L) }
runCurrent()
verify(fingerprintManager).generateChallenge(anyInt(), capture(generateChallengeCallback))
@@ -201,7 +275,10 @@ class FingerprintManagerInteractorTest {
var result: Boolean? = null
val job =
testScope.launch { result = underTest.removeFingerprint(fingerprintViewModelToRemove) }
testScope.launch {
result =
removeFingerprintsInteractorUnderTest.removeFingerprint(fingerprintViewModelToRemove)
}
runCurrent()
verify(fingerprintManager)
@@ -224,7 +301,10 @@ class FingerprintManagerInteractorTest {
var result: Boolean? = null
val job =
testScope.launch { result = underTest.removeFingerprint(fingerprintViewModelToRemove) }
testScope.launch {
result =
removeFingerprintsInteractorUnderTest.removeFingerprint(fingerprintViewModelToRemove)
}
runCurrent()
verify(fingerprintManager)
@@ -246,7 +326,7 @@ class FingerprintManagerInteractorTest {
testScope.runTest {
val fingerprintToRename = FingerprintData("Finger 2", 1, 2L)
underTest.renameFingerprint(fingerprintToRename, "Woo")
renameFingerprintsInteractorUnderTest.renameFingerprint(fingerprintToRename, "Woo")
verify(fingerprintManager).rename(eq(fingerprintToRename.fingerId), anyInt(), safeEq("Woo"))
}
@@ -257,7 +337,7 @@ class FingerprintManagerInteractorTest {
val fingerprint = Fingerprint("Woooo", 100, 101L)
var result: FingerprintAuthAttemptModel? = null
val job = launch { result = underTest.authenticate() }
val job = launch { result = authenticateInteractorImplUnderTest.authenticate() }
val authCallback: ArgumentCaptor<FingerprintManager.AuthenticationCallback> = argumentCaptor()
@@ -284,7 +364,7 @@ class FingerprintManagerInteractorTest {
fun testAuth_lockout() =
testScope.runTest {
var result: FingerprintAuthAttemptModel? = null
val job = launch { result = underTest.authenticate() }
val job = launch { result = authenticateInteractorImplUnderTest.authenticate() }
val authCallback: ArgumentCaptor<FingerprintManager.AuthenticationCallback> = argumentCaptor()
@@ -314,7 +394,7 @@ class FingerprintManagerInteractorTest {
val token = byteArrayOf(5, 3, 2)
var result: FingerEnrollState? = null
val job = launch {
underTest
enrollInteractorUnderTest
.enroll(token, EnrollReason.FindSensor, FingerprintEnrollOptions.Builder().build())
.collect { result = it }
}
@@ -343,7 +423,7 @@ class FingerprintManagerInteractorTest {
val token = byteArrayOf(5, 3, 2)
var result: FingerEnrollState? = null
val job = launch {
underTest
enrollInteractorUnderTest
.enroll(token, EnrollReason.FindSensor, FingerprintEnrollOptions.Builder().build())
.collect { result = it }
}
@@ -372,7 +452,7 @@ class FingerprintManagerInteractorTest {
val token = byteArrayOf(5, 3, 2)
var result: FingerEnrollState? = null
val job = launch {
underTest
enrollInteractorUnderTest
.enroll(token, EnrollReason.FindSensor, FingerprintEnrollOptions.Builder().build())
.collect { result = it }
}

View File

@@ -99,9 +99,10 @@ class FingerprintEnrollFindSensorViewModelV2Test {
backgroundViewModel.inForeground()
enrollViewModel =
FingerprintEnrollViewModel(
fakeFingerprintManagerInteractor,
gatekeeperViewModel,
navigationViewModel,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
)
accessibilityInteractor =
object : AccessibilityInteractor {

View File

@@ -49,8 +49,7 @@ class RFPSIconTouchViewModelTest {
fun setup() {
Dispatchers.setMain(backgroundDispatcher)
testScope = TestScope(backgroundDispatcher)
rfpsIconTouchViewModel =
RFPSIconTouchViewModel()
rfpsIconTouchViewModel = RFPSIconTouchViewModel()
}
@After

View File

@@ -88,9 +88,10 @@ class FingerprintEnrollEnrollingViewModelTest {
backgroundViewModel.inForeground()
val fingerprintEnrollViewModel =
FingerprintEnrollViewModel(
fakeFingerprintManagerInteractor,
gateKeeperViewModel,
navigationViewModel,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
)
enrollEnrollingViewModel =
FingerprintEnrollEnrollingViewModel(fingerprintEnrollViewModel, backgroundViewModel)

View File

@@ -67,10 +67,11 @@ class FingerprintSettingsNavigationViewModelTest {
underTest =
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
null,
null,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
)
.create(FingerprintSettingsNavigationViewModel::class.java)
}
@@ -272,10 +273,11 @@ class FingerprintSettingsNavigationViewModelTest {
underTest =
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
token,
challenge,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
)
.create(FingerprintSettingsNavigationViewModel::class.java)
@@ -299,10 +301,11 @@ class FingerprintSettingsNavigationViewModelTest {
underTest =
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
token,
challenge,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
)
.create(FingerprintSettingsNavigationViewModel::class.java)
@@ -331,10 +334,11 @@ class FingerprintSettingsNavigationViewModelTest {
underTest =
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
token,
challenge,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
)
.create(FingerprintSettingsNavigationViewModel::class.java)

View File

@@ -73,19 +73,25 @@ class FingerprintSettingsViewModelTest {
navigationViewModel =
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
null,
null,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
)
.create(FingerprintSettingsNavigationViewModel::class.java)
underTest =
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
navigationViewModel,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
)
.create(FingerprintSettingsViewModel::class.java)
}
@@ -114,14 +120,7 @@ class FingerprintSettingsViewModelTest {
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
mutableListOf(FingerprintData("a", 1, 3L))
underTest =
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
navigationViewModel,
)
.create(FingerprintSettingsViewModel::class.java)
recreateSettingsViewModel()
var authAttempt: FingerprintAuthAttemptModel? = null
val job = launch { underTest.authFlow.take(5).collectLatest { authAttempt = it } }
@@ -156,14 +155,7 @@ class FingerprintSettingsViewModelTest {
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
mutableListOf(FingerprintData("a", 1, 3L))
underTest =
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
navigationViewModel,
)
.create(FingerprintSettingsViewModel::class.java)
recreateSettingsViewModel()
var authAttempt: FingerprintAuthAttemptModel? = null
val job = launch { underTest.authFlow.take(5).collectLatest { authAttempt = it } }
@@ -198,14 +190,7 @@ class FingerprintSettingsViewModelTest {
val success = FingerprintAuthAttemptModel.Success(1)
fakeFingerprintManagerInteractor.authenticateAttempt = success
underTest =
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
navigationViewModel,
)
.create(FingerprintSettingsViewModel::class.java)
recreateSettingsViewModel()
var authAttempt: FingerprintAuthAttemptModel? = null
@@ -225,14 +210,7 @@ class FingerprintSettingsViewModelTest {
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
mutableListOf(fingerprintToDelete)
underTest =
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
navigationViewModel,
)
.create(FingerprintSettingsViewModel::class.java)
recreateSettingsViewModel()
var dialog: PreferenceViewModel? = null
val dialogJob = launch { underTest.isShowingDialog.collect { dialog = it } }
@@ -261,14 +239,7 @@ class FingerprintSettingsViewModelTest {
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
mutableListOf(fingerprintToRename)
underTest =
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
navigationViewModel,
)
.create(FingerprintSettingsViewModel::class.java)
recreateSettingsViewModel()
var dialog: PreferenceViewModel? = null
val dialogJob = launch { underTest.isShowingDialog.collect { dialog = it } }
@@ -299,14 +270,7 @@ class FingerprintSettingsViewModelTest {
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
mutableListOf(fingerprintToDelete)
underTest =
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
navigationViewModel,
)
.create(FingerprintSettingsViewModel::class.java)
recreateSettingsViewModel()
var dialog: PreferenceViewModel? = null
val dialogJob = launch { underTest.isShowingDialog.collect { dialog = it } }
@@ -390,6 +354,22 @@ class FingerprintSettingsViewModelTest {
assertThat(authAttempt).isEqualTo(null)
}
private fun recreateSettingsViewModel() {
underTest =
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
defaultUserId,
backgroundDispatcher,
navigationViewModel,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
fakeFingerprintManagerInteractor,
)
.create(FingerprintSettingsViewModel::class.java)
}
private fun setupAuth(): MutableList<FingerprintData> {
fakeFingerprintManagerInteractor.sensorProp =
FingerprintSensorPropertiesInternal(
@@ -409,14 +389,7 @@ class FingerprintSettingsViewModelTest {
val success = FingerprintAuthAttemptModel.Success(1)
fakeFingerprintManagerInteractor.authenticateAttempt = success
underTest =
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
defaultUserId,
fakeFingerprintManagerInteractor,
backgroundDispatcher,
navigationViewModel,
)
.create(FingerprintSettingsViewModel::class.java)
recreateSettingsViewModel()
return fingerprints
}