Moved FakeFingerprintManagerInteractor
Test: atest Bug: 295206367 Change-Id: If9f3b9dc88260c0725f70d3444c4f9a4b6ee5c2f
This commit is contained in:
@@ -55,6 +55,9 @@ android_library {
|
||||
],
|
||||
|
||||
srcs: ["src/**/*.java", "src/**/*.kt"],
|
||||
exclude_srcs: [
|
||||
"src/com/android/settings/biometrics/fingerprint2/shared/**/*.kt",
|
||||
],
|
||||
use_resource_processor: true,
|
||||
resource_dirs: [
|
||||
"res",
|
||||
@@ -113,6 +116,7 @@ android_library {
|
||||
"SystemUIUnfoldLib",
|
||||
"aconfig_settings_flags_lib",
|
||||
"android.content.pm.flags-aconfig-java",
|
||||
"FingerprintManagerInteractor",
|
||||
],
|
||||
|
||||
plugins: [
|
||||
|
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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.conversion
|
||||
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintSensorPropertyViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SensorStrength
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
|
||||
|
||||
class Util {
|
||||
companion object {
|
||||
fun sensorPropsToViewModel(
|
||||
props: FingerprintSensorPropertiesInternal
|
||||
): FingerprintSensorPropertyViewModel {
|
||||
val sensorStrength: SensorStrength =
|
||||
when (props.sensorStrength) {
|
||||
FingerprintSensorProperties.STRENGTH_CONVENIENCE -> SensorStrength.Convenient
|
||||
FingerprintSensorProperties.STRENGTH_WEAK -> SensorStrength.Weak
|
||||
FingerprintSensorProperties.STRENGTH_STRONG -> SensorStrength.Strong
|
||||
else -> SensorStrength.Unknown
|
||||
}
|
||||
val sensorType: SensorType =
|
||||
when (props.sensorType) {
|
||||
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL -> SensorType.Optical
|
||||
FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC -> SensorType.Ultrasonic
|
||||
FingerprintSensorProperties.TYPE_REAR -> SensorType.RFPS
|
||||
FingerprintSensorProperties.TYPE_POWER_BUTTON -> SensorType.SFPS
|
||||
else -> SensorType.Unknown
|
||||
}
|
||||
return FingerprintSensorPropertyViewModel(
|
||||
props.sensorId,
|
||||
sensorStrength,
|
||||
props.maxEnrollmentsPerUser,
|
||||
sensorType
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
fun EnrollReason.toOriginalReason(): Int {
|
||||
return when (this) {
|
||||
EnrollReason.EnrollEnrolling -> FingerprintManager.ENROLL_ENROLL
|
||||
EnrollReason.FindSensor -> FingerprintManager.ENROLL_FIND_SENSOR
|
||||
}
|
||||
}
|
@@ -21,15 +21,16 @@ import android.content.Intent
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.hardware.fingerprint.FingerprintManager.GenerateChallengeCallback
|
||||
import android.hardware.fingerprint.FingerprintManager.RemovalCallback
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
||||
import android.os.CancellationSignal
|
||||
import android.util.Log
|
||||
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
||||
import com.android.settings.biometrics.fingerprint2.conversion.Util
|
||||
import com.android.settings.biometrics.fingerprint2.conversion.toOriginalReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerEnrollStateViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.toOriginalReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollStateViewModel
|
||||
import com.android.settings.password.ChooseLockSettingsHelper
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
@@ -45,59 +46,6 @@ import kotlinx.coroutines.withContext
|
||||
|
||||
private const val TAG = "FingerprintManagerInteractor"
|
||||
|
||||
/** Encapsulates business logic related to managing fingerprints. */
|
||||
interface FingerprintManagerInteractor {
|
||||
/** Returns the list of current fingerprints. */
|
||||
val enrolledFingerprints: Flow<List<FingerprintViewModel>>
|
||||
|
||||
/** 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<FingerprintSensorPropertiesInternal?>
|
||||
|
||||
/** Runs [FingerprintManager.authenticate] */
|
||||
suspend fun authenticate(): FingerprintAuthAttemptViewModel
|
||||
|
||||
/**
|
||||
* 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
|
||||
* [FingerprintManager.enroll]
|
||||
*
|
||||
* @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. Returning the [FingerEnrollStateViewModel] that represents this fingerprint
|
||||
* enrollment state.
|
||||
*/
|
||||
suspend fun enroll(
|
||||
hardwareAuthToken: ByteArray?,
|
||||
enrollReason: EnrollReason,
|
||||
): Flow<FingerEnrollStateViewModel>
|
||||
|
||||
/**
|
||||
* Removes the given fingerprint, returning true if it was successfully removed and false
|
||||
* otherwise
|
||||
*/
|
||||
suspend fun removeFingerprint(fp: FingerprintViewModel): Boolean
|
||||
|
||||
/** Renames the given fingerprint if one exists */
|
||||
suspend fun renameFingerprint(fp: FingerprintViewModel, newName: String)
|
||||
|
||||
/** Indicates if the device has side fingerprint */
|
||||
suspend fun hasSideFps(): Boolean
|
||||
|
||||
/** Indicates if the press to auth feature has been enabled */
|
||||
suspend fun pressToAuthEnabled(): Boolean
|
||||
}
|
||||
|
||||
class FingerprintManagerInteractorImpl(
|
||||
applicationContext: Context,
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
@@ -144,7 +92,10 @@ class FingerprintManagerInteractorImpl(
|
||||
|
||||
override val sensorPropertiesInternal = flow {
|
||||
val sensorPropertiesInternal = fingerprintManager.sensorPropertiesInternal
|
||||
emit(if (sensorPropertiesInternal.isEmpty()) null else sensorPropertiesInternal.first())
|
||||
emit(
|
||||
if (sensorPropertiesInternal.isEmpty()) null
|
||||
else Util.sensorPropsToViewModel(sensorPropertiesInternal.first())
|
||||
)
|
||||
}
|
||||
|
||||
override val maxEnrollableFingerprints = flow { emit(maxFingerprints) }
|
||||
@@ -183,7 +134,7 @@ class FingerprintManagerInteractorImpl(
|
||||
cancellationSignal,
|
||||
applicationContext.userId,
|
||||
enrollmentCallback,
|
||||
enrollReason.toOriginalReason()
|
||||
enrollReason.toOriginalReason(),
|
||||
)
|
||||
awaitClose {
|
||||
// If the stream has not been ended, and the user has stopped collecting the flow
|
@@ -0,0 +1,13 @@
|
||||
// This library is mainly used for fakes which will be shared across are various types of tests
|
||||
// unit/robo/screenshot etc.
|
||||
//
|
||||
// This library shouldn't have many dependencies.
|
||||
android_library {
|
||||
name: "FingerprintManagerInteractor",
|
||||
srcs: [
|
||||
"**/*.kt"
|
||||
],
|
||||
static_libs: [
|
||||
"kotlinx-coroutines-android",
|
||||
],
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.settings.biometrics.fingerprint2.shared">
|
||||
</manifest>
|
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.shared.domain.interactor
|
||||
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintSensorPropertyViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollStateViewModel
|
||||
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<FingerprintViewModel>>
|
||||
|
||||
/** 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<FingerprintSensorPropertyViewModel?>
|
||||
|
||||
/** Runs the authenticate flow */
|
||||
suspend fun authenticate(): FingerprintAuthAttemptViewModel
|
||||
|
||||
/**
|
||||
* 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. Returning the [FingerEnrollStateViewModel] that represents this fingerprint
|
||||
* enrollment state.
|
||||
*/
|
||||
suspend fun enroll(
|
||||
hardwareAuthToken: ByteArray?,
|
||||
enrollReason: EnrollReason,
|
||||
): Flow<FingerEnrollStateViewModel>
|
||||
|
||||
/**
|
||||
* Removes the given fingerprint, returning true if it was successfully removed and false
|
||||
* otherwise
|
||||
*/
|
||||
suspend fun removeFingerprint(fp: FingerprintViewModel): Boolean
|
||||
|
||||
/** Renames the given fingerprint if one exists */
|
||||
suspend fun renameFingerprint(fp: FingerprintViewModel, newName: String)
|
||||
|
||||
/** Indicates if the device has side fingerprint */
|
||||
suspend fun hasSideFps(): Boolean
|
||||
|
||||
/** Indicates if the press to auth feature has been enabled */
|
||||
suspend fun pressToAuthEnabled(): Boolean
|
||||
|
||||
}
|
@@ -13,24 +13,16 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
||||
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
package com.android.settings.biometrics.fingerprint2.shared.model
|
||||
|
||||
/**
|
||||
* The reason for enrollment. Represents [FingerprintManager.EnrollReason]
|
||||
*/
|
||||
/** The reason for enrollment */
|
||||
enum class EnrollReason {
|
||||
/** The enroll happens on education screen. */
|
||||
/**
|
||||
* The enroll happens on education screen. This is to support legacy flows where we require the
|
||||
* user to touch the sensor before going ahead to the EnrollEnrolling flow
|
||||
*/
|
||||
FindSensor,
|
||||
/** The enroll happens on enrolling screen. */
|
||||
EnrollEnrolling
|
||||
}
|
||||
|
||||
/** Convert EnrollReason to original [FingerprintManager.EnrollReason]. */
|
||||
fun EnrollReason.toOriginalReason(): Int {
|
||||
return when (this) {
|
||||
EnrollReason.EnrollEnrolling -> FingerprintManager.ENROLL_ENROLL
|
||||
EnrollReason.FindSensor -> FingerprintManager.ENROLL_FIND_SENSOR
|
||||
}
|
||||
}
|
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
||||
package com.android.settings.biometrics.fingerprint2.shared.model
|
||||
|
||||
import android.annotation.StringRes
|
||||
|
@@ -32,3 +32,36 @@ sealed class FingerprintAuthAttemptViewModel {
|
||||
val message: String,
|
||||
) : FingerprintAuthAttemptViewModel()
|
||||
}
|
||||
|
||||
/** The various types of fingerprint sensors */
|
||||
sealed class SensorType {
|
||||
/** Rear fingerprint sensor */
|
||||
data object RFPS : SensorType()
|
||||
|
||||
/** Optical under display sensor */
|
||||
data object Optical : SensorType()
|
||||
|
||||
/** Ultrasonic under display sensor */
|
||||
data object Ultrasonic : SensorType()
|
||||
|
||||
/** Side fingerprint sensor */
|
||||
data object SFPS : SensorType()
|
||||
|
||||
/** Unkonwn fingerprint sensor */
|
||||
data object Unknown : SensorType()
|
||||
}
|
||||
|
||||
/** The strength of a given sensor */
|
||||
sealed class SensorStrength {
|
||||
data object Convenient : SensorStrength()
|
||||
data object Weak : SensorStrength()
|
||||
data object Strong : SensorStrength()
|
||||
data object Unknown : SensorStrength()
|
||||
}
|
||||
|
||||
data class FingerprintSensorPropertyViewModel(
|
||||
val sensorId: Int,
|
||||
val sensorStrength: SensorStrength,
|
||||
val maxEnrollmentsPerUser: Int,
|
||||
val sensorType: SensorType
|
||||
)
|
||||
|
@@ -29,6 +29,7 @@ import com.airbnb.lottie.LottieAnimationView
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintFindSensorAnimation
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollFindSensorViewModel
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import com.google.android.setupcompat.template.FooterBarMixin
|
||||
@@ -65,9 +66,9 @@ class FingerprintEnrollFindSensorV2Fragment : Fragment() {
|
||||
viewModel.sensorType.collect {
|
||||
contentLayoutId =
|
||||
when (it) {
|
||||
FingerprintSensorType.UDFPS_OPTICAL,
|
||||
FingerprintSensorType.UDFPS_ULTRASONIC -> R.layout.udfps_enroll_find_sensor_layout
|
||||
FingerprintSensorType.POWER_BUTTON -> R.layout.sfps_enroll_find_sensor_layout
|
||||
SensorType.Optical,
|
||||
SensorType.Ultrasonic -> R.layout.udfps_enroll_find_sensor_layout
|
||||
SensorType.SFPS -> R.layout.sfps_enroll_find_sensor_layout
|
||||
else -> R.layout.fingerprint_v2_enroll_find_sensor
|
||||
}
|
||||
}
|
||||
@@ -170,14 +171,14 @@ class FingerprintEnrollFindSensorV2Fragment : Fragment() {
|
||||
illustrationLottie?.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun setTexts(sensorType: FingerprintSensorType, view: GlifLayout) {
|
||||
private fun setTexts(sensorType: SensorType, view: GlifLayout) {
|
||||
when (sensorType) {
|
||||
FingerprintSensorType.UDFPS_OPTICAL,
|
||||
FingerprintSensorType.UDFPS_ULTRASONIC -> {
|
||||
SensorType.Optical,
|
||||
SensorType.Ultrasonic -> {
|
||||
view.setHeaderText(R.string.security_settings_udfps_enroll_find_sensor_title)
|
||||
view.setDescriptionText(R.string.security_settings_udfps_enroll_find_sensor_message)
|
||||
}
|
||||
FingerprintSensorType.POWER_BUTTON -> {
|
||||
SensorType.SFPS -> {
|
||||
view.setHeaderText(R.string.security_settings_sfps_enroll_find_sensor_title)
|
||||
view.setDescriptionText(R.string.security_settings_sfps_enroll_find_sensor_message)
|
||||
}
|
||||
|
@@ -35,10 +35,10 @@ import androidx.lifecycle.lifecycleScope
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Unicorn
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import com.google.android.setupcompat.template.FooterBarMixin
|
||||
import com.google.android.setupcompat.template.FooterButton
|
||||
import com.google.android.setupdesign.GlifLayout
|
||||
@@ -144,8 +144,8 @@ class FingerprintEnrollIntroV2Fragment : Fragment(R.layout.fingerprint_v2_enroll
|
||||
val iconShield: ImageView = view.requireViewById(R.id.icon_shield)
|
||||
val footerMessage6: TextView = view.requireViewById(R.id.footer_message_6)
|
||||
when (sensorType) {
|
||||
FingerprintSensorType.UDFPS_ULTRASONIC,
|
||||
FingerprintSensorType.UDFPS_OPTICAL -> {
|
||||
SensorType.Ultrasonic,
|
||||
SensorType.Optical -> {
|
||||
footerMessage6.visibility = View.VISIBLE
|
||||
iconShield.visibility = View.VISIBLE
|
||||
}
|
||||
|
@@ -20,6 +20,9 @@ import android.hardware.fingerprint.FingerprintManager
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollStateViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -42,13 +45,13 @@ class FingerprintEnrollFindSensorViewModel(
|
||||
orientationStateViewModel: OrientationStateViewModel
|
||||
) : ViewModel() {
|
||||
/** Represents the stream of sensor type. */
|
||||
val sensorType: Flow<FingerprintSensorType> =
|
||||
val sensorType: Flow<SensorType> =
|
||||
fingerprintEnrollViewModel.sensorType.filterWhenEducationIsShown()
|
||||
private val _isUdfps: Flow<Boolean> =
|
||||
sensorType.map {
|
||||
it == FingerprintSensorType.UDFPS_OPTICAL || it == FingerprintSensorType.UDFPS_ULTRASONIC
|
||||
it == SensorType.Optical || it == SensorType.Ultrasonic
|
||||
}
|
||||
private val _isSfps: Flow<Boolean> = sensorType.map { it == FingerprintSensorType.POWER_BUTTON }
|
||||
private val _isSfps: Flow<Boolean> = sensorType.map { it == SensorType.RFPS }
|
||||
private val _isRearSfps: Flow<Boolean> =
|
||||
combineTransform(_isSfps, _isUdfps) { v1, v2 -> !v1 && !v2 }
|
||||
|
||||
@@ -92,8 +95,8 @@ class FingerprintEnrollFindSensorViewModel(
|
||||
) { sensorType, hasValidGatekeeperInfo, gatekeeperInfo, navigationViewModel ->
|
||||
val shouldStartEnroll =
|
||||
navigationViewModel.currStep == Education &&
|
||||
sensorType != FingerprintSensorType.UDFPS_OPTICAL &&
|
||||
sensorType != FingerprintSensorType.UDFPS_ULTRASONIC &&
|
||||
sensorType != SensorType.Optical &&
|
||||
sensorType != SensorType.Ultrasonic &&
|
||||
hasValidGatekeeperInfo
|
||||
if (shouldStartEnroll) (gatekeeperInfo as GatekeeperInfo.GatekeeperPasswordInfo).token
|
||||
else null
|
||||
|
@@ -17,13 +17,14 @@ package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollStateViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import com.android.systemui.biometrics.shared.model.toSensorType
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.flowOn
|
||||
@@ -39,17 +40,15 @@ class FingerprintEnrollViewModel(
|
||||
backgroundDispatcher: CoroutineDispatcher,
|
||||
) : ViewModel() {
|
||||
|
||||
/** Represents the stream of [FingerprintSensorType] */
|
||||
val sensorType: Flow<FingerprintSensorType> =
|
||||
fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map {
|
||||
it.sensorType.toSensorType()
|
||||
}
|
||||
|
||||
private var _enrollReason: MutableStateFlow<EnrollReason> =
|
||||
MutableStateFlow(EnrollReason.FindSensor)
|
||||
private var _hardwareAuthToken: MutableStateFlow<ByteArray?> = MutableStateFlow(null)
|
||||
private var _consumerShouldEnroll: MutableStateFlow<Boolean> = MutableStateFlow(false)
|
||||
|
||||
/** Represents the stream of [FingerprintSensorType] */
|
||||
val sensorType: Flow<SensorType> =
|
||||
fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map { it.sensorType }
|
||||
|
||||
/**
|
||||
* A flow that contains a [FingerprintEnrollViewModel] which contains the relevant information for
|
||||
* an enrollment process
|
||||
|
@@ -20,7 +20,7 @@ import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -39,7 +39,7 @@ interface Validator {
|
||||
/**
|
||||
* The [EnrollType] for fingerprint enrollment indicates information on how the flow should behave.
|
||||
*/
|
||||
sealed class EnrollType()
|
||||
sealed class EnrollType
|
||||
|
||||
/** The default enrollment experience, typically called from Settings */
|
||||
object Default : EnrollType()
|
||||
|
@@ -21,7 +21,7 @@ import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
|
@@ -27,6 +27,7 @@ import kotlinx.coroutines.flow.update
|
||||
class FingerprintScrollViewModel : ViewModel() {
|
||||
|
||||
private val _hasReadConsentScreen: MutableStateFlow<Boolean> = MutableStateFlow(false)
|
||||
|
||||
/** Indicates if a user has consented to FingerprintEnrollment */
|
||||
val hasReadConsentScreen: Flow<Boolean> = _hasReadConsentScreen.asStateFlow()
|
||||
|
||||
@@ -35,7 +36,7 @@ class FingerprintScrollViewModel : ViewModel() {
|
||||
_hasReadConsentScreen.update { true }
|
||||
}
|
||||
|
||||
class FingerprintScrollViewModelFactory() : ViewModelProvider.Factory {
|
||||
class FingerprintScrollViewModelFactory : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
|
@@ -34,7 +34,6 @@ import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.Prefer
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.ShowSettings
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -55,7 +54,6 @@ object FingerprintSettingsViewBinder {
|
||||
challenge: Long?,
|
||||
challengeToken: ByteArray?
|
||||
)
|
||||
|
||||
/** Helper to launch an add fingerprint request */
|
||||
fun launchAddFingerprint(userId: Int, challengeToken: ByteArray?)
|
||||
/**
|
||||
@@ -63,10 +61,8 @@ object FingerprintSettingsViewBinder {
|
||||
* choose a PIN/PATTERN/PASS.
|
||||
*/
|
||||
fun launchConfirmOrChooseLock(userId: Int)
|
||||
|
||||
/** Used to indicate that FingerprintSettings is finished. */
|
||||
fun finish()
|
||||
|
||||
/** Indicates what result should be set for the returning callee */
|
||||
fun setResultExternal(resultCode: Int)
|
||||
/** Indicates the settings UI should be shown */
|
||||
|
@@ -106,8 +106,9 @@ class FingerprintSettingsRenameDialog : InstrumentedDialogFragment() {
|
||||
val dialog = FingerprintSettingsRenameDialog()
|
||||
val onClick =
|
||||
DialogInterface.OnClickListener { _, _ ->
|
||||
val dialogTextField = dialog.requireDialog()
|
||||
.requireViewById(R.id.fingerprint_rename_field) as ImeAwareEditText
|
||||
val dialogTextField =
|
||||
dialog.requireDialog().requireViewById(R.id.fingerprint_rename_field)
|
||||
as ImeAwareEditText
|
||||
val newName = dialogTextField.text.toString()
|
||||
if (!TextUtils.equals(newName, fp.name)) {
|
||||
Log.d(TAG, "rename $fp.name to $newName for $dialog")
|
||||
|
@@ -21,7 +21,7 @@ import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.android.settings.biometrics.BiometricEnrollBase
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@@ -32,17 +32,18 @@ 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 userId: Int,
|
||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
tokenInit: ByteArray?,
|
||||
challengeInit: Long?,
|
||||
) : ViewModel() {
|
||||
|
||||
private var token = tokenInit
|
||||
private var challenge = challengeInit
|
||||
|
||||
private val _nextStep: MutableStateFlow<NextStepViewModel?> = MutableStateFlow(null)
|
||||
|
||||
/** This flow represents the high level state for the FingerprintSettingsV2Fragment. */
|
||||
val nextStep: StateFlow<NextStepViewModel?> = _nextStep.asStateFlow()
|
||||
|
||||
@@ -118,8 +119,8 @@ class FingerprintSettingsNavigationViewModel(
|
||||
launchFinishSettings("Error, empty keyChallenge")
|
||||
return
|
||||
}
|
||||
token = theToken!!
|
||||
challenge = theChallenge!!
|
||||
token = theToken
|
||||
challenge = theChallenge
|
||||
|
||||
showSettingsHelper()
|
||||
}
|
||||
@@ -170,12 +171,13 @@ class FingerprintSettingsNavigationViewModel(
|
||||
private fun launchFinishSettings(reason: String, errorCode: Int) {
|
||||
_nextStep.update { FinishSettingsWithResult(errorCode, reason) }
|
||||
}
|
||||
|
||||
class FingerprintSettingsNavigationModelFactory(
|
||||
private val userId: Int,
|
||||
private val interactor: FingerprintManagerInteractor,
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
private val token: ByteArray?,
|
||||
private val challenge: Long?,
|
||||
private val userId: Int,
|
||||
private val interactor: FingerprintManagerInteractor,
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
private val token: ByteArray?,
|
||||
private val challenge: Long?,
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@@ -21,11 +21,10 @@ import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import com.android.systemui.biometrics.shared.model.toSensorType
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
@@ -90,10 +89,8 @@ class FingerprintSettingsViewModel(
|
||||
|
||||
private val _consumerShouldAuthenticate: MutableStateFlow<Boolean> = MutableStateFlow(false)
|
||||
|
||||
private val _fingerprintSensorType: Flow<FingerprintSensorType> =
|
||||
fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map {
|
||||
it.sensorType.toSensorType()
|
||||
}
|
||||
private val _fingerprintSensorType: Flow<SensorType> =
|
||||
fingerprintManagerInteractor.sensorPropertiesInternal.filterNotNull().map { it.sensorType }
|
||||
|
||||
private val _sensorNullOrEmpty: Flow<Boolean> =
|
||||
fingerprintManagerInteractor.sensorPropertiesInternal.map { it == null }
|
||||
@@ -149,10 +146,7 @@ class FingerprintSettingsViewModel(
|
||||
if (sensorNullOrEmpty) {
|
||||
return@combine false
|
||||
}
|
||||
if (
|
||||
listOf(FingerprintSensorType.UDFPS_ULTRASONIC, FingerprintSensorType.UDFPS_OPTICAL)
|
||||
.contains(sensorType)
|
||||
) {
|
||||
if (listOf(SensorType.Ultrasonic, SensorType.Optical).contains(sensorType)) {
|
||||
return@combine false
|
||||
}
|
||||
|
||||
|
@@ -61,6 +61,7 @@ android_robolectric_test {
|
||||
"flag-junit",
|
||||
"aconfig_settings_flags_lib",
|
||||
"platform-test-annotations",
|
||||
"Settings-testutils2",
|
||||
],
|
||||
|
||||
libs: [
|
||||
|
9
tests/shared/Android.bp
Normal file
9
tests/shared/Android.bp
Normal file
@@ -0,0 +1,9 @@
|
||||
android_library {
|
||||
name: "Settings-testutils2",
|
||||
srcs: [
|
||||
"src/**/*.kt"
|
||||
],
|
||||
libs: [
|
||||
"FingerprintManagerInteractor",
|
||||
],
|
||||
}
|
20
tests/shared/AndroidManifest.xml
Normal file
20
tests/shared/AndroidManifest.xml
Normal file
@@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 2022 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.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.settings.testutils2">
|
||||
</manifest>
|
@@ -14,18 +14,19 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.fingerprint2.domain.interactor
|
||||
package com.android.settings.testutils2
|
||||
|
||||
import android.hardware.biometrics.SensorProperties
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintSensorPropertyViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerEnrollStateViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollStateViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SensorStrength
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
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 {
|
||||
@@ -37,17 +38,8 @@ class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
|
||||
val enrollStateViewModel = FingerEnrollStateViewModel.EnrollProgress(1)
|
||||
var pressToAuthEnabled = true
|
||||
|
||||
var sensorProps =
|
||||
listOf(
|
||||
FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
emptyList() /* ComponentInfoInternal */,
|
||||
TYPE_POWER_BUTTON,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */
|
||||
)
|
||||
)
|
||||
var sensorProp =
|
||||
FingerprintSensorPropertyViewModel(0 /* sensorId */, SensorStrength.Strong, 5, SensorType.SFPS)
|
||||
|
||||
override suspend fun authenticate(): FingerprintAuthAttemptViewModel {
|
||||
return authenticateAttempt
|
||||
@@ -65,8 +57,8 @@ class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
|
||||
emit(enrolledFingerprintsInternal.size < enrollableFingerprints)
|
||||
}
|
||||
|
||||
override val sensorPropertiesInternal: Flow<FingerprintSensorPropertiesInternal?> = flow {
|
||||
emit(sensorProps.first())
|
||||
override val sensorPropertiesInternal: Flow<FingerprintSensorPropertyViewModel?> = flow {
|
||||
emit(sensorProp)
|
||||
}
|
||||
|
||||
override val maxEnrollableFingerprints: Flow<Int> = flow { emit(enrollableFingerprints) }
|
||||
@@ -74,7 +66,7 @@ class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
|
||||
override suspend fun enroll(
|
||||
hardwareAuthToken: ByteArray?,
|
||||
enrollReason: EnrollReason
|
||||
): Flow<FingerEnrollStateViewModel> = flow { emit(enrollStateViewModel) }
|
||||
): Flow<FingerEnrollStateViewModel> = flowOf(enrollStateViewModel)
|
||||
|
||||
override suspend fun removeFingerprint(fp: FingerprintViewModel): Boolean {
|
||||
return enrolledFingerprintsInternal.remove(fp)
|
||||
@@ -87,7 +79,7 @@ class FakeFingerprintManagerInteractor : FingerprintManagerInteractor {
|
||||
}
|
||||
|
||||
override suspend fun hasSideFps(): Boolean {
|
||||
return sensorProps.any { it.isAnySidefpsType }
|
||||
return sensorProp.sensorType == SensorType.SFPS
|
||||
}
|
||||
|
||||
override suspend fun pressToAuthEnabled(): Boolean {
|
@@ -28,6 +28,7 @@ android_test {
|
||||
"truth-prebuilt",
|
||||
"kotlinx_coroutines_test",
|
||||
"flag-junit",
|
||||
"Settings-testutils2",
|
||||
// Don't add SettingsLib libraries here - you can use them directly as they are in the
|
||||
// instrumented Settings app.
|
||||
],
|
||||
|
@@ -26,12 +26,12 @@ 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.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.EnrollReason.FindSensor
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerEnrollStateViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollStateViewModel
|
||||
import com.android.settings.password.ChooseLockSettingsHelper
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.cancelAndJoin
|
||||
@@ -283,7 +283,7 @@ class FingerprintManagerInteractorTest {
|
||||
testScope.runTest {
|
||||
val token = byteArrayOf(5, 3, 2)
|
||||
var result: FingerEnrollStateViewModel? = null
|
||||
val job = launch { underTest.enroll(token, FindSensor).collect { result = it } }
|
||||
val job = launch { underTest.enroll(token, EnrollReason.FindSensor).collect { result = it } }
|
||||
val enrollCallback: ArgumentCaptor<FingerprintManager.EnrollmentCallback> = argumentCaptor()
|
||||
runCurrent()
|
||||
|
||||
@@ -307,7 +307,7 @@ class FingerprintManagerInteractorTest {
|
||||
testScope.runTest {
|
||||
val token = byteArrayOf(5, 3, 2)
|
||||
var result: FingerEnrollStateViewModel? = null
|
||||
val job = launch { underTest.enroll(token, FindSensor).collect { result = it } }
|
||||
val job = launch { underTest.enroll(token, EnrollReason.FindSensor).collect { result = it } }
|
||||
val enrollCallback: ArgumentCaptor<FingerprintManager.EnrollmentCallback> = argumentCaptor()
|
||||
runCurrent()
|
||||
|
||||
@@ -331,7 +331,7 @@ class FingerprintManagerInteractorTest {
|
||||
testScope.runTest {
|
||||
val token = byteArrayOf(5, 3, 2)
|
||||
var result: FingerEnrollStateViewModel? = null
|
||||
val job = launch { underTest.enroll(token, FindSensor).collect { result = it } }
|
||||
val job = launch { underTest.enroll(token, EnrollReason.FindSensor).collect { result = it } }
|
||||
val enrollCallback: ArgumentCaptor<FingerprintManager.EnrollmentCallback> = argumentCaptor()
|
||||
runCurrent()
|
||||
|
||||
|
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.fingerprint2.settings.viewmodel
|
||||
package com.android.settings.fingerprint2.ui.settings
|
||||
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.android.settings.biometrics.BiometricEnrollBase
|
||||
@@ -26,7 +26,7 @@ import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.Finish
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.LaunchConfirmDeviceCredential
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.NextStepViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.ShowSettings
|
||||
import com.android.settings.fingerprint2.domain.interactor.FakeFingerprintManagerInteractor
|
||||
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -132,22 +132,6 @@ class FingerprintSettingsNavigationViewModelTest {
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstEnrollment_fails() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf()
|
||||
|
||||
var nextStep: NextStepViewModel? = null
|
||||
val job = launch { underTest.nextStep.collect { nextStep = it } }
|
||||
|
||||
underTest.onConfirmDevice(true, 10L)
|
||||
underTest.onEnrollFirstFailure("We failed!!")
|
||||
runCurrent()
|
||||
|
||||
assertThat(nextStep).isInstanceOf(FinishSettings::class.java)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun firstEnrollment_failsWithReason() =
|
||||
testScope.runTest {
|
@@ -14,18 +14,18 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.fingerprint2.settings.viewmodel
|
||||
package com.android.settings.fingerprint2.ui.settings
|
||||
|
||||
import android.hardware.biometrics.SensorProperties
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintSensorPropertyViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SensorStrength
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SensorType
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FingerprintSettingsNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FingerprintSettingsViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.PreferenceViewModel
|
||||
import com.android.settings.fingerprint2.domain.interactor.FakeFingerprintManagerInteractor
|
||||
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
@@ -95,16 +95,12 @@ class FingerprintSettingsViewModelTest {
|
||||
@Test
|
||||
fun authenticate_DoesNotRun_ifOptical() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.sensorProps =
|
||||
listOf(
|
||||
FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
emptyList() /* ComponentInfoInternal */,
|
||||
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */
|
||||
)
|
||||
fakeFingerprintManagerInteractor.sensorProp =
|
||||
FingerprintSensorPropertyViewModel(
|
||||
0 /* sensorId */,
|
||||
SensorStrength.Strong,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
SensorType.Optical,
|
||||
)
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(FingerprintViewModel("a", 1, 3L))
|
||||
@@ -135,16 +131,12 @@ class FingerprintSettingsViewModelTest {
|
||||
@Test
|
||||
fun authenticate_DoesNotRun_ifUltrasonic() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.sensorProps =
|
||||
listOf(
|
||||
FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
emptyList() /* ComponentInfoInternal */,
|
||||
FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */
|
||||
)
|
||||
fakeFingerprintManagerInteractor.sensorProp =
|
||||
FingerprintSensorPropertyViewModel(
|
||||
0 /* sensorId */,
|
||||
SensorStrength.Strong,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
SensorType.Ultrasonic,
|
||||
)
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(FingerprintViewModel("a", 1, 3L))
|
||||
@@ -173,16 +165,12 @@ class FingerprintSettingsViewModelTest {
|
||||
@Test
|
||||
fun authenticate_DoesRun_ifNotUdfps() =
|
||||
testScope.runTest {
|
||||
fakeFingerprintManagerInteractor.sensorProps =
|
||||
listOf(
|
||||
FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
emptyList() /* ComponentInfoInternal */,
|
||||
FingerprintSensorProperties.TYPE_POWER_BUTTON,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */
|
||||
)
|
||||
fakeFingerprintManagerInteractor.sensorProp =
|
||||
FingerprintSensorPropertyViewModel(
|
||||
0 /* sensorId */,
|
||||
SensorStrength.Strong,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
SensorType.SFPS
|
||||
)
|
||||
fakeFingerprintManagerInteractor.enrolledFingerprintsInternal =
|
||||
mutableListOf(FingerprintViewModel("a", 1, 3L))
|
||||
@@ -383,16 +371,12 @@ class FingerprintSettingsViewModelTest {
|
||||
}
|
||||
|
||||
private fun setupAuth(): MutableList<FingerprintViewModel> {
|
||||
fakeFingerprintManagerInteractor.sensorProps =
|
||||
listOf(
|
||||
FingerprintSensorPropertiesInternal(
|
||||
0 /* sensorId */,
|
||||
SensorProperties.STRENGTH_STRONG,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
emptyList() /* ComponentInfoInternal */,
|
||||
FingerprintSensorProperties.TYPE_POWER_BUTTON,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */
|
||||
)
|
||||
fakeFingerprintManagerInteractor.sensorProp =
|
||||
FingerprintSensorPropertyViewModel(
|
||||
0 /* sensorId */,
|
||||
SensorStrength.Strong,
|
||||
5 /* maxEnrollmentsPerUser */,
|
||||
SensorType.SFPS
|
||||
)
|
||||
val fingerprints =
|
||||
mutableListOf(FingerprintViewModel("a", 1, 3L), FingerprintViewModel("b", 2, 5L))
|
Reference in New Issue
Block a user