Updating navigation view model
Test: atest com.android.settings.fingerprint2.ui.enrollment.modules.enrolling.rfps.viewmodel com.android.settings.fingerprint2.ui.enrollment.viewmodel com.android.settings.fingerprint2.ui.settings com.android.settings.fingerprint2.domain.interactor com.android.settings.fingerprint2.enrollment.viewmodel Bug: 295205754 Change-Id: I210712ab76050b89452fb871cd2a4fb28bfd4012
This commit is contained in:
@@ -57,7 +57,7 @@ android_library {
|
||||
"src/**/*.kt",
|
||||
],
|
||||
exclude_srcs: [
|
||||
"src/com/android/settings/biometrics/fingerprint2/shared/**/*.kt",
|
||||
"src/com/android/settings/biometrics/fingerprint2/lib/**/*.kt",
|
||||
],
|
||||
use_resource_processor: true,
|
||||
resource_dirs: [
|
||||
|
@@ -20,8 +20,8 @@ import android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERR
|
||||
import android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_UNABLE_TO_PROCESS
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||
|
||||
object Util {
|
||||
fun EnrollReason.toOriginalReason(): Int {
|
||||
@@ -71,6 +71,4 @@ object Util {
|
||||
this == FINGERPRINT_ERROR_CANCELED,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.ComponentInfoInternal
|
||||
import android.hardware.biometrics.SensorLocationInternal
|
||||
import android.hardware.biometrics.SensorProperties
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.hardware.fingerprint.FingerprintSensorProperties
|
||||
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal
|
||||
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
|
||||
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.stateIn
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
/**
|
||||
* Provides the [FingerprintSensor]
|
||||
*
|
||||
* TODO(b/313493336): Move this to systemui
|
||||
*/
|
||||
interface FingerprintSensorRepo {
|
||||
/** Get the [FingerprintSensor] */
|
||||
val fingerprintSensor: Flow<FingerprintSensor>
|
||||
}
|
||||
|
||||
class FingerprintSensorRepoImpl(
|
||||
fingerprintManager: FingerprintManager,
|
||||
backgroundDispatcher: CoroutineDispatcher,
|
||||
activityScope: CoroutineScope,
|
||||
) : FingerprintSensorRepo {
|
||||
|
||||
override val fingerprintSensor: Flow<FingerprintSensor> =
|
||||
callbackFlow {
|
||||
val callback =
|
||||
object : IFingerprintAuthenticatorsRegisteredCallback.Stub() {
|
||||
override fun onAllAuthenticatorsRegistered(
|
||||
sensors: List<FingerprintSensorPropertiesInternal>
|
||||
) {
|
||||
if (sensors.isEmpty()) {
|
||||
trySend(DEFAULT_PROPS)
|
||||
} else {
|
||||
trySend(sensors[0].toFingerprintSensor())
|
||||
}
|
||||
}
|
||||
}
|
||||
withContext(backgroundDispatcher) {
|
||||
fingerprintManager?.addAuthenticatorsRegisteredCallback(callback)
|
||||
}
|
||||
awaitClose {}
|
||||
}
|
||||
.stateIn(activityScope, started = SharingStarted.Eagerly, initialValue = DEFAULT_PROPS)
|
||||
|
||||
companion object {
|
||||
private const val TAG = "FingerprintSensorRepoImpl"
|
||||
|
||||
private val DEFAULT_PROPS =
|
||||
FingerprintSensorPropertiesInternal(
|
||||
-1 /* sensorId */,
|
||||
SensorProperties.STRENGTH_CONVENIENCE,
|
||||
0 /* maxEnrollmentsPerUser */,
|
||||
listOf<ComponentInfoInternal>(),
|
||||
FingerprintSensorProperties.TYPE_UNKNOWN,
|
||||
false /* halControlsIllumination */,
|
||||
true /* resetLockoutRequiresHardwareAuthToken */,
|
||||
listOf<SensorLocationInternal>(SensorLocationInternal.DEFAULT),
|
||||
)
|
||||
.toFingerprintSensor()
|
||||
}
|
||||
}
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
* 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.
|
||||
@@ -14,13 +14,24 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2.repository
|
||||
package com.android.settings.biometrics.fingerprint2.data.repository
|
||||
|
||||
import android.content.Context
|
||||
import android.provider.Settings
|
||||
import com.android.settings.biometrics.fingerprint2.shared.data.repository.PressToAuthProvider
|
||||
|
||||
class PressToAuthProviderImpl(val context: Context) : PressToAuthProvider {
|
||||
/** Interface that indicates if press to auth is on or off. */
|
||||
interface PressToAuthRepo {
|
||||
/** Indicates true if the PressToAuth feature is enabled, false otherwise. */
|
||||
val isEnabled: Boolean
|
||||
}
|
||||
|
||||
/** Indicates whether or not the press to auth feature is enabled. */
|
||||
class PressToAuthRepoImpl(private val context: Context) : PressToAuthRepo {
|
||||
/**
|
||||
* Gets the status of the press to auth feature.
|
||||
*
|
||||
* Returns whether or not the press to auth feature is enabled.
|
||||
*/
|
||||
override val isEnabled: Boolean
|
||||
get() {
|
||||
var toReturn: Int =
|
||||
@@ -43,7 +54,7 @@ class PressToAuthProviderImpl(val context: Context) : PressToAuthProvider {
|
||||
context.contentResolver,
|
||||
Settings.Secure.SFPS_PERFORMANT_AUTH_ENABLED,
|
||||
toReturn,
|
||||
context.userId
|
||||
context.userId,
|
||||
)
|
||||
}
|
||||
return (toReturn == 1)
|
@@ -26,16 +26,16 @@ import android.util.Log
|
||||
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
||||
import com.android.settings.biometrics.fingerprint2.conversion.Util.toEnrollError
|
||||
import com.android.settings.biometrics.fingerprint2.conversion.Util.toOriginalReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.data.repository.PressToAuthProvider
|
||||
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.FingerprintFlow
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SetupWizard
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepo
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.PressToAuthRepo
|
||||
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.biometrics.fingerprint2.lib.model.FingerprintFlow
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.SetupWizard
|
||||
import com.android.settings.password.ChooseLockSettingsHelper
|
||||
import com.android.systemui.biometrics.shared.model.toFingerprintSensor
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
import kotlinx.coroutines.CancellableContinuation
|
||||
@@ -57,8 +57,9 @@ class FingerprintManagerInteractorImpl(
|
||||
applicationContext: Context,
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
private val fingerprintManager: FingerprintManager,
|
||||
fingerprintSensorRepo: FingerprintSensorRepo,
|
||||
private val gatekeeperPasswordProvider: GatekeeperPasswordProvider,
|
||||
private val pressToAuthProvider: PressToAuthProvider,
|
||||
private val pressToAuthRepo: PressToAuthRepo,
|
||||
private val fingerprintFlow: FingerprintFlow,
|
||||
) : FingerprintManagerInteractor {
|
||||
|
||||
@@ -100,13 +101,7 @@ class FingerprintManagerInteractorImpl(
|
||||
)
|
||||
}
|
||||
|
||||
override val sensorPropertiesInternal = flow {
|
||||
val sensorPropertiesInternal = fingerprintManager.sensorPropertiesInternal
|
||||
emit(
|
||||
if (sensorPropertiesInternal.isEmpty()) null
|
||||
else sensorPropertiesInternal.first().toFingerprintSensor()
|
||||
)
|
||||
}
|
||||
override val sensorPropertiesInternal = fingerprintSensorRepo.fingerprintSensor
|
||||
|
||||
override val maxEnrollableFingerprints = flow { emit(maxFingerprints) }
|
||||
|
||||
@@ -136,8 +131,7 @@ class FingerprintManagerInteractorImpl(
|
||||
totalSteps = remaining + 1
|
||||
}
|
||||
|
||||
trySend(FingerEnrollState.EnrollProgress(remaining, totalSteps!!)).onFailure {
|
||||
error ->
|
||||
trySend(FingerEnrollState.EnrollProgress(remaining, totalSteps!!)).onFailure { error ->
|
||||
Log.d(TAG, "onEnrollmentProgress($remaining) failed to send, due to $error")
|
||||
}
|
||||
|
||||
@@ -148,13 +142,16 @@ class FingerprintManagerInteractorImpl(
|
||||
}
|
||||
|
||||
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") }
|
||||
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") }
|
||||
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 }
|
||||
@@ -185,14 +182,14 @@ class FingerprintManagerInteractorImpl(
|
||||
override fun onRemovalError(
|
||||
fp: android.hardware.fingerprint.Fingerprint,
|
||||
errMsgId: Int,
|
||||
errString: CharSequence
|
||||
errString: CharSequence,
|
||||
) {
|
||||
it.resume(false)
|
||||
}
|
||||
|
||||
override fun onRemovalSucceeded(
|
||||
fp: android.hardware.fingerprint.Fingerprint?,
|
||||
remaining: Int
|
||||
remaining: Int,
|
||||
) {
|
||||
it.resume(true)
|
||||
}
|
||||
@@ -200,7 +197,7 @@ class FingerprintManagerInteractorImpl(
|
||||
fingerprintManager.remove(
|
||||
android.hardware.fingerprint.Fingerprint(fp.name, fp.fingerId, fp.deviceId),
|
||||
applicationContext.userId,
|
||||
callback
|
||||
callback,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -215,7 +212,7 @@ class FingerprintManagerInteractorImpl(
|
||||
}
|
||||
|
||||
override suspend fun pressToAuthEnabled(): Boolean = suspendCancellableCoroutine {
|
||||
it.resume(pressToAuthProvider.isEnabled)
|
||||
it.resume(pressToAuthRepo.isEnabled)
|
||||
}
|
||||
|
||||
override suspend fun authenticate(): FingerprintAuthAttemptModel =
|
||||
@@ -249,7 +246,7 @@ class FingerprintManagerInteractorImpl(
|
||||
cancellationSignal,
|
||||
authenticationCallback,
|
||||
null,
|
||||
applicationContext.userId
|
||||
applicationContext.userId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -14,5 +14,5 @@
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.android.settings.biometrics.fingerprint2.shared">
|
||||
package="com.android.settings.biometrics.fingerprint2.lib">
|
||||
</manifest>
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
* 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.
|
||||
@@ -14,12 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2.shared.domain.interactor
|
||||
package com.android.settings.biometrics.fingerprint2.lib.domain.interactor
|
||||
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollState
|
||||
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
|
||||
|
||||
@@ -56,8 +56,8 @@ interface FingerprintManagerInteractor {
|
||||
|
||||
/**
|
||||
* Runs [FingerprintManager.enroll] with the [hardwareAuthToken] and [EnrollReason] for this
|
||||
* enrollment. Returning the [FingerEnrollState] that represents this fingerprint
|
||||
* enrollment state.
|
||||
* enrollment. Returning the [FingerEnrollState] that represents this fingerprint enrollment
|
||||
* state.
|
||||
*/
|
||||
suspend fun enroll(
|
||||
hardwareAuthToken: ByteArray?,
|
||||
@@ -78,5 +78,4 @@ interface FingerprintManagerInteractor {
|
||||
|
||||
/** Indicates if the press to auth feature has been enabled */
|
||||
suspend fun pressToAuthEnabled(): Boolean
|
||||
|
||||
}
|
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2.shared.model
|
||||
package com.android.settings.biometrics.fingerprint2.lib.model
|
||||
|
||||
/** The reason for enrollment */
|
||||
enum class EnrollReason {
|
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2.shared.model
|
||||
package com.android.settings.biometrics.fingerprint2.lib.model
|
||||
|
||||
import android.annotation.StringRes
|
||||
|
||||
@@ -28,16 +28,12 @@ sealed class FingerEnrollState {
|
||||
*
|
||||
* Progress is obtained by (totalStepsRequired - remainingSteps) / totalStepsRequired
|
||||
*/
|
||||
data class EnrollProgress(
|
||||
val remainingSteps: Int,
|
||||
val totalStepsRequired: Int,
|
||||
) : FingerEnrollState()
|
||||
data class EnrollProgress(val remainingSteps: Int, val totalStepsRequired: Int) :
|
||||
FingerEnrollState()
|
||||
|
||||
/** Represents that recoverable error has been encountered during enrollment. */
|
||||
data class EnrollHelp(
|
||||
@StringRes val helpMsgId: Int,
|
||||
val helpString: String,
|
||||
) : FingerEnrollState()
|
||||
data class EnrollHelp(@StringRes val helpMsgId: Int, val helpString: String) :
|
||||
FingerEnrollState()
|
||||
|
||||
/** Represents that an unrecoverable error has been encountered and the operation is complete. */
|
||||
data class EnrollError(
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2023 The Android Open Source Project
|
||||
* 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.
|
||||
@@ -14,21 +14,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2.shared.model
|
||||
|
||||
data class FingerprintData(
|
||||
val name: String,
|
||||
val fingerId: Int,
|
||||
val deviceId: Long,
|
||||
)
|
||||
package com.android.settings.biometrics.fingerprint2.lib.model
|
||||
|
||||
/** Information indicating whether an auth was successful or not */
|
||||
sealed class FingerprintAuthAttemptModel {
|
||||
data class Success(
|
||||
val fingerId: Int,
|
||||
) : FingerprintAuthAttemptModel()
|
||||
/** Indicates a successful auth attempt has occurred for [fingerId] */
|
||||
data class Success(val fingerId: Int) : FingerprintAuthAttemptModel()
|
||||
|
||||
data class Error(
|
||||
val error: Int,
|
||||
val message: String,
|
||||
) : FingerprintAuthAttemptModel()
|
||||
/** Indicates a failed auth attempt has occurred. */
|
||||
data class Error(val error: Int, val message: String) : FingerprintAuthAttemptModel()
|
||||
}
|
@@ -14,14 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2.shared.data.repository
|
||||
package com.android.settings.biometrics.fingerprint2.lib.model
|
||||
|
||||
/**
|
||||
* Interface that indicates if press to auth is on or off.
|
||||
*/
|
||||
interface PressToAuthProvider {
|
||||
/**
|
||||
* Indicates true if the PressToAuth feature is enabled, false otherwise.
|
||||
*/
|
||||
val isEnabled: Boolean
|
||||
}
|
||||
/** Basic information about an enrolled fingerprint */
|
||||
data class FingerprintData(val name: String, val fingerId: Int, val deviceId: Long)
|
@@ -14,10 +14,11 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2.shared.model
|
||||
package com.android.settings.biometrics.fingerprint2.lib.model
|
||||
|
||||
/**
|
||||
* The [FingerprintFlow] for fingerprint enrollment indicates information on how the flow should behave.
|
||||
* The [FingerprintFlow] for fingerprint enrollment indicates information on how the flow should
|
||||
* behave.
|
||||
*/
|
||||
sealed class FingerprintFlow
|
||||
|
||||
@@ -32,3 +33,6 @@ data object Unicorn : FingerprintFlow()
|
||||
|
||||
/** Flow to specify settings type */
|
||||
data object Settings : FingerprintFlow()
|
||||
|
||||
/** Indicates that the fast enroll experience should occur */
|
||||
data object FastEnroll : FingerprintFlow()
|
@@ -21,7 +21,6 @@ import android.content.Intent
|
||||
import android.content.res.Configuration
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.os.Bundle
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.view.accessibility.AccessibilityManager
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
@@ -31,16 +30,18 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.android.internal.widget.LockPatternUtils
|
||||
import com.android.settings.R
|
||||
import com.android.settings.SettingsApplication
|
||||
import com.android.settings.SetupWizardUtils
|
||||
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.RESULT_FINISHED
|
||||
import com.android.settings.biometrics.GatekeeperPasswordProvider
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepoImpl
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.PressToAuthRepoImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SetupWizard
|
||||
import com.android.settings.biometrics.fingerprint2.repository.PressToAuthProviderImpl
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.SetupWizard
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollConfirmationV2Fragment
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollEnrollingV2Fragment
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollFindSensorV2Fragment
|
||||
@@ -49,20 +50,24 @@ import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enroll
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.AccessibilityViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.BackgroundViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Confirmation
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Education
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Enrollment
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintAction
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollEnrollingViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollFindSensorViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollIntroViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.ConfirmDeviceCredential
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Confirmation
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Education
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Enrollment
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Init
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Introduction
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.TransitionStep
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Finish
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FoldStateViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Intro
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.LaunchConfirmDeviceCredential
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.OrientationStateViewModel
|
||||
import com.android.settings.password.ChooseLockGeneric
|
||||
import com.android.settings.password.ChooseLockSettingsHelper
|
||||
@@ -71,7 +76,6 @@ import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import com.google.android.setupcompat.util.WizardManagerHelper
|
||||
import com.google.android.setupdesign.util.ThemeHelper
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@@ -83,7 +87,7 @@ private const val TAG = "FingerprintEnrollmentV2Activity"
|
||||
*/
|
||||
class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
private lateinit var fingerprintEnrollEnrollingViewModel: FingerprintEnrollEnrollingViewModel
|
||||
private lateinit var navigationViewModel: FingerprintEnrollNavigationViewModel
|
||||
private lateinit var navigationViewModel: FingerprintNavigationViewModel
|
||||
private lateinit var gatekeeperViewModel: FingerprintGatekeeperViewModel
|
||||
private lateinit var fingerprintEnrollViewModel: FingerprintEnrollViewModel
|
||||
private lateinit var accessibilityViewModel: AccessibilityViewModel
|
||||
@@ -91,6 +95,7 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
private lateinit var orientationStateViewModel: OrientationStateViewModel
|
||||
private lateinit var fingerprintScrollViewModel: FingerprintScrollViewModel
|
||||
private lateinit var backgroundViewModel: BackgroundViewModel
|
||||
private lateinit var fingerprintFlowViewModel: FingerprintFlowViewModel
|
||||
private val coroutineDispatcher = Dispatchers.Default
|
||||
|
||||
/** Result listener for ChooseLock activity flow. */
|
||||
@@ -119,6 +124,7 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
super.onResume()
|
||||
backgroundViewModel.inForeground()
|
||||
}
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
foldStateViewModel.onConfigurationChange(newConfig)
|
||||
@@ -127,8 +133,20 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
private fun onConfirmDevice(resultCode: Int, data: Intent?) {
|
||||
val wasSuccessful = resultCode == RESULT_FINISHED || resultCode == Activity.RESULT_OK
|
||||
val gateKeeperPasswordHandle = data?.getExtra(EXTRA_KEY_GK_PW_HANDLE) as Long?
|
||||
|
||||
lifecycleScope.launch {
|
||||
val confirmDeviceResult =
|
||||
if (wasSuccessful) {
|
||||
FingerprintAction.CONFIRM_DEVICE_SUCCESS
|
||||
} else {
|
||||
FingerprintAction.CONFIRM_DEVICE_FAIL
|
||||
}
|
||||
gatekeeperViewModel.onConfirmDevice(wasSuccessful, gateKeeperPasswordHandle)
|
||||
navigationViewModel.update(
|
||||
confirmDeviceResult,
|
||||
ConfirmDeviceCredential::class,
|
||||
"$TAG#onConfirmDevice",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,14 +174,21 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
ViewModelProvider(this, BackgroundViewModel.BackgroundViewModelFactory())[
|
||||
BackgroundViewModel::class.java]
|
||||
|
||||
fingerprintFlowViewModel =
|
||||
ViewModelProvider(this, FingerprintFlowViewModel.FingerprintFlowViewModelFactory(enrollType))[
|
||||
FingerprintFlowViewModel::class.java]
|
||||
|
||||
val interactor =
|
||||
val fingerprintSensorRepo =
|
||||
FingerprintSensorRepoImpl(fingerprintManager, backgroundDispatcher, lifecycleScope)
|
||||
|
||||
val fingerprintManagerInteractor =
|
||||
FingerprintManagerInteractorImpl(
|
||||
context,
|
||||
backgroundDispatcher,
|
||||
fingerprintManager,
|
||||
fingerprintSensorRepo,
|
||||
GatekeeperPasswordProvider(LockPatternUtils(context)),
|
||||
PressToAuthProviderImpl(context),
|
||||
PressToAuthRepoImpl(context),
|
||||
enrollType,
|
||||
)
|
||||
|
||||
@@ -171,27 +196,37 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
val token = intent.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN)
|
||||
val gatekeeperInfo = FingerprintGatekeeperViewModel.toGateKeeperInfo(challenge, token)
|
||||
|
||||
val hasConfirmedDeviceCredential = gatekeeperInfo is GatekeeperInfo.GatekeeperPasswordInfo
|
||||
|
||||
navigationViewModel =
|
||||
ViewModelProvider(
|
||||
this,
|
||||
FingerprintNavigationViewModel.FingerprintNavigationViewModelFactory(
|
||||
Init,
|
||||
hasConfirmedDeviceCredential,
|
||||
fingerprintFlowViewModel,
|
||||
fingerprintManagerInteractor,
|
||||
),
|
||||
)[FingerprintNavigationViewModel::class.java]
|
||||
// Initialize FingerprintEnrollIntroViewModel
|
||||
ViewModelProvider(
|
||||
this,
|
||||
FingerprintEnrollIntroViewModel.FingerprintEnrollIntoViewModelFactory(
|
||||
navigationViewModel,
|
||||
fingerprintFlowViewModel,
|
||||
fingerprintManagerInteractor,
|
||||
),
|
||||
)[FingerprintEnrollIntroViewModel::class.java]
|
||||
|
||||
gatekeeperViewModel =
|
||||
ViewModelProvider(
|
||||
this,
|
||||
FingerprintGatekeeperViewModel.FingerprintGatekeeperViewModelFactory(
|
||||
gatekeeperInfo,
|
||||
interactor,
|
||||
)
|
||||
fingerprintManagerInteractor,
|
||||
),
|
||||
)[FingerprintGatekeeperViewModel::class.java]
|
||||
|
||||
navigationViewModel =
|
||||
ViewModelProvider(
|
||||
this,
|
||||
FingerprintEnrollNavigationViewModel.FingerprintEnrollNavigationViewModelFactory(
|
||||
backgroundDispatcher,
|
||||
interactor,
|
||||
gatekeeperViewModel,
|
||||
gatekeeperInfo is GatekeeperInfo.GatekeeperPasswordInfo,
|
||||
enrollType,
|
||||
)
|
||||
)[FingerprintEnrollNavigationViewModel::class.java]
|
||||
|
||||
// Initialize FoldStateViewModel
|
||||
foldStateViewModel =
|
||||
ViewModelProvider(this, FoldStateViewModel.FoldStateViewModelFactory(context))[
|
||||
@@ -203,10 +238,10 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
ViewModelProvider(
|
||||
this,
|
||||
FingerprintEnrollViewModel.FingerprintEnrollViewModelFactory(
|
||||
interactor,
|
||||
fingerprintManagerInteractor,
|
||||
gatekeeperViewModel,
|
||||
navigationViewModel,
|
||||
)
|
||||
),
|
||||
)[FingerprintEnrollViewModel::class.java]
|
||||
|
||||
// Initialize scroll view model
|
||||
@@ -220,7 +255,7 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
this,
|
||||
AccessibilityViewModel.AccessibilityViewModelFactory(
|
||||
getSystemService(AccessibilityManager::class.java)!!
|
||||
)
|
||||
),
|
||||
)[AccessibilityViewModel::class.java]
|
||||
|
||||
// Initialize OrientationViewModel
|
||||
@@ -234,8 +269,8 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
this,
|
||||
FingerprintEnrollEnrollingViewModel.FingerprintEnrollEnrollingViewModelFactory(
|
||||
fingerprintEnrollViewModel,
|
||||
backgroundViewModel
|
||||
)
|
||||
backgroundViewModel,
|
||||
),
|
||||
)[FingerprintEnrollEnrollingViewModel::class.java]
|
||||
|
||||
// Initialize FingerprintEnrollFindSensorViewModel
|
||||
@@ -248,36 +283,48 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
backgroundViewModel,
|
||||
accessibilityViewModel,
|
||||
foldStateViewModel,
|
||||
orientationStateViewModel
|
||||
)
|
||||
orientationStateViewModel,
|
||||
fingerprintFlowViewModel,
|
||||
),
|
||||
)[FingerprintEnrollFindSensorViewModel::class.java]
|
||||
|
||||
// Initialize RFPS View Model
|
||||
ViewModelProvider(
|
||||
this,
|
||||
RFPSViewModel.RFPSViewModelFactory(fingerprintEnrollEnrollingViewModel)
|
||||
RFPSViewModel.RFPSViewModelFactory(fingerprintEnrollEnrollingViewModel, navigationViewModel),
|
||||
)[RFPSViewModel::class.java]
|
||||
lifecycleScope.launch {
|
||||
navigationViewModel.currentStep.collect { step ->
|
||||
if (step is Init) {
|
||||
Log.d(TAG, "FingerprintNav.init($step)")
|
||||
navigationViewModel.update(FingerprintAction.ACTIVITY_CREATED, Init::class, "$TAG#init")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
navigationViewModel.navigationViewModel
|
||||
.filterNotNull()
|
||||
.combine(fingerprintEnrollViewModel.sensorType) { nav, sensorType -> Pair(nav, sensorType) }
|
||||
.collect { (nav, sensorType) ->
|
||||
Log.d(TAG, "navigationStep $nav")
|
||||
fingerprintEnrollViewModel.sensorTypeCached = sensorType
|
||||
val isForward = nav.forward
|
||||
val currStep = nav.currStep
|
||||
val theClass: Class<Fragment>? =
|
||||
when (currStep) {
|
||||
Confirmation -> FingerprintEnrollConfirmationV2Fragment::class.java as Class<Fragment>
|
||||
Education -> FingerprintEnrollFindSensorV2Fragment::class.java as Class<Fragment>
|
||||
navigationViewModel.navigateTo.filterNotNull().collect { step ->
|
||||
if (step is ConfirmDeviceCredential) {
|
||||
launchConfirmOrChooseLock(userId)
|
||||
navigationViewModel.update(
|
||||
FingerprintAction.TRANSITION_FINISHED,
|
||||
TransitionStep::class,
|
||||
"$TAG#launchConfirmOrChooseLock",
|
||||
)
|
||||
} else {
|
||||
val theClass: Fragment? =
|
||||
when (step) {
|
||||
Confirmation -> FingerprintEnrollConfirmationV2Fragment()
|
||||
is Education -> {
|
||||
FingerprintEnrollFindSensorV2Fragment(step.sensor.sensorType)
|
||||
}
|
||||
is Enrollment -> {
|
||||
when (sensorType) {
|
||||
FingerprintSensorType.REAR -> RFPSEnrollFragment::class.java as Class<Fragment>
|
||||
else -> FingerprintEnrollEnrollingV2Fragment::class.java as Class<Fragment>
|
||||
when (step.sensor.sensorType) {
|
||||
FingerprintSensorType.REAR -> RFPSEnrollFragment()
|
||||
else -> FingerprintEnrollEnrollingV2Fragment()
|
||||
}
|
||||
}
|
||||
Intro -> FingerprintEnrollIntroV2Fragment::class.java as Class<Fragment>
|
||||
Introduction -> FingerprintEnrollIntroV2Fragment()
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -291,18 +338,30 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
.setReorderingAllowed(true)
|
||||
.add(R.id.fragment_container_view, theClass, null)
|
||||
.commit()
|
||||
} else {
|
||||
navigationViewModel.update(
|
||||
FingerprintAction.TRANSITION_FINISHED,
|
||||
TransitionStep::class,
|
||||
"$TAG#fragmentManager.add($theClass)",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currStep is Finish) {
|
||||
if (currStep.resultCode != null) {
|
||||
finishActivity(currStep.resultCode)
|
||||
lifecycleScope.launch {
|
||||
navigationViewModel.shouldFinish.filterNotNull().collect {
|
||||
Log.d(TAG, "FingerprintSettingsNav.finishing($it)")
|
||||
if (it.result != null) {
|
||||
finishActivity(it.result as Int)
|
||||
} else {
|
||||
finish()
|
||||
}
|
||||
} else if (currStep == LaunchConfirmDeviceCredential) {
|
||||
launchConfirmOrChooseLock(userId)
|
||||
}
|
||||
}
|
||||
|
||||
lifecycleScope.launch {
|
||||
navigationViewModel.currentScreen.filterNotNull().collect { screen ->
|
||||
Log.d(TAG, "FingerprintSettingsNav.currentScreen($screen)")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -313,7 +372,7 @@ class FingerprintEnrollmentV2Activity : FragmentActivity() {
|
||||
) {
|
||||
overridePendingTransition(
|
||||
com.google.android.setupdesign.R.anim.sud_slide_next_in,
|
||||
com.google.android.setupdesign.R.anim.sud_slide_next_out
|
||||
com.google.android.setupdesign.R.anim.sud_slide_next_out,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -18,8 +18,6 @@ package com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollNavigationViewModel
|
||||
|
||||
/**
|
||||
* A fragment to indicate that fingerprint enrollment has been completed.
|
||||
@@ -31,9 +29,5 @@ class FingerprintEnrollConfirmationV2Fragment : Fragment() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (savedInstanceState == null) {
|
||||
val navigationViewModel =
|
||||
ViewModelProvider(requireActivity())[FingerprintEnrollNavigationViewModel::class.java]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,18 +18,12 @@ package com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollNavigationViewModel
|
||||
|
||||
/** A fragment that is responsible for enrolling a users fingerprint. */
|
||||
class FingerprintEnrollEnrollingV2Fragment : Fragment(R.layout.fingerprint_enroll_enrolling) {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (savedInstanceState == null) {
|
||||
val navigationViewModel =
|
||||
ViewModelProvider(requireActivity())[FingerprintEnrollNavigationViewModel::class.java]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ private const val TAG = "FingerprintEnrollFindSensorV2Fragment"
|
||||
* 2. Explain to the user how the enrollment process shown by [FingerprintEnrollEnrollingV2Fragment]
|
||||
* will work.
|
||||
*/
|
||||
class FingerprintEnrollFindSensorV2Fragment : Fragment() {
|
||||
class FingerprintEnrollFindSensorV2Fragment(val sensorType: FingerprintSensorType) : Fragment() {
|
||||
// This is only for non-udfps or non-sfps sensor. For udfps and sfps, we show lottie.
|
||||
private var animation: FingerprintFindSensorAnimation? = null
|
||||
|
||||
@@ -62,7 +62,7 @@ class FingerprintEnrollFindSensorV2Fragment : Fragment() {
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
savedInstanceState: Bundle?,
|
||||
): View? {
|
||||
|
||||
val sensorType =
|
||||
@@ -104,8 +104,7 @@ class FingerprintEnrollFindSensorV2Fragment : Fragment() {
|
||||
}
|
||||
lifecycleScope.launch {
|
||||
viewModel.showRfpsAnimation.collect {
|
||||
animation =
|
||||
view.findViewById(R.id.fingerprint_sensor_location_animation)
|
||||
animation = view.findViewById(R.id.fingerprint_sensor_location_animation)
|
||||
animation!!.startAnimation()
|
||||
}
|
||||
}
|
||||
@@ -128,14 +127,7 @@ class FingerprintEnrollFindSensorV2Fragment : Fragment() {
|
||||
footerBarMixin.secondaryButton =
|
||||
FooterButton.Builder(requireActivity())
|
||||
.setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
|
||||
.setListener {
|
||||
run {
|
||||
// TODO: Show the dialog for suw
|
||||
Log.d(TAG, "onSkipClicked")
|
||||
// TODO: Finish activity in the root activity instead.
|
||||
requireActivity().finish()
|
||||
}
|
||||
}
|
||||
.setListener { viewModel.secondaryButtonClicked() }
|
||||
.setButtonType(FooterButton.ButtonType.SKIP)
|
||||
.setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary)
|
||||
.build()
|
||||
@@ -146,11 +138,9 @@ class FingerprintEnrollFindSensorV2Fragment : Fragment() {
|
||||
FooterButton.Builder(requireActivity())
|
||||
.setText(R.string.security_settings_udfps_enroll_find_sensor_start_button)
|
||||
.setListener {
|
||||
run {
|
||||
Log.d(TAG, "onStartButtonClick")
|
||||
viewModel.proceedToEnrolling()
|
||||
}
|
||||
}
|
||||
.setButtonType(FooterButton.ButtonType.NEXT)
|
||||
.setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
|
||||
.build()
|
||||
@@ -159,7 +149,7 @@ class FingerprintEnrollFindSensorV2Fragment : Fragment() {
|
||||
private fun setupLottie(
|
||||
view: View,
|
||||
lottieAnimation: Int,
|
||||
lottieClickListener: View.OnClickListener? = null
|
||||
lottieClickListener: View.OnClickListener? = null,
|
||||
) {
|
||||
val illustrationLottie: LottieAnimationView? = view.findViewById(R.id.illustration_lottie)
|
||||
illustrationLottie?.setAnimation(lottieAnimation)
|
||||
|
@@ -24,7 +24,6 @@ import android.graphics.PorterDuffColorFilter
|
||||
import android.os.Bundle
|
||||
import android.text.Html
|
||||
import android.text.method.LinkMovementMethod
|
||||
import android.util.Log
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -36,9 +35,8 @@ import androidx.fragment.app.Fragment
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.Unicorn
|
||||
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.lib.model.Unicorn
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollIntroViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
@@ -48,6 +46,7 @@ import com.google.android.setupdesign.GlifLayout
|
||||
import com.google.android.setupdesign.template.RequireScrollMixin
|
||||
import com.google.android.setupdesign.util.DynamicColorPalette
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
private const val TAG = "FingerprintEnrollmentIntroV2Fragment"
|
||||
@@ -96,16 +95,14 @@ class FingerprintEnrollIntroV2Fragment() : Fragment(R.layout.fingerprint_v2_enro
|
||||
private lateinit var footerBarMixin: FooterBarMixin
|
||||
private lateinit var textModel: TextModel
|
||||
|
||||
// Note that the ViewModels cannot be requested before the onCreate call
|
||||
private val navigationViewModel: FingerprintEnrollNavigationViewModel by lazy {
|
||||
viewModelProvider[FingerprintEnrollNavigationViewModel::class.java]
|
||||
}
|
||||
private val fingerprintViewModel: FingerprintEnrollViewModel by lazy {
|
||||
viewModelProvider[FingerprintEnrollViewModel::class.java]
|
||||
private val viewModel: FingerprintEnrollIntroViewModel by lazy {
|
||||
viewModelProvider[FingerprintEnrollIntroViewModel::class.java]
|
||||
}
|
||||
|
||||
private val fingerprintScrollViewModel: FingerprintScrollViewModel by lazy {
|
||||
viewModelProvider[FingerprintScrollViewModel::class.java]
|
||||
}
|
||||
|
||||
private val gateKeeperViewModel: FingerprintGatekeeperViewModel by lazy {
|
||||
viewModelProvider[FingerprintGatekeeperViewModel::class.java]
|
||||
}
|
||||
@@ -113,17 +110,16 @@ class FingerprintEnrollIntroV2Fragment() : Fragment(R.layout.fingerprint_v2_enro
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
savedInstanceState: Bundle?,
|
||||
): View? =
|
||||
super.onCreateView(inflater, container, savedInstanceState).also { theView ->
|
||||
val view = theView!!
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
combine(
|
||||
navigationViewModel.fingerprintFlow,
|
||||
fingerprintViewModel.sensorType,
|
||||
) { enrollType, sensorType ->
|
||||
Pair(enrollType, sensorType)
|
||||
combine(viewModel.fingerprintFlow, viewModel.sensor.filterNotNull()) {
|
||||
enrollType,
|
||||
sensorType ->
|
||||
Pair(enrollType, sensorType.sensorType)
|
||||
}
|
||||
.collect { (enrollType, sensorType) ->
|
||||
textModel =
|
||||
@@ -147,7 +143,7 @@ class FingerprintEnrollIntroV2Fragment() : Fragment(R.layout.fingerprint_v2_enro
|
||||
R.id.icon_trash_can,
|
||||
R.id.icon_info,
|
||||
R.id.icon_shield,
|
||||
R.id.icon_link
|
||||
R.id.icon_link,
|
||||
)
|
||||
.forEach { icon ->
|
||||
view.requireViewById<ImageView>(icon).drawable.colorFilter = colorFilter
|
||||
@@ -186,31 +182,24 @@ class FingerprintEnrollIntroV2Fragment() : Fragment(R.layout.fingerprint_v2_enro
|
||||
return view
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO (b/305269201): This link isn't displaying for screenshot tests.
|
||||
*/
|
||||
/** TODO (b/305269201): This link isn't displaying for screenshot tests. */
|
||||
private fun setFooterLink(view: View) {
|
||||
val footerLink: TextView = view.requireViewById(R.id.footer_learn_more)
|
||||
footerLink.movementMethod = LinkMovementMethod.getInstance()
|
||||
footerLink.text =
|
||||
Html.fromHtml(
|
||||
getString(R.string.security_settings_fingerprint_v2_enroll_introduction_message_learn_more),
|
||||
Html.FROM_HTML_MODE_LEGACY
|
||||
Html.FROM_HTML_MODE_LEGACY,
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupFooterBarAndScrollView(
|
||||
view: View,
|
||||
) {
|
||||
private fun setupFooterBarAndScrollView(view: View) {
|
||||
val scrollView: ScrollView =
|
||||
view.requireViewById(com.google.android.setupdesign.R.id.sud_scroll_view)
|
||||
scrollView.importantForAccessibility = View.IMPORTANT_FOR_ACCESSIBILITY_YES
|
||||
// Next button responsible for starting the next fragment.
|
||||
val onNextButtonClick: View.OnClickListener =
|
||||
View.OnClickListener {
|
||||
Log.d(TAG, "OnNextClicked")
|
||||
navigationViewModel.nextStep()
|
||||
}
|
||||
View.OnClickListener { viewModel.primaryButtonClicked() }
|
||||
|
||||
val layout: GlifLayout = view.findViewById(R.id.setup_wizard_layout)!!
|
||||
footerBarMixin = layout.getMixin(FooterBarMixin::class.java)
|
||||
@@ -225,11 +214,11 @@ class FingerprintEnrollIntroV2Fragment() : Fragment(R.layout.fingerprint_v2_enro
|
||||
footerBarMixin.setSecondaryButton(
|
||||
FooterButton.Builder(requireContext())
|
||||
.setText(textModel.negativeButton)
|
||||
.setListener({ Log.d(TAG, "prevClicked") })
|
||||
.setListener { viewModel.onSecondaryButtonClicked() }
|
||||
.setButtonType(FooterButton.ButtonType.NEXT)
|
||||
.setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
|
||||
.build(),
|
||||
true /* usePrimaryStyle */
|
||||
true, /* usePrimaryStyle */
|
||||
)
|
||||
|
||||
val primaryButton = footerBarMixin.primaryButton
|
||||
@@ -242,7 +231,7 @@ class FingerprintEnrollIntroV2Fragment() : Fragment(R.layout.fingerprint_v2_enro
|
||||
requireContext(),
|
||||
primaryButton,
|
||||
R.string.security_settings_face_enroll_introduction_more,
|
||||
onNextButtonClick
|
||||
onNextButtonClick,
|
||||
)
|
||||
|
||||
requireScrollMixin.setOnRequireScrollStateChangedListener { scrollNeeded: Boolean ->
|
||||
@@ -257,7 +246,7 @@ class FingerprintEnrollIntroV2Fragment() : Fragment(R.layout.fingerprint_v2_enro
|
||||
if (consented) {
|
||||
primaryButton.setText(
|
||||
requireContext(),
|
||||
R.string.security_settings_fingerprint_enroll_introduction_agree
|
||||
R.string.security_settings_fingerprint_enroll_introduction_agree,
|
||||
)
|
||||
secondaryButton.visibility = View.VISIBLE
|
||||
} else {
|
||||
@@ -309,7 +298,7 @@ class FingerprintEnrollIntroV2Fragment() : Fragment(R.layout.fingerprint_v2_enro
|
||||
private fun getIconColorFilter(): PorterDuffColorFilter {
|
||||
return PorterDuffColorFilter(
|
||||
DynamicColorPalette.getColor(context, DynamicColorPalette.ColorType.ACCENT),
|
||||
PorterDuff.Mode.SRC_IN
|
||||
PorterDuff.Mode.SRC_IN,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -32,13 +32,15 @@ import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.lifecycle.repeatOnLifecycle
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSIconTouchViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.widget.FingerprintErrorDialog
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.widget.IconTouchDialog
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.widget.RFPSProgressBar
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.BackgroundViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.OrientationStateViewModel
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment
|
||||
import com.google.android.setupcompat.template.FooterBarMixin
|
||||
@@ -49,8 +51,6 @@ import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
private const val TAG = "RFPSEnrollFragment"
|
||||
|
||||
/** This fragment is responsible for taking care of rear fingerprint enrollment. */
|
||||
class RFPSEnrollFragment : Fragment(R.layout.fingerprint_v2_rfps_enroll_enrolling) {
|
||||
|
||||
@@ -74,11 +74,14 @@ class RFPSEnrollFragment : Fragment(R.layout.fingerprint_v2_rfps_enroll_enrollin
|
||||
private val backgroundViewModel: BackgroundViewModel by lazy {
|
||||
ViewModelProvider(requireActivity())[BackgroundViewModel::class.java]
|
||||
}
|
||||
private val navigationViewModel: FingerprintNavigationViewModel by lazy {
|
||||
ViewModelProvider(requireActivity())[FingerprintNavigationViewModel::class.java]
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
inflater: LayoutInflater,
|
||||
container: ViewGroup?,
|
||||
savedInstanceState: Bundle?
|
||||
savedInstanceState: Bundle?,
|
||||
): View? {
|
||||
val view = super.onCreateView(inflater, container, savedInstanceState)!!
|
||||
val fragment = this
|
||||
@@ -99,7 +102,7 @@ class RFPSEnrollFragment : Fragment(R.layout.fingerprint_v2_rfps_enroll_enrollin
|
||||
footerBarMixin.secondaryButton =
|
||||
FooterButton.Builder(context)
|
||||
.setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
|
||||
.setListener { Log.e(TAG, "skip enrollment!") }
|
||||
.setListener { rfpsViewModel.negativeButtonClicked() }
|
||||
.setButtonType(FooterButton.ButtonType.SKIP)
|
||||
.setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary)
|
||||
.build()
|
||||
@@ -150,7 +153,7 @@ class RFPSEnrollFragment : Fragment(R.layout.fingerprint_v2_rfps_enroll_enrollin
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
backgroundViewModel.background
|
||||
.filter { inBackground -> inBackground }
|
||||
.collect { rfpsViewModel.stopEnrollment() }
|
||||
.collect { rfpsViewModel.didGoToBackground() }
|
||||
}
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
@@ -171,7 +174,6 @@ class RFPSEnrollFragment : Fragment(R.layout.fingerprint_v2_rfps_enroll_enrollin
|
||||
.setDuration(200)
|
||||
.setInterpolator(linearOutSlowInInterpolator)
|
||||
.start()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -207,6 +209,12 @@ class RFPSEnrollFragment : Fragment(R.layout.fingerprint_v2_rfps_enroll_enrollin
|
||||
dismissDialogs()
|
||||
}
|
||||
}
|
||||
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
rfpsViewModel.didCompleteEnrollment
|
||||
.filter { it }
|
||||
.collect { rfpsViewModel.finishedSuccessfully() }
|
||||
}
|
||||
return view
|
||||
}
|
||||
|
||||
@@ -215,28 +223,18 @@ class RFPSEnrollFragment : Fragment(R.layout.fingerprint_v2_rfps_enroll_enrollin
|
||||
viewLifecycleOwner.lifecycleScope.launch {
|
||||
try {
|
||||
val shouldRestartEnrollment = FingerprintErrorDialog.showInstance(error, fragment)
|
||||
rfpsViewModel.userClickedStopEnrollDialog()
|
||||
} catch (exception: Exception) {
|
||||
Log.e(TAG, "Exception occurred $exception")
|
||||
}
|
||||
onEnrollmentFailed()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onEnrollmentFailed() {
|
||||
rfpsViewModel.stopEnrollment()
|
||||
}
|
||||
|
||||
private fun handleEnrollProgress(progress: FingerEnrollState.EnrollProgress) {
|
||||
progressBar.updateProgress(
|
||||
progress.remainingSteps.toFloat() / progress.totalStepsRequired.toFloat()
|
||||
)
|
||||
|
||||
if (progress.remainingSteps == 0) {
|
||||
performNextStepSuccess()
|
||||
}
|
||||
}
|
||||
|
||||
private fun performNextStepSuccess() {}
|
||||
|
||||
private fun dismissDialogs() {
|
||||
val transaction = parentFragmentManager.beginTransaction()
|
||||
@@ -249,4 +247,9 @@ class RFPSEnrollFragment : Fragment(R.layout.fingerprint_v2_rfps_enroll_enrollin
|
||||
}
|
||||
transaction.commitAllowingStateLoss()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "RFPSEnrollFragment"
|
||||
private val navStep = FingerprintNavigationStep.Enrollment::class
|
||||
}
|
||||
}
|
||||
|
@@ -38,9 +38,9 @@ class RFPSIconTouchViewModel : ViewModel() {
|
||||
private val _touches: MutableStateFlow<Int> = MutableStateFlow(0)
|
||||
|
||||
/**
|
||||
* Whether or not the UI should be showing the dialog. By making this SharingStarted.Eagerly
|
||||
* the first event 0 % 3 == 0 will fire as soon as this view model is created, so it should
|
||||
* be ignored and work as intended.
|
||||
* Whether or not the UI should be showing the dialog. By making this SharingStarted.Eagerly the
|
||||
* first event 0 % 3 == 0 will fire as soon as this view model is created, so it should be ignored
|
||||
* and work as intended.
|
||||
*/
|
||||
val shouldShowDialog: Flow<Boolean> =
|
||||
_touches
|
||||
|
@@ -19,13 +19,17 @@ package com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrol
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollState
|
||||
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
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Enrollment
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.filterIsInstance
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
import kotlinx.coroutines.flow.transform
|
||||
@@ -34,9 +38,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,
|
||||
) : ViewModel() {
|
||||
|
||||
/** Value to indicate if the text view is visible or not **/
|
||||
/** Value to indicate if the text view is visible or not */
|
||||
private val _textViewIsVisible = MutableStateFlow<Boolean>(false)
|
||||
val textViewIsVisible: Flow<Boolean> = _textViewIsVisible.asStateFlow()
|
||||
|
||||
@@ -61,9 +66,8 @@ class RFPSViewModel(
|
||||
val helpMessage: Flow<FingerEnrollState.EnrollHelp?> =
|
||||
enrollFlow
|
||||
.filterIsInstance<FingerEnrollState.EnrollHelp>()
|
||||
.shareIn(viewModelScope, SharingStarted.Eagerly, 0).transform {
|
||||
_textViewIsVisible.update { true }
|
||||
}
|
||||
.shareIn(viewModelScope, SharingStarted.Eagerly, 0)
|
||||
.transform { _textViewIsVisible.update { true } }
|
||||
|
||||
/**
|
||||
* The error message should only be shown once, for scenarios like screen rotations, we don't want
|
||||
@@ -74,6 +78,8 @@ class RFPSViewModel(
|
||||
.filterIsInstance<FingerEnrollState.EnrollError>()
|
||||
.shareIn(viewModelScope, SharingStarted.Eagerly, 0)
|
||||
|
||||
val didCompleteEnrollment: Flow<Boolean> = progress.filterNotNull().map { it.remainingSteps == 0 }
|
||||
|
||||
/** Indicates if the consumer is ready for enrollment */
|
||||
fun readyForEnrollment() {
|
||||
fingerprintEnrollViewModel.canEnroll()
|
||||
@@ -88,15 +94,51 @@ class RFPSViewModel(
|
||||
_textViewIsVisible.update { isVisible }
|
||||
}
|
||||
|
||||
/** Indicates that the user is done with trying to enroll a fingerprint */
|
||||
fun userClickedStopEnrollDialog() {
|
||||
navigationViewModel.update(
|
||||
FingerprintAction.USER_CLICKED_FINISH,
|
||||
navStep,
|
||||
"${TAG}#userClickedStopEnrollingDialog",
|
||||
)
|
||||
}
|
||||
|
||||
/** Indicates that the application went to the background. */
|
||||
fun didGoToBackground() {
|
||||
navigationViewModel.update(
|
||||
FingerprintAction.DID_GO_TO_BACKGROUND,
|
||||
navStep,
|
||||
"${TAG}#didGoToBackground",
|
||||
)
|
||||
stopEnrollment()
|
||||
}
|
||||
|
||||
/** Indicates the negative button has been clicked */
|
||||
fun negativeButtonClicked() {
|
||||
navigationViewModel.update(
|
||||
FingerprintAction.NEGATIVE_BUTTON_PRESSED,
|
||||
navStep,
|
||||
"${TAG}negativeButtonClicked",
|
||||
)
|
||||
}
|
||||
|
||||
fun finishedSuccessfully() {
|
||||
navigationViewModel.update(FingerprintAction.NEXT, navStep, "${TAG}#progressFinished")
|
||||
}
|
||||
|
||||
class RFPSViewModelFactory(
|
||||
private val fingerprintEnrollEnrollingViewModel: FingerprintEnrollEnrollingViewModel,
|
||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
return RFPSViewModel(fingerprintEnrollEnrollingViewModel) as T
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return RFPSViewModel(fingerprintEnrollEnrollingViewModel, navigationViewModel) as T
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val navStep = Enrollment::class
|
||||
private const val TAG = "RFPSViewModel"
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ import android.os.Bundle
|
||||
import android.util.Log
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerEnrollState
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment
|
||||
import kotlin.coroutines.resume
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
@@ -86,10 +86,8 @@ class FingerprintErrorDialog : InstrumentedDialogFragment() {
|
||||
private const val KEY_TITLE = "fingerprint_title"
|
||||
private const val KEY_SHOULD_TRY_AGAIN = "should_try_again"
|
||||
|
||||
suspend fun showInstance(
|
||||
error: FingerEnrollState.EnrollError,
|
||||
fragment: Fragment,
|
||||
) = suspendCancellableCoroutine { continuation ->
|
||||
suspend fun showInstance(error: FingerEnrollState.EnrollError, fragment: Fragment) =
|
||||
suspendCancellableCoroutine { continuation ->
|
||||
val dialog = FingerprintErrorDialog()
|
||||
dialog.onTryAgain = DialogInterface.OnClickListener { _, _ -> continuation.resume(true) }
|
||||
|
||||
@@ -104,18 +102,9 @@ class FingerprintErrorDialog : InstrumentedDialogFragment() {
|
||||
continuation.invokeOnCancellation { Log.d(TAG, "invokeOnCancellation $dialog") }
|
||||
|
||||
val bundle = Bundle()
|
||||
bundle.putInt(
|
||||
KEY_TITLE,
|
||||
error.errTitle,
|
||||
)
|
||||
bundle.putInt(
|
||||
KEY_MESSAGE,
|
||||
error.errString,
|
||||
)
|
||||
bundle.putBoolean(
|
||||
KEY_SHOULD_TRY_AGAIN,
|
||||
error.shouldRetryEnrollment,
|
||||
)
|
||||
bundle.putInt(KEY_TITLE, error.errTitle)
|
||||
bundle.putInt(KEY_MESSAGE, error.errString)
|
||||
bundle.putBoolean(KEY_SHOULD_TRY_AGAIN, error.shouldRetryEnrollment)
|
||||
dialog.arguments = bundle
|
||||
Log.d(TAG, "showing dialog $dialog")
|
||||
dialog.show(fragment.parentFragmentManager, FingerprintErrorDialog::class.java.toString())
|
||||
|
@@ -41,15 +41,13 @@ class AccessibilityViewModel(accessibilityManager: AccessibilityManager) : ViewM
|
||||
.stateIn(
|
||||
viewModelScope, // This is going to tied to the view model scope
|
||||
SharingStarted.WhileSubscribed(), // When no longer subscribed, we removeTheListener
|
||||
false
|
||||
false,
|
||||
)
|
||||
|
||||
class AccessibilityViewModelFactory(private val accessibilityManager: AccessibilityManager) :
|
||||
ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return AccessibilityViewModel(accessibilityManager) as T
|
||||
}
|
||||
}
|
||||
|
@@ -25,8 +25,8 @@ import kotlinx.coroutines.flow.transformLatest
|
||||
import kotlinx.coroutines.flow.update
|
||||
|
||||
/**
|
||||
* This class is a wrapper around the [FingerprintEnrollViewModel] and decides when
|
||||
* the user should or should not be enrolling.
|
||||
* This class is a wrapper around the [FingerprintEnrollViewModel] and decides when the user should
|
||||
* or should not be enrolling.
|
||||
*/
|
||||
class FingerprintEnrollEnrollingViewModel(
|
||||
private val fingerprintEnrollViewModel: FingerprintEnrollViewModel,
|
||||
@@ -72,12 +72,10 @@ class FingerprintEnrollEnrollingViewModel(
|
||||
|
||||
class FingerprintEnrollEnrollingViewModelFactory(
|
||||
private val fingerprintEnrollViewModel: FingerprintEnrollViewModel,
|
||||
private val backgroundViewModel: BackgroundViewModel
|
||||
private val backgroundViewModel: BackgroundViewModel,
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return FingerprintEnrollEnrollingViewModel(fingerprintEnrollViewModel, backgroundViewModel)
|
||||
as T
|
||||
}
|
||||
|
@@ -19,8 +19,10 @@ package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.SetupWizard
|
||||
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.fragment.FingerprintEnrollFindSensorV2Fragment
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Education
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
@@ -36,20 +38,22 @@ import kotlinx.coroutines.launch
|
||||
|
||||
/** Models the UI state for [FingerprintEnrollFindSensorV2Fragment]. */
|
||||
class FingerprintEnrollFindSensorViewModel(
|
||||
private val navigationViewModel: FingerprintEnrollNavigationViewModel,
|
||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
||||
private val fingerprintEnrollViewModel: FingerprintEnrollViewModel,
|
||||
private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
||||
backgroundViewModel: BackgroundViewModel,
|
||||
accessibilityViewModel: AccessibilityViewModel,
|
||||
foldStateViewModel: FoldStateViewModel,
|
||||
orientationStateViewModel: OrientationStateViewModel
|
||||
orientationStateViewModel: OrientationStateViewModel,
|
||||
fingerprintFlowViewModel: FingerprintFlowViewModel,
|
||||
) : ViewModel() {
|
||||
|
||||
/** Represents the stream of sensor type. */
|
||||
val sensorType: Flow<FingerprintSensorType> =
|
||||
fingerprintEnrollViewModel.sensorType.shareIn(
|
||||
viewModelScope,
|
||||
SharingStarted.WhileSubscribed(),
|
||||
1
|
||||
1,
|
||||
)
|
||||
private val _isUdfps: Flow<Boolean> =
|
||||
sensorType.map {
|
||||
@@ -103,10 +107,10 @@ class FingerprintEnrollFindSensorViewModel(
|
||||
fingerprintEnrollViewModel.sensorType,
|
||||
gatekeeperViewModel.hasValidGatekeeperInfo,
|
||||
gatekeeperViewModel.gatekeeperInfo,
|
||||
navigationViewModel.navigationViewModel
|
||||
) { sensorType, hasValidGatekeeperInfo, gatekeeperInfo, navigationViewModel ->
|
||||
navigationViewModel.currentScreen,
|
||||
) { sensorType, hasValidGatekeeperInfo, gatekeeperInfo, currStep ->
|
||||
val shouldStartEnroll =
|
||||
navigationViewModel.currStep == Education &&
|
||||
currStep is Education &&
|
||||
sensorType != FingerprintSensorType.UDFPS_OPTICAL &&
|
||||
sensorType != FingerprintSensorType.UDFPS_ULTRASONIC &&
|
||||
hasValidGatekeeperInfo
|
||||
@@ -128,22 +132,19 @@ class FingerprintEnrollFindSensorViewModel(
|
||||
// Only collect the flow when we should be running.
|
||||
if (it) {
|
||||
combine(
|
||||
navigationViewModel.fingerprintFlow,
|
||||
fingerprintEnrollViewModel.educationEnrollFlow.filterNotNull(),
|
||||
) { enrollType, educationFlow ->
|
||||
Pair(enrollType, educationFlow)
|
||||
fingerprintFlowViewModel.fingerprintFlow,
|
||||
) { educationFlow, type ->
|
||||
Pair(educationFlow, type)
|
||||
}
|
||||
.collect { (enrollType, educationFlow) ->
|
||||
.collect { (educationFlow, type) ->
|
||||
when (educationFlow) {
|
||||
// TODO: Cancel the enroll() when EnrollProgress is received instead of proceeding
|
||||
// to
|
||||
// Enrolling page. Otherwise Enrolling page will receive the EnrollError.
|
||||
is FingerEnrollState.EnrollProgress -> proceedToEnrolling()
|
||||
is FingerEnrollState.EnrollError -> {
|
||||
if (educationFlow.isCancelled) {
|
||||
proceedToEnrolling()
|
||||
} else {
|
||||
_showErrorDialog.update { Pair(educationFlow.errString, enrollType == SetupWizard) }
|
||||
_showErrorDialog.update { Pair(educationFlow.errString, type == SetupWizard) }
|
||||
}
|
||||
}
|
||||
is FingerEnrollState.EnrollHelp -> {}
|
||||
@@ -169,17 +170,28 @@ class FingerprintEnrollFindSensorViewModel(
|
||||
|
||||
/** Proceed to EnrollEnrolling page. */
|
||||
fun proceedToEnrolling() {
|
||||
navigationViewModel.nextStep()
|
||||
stopEducation()
|
||||
navigationViewModel.update(FingerprintAction.NEXT, navStep, "$TAG#proceedToEnrolling")
|
||||
}
|
||||
|
||||
/** Indicates the secondary button has been clicked */
|
||||
fun secondaryButtonClicked() {
|
||||
navigationViewModel.update(
|
||||
FingerprintAction.NEGATIVE_BUTTON_PRESSED,
|
||||
navStep,
|
||||
"${TAG}#secondaryButtonClicked",
|
||||
)
|
||||
}
|
||||
|
||||
class FingerprintEnrollFindSensorViewModelFactory(
|
||||
private val navigationViewModel: FingerprintEnrollNavigationViewModel,
|
||||
private val navigationViewModel: FingerprintNavigationViewModel,
|
||||
private val fingerprintEnrollViewModel: FingerprintEnrollViewModel,
|
||||
private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
||||
private val backgroundViewModel: BackgroundViewModel,
|
||||
private val accessibilityViewModel: AccessibilityViewModel,
|
||||
private val foldStateViewModel: FoldStateViewModel,
|
||||
private val orientationStateViewModel: OrientationStateViewModel
|
||||
private val orientationStateViewModel: OrientationStateViewModel,
|
||||
private val fingerprintFlowViewModel: FingerprintFlowViewModel,
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
@@ -190,9 +202,15 @@ class FingerprintEnrollFindSensorViewModel(
|
||||
backgroundViewModel,
|
||||
accessibilityViewModel,
|
||||
foldStateViewModel,
|
||||
orientationStateViewModel
|
||||
orientationStateViewModel,
|
||||
fingerprintFlowViewModel,
|
||||
)
|
||||
as T
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "FingerprintEnrollFindSensorViewModel"
|
||||
private val navStep = Education::class
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.ui.enrollment.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
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
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/** A view model for fingerprint enroll introduction. */
|
||||
class FingerprintEnrollIntroViewModel(
|
||||
val navigationViewModel: FingerprintNavigationViewModel,
|
||||
private val fingerprintFlowViewModel: FingerprintFlowViewModel,
|
||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
) : ViewModel() {
|
||||
|
||||
/** Represents a stream of [FingerprintSensor] */
|
||||
val sensor: Flow<FingerprintSensor?> = fingerprintManagerInteractor.sensorPropertiesInternal
|
||||
|
||||
/** Represents a stream of [FingerprintFlow] */
|
||||
val fingerprintFlow: Flow<FingerprintFlow?> = fingerprintFlowViewModel.fingerprintFlow
|
||||
|
||||
/** Indicates the primary button has been clicked */
|
||||
fun primaryButtonClicked() {
|
||||
navigationViewModel.update(FingerprintAction.NEXT, navStep, "${TAG}#onNextClicked")
|
||||
}
|
||||
|
||||
/** Indicates the secondary button has been clicked */
|
||||
fun onSecondaryButtonClicked() {
|
||||
navigationViewModel.update(
|
||||
FingerprintAction.NEGATIVE_BUTTON_PRESSED,
|
||||
navStep,
|
||||
"${TAG}#negativeButtonClicked",
|
||||
)
|
||||
}
|
||||
|
||||
class FingerprintEnrollIntoViewModelFactory(
|
||||
val navigationViewModel: FingerprintNavigationViewModel,
|
||||
val fingerprintFlowViewModel: FingerprintFlowViewModel,
|
||||
val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return FingerprintEnrollIntroViewModel(
|
||||
navigationViewModel,
|
||||
fingerprintFlowViewModel,
|
||||
fingerprintManagerInteractor,
|
||||
)
|
||||
as T
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val navStep = Introduction::class
|
||||
private const val TAG = "FingerprintEnrollIntroViewModel"
|
||||
}
|
||||
}
|
@@ -18,9 +18,11 @@ package com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
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.FingerEnrollState
|
||||
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.ui.enrollment.viewmodel.FingerprintNavigationStep.Education
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Enrollment
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
@@ -34,7 +36,7 @@ import kotlinx.coroutines.flow.transformLatest
|
||||
class FingerprintEnrollViewModel(
|
||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
||||
navigationViewModel: FingerprintEnrollNavigationViewModel,
|
||||
val navigationViewModel: FingerprintNavigationViewModel,
|
||||
) : ViewModel() {
|
||||
|
||||
/**
|
||||
@@ -45,8 +47,8 @@ class FingerprintEnrollViewModel(
|
||||
*/
|
||||
var sensorTypeCached: FingerprintSensorType? = null
|
||||
private var _enrollReason: Flow<EnrollReason?> =
|
||||
navigationViewModel.navigationViewModel.map {
|
||||
when (it.currStep) {
|
||||
navigationViewModel.currentScreen.map {
|
||||
when (it) {
|
||||
is Enrollment -> EnrollReason.EnrollEnrolling
|
||||
is Education -> EnrollReason.FindSensor
|
||||
else -> null
|
||||
@@ -64,8 +66,7 @@ class FingerprintEnrollViewModel(
|
||||
* This flow should be the only flow which calls enroll().
|
||||
*/
|
||||
val _enrollFlow: Flow<FingerEnrollState> =
|
||||
combine(gatekeeperViewModel.gatekeeperInfo, _enrollReason) { hardwareAuthToken, enrollReason,
|
||||
->
|
||||
combine(gatekeeperViewModel.gatekeeperInfo, _enrollReason) { hardwareAuthToken, enrollReason ->
|
||||
Pair(hardwareAuthToken, enrollReason)
|
||||
}
|
||||
.transformLatest {
|
||||
@@ -110,18 +111,11 @@ class FingerprintEnrollViewModel(
|
||||
class FingerprintEnrollViewModelFactory(
|
||||
val interactor: FingerprintManagerInteractor,
|
||||
val gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
||||
val navigationViewModel: FingerprintEnrollNavigationViewModel,
|
||||
val navigationViewModel: FingerprintNavigationViewModel,
|
||||
) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
return FingerprintEnrollViewModel(
|
||||
interactor,
|
||||
gatekeeperViewModel,
|
||||
navigationViewModel,
|
||||
)
|
||||
as T
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return FingerprintEnrollViewModel(interactor, gatekeeperViewModel, navigationViewModel) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,141 +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.ui.enrollment.viewmodel
|
||||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintFlow
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
private const val TAG = "FingerprintEnrollNavigationViewModel"
|
||||
|
||||
/**
|
||||
* This class is responsible for sending a [NavigationStep] which indicates where the user is in the
|
||||
* Fingerprint Enrollment flow
|
||||
*/
|
||||
class FingerprintEnrollNavigationViewModel(
|
||||
private val dispatcher: CoroutineDispatcher,
|
||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
private val gatekeeperViewModel: FingerprintGatekeeperViewModel,
|
||||
private val firstStep: NextStepViewModel,
|
||||
private val navState: NavState,
|
||||
private val theFingerprintFlow: FingerprintFlow,
|
||||
) : ViewModel() {
|
||||
|
||||
private class InternalNavigationStep(
|
||||
lastStep: NextStepViewModel,
|
||||
nextStep: NextStepViewModel,
|
||||
forward: Boolean,
|
||||
var canNavigate: Boolean,
|
||||
) : NavigationStep(lastStep, nextStep, forward)
|
||||
|
||||
private var _fingerprintFlow = MutableStateFlow<FingerprintFlow?>(theFingerprintFlow)
|
||||
|
||||
/** A flow that indicates the [FingerprintFlow] */
|
||||
val fingerprintFlow: Flow<FingerprintFlow?> = _fingerprintFlow.asStateFlow()
|
||||
|
||||
private val _navigationStep =
|
||||
MutableStateFlow(
|
||||
InternalNavigationStep(PlaceHolderState, firstStep, forward = false, canNavigate = true)
|
||||
)
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
gatekeeperViewModel.credentialConfirmed.filterNotNull().collect {
|
||||
if (_navigationStep.value.currStep is LaunchConfirmDeviceCredential) {
|
||||
if (it) nextStep() else finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A flow that contains the [NavigationStep] used to indicate where in the enrollment process the
|
||||
* user is.
|
||||
*/
|
||||
val navigationViewModel: Flow<NavigationStep> = _navigationStep.asStateFlow()
|
||||
|
||||
/** This action indicates that the UI should actually update the navigation to the given step. */
|
||||
val navigationAction: Flow<NavigationStep?> =
|
||||
_navigationStep.shareIn(viewModelScope, SharingStarted.Lazily, 0)
|
||||
|
||||
/** Used to start the next step of Fingerprint Enrollment. */
|
||||
fun nextStep() {
|
||||
viewModelScope.launch {
|
||||
val currStep = _navigationStep.value.currStep
|
||||
val nextStep = currStep.next(navState)
|
||||
Log.d(TAG, "nextStep(${currStep} -> $nextStep)")
|
||||
_navigationStep.update {
|
||||
InternalNavigationStep(currStep, nextStep, forward = true, canNavigate = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Go back a step of fingerprint enrollment. */
|
||||
fun prevStep() {
|
||||
viewModelScope.launch {
|
||||
val currStep = _navigationStep.value.currStep
|
||||
val nextStep = currStep.prev(navState)
|
||||
_navigationStep.update {
|
||||
InternalNavigationStep(currStep, nextStep, forward = false, canNavigate = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun finish() {
|
||||
_navigationStep.update {
|
||||
InternalNavigationStep(Finish(null), Finish(null), forward = false, canNavigate = false)
|
||||
}
|
||||
}
|
||||
|
||||
class FingerprintEnrollNavigationViewModelFactory(
|
||||
private val backgroundDispatcher: CoroutineDispatcher,
|
||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
private val fingerprintGatekeeperViewModel: FingerprintGatekeeperViewModel,
|
||||
private val canSkipConfirm: Boolean,
|
||||
private val fingerprintFlow: FingerprintFlow,
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
|
||||
val navState = NavState(canSkipConfirm)
|
||||
return FingerprintEnrollNavigationViewModel(
|
||||
backgroundDispatcher,
|
||||
fingerprintManagerInteractor,
|
||||
fingerprintGatekeeperViewModel,
|
||||
Start.next(navState),
|
||||
navState,
|
||||
fingerprintFlow,
|
||||
)
|
||||
as T
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.ui.enrollment.viewmodel
|
||||
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintFlow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
|
||||
class FingerprintFlowViewModel(private val fingerprintFlowType: FingerprintFlow) : ViewModel() {
|
||||
val fingerprintFlow: Flow<FingerprintFlow> =
|
||||
flowOf(fingerprintFlowType).shareIn(viewModelScope, SharingStarted.Eagerly, 1)
|
||||
|
||||
class FingerprintFlowViewModelFactory(val flowType: FingerprintFlow) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return FingerprintFlowViewModel(flowType) as T
|
||||
}
|
||||
}
|
||||
}
|
@@ -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.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
@@ -29,11 +29,11 @@ import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
private const val TAG = "FingerprintGatekeeperViewModel"
|
||||
|
||||
sealed interface GatekeeperInfo {
|
||||
object Invalid : GatekeeperInfo
|
||||
|
||||
object Timeout : GatekeeperInfo
|
||||
|
||||
data class GatekeeperPasswordInfo(val token: ByteArray?, val passwordHandle: Long?) :
|
||||
GatekeeperInfo
|
||||
}
|
||||
@@ -97,7 +97,19 @@ class FingerprintGatekeeperViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
class FingerprintGatekeeperViewModelFactory(
|
||||
private val gatekeeperInfo: GatekeeperInfo?,
|
||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return FingerprintGatekeeperViewModel(gatekeeperInfo, fingerprintManagerInteractor) as T
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "FingerprintGatekeeperViewModel"
|
||||
/**
|
||||
* A function that checks if the challenge and token are valid, in which case a
|
||||
* [GatekeeperInfo.GatekeeperPasswordInfo] is provided, else [GatekeeperInfo.Invalid]
|
||||
@@ -110,17 +122,4 @@ class FingerprintGatekeeperViewModel(
|
||||
return GatekeeperInfo.GatekeeperPasswordInfo(token, challenge)
|
||||
}
|
||||
}
|
||||
|
||||
class FingerprintGatekeeperViewModelFactory(
|
||||
private val gatekeeperInfo: GatekeeperInfo?,
|
||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
return FingerprintGatekeeperViewModel(gatekeeperInfo, fingerprintManagerInteractor) as T
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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.ui.enrollment.viewmodel
|
||||
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FastEnroll
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintFlow
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||
|
||||
/**
|
||||
* A [FingerprintAction] event notifies the current [FingerprintNavigationStep] that an event
|
||||
* occurred. Depending on the type of [FingerprintAction] and the current
|
||||
* [FingerprintNavigationStep], the navstep will potentially produce a new
|
||||
* [FingerprintNavigationStep] indicating either 1). Control flow has changed 2). The activity has
|
||||
* finished 3). A transition is required
|
||||
*/
|
||||
enum class FingerprintAction {
|
||||
NEXT,
|
||||
PREV,
|
||||
CONFIRM_DEVICE_SUCCESS,
|
||||
CONFIRM_DEVICE_FAIL,
|
||||
TRANSITION_FINISHED,
|
||||
DID_GO_TO_BACKGROUND,
|
||||
ACTIVITY_CREATED,
|
||||
NEGATIVE_BUTTON_PRESSED,
|
||||
USER_CLICKED_FINISH,
|
||||
}
|
||||
|
||||
/** State that can be used to help a [FingerprintNavigationStep] determine the next step to take. */
|
||||
data class NavigationState(
|
||||
val flowType: FingerprintFlow,
|
||||
val hasConfirmedDeviceCredential: Boolean,
|
||||
val fingerprintSensor: FingerprintSensor?,
|
||||
)
|
||||
|
||||
/**
|
||||
* A generic interface for operating on (state, action) -> state? which will produce either another
|
||||
* FingerprintNavStep if something is required, or nothing.
|
||||
*
|
||||
* Note during the lifetime of the Activity, their should only be one [FingerprintNavigationStep] at
|
||||
* a time.
|
||||
*/
|
||||
sealed interface FingerprintNavigationStep {
|
||||
fun update(state: NavigationState, action: FingerprintAction): FingerprintNavigationStep?
|
||||
|
||||
/**
|
||||
* This indicates that a transition should occur from one screen to another. This class should
|
||||
* contain all necessary info about the transition.
|
||||
*
|
||||
* A transition step will cause a screen to change ownership from the current screen to the
|
||||
* [nextUiStep], after the transition has been completed and a
|
||||
* [FingerprintAction.TRANSITION_FINISHED] has been sent, the [nextUiStep] will be given control.
|
||||
*/
|
||||
class TransitionStep(val nextUiStep: UiStep) : FingerprintNavigationStep {
|
||||
override fun update(
|
||||
state: NavigationState,
|
||||
action: FingerprintAction,
|
||||
): FingerprintNavigationStep? {
|
||||
return when (action) {
|
||||
FingerprintAction.TRANSITION_FINISHED -> nextUiStep
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String = "TransitionStep(nextUiStep=$nextUiStep)"
|
||||
}
|
||||
|
||||
/** Indicates we should finish the enrolling activity */
|
||||
data class Finish(val result: Int?) : FingerprintNavigationStep {
|
||||
override fun update(
|
||||
state: NavigationState,
|
||||
action: FingerprintAction,
|
||||
): FingerprintNavigationStep? = null
|
||||
}
|
||||
|
||||
/** UiSteps should have a 1 to 1 mapping between each screen of FingerprintEnrollment */
|
||||
sealed class UiStep : FingerprintNavigationStep
|
||||
|
||||
/** This is the landing page for enrollment, where no content is shown. */
|
||||
data object Init : UiStep() {
|
||||
override fun update(
|
||||
state: NavigationState,
|
||||
action: FingerprintAction,
|
||||
): FingerprintNavigationStep? {
|
||||
return when (action) {
|
||||
FingerprintAction.ACTIVITY_CREATED -> {
|
||||
if (!state.hasConfirmedDeviceCredential) {
|
||||
TransitionStep(ConfirmDeviceCredential)
|
||||
} else if (state.flowType is FastEnroll) {
|
||||
TransitionStep(Enrollment(state.fingerprintSensor!!))
|
||||
} else {
|
||||
TransitionStep(Introduction)
|
||||
}
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Indicates the ConfirmDeviceCredential activity is being presented to the user */
|
||||
data object ConfirmDeviceCredential : UiStep() {
|
||||
override fun update(
|
||||
state: NavigationState,
|
||||
action: FingerprintAction,
|
||||
): FingerprintNavigationStep? {
|
||||
return when (action) {
|
||||
FingerprintAction.CONFIRM_DEVICE_SUCCESS -> TransitionStep(Introduction)
|
||||
FingerprintAction.CONFIRM_DEVICE_FAIL -> Finish(null)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Indicates the FingerprintIntroduction screen is being presented to the user */
|
||||
data object Introduction : UiStep() {
|
||||
override fun update(
|
||||
state: NavigationState,
|
||||
action: FingerprintAction,
|
||||
): FingerprintNavigationStep? {
|
||||
return when (action) {
|
||||
FingerprintAction.NEXT -> TransitionStep(Education(state.fingerprintSensor!!))
|
||||
FingerprintAction.NEGATIVE_BUTTON_PRESSED,
|
||||
FingerprintAction.PREV -> Finish(null)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Indicates the FingerprintEducation screen is being presented to the user */
|
||||
data class Education(val sensor: FingerprintSensor) : UiStep() {
|
||||
override fun update(
|
||||
state: NavigationState,
|
||||
action: FingerprintAction,
|
||||
): FingerprintNavigationStep? {
|
||||
return when (action) {
|
||||
FingerprintAction.NEXT -> TransitionStep(Enrollment(state.fingerprintSensor!!))
|
||||
FingerprintAction.NEGATIVE_BUTTON_PRESSED,
|
||||
FingerprintAction.PREV -> TransitionStep(Introduction)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Indicates the Enrollment screen is being presented to the user */
|
||||
data class Enrollment(val sensor: FingerprintSensor) : UiStep() {
|
||||
override fun update(
|
||||
state: NavigationState,
|
||||
action: FingerprintAction,
|
||||
): FingerprintNavigationStep? {
|
||||
return when (action) {
|
||||
FingerprintAction.NEXT -> TransitionStep(Confirmation)
|
||||
FingerprintAction.NEGATIVE_BUTTON_PRESSED,
|
||||
FingerprintAction.USER_CLICKED_FINISH,
|
||||
FingerprintAction.DID_GO_TO_BACKGROUND -> Finish(null)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Indicates the Confirmation screen is being presented to the user */
|
||||
data object Confirmation : UiStep() {
|
||||
override fun update(
|
||||
state: NavigationState,
|
||||
action: FingerprintAction,
|
||||
): FingerprintNavigationStep? {
|
||||
return when (action) {
|
||||
FingerprintAction.NEXT -> Finish(null)
|
||||
FingerprintAction.PREV -> TransitionStep(Education(state.fingerprintSensor!!))
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* 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.ui.enrollment.viewmodel
|
||||
|
||||
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.ui.enrollment.viewmodel.FingerprintNavigationStep.Finish
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.TransitionStep
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.UiStep
|
||||
import java.lang.NullPointerException
|
||||
import kotlin.reflect.KClass
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.combineTransform
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
/**
|
||||
* This class is essentially a wrapper around [FingerprintNavigationStep] that will be used by
|
||||
* fragments/viewmodels that want to consume these events. It should provide no additional
|
||||
* functionality beyond what is available in [FingerprintNavigationStep].
|
||||
*/
|
||||
class FingerprintNavigationViewModel(
|
||||
step: UiStep,
|
||||
hasConfirmedDeviceCredential: Boolean,
|
||||
flowViewModel: FingerprintFlowViewModel,
|
||||
fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
) : ViewModel() {
|
||||
|
||||
private var _navStateInternal: MutableStateFlow<NavigationState?> = MutableStateFlow(null)
|
||||
|
||||
init {
|
||||
viewModelScope.launch {
|
||||
flowViewModel.fingerprintFlow
|
||||
.combineTransform(fingerprintManagerInteractor.sensorPropertiesInternal) { flow, props ->
|
||||
if (props?.sensorId != -1) {
|
||||
emit(NavigationState(flow, hasConfirmedDeviceCredential, props))
|
||||
}
|
||||
}
|
||||
.collect { navState -> _navStateInternal.update { navState } }
|
||||
}
|
||||
}
|
||||
|
||||
private var _currentStep = MutableStateFlow<FingerprintNavigationStep?>(step)
|
||||
|
||||
private var _navigateTo: MutableStateFlow<UiStep?> = MutableStateFlow(null)
|
||||
val navigateTo: Flow<UiStep?> = _navigateTo.asStateFlow()
|
||||
|
||||
/**
|
||||
* This indicates a navigation event should occur. Navigation depends on navStateInternal being
|
||||
* present.
|
||||
*/
|
||||
val currentStep: Flow<FingerprintNavigationStep> =
|
||||
_currentStep.filterNotNull().combineTransform(_navStateInternal.filterNotNull()) { navigation, _
|
||||
->
|
||||
emit(navigation)
|
||||
}
|
||||
|
||||
private var _finishState = MutableStateFlow<Finish?>(null)
|
||||
|
||||
/** This indicates the activity should finish. */
|
||||
val shouldFinish: Flow<Finish?> = _finishState.asStateFlow()
|
||||
|
||||
private var _currentScreen = MutableStateFlow<UiStep?>(null)
|
||||
|
||||
/** This indicates what screen should currently be presenting to the user. */
|
||||
val currentScreen: Flow<UiStep?> = _currentScreen.asStateFlow()
|
||||
|
||||
/** See [updateInternal] for more details */
|
||||
fun update(action: FingerprintAction, caller: KClass<*>, debugStr: String) {
|
||||
Log.d(TAG, "$caller.update($action) $debugStr")
|
||||
val currentStep = _currentStep.value
|
||||
val isUiStep = currentStep is UiStep
|
||||
if (currentStep == null) {
|
||||
throw NullPointerException("current step is null")
|
||||
}
|
||||
if (isUiStep && currentStep::class != caller) {
|
||||
throw IllegalAccessError(
|
||||
"Error $currentStep != $caller, $caller should not be sending any events at this time"
|
||||
)
|
||||
}
|
||||
val navState = _navStateInternal.value
|
||||
if (navState == null) {
|
||||
throw NullPointerException("nav state is null")
|
||||
}
|
||||
val nextStep = currentStep.update(navState, action) ?: return
|
||||
Log.d(TAG, "nextStep=$nextStep")
|
||||
// Whenever an state update occurs, everything should be cleared.
|
||||
_currentStep.update { nextStep }
|
||||
_finishState.update { null }
|
||||
_currentScreen.update { null }
|
||||
|
||||
when (nextStep) {
|
||||
is TransitionStep -> {
|
||||
_navigateTo.update { nextStep.nextUiStep }
|
||||
}
|
||||
is Finish -> {
|
||||
_finishState.update { nextStep }
|
||||
}
|
||||
is UiStep -> {
|
||||
_currentScreen.update { nextStep }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FingerprintNavigationViewModelFactory(
|
||||
private val step: UiStep,
|
||||
private val hasConfirmedDeviceCredential: Boolean,
|
||||
private val flowViewModel: FingerprintFlowViewModel,
|
||||
private val fingerprintManagerInteractor: FingerprintManagerInteractor,
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return FingerprintNavigationViewModel(
|
||||
step,
|
||||
hasConfirmedDeviceCredential,
|
||||
flowViewModel,
|
||||
fingerprintManagerInteractor,
|
||||
)
|
||||
as T
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "FingerprintNavigationViewModel"
|
||||
}
|
||||
}
|
@@ -39,9 +39,7 @@ class FingerprintScrollViewModel : ViewModel() {
|
||||
class FingerprintScrollViewModelFactory : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return FingerprintScrollViewModel() as T
|
||||
}
|
||||
}
|
||||
|
@@ -49,9 +49,7 @@ class FoldStateViewModel(context: Context) : ViewModel() {
|
||||
|
||||
class FoldStateViewModelFactory(private val context: Context) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return FoldStateViewModel(context) as T
|
||||
}
|
||||
}
|
||||
|
@@ -1,104 +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.ui.enrollment.viewmodel
|
||||
|
||||
/**
|
||||
* A class that represents an action that the consumer should transition between lastStep and
|
||||
* currStep and in what direction this transition is occurring (e.g. forward or backwards)
|
||||
*/
|
||||
open class NavigationStep(
|
||||
val lastStep: NextStepViewModel,
|
||||
val currStep: NextStepViewModel,
|
||||
val forward: Boolean
|
||||
) {
|
||||
override fun toString(): String {
|
||||
return "lastStep=$lastStep, currStep=$currStep, forward=$forward"
|
||||
}
|
||||
}
|
||||
|
||||
/** The navigation state used by a [NavStep] to determine what the [NextStepViewModel] should be. */
|
||||
class NavState(val confirmedDevice: Boolean)
|
||||
|
||||
interface NavStep<T> {
|
||||
fun next(state: NavState): T
|
||||
fun prev(state: NavState): T
|
||||
}
|
||||
|
||||
/**
|
||||
* A class to represent a high level step (I.E. EnrollmentIntroduction) for FingerprintEnrollment.
|
||||
*/
|
||||
sealed class NextStepViewModel : NavStep<NextStepViewModel>
|
||||
|
||||
/**
|
||||
* This is the initial state for the previous step, used to indicate that there have been no
|
||||
* previous states.
|
||||
*/
|
||||
object PlaceHolderState : NextStepViewModel() {
|
||||
override fun next(state: NavState): NextStepViewModel = Finish(null)
|
||||
|
||||
override fun prev(state: NavState): NextStepViewModel = Finish(null)
|
||||
}
|
||||
|
||||
/**
|
||||
* This state is the initial state for the current step, and will be used to determine if the user
|
||||
* needs to [LaunchConfirmDeviceCredential] if not, it will go to [Intro]
|
||||
*/
|
||||
data object Start : NextStepViewModel() {
|
||||
override fun next(state: NavState): NextStepViewModel =
|
||||
if (state.confirmedDevice) Intro else LaunchConfirmDeviceCredential
|
||||
|
||||
override fun prev(state: NavState): NextStepViewModel = Finish(null)
|
||||
}
|
||||
|
||||
/** State indicating enrollment has been completed */
|
||||
class Finish(val resultCode: Int?) : NextStepViewModel() {
|
||||
override fun next(state: NavState): NextStepViewModel = Finish(resultCode)
|
||||
override fun prev(state: NavState): NextStepViewModel = Finish(null)
|
||||
}
|
||||
|
||||
/** State for the FingerprintEnrollment introduction */
|
||||
data object Intro : NextStepViewModel() {
|
||||
override fun next(state: NavState): NextStepViewModel = Education
|
||||
override fun prev(state: NavState): NextStepViewModel = Finish(null)
|
||||
}
|
||||
|
||||
/** State for the FingerprintEnrollment education */
|
||||
data object Education : NextStepViewModel() {
|
||||
override fun next(state: NavState): NextStepViewModel = Enrollment
|
||||
override fun prev(state: NavState): NextStepViewModel = Intro
|
||||
}
|
||||
|
||||
/** State for the FingerprintEnrollment enrollment */
|
||||
data object Enrollment : NextStepViewModel() {
|
||||
override fun next(state: NavState): NextStepViewModel = Confirmation
|
||||
override fun prev(state: NavState): NextStepViewModel = Education
|
||||
}
|
||||
|
||||
/** State for the FingerprintEnrollment confirmation */
|
||||
object Confirmation : NextStepViewModel() {
|
||||
override fun next(state: NavState): NextStepViewModel = Finish(0)
|
||||
override fun prev(state: NavState): NextStepViewModel = Intro
|
||||
}
|
||||
|
||||
/**
|
||||
* State used to send the user to the ConfirmDeviceCredential activity. This activity can either
|
||||
* confirm a users device credential, or have them create one.
|
||||
*/
|
||||
object LaunchConfirmDeviceCredential : NextStepViewModel() {
|
||||
override fun next(state: NavState): NextStepViewModel = Intro
|
||||
override fun prev(state: NavState): NextStepViewModel = Finish(0)
|
||||
}
|
@@ -58,7 +58,7 @@ class OrientationStateViewModel(private val context: Context) : ViewModel() {
|
||||
.stateIn(
|
||||
viewModelScope, // This is going to tied to the view model scope
|
||||
SharingStarted.WhileSubscribed(), // When no longer subscribed, we removeTheListener
|
||||
context.display!!.rotation
|
||||
context.display!!.rotation,
|
||||
)
|
||||
|
||||
fun getRotationFromDefault(rotation: Int): Int {
|
||||
@@ -73,9 +73,7 @@ class OrientationStateViewModel(private val context: Context) : ViewModel() {
|
||||
|
||||
class OrientationViewModelFactory(private val context: Context) : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return OrientationStateViewModel(context) as T
|
||||
}
|
||||
}
|
||||
|
@@ -19,8 +19,8 @@ package com.android.settings.biometrics.fingerprint2.ui.settings.binder
|
||||
import android.hardware.fingerprint.FingerprintManager
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.LifecycleCoroutineScope
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.binder.FingerprintSettingsViewBinder.FingerprintView
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.EnrollAdditionalFingerprint
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.EnrollFirstFingerprint
|
||||
@@ -52,7 +52,7 @@ object FingerprintSettingsViewBinder {
|
||||
userId: Int,
|
||||
gateKeeperPasswordHandle: Long?,
|
||||
challenge: Long?,
|
||||
challengeToken: ByteArray?
|
||||
challengeToken: ByteArray?,
|
||||
)
|
||||
/** Helper to launch an add fingerprint request */
|
||||
fun launchAddFingerprint(userId: Int, challengeToken: ByteArray?)
|
||||
@@ -158,7 +158,7 @@ object FingerprintSettingsViewBinder {
|
||||
nextStep.userId,
|
||||
nextStep.gateKeeperPasswordHandle,
|
||||
nextStep.challenge,
|
||||
nextStep.challengeToken
|
||||
nextStep.challengeToken,
|
||||
)
|
||||
is EnrollAdditionalFingerprint ->
|
||||
view.launchAddFingerprint(nextStep.userId, nextStep.challengeToken)
|
||||
|
@@ -26,7 +26,7 @@ import android.os.Bundle
|
||||
import android.os.UserManager
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment
|
||||
import kotlin.coroutines.resume
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
@@ -75,8 +75,7 @@ class FingerprintDeletionDialog : InstrumentedDialogFragment() {
|
||||
message =
|
||||
devicePolicyManager?.resources?.getString(messageId) {
|
||||
message + "\n\n" + context.getString(defaultMessageId)
|
||||
}
|
||||
?: ""
|
||||
} ?: ""
|
||||
}
|
||||
|
||||
alertDialog =
|
||||
@@ -85,7 +84,7 @@ class FingerprintDeletionDialog : InstrumentedDialogFragment() {
|
||||
.setMessage(message)
|
||||
.setPositiveButton(
|
||||
R.string.security_settings_fingerprint_enroll_dialog_delete,
|
||||
onClickListener
|
||||
onClickListener,
|
||||
)
|
||||
.setNegativeButton(R.string.cancel, onNegativeClickListener)
|
||||
.create()
|
||||
@@ -94,6 +93,7 @@ class FingerprintDeletionDialog : InstrumentedDialogFragment() {
|
||||
|
||||
companion object {
|
||||
private const val KEY_FINGERPRINT = "fingerprint"
|
||||
|
||||
suspend fun showInstance(
|
||||
fp: FingerprintData,
|
||||
lastFingerprint: Boolean,
|
||||
@@ -109,7 +109,7 @@ class FingerprintDeletionDialog : InstrumentedDialogFragment() {
|
||||
val bundle = Bundle()
|
||||
bundle.putObject(
|
||||
KEY_FINGERPRINT,
|
||||
android.hardware.fingerprint.Fingerprint(fp.name, fp.fingerId, fp.deviceId)
|
||||
android.hardware.fingerprint.Fingerprint(fp.name, fp.fingerId, fp.deviceId),
|
||||
)
|
||||
bundle.putBoolean(KEY_IS_LAST_FINGERPRINT, lastFingerprint)
|
||||
dialog.arguments = bundle
|
||||
|
@@ -22,7 +22,7 @@ import android.view.View
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import androidx.preference.PreferenceViewHolder
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
import com.android.settingslib.widget.TwoTargetPreference
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -33,7 +33,7 @@ class FingerprintSettingsPreference(
|
||||
context: Context,
|
||||
val fingerprintViewModel: FingerprintData,
|
||||
val fragment: FingerprintSettingsV2Fragment,
|
||||
val isLastFingerprint: Boolean
|
||||
val isLastFingerprint: Boolean,
|
||||
) : TwoTargetPreference(context) {
|
||||
private lateinit var myView: View
|
||||
|
||||
|
@@ -27,7 +27,7 @@ import android.util.Log
|
||||
import android.widget.ImeAwareEditText
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
import com.android.settings.core.instrumentation.InstrumentedDialogFragment
|
||||
import kotlin.coroutines.resume
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
@@ -78,7 +78,7 @@ class FingerprintSettingsRenameDialog : InstrumentedDialogFragment() {
|
||||
end: Int,
|
||||
dest: Spanned?,
|
||||
dstart: Int,
|
||||
dend: Int
|
||||
dend: Int,
|
||||
): CharSequence? {
|
||||
for (index in start until end) {
|
||||
val c = source[index]
|
||||
@@ -133,13 +133,13 @@ class FingerprintSettingsRenameDialog : InstrumentedDialogFragment() {
|
||||
val bundle = Bundle()
|
||||
bundle.putObject(
|
||||
KEY_FINGERPRINT,
|
||||
android.hardware.fingerprint.Fingerprint(fp.name, fp.fingerId, fp.deviceId)
|
||||
android.hardware.fingerprint.Fingerprint(fp.name, fp.fingerId, fp.deviceId),
|
||||
)
|
||||
dialog.arguments = bundle
|
||||
Log.d(TAG, "showing dialog $dialog")
|
||||
dialog.show(
|
||||
target.parentFragmentManager,
|
||||
FingerprintSettingsRenameDialog::class.java.toString()
|
||||
FingerprintSettingsRenameDialog::class.java.toString(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -45,11 +45,12 @@ 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.FingerprintSensorRepoImpl
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.PressToAuthRepoImpl
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.repository.PressToAuthProviderImpl
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.Settings
|
||||
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.Settings
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.binder.FingerprintSettingsViewBinder
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FingerprintSettingsNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FingerprintSettingsViewModel
|
||||
@@ -128,12 +129,12 @@ class FingerprintSettingsV2Fragment :
|
||||
if (resultCode == BiometricEnrollBase.RESULT_TIMEOUT) {
|
||||
navigationViewModel.onEnrollFirstFailure(
|
||||
"Received RESULT_TIMEOUT when enrolling",
|
||||
resultCode
|
||||
resultCode,
|
||||
)
|
||||
} else {
|
||||
navigationViewModel.onEnrollFirstFailure(
|
||||
"Incorrect resultCode or data was null",
|
||||
resultCode
|
||||
resultCode,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
@@ -212,21 +213,24 @@ class FingerprintSettingsV2Fragment :
|
||||
context.contentResolver,
|
||||
Secure.SFPS_PERFORMANT_AUTH_ENABLED,
|
||||
toReturn,
|
||||
userHandle
|
||||
userHandle,
|
||||
)
|
||||
}
|
||||
|
||||
toReturn == 1
|
||||
}
|
||||
val fingerprintSensorProvider =
|
||||
FingerprintSensorRepoImpl(fingerprintManager, backgroundDispatcher, lifecycleScope)
|
||||
|
||||
val interactor =
|
||||
FingerprintManagerInteractorImpl(
|
||||
context.applicationContext,
|
||||
backgroundDispatcher,
|
||||
fingerprintManager,
|
||||
fingerprintSensorProvider,
|
||||
GatekeeperPasswordProvider(LockPatternUtils(context.applicationContext)),
|
||||
PressToAuthProviderImpl(context),
|
||||
isAnySuw
|
||||
PressToAuthRepoImpl(context),
|
||||
Settings,
|
||||
)
|
||||
|
||||
val token = intent.getByteArrayExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN)
|
||||
@@ -240,8 +244,8 @@ class FingerprintSettingsV2Fragment :
|
||||
interactor,
|
||||
backgroundDispatcher,
|
||||
token,
|
||||
challenge
|
||||
)
|
||||
challenge,
|
||||
),
|
||||
)[FingerprintSettingsNavigationViewModel::class.java]
|
||||
|
||||
settingsViewModel =
|
||||
@@ -252,15 +256,10 @@ class FingerprintSettingsV2Fragment :
|
||||
interactor,
|
||||
backgroundDispatcher,
|
||||
navigationViewModel,
|
||||
)
|
||||
),
|
||||
)[FingerprintSettingsViewModel::class.java]
|
||||
|
||||
FingerprintSettingsViewBinder.bind(
|
||||
this,
|
||||
settingsViewModel,
|
||||
navigationViewModel,
|
||||
lifecycleScope,
|
||||
)
|
||||
FingerprintSettingsViewBinder.bind(this, settingsViewModel, navigationViewModel, lifecycleScope)
|
||||
}
|
||||
|
||||
override fun getMetricsCategory(): Int {
|
||||
@@ -364,7 +363,7 @@ class FingerprintSettingsV2Fragment :
|
||||
RestrictedLockUtilsInternal.checkIfKeyguardFeaturesDisabled(
|
||||
activity,
|
||||
DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT,
|
||||
requireActivity().userId
|
||||
requireActivity().userId,
|
||||
)
|
||||
val activity = requireActivity()
|
||||
val helpIntent =
|
||||
@@ -404,7 +403,7 @@ class FingerprintSettingsV2Fragment :
|
||||
column.title =
|
||||
getString(
|
||||
R.string.security_settings_fingerprint_enroll_introduction_v3_message,
|
||||
DeviceHelper.getDeviceName(requireActivity())
|
||||
DeviceHelper.getDeviceName(requireActivity()),
|
||||
)
|
||||
column.learnMoreOnClickListener = learnMoreClickListener
|
||||
column.learnMoreOverrideText =
|
||||
@@ -437,13 +436,12 @@ class FingerprintSettingsV2Fragment :
|
||||
val willDelete =
|
||||
fingerprintPreferences()
|
||||
.first { it?.fingerprintViewModel == fingerprintViewModel }
|
||||
?.askUserToDeleteDialog()
|
||||
?: false
|
||||
?.askUserToDeleteDialog() ?: false
|
||||
if (willDelete) {
|
||||
mMetricsFeatureProvider.action(
|
||||
context,
|
||||
SettingsEnums.ACTION_FINGERPRINT_DELETE,
|
||||
fingerprintViewModel.fingerId
|
||||
fingerprintViewModel.fingerId,
|
||||
)
|
||||
}
|
||||
return willDelete
|
||||
@@ -466,7 +464,7 @@ class FingerprintSettingsV2Fragment :
|
||||
mMetricsFeatureProvider.action(
|
||||
context,
|
||||
SettingsEnums.ACTION_FINGERPRINT_RENAME,
|
||||
toReturn.first.fingerId
|
||||
toReturn.first.fingerId,
|
||||
)
|
||||
}
|
||||
return toReturn
|
||||
@@ -518,12 +516,12 @@ class FingerprintSettingsV2Fragment :
|
||||
val intent = Intent()
|
||||
intent.setClassName(
|
||||
SETTINGS_PACKAGE_NAME,
|
||||
FingerprintEnrollIntroductionInternal::class.java.name
|
||||
FingerprintEnrollIntroductionInternal::class.java.name,
|
||||
)
|
||||
intent.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, true)
|
||||
intent.putExtra(
|
||||
SettingsBaseActivity.EXTRA_PAGE_TRANSITION_TYPE,
|
||||
SettingsTransitionHelper.TransitionType.TRANSITION_SLIDE
|
||||
SettingsTransitionHelper.TransitionType.TRANSITION_SLIDE,
|
||||
)
|
||||
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, userId)
|
||||
@@ -546,7 +544,7 @@ class FingerprintSettingsV2Fragment :
|
||||
val intent = Intent()
|
||||
intent.setClassName(
|
||||
SETTINGS_PACKAGE_NAME,
|
||||
FingerprintEnrollEnrolling::class.qualifiedName.toString()
|
||||
FingerprintEnrollEnrolling::class.qualifiedName.toString(),
|
||||
)
|
||||
intent.putExtra(Intent.EXTRA_USER_ID, userId)
|
||||
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, challengeToken)
|
||||
@@ -568,8 +566,7 @@ class FingerprintSettingsV2Fragment :
|
||||
|
||||
return category?.let { cat ->
|
||||
cat.childrenToList().map { it as FingerprintSettingsPreference? }
|
||||
}
|
||||
?: emptyList()
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
private fun PreferenceCategory.childrenToList(): List<Preference> {
|
||||
|
@@ -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.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
@@ -181,9 +181,7 @@ class FingerprintSettingsNavigationViewModel(
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
|
||||
return FingerprintSettingsNavigationViewModel(
|
||||
userId,
|
||||
|
@@ -21,9 +21,9 @@ import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
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
|
||||
import kotlinx.coroutines.CoroutineDispatcher
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@@ -66,7 +66,7 @@ class FingerprintSettingsViewModel(
|
||||
emit(
|
||||
Pair(
|
||||
fingerprintManagerInteractor.canEnrollFingerprints.first(),
|
||||
fingerprintManagerInteractor.maxEnrollableFingerprints.first()
|
||||
fingerprintManagerInteractor.maxEnrollableFingerprints.first(),
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -120,7 +120,7 @@ class FingerprintSettingsViewModel(
|
||||
_isLockedOut,
|
||||
_attemptsSoFar,
|
||||
_fingerprintSensorType,
|
||||
_sensorNullOrEmpty
|
||||
_sensorNullOrEmpty,
|
||||
) {
|
||||
dialogShowing,
|
||||
step,
|
||||
@@ -140,7 +140,7 @@ class FingerprintSettingsViewModel(
|
||||
"lockedOut=${isLockedOut}," +
|
||||
"attempts=${attempts}," +
|
||||
"sensorType=${sensorType}" +
|
||||
"sensorNullOrEmpty=${sensorNullOrEmpty}"
|
||||
"sensorNullOrEmpty=${sensorNullOrEmpty}",
|
||||
)
|
||||
}
|
||||
if (sensorNullOrEmpty) {
|
||||
@@ -294,9 +294,7 @@ class FingerprintSettingsViewModel(
|
||||
) : ViewModelProvider.Factory {
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
|
||||
return FingerprintSettingsViewModel(
|
||||
userId,
|
||||
@@ -318,7 +316,7 @@ private inline fun <T1, T2, T3, T4, T5, T6, T7, T8, R> combine(
|
||||
flow6: Flow<T6>,
|
||||
flow7: Flow<T7>,
|
||||
flow8: Flow<T8>,
|
||||
crossinline transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8) -> R
|
||||
crossinline transform: suspend (T1, T2, T3, T4, T5, T6, T7, T8) -> R,
|
||||
): Flow<R> {
|
||||
return combine(flow, flow2, flow3, flow4, flow5, flow6, flow7, flow8) { args: Array<*> ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
|
@@ -29,10 +29,8 @@ data class EnrollFirstFingerprint(
|
||||
val challengeToken: ByteArray?,
|
||||
) : NextStepViewModel()
|
||||
|
||||
data class EnrollAdditionalFingerprint(
|
||||
val userId: Int,
|
||||
val challengeToken: ByteArray?,
|
||||
) : NextStepViewModel()
|
||||
data class EnrollAdditionalFingerprint(val userId: Int, val challengeToken: ByteArray?) :
|
||||
NextStepViewModel()
|
||||
|
||||
data class FinishSettings(val reason: String) : NextStepViewModel()
|
||||
|
||||
|
@@ -16,15 +16,11 @@
|
||||
|
||||
package com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel
|
||||
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
|
||||
/** Classed use to represent a Dialogs state. */
|
||||
sealed class PreferenceViewModel {
|
||||
data class RenameDialog(
|
||||
val fingerprintViewModel: FingerprintData,
|
||||
) : PreferenceViewModel()
|
||||
data class RenameDialog(val fingerprintViewModel: FingerprintData) : PreferenceViewModel()
|
||||
|
||||
data class DeleteDialog(
|
||||
val fingerprintViewModel: FingerprintData,
|
||||
) : PreferenceViewModel()
|
||||
data class DeleteDialog(val fingerprintViewModel: FingerprintData) : PreferenceViewModel()
|
||||
}
|
||||
|
@@ -33,16 +33,20 @@ import androidx.test.espresso.matcher.ViewMatchers.withId
|
||||
import androidx.test.espresso.matcher.ViewMatchers.withText
|
||||
import androidx.test.runner.AndroidJUnit4
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Introduction
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.NavigationState
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollIntroV2Fragment
|
||||
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.ui.enrollment.viewmodel.FingerprintEnrollIntroViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Intro
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.NavState
|
||||
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import com.android.systemui.biometrics.shared.model.SensorStrength
|
||||
import com.google.android.setupdesign.GlifLayout
|
||||
import com.google.android.setupdesign.template.RequireScrollMixin
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
@@ -62,18 +66,27 @@ class FingerprintEnrollIntroFragmentTest {
|
||||
)
|
||||
private val backgroundDispatcher = StandardTestDispatcher()
|
||||
private lateinit var fragmentScenario: FragmentScenario<FingerprintEnrollIntroV2Fragment>
|
||||
private val fingerprintSensor =
|
||||
FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.POWER_BUTTON)
|
||||
|
||||
var enrollFlow = Default
|
||||
val flowViewModel = FingerprintFlowViewModel(enrollFlow)
|
||||
|
||||
private val navigationViewModel =
|
||||
FingerprintEnrollNavigationViewModel(
|
||||
backgroundDispatcher,
|
||||
interactor,
|
||||
gatekeeperViewModel,
|
||||
Intro,
|
||||
NavState(true),
|
||||
Default,
|
||||
FingerprintNavigationViewModel(
|
||||
Introduction,
|
||||
false,
|
||||
flowViewModel,
|
||||
interactor
|
||||
)
|
||||
|
||||
private var fingerprintViewModel =
|
||||
FingerprintEnrollViewModel(interactor, gatekeeperViewModel, navigationViewModel)
|
||||
FingerprintEnrollIntroViewModel(
|
||||
navigationViewModel,
|
||||
flowViewModel,
|
||||
interactor,
|
||||
)
|
||||
|
||||
private var fingerprintScrollViewModel = FingerprintScrollViewModel()
|
||||
|
||||
@Before
|
||||
@@ -85,9 +98,9 @@ class FingerprintEnrollIntroFragmentTest {
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
return when (modelClass) {
|
||||
FingerprintEnrollViewModel::class.java -> fingerprintViewModel
|
||||
FingerprintEnrollIntroViewModel::class.java -> fingerprintViewModel
|
||||
FingerprintScrollViewModel::class.java -> fingerprintScrollViewModel
|
||||
FingerprintEnrollNavigationViewModel::class.java -> navigationViewModel
|
||||
FingerprintNavigationViewModel::class.java -> navigationViewModel
|
||||
FingerprintGatekeeperViewModel::class.java -> gatekeeperViewModel
|
||||
else -> null
|
||||
}
|
||||
|
@@ -30,16 +30,19 @@ import androidx.test.core.app.ApplicationProvider
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.android.settings.R
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollIntroV2Fragment
|
||||
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.ui.enrollment.viewmodel.FingerprintEnrollIntroViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintScrollViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.NavState
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Start
|
||||
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import com.android.systemui.biometrics.shared.model.SensorStrength
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import org.junit.Before
|
||||
import org.junit.Rule
|
||||
@@ -60,7 +63,7 @@ class BasicScreenshotTest {
|
||||
InstrumentationRegistry.getInstrumentation()
|
||||
.getTargetContext()
|
||||
.getFilesDir()
|
||||
.getAbsolutePath() + "/settings_screenshots"
|
||||
.getAbsolutePath() + "/settings_screenshots",
|
||||
)
|
||||
)
|
||||
|
||||
@@ -70,24 +73,27 @@ class BasicScreenshotTest {
|
||||
private val gatekeeperViewModel =
|
||||
FingerprintGatekeeperViewModel(
|
||||
GatekeeperInfo.GatekeeperPasswordInfo(byteArrayOf(1, 2, 3), 100L),
|
||||
interactor
|
||||
interactor,
|
||||
)
|
||||
|
||||
private val backgroundDispatcher = StandardTestDispatcher()
|
||||
private lateinit var fragmentScenario: FragmentScenario<FingerprintEnrollIntroV2Fragment>
|
||||
val navState = NavState(true)
|
||||
private val fingerprintSensor =
|
||||
FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.POWER_BUTTON)
|
||||
|
||||
private val navigationViewModel = FingerprintEnrollNavigationViewModel(
|
||||
backgroundDispatcher,
|
||||
var enrollFlow = Default
|
||||
val flowViewModel = FingerprintFlowViewModel(enrollFlow)
|
||||
|
||||
private val navigationViewModel =
|
||||
FingerprintNavigationViewModel(
|
||||
FingerprintNavigationStep.Introduction,
|
||||
false,
|
||||
flowViewModel,
|
||||
interactor,
|
||||
gatekeeperViewModel,
|
||||
Start.next(navState),
|
||||
navState,
|
||||
Default,
|
||||
)
|
||||
private var fingerprintViewModel = FingerprintEnrollViewModel(
|
||||
interactor, gatekeeperViewModel, navigationViewModel,
|
||||
)
|
||||
|
||||
private var fingerprintViewModel =
|
||||
FingerprintEnrollIntroViewModel(navigationViewModel, flowViewModel, interactor)
|
||||
private var fingerprintScrollViewModel = FingerprintScrollViewModel()
|
||||
|
||||
@Before
|
||||
@@ -95,13 +101,11 @@ class BasicScreenshotTest {
|
||||
val factory =
|
||||
object : ViewModelProvider.Factory {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : ViewModel> create(
|
||||
modelClass: Class<T>,
|
||||
): T {
|
||||
override fun <T : ViewModel> create(modelClass: Class<T>): T {
|
||||
return when (modelClass) {
|
||||
FingerprintEnrollViewModel::class.java -> fingerprintViewModel
|
||||
FingerprintEnrollIntroViewModel::class.java -> fingerprintViewModel
|
||||
FingerprintScrollViewModel::class.java -> fingerprintScrollViewModel
|
||||
FingerprintEnrollNavigationViewModel::class.java -> navigationViewModel
|
||||
FingerprintNavigationViewModel::class.java -> navigationViewModel
|
||||
FingerprintGatekeeperViewModel::class.java -> gatekeeperViewModel
|
||||
else -> null
|
||||
}
|
||||
@@ -118,11 +122,7 @@ class BasicScreenshotTest {
|
||||
/** Renders a [view] into a [Bitmap]. */
|
||||
private fun viewToBitmap(view: View): Bitmap {
|
||||
val bitmap =
|
||||
Bitmap.createBitmap(
|
||||
view.measuredWidth,
|
||||
view.measuredHeight,
|
||||
Bitmap.Config.ARGB_8888,
|
||||
)
|
||||
Bitmap.createBitmap(view.measuredWidth, view.measuredHeight, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(bitmap)
|
||||
view.draw(canvas)
|
||||
return bitmap
|
||||
@@ -136,12 +136,7 @@ class BasicScreenshotTest {
|
||||
}
|
||||
fragmentScenario.onFragment { fragment ->
|
||||
val view = fragment.requireView().findViewById<View>(R.id.enroll_intro_content_view)!!
|
||||
rule.assertBitmapAgainstGolden(
|
||||
viewToBitmap(view),
|
||||
"fp_enroll_intro",
|
||||
MSSIMMatcher()
|
||||
)
|
||||
rule.assertBitmapAgainstGolden(viewToBitmap(view), "fp_enroll_intro", MSSIMMatcher())
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -16,11 +16,11 @@
|
||||
|
||||
package com.android.settings.testutils2
|
||||
|
||||
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.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
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.systemui.biometrics.shared.model.FingerprintSensor
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import com.android.systemui.biometrics.shared.model.SensorStrength
|
||||
|
@@ -26,17 +26,23 @@ 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.FingerprintSensorRepo
|
||||
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
|
||||
import com.android.settings.biometrics.fingerprint2.shared.data.repository.PressToAuthProvider
|
||||
import com.android.settings.biometrics.fingerprint2.shared.domain.interactor.FingerprintManagerInteractor
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.EnrollReason
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerEnrollState
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.data.repository.PressToAuthRepo
|
||||
import com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
|
||||
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.password.ChooseLockSettingsHelper
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import com.android.systemui.biometrics.shared.model.SensorStrength
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.cancelAndJoin
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.last
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
@@ -71,21 +77,28 @@ class FingerprintManagerInteractorTest {
|
||||
@Mock private lateinit var gateKeeperPasswordProvider: GatekeeperPasswordProvider
|
||||
|
||||
private var testScope = TestScope(backgroundDispatcher)
|
||||
private var pressToAuthProvider =
|
||||
object : PressToAuthProvider {
|
||||
private var pressToAuthRepo =
|
||||
object : PressToAuthRepo {
|
||||
override val isEnabled: Boolean
|
||||
get() = false
|
||||
}
|
||||
|
||||
@Before
|
||||
fun setup() {
|
||||
val sensor = FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.POWER_BUTTON)
|
||||
val fingerprintSensorRepo =
|
||||
object : FingerprintSensorRepo {
|
||||
override val fingerprintSensor: Flow<FingerprintSensor> = flowOf(sensor)
|
||||
}
|
||||
|
||||
underTest =
|
||||
FingerprintManagerInteractorImpl(
|
||||
context,
|
||||
backgroundDispatcher,
|
||||
fingerprintManager,
|
||||
fingerprintSensorRepo,
|
||||
gateKeeperPasswordProvider,
|
||||
pressToAuthProvider,
|
||||
pressToAuthRepo,
|
||||
Default,
|
||||
)
|
||||
}
|
||||
|
@@ -21,16 +21,17 @@ import android.content.res.Configuration
|
||||
import android.view.accessibility.AccessibilityManager
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import androidx.test.core.app.ApplicationProvider
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.AccessibilityViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.BackgroundViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Education
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollFindSensorViewModel
|
||||
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.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Education
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FoldStateViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.NextStepViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.NavigationState
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.OrientationStateViewModel
|
||||
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||
@@ -38,7 +39,6 @@ import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import com.android.systemui.biometrics.shared.model.SensorStrength
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.collectLatest
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.test.StandardTestDispatcher
|
||||
import kotlinx.coroutines.test.TestScope
|
||||
@@ -67,7 +67,7 @@ class FingerprintEnrollFindSensorViewModelV2Test {
|
||||
private lateinit var fakeFingerprintManagerInteractor: FakeFingerprintManagerInteractor
|
||||
private lateinit var gatekeeperViewModel: FingerprintGatekeeperViewModel
|
||||
private lateinit var enrollViewModel: FingerprintEnrollViewModel
|
||||
private lateinit var navigationViewModel: FingerprintEnrollNavigationViewModel
|
||||
private lateinit var navigationViewModel: FingerprintNavigationViewModel
|
||||
private lateinit var accessibilityViewModel: AccessibilityViewModel
|
||||
private lateinit var foldStateViewModel: FoldStateViewModel
|
||||
private lateinit var orientationStateViewModel: OrientationStateViewModel
|
||||
@@ -87,18 +87,19 @@ class FingerprintEnrollFindSensorViewModelV2Test {
|
||||
gatekeeperViewModel =
|
||||
FingerprintGatekeeperViewModel.FingerprintGatekeeperViewModelFactory(
|
||||
null,
|
||||
fakeFingerprintManagerInteractor
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
.create(FingerprintGatekeeperViewModel::class.java)
|
||||
|
||||
val sensor = FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.POWER_BUTTON)
|
||||
val fingerprintFlowViewModel = FingerprintFlowViewModel(Default)
|
||||
navigationViewModel =
|
||||
FingerprintEnrollNavigationViewModel.FingerprintEnrollNavigationViewModelFactory(
|
||||
backgroundDispatcher,
|
||||
FingerprintNavigationViewModel(
|
||||
Education(sensor),
|
||||
false,
|
||||
fingerprintFlowViewModel,
|
||||
fakeFingerprintManagerInteractor,
|
||||
gatekeeperViewModel,
|
||||
canSkipConfirm = true,
|
||||
Default,
|
||||
)
|
||||
.create(FingerprintEnrollNavigationViewModel::class.java)
|
||||
|
||||
backgroundViewModel =
|
||||
BackgroundViewModel.BackgroundViewModelFactory().create(BackgroundViewModel::class.java)
|
||||
@@ -126,12 +127,10 @@ class FingerprintEnrollFindSensorViewModelV2Test {
|
||||
backgroundViewModel,
|
||||
accessibilityViewModel,
|
||||
foldStateViewModel,
|
||||
orientationStateViewModel
|
||||
orientationStateViewModel,
|
||||
fingerprintFlowViewModel,
|
||||
)
|
||||
.create(FingerprintEnrollFindSensorViewModel::class.java)
|
||||
|
||||
// Navigate to Education page
|
||||
navigationViewModel.nextStep()
|
||||
}
|
||||
|
||||
@After
|
||||
@@ -141,18 +140,6 @@ class FingerprintEnrollFindSensorViewModelV2Test {
|
||||
|
||||
// TODO(b/305094585): test enroll() logic
|
||||
|
||||
@Test
|
||||
fun currentStepIsEducation() =
|
||||
testScope.runTest {
|
||||
var step: NextStepViewModel? = null
|
||||
val job = launch {
|
||||
navigationViewModel.navigationViewModel.collectLatest { step = it.currStep }
|
||||
}
|
||||
advanceUntilIdle()
|
||||
assertThat(step).isEqualTo(Education)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun udfpsLottieInfo() =
|
||||
testScope.runTest {
|
||||
@@ -161,7 +148,7 @@ class FingerprintEnrollFindSensorViewModelV2Test {
|
||||
0 /* sensorId */,
|
||||
SensorStrength.STRONG,
|
||||
5,
|
||||
FingerprintSensorType.UDFPS_OPTICAL
|
||||
FingerprintSensorType.UDFPS_OPTICAL,
|
||||
)
|
||||
|
||||
var udfpsLottieInfo: Boolean? = null
|
||||
@@ -234,7 +221,7 @@ class FingerprintEnrollFindSensorViewModelV2Test {
|
||||
0 /* sensorId */,
|
||||
SensorStrength.STRONG,
|
||||
5,
|
||||
FingerprintSensorType.UDFPS_OPTICAL
|
||||
FingerprintSensorType.UDFPS_OPTICAL,
|
||||
)
|
||||
|
||||
var showPrimaryButton: Boolean? = null
|
||||
|
@@ -17,16 +17,20 @@
|
||||
package com.android.settings.fingerprint2.ui.enrollment.viewmodel
|
||||
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.Default
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.BackgroundViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.Enrollment
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollEnrollingViewModel
|
||||
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.ui.enrollment.viewmodel.FingerprintFlowViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintGatekeeperViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep.Enrollment
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.GatekeeperInfo
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.NavState
|
||||
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.NavigationState
|
||||
import com.android.settings.testutils2.FakeFingerprintManagerInteractor
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensor
|
||||
import com.android.systemui.biometrics.shared.model.FingerprintSensorType
|
||||
import com.android.systemui.biometrics.shared.model.SensorStrength
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
@@ -54,7 +58,7 @@ class FingerprintEnrollEnrollingViewModelTest {
|
||||
private lateinit var enrollEnrollingViewModel: FingerprintEnrollEnrollingViewModel
|
||||
private lateinit var backgroundViewModel: BackgroundViewModel
|
||||
private lateinit var gateKeeperViewModel: FingerprintGatekeeperViewModel
|
||||
private lateinit var navigationViewModel: FingerprintEnrollNavigationViewModel
|
||||
private lateinit var navigationViewModel: FingerprintNavigationViewModel
|
||||
private val defaultGatekeeperInfo = GatekeeperInfo.GatekeeperPasswordInfo(byteArrayOf(1, 3), 3)
|
||||
private var testScope = TestScope(backgroundDispatcher)
|
||||
|
||||
@@ -65,18 +69,18 @@ class FingerprintEnrollEnrollingViewModelTest {
|
||||
gateKeeperViewModel =
|
||||
FingerprintGatekeeperViewModel.FingerprintGatekeeperViewModelFactory(
|
||||
gatekeeperInfo,
|
||||
fakeFingerprintManagerInteractor
|
||||
fakeFingerprintManagerInteractor,
|
||||
)
|
||||
.create(FingerprintGatekeeperViewModel::class.java)
|
||||
val sensor = FingerprintSensor(1, SensorStrength.STRONG, 5, FingerprintSensorType.POWER_BUTTON)
|
||||
val fingerprintFlowViewModel = FingerprintFlowViewModel(Default)
|
||||
|
||||
navigationViewModel =
|
||||
FingerprintEnrollNavigationViewModel(
|
||||
backgroundDispatcher,
|
||||
FingerprintNavigationViewModel(
|
||||
Enrollment(sensor),
|
||||
false,
|
||||
fingerprintFlowViewModel,
|
||||
fakeFingerprintManagerInteractor,
|
||||
gateKeeperViewModel,
|
||||
Enrollment,
|
||||
NavState(true),
|
||||
Default,
|
||||
)
|
||||
|
||||
backgroundViewModel =
|
||||
|
@@ -18,7 +18,7 @@ package com.android.settings.fingerprint2.ui.settings
|
||||
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.android.settings.biometrics.BiometricEnrollBase
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.EnrollFirstFingerprint
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FingerprintSettingsNavigationViewModel
|
||||
import com.android.settings.biometrics.fingerprint2.ui.settings.viewmodel.FinishSettings
|
||||
|
@@ -17,8 +17,8 @@
|
||||
package com.android.settings.fingerprint2.ui.settings
|
||||
|
||||
import androidx.arch.core.executor.testing.InstantTaskExecutorRule
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.shared.model.FingerprintData
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintAuthAttemptModel
|
||||
import com.android.settings.biometrics.fingerprint2.lib.model.FingerprintData
|
||||
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
|
||||
|
Reference in New Issue
Block a user