Adding FingerprintEnrollConfirmation
Bug: 295217067
Test: atest FingerprintEnrollConfirmationScreenshotTest.kt
Test: adb shell device_config put biometrics_framework com.android.settings.flags.fingerprint_v2_enrollment true
Change-Id: I0b4995a97b7bccd35e26ed89bbbf14b80af4b0e1
diff --git a/aconfig/settings_biometrics_framework_flag_declarations.aconfig b/aconfig/settings_biometrics_framework_flag_declarations.aconfig
index e9f19bc..4355ed1 100644
--- a/aconfig/settings_biometrics_framework_flag_declarations.aconfig
+++ b/aconfig/settings_biometrics_framework_flag_declarations.aconfig
@@ -7,3 +7,10 @@
description: "This flag enables or disables the BiometricSettingsProvider"
bug: "303595205"
}
+
+flag {
+ name: "fingerprint_v2_enrollment"
+ namespace: "biometrics_framework"
+ description: "This flag enables or disables the Fingerprint v2 enrollment"
+ bug: "295206723"
+}
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/activity/FingerprintEnrollmentV2Activity.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/activity/FingerprintEnrollmentV2Activity.kt
index 65030de..d26b812 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/activity/FingerprintEnrollmentV2Activity.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/activity/FingerprintEnrollmentV2Activity.kt
@@ -37,13 +37,13 @@
import com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED
import com.android.settings.biometrics.GatekeeperPasswordProvider
import com.android.settings.biometrics.fingerprint2.data.repository.FingerprintSensorRepositoryImpl
-import com.android.settings.biometrics.fingerprint2.domain.interactor.PressToAuthInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.AccessibilityInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.FingerprintManagerInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractor
import com.android.settings.biometrics.fingerprint2.domain.interactor.FoldStateInteractorImpl
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractor
import com.android.settings.biometrics.fingerprint2.domain.interactor.OrientationInteractorImpl
+import com.android.settings.biometrics.fingerprint2.domain.interactor.PressToAuthInteractorImpl
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
@@ -54,6 +54,7 @@
import com.android.settings.biometrics.fingerprint2.ui.enrollment.modules.enrolling.rfps.ui.viewmodel.RFPSViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.BackgroundViewModel
import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintAction
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollConfirmationViewModel
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.FingerprintEnrollIntroViewModel
@@ -70,6 +71,7 @@
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.flags.Flags
import com.android.settings.password.ChooseLockGeneric
import com.android.settings.password.ChooseLockSettingsHelper
import com.android.settings.password.ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE
@@ -96,6 +98,8 @@
private lateinit var fingerprintScrollViewModel: FingerprintScrollViewModel
private lateinit var backgroundViewModel: BackgroundViewModel
private lateinit var fingerprintFlowViewModel: FingerprintFlowViewModel
+ private lateinit var fingerprintEnrollConfirmationViewModel:
+ FingerprintEnrollConfirmationViewModel
private val coroutineDispatcher = Dispatchers.Default
/** Result listener for ChooseLock activity flow. */
@@ -155,6 +159,15 @@
// TODO(b/299573056): Show split screen dialog when it's in multi window mode.
setContentView(R.layout.fingerprint_v2_enroll_main)
+ if (!Flags.fingerprintV2Enrollment()) {
+ check(false) {
+ "fingerprint enrollment v2 is not enabled, " +
+ "please run adb shell device_config put " +
+ "biometrics_framework com.android.settings.flags.fingerprint_v2_enrollment true"
+ }
+ finish()
+ }
+
setTheme(SetupWizardUtils.getTheme(applicationContext, intent))
ThemeHelper.trySetDynamicColor(applicationContext)
@@ -293,6 +306,15 @@
),
)[RFPSViewModel::class.java]
+ fingerprintEnrollConfirmationViewModel =
+ ViewModelProvider(
+ this,
+ FingerprintEnrollConfirmationViewModel.FingerprintEnrollConfirmationViewModelFactory(
+ navigationViewModel,
+ fingerprintManagerInteractor,
+ ),
+ )[FingerprintEnrollConfirmationViewModel::class.java]
+
lifecycleScope.launch {
navigationViewModel.currentStep.collect { step ->
if (step is Init) {
@@ -304,6 +326,7 @@
lifecycleScope.launch {
navigationViewModel.navigateTo.filterNotNull().collect { step ->
+ Log.d(TAG, "navigateTo: $step")
if (step is ConfirmDeviceCredential) {
launchConfirmOrChooseLock(userId)
navigationViewModel.update(
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollConfirmationV2Fragment.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollConfirmationV2Fragment.kt
index fd07a95..d8c1c93 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollConfirmationV2Fragment.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/fragment/FingerprintEnrollConfirmationV2Fragment.kt
@@ -17,7 +17,21 @@
package com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment
import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.annotation.VisibleForTesting
import androidx.fragment.app.Fragment
+import androidx.lifecycle.Lifecycle
+import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.lifecycleScope
+import androidx.lifecycle.repeatOnLifecycle
+import com.android.settings.R
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollConfirmationViewModel
+import com.google.android.setupcompat.template.FooterBarMixin
+import com.google.android.setupcompat.template.FooterButton
+import com.google.android.setupdesign.GlifLayout
+import kotlinx.coroutines.launch
/**
* A fragment to indicate that fingerprint enrollment has been completed.
@@ -25,9 +39,71 @@
* This page will display basic information about what a fingerprint can be used for and acts as the
* final step of enrollment.
*/
-class FingerprintEnrollConfirmationV2Fragment : Fragment() {
+class FingerprintEnrollConfirmationV2Fragment() :
+ Fragment(R.layout.fingerprint_enroll_finish_base) {
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
+ companion object {
+ const val TAG = "FingerprintEnrollConfirmationV2Fragment"
+ }
+
+ /** Used for testing purposes */
+ private var factory: ViewModelProvider.Factory? = null
+
+ @VisibleForTesting
+ constructor(theFactory: ViewModelProvider.Factory) : this() {
+ factory = theFactory
+ }
+
+ private val viewModelProvider: ViewModelProvider by lazy {
+ if (factory != null) {
+ ViewModelProvider(requireActivity(), factory!!)
+ } else {
+ ViewModelProvider(requireActivity())
+ }
+ }
+
+ private val viewModel: FingerprintEnrollConfirmationViewModel by lazy {
+ viewModelProvider[FingerprintEnrollConfirmationViewModel::class.java]
+ }
+
+ override fun onCreateView(
+ inflater: LayoutInflater,
+ container: ViewGroup?,
+ savedInstanceState: Bundle?,
+ ): View? =
+ super.onCreateView(inflater, container, savedInstanceState).also { theView ->
+ val mainView = theView!! as GlifLayout
+
+ mainView.setHeaderText(R.string.security_settings_fingerprint_enroll_finish_title)
+ mainView.setDescriptionText(R.string.security_settings_fingerprint_enroll_finish_v2_message)
+
+ val mixin = mainView.getMixin(FooterBarMixin::class.java)
+ viewLifecycleOwner.lifecycleScope.launch {
+ repeatOnLifecycle(Lifecycle.State.RESUMED) {
+ viewModel.isAddAnotherButtonVisible.collect {
+ mixin.secondaryButton =
+ FooterButton.Builder(requireContext())
+ .setText(R.string.fingerprint_enroll_button_add)
+ .setListener { viewModel.onAddAnotherButtonClicked() }
+ .setButtonType(FooterButton.ButtonType.SKIP)
+ .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Secondary)
+ .build()
+ }
+ }
+ }
+
+ mixin.setPrimaryButton(
+ FooterButton.Builder(requireContext())
+ .setText(R.string.security_settings_fingerprint_enroll_done)
+ .setListener(this::onNextButtonClick)
+ .setButtonType(FooterButton.ButtonType.NEXT)
+ .setTheme(com.google.android.setupdesign.R.style.SudGlifButton_Primary)
+ .build()
+ )
+ }
+
+ @Suppress("UNUSED_PARAMETER")
+ private fun onNextButtonClick(view: View?) {
+ viewModel.onNextButtonClicked()
}
}
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/rfps/ui/viewmodel/RFPSViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/rfps/ui/viewmodel/RFPSViewModel.kt
index 2408a88..6ee5709 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/rfps/ui/viewmodel/RFPSViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/modules/enrolling/rfps/ui/viewmodel/RFPSViewModel.kt
@@ -47,10 +47,12 @@
/** Value to indicate if the text view is visible or not */
val textViewIsVisible: Flow<Boolean> = _textViewIsVisible.asStateFlow()
+ private var _shouldAnimateIcon: Flow<Boolean> =
+ fingerprintEnrollViewModel.enrollFlowShouldBeRunning
/** Indicates if the icon should be animating or not */
- val shouldAnimateIcon = fingerprintEnrollViewModel.enrollFlowShouldBeRunning
+ val shouldAnimateIcon = _shouldAnimateIcon
- private val enrollFlow: Flow<FingerEnrollState?> = fingerprintEnrollViewModel.enrollFLow
+ private var enrollFlow: Flow<FingerEnrollState?> = fingerprintEnrollViewModel.enrollFLow
/**
* Enroll progress message with a replay of size 1 allowing for new subscribers to get the most
@@ -59,7 +61,7 @@
val progress: Flow<FingerEnrollState.EnrollProgress?> =
enrollFlow
.filterIsInstance<FingerEnrollState.EnrollProgress>()
- .shareIn(viewModelScope, SharingStarted.Eagerly, 1)
+ .shareIn(viewModelScope, SharingStarted.Eagerly, 0)
/** Clear help message on enroll progress */
val clearHelpMessage: Flow<Boolean> = progress.map { it != null }
@@ -122,6 +124,7 @@
/** Indicates the negative button has been clicked */
fun negativeButtonClicked() {
+ doReset()
navigationViewModel.update(
FingerprintAction.NEGATIVE_BUTTON_PRESSED,
navStep,
@@ -129,11 +132,19 @@
)
}
- /** Indicates that enrollment has been finished and we can proceed to the next step. */
+ /** Indicates that an enrollment was completed */
fun finishedSuccessfully() {
+ doReset()
navigationViewModel.update(FingerprintAction.NEXT, navStep, "${TAG}#progressFinished")
}
+ private fun doReset() {
+ _textViewIsVisible.update { false }
+ _shouldAnimateIcon = fingerprintEnrollViewModel.enrollFlowShouldBeRunning
+ /** Indicates if the icon should be animating or not */
+ enrollFlow = fingerprintEnrollViewModel.enrollFLow
+ }
+
class RFPSViewModelFactory(
private val fingerprintEnrollEnrollingViewModel: FingerprintEnrollEnrollingViewModel,
private val navigationViewModel: FingerprintNavigationViewModel,
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollConfirmationViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollConfirmationViewModel.kt
new file mode 100644
index 0000000..d9b31d7
--- /dev/null
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollConfirmationViewModel.kt
@@ -0,0 +1,67 @@
+/*
+ * 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 com.android.settings.biometrics.fingerprint2.lib.domain.interactor.FingerprintManagerInteractor
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * Models the UI state for [FingerprintEnrollConfirmationV2Fragment]
+ */
+class FingerprintEnrollConfirmationViewModel(
+ private val navigationViewModel: FingerprintNavigationViewModel,
+ fingerprintInteractor: FingerprintManagerInteractor,
+) : ViewModel() {
+
+ /**
+ * Indicates if the add another button is possible. This should only be true when the user is able
+ * to enroll more fingerprints.
+ */
+ val isAddAnotherButtonVisible: Flow<Boolean> = fingerprintInteractor.canEnrollFingerprints
+
+ /**
+ * Indicates that the user has clicked the next button and is done with fingerprint enrollment.
+ */
+ fun onNextButtonClicked() {
+ navigationViewModel.update(FingerprintAction.NEXT, navStep, "onNextButtonClicked")
+ }
+
+ /**
+ * Indicates that the user has clicked the add another button and will be sent to the enrollment
+ * screen.
+ */
+ fun onAddAnotherButtonClicked() {
+ navigationViewModel.update(FingerprintAction.ADD_ANOTHER, navStep, "onAddAnotherButtonClicked")
+ }
+
+ class FingerprintEnrollConfirmationViewModelFactory(
+ private val navigationViewModel: FingerprintNavigationViewModel,
+ private val fingerprintInteractor: FingerprintManagerInteractor,
+ ) : ViewModelProvider.Factory {
+ @Suppress("UNCHECKED_CAST")
+ override fun <T : ViewModel> create(modelClass: Class<T>): T {
+ return FingerprintEnrollConfirmationViewModel(navigationViewModel, fingerprintInteractor) as T
+ }
+ }
+
+ companion object {
+ private const val TAG = "FingerprintEnrollConfirmationViewModel"
+ private val navStep = FingerprintNavigationStep.Confirmation::class
+ }
+}
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintNavigationStep.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintNavigationStep.kt
index 979f953..76b4895 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintNavigationStep.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintNavigationStep.kt
@@ -37,6 +37,7 @@
ACTIVITY_CREATED,
NEGATIVE_BUTTON_PRESSED,
USER_CLICKED_FINISH,
+ ADD_ANOTHER,
}
/** State that can be used to help a [FingerprintNavigationStep] determine the next step to take. */
@@ -179,6 +180,7 @@
return when (action) {
FingerprintAction.NEXT -> Finish(null)
FingerprintAction.PREV -> TransitionStep(Education(state.fingerprintSensor!!))
+ FingerprintAction.ADD_ANOTHER -> TransitionStep(Enrollment(state.fingerprintSensor!!))
else -> null
}
}
diff --git a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintNavigationViewModel.kt b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintNavigationViewModel.kt
index 26c20cf..131f5bb 100644
--- a/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintNavigationViewModel.kt
+++ b/src/com/android/settings/biometrics/fingerprint2/ui/enrollment/viewmodel/FingerprintNavigationViewModel.kt
@@ -89,7 +89,7 @@
fun update(action: FingerprintAction, caller: KClass<*>, debugStr: String) {
Log.d(TAG, "$caller.update($action) $debugStr")
val currentStep = _currentStep.value
- val isUiStep = currentStep is UiStep
+ val isUiStep = currentStep is UiStep && caller is UiStep
if (currentStep == null) {
throw NullPointerException("current step is null")
}
diff --git a/tests/screenshot/OWNERS b/tests/screenshot/OWNERS
new file mode 100644
index 0000000..fbe29d1
--- /dev/null
+++ b/tests/screenshot/OWNERS
@@ -0,0 +1,2 @@
+joshmccloskey@google.com
+jbolinger@google.com
diff --git a/tests/screenshot/assets/robolectric/fp_enroll_confirmation.png b/tests/screenshot/assets/robolectric/fp_enroll_confirmation.png
new file mode 100644
index 0000000..db9009b
--- /dev/null
+++ b/tests/screenshot/assets/robolectric/fp_enroll_confirmation.png
Binary files differ
diff --git a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
index 84d76ff..3cd2002 100644
--- a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
+++ b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/Injector.kt
@@ -27,6 +27,7 @@
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.viewmodel.BackgroundViewModel
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollConfirmationViewModel
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.FingerprintEnrollIntroViewModel
@@ -103,6 +104,9 @@
var rfpsViewModel =
RFPSViewModel(fingerprintEnrollEnrollingViewModel, navigationViewModel, orientationInteractor)
+ val fingerprintEnrollConfirmationViewModel =
+ FingerprintEnrollConfirmationViewModel(navigationViewModel, interactor)
+
var fingerprintFindSensorViewModel =
FingerprintEnrollFindSensorViewModel(
navigationViewModel,
@@ -131,6 +135,7 @@
BackgroundViewModel::class.java -> backgroundViewModel
RFPSIconTouchViewModel::class.java -> rfpsIconTouchViewModel
FingerprintEnrollEnrollingViewModel::class.java -> fingerprintEnrollEnrollingViewModel
+ FingerprintEnrollConfirmationViewModel::class.java -> fingerprintEnrollConfirmationViewModel
else -> null
}
as T
diff --git a/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/fragment/FingerprintEnrollConfirmationScreenshotTest.kt b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/fragment/FingerprintEnrollConfirmationScreenshotTest.kt
new file mode 100644
index 0000000..28f4fbe
--- /dev/null
+++ b/tests/screenshot/src/com/android/settings/tests/screenshot/biometrics/fingerprint/fragment/FingerprintEnrollConfirmationScreenshotTest.kt
@@ -0,0 +1,46 @@
+/*
+ * 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.tests.screenshot.biometrics.fingerprint.fragment
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.platform.app.InstrumentationRegistry
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.fragment.FingerprintEnrollConfirmationV2Fragment
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
+import com.android.settings.tests.screenshot.biometrics.fingerprint.Injector
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import platform.test.screenshot.FragmentScreenshotTestRule
+import platform.test.screenshot.ViewScreenshotTestRule.Mode
+
+@RunWith(AndroidJUnit4::class)
+class FingerprintEnrollConfirmationScreenshotTest {
+ private val injector: Injector = Injector(FingerprintNavigationStep.Confirmation)
+
+ @Rule
+ @JvmField
+ var rule: FragmentScreenshotTestRule = Injector.BiometricFragmentScreenShotRule()
+
+ @Test
+ fun testConfirmation() {
+ rule.screenshotTest(
+ "fp_enroll_confirmation",
+ Mode.MatchSize,
+ FingerprintEnrollConfirmationV2Fragment(injector.factory),
+ )
+ }
+}
diff --git a/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt b/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt
index f202c4f..829716e 100644
--- a/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt
+++ b/tests/unit/src/com/android/settings/fingerprint2/enrollment/viewmodel/FingerprintEnrollFindSensorViewModelV2Test.kt
@@ -40,6 +40,7 @@
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
@@ -119,21 +120,18 @@
}
foldStateInteractor =
object : FoldStateInteractor {
- override val isFolded: Flow<Boolean> = foldState
+ override val isFolded: Flow<Boolean> = foldState.asStateFlow()
+
override fun onConfigurationChange(newConfig: Configuration) {
- TODO("Not yet implemented")
+ foldState.update { false }
}
}
+
orientationInteractor =
- object: OrientationInteractor {
- override val orientation: Flow<Int>
- get() = TODO("Not yet implemented")
+ object : OrientationInteractor {
+ override val orientation: Flow<Int> = flowOf(Configuration.ORIENTATION_LANDSCAPE)
override val rotation: Flow<Int> = flowOf(Surface.ROTATION_0)
-
- override fun getRotationFromDefault(rotation: Int): Int {
- TODO("Not yet implemented")
- }
-
+ override fun getRotationFromDefault(rotation: Int): Int = rotation
}
underTest =
FingerprintEnrollFindSensorViewModel.FingerprintEnrollFindSensorViewModelFactory(
diff --git a/tests/unit/src/com/android/settings/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollConfirmationViewModelTest.kt b/tests/unit/src/com/android/settings/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollConfirmationViewModelTest.kt
new file mode 100644
index 0000000..696e4fa
--- /dev/null
+++ b/tests/unit/src/com/android/settings/fingerprint2/ui/enrollment/viewmodel/FingerprintEnrollConfirmationViewModelTest.kt
@@ -0,0 +1,111 @@
+/*
+ * 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.fingerprint2.ui.enrollment.viewmodel
+
+import androidx.arch.core.executor.testing.InstantTaskExecutorRule
+import com.android.settings.biometrics.fingerprint2.lib.model.Default
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintEnrollConfirmationViewModel
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintFlowViewModel
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationStep
+import com.android.settings.biometrics.fingerprint2.ui.enrollment.viewmodel.FingerprintNavigationViewModel
+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.launch
+import kotlinx.coroutines.test.StandardTestDispatcher
+import kotlinx.coroutines.test.TestScope
+import kotlinx.coroutines.test.advanceUntilIdle
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.junit.MockitoJUnit
+import org.mockito.junit.MockitoJUnitRunner
+
+@RunWith(MockitoJUnitRunner::class)
+class FingerprintEnrollConfirmationViewModelTest {
+ @JvmField @Rule var rule = MockitoJUnit.rule()
+
+ @get:Rule val instantTaskRule = InstantTaskExecutorRule()
+ private var backgroundDispatcher = StandardTestDispatcher()
+ private var testScope = TestScope(backgroundDispatcher)
+ val fingerprintFlowViewModel = FingerprintFlowViewModel(Default)
+ val fakeFingerprintManagerInteractor = FakeFingerprintManagerInteractor()
+ lateinit var navigationViewModel: FingerprintNavigationViewModel
+ lateinit var underTest: FingerprintEnrollConfirmationViewModel
+
+ @Before
+ fun setup() {
+ navigationViewModel =
+ FingerprintNavigationViewModel(
+ FingerprintNavigationStep.Confirmation,
+ false,
+ fingerprintFlowViewModel,
+ fakeFingerprintManagerInteractor,
+ )
+ underTest =
+ FingerprintEnrollConfirmationViewModel(navigationViewModel, fakeFingerprintManagerInteractor)
+ }
+
+ @Test
+ fun testCanEnrollFingerprints() =
+ testScope.runTest {
+ fakeFingerprintManagerInteractor.sensorProp =
+ FingerprintSensor(0 /* sensorId */, SensorStrength.STRONG, 5, FingerprintSensorType.REAR)
+ fakeFingerprintManagerInteractor.enrolledFingerprintsInternal = mutableListOf()
+ fakeFingerprintManagerInteractor.enrollableFingerprints = 5
+
+ var canEnrollFingerprints: Boolean = false
+ val job = launch { underTest.isAddAnotherButtonVisible.collect { canEnrollFingerprints = it } }
+
+ advanceUntilIdle()
+ assertThat(canEnrollFingerprints).isTrue()
+ job.cancel()
+ }
+
+ @Test
+ fun testNextButtonSendsNextStep() =
+ testScope.runTest {
+ var step: FingerprintNavigationStep.UiStep? = null
+ val job = launch { navigationViewModel.navigateTo.collect { step = it } }
+
+ underTest.onNextButtonClicked()
+
+ runCurrent()
+
+ assertThat(step).isNull()
+ job.cancel()
+ }
+
+ @Test
+ fun testAddAnotherSendsAction() =
+ testScope.runTest {
+ var step: FingerprintNavigationStep.UiStep? = null
+ val job = launch { navigationViewModel.navigateTo.collect { step = it } }
+
+ underTest.onAddAnotherButtonClicked()
+
+ runCurrent()
+
+ assertThat(step).isInstanceOf(FingerprintNavigationStep.Enrollment::class.java)
+ job.cancel()
+ }
+}