Remove package biometric2 from AOSP settings

Flag: EXEMPT Remove legacy code from AOSP
Bug: 351977012
Test: Build pass
Change-Id: I2285ab8cc2776071c329d7432849aeffc28ed8ee
This commit is contained in:
Vincent Wang
2024-07-09 08:50:11 +00:00
parent 3e393d0a46
commit e9c4adfaf1
61 changed files with 7 additions and 10449 deletions

View File

@@ -1 +0,0 @@
include /src/com/android/settings/biometrics/OWNERS

View File

@@ -1,203 +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.biometrics2.repository;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_HOME_BUTTON;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_ULTRASONIC;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UNKNOWN;
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository;
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints;
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupSuwMaxFingerprintsEnrollable;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.biometrics.SensorProperties;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import java.util.ArrayList;
@RunWith(AndroidJUnit4.class)
public class FingerprintRepositoryTest {
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
@Mock private Resources mResources;
@Mock private FingerprintManager mFingerprintManager;
private Context mContext;
@Before
public void setUp() {
mContext = ApplicationProvider.getApplicationContext();
}
@Test
public void testCanAssumeSensorType_forUnknownSensor() {
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
TYPE_UNKNOWN, 1);
assertThat(repository.canAssumeUdfps()).isFalse();
assertThat(repository.canAssumeSfps()).isFalse();
}
@Test
public void testCanAssumeSensorType_forRearSensor() {
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
TYPE_REAR, 1);
assertThat(repository.canAssumeUdfps()).isFalse();
assertThat(repository.canAssumeSfps()).isFalse();
}
@Test
public void testCanAssumeSensorType_forUdfpsUltrasonicSensor() {
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
TYPE_UDFPS_ULTRASONIC, 1);
assertThat(repository.canAssumeUdfps()).isTrue();
assertThat(repository.canAssumeSfps()).isFalse();
}
@Test
public void testCanAssumeSensorType_forUdfpsOpticalSensor() {
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
TYPE_UDFPS_OPTICAL, 1);
assertThat(repository.canAssumeUdfps()).isTrue();
assertThat(repository.canAssumeSfps()).isFalse();
}
@Test
public void testCanAssumeSensorType_forPowerButtonSensor() {
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
TYPE_POWER_BUTTON, 1);
assertThat(repository.canAssumeUdfps()).isFalse();
assertThat(repository.canAssumeSfps()).isTrue();
}
@Test
public void testCanAssumeSensorType_forHomeButtonSensor() {
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
TYPE_HOME_BUTTON, 1);
assertThat(repository.canAssumeUdfps()).isFalse();
assertThat(repository.canAssumeSfps()).isFalse();
}
@Test
public void testGetMaxFingerprints() {
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
TYPE_UNKNOWN, 999);
assertThat(repository.getMaxFingerprints()).isEqualTo(999);
}
@Test
public void testGetNumOfEnrolledFingerprintsSize() {
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
TYPE_UNKNOWN, 999);
setupFingerprintEnrolledFingerprints(mFingerprintManager, 10, 3);
setupFingerprintEnrolledFingerprints(mFingerprintManager, 22, 99);
assertThat(repository.getNumOfEnrolledFingerprintsSize(10)).isEqualTo(3);
assertThat(repository.getNumOfEnrolledFingerprintsSize(22)).isEqualTo(99);
}
@Test
public void testGetMaxFingerprintsInSuw() {
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
TYPE_UNKNOWN, 999);
setupSuwMaxFingerprintsEnrollable(mContext, mResources, 333);
assertThat(repository.getMaxFingerprintsInSuw(mResources))
.isEqualTo(333);
setupSuwMaxFingerprintsEnrollable(mContext, mResources, 20);
assertThat(repository.getMaxFingerprintsInSuw(mResources)).isEqualTo(20);
}
@Test
public void testGetFirstFingerprintSensorPropertiesInternal() {
final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
final FingerprintSensorPropertiesInternal prop = new FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5,
new ArrayList<>() /* componentInfo */,
TYPE_UDFPS_OPTICAL,
true /* resetLockoutRequiresHardwareAuthToken */);
props.add(prop);
doAnswer(invocation -> {
final IFingerprintAuthenticatorsRegisteredCallback callback =
invocation.getArgument(0);
callback.onAllAuthenticatorsRegistered(props);
return null;
}).when(mFingerprintManager).addAuthenticatorsRegisteredCallback(any());
final FingerprintRepository repository = new FingerprintRepository(mFingerprintManager);
assertThat(repository.getFirstFingerprintSensorPropertiesInternal()).isEqualTo(prop);
}
@Test
public void testGetEnrollStageCount() {
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
TYPE_UNKNOWN, 999);
final int expectedValue = 24;
doReturn(expectedValue).when(mFingerprintManager).getEnrollStageCount();
assertThat(repository.getEnrollStageCount()).isEqualTo(expectedValue);
}
@Test
public void testGetEnrollStageThreshold() {
final FingerprintRepository repository = newFingerprintRepository(mFingerprintManager,
TYPE_UNKNOWN, 999);
final float expectedValue0 = 0.42f;
final float expectedValue1 = 0.24f;
final float expectedValue2 = 0.33f;
final float expectedValue3 = 0.90f;
doReturn(expectedValue0).when(mFingerprintManager).getEnrollStageThreshold(0);
doReturn(expectedValue1).when(mFingerprintManager).getEnrollStageThreshold(1);
doReturn(expectedValue2).when(mFingerprintManager).getEnrollStageThreshold(2);
doReturn(expectedValue3).when(mFingerprintManager).getEnrollStageThreshold(3);
assertThat(repository.getEnrollStageThreshold(2)).isEqualTo(expectedValue2);
assertThat(repository.getEnrollStageThreshold(1)).isEqualTo(expectedValue1);
assertThat(repository.getEnrollStageThreshold(3)).isEqualTo(expectedValue3);
assertThat(repository.getEnrollStageThreshold(0)).isEqualTo(expectedValue0);
}
}

View File

@@ -1,136 +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.biometrics2.ui.model
import android.content.Intent
import android.os.Bundle
import android.os.SystemClock
import android.os.UserHandle
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.biometrics.BiometricEnrollBase
import com.android.settings.password.ChooseLockSettingsHelper
import com.google.common.truth.Truth
import org.junit.Test
import org.junit.runner.RunWith
import java.util.Arrays
@RunWith(AndroidJUnit4::class)
class CredentialModelTest {
private val clock = SystemClock.elapsedRealtimeClock()
@Test
fun testNullBundle() {
val credentialModel = CredentialModel(null, clock)
Truth.assertThat(credentialModel.userId).isEqualTo(UserHandle.myUserId())
}
companion object {
@JvmStatic
fun newCredentialModelIntentExtras(
userId: Int, challenge: Long,
token: ByteArray?, gkPwHandle: Long
): Bundle {
val bundle = Bundle()
bundle.putInt(Intent.EXTRA_USER_ID, userId)
bundle.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge)
bundle.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token)
bundle.putLong(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
return bundle
}
@JvmStatic
fun newValidTokenCredentialIntentExtras(userId: Int): Bundle {
return newCredentialModelIntentExtras(
userId, 1L, byteArrayOf(0, 1, 2),
CredentialModel.INVALID_GK_PW_HANDLE
)
}
@JvmStatic
fun newOnlySensorValidCredentialIntentExtras(userId: Int): Bundle {
return newCredentialModelIntentExtras(
userId, CredentialModel.INVALID_CHALLENGE, null,
CredentialModel.INVALID_GK_PW_HANDLE
)
}
@JvmStatic
fun newGkPwHandleCredentialIntentExtras(userId: Int, gkPwHandle: Long): Bundle {
return newCredentialModelIntentExtras(
userId,
CredentialModel.INVALID_CHALLENGE,
null,
gkPwHandle
)
}
private fun checkBundleLongValue(
bundle1: Bundle, bundle2: Bundle,
key: String
) {
if (!bundle1.containsKey(key)) {
return
}
val value1 = bundle1.getInt(key)
val value2 = bundle2.getInt(key)
Truth.assertWithMessage(
"bundle not match, key:" + key + ", value1:" + value1 + ", value2:"
+ value2
).that(value1).isEqualTo(value2)
}
private fun checkBundleIntValue(
bundle1: Bundle, bundle2: Bundle,
key: String
) {
if (!bundle1.containsKey(key)) {
return
}
val value1 = bundle1.getLong(key)
val value2 = bundle2.getLong(key)
Truth.assertWithMessage(
"bundle not match, key:" + key + ", value1:" + value1 + ", value2:"
+ value2
).that(value1).isEqualTo(value2)
}
private fun checkBundleByteArrayValue(
bundle1: Bundle, bundle2: Bundle,
key: String
) {
if (!bundle1.containsKey(key)) {
return
}
val value1 = bundle1.getByteArray(key)
val value2 = bundle2.getByteArray(key)
val errMsg = ("bundle not match, key:" + key + ", value1:" + Arrays.toString(value1)
+ ", value2:" + Arrays.toString(value2))
if (value1 == null) {
Truth.assertWithMessage(errMsg).that(value2).isNull()
} else {
Truth.assertWithMessage(errMsg).that(value1.size).isEqualTo(
value2!!.size
)
for (i in value1.indices) {
Truth.assertWithMessage(errMsg).that(value1[i]).isEqualTo(
value2[i]
)
}
}
}
}
}

View File

@@ -1,175 +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.biometrics2.ui.model
import android.content.Context
import android.content.Intent
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.biometrics.BiometricEnrollActivity
import com.google.android.setupcompat.util.WizardManagerHelper
import com.google.common.truth.Truth
import org.junit.Test
import org.junit.runner.RunWith
@RunWith(AndroidJUnit4::class)
class EnrollmentRequestTest {
private val context = ApplicationProvider.getApplicationContext<Context>()
@Test
fun testIsSuw() {
// Default false
Truth.assertThat(EnrollmentRequest(Intent(), context, true).isSuw).isFalse()
Truth.assertThat(EnrollmentRequest(Intent(), context, false).isSuw).isFalse()
val trueIntent = Intent()
trueIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true)
Truth.assertThat(EnrollmentRequest(trueIntent, context, true).isSuw).isTrue()
Truth.assertThat(EnrollmentRequest(trueIntent, context, false).isSuw).isFalse()
val falseIntent = Intent()
trueIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, false)
Truth.assertThat(EnrollmentRequest(falseIntent, context, true).isSuw).isFalse()
Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSuw).isFalse()
}
@Test
fun testIsAfterSuwOrSuwSuggestedAction() {
// Default false
Truth.assertThat(
EnrollmentRequest(Intent(), context, true)
.isAfterSuwOrSuwSuggestedAction
).isFalse()
Truth.assertThat(
EnrollmentRequest(Intent(), context, false)
.isAfterSuwOrSuwSuggestedAction
).isFalse()
val deferredTrueIntent = Intent()
deferredTrueIntent.putExtra(WizardManagerHelper.EXTRA_IS_DEFERRED_SETUP, true)
Truth.assertThat(
EnrollmentRequest(deferredTrueIntent, context, true)
.isAfterSuwOrSuwSuggestedAction
).isTrue()
Truth.assertThat(
EnrollmentRequest(deferredTrueIntent, context, false)
.isAfterSuwOrSuwSuggestedAction
).isFalse()
val deferredFalseIntent = Intent()
deferredFalseIntent.putExtra(WizardManagerHelper.EXTRA_IS_DEFERRED_SETUP, false)
Truth.assertThat(
EnrollmentRequest(deferredFalseIntent, context, false)
.isAfterSuwOrSuwSuggestedAction
).isFalse()
Truth.assertThat(
EnrollmentRequest(deferredFalseIntent, context, false)
.isAfterSuwOrSuwSuggestedAction
).isFalse()
val portalTrueIntent = Intent()
portalTrueIntent.putExtra(WizardManagerHelper.EXTRA_IS_PORTAL_SETUP, true)
Truth.assertThat(
EnrollmentRequest(portalTrueIntent, context, true)
.isAfterSuwOrSuwSuggestedAction
).isTrue()
Truth.assertThat(
EnrollmentRequest(portalTrueIntent, context, false)
.isAfterSuwOrSuwSuggestedAction
).isFalse()
val portalFalseIntent = Intent()
portalFalseIntent.putExtra(WizardManagerHelper.EXTRA_IS_PORTAL_SETUP, false)
Truth.assertThat(
EnrollmentRequest(portalFalseIntent, context, false)
.isAfterSuwOrSuwSuggestedAction
).isFalse()
Truth.assertThat(
EnrollmentRequest(portalFalseIntent, context, false)
.isAfterSuwOrSuwSuggestedAction
).isFalse()
val suggestedTrueIntent = Intent()
suggestedTrueIntent.putExtra(WizardManagerHelper.EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW, true)
Truth.assertThat(
EnrollmentRequest(suggestedTrueIntent, context, true)
.isAfterSuwOrSuwSuggestedAction
).isTrue()
Truth.assertThat(
EnrollmentRequest(suggestedTrueIntent, context, false)
.isAfterSuwOrSuwSuggestedAction
).isFalse()
val suggestedFalseIntent = Intent()
suggestedFalseIntent.putExtra(WizardManagerHelper.EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW, false)
Truth.assertThat(
EnrollmentRequest(suggestedFalseIntent, context, false)
.isAfterSuwOrSuwSuggestedAction
).isFalse()
Truth.assertThat(
EnrollmentRequest(suggestedFalseIntent, context, false)
.isAfterSuwOrSuwSuggestedAction
).isFalse()
}
@Test
fun testGetSuwExtras_inSuw() {
val suwIntent = Intent()
suwIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true)
val setupRequest = EnrollmentRequest(suwIntent, context, true)
val bundle = setupRequest.suwExtras
Truth.assertThat(bundle).isNotNull()
Truth.assertThat(bundle.size()).isAtLeast(1)
Truth.assertThat(bundle.getBoolean(WizardManagerHelper.EXTRA_IS_SETUP_FLOW)).isTrue()
}
@Test
fun testGetSuwExtras_notInSuw() {
val suwIntent = Intent()
suwIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true)
val setupRequest = EnrollmentRequest(suwIntent, context, false)
val bundle = setupRequest.suwExtras
Truth.assertThat(bundle).isNotNull()
Truth.assertThat(bundle.size()).isEqualTo(0)
}
@Test
fun testIsSkipIntro() {
// Default false
Truth.assertThat(EnrollmentRequest(Intent(), context, true).isSkipIntro).isFalse()
Truth.assertThat(EnrollmentRequest(Intent(), context, false).isSkipIntro).isFalse()
val trueIntent = Intent()
trueIntent.putExtra(BiometricEnrollActivity.EXTRA_SKIP_INTRO, true)
Truth.assertThat(EnrollmentRequest(trueIntent, context, true).isSkipIntro).isTrue()
Truth.assertThat(EnrollmentRequest(trueIntent, context, false).isSkipIntro).isTrue()
val falseIntent = Intent()
falseIntent.putExtra(BiometricEnrollActivity.EXTRA_SKIP_INTRO, false)
Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSkipIntro).isFalse()
Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSkipIntro).isFalse()
}
@Test
fun testIsSkipFindSensor() {
// Default false
Truth.assertThat(EnrollmentRequest(Intent(), context, true).isSkipFindSensor)
.isFalse()
Truth.assertThat(EnrollmentRequest(Intent(), context, false).isSkipFindSensor)
.isFalse()
val trueIntent = Intent()
trueIntent.putExtra(EnrollmentRequest.EXTRA_SKIP_FIND_SENSOR, true)
Truth.assertThat(EnrollmentRequest(trueIntent, context, true).isSkipFindSensor).isTrue()
Truth.assertThat(EnrollmentRequest(trueIntent, context, false).isSkipFindSensor).isTrue()
val falseIntent = Intent()
falseIntent.putExtra(EnrollmentRequest.EXTRA_SKIP_FIND_SENSOR, false)
Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSkipFindSensor)
.isFalse()
Truth.assertThat(EnrollmentRequest(falseIntent, context, false).isSkipFindSensor)
.isFalse()
}
}

View File

@@ -1,519 +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.biometrics2.ui.viewmodel
import android.app.Activity
import android.app.admin.DevicePolicyManager
import android.content.Intent
import android.os.Bundle
import android.os.SystemClock
import android.os.UserHandle
import androidx.activity.result.ActivityResult
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.internal.widget.LockPatternUtils
import com.android.internal.widget.VerifyCredentialResponse
import com.android.settings.biometrics.BiometricEnrollBase
import com.android.settings.biometrics2.ui.model.CredentialModel
import com.android.settings.biometrics2.ui.model.CredentialModelTest.Companion.newGkPwHandleCredentialIntentExtras
import com.android.settings.biometrics2.ui.model.CredentialModelTest.Companion.newOnlySensorValidCredentialIntentExtras
import com.android.settings.biometrics2.ui.model.CredentialModelTest.Companion.newValidTokenCredentialIntentExtras
import com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.ChallengeGenerator
import com.android.settings.password.ChooseLockPattern
import com.android.settings.password.ChooseLockSettingsHelper
import com.google.common.truth.Truth.assertThat
import java.util.concurrent.atomic.AtomicBoolean
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
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.Mock
import org.mockito.Mockito
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
import org.mockito.Mockito.`when` as whenever
@RunWith(AndroidJUnit4::class)
class AutoCredentialViewModelTest {
@get:Rule val mockito: MockitoRule = MockitoJUnit.rule()
@Mock private lateinit var lockPatternUtils: LockPatternUtils
private var challengeGenerator: TestChallengeGenerator = TestChallengeGenerator()
private lateinit var viewModel: AutoCredentialViewModel
private fun newAutoCredentialViewModel(bundle: Bundle?): AutoCredentialViewModel {
return AutoCredentialViewModel(
ApplicationProvider.getApplicationContext(),
lockPatternUtils,
challengeGenerator,
CredentialModel(bundle, SystemClock.elapsedRealtimeClock())
)
}
@Before
fun setUp() {
challengeGenerator = TestChallengeGenerator()
}
private fun setupGenerateChallenge(userId: Int, newSensorId: Int, newChallenge: Long) {
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
)
challengeGenerator.userId = userId
challengeGenerator.sensorId = newSensorId
challengeGenerator.challenge = newChallenge
}
@Test
fun testCheckCredential_validCredentialCase() = runTest {
val userId = 99
viewModel = newAutoCredentialViewModel(newValidTokenCredentialIntentExtras(userId))
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
)
val generateFails = listOfGenerateChallengeFailedFlow()
// Run credential check
val action = viewModel.checkCredential(backgroundScope)
runCurrent()
// Check viewModel behavior
assertThat(action).isEqualTo(CredentialAction.CREDENTIAL_VALID)
assertThat(generateFails.size).isEqualTo(0)
// Check createGeneratingChallengeExtras()
assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
}
@Test
fun testCheckCredential_needToChooseLock() = runTest {
val userId = 100
viewModel = newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED
)
val generateFails = listOfGenerateChallengeFailedFlow()
// Run credential check
val action = viewModel.checkCredential(backgroundScope)
runCurrent()
// Check viewModel behavior
assertThat(action).isEqualTo(CredentialAction.FAIL_NEED_TO_CHOOSE_LOCK)
assertThat(generateFails.size).isEqualTo(0)
// Check createGeneratingChallengeExtras()
assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
}
@Test
fun testCheckCredential_needToConfirmLockForSomething() = runTest {
val userId = 101
viewModel =
newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
)
val generateFails = listOfGenerateChallengeFailedFlow()
// Run credential check
val action = viewModel.checkCredential(backgroundScope)
runCurrent()
// Check viewModel behavior
assertThat(action).isEqualTo(CredentialAction.FAIL_NEED_TO_CONFIRM_LOCK)
assertThat(generateFails.size).isEqualTo(0)
// Check createGeneratingChallengeExtras()
assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
}
@Test
fun testCheckCredential_needToConfirmLockForNumeric() = runTest {
val userId = 102
viewModel =
newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
DevicePolicyManager.PASSWORD_QUALITY_NUMERIC
)
val generateFails = listOfGenerateChallengeFailedFlow()
// Run credential check
val action = viewModel.checkCredential(backgroundScope)
runCurrent()
// Check viewModel behavior
assertThat(action).isEqualTo(CredentialAction.FAIL_NEED_TO_CONFIRM_LOCK)
assertThat(generateFails.size).isEqualTo(0)
// Check createGeneratingChallengeExtras()
assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
}
@Test
fun testCheckCredential_needToConfirmLockForAlphabetic() = runTest {
val userId = 103
viewModel =
newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
)
val generateFails = listOfGenerateChallengeFailedFlow()
// Run credential check
val action = viewModel.checkCredential(this)
runCurrent()
// Check viewModel behavior
assertThat(action).isEqualTo(CredentialAction.FAIL_NEED_TO_CONFIRM_LOCK)
assertThat(generateFails.size).isEqualTo(0)
// Check createGeneratingChallengeExtras()
assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
}
@Test
fun testCheckCredential_generateChallenge() = runTest {
val userId = 104
val gkPwHandle = 1111L
viewModel =
newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
)
val newSensorId = 10
val newChallenge = 20L
setupGenerateChallenge(userId, newSensorId, newChallenge)
whenever(
lockPatternUtils.verifyGatekeeperPasswordHandle(
gkPwHandle,
newChallenge,
userId
)
)
.thenReturn(newGoodCredential(gkPwHandle, byteArrayOf(1)))
val hasCalledRemoveGkPwHandle = AtomicBoolean()
Mockito.doAnswer {
hasCalledRemoveGkPwHandle.set(true)
null
}.`when`(lockPatternUtils).removeGatekeeperPasswordHandle(gkPwHandle)
val generateFails = listOfGenerateChallengeFailedFlow()
// Run credential check
val action = viewModel.checkCredential(backgroundScope)
runCurrent()
// Check viewModel behavior
assertThat(action).isEqualTo(CredentialAction.IS_GENERATING_CHALLENGE)
assertThat(generateFails.size).isEqualTo(0)
// Check data inside CredentialModel
assertThat(viewModel.token).isNotNull()
assertThat(challengeGenerator.callbackRunCount).isEqualTo(1)
assertThat(hasCalledRemoveGkPwHandle.get()).isFalse()
// Check createGeneratingChallengeExtras()
val generatingChallengeExtras = viewModel.createGeneratingChallengeExtras()
assertThat(generatingChallengeExtras).isNotNull()
assertThat(generatingChallengeExtras!!.getLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE))
.isEqualTo(newChallenge)
val tokens =
generatingChallengeExtras.getByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN)
assertThat(tokens).isNotNull()
assertThat(tokens!!.size).isEqualTo(1)
assertThat(tokens[0]).isEqualTo(1)
}
@Test
fun testCheckCredential_generateChallengeFail() = runTest {
backgroundScope.launch {
val userId = 104
val gkPwHandle = 1111L
viewModel =
newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
)
val newSensorId = 10
val newChallenge = 20L
setupGenerateChallenge(userId, newSensorId, newChallenge)
whenever(
lockPatternUtils.verifyGatekeeperPasswordHandle(
gkPwHandle,
newChallenge,
userId
)
)
.thenReturn(newBadCredential(0))
val generateFails = listOfGenerateChallengeFailedFlow()
// Run credential check
val action = viewModel.checkCredential(this)
runCurrent()
assertThat(action).isEqualTo(CredentialAction.IS_GENERATING_CHALLENGE)
assertThat(generateFails.size).isEqualTo(1)
assertThat(generateFails[0]).isEqualTo(true)
assertThat(challengeGenerator.callbackRunCount).isEqualTo(1)
// Check createGeneratingChallengeExtras()
assertThat(viewModel.createGeneratingChallengeExtras()).isNull()
}
}
@Test
fun testGetUserId_fromIntent() {
val userId = 106
viewModel = newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
// Get userId
assertThat(viewModel.userId).isEqualTo(userId)
}
@Test
fun testGenerateChallengeAsCredentialActivityResult_invalidChooseLock() = runTest {
backgroundScope.launch {
val userId = 107
val gkPwHandle = 3333L
viewModel =
newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
val intent = Intent()
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
val generateFails = listOfGenerateChallengeFailedFlow()
// Run generateChallengeAsCredentialActivityResult()
val ret = viewModel.generateChallengeAsCredentialActivityResult(
true,
ActivityResult(ChooseLockPattern.RESULT_FINISHED + 1, intent),
backgroundScope
)
runCurrent()
assertThat(ret).isFalse()
assertThat(generateFails.size).isEqualTo(0)
}
}
@Test
fun testGenerateChallengeAsCredentialActivityResult_invalidConfirmLock() = runTest {
backgroundScope.launch {
val userId = 107
val gkPwHandle = 3333L
viewModel =
newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
val intent = Intent()
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
val generateFails = listOfGenerateChallengeFailedFlow()
// Run generateChallengeAsCredentialActivityResult()
val ret = viewModel.generateChallengeAsCredentialActivityResult(
false,
ActivityResult(Activity.RESULT_OK + 1, intent),
backgroundScope
)
runCurrent()
assertThat(ret).isFalse()
assertThat(generateFails.size).isEqualTo(0)
}
}
@Test
fun testGenerateChallengeAsCredentialActivityResult_nullDataChooseLock() = runTest {
val userId = 108
val gkPwHandle = 4444L
viewModel =
newAutoCredentialViewModel(newGkPwHandleCredentialIntentExtras(userId, gkPwHandle))
val generateFails = listOfGenerateChallengeFailedFlow()
// Run generateChallengeAsCredentialActivityResult()
val ret = viewModel.generateChallengeAsCredentialActivityResult(
true,
ActivityResult(ChooseLockPattern.RESULT_FINISHED, null),
backgroundScope
)
runCurrent()
assertThat(ret).isFalse()
assertThat(generateFails.size).isEqualTo(0)
}
@Test
fun testGenerateChallengeAsCredentialActivityResult_nullDataConfirmLock() = runTest {
val userId = 109
viewModel =
newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
val generateFails = listOfGenerateChallengeFailedFlow()
// Run generateChallengeAsCredentialActivityResult()
val ret = viewModel.generateChallengeAsCredentialActivityResult(
false,
ActivityResult(Activity.RESULT_OK, null),
backgroundScope
)
runCurrent()
assertThat(ret).isFalse()
assertThat(generateFails.size).isEqualTo(0)
}
@Test
fun testGenerateChallengeAsCredentialActivityResult_validChooseLock() = runTest {
val userId = 108
viewModel =
newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
)
val gkPwHandle = 6666L
val newSensorId = 50
val newChallenge = 60L
setupGenerateChallenge(userId, newSensorId, newChallenge)
whenever(
lockPatternUtils.verifyGatekeeperPasswordHandle(
gkPwHandle,
newChallenge,
userId
)
)
.thenReturn(newGoodCredential(gkPwHandle, byteArrayOf(1)))
val hasCalledRemoveGkPwHandle = AtomicBoolean()
Mockito.doAnswer {
hasCalledRemoveGkPwHandle.set(true)
null
}.`when`(lockPatternUtils).removeGatekeeperPasswordHandle(gkPwHandle)
val generateFails = listOfGenerateChallengeFailedFlow()
// Run generateChallengeAsCredentialActivityResult()
val intent =
Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
val ret = viewModel.generateChallengeAsCredentialActivityResult(
true,
ActivityResult(ChooseLockPattern.RESULT_FINISHED, intent),
backgroundScope
)
runCurrent()
assertThat(ret).isTrue()
assertThat(generateFails.size).isEqualTo(0)
assertThat(viewModel.token).isNotNull()
assertThat(challengeGenerator.callbackRunCount).isEqualTo(1)
assertThat(hasCalledRemoveGkPwHandle.get()).isTrue()
}
@Test
fun testGenerateChallengeAsCredentialActivityResult_validConfirmLock() = runTest {
val userId = 109
viewModel =
newAutoCredentialViewModel(newOnlySensorValidCredentialIntentExtras(userId))
whenever(lockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
DevicePolicyManager.PASSWORD_QUALITY_SOMETHING
)
val gkPwHandle = 5555L
val newSensorId = 80
val newChallenge = 90L
setupGenerateChallenge(userId, newSensorId, newChallenge)
whenever(
lockPatternUtils.verifyGatekeeperPasswordHandle(
gkPwHandle,
newChallenge,
userId
)
)
.thenReturn(newGoodCredential(gkPwHandle, byteArrayOf(1)))
val hasCalledRemoveGkPwHandle = AtomicBoolean()
Mockito.doAnswer {
hasCalledRemoveGkPwHandle.set(true)
null
}.`when`(lockPatternUtils).removeGatekeeperPasswordHandle(gkPwHandle)
val generateFails = listOfGenerateChallengeFailedFlow()
// Run generateChallengeAsCredentialActivityResult()
val intent =
Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle)
val ret = viewModel.generateChallengeAsCredentialActivityResult(
false,
ActivityResult(Activity.RESULT_OK, intent),
backgroundScope
)
runCurrent()
assertThat(ret).isTrue()
assertThat(generateFails.size).isEqualTo(0)
assertThat(viewModel.token).isNotNull()
assertThat(challengeGenerator.callbackRunCount).isEqualTo(1)
assertThat(hasCalledRemoveGkPwHandle.get()).isTrue()
}
private fun TestScope.listOfGenerateChallengeFailedFlow(): List<Boolean> =
mutableListOf<Boolean>().also {
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
viewModel.generateChallengeFailedFlow.toList(it)
}
}
class TestChallengeGenerator : ChallengeGenerator {
var sensorId = -1
var userId = UserHandle.myUserId()
var challenge = CredentialModel.INVALID_CHALLENGE
var callbackRunCount = 0
override var callback: AutoCredentialViewModel.GenerateChallengeCallback? = null
override fun generateChallenge(userId: Int) {
callback?.let {
it.onChallengeGenerated(sensorId, this.userId, challenge)
++callbackRunCount
}
}
}
private fun newGoodCredential(gkPwHandle: Long, hat: ByteArray): VerifyCredentialResponse {
return VerifyCredentialResponse.Builder()
.setGatekeeperPasswordHandle(gkPwHandle)
.setGatekeeperHAT(hat)
.build()
}
private fun newBadCredential(timeout: Int): VerifyCredentialResponse {
return if (timeout > 0) {
VerifyCredentialResponse.fromTimeout(timeout)
} else {
VerifyCredentialResponse.fromError()
}
}
}

View File

@@ -1,61 +0,0 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.biometrics2.ui.viewmodel;
import static com.google.common.truth.Truth.assertThat;
import android.app.Application;
import android.content.res.Configuration;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.testutils.InstantTaskExecutorRule;
import com.android.systemui.unfold.compat.ScreenSizeFoldProvider;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class DeviceFoldedViewModelTest {
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
private DeviceFoldedViewModel mViewModel;
@Before
public void setUp() {
final Application application = ApplicationProvider.getApplicationContext();
mViewModel = new DeviceFoldedViewModel(new ScreenSizeFoldProvider(application),
application.getMainExecutor());
}
@Test
public void testLiveData() {
final Configuration config1 = new Configuration();
config1.smallestScreenWidthDp = 601;
mViewModel.onConfigurationChanged(config1);
assertThat(mViewModel.getLiveData().getValue()).isFalse();
final Configuration config2 = new Configuration();
config2.smallestScreenWidthDp = 599;
mViewModel.onConfigurationChanged(config2);
assertThat(mViewModel.getLiveData().getValue()).isTrue();
}
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.biometrics2.ui.viewmodel;
import static com.google.common.truth.Truth.assertThat;
import android.app.Application;
import android.view.Surface;
import androidx.annotation.NonNull;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.testutils.InstantTaskExecutorRule;
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.MockitoRule;
@RunWith(AndroidJUnit4.class)
public class DeviceRotationViewModelTest {
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
private TestDeviceRotationViewModel mViewModel;
@Before
public void setUp() {
TestDeviceRotationViewModel.sTestRotation = 3;
mViewModel = new TestDeviceRotationViewModel(ApplicationProvider.getApplicationContext());
}
@Test
public void testDefaultLiveDataNotNull() {
assertThat(mViewModel.getLiveData().getValue()).isEqualTo(mViewModel.sTestRotation);
}
@Test
public void testOnDisplayChange() {
mViewModel.sTestRotation = 3;
mViewModel.triggerOnDisplayChanged();
assertThat(mViewModel.getLiveData().getValue()).isEqualTo(mViewModel.sTestRotation);
}
public static class TestDeviceRotationViewModel extends DeviceRotationViewModel {
@Surface.Rotation static int sTestRotation = 0;
public TestDeviceRotationViewModel(@NonNull Application application) {
super(application);
}
void triggerOnDisplayChanged() {
mDisplayListener.onDisplayChanged(0);
}
@Override
protected int getRotation() {
return sTestRotation;
}
}
}

View File

@@ -1,173 +0,0 @@
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.biometrics2.ui.viewmodel;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
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.utils.FingerprintRepositoryUtils.newFingerprintRepository;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
import android.app.Application;
import android.hardware.biometrics.SensorProperties;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import androidx.lifecycle.LiveData;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
import com.android.settings.testutils.InstantTaskExecutorRule;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import java.util.ArrayList;
@RunWith(AndroidJUnit4.class)
public class FingerprintEnrollEnrollingViewModelTest {
private static final int TEST_USER_ID = 33;
@Rule
public final MockitoRule mockito = MockitoJUnit.rule();
@Rule
public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
@Mock
private FingerprintManager mFingerprintManager;
private Application mApplication;
private FingerprintEnrollEnrollingViewModel mViewModel;
@Before
public void setUp() {
mApplication = ApplicationProvider.getApplicationContext();
mViewModel = new FingerprintEnrollEnrollingViewModel(
mApplication,
TEST_USER_ID,
newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL, 5)
);
}
@Test
public void testIconTouchDialog() {
final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
assertThat(actionLiveData.getValue()).isEqualTo(null);
mViewModel.showIconTouchDialog();
assertThat(actionLiveData.getValue()).isEqualTo(
FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG);
}
@Test
public void tesBackPressedScenario() {
final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
assertThat(actionLiveData.getValue()).isEqualTo(null);
assertThat(mViewModel.getOnBackPressed()).isEqualTo(false);
mViewModel.setOnBackPressed();
assertThat(mViewModel.getOnBackPressed()).isEqualTo(true);
mViewModel.onCancelledDueToOnBackPressed();
assertThat(mViewModel.getOnBackPressed()).isEqualTo(false);
assertThat(actionLiveData.getValue()).isEqualTo(
FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED);
}
@Test
public void testSkipPressedScenario() {
final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
assertThat(actionLiveData.getValue()).isEqualTo(null);
assertThat(mViewModel.getOnSkipPressed()).isEqualTo(false);
mViewModel.setOnSkipPressed();
assertThat(mViewModel.getOnSkipPressed()).isEqualTo(true);
mViewModel.onCancelledDueToOnSkipPressed();
assertThat(mViewModel.getOnSkipPressed()).isEqualTo(false);
assertThat(actionLiveData.getValue()).isEqualTo(
FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_USER_SKIP);
}
@Test
public void testGetFirstFingerprintSensorPropertiesInternal() {
final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
final FingerprintSensorPropertiesInternal prop = new FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
5,
new ArrayList<>() /* componentInfo */,
TYPE_UDFPS_OPTICAL,
true /* resetLockoutRequiresHardwareAuthToken */);
props.add(prop);
doAnswer(invocation -> {
final IFingerprintAuthenticatorsRegisteredCallback callback =
invocation.getArgument(0);
callback.onAllAuthenticatorsRegistered(props);
return null;
}).when(mFingerprintManager).addAuthenticatorsRegisteredCallback(any());
mViewModel = new FingerprintEnrollEnrollingViewModel(
mApplication,
TEST_USER_ID,
new FingerprintRepository(mFingerprintManager)
);
assertThat(mViewModel.getFirstFingerprintSensorPropertiesInternal()).isEqualTo(prop);
}
@Test
public void testGetEnrollStageCount() {
final int expectedValue = 24;
doReturn(expectedValue).when(mFingerprintManager).getEnrollStageCount();
assertThat(mViewModel.getEnrollStageCount()).isEqualTo(expectedValue);
}
@Test
public void testGetEnrollStageThreshold() {
final float expectedValue0 = 0.42f;
final float expectedValue1 = 0.24f;
final float expectedValue2 = 0.33f;
final float expectedValue3 = 0.90f;
doReturn(expectedValue0).when(mFingerprintManager).getEnrollStageThreshold(0);
doReturn(expectedValue1).when(mFingerprintManager).getEnrollStageThreshold(1);
doReturn(expectedValue2).when(mFingerprintManager).getEnrollStageThreshold(2);
doReturn(expectedValue3).when(mFingerprintManager).getEnrollStageThreshold(3);
assertThat(mViewModel.getEnrollStageThreshold(2)).isEqualTo(expectedValue2);
assertThat(mViewModel.getEnrollStageThreshold(1)).isEqualTo(expectedValue1);
assertThat(mViewModel.getEnrollStageThreshold(3)).isEqualTo(expectedValue3);
assertThat(mViewModel.getEnrollStageThreshold(0)).isEqualTo(expectedValue0);
}
}

View File

@@ -1,121 +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.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.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher
import kotlinx.coroutines.test.runCurrent
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()
}
@Test
fun testNewDialog() = runTest {
val newDialogs: List<Int> = mutableListOf<Int>().also {
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
viewModel.newDialogFlow.toList(it)
}
}
runCurrent()
// Default values
assertThat(viewModel.isDialogShown).isFalse()
assertThat(newDialogs.size).isEqualTo(0)
val testErrorMsgId = 3456
viewModel.newDialog(testErrorMsgId)
runCurrent()
// verify after emit
assertThat(viewModel.isDialogShown).isTrue()
assertThat(newDialogs.size).isEqualTo(1)
assertThat(newDialogs[0]).isEqualTo(testErrorMsgId)
}
@Test
fun testTriggerRetry() = runTest {
val triggerRetries: List<Any> = mutableListOf<Any>().also {
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
viewModel.triggerRetryFlow.toList(it)
}
}
runCurrent()
// Default values
assertThat(triggerRetries.size).isEqualTo(0)
viewModel.triggerRetry()
runCurrent()
// verify after emit
assertThat(triggerRetries.size).isEqualTo(1)
}
@Test
fun testSetResultFinish() = runTest {
val setResults: List<FingerprintErrorDialogSetResultAction> =
mutableListOf<FingerprintErrorDialogSetResultAction>().also {
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
viewModel.setResultFlow.toList(it)
}
}
runCurrent()
// Default values
assertThat(setResults.size).isEqualTo(0)
viewModel.setResultAndFinish(FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH)
runCurrent()
// verify after emit
assertThat(setResults.size).isEqualTo(1)
assertThat(setResults[0]).isEqualTo(FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH)
}
}

View File

@@ -1,91 +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.biometrics2.ui.viewmodel;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFindSensorViewModel.FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START;
import static com.google.common.truth.Truth.assertThat;
import android.app.Application;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.testutils.InstantTaskExecutorRule;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class FingerprintEnrollFindSensorViewModelTest {
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
private Application mApplication;
private FingerprintEnrollFindSensorViewModel mViewModel;
@Before
public void setUp() {
mApplication = ApplicationProvider.getApplicationContext();
mViewModel = new FingerprintEnrollFindSensorViewModel(mApplication, false);
}
@Test
public void testClickSkipButtonNotInSuw() {
mViewModel = new FingerprintEnrollFindSensorViewModel(mApplication, false);
mViewModel.onSkipButtonClick();
assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP);
}
@Test
public void testClickSkipButtonInSuw() {
mViewModel = new FingerprintEnrollFindSensorViewModel(mApplication, true);
mViewModel.onSkipButtonClick();
assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG);
}
@Test
public void testClickSkipDialogButton() {
mViewModel.onSkipDialogButtonClick();
assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP);
}
@Test
public void testClickStartDialogButton() {
mViewModel.onStartButtonClick();
assertThat(mViewModel.getActionLiveData().getValue()).isEqualTo(
FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_START);
}
@Test
public void testClearActionLiveData() {
assertThat(mViewModel.getActionLiveData().getValue()).isNull();
mViewModel.onStartButtonClick();
assertThat(mViewModel.getActionLiveData().getValue()).isNotNull();
mViewModel.clearActionLiveData();
assertThat(mViewModel.getActionLiveData().getValue()).isNull();
}
}

View File

@@ -1,134 +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.biometrics2.ui.viewmodel;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_REAR;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel.FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollFinishViewModel.FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK;
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository;
import static com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints;
import static com.google.common.truth.Truth.assertThat;
import android.app.Application;
import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
import androidx.lifecycle.LiveData;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.biometrics2.ui.model.EnrollmentRequest;
import com.android.settings.testutils.InstantTaskExecutorRule;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@RunWith(AndroidJUnit4.class)
public class FingerprintEnrollFinishViewModelTest {
private static final int USER_ID = 334;
private static final int MAX_ENROLLABLE = 5;
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
@Mock private FingerprintManager mFingerprintManager;
private Application mApplication;
private EnrollmentRequest mRequest;
private FingerprintEnrollFinishViewModel mViewModel;
@Before
public void setUp() {
mApplication = ApplicationProvider.getApplicationContext();
mRequest = new EnrollmentRequest(new Intent(), mApplication, true);
mViewModel = new FingerprintEnrollFinishViewModel(mApplication, USER_ID, mRequest,
newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL, MAX_ENROLLABLE));
}
@Test
public void testCanAssumeSfps() {
mViewModel = new FingerprintEnrollFinishViewModel(mApplication, USER_ID, mRequest,
newFingerprintRepository(mFingerprintManager, TYPE_UDFPS_OPTICAL, MAX_ENROLLABLE));
assertThat(mViewModel.canAssumeSfps()).isFalse();
mViewModel = new FingerprintEnrollFinishViewModel(mApplication, USER_ID, mRequest,
newFingerprintRepository(mFingerprintManager, TYPE_REAR, MAX_ENROLLABLE));
assertThat(mViewModel.canAssumeSfps()).isFalse();
mViewModel = new FingerprintEnrollFinishViewModel(mApplication, USER_ID, mRequest,
newFingerprintRepository(mFingerprintManager, TYPE_POWER_BUTTON, MAX_ENROLLABLE));
assertThat(mViewModel.canAssumeSfps()).isTrue();
}
@Test
public void testIsAnotherFingerprintEnrollable() {
setupFingerprintEnrolledFingerprints(mFingerprintManager, USER_ID, MAX_ENROLLABLE);
assertThat(mViewModel.isAnotherFingerprintEnrollable()).isFalse();
setupFingerprintEnrolledFingerprints(mFingerprintManager, USER_ID, MAX_ENROLLABLE - 1);
assertThat(mViewModel.isAnotherFingerprintEnrollable()).isTrue();
}
@Test
public void testGetRequest() {
assertThat(mViewModel.getRequest()).isEqualTo(mRequest);
}
@Test
public void testOnAddButtonClick() {
final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
// Test init value
assertThat(actionLiveData.getValue()).isNull();
// Test onAddButtonClick()
mViewModel.onAddButtonClick();
assertThat(actionLiveData.getValue()).isEqualTo(
FINGERPRINT_ENROLL_FINISH_ACTION_ADD_BUTTON_CLICK);
// Clear
mViewModel.clearActionLiveData();
assertThat(actionLiveData.getValue()).isNull();
}
@Test
public void testOnNextButtonClick() {
final LiveData<Integer> actionLiveData = mViewModel.getActionLiveData();
// Test init value
assertThat(actionLiveData.getValue()).isNull();
// Test onNextButtonClick()
mViewModel.onNextButtonClick();
assertThat(actionLiveData.getValue()).isEqualTo(
FINGERPRINT_ENROLL_FINISH_ACTION_NEXT_BUTTON_CLICK);
// Clear
mViewModel.clearActionLiveData();
assertThat(actionLiveData.getValue()).isNull();
}
}

View File

@@ -1,357 +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.biometrics2.ui.viewmodel
import android.app.Application
import android.content.res.Resources
import android.hardware.fingerprint.FingerprintManager
import android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.biometrics2.data.repository.FingerprintRepository
import com.android.settings.biometrics2.ui.model.EnrollmentRequest
import com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus
import com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
import com.android.settings.biometrics2.ui.model.FingerprintEnrollable.FINGERPRINT_ENROLLABLE_OK
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction.CONTINUE_ENROLL
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction.DONE_AND_FINISH
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroAction.SKIP_OR_CANCEL
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newAllFalseRequest
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwDeferredRequest
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwPortalRequest
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwRequest
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwSuggestedActionFlowRequest
import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository
import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints
import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupSuwMaxFingerprintsEnrollable
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
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.Mock
import org.mockito.Mockito
import org.mockito.junit.MockitoJUnit
@RunWith(AndroidJUnit4::class)
class FingerprintEnrollIntroViewModelTest {
@get:Rule val mockito = MockitoJUnit.rule()
@Mock private lateinit var resources: Resources
@Mock private lateinit var fingerprintManager: FingerprintManager
private var application: Application = ApplicationProvider.getApplicationContext()
private fun newFingerprintEnrollIntroViewModel(
fingerprintRepository: FingerprintRepository,
enrollmentRequest: EnrollmentRequest
) = FingerprintEnrollIntroViewModel(
application,
fingerprintRepository,
enrollmentRequest,
TEST_USER_ID
)
@Before
fun setUp() {
application = ApplicationProvider.getApplicationContext()
}
@Test
fun testPageStatusFlowDefaultAndUpdate() = runTest {
val viewModel = newFingerprintEnrollIntroViewModel(
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 1),
newAllFalseRequest(application)
)
val statusList = listOfPageStatusFlow(viewModel)
runCurrent()
// assert default values
assertThat(statusList.size).isEqualTo(1)
assertThat(statusList[0].hasScrollToBottom()).isFalse()
assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_OK)
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 1)
viewModel.updateEnrollableStatus(backgroundScope)
runCurrent()
// assert new updated value
assertThat(statusList.size).isEqualTo(2)
assertThat(statusList[1].hasScrollToBottom()).isFalse()
assertThat(statusList[1].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
}
fun testOnStartToUpdateEnrollableStatusOk_isSuw() = runTest {
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 0)
setupSuwMaxFingerprintsEnrollable(application, resources, 1)
val viewModel = newFingerprintEnrollIntroViewModel(
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
newIsSuwRequest(application)
)
val statusList = listOfPageStatusFlow(viewModel)
runCurrent()
assertThat(statusList.size).isEqualTo(1)
assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_OK)
}
@Test
fun testOnStartToUpdateEnrollableStatusReachMax_isSuw() = runTest {
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 1)
setupSuwMaxFingerprintsEnrollable(application, resources, 1)
val viewModel = newFingerprintEnrollIntroViewModel(
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
newIsSuwRequest(application)
)
val statusList = listOfPageStatusFlow(viewModel)
runCurrent()
assertThat(statusList.size).isEqualTo(1)
assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
}
@Test
fun testOnStartToUpdateEnrollableStatusOk_isNotSuw() = runTest {
testOnStartToUpdateEnrollableStatusOk(newAllFalseRequest(application))
}
@Test
fun testOnStartToUpdateEnrollableStatusReachMax_isNotSuw() = runTest {
testOnStartToUpdateEnrollableStatusReachMax(newAllFalseRequest(application))
}
@Test
fun testOnStartToUpdateEnrollableStatusOk_isSuwDeferred() = runTest {
testOnStartToUpdateEnrollableStatusOk(newIsSuwDeferredRequest(application))
}
@Test
fun testOnStartToUpdateEnrollableStatusReachMax_isSuwDeferred() = runTest {
testOnStartToUpdateEnrollableStatusReachMax(newIsSuwDeferredRequest(application))
}
@Test
fun testOnStartToUpdateEnrollableStatusOk_isSuwPortal() = runTest {
testOnStartToUpdateEnrollableStatusOk(newIsSuwPortalRequest(application))
}
@Test
fun testOnStartToUpdateEnrollableStatusReachMax_isSuwPortal() = runTest {
testOnStartToUpdateEnrollableStatusReachMax(newIsSuwPortalRequest(application))
}
@Test
fun testOnStartToUpdateEnrollableStatusOk_isSuwSuggestedActionFlow() = runTest {
testOnStartToUpdateEnrollableStatusOk(newIsSuwSuggestedActionFlowRequest(application))
}
@Test
fun testOnStartToUpdateEnrollableStatusReachMax_isSuwSuggestedActionFlow() = runTest {
testOnStartToUpdateEnrollableStatusReachMax(
newIsSuwSuggestedActionFlowRequest(application)
)
}
private fun TestScope.testOnStartToUpdateEnrollableStatusOk(request: EnrollmentRequest) {
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 0)
val viewModel = newFingerprintEnrollIntroViewModel(
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
request
)
val statusList = listOfPageStatusFlow(viewModel)
runCurrent()
assertThat(statusList.size).isEqualTo(1)
assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_OK)
}
private fun TestScope.testOnStartToUpdateEnrollableStatusReachMax(request: EnrollmentRequest) {
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 5)
val viewModel = newFingerprintEnrollIntroViewModel(
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
request
)
val statusList = listOfPageStatusFlow(viewModel)
runCurrent()
assertThat(statusList.size).isEqualTo(1)
assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
}
@Test
fun testIsParentalConsentRequired() {
// We shall not mock FingerprintRepository, but
// FingerprintRepository.isParentalConsentRequired() calls static method inside, we can't
// mock static method
val fingerprintRepository = Mockito.mock(
FingerprintRepository::class.java
)
val viewModel = FingerprintEnrollIntroViewModel(
application,
fingerprintRepository,
newAllFalseRequest(application),
TEST_USER_ID
)
Mockito.`when`(
fingerprintRepository.isParentalConsentRequired(application)
).thenReturn(true)
assertThat(viewModel.isParentalConsentRequired).isEqualTo(true)
Mockito.`when`(
fingerprintRepository.isParentalConsentRequired(application)
).thenReturn(false)
assertThat(viewModel.isParentalConsentRequired).isEqualTo(false)
}
@Test
fun testIsBiometricUnlockDisabledByAdmin() {
// We shall not mock FingerprintRepository, but
// FingerprintRepository.isDisabledByAdmin() calls static method inside, we can't mock
// static method
val fingerprintRepository = Mockito.mock(FingerprintRepository::class.java)
val viewModel = FingerprintEnrollIntroViewModel(
application,
fingerprintRepository,
newAllFalseRequest(application),
TEST_USER_ID
)
Mockito.`when`(
fingerprintRepository.isDisabledByAdmin(application, TEST_USER_ID)
).thenReturn(true)
assertThat(viewModel.isBiometricUnlockDisabledByAdmin).isEqualTo(true)
Mockito.`when`(
fingerprintRepository.isDisabledByAdmin(application, TEST_USER_ID)
).thenReturn(false)
assertThat(viewModel.isBiometricUnlockDisabledByAdmin).isEqualTo(false)
}
@Test
fun testSetHasScrolledToBottom() = runTest {
val viewModel = newFingerprintEnrollIntroViewModel(
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
newAllFalseRequest(application)
)
val pageStatusList = listOfPageStatusFlow(viewModel)
viewModel.setHasScrolledToBottom(true, backgroundScope)
runCurrent()
assertThat(pageStatusList[pageStatusList.size-1].hasScrollToBottom()).isEqualTo(true)
}
@Test
fun testOnNextButtonClick_enrollNext() = runTest {
// Set latest status to FINGERPRINT_ENROLLABLE_OK
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 0)
setupSuwMaxFingerprintsEnrollable(application, resources, 1)
val viewModel = newFingerprintEnrollIntroViewModel(
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
newIsSuwRequest(application)
)
val actions = listOfActionFlow(viewModel)
// Perform click on `next`
viewModel.onNextButtonClick(backgroundScope)
runCurrent()
assertThat(actions.size).isEqualTo(1)
assertThat(actions[0]).isEqualTo(CONTINUE_ENROLL)
}
@Test
fun testOnNextButtonClick_doneAndFinish() = runTest {
// Set latest status to FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
setupFingerprintEnrolledFingerprints(fingerprintManager, TEST_USER_ID, 1)
setupSuwMaxFingerprintsEnrollable(application, resources, 1)
val viewModel = newFingerprintEnrollIntroViewModel(
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
newIsSuwRequest(application)
)
val statusList = listOfPageStatusFlow(viewModel)
val actionList = listOfActionFlow(viewModel)
runCurrent()
assertThat(statusList.size).isEqualTo(1)
assertThat(statusList[0].enrollableStatus).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX)
val actions = listOfActionFlow(viewModel)
// Perform click on `next`
viewModel.onNextButtonClick(backgroundScope)
runCurrent()
assertThat(actionList.size).isEqualTo(1)
assertThat(actionList[0]).isEqualTo(DONE_AND_FINISH)
}
@Test
fun testOnSkipOrCancelButtonClick() = runTest {
val viewModel = newFingerprintEnrollIntroViewModel(
newFingerprintRepository(fingerprintManager, TYPE_UDFPS_OPTICAL, 5),
newAllFalseRequest(application)
)
val actions = listOfActionFlow(viewModel)
viewModel.onSkipOrCancelButtonClick(backgroundScope)
runCurrent()
assertThat(actions.size).isEqualTo(1)
assertThat(actions[0]).isEqualTo(SKIP_OR_CANCEL)
}
private fun TestScope.listOfActionFlow(
viewModel: FingerprintEnrollIntroViewModel
): List<FingerprintEnrollIntroAction> =
mutableListOf<FingerprintEnrollIntroAction>().also {
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
viewModel.actionFlow.toList(it)
}
}
private fun TestScope.listOfPageStatusFlow(
viewModel: FingerprintEnrollIntroViewModel
): List<FingerprintEnrollIntroStatus> =
mutableListOf<FingerprintEnrollIntroStatus>().also {
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
viewModel.pageStatusFlow.toList(it)
}
}
companion object {
private const val TEST_USER_ID = 33
}
}

View File

@@ -1,421 +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.biometrics2.ui.viewmodel;
import static android.hardware.fingerprint.FingerprintManager.ENROLL_ENROLL;
import static android.hardware.fingerprint.FingerprintManager.ENROLL_FIND_SENSOR;
import static android.hardware.fingerprint.FingerprintManager.EnrollReason;
import static android.hardware.fingerprint.FingerprintManager.EnrollmentCallback;
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.only;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Application;
import android.content.res.Resources;
import android.os.CancellationSignal;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import androidx.annotation.NonNull;
import androidx.lifecycle.LiveData;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.biometrics.fingerprint.FingerprintUpdater;
import com.android.settings.biometrics.fingerprint.MessageDisplayController;
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
import com.android.settings.testutils.InstantTaskExecutorRule;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
@RunWith(AndroidJUnit4.class)
public class FingerprintEnrollProgressViewModelTest {
private static final int TEST_USER_ID = 334;
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
@Mock private Application mApplication;
@Mock private Resources mResources;
@Mock private FingerprintUpdater mFingerprintUpdater;
private FingerprintEnrollProgressViewModel mViewModel;
private final TestWrapper<CancellationSignal> mCancellationSignalWrapper = new TestWrapper<>();
private final TestWrapper<EnrollmentCallback> mCallbackWrapper = new TestWrapper<>();
private int mEnrollmentMessageDisplayControllerFlagResId;
@Before
public void setUp() {
mEnrollmentMessageDisplayControllerFlagResId = ApplicationProvider.getApplicationContext()
.getResources().getIdentifier("enrollment_message_display_controller_flag", "bool",
SETTINGS_PACKAGE_NAME);
when(mApplication.getResources()).thenReturn(mResources);
// Not use MessageDisplayController by default
when(mResources.getBoolean(mEnrollmentMessageDisplayControllerFlagResId)).thenReturn(false);
mViewModel = new FingerprintEnrollProgressViewModel(mApplication, mFingerprintUpdater,
TEST_USER_ID);
mCancellationSignalWrapper.mValue = null;
mCallbackWrapper.mValue = null;
doAnswer(invocation -> {
mCancellationSignalWrapper.mValue = invocation.getArgument(1);
mCallbackWrapper.mValue = invocation.getArgument(3);
return null;
}).when(mFingerprintUpdater).enroll(any(byte[].class), any(CancellationSignal.class),
eq(TEST_USER_ID), any(EnrollmentCallback.class), anyInt(), any());
}
@Test
public void testStartFindSensor() {
@EnrollReason final int enrollReason = ENROLL_FIND_SENSOR;
final byte[] token = new byte[] { 1, 2, 3 };
mViewModel.setToken(token);
// Start enrollment
final Object ret = mViewModel.startEnrollment(enrollReason);
assertThat(ret).isNotNull();
verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason), any());
assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isFalse();
}
@Test
public void testStartEnrolling() {
@EnrollReason final int enrollReason = ENROLL_ENROLL;
final byte[] token = new byte[] { 1, 2, 3 };
mViewModel.setToken(token);
// Start enrollment
final Object ret = mViewModel.startEnrollment(enrollReason);
assertThat(ret).isNotNull();
verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
eq(TEST_USER_ID), any(EnrollmentCallback.class), eq(enrollReason), any());
assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isFalse();
}
@Test
public void testStartEnrollingWithMessageDisplayController() {
// Enable MessageDisplayController and mock handler for it
when(mResources.getBoolean(mEnrollmentMessageDisplayControllerFlagResId)).thenReturn(true);
when(mApplication.getMainThreadHandler()).thenReturn(new TestHandler());
@EnrollReason final int enrollReason = ENROLL_ENROLL;
final byte[] token = new byte[] { 1, 2, 3 };
mViewModel.setToken(token);
// Start enrollment
final Object ret = mViewModel.startEnrollment(enrollReason);
assertThat(ret).isNotNull();
verify(mFingerprintUpdater, only()).enroll(eq(token), any(CancellationSignal.class),
eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason), any());
assertThat(mCallbackWrapper.mValue).isNotNull();
assertThat(mCallbackWrapper.mValue instanceof MessageDisplayController).isTrue();
final EnrollmentCallback callback1 = mCallbackWrapper.mValue;
// Cancel and start again
mViewModel.cancelEnrollment();
mViewModel.startEnrollment(enrollReason);
// Shall not use the same MessageDisplayController
verify(mFingerprintUpdater, times(2)).enroll(eq(token), any(CancellationSignal.class),
eq(TEST_USER_ID), any(MessageDisplayController.class), eq(enrollReason), any());
assertThat(mCallbackWrapper.mValue).isNotNull();
assertThat(callback1).isNotEqualTo(mCallbackWrapper.mValue);
}
@Test
public void testStartEnrollmentFailBecauseOfNoToken() {
// Start enrollment
final Object ret = mViewModel.startEnrollment(ENROLL_FIND_SENSOR);
assertThat(ret).isNull();
verify(mFingerprintUpdater, never()).enroll(any(byte[].class),
any(CancellationSignal.class), anyInt(), any(EnrollmentCallback.class), anyInt(),
any());
}
@Test
public void testCancelEnrollment() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCancellationSignalWrapper.mValue).isNotNull();
// Cancel enrollment
mViewModel.cancelEnrollment();
assertThat(mCancellationSignalWrapper.mValue.isCanceled()).isTrue();
}
@Test
public void testProgressUpdate() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Test default value
final LiveData<EnrollmentProgress> progressLiveData = mViewModel.getProgressLiveData();
EnrollmentProgress progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(-1);
assertThat(progress.getRemaining()).isEqualTo(0);
// Update first progress
mCallbackWrapper.mValue.onEnrollmentProgress(25);
progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(25);
assertThat(progress.getRemaining()).isEqualTo(25);
// Update second progress
mCallbackWrapper.mValue.onEnrollmentProgress(20);
progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(25);
assertThat(progress.getRemaining()).isEqualTo(20);
// Update latest progress
mCallbackWrapper.mValue.onEnrollmentProgress(0);
progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(25);
assertThat(progress.getRemaining()).isEqualTo(0);
}
@Test
public void testProgressUpdateClearHelpMessage() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
final LiveData<EnrollmentProgress> progressLiveData = mViewModel.getProgressLiveData();
final LiveData<EnrollmentStatusMessage> helpMsgLiveData =
mViewModel.getHelpMessageLiveData();
// Update first progress
mCallbackWrapper.mValue.onEnrollmentProgress(25);
EnrollmentProgress progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(25);
assertThat(progress.getRemaining()).isEqualTo(25);
// Update help message
final int testHelpMsgId = 3;
final String testHelpString = "Test Help String";
mCallbackWrapper.mValue.onEnrollmentHelp(testHelpMsgId, testHelpString);
final EnrollmentStatusMessage helpMsg = helpMsgLiveData.getValue();
assertThat(helpMsg).isNotNull();
assertThat(helpMsg.getMsgId()).isEqualTo(testHelpMsgId);
assertThat(helpMsg.getStr().toString()).isEqualTo(testHelpString);
// Update second progress
mCallbackWrapper.mValue.onEnrollmentProgress(20);
progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(25);
assertThat(progress.getRemaining()).isEqualTo(20);
// Help message shall be set to null
assertThat(helpMsgLiveData.getValue()).isNull();
}
@Test
public void testProgressUpdateWithMessageDisplayController() {
// Enable MessageDisplayController and mock handler for it
when(mResources.getBoolean(mEnrollmentMessageDisplayControllerFlagResId)).thenReturn(true);
when(mApplication.getMainThreadHandler()).thenReturn(new TestHandler());
mViewModel.setToken(new byte[] { 1, 2, 3 });
// Start enrollment
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Test default value
final LiveData<EnrollmentProgress> progressLiveData = mViewModel.getProgressLiveData();
EnrollmentProgress progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(-1);
assertThat(progress.getRemaining()).isEqualTo(0);
// Update first progress
mCallbackWrapper.mValue.onEnrollmentProgress(25);
progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(25);
assertThat(progress.getRemaining()).isEqualTo(25);
// Update second progress
mCallbackWrapper.mValue.onEnrollmentProgress(20);
progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(25);
assertThat(progress.getRemaining()).isEqualTo(20);
// Update latest progress
mCallbackWrapper.mValue.onEnrollmentProgress(0);
progress = progressLiveData.getValue();
assertThat(progress).isNotNull();
assertThat(progress.getSteps()).isEqualTo(25);
assertThat(progress.getRemaining()).isEqualTo(0);
}
@Test
public void testGetErrorMessageLiveData() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Check default value
final LiveData<EnrollmentStatusMessage> liveData = mViewModel.getErrorMessageLiveData();
assertThat(liveData.getValue()).isNull();
// Notify error message
final int errMsgId = 3;
final String errMsg = "test error message";
mCallbackWrapper.mValue.onEnrollmentError(errMsgId, errMsg);
final EnrollmentStatusMessage value = liveData.getValue();
assertThat(value).isNotNull();
assertThat(value.getMsgId()).isEqualTo(errMsgId);
assertThat(value.getStr().toString()).isEqualTo(errMsg);
}
@Test
public void testGetHelpMessageLiveData() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Check default value
final LiveData<EnrollmentStatusMessage> liveData = mViewModel.getHelpMessageLiveData();
assertThat(liveData.getValue()).isNull();
// Notify help message
final int errMsgId = 3;
final String errMsg = "test error message";
mCallbackWrapper.mValue.onEnrollmentHelp(errMsgId, errMsg);
final EnrollmentStatusMessage value = liveData.getValue();
assertThat(value).isNotNull();
assertThat(value.getMsgId()).isEqualTo(errMsgId);
assertThat(value.getStr().toString()).isEqualTo(errMsg);
}
@Test
public void testGetAcquireLiveData() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Check default value
final LiveData<Boolean> liveData = mViewModel.getAcquireLiveData();
assertThat(liveData.getValue()).isNull();
// Notify acquire message
mCallbackWrapper.mValue.onAcquired(true);
assertThat(liveData.getValue()).isTrue();
}
@Test
public void testGetPointerDownLiveData() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Check default value
final LiveData<Integer> liveData = mViewModel.getPointerDownLiveData();
assertThat(liveData.getValue()).isNull();
// Notify acquire message
final int value = 33;
mCallbackWrapper.mValue.onUdfpsPointerDown(value);
assertThat(liveData.getValue()).isEqualTo(value);
}
@Test
public void testGetPointerUpLiveData() {
// Start enrollment
mViewModel.setToken(new byte[] { 1, 2, 3 });
final Object ret = mViewModel.startEnrollment(ENROLL_ENROLL);
assertThat(ret).isNotNull();
assertThat(mCallbackWrapper.mValue).isNotNull();
// Check default value
final LiveData<Integer> liveData = mViewModel.getPointerUpLiveData();
assertThat(liveData.getValue()).isNull();
// Notify acquire message
final int value = 44;
mCallbackWrapper.mValue.onUdfpsPointerUp(value);
assertThat(liveData.getValue()).isEqualTo(value);
}
private static class TestWrapper<T> {
T mValue;
}
private static class TestHandler extends Handler {
TestHandler() {
super(Looper.getMainLooper());
}
@Override
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
msg.getCallback().run();
return true;
}
}
}

View File

@@ -1,322 +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.biometrics2.ui.viewmodel
import android.app.Application
import android.content.Intent
import android.hardware.fingerprint.FingerprintManager
import android.hardware.fingerprint.FingerprintSensorProperties
import android.os.Bundle
import androidx.activity.result.ActivityResult
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.biometrics.BiometricEnrollBase
import com.android.settings.biometrics2.data.repository.FingerprintRepository
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newAllFalseRequest
import com.android.settings.biometrics2.utils.EnrollmentRequestUtils.newIsSuwRequest
import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.newFingerprintRepository
import com.android.settings.biometrics2.utils.FingerprintRepositoryUtils.setupFingerprintEnrolledFingerprints
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
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.Mock
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoRule
@RunWith(AndroidJUnit4::class)
class FingerprintEnrollmentViewModelTest {
@get:Rule val mockito: MockitoRule = MockitoJUnit.rule()
private val application: Application
get() = ApplicationProvider.getApplicationContext()
@Mock
private lateinit var fingerprintManager: FingerprintManager
private lateinit var fingerprintRepository: FingerprintRepository
private lateinit var viewModel: FingerprintEnrollmentViewModel
@Before
fun setUp() {
fingerprintRepository = newFingerprintRepository(
fingerprintManager,
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
5
)
viewModel = FingerprintEnrollmentViewModel(
application,
fingerprintRepository,
newAllFalseRequest(application)
)
}
@Test
fun testGetRequest() {
assertThat(viewModel.request).isNotNull()
}
@Test
fun testIsWaitingActivityResultDefaultFalse() {
assertThat(viewModel.isWaitingActivityResult.value).isFalse()
}
@Test
fun testOverrideActivityResult_shallKeepNullIntent_woChallengeExtra() {
val retResult = viewModel.getOverrideActivityResult(
ActivityResult(22, null), null
)
assertThat(retResult).isNotNull()
assertThat(retResult.data).isNull()
}
@Test
fun testOverrideActivityResult_shallKeepNullIntent_noIntent_woChallengeExtra() {
val intent = Intent()
val retResult = viewModel.getOverrideActivityResult(
ActivityResult(33, intent), null
)
assertThat(retResult).isNotNull()
assertThat(retResult.data).isEqualTo(intent)
}
@Test
fun testOverrideActivityResult_shallKeepNull_woAdded_woIntent_withChallenge() {
val extra = Bundle()
extra.putString("test1", "test123")
val retResult = viewModel.getOverrideActivityResult(
ActivityResult(33, null), extra
)
assertThat(retResult).isNotNull()
assertThat(retResult.data).isNull()
}
@Test
fun testOverrideActivityResult_shallCreateNew_woIntent_withChallenge() {
val key1 = "test1"
val key2 = "test2"
val extra = Bundle().apply {
putString(key1, "test123")
putInt(key2, 9999)
}
viewModel.isNewFingerprintAdded = true
val retResult = viewModel.getOverrideActivityResult(
ActivityResult(33, null), extra
)
assertThat(retResult).isNotNull()
val retIntent = retResult.data
assertThat(retIntent).isNotNull()
val retExtra = retIntent!!.extras
assertThat(retExtra).isNotNull()
assertThat(retExtra!!.size).isEqualTo(extra.size)
assertThat(retExtra.getString(key1)).isEqualTo(extra.getString(key1))
assertThat(retExtra.getInt(key2)).isEqualTo(extra.getInt(key2))
}
@Test
fun testOverrideActivityResult_shallNotMerge_nonAdded_woIntent_withChallenge() {
val extra = Bundle().apply {
putString("test2", "test123")
}
val key2 = "test2"
val intent = Intent().apply {
putExtra(key2, 3456L)
}
val retResult = viewModel.getOverrideActivityResult(ActivityResult(33, intent), extra)
assertThat(retResult).isNotNull()
val retIntent = retResult.data
assertThat(retIntent).isNotNull()
val retExtra = retIntent!!.extras
assertThat(retExtra).isNotNull()
assertThat(retExtra!!.size).isEqualTo(intent.extras!!.size)
assertThat(retExtra.getString(key2)).isEqualTo(intent.extras!!.getString(key2))
}
@Test
fun testOverrideActivityResult_shallMerge_added_woIntent_withChallenge() {
val key1 = "test1"
val key2 = "test2"
val extra = Bundle().apply {
putString(key1, "test123")
putInt(key2, 9999)
}
val key3 = "test3"
val intent = Intent().apply {
putExtra(key3, 3456L)
}
viewModel.isNewFingerprintAdded = true
val retResult = viewModel.getOverrideActivityResult(ActivityResult(33, intent), extra)
assertThat(retResult).isNotNull()
val retIntent = retResult.data
assertThat(retIntent).isNotNull()
val retExtra = retIntent!!.extras
assertThat(retExtra).isNotNull()
assertThat(retExtra!!.size).isEqualTo(extra.size + intent.extras!!.size)
assertThat(retExtra.getString(key1)).isEqualTo(extra.getString(key1))
assertThat(retExtra.getInt(key2)).isEqualTo(extra.getInt(key2))
assertThat(retExtra.getLong(key3)).isEqualTo(intent.extras!!.getLong(key3))
}
@Test
fun testIsMaxEnrolledReached() {
val uid = 100
fingerprintRepository = newFingerprintRepository(
fingerprintManager,
FingerprintSensorProperties.TYPE_UDFPS_OPTICAL,
3
)
viewModel = FingerprintEnrollmentViewModel(
application,
fingerprintRepository,
newAllFalseRequest(application)
)
setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 0)
assertThat(viewModel.isMaxEnrolledReached(uid)).isFalse()
setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 1)
assertThat(viewModel.isMaxEnrolledReached(uid)).isFalse()
setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 2)
assertThat(viewModel.isMaxEnrolledReached(uid)).isFalse()
setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 3)
assertThat(viewModel.isMaxEnrolledReached(uid)).isTrue()
setupFingerprintEnrolledFingerprints(fingerprintManager, uid, 4)
assertThat(viewModel.isMaxEnrolledReached(uid)).isTrue()
}
@Test
fun testSetResultFlow_defaultEmpty() = runTest {
val activityResults = listOfSetResultFlow()
runCurrent()
assertThat(activityResults.size).isEqualTo(0)
}
@Test
fun testCheckFinishActivityDuringOnPause_doNothingIfIsSuw() = runTest {
viewModel = FingerprintEnrollmentViewModel(
application,
fingerprintRepository,
newIsSuwRequest(application)
)
val activityResults = listOfSetResultFlow()
viewModel.checkFinishActivityDuringOnPause(
isActivityFinishing = false,
isChangingConfigurations = false,
scope = this
)
runCurrent()
assertThat(activityResults.size).isEqualTo(0)
}
@Test
fun testCheckFinishActivityDuringOnPause_doNothingIfIsWaitingActivity() = runTest {
val activityResults = listOfSetResultFlow()
viewModel.isWaitingActivityResult.value = true
viewModel.checkFinishActivityDuringOnPause(
isActivityFinishing = false,
isChangingConfigurations = false,
scope = this
)
runCurrent()
assertThat(activityResults.size).isEqualTo(0)
}
@Test
fun testCheckFinishActivityDuringOnPause_doNothingIfIsActivityFinishing() = runTest {
val activityResults = listOfSetResultFlow()
viewModel.checkFinishActivityDuringOnPause(
isActivityFinishing = true,
isChangingConfigurations = false,
scope = this
)
runCurrent()
assertThat(activityResults.size).isEqualTo(0)
}
@Test
fun testCheckFinishActivityDuringOnPause_doNothingIfIsChangingConfigurations() = runTest {
val activityResults = listOfSetResultFlow()
viewModel.checkFinishActivityDuringOnPause(
isActivityFinishing = false,
isChangingConfigurations = true,
scope = this
)
runCurrent()
assertThat(activityResults.size).isEqualTo(0)
}
@Test
fun testCheckFinishActivityDuringOnPause_defaultFinishSelf() = runTest {
val activityResults = listOfSetResultFlow()
viewModel.checkFinishActivityDuringOnPause(
isActivityFinishing = false,
isChangingConfigurations = false,
scope = backgroundScope
)
runCurrent()
assertThat(activityResults.size).isEqualTo(1)
assertThat(activityResults[0].resultCode).isEqualTo(BiometricEnrollBase.RESULT_TIMEOUT)
assertThat(activityResults[0].data).isEqualTo(null)
}
private fun TestScope.listOfSetResultFlow(): List<ActivityResult> =
mutableListOf<ActivityResult>().also {
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
viewModel.setResultFlow.toList(it)
}
}
}

View File

@@ -1,110 +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.biometrics2.utils
import android.content.Context
import android.content.Intent
import android.text.TextUtils
import com.android.settings.biometrics.BiometricEnrollBase
import com.android.settings.biometrics2.ui.model.EnrollmentRequest
import com.google.android.setupcompat.util.WizardManagerHelper
object EnrollmentRequestUtils {
@JvmStatic
fun newAllFalseRequest(context: Context): EnrollmentRequest {
return newRequest(
context = context,
isSuw = false,
isSuwDeferred = false,
isSuwPortal = false,
isSuwSuggestedActionFlow = false,
isSuwFirstRun = false,
isFromSettingsSummery = false)
}
@JvmStatic
fun newIsSuwRequest(context: Context): EnrollmentRequest {
return newRequest(
context = context,
isSuw = true,
isSuwDeferred = false,
isSuwPortal = false,
isSuwSuggestedActionFlow = false,
isSuwFirstRun = false,
isFromSettingsSummery = false)
}
@JvmStatic
fun newIsSuwDeferredRequest(context: Context): EnrollmentRequest {
return newRequest(
context = context,
isSuw = true,
isSuwDeferred = true,
isSuwPortal = false,
isSuwSuggestedActionFlow = false,
isSuwFirstRun = false,
isFromSettingsSummery = false, null)
}
@JvmStatic
fun newIsSuwPortalRequest(context: Context): EnrollmentRequest {
return newRequest(
context = context,
isSuw = true,
isSuwDeferred = false,
isSuwPortal = true,
isSuwSuggestedActionFlow = false,
isSuwFirstRun = false,
isFromSettingsSummery = false)
}
@JvmStatic
fun newIsSuwSuggestedActionFlowRequest(
context: Context
): EnrollmentRequest {
return newRequest(
context = context,
isSuw = true,
isSuwDeferred = false,
isSuwPortal = false,
isSuwSuggestedActionFlow = true,
isSuwFirstRun = false,
isFromSettingsSummery = false)
}
fun newRequest(
context: Context,
isSuw: Boolean,
isSuwDeferred: Boolean,
isSuwPortal: Boolean,
isSuwSuggestedActionFlow: Boolean,
isSuwFirstRun: Boolean,
isFromSettingsSummery: Boolean,
theme: String? = null
): EnrollmentRequest {
val i = Intent()
i.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, isSuw)
i.putExtra(WizardManagerHelper.EXTRA_IS_DEFERRED_SETUP, isSuwDeferred)
i.putExtra(WizardManagerHelper.EXTRA_IS_PORTAL_SETUP, isSuwPortal)
i.putExtra(WizardManagerHelper.EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW, isSuwSuggestedActionFlow)
i.putExtra(WizardManagerHelper.EXTRA_IS_FIRST_RUN, isSuwFirstRun)
i.putExtra(BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY, isFromSettingsSummery)
if (!TextUtils.isEmpty(theme)) {
i.putExtra(WizardManagerHelper.EXTRA_THEME, theme)
}
return EnrollmentRequest(i, context, true)
}
}

View File

@@ -1,81 +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.biometrics2.utils;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.biometrics.SensorProperties;
import android.hardware.fingerprint.Fingerprint;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintSensorProperties;
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.hardware.fingerprint.IFingerprintAuthenticatorsRegisteredCallback;
import androidx.annotation.NonNull;
import com.android.settings.biometrics2.data.repository.FingerprintRepository;
import java.util.ArrayList;
public class FingerprintRepositoryUtils {
public static void setupSuwMaxFingerprintsEnrollable(
@NonNull Context context,
@NonNull Resources mockedResources,
int numOfFp) {
final int resId = context.getResources().getIdentifier("suw_max_fingerprints_enrollable",
"integer", context.getPackageName());
when(mockedResources.getInteger(resId)).thenReturn(numOfFp);
}
public static FingerprintRepository newFingerprintRepository(
@NonNull FingerprintManager mockedFingerprintManager,
@FingerprintSensorProperties.SensorType int sensorType,
int maxEnrollmentsPerUser) {
final ArrayList<FingerprintSensorPropertiesInternal> props = new ArrayList<>();
props.add(new FingerprintSensorPropertiesInternal(
0 /* sensorId */,
SensorProperties.STRENGTH_STRONG,
maxEnrollmentsPerUser,
new ArrayList<>() /* componentInfo */,
sensorType,
true /* resetLockoutRequiresHardwareAuthToken */));
doAnswer(invocation -> {
final IFingerprintAuthenticatorsRegisteredCallback callback =
invocation.getArgument(0);
callback.onAllAuthenticatorsRegistered(props);
return null;
}).when(mockedFingerprintManager).addAuthenticatorsRegisteredCallback(any());
return new FingerprintRepository(mockedFingerprintManager);
}
public static void setupFingerprintEnrolledFingerprints(
@NonNull FingerprintManager mockedFingerprintManager,
int userId,
int enrolledFingerprints) {
final ArrayList<Fingerprint> ret = new ArrayList<>();
for (int i = 0; i < enrolledFingerprints; ++i) {
ret.add(new Fingerprint("name", 0, 0, 0L));
}
when(mockedFingerprintManager.getEnrolledFingerprints(userId)).thenReturn(ret);
}
}

View File

@@ -25,7 +25,6 @@ import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.biometrics.face.FaceFeatureProvider;
import com.android.settings.biometrics.fingerprint.FingerprintFeatureProvider;
import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider;
import com.android.settings.bluetooth.BluetoothFeatureProvider;
import com.android.settings.connecteddevice.fastpair.FastPairFeatureProvider;
import com.android.settings.connecteddevice.stylus.StylusFeatureProvider;
@@ -82,7 +81,6 @@ public class FakeFeatureFactory extends FeatureFactory {
public final BluetoothFeatureProvider mBluetoothFeatureProvider;
public final FaceFeatureProvider mFaceFeatureProvider;
public final FingerprintFeatureProvider mFingerprintFeatureProvider;
public final BiometricsRepositoryProvider mBiometricsRepositoryProvider;
public PanelFeatureProvider panelFeatureProvider;
public SlicesFeatureProvider slicesFeatureProvider;
@@ -140,7 +138,6 @@ public class FakeFeatureFactory extends FeatureFactory {
mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class);
mFaceFeatureProvider = mock(FaceFeatureProvider.class);
mFingerprintFeatureProvider = mock(FingerprintFeatureProvider.class);
mBiometricsRepositoryProvider = mock(BiometricsRepositoryProvider.class);
wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class);
securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class);
@@ -272,11 +269,6 @@ public class FakeFeatureFactory extends FeatureFactory {
return mFingerprintFeatureProvider;
}
@Override
public BiometricsRepositoryProvider getBiometricsRepositoryProvider() {
return mBiometricsRepositoryProvider;
}
@Override
public WifiTrackerLibProvider getWifiTrackerLibProvider() {
return wifiTrackerLibProvider;