[BiometricsV2] Add retry button

Add retry button for FingerprintEnrollErrorDialog and make sure that
this button works well in the whole enrollment flow.

Bug: 287168522
Test: manually test this dialog with error and rotate devices
Test: atest FingerprintEnrollEnrollingViewModelTest
Test: atest FingerprintEnrollErrorDialogViewModelTest
Test: atest FingerprintEnrollProgressViewModelTest
Test: atest FingerprintEnrollmentActivityTest
Test: atest biometrics-enrollment-test

Change-Id: Ica1d91d077ca322caca5551068f2a3c23b544361
This commit is contained in:
Milton Wu
2023-06-28 21:51:53 +08:00
parent a372258805
commit f94932801a
21 changed files with 1138 additions and 729 deletions

View File

@@ -18,13 +18,9 @@ package com.android.settings.biometrics2.ui.viewmodel;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.ErrorDialogData;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FingerprintErrorDialogAction;
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository;
import static com.google.common.truth.Truth.assertThat;
@@ -78,19 +74,10 @@ public class FingerprintEnrollEnrollingViewModelTest {
mViewModel = new FingerprintEnrollEnrollingViewModel(
mApplication,
TEST_USER_ID,
newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL, 5)
newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL, 5)
);
}
@Test
public void testShowErrorDialogLiveData() {
assertThat(mViewModel.getErrorDialogLiveData().getValue()).isEqualTo(null);
final ErrorDialogData data = new ErrorDialogData("errMsg", "errTitle", 0);
mViewModel.showErrorDialog(data);
assertThat(mViewModel.getErrorDialogLiveData().getValue()).isEqualTo(data);
}
@Test
public void testIconTouchDialog() {
final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
@@ -101,20 +88,6 @@ public class FingerprintEnrollEnrollingViewModelTest {
FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG);
}
@Test
public void testErrorDialogActionLiveData() {
assertThat(mViewModel.getErrorDialogActionLiveData().getValue()).isEqualTo(null);
@FingerprintErrorDialogAction int action =
FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT;
mViewModel.onErrorDialogAction(action);
assertThat(mViewModel.getErrorDialogActionLiveData().getValue()).isEqualTo(action);
action = FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH;
mViewModel.onErrorDialogAction(action);
assertThat(mViewModel.getErrorDialogActionLiveData().getValue()).isEqualTo(action);
}
@Test
public void tesBackPressedScenario() {
final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();

View File

@@ -0,0 +1,134 @@
/*
* 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.biometrics2.ui.viewmodel
import android.app.Application
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.biometrics2.ui.viewmodel.FingerprintErrorDialogSetResultAction.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH
import com.android.settings.biometrics2.ui.viewmodel.FingerprintErrorDialogSetResultAction.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class FingerprintEnrollErrorDialogViewModelTest {
private val application = ApplicationProvider.getApplicationContext<Application>()
private var viewModel: FingerprintEnrollErrorDialogViewModel =
FingerprintEnrollErrorDialogViewModel(application, false)
@Before
fun setUp() {
// Make sure viewModel is new for each test
viewModel = FingerprintEnrollErrorDialogViewModel(application, false)
}
@Test
fun testIsDialogNotShownDefaultFalse() {
assertThat(viewModel.isDialogShown).isFalse()
}
@Test
fun testIsSuw() {
assertThat(FingerprintEnrollErrorDialogViewModel(application, false).isSuw).isFalse()
assertThat(FingerprintEnrollErrorDialogViewModel(application, true).isSuw).isTrue()
}
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun testNewDialog() = runTest {
backgroundScope.launch {
mutableListOf<Any>().let { list ->
viewModel.newDialogFlow.toList(list)
assertThat(list.size).isEqualTo(0)
}
mutableListOf<FingerprintErrorDialogSetResultAction>().let { list ->
val testErrorMsgId = 3456
viewModel.newDialog(testErrorMsgId)
assertThat(viewModel.isDialogShown).isTrue()
viewModel.setResultFlow.toList(list)
assertThat(list.size).isEqualTo(1)
assertThat(list[0]).isEqualTo(testErrorMsgId)
}
}
}
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun testTriggerRetry() = runTest {
backgroundScope.launch {
// triggerRetryFlow shall be empty on begin
mutableListOf<Any>().let { list ->
viewModel.triggerRetryFlow.toList(list)
assertThat(list.size).isEqualTo(0)
}
// emit newDialog
mutableListOf<FingerprintErrorDialogSetResultAction>().let { list ->
viewModel.newDialog(0)
viewModel.triggerRetry()
assertThat(viewModel.isDialogShown).isFalse()
viewModel.setResultFlow.toList(list)
assertThat(list.size).isEqualTo(1)
}
}
}
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun testSetResultFinish() = runTest {
backgroundScope.launch {
// setResultFlow shall be empty on begin
mutableListOf<FingerprintErrorDialogSetResultAction>().let { list ->
viewModel.setResultFlow.toList(list)
assertThat(list.size).isEqualTo(0)
}
// emit FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH
viewModel = FingerprintEnrollErrorDialogViewModel(application, false)
mutableListOf<FingerprintErrorDialogSetResultAction>().let { list ->
viewModel.newDialog(0)
viewModel.setResultAndFinish(FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH)
assertThat(viewModel.isDialogShown).isFalse()
viewModel.setResultFlow.toList(list)
assertThat(list.size).isEqualTo(1)
assertThat(list[0]).isEqualTo(FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH)
}
// emit FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT
viewModel = FingerprintEnrollErrorDialogViewModel(application, false)
mutableListOf<FingerprintErrorDialogSetResultAction>().let { list ->
viewModel.newDialog(0)
viewModel.setResultAndFinish(FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT)
assertThat(viewModel.isDialogShown).isFalse()
viewModel.setResultFlow.toList(list)
assertThat(list.size).isEqualTo(1)
assertThat(list[0]).isEqualTo(FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH)
}
}
}
}

View File

@@ -108,9 +108,9 @@ public class FingerprintEnrollProgressViewModelTest {
mViewModel.setToken(token);
// Start enrollment
final boolean ret = mViewModel.startEnrollment(enrollReason);
final Object ret = mViewModel.startEnrollment(enrollReason);
assertThat(ret).isTrue();
assertThat(ret).isNotNull();
verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason));
assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isFalse();
@@ -123,9 +123,9 @@ public class FingerprintEnrollProgressViewModelTest {
mViewModel.setToken(token);
// Start enrollment
final boolean ret = mViewModel.startEnrollment(enrollReason);
final Object ret = mViewModel.startEnrollment(enrollReason);
assertThat(ret).isTrue();
assertThat(ret).isNotNull();
verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason));
assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isFalse();
@@ -142,9 +142,9 @@ public class FingerprintEnrollProgressViewModelTest {
mViewModel.setToken(token);
// Start enrollment
final boolean ret = mViewModel.startEnrollment(enrollReason);
final Object ret = mViewModel.startEnrollment(enrollReason);
assertThat(ret).isTrue();
assertThat(ret).isNotNull();
verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason));
assertThat(mCallbackWrapper.mValue).isNotNull();
@@ -166,9 +166,9 @@ public class FingerprintEnrollProgressViewModelTest {
@Test
public void testStartEnrollmentFailBecauseOfNoToken() {
// Start enrollment
final boolean ret = mViewModel.startEnrollment(ENROLL_FIND_SENSOR);
final Object ret = mViewModel.startEnrollment(ENROLL_FIND_SENSOR);
assertThat(ret).isFalse();
assertThat(ret).isNull();
verify(mFingerprintUpdater, never()).enroll(any(byte[].class),
any(CancellationSignal.class), anyInt(), any(EnrollmentCallback.class), anyInt());
}
@@ -177,8 +177,8 @@ public class FingerprintEnrollProgressViewModelTest {
public void testCancelEnrollment() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isTrue();
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCancellationSignalWrapper.mValue).isNotNull();
// Cancel enrollment
@@ -191,8 +191,8 @@ public class FingerprintEnrollProgressViewModelTest {
public void testProgressUpdate() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isTrue();
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Test default value
@@ -228,8 +228,8 @@ public class FingerprintEnrollProgressViewModelTest {
public void testProgressUpdateClearHelpMessage() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isTrue();
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
final LiveData<EnrollmentProgress> progressLiveData = mViewModel.getProgressLiveData();
final LiveData<EnrollmentStatusMessage> helpMsgLiveData =
@@ -271,8 +271,8 @@ public class FingerprintEnrollProgressViewModelTest {
mViewModel.setToken(new byte[] { 1, 2, 3 });
// Start enrollment
final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isTrue();
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Test default value
@@ -308,8 +308,8 @@ public class FingerprintEnrollProgressViewModelTest {
public void testGetErrorMessageLiveData() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isTrue();
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Check default value
@@ -330,8 +330,8 @@ public class FingerprintEnrollProgressViewModelTest {
public void testGetHelpMessageLiveData() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isTrue();
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Check default value
@@ -352,8 +352,8 @@ public class FingerprintEnrollProgressViewModelTest {
public void testGetAcquireLiveData() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isTrue();
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Check default value
@@ -369,8 +369,8 @@ public class FingerprintEnrollProgressViewModelTest {
public void testGetPointerDownLiveData() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isTrue();
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Check default value
@@ -387,8 +387,8 @@ public class FingerprintEnrollProgressViewModelTest {
public void testGetPointerUpLiveData() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isTrue();
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Check default value