Split up FingerprintManagerInteractor
Test: atest, screenshot tests passed Flag: com.android.settings.flags.fingerprint_v2_enrollment Change-Id: I70833d5d9888f730233a9757589ce7faa45eccc9
This commit is contained in:
@@ -18,7 +18,9 @@ package com.android.settings;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.ContentObserver;
|
||||
import android.hardware.fingerprint.FingerprintManager;
|
||||
import android.net.Uri;
|
||||
import android.provider.Settings;
|
||||
import android.util.FeatureFlagUtils;
|
||||
@@ -74,9 +76,6 @@ public class SettingsApplication extends Application {
|
||||
|
||||
// Set Spa environment.
|
||||
setSpaEnvironment();
|
||||
if (Flags.fingerprintV2Enrollment()) {
|
||||
mBiometricsEnvironment = new BiometricsEnvironment(this);
|
||||
}
|
||||
|
||||
if (ActivityEmbeddingUtils.isSettingsSplitEnabled(this)
|
||||
&& FeatureFlagUtils.isEnabled(this,
|
||||
@@ -120,7 +119,20 @@ public class SettingsApplication extends Application {
|
||||
|
||||
@Nullable
|
||||
public BiometricsEnvironment getBiometricEnvironment() {
|
||||
return mBiometricsEnvironment;
|
||||
if (Flags.fingerprintV2Enrollment()) {
|
||||
if (getPackageManager().hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
|
||||
final FingerprintManager fpm = getSystemService(FingerprintManager.class);
|
||||
if (mBiometricsEnvironment == null) {
|
||||
mBiometricsEnvironment = new BiometricsEnvironment(this, fpm);
|
||||
}
|
||||
return mBiometricsEnvironment;
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -16,12 +16,9 @@
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2
|
||||
|
||||
import android.content.pm.PackageManager
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.os.ServiceManager.ServiceNotFoundException
|
||||
import android.view.MotionEvent
|
||||
import android.view.accessibility.AccessibilityManager
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.lifecycle.ViewModelStore
|
||||
import androidx.lifecycle.ViewModelStoreOwner
|
||||
import com.android.internal.widget.LockPatternUtils
|
||||
@@ -29,33 +26,47 @@ import com.android.settings.SettingsApplication
|
||||
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.DebuggingRepository
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.DebuggingRepositoryImpl
|
||||
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.FingerprintSensorRepositoryImpl
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSettingsRepositoryImpl
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.UserRepoImpl
|
||||
import com.android.settings.biometrics.fingerprint2.debug.data.repository.UdfpsEnrollDebugRepositoryImpl
|
||||
import com.android.settings.biometrics.fingerprint2.debug.domain.interactor.DebugTouchEventInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.AccessibilityInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.AccessibilityInteractorImpl
|
||||
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.DebuggingInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.DebuggingInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.DisplayDensityInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.DisplayDensityInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrollFingerprintInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrollStageInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrollStageInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintEnrollInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintEnrollInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.EnrolledFingerprintsInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintSensorInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintSensorInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.GenerateChallengeInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.RemoveFingerprintsInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.RenameFingerprintsInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.SensorInteractorImpl
|
||||
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.UdfpsEnrollInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.VibrationInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.AuthenitcateInteractor
|
||||
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.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.domain.interactor.SensorInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.Settings
|
||||
import java.util.concurrent.Executors
|
||||
import kotlinx.coroutines.MainScope
|
||||
@@ -70,43 +81,53 @@ import kotlinx.coroutines.flow.flowOf
|
||||
* This code is instantiated within the [SettingsApplication], all repos should be private &
|
||||
* immutable and all interactors should public and immutable
|
||||
*/
|
||||
class BiometricsEnvironment(context: SettingsApplication) : ViewModelStoreOwner {
|
||||
|
||||
class BiometricsEnvironment(
|
||||
val context: SettingsApplication,
|
||||
private val fingerprintManager: FingerprintManager,
|
||||
) : ViewModelStoreOwner {
|
||||
private val executorService = Executors.newSingleThreadExecutor()
|
||||
private val backgroundDispatcher = executorService.asCoroutineDispatcher()
|
||||
private val applicationScope = MainScope()
|
||||
private val gateKeeperPasswordProvider = GatekeeperPasswordProvider(LockPatternUtils(context))
|
||||
private val fingerprintManager = try {
|
||||
if (context.packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)) {
|
||||
context.getSystemService(FragmentActivity.FINGERPRINT_SERVICE) as FingerprintManager?
|
||||
} else {
|
||||
null
|
||||
}
|
||||
} catch (exception: ServiceNotFoundException){
|
||||
null
|
||||
}
|
||||
|
||||
private val userRepo = UserRepoImpl(context.userId)
|
||||
private val fingerprintSettingsRepository =
|
||||
FingerprintSettingsRepositoryImpl(
|
||||
context.resources.getInteger(
|
||||
com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser
|
||||
)
|
||||
)
|
||||
private val fingerprintEnrollmentRepository =
|
||||
FingerprintEnrollmentRepositoryImpl(fingerprintManager, userRepo, fingerprintSettingsRepository,
|
||||
backgroundDispatcher, applicationScope)
|
||||
private val fingerprintSensorRepository: FingerprintSensorRepository =
|
||||
FingerprintSensorRepositoryImpl(fingerprintManager, backgroundDispatcher, applicationScope)
|
||||
private val debuggingRepository: DebuggingRepository = DebuggingRepositoryImpl()
|
||||
private val udfpsDebugRepo = UdfpsEnrollDebugRepositoryImpl()
|
||||
|
||||
/** For now, interactors are public to those with access to the [BiometricsEnvironment] class */
|
||||
val fingerprintEnrollInteractor: FingerprintEnrollInteractor by lazy {
|
||||
FingerprintEnrollInteractorImpl(context, fingerprintManager, Settings)
|
||||
}
|
||||
fun createSensorPropertiesInteractor(): SensorInteractor =
|
||||
SensorInteractorImpl(fingerprintSensorRepository)
|
||||
|
||||
/** [FingerprintManagerInteractor] to be used to construct view models */
|
||||
val fingerprintManagerInteractor: FingerprintManagerInteractor by lazy {
|
||||
FingerprintManagerInteractorImpl(
|
||||
context,
|
||||
backgroundDispatcher,
|
||||
fingerprintManager,
|
||||
fingerprintSensorRepository,
|
||||
gateKeeperPasswordProvider,
|
||||
fingerprintEnrollInteractor,
|
||||
)
|
||||
}
|
||||
fun createCanEnrollFingerprintsInteractor(): CanEnrollFingerprintsInteractor =
|
||||
CanEnrollFingerprintsInteractorImpl(fingerprintEnrollmentRepository)
|
||||
|
||||
fun createGenerateChallengeInteractor(): GenerateChallengeInteractor =
|
||||
GenerateChallengeInteractorImpl(fingerprintManager, context.userId, gateKeeperPasswordProvider)
|
||||
|
||||
fun createFingerprintEnrollInteractor(): EnrollFingerprintInteractor =
|
||||
EnrollFingerprintInteractorImpl(context.userId, fingerprintManager, Settings)
|
||||
|
||||
fun createFingerprintsEnrolledInteractor(): EnrolledFingerprintsInteractorImpl =
|
||||
EnrolledFingerprintsInteractorImpl(fingerprintManager, context.userId)
|
||||
|
||||
fun createAuthenticateInteractor(): AuthenitcateInteractor =
|
||||
AuthenticateInteractorImpl(fingerprintManager, context.userId)
|
||||
|
||||
fun createRemoveFingerprintInteractor(): RemoveFingerprintInteractor =
|
||||
RemoveFingerprintsInteractorImpl(fingerprintManager, context.userId)
|
||||
|
||||
fun createRenameFingerprintInteractor(): RenameFingerprintInteractor =
|
||||
RenameFingerprintsInteractorImpl(fingerprintManager, context.userId, backgroundDispatcher)
|
||||
|
||||
val accessibilityInteractor: AccessibilityInteractor by lazy {
|
||||
AccessibilityInteractorImpl(
|
||||
|
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* 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.data.repository
|
||||
|
||||
import android.hardware.biometrics.BiometricStateListener
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/** Repository that contains information about fingerprint enrollments. */
|
||||
interface FingerprintEnrollmentRepository {
|
||||
/** The current enrollments of the user */
|
||||
val currentEnrollments: Flow<List<FingerprintData>?>
|
||||
|
||||
/** Indicates if a user can enroll another fingerprint */
|
||||
val canEnrollUser: Flow<Boolean>
|
||||
|
||||
fun maxFingerprintsEnrollable(): Int
|
||||
}
|
||||
|
||||
class FingerprintEnrollmentRepositoryImpl(
|
||||
fingerprintManager: FingerprintManager,
|
||||
userRepo: UserRepo,
|
||||
private val settingsRepository: FingerprintSettingsRepository,
|
||||
backgroundDispatcher: CoroutineDispatcher,
|
||||
applicationScope: CoroutineScope,
|
||||
) : FingerprintEnrollmentRepository {
|
||||
|
||||
private val enrollmentChangedFlow: Flow<Int?> =
|
||||
callbackFlow {
|
||||
val callback =
|
||||
object : BiometricStateListener() {
|
||||
override fun onEnrollmentsChanged(userId: Int, sensorId: Int, hasEnrollments: Boolean) {
|
||||
trySend(userId)
|
||||
}
|
||||
}
|
||||
withContext(backgroundDispatcher) {
|
||||
fingerprintManager.registerBiometricStateListener(callback)
|
||||
}
|
||||
awaitClose {
|
||||
// no way to unregister
|
||||
}
|
||||
}
|
||||
.stateIn(applicationScope, started = SharingStarted.Eagerly, initialValue = null)
|
||||
|
||||
override val currentEnrollments: Flow<List<FingerprintData>> =
|
||||
userRepo.currentUser
|
||||
.distinctUntilChanged()
|
||||
.flatMapLatest { 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()
|
||||
.flowOn(backgroundDispatcher)
|
||||
|
||||
override val canEnrollUser: Flow<Boolean> =
|
||||
currentEnrollments.map {
|
||||
it?.size?.let { it < settingsRepository.maxEnrollableFingerprints() } ?: false
|
||||
}
|
||||
|
||||
override fun maxFingerprintsEnrollable(): Int {
|
||||
return settingsRepository.maxEnrollableFingerprints()
|
||||
}
|
||||
}
|
@@ -31,6 +31,8 @@ import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.flow.transform
|
||||
import kotlinx.coroutines.withContext
|
||||
@@ -43,10 +45,13 @@ import kotlinx.coroutines.withContext
|
||||
interface FingerprintSensorRepository {
|
||||
/** Get the [FingerprintSensor] */
|
||||
val fingerprintSensor: Flow<FingerprintSensor>
|
||||
|
||||
/** Indicates if this device supports the side fingerprint sensor */
|
||||
val hasSideFps: Flow<Boolean>
|
||||
}
|
||||
|
||||
class FingerprintSensorRepositoryImpl(
|
||||
fingerprintManager: FingerprintManager?,
|
||||
private val fingerprintManager: FingerprintManager,
|
||||
backgroundDispatcher: CoroutineDispatcher,
|
||||
activityScope: CoroutineScope,
|
||||
) : FingerprintSensorRepository {
|
||||
@@ -66,7 +71,7 @@ class FingerprintSensorRepositoryImpl(
|
||||
}
|
||||
}
|
||||
withContext(backgroundDispatcher) {
|
||||
fingerprintManager?.addAuthenticatorsRegisteredCallback(callback)
|
||||
fingerprintManager.addAuthenticatorsRegisteredCallback(callback)
|
||||
}
|
||||
awaitClose {}
|
||||
}
|
||||
@@ -75,6 +80,9 @@ class FingerprintSensorRepositoryImpl(
|
||||
override val fingerprintSensor: Flow<FingerprintSensor> =
|
||||
fingerprintPropsInternal.transform { emit(it.toFingerprintSensor()) }
|
||||
|
||||
override val hasSideFps: Flow<Boolean> =
|
||||
fingerprintSensor.flatMapLatest { flow { emit(fingerprintManager.isPowerbuttonFps()) } }
|
||||
|
||||
companion object {
|
||||
|
||||
private val DEFAULT_PROPS =
|
||||
|
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.data.repository
|
||||
|
||||
/**
|
||||
* Repository for storing metadata about fingerprint enrollments.
|
||||
*/
|
||||
interface FingerprintSettingsRepository {
|
||||
/**
|
||||
* Indicates the maximum number of fingerprints enrollable
|
||||
*/
|
||||
fun maxEnrollableFingerprints(): Int
|
||||
}
|
||||
|
||||
class FingerprintSettingsRepositoryImpl(private val maxFingerprintsEnrollable: Int) :
|
||||
FingerprintSettingsRepository {
|
||||
override fun maxEnrollableFingerprints() = maxFingerprintsEnrollable
|
||||
}
|
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2.data.repository
|
||||
|
||||
import android.graphics.Point
|
||||
import android.view.MotionEvent
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.data.repository
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
/**
|
||||
* A repository responsible for indicating the current user.
|
||||
*/
|
||||
interface UserRepo {
|
||||
/**
|
||||
* This flow indicates the current user.
|
||||
*/
|
||||
val currentUser: Flow<Int>
|
||||
}
|
||||
|
||||
class UserRepoImpl(val currUser: Int): UserRepo {
|
||||
override val currentUser: Flow<Int> = flowOf(currUser)
|
||||
}
|
@@ -97,6 +97,8 @@ class UdfpsEnrollDebugRepositoryImpl :
|
||||
}
|
||||
|
||||
override val fingerprintSensor: Flow<FingerprintSensor> = flowOf(sensorProps)
|
||||
override val hasSideFps: Flow<Boolean>
|
||||
get() = flowOf(false)
|
||||
|
||||
private fun pointToLeftOfSensor(sensorLocation: Rect): MotionEvent =
|
||||
MotionEvent.obtain(
|
||||
|
@@ -26,4 +26,4 @@ class DebugTouchEventInteractorImpl(
|
||||
) : TouchEventInteractor {
|
||||
override val touchEvent: Flow<MotionEvent> =
|
||||
udfpsSimulatedTouchEventsRepository.touchExplorationDebug
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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 android.hardware.fingerprint.FingerprintManager
|
||||
import android.os.CancellationSignal
|
||||
import android.util.Log
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.AuthenitcateInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
|
||||
import kotlin.coroutines.resume
|
||||
import kotlinx.coroutines.CancellableContinuation
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
|
||||
class AuthenticateInteractorImpl(
|
||||
private val fingerprintManager: FingerprintManager,
|
||||
private val userId: Int,
|
||||
) : AuthenitcateInteractor {
|
||||
|
||||
override suspend fun authenticate(): FingerprintAuthAttemptModel =
|
||||
suspendCancellableCoroutine { c: CancellableContinuation<FingerprintAuthAttemptModel> ->
|
||||
val authenticationCallback =
|
||||
object : FingerprintManager.AuthenticationCallback() {
|
||||
|
||||
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
||||
super.onAuthenticationError(errorCode, errString)
|
||||
if (c.isCompleted) {
|
||||
Log.d(TAG, "framework sent down onAuthError after finish")
|
||||
return
|
||||
}
|
||||
c.resume(FingerprintAuthAttemptModel.Error(errorCode, errString.toString()))
|
||||
}
|
||||
|
||||
override fun onAuthenticationSucceeded(result: FingerprintManager.AuthenticationResult) {
|
||||
super.onAuthenticationSucceeded(result)
|
||||
if (c.isCompleted) {
|
||||
Log.d(TAG, "framework sent down onAuthError after finish")
|
||||
return
|
||||
}
|
||||
c.resume(FingerprintAuthAttemptModel.Success(result.fingerprint?.biometricId ?: -1))
|
||||
}
|
||||
}
|
||||
|
||||
val cancellationSignal = CancellationSignal()
|
||||
c.invokeOnCancellation { cancellationSignal.cancel() }
|
||||
fingerprintManager.authenticate(
|
||||
null,
|
||||
cancellationSignal,
|
||||
authenticationCallback,
|
||||
null,
|
||||
userId,
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "AuthenticateInteractor"
|
||||
}
|
||||
}
|
@@ -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.domain.interactor
|
||||
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintEnrollmentRepository
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.CanEnrollFingerprintsInteractor
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class CanEnrollFingerprintsInteractorImpl(
|
||||
val fingerprintEnrollmentRepository: FingerprintEnrollmentRepository
|
||||
) : CanEnrollFingerprintsInteractor {
|
||||
override val canEnrollFingerprints: Flow<Boolean> = fingerprintEnrollmentRepository.canEnrollUser
|
||||
/** Indicates the maximum fingerprints enrollable for a given user */
|
||||
override fun maxFingerprintsEnrollable(): Int {
|
||||
return fingerprintEnrollmentRepository.maxFingerprintsEnrollable()
|
||||
}
|
||||
}
|
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* 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 android.hardware.fingerprint.FingerprintEnrollOptions
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.os.CancellationSignal
|
||||
import android.util.Log
|
||||
import com.android.settings.biometrics.fingerprint2.conversion.Util.toEnrollError
|
||||
import com.android.settings.biometrics.fingerprint2.conversion.Util.toOriginalReason
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.EnrollFingerprintInteractor
|
||||
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.FingerprintFlow
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.SetupWizard
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.channels.onFailure
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
||||
class EnrollFingerprintInteractorImpl(
|
||||
private val userId: Int,
|
||||
private val fingerprintManager: FingerprintManager,
|
||||
private val fingerprintFlow: FingerprintFlow,
|
||||
) : EnrollFingerprintInteractor {
|
||||
private val enrollRequestOutstanding = MutableStateFlow(false)
|
||||
|
||||
override suspend fun enroll(
|
||||
hardwareAuthToken: ByteArray?,
|
||||
enrollReason: EnrollReason,
|
||||
fingerprintEnrollOptions: FingerprintEnrollOptions,
|
||||
): Flow<FingerEnrollState> = callbackFlow {
|
||||
// TODO (b/308456120) Improve this logic
|
||||
if (enrollRequestOutstanding.value) {
|
||||
Log.d(TAG, "Outstanding enroll request, waiting 150ms")
|
||||
delay(150)
|
||||
if (enrollRequestOutstanding.value) {
|
||||
Log.e(TAG, "Request still present, continuing")
|
||||
}
|
||||
}
|
||||
|
||||
enrollRequestOutstanding.update { true }
|
||||
|
||||
var streamEnded = false
|
||||
var totalSteps: Int? = null
|
||||
val enrollmentCallback =
|
||||
object : FingerprintManager.EnrollmentCallback() {
|
||||
override fun onEnrollmentProgress(remaining: Int) {
|
||||
// This is sort of an implementation detail, but unfortunately the API isn't
|
||||
// very expressive. If anything we should look at changing the FingerprintManager API.
|
||||
if (totalSteps == null) {
|
||||
totalSteps = remaining + 1
|
||||
}
|
||||
|
||||
trySend(FingerEnrollState.EnrollProgress(remaining, totalSteps!!)).onFailure { error ->
|
||||
Log.d(TAG, "onEnrollmentProgress($remaining) failed to send, due to $error")
|
||||
}
|
||||
|
||||
if (remaining == 0) {
|
||||
streamEnded = true
|
||||
enrollRequestOutstanding.update { false }
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEnrollmentHelp(helpMsgId: Int, helpString: CharSequence?) {
|
||||
trySend(FingerEnrollState.EnrollHelp(helpMsgId, helpString.toString())).onFailure { error
|
||||
->
|
||||
Log.d(TAG, "onEnrollmentHelp failed to send, due to $error")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEnrollmentError(errMsgId: Int, errString: CharSequence?) {
|
||||
trySend(errMsgId.toEnrollError(fingerprintFlow == SetupWizard)).onFailure { error ->
|
||||
Log.d(TAG, "onEnrollmentError failed to send, due to $error")
|
||||
}
|
||||
Log.d(TAG, "onEnrollmentError($errMsgId)")
|
||||
streamEnded = true
|
||||
enrollRequestOutstanding.update { false }
|
||||
}
|
||||
|
||||
override fun onUdfpsPointerDown(sensorId: Int) {
|
||||
trySend(FingerEnrollState.PointerDown(sensorId)).onFailure { error ->
|
||||
Log.d(TAG, "onUdfpsPointerDown failed to send, due to $error")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUdfpsPointerUp(sensorId: Int) {
|
||||
trySend(FingerEnrollState.PointerUp(sensorId)).onFailure { error ->
|
||||
Log.d(TAG, "onUdfpsPointerUp failed to send, due to $error")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUdfpsOverlayShown() {
|
||||
trySend(FingerEnrollState.OverlayShown).onFailure { error ->
|
||||
Log.d(TAG, "OverlayShown failed to send, due to $error")
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAcquired(isAcquiredGood: Boolean) {
|
||||
trySend(FingerEnrollState.Acquired(isAcquiredGood)).onFailure { error ->
|
||||
Log.d(TAG, "Acquired failed to send, due to $error")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val cancellationSignal = CancellationSignal()
|
||||
|
||||
fingerprintManager.enroll(
|
||||
hardwareAuthToken,
|
||||
cancellationSignal,
|
||||
userId,
|
||||
enrollmentCallback,
|
||||
enrollReason.toOriginalReason(),
|
||||
fingerprintEnrollOptions,
|
||||
)
|
||||
awaitClose {
|
||||
// If the stream has not been ended, and the user has stopped collecting the flow
|
||||
// before it was over, send cancel.
|
||||
if (!streamEnded) {
|
||||
Log.e(TAG, "Cancel is sent from settings for enroll()")
|
||||
cancellationSignal.cancel()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "FingerprintEnrollStateRepository"
|
||||
}
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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 android.hardware.fingerprint.FingerprintManager
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.EnrolledFingerprintsInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
|
||||
class EnrolledFingerprintsInteractorImpl(
|
||||
private val fingerprintManager: FingerprintManager,
|
||||
userId: Int,
|
||||
) : EnrolledFingerprintsInteractor {
|
||||
override val enrolledFingerprints: Flow<List<FingerprintData>?> = flow {
|
||||
emit(
|
||||
fingerprintManager
|
||||
.getEnrolledFingerprints(userId)
|
||||
?.map { (FingerprintData(it.name.toString(), it.biometricId, it.deviceId)) }
|
||||
?.toList()
|
||||
)
|
||||
}
|
||||
}
|
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2.domain.interactor
|
||||
|
||||
import android.content.Context
|
||||
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.os.CancellationSignal
|
||||
@@ -49,7 +48,7 @@ interface FingerprintEnrollInteractor {
|
||||
}
|
||||
|
||||
class FingerprintEnrollInteractorImpl(
|
||||
private val applicationContext: Context,
|
||||
private val userId: Int,
|
||||
private val fingerprintManager: FingerprintManager?,
|
||||
private val fingerprintFlow: FingerprintFlow,
|
||||
) : FingerprintEnrollInteractor {
|
||||
@@ -138,7 +137,7 @@ class FingerprintEnrollInteractorImpl(
|
||||
fingerprintManager?.enroll(
|
||||
hardwareAuthToken,
|
||||
cancellationSignal,
|
||||
applicationContext.userId,
|
||||
userId,
|
||||
enrollmentCallback,
|
||||
enrollReason.toOriginalReason(),
|
||||
fingerprintEnrollOptions,
|
||||
|
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* 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.settings.biometrics.fingerprint2.domain.interactor
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.hardware.fingerprint.FingerprintManager.GenerateChallengeCallback
|
||||
import android.hardware.fingerprint.FingerprintManager.RemovalCallback
|
||||
import android.os.CancellationSignal
|
||||
import android.util.Log
|
||||
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepository
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
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.password.ChooseLockSettingsHelper
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
import kotlinx.coroutines.CancellableContinuation
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
private const val TAG = "FingerprintManagerInteractor"
|
||||
|
||||
class FingerprintManagerInteractorImpl(
|
||||
applicationContext: Context,
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
private val fingerprintManager: FingerprintManager?,
|
||||
fingerprintSensorRepository: FingerprintSensorRepository,
|
||||
private val gatekeeperPasswordProvider: GatekeeperPasswordProvider,
|
||||
private val fingerprintEnrollStateRepository: FingerprintEnrollInteractor,
|
||||
) : FingerprintManagerInteractor {
|
||||
|
||||
private val maxFingerprints =
|
||||
applicationContext.resources.getInteger(
|
||||
com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser
|
||||
)
|
||||
private val applicationContext = applicationContext.applicationContext
|
||||
|
||||
override suspend fun generateChallenge(gateKeeperPasswordHandle: Long): Pair<Long, ByteArray> =
|
||||
suspendCoroutine {
|
||||
val callback = GenerateChallengeCallback { _, userId, challenge ->
|
||||
val intent = Intent()
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gateKeeperPasswordHandle)
|
||||
val challengeToken =
|
||||
gatekeeperPasswordProvider.requestGatekeeperHat(intent, challenge, userId)
|
||||
|
||||
gatekeeperPasswordProvider.removeGatekeeperPasswordHandle(intent, false)
|
||||
val p = Pair(challenge, challengeToken)
|
||||
it.resume(p)
|
||||
}
|
||||
fingerprintManager?.generateChallenge(applicationContext.userId, callback)
|
||||
}
|
||||
|
||||
override val enrolledFingerprints: Flow<List<FingerprintData>?> = flow {
|
||||
emit(
|
||||
fingerprintManager?.getEnrolledFingerprints(applicationContext.userId)
|
||||
?.map { (FingerprintData(it.name.toString(), it.biometricId, it.deviceId)) }?.toList()
|
||||
)
|
||||
}
|
||||
|
||||
override val canEnrollFingerprints: Flow<Boolean> = flow {
|
||||
emit(
|
||||
fingerprintManager?.getEnrolledFingerprints(applicationContext.userId)?.size ?: maxFingerprints < maxFingerprints
|
||||
)
|
||||
}
|
||||
|
||||
override val sensorPropertiesInternal = fingerprintSensorRepository.fingerprintSensor
|
||||
|
||||
override val maxEnrollableFingerprints = flow { emit(maxFingerprints) }
|
||||
|
||||
override suspend fun enroll(
|
||||
hardwareAuthToken: ByteArray?,
|
||||
enrollReason: EnrollReason,
|
||||
fingerprintEnrollOptions: FingerprintEnrollOptions,
|
||||
): Flow<FingerEnrollState> =
|
||||
fingerprintEnrollStateRepository.enroll(
|
||||
hardwareAuthToken,
|
||||
enrollReason,
|
||||
fingerprintEnrollOptions,
|
||||
)
|
||||
|
||||
override suspend fun removeFingerprint(fp: FingerprintData): Boolean = suspendCoroutine {
|
||||
val callback =
|
||||
object : RemovalCallback() {
|
||||
override fun onRemovalError(
|
||||
fp: android.hardware.fingerprint.Fingerprint,
|
||||
errMsgId: Int,
|
||||
errString: CharSequence,
|
||||
) {
|
||||
it.resume(false)
|
||||
}
|
||||
|
||||
override fun onRemovalSucceeded(
|
||||
fp: android.hardware.fingerprint.Fingerprint?,
|
||||
remaining: Int,
|
||||
) {
|
||||
it.resume(true)
|
||||
}
|
||||
}
|
||||
fingerprintManager?.remove(
|
||||
android.hardware.fingerprint.Fingerprint(fp.name, fp.fingerId, fp.deviceId),
|
||||
applicationContext.userId,
|
||||
callback,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun renameFingerprint(fp: FingerprintData, newName: String) {
|
||||
withContext(backgroundDispatcher) {
|
||||
fingerprintManager?.rename(fp.fingerId, applicationContext.userId, newName)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun hasSideFps(): Boolean? = suspendCancellableCoroutine {
|
||||
it.resume(fingerprintManager?.isPowerbuttonFps)
|
||||
}
|
||||
|
||||
override suspend fun authenticate(): FingerprintAuthAttemptModel =
|
||||
suspendCancellableCoroutine { c: CancellableContinuation<FingerprintAuthAttemptModel> ->
|
||||
val authenticationCallback =
|
||||
object : FingerprintManager.AuthenticationCallback() {
|
||||
|
||||
override fun onAuthenticationError(errorCode: Int, errString: CharSequence) {
|
||||
super.onAuthenticationError(errorCode, errString)
|
||||
if (c.isCompleted) {
|
||||
Log.d(TAG, "framework sent down onAuthError after finish")
|
||||
return
|
||||
}
|
||||
c.resume(FingerprintAuthAttemptModel.Error(errorCode, errString.toString()))
|
||||
}
|
||||
|
||||
override fun onAuthenticationSucceeded(result: FingerprintManager.AuthenticationResult) {
|
||||
super.onAuthenticationSucceeded(result)
|
||||
if (c.isCompleted) {
|
||||
Log.d(TAG, "framework sent down onAuthError after finish")
|
||||
return
|
||||
}
|
||||
c.resume(FingerprintAuthAttemptModel.Success(result.fingerprint?.biometricId ?: -1))
|
||||
}
|
||||
}
|
||||
|
||||
val cancellationSignal = CancellationSignal()
|
||||
c.invokeOnCancellation { cancellationSignal.cancel() }
|
||||
fingerprintManager?.authenticate(
|
||||
null,
|
||||
cancellationSignal,
|
||||
authenticationCallback,
|
||||
null,
|
||||
applicationContext.userId,
|
||||
)
|
||||
}
|
||||
}
|
@@ -20,9 +20,7 @@ import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintS
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Interactor that propagates the type of [FingerprintSensor] this device supports.
|
||||
*/
|
||||
/** Interactor that propagates the type of [FingerprintSensor] this device supports. */
|
||||
interface FingerprintSensorInteractor {
|
||||
/** Get the [FingerprintSensor] */
|
||||
val fingerprintSensor: Flow<FingerprintSensor>
|
||||
|
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 android.content.Intent
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.GenerateChallengeInteractor
|
||||
import com.android.settings.password.ChooseLockSettingsHelper
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
class GenerateChallengeInteractorImpl(
|
||||
private val fingerprintManager: FingerprintManager,
|
||||
private val userId: Int,
|
||||
private val gatekeeperPasswordProvider: GatekeeperPasswordProvider,
|
||||
) : GenerateChallengeInteractor {
|
||||
|
||||
override suspend fun generateChallenge(gateKeeperPasswordHandle: Long): Pair<Long, ByteArray> =
|
||||
suspendCoroutine {
|
||||
val callback =
|
||||
FingerprintManager.GenerateChallengeCallback { _, userId, challenge ->
|
||||
val intent = Intent()
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gateKeeperPasswordHandle)
|
||||
val challengeToken =
|
||||
gatekeeperPasswordProvider.requestGatekeeperHat(intent, challenge, userId)
|
||||
|
||||
gatekeeperPasswordProvider.removeGatekeeperPasswordHandle(intent, false)
|
||||
val p = Pair(challenge, challengeToken)
|
||||
it.resume(p)
|
||||
}
|
||||
fingerprintManager.generateChallenge(userId, callback)
|
||||
}
|
||||
}
|
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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 android.hardware.fingerprint.FingerprintManager
|
||||
import android.hardware.fingerprint.FingerprintManager.RemovalCallback
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.RemoveFingerprintInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
class RemoveFingerprintsInteractorImpl(
|
||||
private val fingerprintManager: FingerprintManager,
|
||||
private val userId: Int,
|
||||
) : RemoveFingerprintInteractor {
|
||||
|
||||
override suspend fun removeFingerprint(fp: FingerprintData): Boolean = suspendCoroutine {
|
||||
val callback =
|
||||
object : RemovalCallback() {
|
||||
override fun onRemovalError(
|
||||
fp: android.hardware.fingerprint.Fingerprint,
|
||||
errMsgId: Int,
|
||||
errString: CharSequence,
|
||||
) {
|
||||
it.resume(false)
|
||||
}
|
||||
|
||||
override fun onRemovalSucceeded(
|
||||
fp: android.hardware.fingerprint.Fingerprint?,
|
||||
remaining: Int,
|
||||
) {
|
||||
it.resume(true)
|
||||
}
|
||||
}
|
||||
fingerprintManager.remove(
|
||||
android.hardware.fingerprint.Fingerprint(fp.name, fp.fingerId, fp.deviceId),
|
||||
userId,
|
||||
callback,
|
||||
)
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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 android.hardware.fingerprint.FingerprintManager
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.RenameFingerprintInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class RenameFingerprintsInteractorImpl(
|
||||
private val fingerprintManager: FingerprintManager,
|
||||
private val userId: Int,
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
) : RenameFingerprintInteractor {
|
||||
|
||||
override suspend fun renameFingerprint(fp: FingerprintData, newName: String) {
|
||||
withContext(backgroundDispatcher) { fingerprintManager.rename(fp.fingerId, userId, newName) }
|
||||
}
|
||||
}
|
@@ -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.FingerprintSensorRepository
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.SensorInteractor
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
class SensorInteractorImpl(private val repo: FingerprintSensorRepository) :
|
||||
SensorInteractor {
|
||||
override val sensorPropertiesInternal = repo.fingerprintSensor
|
||||
override val hasSideFps: Flow<Boolean> = repo.hasSideFps
|
||||
}
|
@@ -24,4 +24,3 @@ interface TouchEventInteractor {
|
||||
/** A flow simulating user touches. */
|
||||
val touchEvent: Flow<MotionEvent>
|
||||
}
|
||||
|
||||
|
@@ -13,6 +13,6 @@
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<manifest
|
||||
package="com.android.settings.biometrics.fingerprint2.lib">
|
||||
</manifest>
|
||||
|
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
|
||||
|
||||
/** Interactor responsible for coordinating authentication. */
|
||||
interface AuthenitcateInteractor {
|
||||
/** Runs the authenticate flow */
|
||||
suspend fun authenticate(): FingerprintAuthAttemptModel
|
||||
}
|
@@ -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.lib.domain.interactor
|
||||
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/** Returns whether or not a user can enroll a fingerprint */
|
||||
interface CanEnrollFingerprintsInteractor {
|
||||
/** Returns true if a user can enroll a fingerprint false otherwise. */
|
||||
val canEnrollFingerprints: Flow<Boolean>
|
||||
/** Indicates the maximum fingerprints enrollable for a given user */
|
||||
fun maxFingerprintsEnrollable(): Int
|
||||
}
|
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 android.hardware.fingerprint.FingerprintEnrollOptions
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/** Interactor that enrolls a fingerprint */
|
||||
interface EnrollFingerprintInteractor {
|
||||
/**
|
||||
* Runs [FingerprintManager.enroll] with the [hardwareAuthToken] and [EnrollReason] for this
|
||||
* enrollment. If successful data in the [fingerprintEnrollState] should be populated.
|
||||
*/
|
||||
suspend fun enroll(
|
||||
hardwareAuthToken: ByteArray?,
|
||||
enrollReason: EnrollReason,
|
||||
fingerprintEnrollOptions: FingerprintEnrollOptions,
|
||||
): Flow<FingerEnrollState>
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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 com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/** Interface to obtain the enrolled fingerprints */
|
||||
interface EnrolledFingerprintsInteractor {
|
||||
/** Returns the list of current fingerprints. */
|
||||
val enrolledFingerprints: Flow<List<FingerprintData>?>
|
||||
}
|
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* 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 android.hardware.fingerprint.FingerprintEnrollOptions
|
||||
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.systemui.biometrics.shared.model.FingerprintSensor
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Interface to obtain the necessary data for FingerprintEnrollment/Settings
|
||||
*
|
||||
* Note that this interface should not have dependencies on heavyweight libraries such as the
|
||||
* framework, hidl/aidl, etc. This makes it much easier to test and create fakes for.
|
||||
*/
|
||||
interface FingerprintManagerInteractor {
|
||||
/** Returns the list of current fingerprints. */
|
||||
val enrolledFingerprints: Flow<List<FingerprintData>?>
|
||||
|
||||
/** Returns the max enrollable fingerprints, note during SUW this might be 1 */
|
||||
val maxEnrollableFingerprints: Flow<Int>
|
||||
|
||||
/** Returns true if a user can enroll a fingerprint false otherwise. */
|
||||
val canEnrollFingerprints: Flow<Boolean>
|
||||
|
||||
/** Retrieves the sensor properties of a device */
|
||||
val sensorPropertiesInternal: Flow<FingerprintSensor?>
|
||||
|
||||
/** Runs the authenticate flow */
|
||||
suspend fun authenticate(): FingerprintAuthAttemptModel
|
||||
|
||||
/**
|
||||
* Generates a challenge with the provided [gateKeeperPasswordHandle] and on success returns a
|
||||
* challenge and challenge token. This info can be used for secure operations such as enrollment
|
||||
*
|
||||
* @param gateKeeperPasswordHandle GateKeeper password handle generated by a Confirm
|
||||
* @return A [Pair] of the challenge and challenge token
|
||||
*/
|
||||
suspend fun generateChallenge(gateKeeperPasswordHandle: Long): Pair<Long, ByteArray>
|
||||
|
||||
/**
|
||||
* Runs [FingerprintManager.enroll] with the [hardwareAuthToken] and [EnrollReason] for this
|
||||
* enrollment. If successful data in the [fingerprintEnrollState] should be populated.
|
||||
*/
|
||||
suspend fun enroll(
|
||||
hardwareAuthToken: ByteArray?,
|
||||
enrollReason: EnrollReason,
|
||||
fingerprintEnrollOptions: FingerprintEnrollOptions,
|
||||
): Flow<FingerEnrollState>
|
||||
|
||||
/**
|
||||
* Removes the given fingerprint, returning true if it was successfully removed and false
|
||||
* otherwise
|
||||
*/
|
||||
suspend fun removeFingerprint(fp: FingerprintData): Boolean
|
||||
|
||||
/** Renames the given fingerprint if one exists */
|
||||
suspend fun renameFingerprint(fp: FingerprintData, newName: String)
|
||||
|
||||
/** Indicates if the device has side fingerprint */
|
||||
suspend fun hasSideFps(): Boolean?
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
/** This interactor is responsible for generating a challenge. */
|
||||
interface GenerateChallengeInteractor {
|
||||
/**
|
||||
* Generates a challenge with the provided [gateKeeperPasswordHandle] and on success returns a
|
||||
* challenge and challenge token. This info can be used for secure operations such as enrollment
|
||||
*
|
||||
* @param gateKeeperPasswordHandle GateKeeper password handle generated by a Confirm
|
||||
* @return A [Pair] of the challenge and challenge token
|
||||
*/
|
||||
suspend fun generateChallenge(gateKeeperPasswordHandle: Long): Pair<Long, ByteArray>
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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 com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
|
||||
/** Interactor in charge of removing a fingerprint */
|
||||
interface RemoveFingerprintInteractor {
|
||||
/**
|
||||
* Removes the given fingerprint, returning true if it was successfully removed and false
|
||||
* otherwise
|
||||
*/
|
||||
suspend fun removeFingerprint(fp: FingerprintData): Boolean
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
|
||||
/** Interactor that can rename a fingerprint. */
|
||||
interface RenameFingerprintInteractor {
|
||||
/** Renames the given fingerprint if one exists */
|
||||
suspend fun renameFingerprint(fp: FingerprintData, newName: String)
|
||||
}
|
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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 com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/** Interactor that has various information about a fingerprint sensor */
|
||||
interface SensorInteractor {
|
||||
/** Retrieves the sensor properties of the device */
|
||||
val sensorPropertiesInternal: Flow<FingerprintSensor?>
|
||||
/** Indicates if the device supports side fps */
|
||||
val hasSideFps: Flow<Boolean>
|
||||
}
|
@@ -96,8 +96,8 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
}
|
||||
|
||||
/**
|
||||
* View models below this line are not used by this class but must be initialized
|
||||
* in the activity view model store to be used by other view models.
|
||||
* View models below this line are not used by this class but must be initialized in the activity
|
||||
* view model store to be used by other view models.
|
||||
*/
|
||||
private val fingerprintEnrollViewModel: FingerprintEnrollViewModel by viewModels {
|
||||
FingerprintEnrollViewModel.Factory
|
||||
|
@@ -25,7 +25,7 @@ import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import com.android.settings.SettingsApplication
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.SensorInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintAction
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollEnrollingViewModel
|
||||
@@ -46,10 +46,10 @@ import kotlinx.coroutines.flow.update
|
||||
|
||||
/** View Model used by the rear fingerprint enrollment fragment. */
|
||||
class RFPSViewModel(
|
||||
private val fingerprintEnrollViewModel: FingerprintEnrollEnrollingViewModel,
|
||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
||||
orientationInteractor: OrientationInteractor,
|
||||
private val fingerprintManager: FingerprintManagerInteractor,
|
||||
private val fingerprintEnrollViewModel: FingerprintEnrollEnrollingViewModel,
|
||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
||||
orientationInteractor: OrientationInteractor,
|
||||
private val sensorInteractor: SensorInteractor,
|
||||
) : ViewModel() {
|
||||
|
||||
private val _textViewIsVisible = MutableStateFlow(false)
|
||||
@@ -62,7 +62,7 @@ class RFPSViewModel(
|
||||
val shouldAnimateIcon = _shouldAnimateIcon
|
||||
|
||||
private var enrollFlow: Flow<FingerEnrollState?> =
|
||||
fingerprintManager.sensorPropertiesInternal.filterNotNull().combine(
|
||||
sensorInteractor.sensorPropertiesInternal.filterNotNull().combine(
|
||||
fingerprintEnrollViewModel.enrollFlow
|
||||
) { props, enroll ->
|
||||
if (props.sensorType == FingerprintSensorType.REAR) {
|
||||
@@ -181,7 +181,7 @@ class RFPSViewModel(
|
||||
provider[FingerprintEnrollEnrollingViewModel::class],
|
||||
provider[FingerprintNavigationViewModel::class],
|
||||
biometricEnvironment.orientationInteractor,
|
||||
biometricEnvironment.fingerprintManagerInteractor,
|
||||
biometricEnvironment.createSensorPropertiesInteractor(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@ import com.android.settings.biometrics.fingerprint2.domain.interactor.Orientatio
|
||||
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.VibrationInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.SensorInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.model.DescriptionText
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.udfps.ui.model.HeaderText
|
||||
@@ -76,17 +76,17 @@ class UdfpsViewModel(
|
||||
enrollStageInteractor: EnrollStageInteractor,
|
||||
orientationInteractor: OrientationInteractor,
|
||||
udfpsEnrollInteractor: UdfpsEnrollInteractor,
|
||||
fingerprintManager: FingerprintManagerInteractor,
|
||||
accessibilityInteractor: AccessibilityInteractor,
|
||||
sensorRepository: FingerprintSensorInteractor,
|
||||
touchEventInteractor: TouchEventInteractor,
|
||||
sensorInteractor: SensorInteractor,
|
||||
) : ViewModel() {
|
||||
|
||||
private val isSetupWizard = flowOf(false)
|
||||
private var shouldResetErollment = false
|
||||
|
||||
private var _enrollState: Flow<FingerEnrollState?> =
|
||||
fingerprintManager.sensorPropertiesInternal.filterNotNull().combine(
|
||||
sensorInteractor.sensorPropertiesInternal.filterNotNull().combine(
|
||||
fingerprintEnrollEnrollingViewModel.enrollFlow
|
||||
) { props, enroll ->
|
||||
if (props.sensorType.isUdfps()) {
|
||||
@@ -198,8 +198,7 @@ class UdfpsViewModel(
|
||||
.distinctUntilChanged()
|
||||
|
||||
private val _touchEvent: MutableStateFlow<MotionEvent?> = MutableStateFlow(null)
|
||||
val touchEvent =
|
||||
_touchEvent.asStateFlow().filterNotNull()
|
||||
val touchEvent = _touchEvent.asStateFlow().filterNotNull()
|
||||
|
||||
/** Determines the current [EnrollStageModel] enrollment is in */
|
||||
private val enrollStage: Flow<EnrollStageModel> =
|
||||
@@ -267,11 +266,7 @@ class UdfpsViewModel(
|
||||
backgroundViewModel.background.filter { it }.collect { didGoToBackground() }
|
||||
}
|
||||
|
||||
viewModelScope.launch {
|
||||
touchEventInteractor.touchEvent.collect {
|
||||
_touchEvent.update { it }
|
||||
}
|
||||
}
|
||||
viewModelScope.launch { touchEventInteractor.touchEvent.collect { _touchEvent.update { it } } }
|
||||
}
|
||||
|
||||
/** Indicates if we should show the lottie. */
|
||||
@@ -430,10 +425,10 @@ class UdfpsViewModel(
|
||||
biometricEnvironment.enrollStageInteractor,
|
||||
biometricEnvironment.orientationInteractor,
|
||||
biometricEnvironment.udfpsEnrollInteractor,
|
||||
biometricEnvironment.fingerprintManagerInteractor,
|
||||
biometricEnvironment.accessibilityInteractor,
|
||||
biometricEnvironment.sensorInteractor,
|
||||
biometricEnvironment.touchEventInteractor,
|
||||
biometricEnvironment.createSensorPropertiesInteractor(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -16,27 +16,27 @@
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import com.android.settings.SettingsApplication
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.CanEnrollFingerprintsInteractor
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/** Models the UI state for [FingerprintEnrollConfirmationV2Fragment] */
|
||||
class FingerprintEnrollConfirmationViewModel(
|
||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
||||
fingerprintInteractor: FingerprintManagerInteractor,
|
||||
private val canEnrollFingerprintsInteractor: CanEnrollFingerprintsInteractor,
|
||||
) : ViewModel() {
|
||||
|
||||
/**
|
||||
* Indicates if the add another button is possible. This should only be true when the user is able
|
||||
* to enroll more fingerprints.
|
||||
*/
|
||||
val isAddAnotherButtonVisible: Flow<Boolean> = fingerprintInteractor.canEnrollFingerprints
|
||||
val isAddAnotherButtonVisible: Flow<Boolean> =
|
||||
canEnrollFingerprintsInteractor.canEnrollFingerprints
|
||||
|
||||
/**
|
||||
* Indicates that the user has clicked the next button and is done with fingerprint enrollment.
|
||||
@@ -64,7 +64,7 @@ class FingerprintEnrollConfirmationViewModel(
|
||||
val provider = ViewModelProvider(this[VIEW_MODEL_STORE_OWNER_KEY]!!)
|
||||
FingerprintEnrollConfirmationViewModel(
|
||||
provider[FingerprintNavigationViewModel::class],
|
||||
biometricEnvironment!!.fingerprintManagerInteractor,
|
||||
biometricEnvironment!!.createCanEnrollFingerprintsInteractor(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -27,7 +27,7 @@ import com.android.settings.SettingsApplication
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.AccessibilityInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.SensorInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.SetupWizard
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Education
|
||||
@@ -44,20 +44,20 @@ import kotlinx.coroutines.launch
|
||||
|
||||
/** Models the UI state for fingerprint enroll education */
|
||||
class FingerprintEnrollFindSensorViewModel(
|
||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
||||
private val fingerprintEnrollViewModel: FingerprintEnrollViewModel,
|
||||
private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
||||
backgroundViewModel: BackgroundViewModel,
|
||||
fingerprintFlowViewModel: FingerprintFlowViewModel,
|
||||
accessibilityInteractor: AccessibilityInteractor,
|
||||
foldStateInteractor: FoldStateInteractor,
|
||||
orientationInteractor: OrientationInteractor,
|
||||
fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
||||
private val fingerprintEnrollViewModel: FingerprintEnrollViewModel,
|
||||
private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
||||
backgroundViewModel: BackgroundViewModel,
|
||||
fingerprintFlowViewModel: FingerprintFlowViewModel,
|
||||
accessibilityInteractor: AccessibilityInteractor,
|
||||
foldStateInteractor: FoldStateInteractor,
|
||||
orientationInteractor: OrientationInteractor,
|
||||
sensorInteractor: SensorInteractor,
|
||||
) : ViewModel() {
|
||||
|
||||
/** Represents the stream of sensor type. */
|
||||
val sensorType: Flow<FingerprintSensorType> =
|
||||
fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map { it.sensorType }
|
||||
sensorInteractor.sensorPropertiesInternal.filterNotNull().map { it.sensorType }
|
||||
private val _isUdfps: Flow<Boolean> =
|
||||
sensorType.map {
|
||||
it == FingerprintSensorType.UDFPS_OPTICAL || it == FingerprintSensorType.UDFPS_ULTRASONIC
|
||||
@@ -216,7 +216,7 @@ class FingerprintEnrollFindSensorViewModel(
|
||||
biometricEnvironment.accessibilityInteractor,
|
||||
biometricEnvironment.foldStateInteractor,
|
||||
biometricEnvironment.orientationInteractor,
|
||||
biometricEnvironment.fingerprintManagerInteractor,
|
||||
biometricEnvironment.createSensorPropertiesInteractor(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -22,7 +22,7 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import com.android.settings.SettingsApplication
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.SensorInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintFlow
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Introduction
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||
@@ -30,13 +30,13 @@ import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/** A view model for fingerprint enroll introduction. */
|
||||
class FingerprintEnrollIntroViewModel(
|
||||
val navigationViewModel: FingerprintNavigationViewModel,
|
||||
fingerprintFlowViewModel: FingerprintFlowViewModel,
|
||||
fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
val navigationViewModel: FingerprintNavigationViewModel,
|
||||
fingerprintFlowViewModel: FingerprintFlowViewModel,
|
||||
sensorInteractor: SensorInteractor,
|
||||
) : ViewModel() {
|
||||
|
||||
/** Represents a stream of [FingerprintSensor] */
|
||||
val sensor: Flow<FingerprintSensor?> = fingerprintManagerInteractor.sensorPropertiesInternal
|
||||
val sensor: Flow<FingerprintSensor?> = sensorInteractor.sensorPropertiesInternal
|
||||
|
||||
/** Represents a stream of [FingerprintFlow] */
|
||||
val fingerprintFlow: Flow<FingerprintFlow?> = fingerprintFlowViewModel.fingerprintFlow
|
||||
@@ -67,7 +67,7 @@ class FingerprintEnrollIntroViewModel(
|
||||
FingerprintEnrollIntroViewModel(
|
||||
provider[FingerprintNavigationViewModel::class],
|
||||
provider[FingerprintFlowViewModel::class],
|
||||
biometricEnvironment!!.fingerprintManagerInteractor,
|
||||
biometricEnvironment!!.createSensorPropertiesInteractor(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,8 @@ import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import com.android.settings.SettingsApplication
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.EnrollFingerprintInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.SensorInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Education
|
||||
@@ -42,9 +43,10 @@ import kotlinx.coroutines.flow.update
|
||||
|
||||
/** Represents all of the fingerprint information needed for a fingerprint enrollment process. */
|
||||
class FingerprintEnrollViewModel(
|
||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
||||
val navigationViewModel: FingerprintNavigationViewModel,
|
||||
gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
||||
val navigationViewModel: FingerprintNavigationViewModel,
|
||||
private val sensorInteractor: SensorInteractor,
|
||||
private val fingerprintEnrollInteractor: EnrollFingerprintInteractor,
|
||||
) : ViewModel() {
|
||||
|
||||
/**
|
||||
@@ -67,7 +69,7 @@ class FingerprintEnrollViewModel(
|
||||
|
||||
/** Represents the stream of [FingerprintSensorType] */
|
||||
val sensorType: Flow<FingerprintSensorType?> =
|
||||
fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map { it.sensorType }
|
||||
sensorInteractor.sensorPropertiesInternal.filterNotNull().map { it.sensorType }
|
||||
|
||||
/**
|
||||
* A flow that contains a [FingerprintEnrollViewModel] which contains the relevant information for
|
||||
@@ -90,7 +92,7 @@ class FingerprintEnrollViewModel(
|
||||
enrollReason != null &&
|
||||
enrollOptions != null
|
||||
) {
|
||||
fingerprintManagerInteractor
|
||||
fingerprintEnrollInteractor
|
||||
.enroll(hardwareAuthToken.token, enrollReason, enrollOptions)
|
||||
.collect { emit(it) }
|
||||
}
|
||||
@@ -137,9 +139,10 @@ class FingerprintEnrollViewModel(
|
||||
val biometricEnvironment = settingsApplication.biometricEnvironment
|
||||
val provider = ViewModelProvider(this[VIEW_MODEL_STORE_OWNER_KEY]!!)
|
||||
FingerprintEnrollViewModel(
|
||||
biometricEnvironment!!.fingerprintManagerInteractor,
|
||||
provider[FingerprintGatekeeperViewModel::class],
|
||||
provider[FingerprintNavigationViewModel::class],
|
||||
biometricEnvironment!!.createSensorPropertiesInteractor(),
|
||||
biometricEnvironment!!.createFingerprintEnrollInteractor(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import com.android.settings.SettingsApplication
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.GenerateChallengeInteractor
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
@@ -50,7 +50,7 @@ sealed interface GatekeeperInfo {
|
||||
* in as a parameter to this class.
|
||||
*/
|
||||
class FingerprintGatekeeperViewModel(
|
||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor
|
||||
private val generateChallengeInteractor: GenerateChallengeInteractor
|
||||
) : ViewModel() {
|
||||
|
||||
private var _gatekeeperInfo: MutableStateFlow<GatekeeperInfo?> = MutableStateFlow(null)
|
||||
@@ -78,7 +78,7 @@ class FingerprintGatekeeperViewModel(
|
||||
_gatekeeperInfo.update { GatekeeperInfo.Invalid }
|
||||
} else {
|
||||
viewModelScope.launch {
|
||||
val res = fingerprintManagerInteractor.generateChallenge(theGatekeeperPasswordHandle!!)
|
||||
val res = generateChallengeInteractor.generateChallenge(theGatekeeperPasswordHandle!!)
|
||||
_gatekeeperInfo.update { GatekeeperInfo.GatekeeperPasswordInfo(res.second, res.first) }
|
||||
if (shouldStartTimer) {
|
||||
startTimeout()
|
||||
@@ -119,7 +119,7 @@ class FingerprintGatekeeperViewModel(
|
||||
val settingsApplication =
|
||||
this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as SettingsApplication
|
||||
val biometricEnvironment = settingsApplication.biometricEnvironment
|
||||
FingerprintGatekeeperViewModel(biometricEnvironment!!.fingerprintManagerInteractor)
|
||||
FingerprintGatekeeperViewModel(biometricEnvironment!!.createGenerateChallengeInteractor())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@ import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import com.android.settings.SettingsApplication
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.SensorInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintFlow
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Finish
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.TransitionStep
|
||||
@@ -46,7 +46,7 @@ import kotlinx.coroutines.flow.update
|
||||
* fragments/viewmodels that want to consume these events. It should provide no additional
|
||||
* functionality beyond what is available in [FingerprintNavigationStep].
|
||||
*/
|
||||
class FingerprintNavigationViewModel(fingerprintManagerInteractor: FingerprintManagerInteractor) :
|
||||
class FingerprintNavigationViewModel(sensorInteractor: SensorInteractor) :
|
||||
ViewModel() {
|
||||
|
||||
private val _flowInternal: MutableStateFlow<FingerprintFlow?> = MutableStateFlow(null)
|
||||
@@ -55,7 +55,7 @@ class FingerprintNavigationViewModel(fingerprintManagerInteractor: FingerprintMa
|
||||
combine(
|
||||
_flowInternal,
|
||||
_hasConfirmedDeviceCredential,
|
||||
fingerprintManagerInteractor.sensorPropertiesInternal,
|
||||
sensorInteractor.sensorPropertiesInternal,
|
||||
) { flow, hasConfirmed, sensorType ->
|
||||
if (flow == null || sensorType == null) {
|
||||
return@combine null
|
||||
@@ -144,7 +144,7 @@ class FingerprintNavigationViewModel(fingerprintManagerInteractor: FingerprintMa
|
||||
val settingsApplication =
|
||||
this[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] as SettingsApplication
|
||||
val biometricEnvironment = settingsApplication.biometricEnvironment
|
||||
FingerprintNavigationViewModel(biometricEnvironment!!.fingerprintManagerInteractor)
|
||||
FingerprintNavigationViewModel(biometricEnvironment!!.createSensorPropertiesInteractor())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -35,19 +35,16 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.Preference
|
||||
import androidx.preference.PreferenceCategory
|
||||
import com.android.internal.widget.LockPatternUtils
|
||||
import com.android.settings.R
|
||||
import com.android.settings.SettingsApplication
|
||||
import com.android.settings.Utils.SETTINGS_PACKAGE_NAME
|
||||
import com.android.settings.biometrics.BiometricEnrollBase
|
||||
import com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST
|
||||
import com.android.settings.biometrics.BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY
|
||||
import com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED
|
||||
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroductionInternal
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepositoryImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintEnrollInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.PressToAuthInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
@@ -223,35 +220,24 @@ class FingerprintSettingsV2Fragment :
|
||||
val fingerprintSensorProvider =
|
||||
FingerprintSensorRepositoryImpl(fingerprintManager, backgroundDispatcher, lifecycleScope)
|
||||
val pressToAuthInteractor = PressToAuthInteractorImpl(context, backgroundDispatcher)
|
||||
val fingerprintEnrollStateRepository =
|
||||
FingerprintEnrollInteractorImpl(
|
||||
requireContext().applicationContext,
|
||||
fingerprintManager,
|
||||
Settings,
|
||||
)
|
||||
|
||||
val interactor =
|
||||
FingerprintManagerInteractorImpl(
|
||||
context.applicationContext,
|
||||
backgroundDispatcher,
|
||||
fingerprintManager,
|
||||
fingerprintSensorProvider,
|
||||
GatekeeperPasswordProvider(LockPatternUtils(context.applicationContext)),
|
||||
fingerprintEnrollStateRepository,
|
||||
)
|
||||
|
||||
val token = intent.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN)
|
||||
val challenge = intent.getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, -1L)
|
||||
val application = requireActivity().application as SettingsApplication
|
||||
val environment =
|
||||
application.biometricEnvironment
|
||||
?: throw IllegalStateException("The biometric environment must be present")
|
||||
|
||||
navigationViewModel =
|
||||
ViewModelProvider(
|
||||
this,
|
||||
FingerprintSettingsNavigationViewModel.FingerprintSettingsNavigationModelFactory(
|
||||
userId,
|
||||
interactor,
|
||||
backgroundDispatcher,
|
||||
token,
|
||||
challenge,
|
||||
environment.createFingerprintsEnrolledInteractor(),
|
||||
environment.createGenerateChallengeInteractor(),
|
||||
),
|
||||
)[FingerprintSettingsNavigationViewModel::class.java]
|
||||
|
||||
@@ -260,9 +246,14 @@ class FingerprintSettingsV2Fragment :
|
||||
this,
|
||||
FingerprintSettingsViewModel.FingerprintSettingsViewModelFactory(
|
||||
userId,
|
||||
interactor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
environment.createCanEnrollFingerprintsInteractor(),
|
||||
environment.createSensorPropertiesInteractor(),
|
||||
environment.createAuthenticateInteractor(),
|
||||
environment.createRenameFingerprintInteractor(),
|
||||
environment.createRemoveFingerprintInteractor(),
|
||||
environment.createFingerprintsEnrolledInteractor(),
|
||||
),
|
||||
)[FingerprintSettingsViewModel::class.java]
|
||||
|
||||
|
@@ -21,7 +21,8 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.android.settings.biometrics.BiometricEnrollBase
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.EnrolledFingerprintsInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.GenerateChallengeInteractor
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@@ -33,10 +34,11 @@ import kotlinx.coroutines.launch
|
||||
/** A Viewmodel that represents the navigation of the FingerprintSettings activity. */
|
||||
class FingerprintSettingsNavigationViewModel(
|
||||
private val userId: Int,
|
||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
tokenInit: ByteArray?,
|
||||
challengeInit: Long?,
|
||||
private val enrolledFingerprintsInteractor: EnrolledFingerprintsInteractor,
|
||||
private val generateChallengeInteractor: GenerateChallengeInteractor,
|
||||
) : ViewModel() {
|
||||
|
||||
private var token = tokenInit
|
||||
@@ -52,7 +54,7 @@ class FingerprintSettingsNavigationViewModel(
|
||||
_nextStep.update { LaunchConfirmDeviceCredential(userId) }
|
||||
} else {
|
||||
viewModelScope.launch {
|
||||
if (fingerprintManagerInteractor.enrolledFingerprints.last()?.isEmpty() == true) {
|
||||
if (enrolledFingerprintsInteractor.enrolledFingerprints.last()?.isEmpty() == true) {
|
||||
_nextStep.update { EnrollFirstFingerprint(userId, null, challenge, token) }
|
||||
} else {
|
||||
showSettingsHelper()
|
||||
@@ -148,13 +150,13 @@ class FingerprintSettingsNavigationViewModel(
|
||||
}
|
||||
|
||||
private suspend fun launchEnrollNextStep(gateKeeperPasswordHandle: Long?) {
|
||||
fingerprintManagerInteractor.enrolledFingerprints.collect {
|
||||
enrolledFingerprintsInteractor.enrolledFingerprints.collect {
|
||||
if (it?.isEmpty() == true) {
|
||||
_nextStep.update { EnrollFirstFingerprint(userId, gateKeeperPasswordHandle, null, null) }
|
||||
} else {
|
||||
viewModelScope.launch(backgroundDispatcher) {
|
||||
val challengePair =
|
||||
fingerprintManagerInteractor.generateChallenge(gateKeeperPasswordHandle!!)
|
||||
generateChallengeInteractor.generateChallenge(gateKeeperPasswordHandle!!)
|
||||
challenge = challengePair.first
|
||||
token = challengePair.second
|
||||
|
||||
@@ -174,10 +176,11 @@ class FingerprintSettingsNavigationViewModel(
|
||||
|
||||
class FingerprintSettingsNavigationModelFactory(
|
||||
private val userId: Int,
|
||||
private val interactor: FingerprintManagerInteractor,
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
private val token: ByteArray?,
|
||||
private val challenge: Long?,
|
||||
private val enrolledFingerprintsInteractor: EnrolledFingerprintsInteractor,
|
||||
private val generateChallengeInteractor: GenerateChallengeInteractor,
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -185,10 +188,11 @@ class FingerprintSettingsNavigationViewModel(
|
||||
|
||||
return FingerprintSettingsNavigationViewModel(
|
||||
userId,
|
||||
interactor,
|
||||
backgroundDispatcher,
|
||||
token,
|
||||
challenge,
|
||||
enrolledFingerprintsInteractor,
|
||||
generateChallengeInteractor,
|
||||
)
|
||||
as T
|
||||
}
|
||||
|
@@ -21,7 +21,12 @@ import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.AuthenitcateInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.CanEnrollFingerprintsInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.EnrolledFingerprintsInteractor
|
||||
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.SensorInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
@@ -49,9 +54,14 @@ private const val DEBUG = false
|
||||
/** Models the UI state for fingerprint settings. */
|
||||
class FingerprintSettingsViewModel(
|
||||
private val userId: Int,
|
||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
private val navigationViewModel: FingerprintSettingsNavigationViewModel,
|
||||
private val canEnrollFingerprintsInteractor: CanEnrollFingerprintsInteractor,
|
||||
private val sensorInteractor: SensorInteractor,
|
||||
private val authenticateInteractor: AuthenitcateInteractor,
|
||||
private val renameFingerprintInteractor: RenameFingerprintInteractor,
|
||||
private val removeFingerprintInteractor: RemoveFingerprintInteractor,
|
||||
private val enrolledFingerprintsInteractor: EnrolledFingerprintsInteractor,
|
||||
) : ViewModel() {
|
||||
private val _enrolledFingerprints: MutableStateFlow<List<FingerprintData>?> =
|
||||
MutableStateFlow(null)
|
||||
@@ -62,19 +72,18 @@ class FingerprintSettingsViewModel(
|
||||
|
||||
/** Represents the stream of the information of "Add Fingerprint" preference. */
|
||||
val addFingerprintPrefInfo: Flow<Pair<Boolean, Int>> =
|
||||
_enrolledFingerprints.filterOnlyWhenSettingsIsShown().transform {
|
||||
emit(
|
||||
Pair(
|
||||
fingerprintManagerInteractor.canEnrollFingerprints.first(),
|
||||
fingerprintManagerInteractor.maxEnrollableFingerprints.first(),
|
||||
)
|
||||
)
|
||||
_enrolledFingerprints.filterOnlyWhenSettingsIsShown().combine(
|
||||
canEnrollFingerprintsInteractor.canEnrollFingerprints
|
||||
) { _, canEnrollFingerprints ->
|
||||
Pair(canEnrollFingerprints, canEnrollFingerprintsInteractor.maxFingerprintsEnrollable())
|
||||
}
|
||||
|
||||
/** Represents the stream of visibility of sfps preference. */
|
||||
val isSfpsPrefVisible: Flow<Boolean> =
|
||||
_enrolledFingerprints.filterOnlyWhenSettingsIsShown().transform {
|
||||
emit(fingerprintManagerInteractor.hasSideFps() == true && !it.isNullOrEmpty())
|
||||
_enrolledFingerprints.filterOnlyWhenSettingsIsShown().combine(sensorInteractor.hasSideFps) {
|
||||
fingerprints,
|
||||
hasSideFps ->
|
||||
hasSideFps && !fingerprints.isNullOrEmpty()
|
||||
}
|
||||
|
||||
private val _isShowingDialog: MutableStateFlow<PreferenceViewModel?> = MutableStateFlow(null)
|
||||
@@ -90,10 +99,10 @@ class FingerprintSettingsViewModel(
|
||||
private val _consumerShouldAuthenticate: MutableStateFlow<Boolean> = MutableStateFlow(false)
|
||||
|
||||
private val _fingerprintSensorType: Flow<FingerprintSensorType> =
|
||||
fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map { it.sensorType }
|
||||
sensorInteractor.sensorPropertiesInternal.filterNotNull().map { it.sensorType }
|
||||
|
||||
private val _sensorNullOrEmpty: Flow<Boolean> =
|
||||
fingerprintManagerInteractor.sensorPropertiesInternal.map { it == null }
|
||||
sensorInteractor.sensorPropertiesInternal.map { it == null }
|
||||
|
||||
private val _isLockedOut: MutableStateFlow<FingerprintAuthAttemptModel.Error?> =
|
||||
MutableStateFlow(null)
|
||||
@@ -172,7 +181,7 @@ class FingerprintSettingsViewModel(
|
||||
while (it && navigationViewModel.nextStep.value is ShowSettings) {
|
||||
Log.d(TAG, "canAuthenticate authing")
|
||||
attemptingAuth()
|
||||
when (val authAttempt = fingerprintManagerInteractor.authenticate()) {
|
||||
when (val authAttempt = authenticateInteractor.authenticate()) {
|
||||
is FingerprintAuthAttemptModel.Success -> {
|
||||
onAuthSuccess(authAttempt)
|
||||
emit(authAttempt)
|
||||
@@ -243,7 +252,7 @@ class FingerprintSettingsViewModel(
|
||||
/** A request to delete a fingerprint */
|
||||
fun deleteFingerprint(fp: FingerprintData) {
|
||||
viewModelScope.launch(backgroundDispatcher) {
|
||||
if (fingerprintManagerInteractor.removeFingerprint(fp)) {
|
||||
if (removeFingerprintInteractor.removeFingerprint(fp)) {
|
||||
updateEnrolledFingerprints()
|
||||
}
|
||||
}
|
||||
@@ -252,7 +261,7 @@ class FingerprintSettingsViewModel(
|
||||
/** A request to rename a fingerprint */
|
||||
fun renameFingerprint(fp: FingerprintData, newName: String) {
|
||||
viewModelScope.launch {
|
||||
fingerprintManagerInteractor.renameFingerprint(fp, newName)
|
||||
renameFingerprintInteractor.renameFingerprint(fp, newName)
|
||||
updateEnrolledFingerprints()
|
||||
}
|
||||
}
|
||||
@@ -271,7 +280,7 @@ class FingerprintSettingsViewModel(
|
||||
}
|
||||
|
||||
private suspend fun updateEnrolledFingerprints() {
|
||||
_enrolledFingerprints.update { fingerprintManagerInteractor.enrolledFingerprints.first() }
|
||||
_enrolledFingerprints.update { enrolledFingerprintsInteractor.enrolledFingerprints.first() }
|
||||
}
|
||||
|
||||
/** Used to indicate whether the consumer of the view model is ready for authentication. */
|
||||
@@ -288,9 +297,14 @@ class FingerprintSettingsViewModel(
|
||||
|
||||
class FingerprintSettingsViewModelFactory(
|
||||
private val userId: Int,
|
||||
private val interactor: FingerprintManagerInteractor,
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
private val navigationViewModel: FingerprintSettingsNavigationViewModel,
|
||||
private val canEnrollFingerprintsInteractor: CanEnrollFingerprintsInteractor,
|
||||
private val sensorInteractor: SensorInteractor,
|
||||
private val authenticateInteractor: AuthenitcateInteractor,
|
||||
private val renameFingerprintInteractor: RenameFingerprintInteractor,
|
||||
private val removeFingerprintInteractor: RemoveFingerprintInteractor,
|
||||
private val enrolledFingerprintsInteractor: EnrolledFingerprintsInteractor,
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -298,9 +312,14 @@ class FingerprintSettingsViewModel(
|
||||
|
||||
return FingerprintSettingsViewModel(
|
||||
userId,
|
||||
interactor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
canEnrollFingerprintsInteractor,
|
||||
sensorInteractor,
|
||||
authenticateInteractor,
|
||||
renameFingerprintInteractor,
|
||||
removeFingerprintInteractor,
|
||||
enrolledFingerprintsInteractor,
|
||||
)
|
||||
as T
|
||||
}
|
||||
|
@@ -111,9 +111,10 @@ class Injector(step: FingerprintNavigationStep.UiStep) {
|
||||
|
||||
var fingerprintEnrollViewModel =
|
||||
FingerprintEnrollViewModel(
|
||||
fingerprintManagerInteractor,
|
||||
gatekeeperViewModel,
|
||||
navigationViewModel,
|
||||
fingerprintManagerInteractor,
|
||||
fingerprintManagerInteractor,
|
||||
)
|
||||
|
||||
var fingerprintEnrollEnrollingViewModel =
|
||||
|
@@ -22,7 +22,14 @@ import android.hardware.biometrics.SensorProperties
|
||||
import android.hardware.fingerprint.FingerprintEnrollOptions
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.AuthenitcateInteractor
|
||||
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.domain.interactor.SensorInteractor
|
||||
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
|
||||
@@ -35,7 +42,15 @@ import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
/** Fake to be used by other classes to easily fake the FingerprintManager implementation. */
|
||||
class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
|
||||
class FakeFingerprintManagerInteractor :
|
||||
AuthenitcateInteractor,
|
||||
CanEnrollFingerprintsInteractor,
|
||||
EnrolledFingerprintsInteractor,
|
||||
EnrollFingerprintInteractor,
|
||||
GenerateChallengeInteractor,
|
||||
RemoveFingerprintInteractor,
|
||||
RenameFingerprintInteractor,
|
||||
SensorInteractor {
|
||||
|
||||
var enrollableFingerprints: Int = 5
|
||||
var enrolledFingerprintsInternal: MutableList<FingerprintData> = mutableListOf()
|
||||
@@ -67,19 +82,22 @@ class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
|
||||
override val enrolledFingerprints: Flow<List<FingerprintData>> = flow {
|
||||
emit(enrolledFingerprintsInternal)
|
||||
}
|
||||
|
||||
override val canEnrollFingerprints: Flow<Boolean> = flow {
|
||||
emit(enrolledFingerprintsInternal.size < enrollableFingerprints)
|
||||
}
|
||||
|
||||
override val sensorPropertiesInternal: Flow<FingerprintSensor?> = flow { emit(sensorProp) }
|
||||
override fun maxFingerprintsEnrollable(): Int {
|
||||
return enrollableFingerprints
|
||||
}
|
||||
|
||||
override val maxEnrollableFingerprints: Flow<Int> = flow { emit(enrollableFingerprints) }
|
||||
override val sensorPropertiesInternal: Flow<FingerprintSensor?> = flow { emit(sensorProp) }
|
||||
override val hasSideFps: Flow<Boolean> =
|
||||
flowOf(sensorProp.sensorType == FingerprintSensorType.POWER_BUTTON)
|
||||
|
||||
override suspend fun enroll(
|
||||
hardwareAuthToken: ByteArray?,
|
||||
enrollReason: EnrollReason,
|
||||
fingerprintEnrollOptions: FingerprintEnrollOptions
|
||||
fingerprintEnrollOptions: FingerprintEnrollOptions,
|
||||
): Flow<FingerEnrollState> = flowOf(*enrollStateViewModel.toTypedArray())
|
||||
|
||||
override suspend fun removeFingerprint(fp: FingerprintData): Boolean {
|
||||
@@ -92,7 +110,4 @@ class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun hasSideFps(): Boolean {
|
||||
return sensorProp.sensorType == FingerprintSensorType.POWER_BUTTON
|
||||
}
|
||||
}
|
||||
|
@@ -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 }
|
||||
}
|
||||
|
@@ -99,9 +99,10 @@ class FingerprintEnrollFindSensorViewModelV2Test {
|
||||
backgroundViewModel.inForeground()
|
||||
enrollViewModel =
|
||||
FingerprintEnrollViewModel(
|
||||
fakeFingerprintManagerInteractor,
|
||||
gatekeeperViewModel,
|
||||
navigationViewModel,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
accessibilityInteractor =
|
||||
object : AccessibilityInteractor {
|
||||
|
@@ -49,8 +49,7 @@ class RFPSIconTouchViewModelTest {
|
||||
fun setup() {
|
||||
Dispatchers.setMain(backgroundDispatcher)
|
||||
testScope = TestScope(backgroundDispatcher)
|
||||
rfpsIconTouchViewModel =
|
||||
RFPSIconTouchViewModel()
|
||||
rfpsIconTouchViewModel = RFPSIconTouchViewModel()
|
||||
}
|
||||
|
||||
@After
|
||||
|
@@ -88,9 +88,10 @@ class FingerprintEnrollEnrollingViewModelTest {
|
||||
backgroundViewModel.inForeground()
|
||||
val fingerprintEnrollViewModel =
|
||||
FingerprintEnrollViewModel(
|
||||
fakeFingerprintManagerInteractor,
|
||||
gateKeeperViewModel,
|
||||
navigationViewModel,
|
||||
fakeFingerprintManagerInteractor,
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
enrollEnrollingViewModel =
|
||||
FingerprintEnrollEnrollingViewModel(fingerprintEnrollViewModel, backgroundViewModel)
|
||||
|
@@ -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)
|
||||
|
||||
|
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user