Merge "Fingerprint Introduction FragmentActivity"

This commit is contained in:
TreeHugger Robot
2022-11-16 00:04:49 +00:00
committed by Android (Google) Code Review
30 changed files with 3319 additions and 1 deletions

View File

@@ -0,0 +1,125 @@
/*
* 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.data.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.util.FingerprintManagerUtil.setupFingerprintEnrolledFingerprints;
import static com.android.settings.biometrics2.util.FingerprintManagerUtil.setupFingerprintFirstSensor;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.hardware.fingerprint.FingerprintManager;
import androidx.annotation.NonNull;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.settings.testutils.ResourcesUtils;
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 FingerprintRepositoryTest {
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
@Mock private Resources mResources;
@Mock private FingerprintManager mFingerprintManager;
private Context mContext;
private FingerprintRepository mFingerprintRepository;
@Before
public void setUp() {
mContext = ApplicationProvider.getApplicationContext();
mFingerprintRepository = new FingerprintRepository(mFingerprintManager);
}
@Test
public void testCanAssumeSensorType() {
setupFingerprintFirstSensor(mFingerprintManager, TYPE_UNKNOWN, 1);
assertThat(mFingerprintRepository.canAssumeUdfps()).isFalse();
setupFingerprintFirstSensor(mFingerprintManager, TYPE_REAR, 1);
assertThat(mFingerprintRepository.canAssumeUdfps()).isFalse();
setupFingerprintFirstSensor(mFingerprintManager, TYPE_UDFPS_ULTRASONIC, 1);
assertThat(mFingerprintRepository.canAssumeUdfps()).isTrue();
setupFingerprintFirstSensor(mFingerprintManager, TYPE_UDFPS_OPTICAL, 1);
assertThat(mFingerprintRepository.canAssumeUdfps()).isTrue();
setupFingerprintFirstSensor(mFingerprintManager, TYPE_POWER_BUTTON, 1);
assertThat(mFingerprintRepository.canAssumeUdfps()).isFalse();
setupFingerprintFirstSensor(mFingerprintManager, TYPE_HOME_BUTTON, 1);
assertThat(mFingerprintRepository.canAssumeUdfps()).isFalse();
}
@Test
public void testGetMaxFingerprints() {
setupFingerprintFirstSensor(mFingerprintManager, TYPE_UNKNOWN, 44);
assertThat(mFingerprintRepository.getMaxFingerprints()).isEqualTo(44);
setupFingerprintFirstSensor(mFingerprintManager, TYPE_UNKNOWN, 999);
assertThat(mFingerprintRepository.getMaxFingerprints()).isEqualTo(999);
}
@Test
public void testGetNumOfEnrolledFingerprintsSize() {
setupFingerprintEnrolledFingerprints(mFingerprintManager, 10, 3);
setupFingerprintEnrolledFingerprints(mFingerprintManager, 22, 99);
assertThat(mFingerprintRepository.getNumOfEnrolledFingerprintsSize(10)).isEqualTo(3);
assertThat(mFingerprintRepository.getNumOfEnrolledFingerprintsSize(22)).isEqualTo(99);
}
@Test
public void testGetMaxFingerprintsInSuw() {
setupSuwMaxFingerprintsEnrollable(mContext, mResources, 333);
assertThat(mFingerprintRepository.getMaxFingerprintsInSuw(mResources))
.isEqualTo(333);
setupSuwMaxFingerprintsEnrollable(mContext, mResources, 20);
assertThat(mFingerprintRepository.getMaxFingerprintsInSuw(mResources)).isEqualTo(20);
}
public static void setupSuwMaxFingerprintsEnrollable(
@NonNull Context context,
@NonNull Resources mockedResources,
int numOfFp) {
final int resId = ResourcesUtils.getResourcesId(context, "integer",
"suw_max_fingerprints_enrollable");
when(mockedResources.getInteger(resId)).thenReturn(numOfFp);
}
}

View File

@@ -0,0 +1,380 @@
/*
* 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 android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_NUMERIC;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_CHALLENGE;
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_SENSOR_ID;
import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_CHALLENGE;
import static com.android.settings.biometrics2.ui.model.CredentialModel.INVALID_SENSOR_ID;
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK;
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK;
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.ChallengeGenerator;
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.CredentialAction;
import static com.android.settings.biometrics2.ui.viewmodel.AutoCredentialViewModel.GenerateChallengeCallback;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.app.Activity;
import android.content.Intent;
import android.os.SystemClock;
import android.os.UserHandle;
import androidx.activity.result.ActivityResult;
import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleOwner;
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.biometrics2.ui.model.CredentialModel;
import com.android.settings.password.ChooseLockPattern;
import com.android.settings.password.ChooseLockSettingsHelper;
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 AutoCredentialViewModelTest {
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
@Mock private LifecycleOwner mLifecycleOwner;
@Mock private LockPatternUtils mLockPatternUtils;
private TestChallengeGenerator mChallengeGenerator = null;
private AutoCredentialViewModel mAutoCredentialViewModel;
@Before
public void setUp() {
mChallengeGenerator = new TestChallengeGenerator();
mAutoCredentialViewModel = new AutoCredentialViewModel(
ApplicationProvider.getApplicationContext(),
mLockPatternUtils,
mChallengeGenerator);
}
private CredentialModel newCredentialModel(int userId, long challenge,
@Nullable byte[] token, long gkPwHandle) {
final Intent intent = new Intent();
intent.putExtra(Intent.EXTRA_USER_ID, userId);
intent.putExtra(EXTRA_KEY_SENSOR_ID, 1);
intent.putExtra(EXTRA_KEY_CHALLENGE, challenge);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
return new CredentialModel(intent, SystemClock.elapsedRealtimeClock());
}
private CredentialModel newValidTokenCredentialModel(int userId) {
return newCredentialModel(userId, 1L, new byte[] { 0 }, 0L);
}
private CredentialModel newInvalidChallengeCredentialModel(int userId) {
return newCredentialModel(userId, INVALID_CHALLENGE, null, 0L);
}
private CredentialModel newGkPwHandleCredentialModel(int userId, long gkPwHandle) {
return newCredentialModel(userId, INVALID_CHALLENGE, null, gkPwHandle);
}
private void verifyNothingHappen() {
assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull();
}
private void verifyOnlyActionLiveData(@CredentialAction int action) {
final Integer value = mAutoCredentialViewModel.getActionLiveData().getValue();
assertThat(value).isEqualTo(action);
}
private void setupGenerateTokenFlow(long gkPwHandle, int userId, int newSensorId,
long newChallenge) {
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_SOMETHING);
mChallengeGenerator.mUserId = userId;
mChallengeGenerator.mSensorId = newSensorId;
mChallengeGenerator.mChallenge = newChallenge;
when(mLockPatternUtils.verifyGatekeeperPasswordHandle(gkPwHandle, newChallenge, userId))
.thenReturn(newGoodCredential(gkPwHandle, new byte[] { 1 }));
}
@Test
public void checkCredential_validCredentialCase() {
final int userId = 99;
mAutoCredentialViewModel.setCredentialModel(newValidTokenCredentialModel(userId));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_SOMETHING);
// Run credential check
mAutoCredentialViewModel.onCreate(mLifecycleOwner);
verifyNothingHappen();
}
@Test
public void checkCredential_needToChooseLock() {
final int userId = 100;
mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_UNSPECIFIED);
// Run credential check
mAutoCredentialViewModel.onCreate(mLifecycleOwner);
verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CHOOSE_LOCK);
}
@Test
public void checkCredential_needToConfirmLockFoSomething() {
final int userId = 101;
mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_SOMETHING);
// Run credential check
mAutoCredentialViewModel.onCreate(mLifecycleOwner);
verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK);
}
@Test
public void checkCredential_needToConfirmLockForNumeric() {
final int userId = 102;
mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_NUMERIC);
// Run credential check
mAutoCredentialViewModel.onCreate(mLifecycleOwner);
verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK);
}
@Test
public void checkCredential_needToConfirmLockForAlphabetic() {
final int userId = 103;
mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId));
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_ALPHABETIC);
// Run credential check
mAutoCredentialViewModel.onCreate(mLifecycleOwner);
verifyOnlyActionLiveData(CREDENTIAL_FAIL_NEED_TO_CONFIRM_LOCK);
}
@Test
public void checkCredential_generateChallenge() {
final int userId = 104;
final long gkPwHandle = 1111L;
final CredentialModel credentialModel = newGkPwHandleCredentialModel(userId, gkPwHandle);
mAutoCredentialViewModel.setCredentialModel(credentialModel);
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_SOMETHING);
final int newSensorId = 10;
final long newChallenge = 20L;
setupGenerateTokenFlow(gkPwHandle, userId, newSensorId, newChallenge);
// Run credential check
mAutoCredentialViewModel.onCreate(mLifecycleOwner);
assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull();
assertThat(credentialModel.getSensorId()).isEqualTo(newSensorId);
assertThat(credentialModel.getChallenge()).isEqualTo(newChallenge);
assertThat(CredentialModel.isValidToken(credentialModel.getToken())).isTrue();
assertThat(CredentialModel.isValidGkPwHandle(credentialModel.getGkPwHandle())).isFalse();
assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1);
}
@Test
public void testGetUserId() {
final int userId = 106;
mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId));
// Get userId
assertThat(mAutoCredentialViewModel.getUserId()).isEqualTo(userId);
}
@Test
public void testCheckNewCredentialFromActivityResult_invalidChooseLock() {
final int userId = 107;
final long gkPwHandle = 3333L;
mAutoCredentialViewModel.setCredentialModel(
newGkPwHandleCredentialModel(userId, gkPwHandle));
final Intent intent = new Intent();
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
// run checkNewCredentialFromActivityResult()
final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true,
new ActivityResult(ChooseLockPattern.RESULT_FINISHED + 1, intent));
assertThat(ret).isFalse();
verifyNothingHappen();
}
@Test
public void testCheckNewCredentialFromActivityResult_invalidConfirmLock() {
final int userId = 107;
final long gkPwHandle = 3333L;
mAutoCredentialViewModel.setCredentialModel(
newGkPwHandleCredentialModel(userId, gkPwHandle));
final Intent intent = new Intent();
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
// run checkNewCredentialFromActivityResult()
final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false,
new ActivityResult(Activity.RESULT_OK + 1, intent));
assertThat(ret).isFalse();
verifyNothingHappen();
}
@Test
public void testCheckNewCredentialFromActivityResult_nullDataChooseLock() {
final int userId = 108;
final long gkPwHandle = 4444L;
mAutoCredentialViewModel.setCredentialModel(
newGkPwHandleCredentialModel(userId, gkPwHandle));
// run checkNewCredentialFromActivityResult()
final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true,
new ActivityResult(ChooseLockPattern.RESULT_FINISHED, null));
assertThat(ret).isFalse();
verifyNothingHappen();
}
@Test
public void testCheckNewCredentialFromActivityResult_nullDataConfirmLock() {
final int userId = 109;
mAutoCredentialViewModel.setCredentialModel(newInvalidChallengeCredentialModel(userId));
// run checkNewCredentialFromActivityResult()
final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false,
new ActivityResult(Activity.RESULT_OK, null));
assertThat(ret).isFalse();
verifyNothingHappen();
}
@Test
public void testCheckNewCredentialFromActivityResult_validChooseLock() {
final int userId = 108;
final CredentialModel credentialModel = newInvalidChallengeCredentialModel(userId);
mAutoCredentialViewModel.setCredentialModel(credentialModel);
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_SOMETHING);
final long gkPwHandle = 6666L;
final int newSensorId = 50;
final long newChallenge = 60L;
setupGenerateTokenFlow(gkPwHandle, userId, newSensorId, newChallenge);
final Intent intent = new Intent();
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
// Run checkNewCredentialFromActivityResult()
final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(true,
new ActivityResult(ChooseLockPattern.RESULT_FINISHED, intent));
assertThat(ret).isTrue();
assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull();
assertThat(credentialModel.getSensorId()).isEqualTo(newSensorId);
assertThat(credentialModel.getChallenge()).isEqualTo(newChallenge);
assertThat(CredentialModel.isValidToken(credentialModel.getToken())).isTrue();
assertThat(CredentialModel.isValidGkPwHandle(credentialModel.getGkPwHandle())).isFalse();
assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1);
}
@Test
public void testCheckNewCredentialFromActivityResult_validConfirmLock() {
final int userId = 109;
final CredentialModel credentialModel = newInvalidChallengeCredentialModel(userId);
mAutoCredentialViewModel.setCredentialModel(credentialModel);
when(mLockPatternUtils.getActivePasswordQuality(userId)).thenReturn(
PASSWORD_QUALITY_SOMETHING);
final long gkPwHandle = 5555L;
final int newSensorId = 80;
final long newChallenge = 90L;
setupGenerateTokenFlow(gkPwHandle, userId, newSensorId, newChallenge);
final Intent intent = new Intent();
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, gkPwHandle);
// Run checkNewCredentialFromActivityResult()
final boolean ret = mAutoCredentialViewModel.checkNewCredentialFromActivityResult(false,
new ActivityResult(Activity.RESULT_OK, intent));
assertThat(ret).isTrue();
assertThat(mAutoCredentialViewModel.getActionLiveData().getValue()).isNull();
assertThat(credentialModel.getSensorId()).isEqualTo(newSensorId);
assertThat(credentialModel.getChallenge()).isEqualTo(newChallenge);
assertThat(CredentialModel.isValidToken(credentialModel.getToken())).isTrue();
assertThat(CredentialModel.isValidGkPwHandle(credentialModel.getGkPwHandle())).isFalse();
assertThat(mChallengeGenerator.mCallbackRunCount).isEqualTo(1);
}
public static class TestChallengeGenerator implements ChallengeGenerator {
public int mSensorId = INVALID_SENSOR_ID;
public int mUserId = UserHandle.myUserId();
public long mChallenge = INVALID_CHALLENGE;
public int mCallbackRunCount = 0;
private GenerateChallengeCallback mCallback;
@Nullable
@Override
public GenerateChallengeCallback getCallback() {
return mCallback;
}
@Override
public void setCallback(@Nullable GenerateChallengeCallback callback) {
mCallback = callback;
}
@Override
public void generateChallenge(int userId) {
final GenerateChallengeCallback callback = mCallback;
if (callback == null) {
return;
}
callback.onChallengeGenerated(mSensorId, mUserId, mChallenge);
++mCallbackRunCount;
}
}
private VerifyCredentialResponse newGoodCredential(long gkPwHandle, @NonNull byte[] hat) {
return new VerifyCredentialResponse.Builder()
.setGatekeeperPasswordHandle(gkPwHandle)
.setGatekeeperHAT(hat)
.build();
}
}

View File

@@ -0,0 +1,259 @@
/*
* 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 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 com.android.settings.biometrics2.data.repository.FingerprintRepositoryTest.setupSuwMaxFingerprintsEnrollable;
import static com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus.FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX;
import static com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus.FINGERPRINT_ENROLLABLE_OK;
import static com.android.settings.biometrics2.ui.model.FingerprintEnrollIntroStatus.FINGERPRINT_ENROLLABLE_UNKNOWN;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_CONTINUE_ENROLL;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_DONE_AND_FINISH;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollIntroViewModel.FINGERPRINT_ENROLL_INTRO_ACTION_SKIP_OR_CANCEL;
import static com.android.settings.biometrics2.util.EnrollmentRequestUtil.newAllFalseRequest;
import static com.android.settings.biometrics2.util.EnrollmentRequestUtil.newIsSuwDeferredRequest;
import static com.android.settings.biometrics2.util.EnrollmentRequestUtil.newIsSuwPortalRequest;
import static com.android.settings.biometrics2.util.EnrollmentRequestUtil.newIsSuwRequest;
import static com.android.settings.biometrics2.util.EnrollmentRequestUtil.newIsSuwSuggestedActionFlowRequest;
import static com.android.settings.biometrics2.util.FingerprintManagerUtil.setupFingerprintEnrolledFingerprints;
import static com.android.settings.biometrics2.util.FingerprintManagerUtil.setupFingerprintFirstSensor;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.app.Application;
import android.content.res.Resources;
import android.hardware.fingerprint.FingerprintManager;
import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleOwner;
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.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 FingerprintEnrollIntroViewModelTest {
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
@Mock private Resources mResources;
@Mock private LifecycleOwner mLifecycleOwner;
@Mock private FingerprintManager mFingerprintManager;
private Application mApplication;
private FingerprintRepository mFingerprintRepository;
private FingerprintEnrollIntroViewModel mViewModel;
@Before
public void setUp() {
mApplication = ApplicationProvider.getApplicationContext();
mFingerprintRepository = new FingerprintRepository(mFingerprintManager);
mViewModel = new FingerprintEnrollIntroViewModel(mApplication, mFingerprintRepository);
// MediatorLiveData won't update itself unless observed
mViewModel.getPageStatusLiveData().observeForever(event -> {});
}
@Test
public void testPageStatusLiveDataDefaultValue() {
final FingerprintEnrollIntroStatus status = mViewModel.getPageStatusLiveData().getValue();
assertThat(status.hasScrollToBottom()).isFalse();
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_UNKNOWN);
}
@Test
public void testGetEnrollmentRequest() {
final EnrollmentRequest request = newAllFalseRequest(mApplication);
mViewModel.setEnrollmentRequest(request);
assertThat(mViewModel.getEnrollmentRequest()).isEqualTo(request);
}
@Test
public void testOnStartToUpdateEnrollableStatus_isSuw() {
final int userId = 44;
mViewModel.setUserId(userId);
mViewModel.setEnrollmentRequest(newIsSuwRequest(mApplication));
setupFingerprintEnrolledFingerprints(mFingerprintManager, userId, 0);
setupSuwMaxFingerprintsEnrollable(mApplication, mResources, 1);
mViewModel.onStart(mLifecycleOwner);
FingerprintEnrollIntroStatus status = mViewModel.getPageStatusLiveData().getValue();
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_OK);
setupFingerprintEnrolledFingerprints(mFingerprintManager, userId, 1);
setupSuwMaxFingerprintsEnrollable(mApplication, mResources, 1);
mViewModel.onStart(mLifecycleOwner);
status = mViewModel.getPageStatusLiveData().getValue();
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX);
}
@Test
public void testOnStartToUpdateEnrollableStatus_isNotSuw() {
testOnStartToUpdateEnrollableStatus(newAllFalseRequest(mApplication));
}
@Test
public void testOnStartToUpdateEnrollableStatus_isSuwDeferred() {
testOnStartToUpdateEnrollableStatus(newIsSuwDeferredRequest(mApplication));
}
@Test
public void testOnStartToUpdateEnrollableStatus_isSuwPortal() {
testOnStartToUpdateEnrollableStatus(newIsSuwPortalRequest(mApplication));
}
@Test
public void testOnStartToUpdateEnrollableStatus_isSuwSuggestedActionFlow() {
testOnStartToUpdateEnrollableStatus(newIsSuwSuggestedActionFlowRequest(mApplication));
}
private void testOnStartToUpdateEnrollableStatus(@NonNull EnrollmentRequest request) {
final int userId = 45;
mViewModel.setUserId(userId);
mViewModel.setEnrollmentRequest(request);
setupFingerprintEnrolledFingerprints(mFingerprintManager, userId, 0);
setupFingerprintFirstSensor(mFingerprintManager, TYPE_UDFPS_OPTICAL, 5);
mViewModel.onStart(mLifecycleOwner);
FingerprintEnrollIntroStatus status = mViewModel.getPageStatusLiveData().getValue();
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_OK);
setupFingerprintEnrolledFingerprints(mFingerprintManager, userId, 5);
setupFingerprintFirstSensor(mFingerprintManager, TYPE_UDFPS_OPTICAL, 5);
mViewModel.onStart(mLifecycleOwner);
status = mViewModel.getPageStatusLiveData().getValue();
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX);
}
@Test
public void textCanAssumeUdfps() {
setupFingerprintFirstSensor(mFingerprintManager, TYPE_UDFPS_ULTRASONIC, 1);
assertThat(mViewModel.canAssumeUdfps()).isEqualTo(true);
setupFingerprintFirstSensor(mFingerprintManager, TYPE_REAR, 1);
assertThat(mViewModel.canAssumeUdfps()).isEqualTo(false);
}
@Test
public void testIsParentalConsentRequired() {
// We shall not mock FingerprintRepository, but
// FingerprintRepository.isParentalConsentRequired() calls static method inside, we can't
// mock static method
final FingerprintRepository fingerprintRepository = mock(FingerprintRepository.class);
mViewModel = new FingerprintEnrollIntroViewModel(mApplication, fingerprintRepository);
when(fingerprintRepository.isParentalConsentRequired(mApplication)).thenReturn(true);
assertThat(mViewModel.isParentalConsentRequired()).isEqualTo(true);
when(fingerprintRepository.isParentalConsentRequired(mApplication)).thenReturn(false);
assertThat(mViewModel.isParentalConsentRequired()).isEqualTo(false);
}
@Test
public void testIsBiometricUnlockDisabledByAdmin() {
// We shall not mock FingerprintRepository, but
// FingerprintRepository.isDisabledByAdmin() calls static method inside, we can't mock
// static method
final FingerprintRepository fingerprintRepository = mock(FingerprintRepository.class);
mViewModel = new FingerprintEnrollIntroViewModel(mApplication, fingerprintRepository);
final int userId = 33;
mViewModel.setUserId(userId);
when(fingerprintRepository.isDisabledByAdmin(mApplication, userId)).thenReturn(true);
assertThat(mViewModel.isBiometricUnlockDisabledByAdmin()).isEqualTo(true);
when(fingerprintRepository.isDisabledByAdmin(mApplication, userId)).thenReturn(false);
assertThat(mViewModel.isBiometricUnlockDisabledByAdmin()).isEqualTo(false);
}
@Test
public void testSetHasScrolledToBottom() {
mViewModel.setHasScrolledToBottom();
FingerprintEnrollIntroStatus status = mViewModel.getPageStatusLiveData().getValue();
assertThat(status.hasScrollToBottom()).isEqualTo(true);
}
@Test
public void testOnNextButtonClick_enrollNext() {
final int userId = 46;
mViewModel.setUserId(userId);
mViewModel.setEnrollmentRequest(newIsSuwRequest(mApplication));
// Set latest status to FINGERPRINT_ENROLLABLE_OK
setupFingerprintEnrolledFingerprints(mFingerprintManager, userId, 0);
setupSuwMaxFingerprintsEnrollable(mApplication, mResources, 1);
mViewModel.onStart(mLifecycleOwner);
FingerprintEnrollIntroStatus status = mViewModel.getPageStatusLiveData().getValue();
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_OK);
// Perform click on `next`
mViewModel.onNextButtonClick(null);
assertThat(mViewModel.getActionLiveData().getValue())
.isEqualTo(FINGERPRINT_ENROLL_INTRO_ACTION_CONTINUE_ENROLL);
}
@Test
public void testOnNextButtonClick_doneAndFinish() {
final int userId = 46;
mViewModel.setUserId(userId);
mViewModel.setEnrollmentRequest(newIsSuwRequest(mApplication));
// Set latest status to FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX
setupFingerprintEnrolledFingerprints(mFingerprintManager, userId, 1);
setupSuwMaxFingerprintsEnrollable(mApplication, mResources, 1);
mViewModel.onStart(mLifecycleOwner);
FingerprintEnrollIntroStatus status = mViewModel.getPageStatusLiveData().getValue();
assertThat(status.getEnrollableStatus()).isEqualTo(FINGERPRINT_ENROLLABLE_ERROR_REACH_MAX);
// Perform click on `next`
mViewModel.onNextButtonClick(null);
assertThat(mViewModel.getActionLiveData().getValue())
.isEqualTo(FINGERPRINT_ENROLL_INTRO_ACTION_DONE_AND_FINISH);
}
@Test
public void testOnSkipOrCancelButtonClick() {
mViewModel.onSkipOrCancelButtonClick(null);
assertThat(mViewModel.getActionLiveData().getValue())
.isEqualTo(FINGERPRINT_ENROLL_INTRO_ACTION_SKIP_OR_CANCEL);
}
}

View File

@@ -0,0 +1,252 @@
/*
* 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.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED;
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_SKIP;
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_TIMEOUT;
import static com.android.settings.biometrics.fingerprint.SetupFingerprintEnrollIntroduction.EXTRA_FINGERPRINT_ENROLLED_COUNT;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollmentViewModel.SAVED_STATE_IS_WAITING_ACTIVITY_RESULT;
import static com.android.settings.biometrics2.util.EnrollmentRequestUtil.newAllFalseRequest;
import static com.android.settings.biometrics2.util.EnrollmentRequestUtil.newIsSuwRequest;
import static com.android.settings.biometrics2.util.FingerprintManagerUtil.setupFingerprintEnrolledFingerprints;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.app.Application;
import android.app.KeyguardManager;
import android.content.Intent;
import android.hardware.fingerprint.FingerprintManager;
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.biometrics2.data.repository.FingerprintRepository;
import com.android.settings.biometrics2.ui.model.EnrollmentRequest;
import com.android.settings.password.SetupSkipDialog;
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 FingerprintEnrollmentViewModelTest {
@Rule public final MockitoRule mockito = MockitoJUnit.rule();
@Rule public final InstantTaskExecutorRule mTaskExecutorRule = new InstantTaskExecutorRule();
@Mock private FingerprintManager mFingerprintManager;
@Mock private KeyguardManager mKeyguardManager;
private Application mApplication;
private FingerprintRepository mFingerprintRepository;
private FingerprintEnrollmentViewModel mViewModel;
@Before
public void setUp() {
mApplication = ApplicationProvider.getApplicationContext();
mFingerprintRepository = new FingerprintRepository(mFingerprintManager);
mViewModel = new FingerprintEnrollmentViewModel(mApplication, mFingerprintRepository,
mKeyguardManager);
}
@Test
public void testGetRequest() {
when(mKeyguardManager.isKeyguardSecure()).thenReturn(true);
assertThat(mViewModel.getRequest()).isNull();
final EnrollmentRequest request = newAllFalseRequest(mApplication);
mViewModel.setRequest(request);
assertThat(mViewModel.getRequest()).isEqualTo(request);
}
@Test
public void testGetNextActivityBaseIntentExtras() {
mViewModel.setRequest(newAllFalseRequest(mApplication));
assertThat(mViewModel.getNextActivityBaseIntentExtras()).isNotNull();
}
@Test
public void testOnContinueEnrollActivityResult_shouldRelaySkip1Result() {
mViewModel.setRequest(newAllFalseRequest(mApplication));
final ActivityResult result = new ActivityResult(RESULT_SKIP, null);
// Run onContinueEnrollActivityResult
mViewModel.onContinueEnrollActivityResult(result, 100);
assertThat(mViewModel.getSetResultLiveData().getValue()).isEqualTo(result);
}
@Test
public void testOnContinueEnrollActivityResult_shouldRelaySkip2Result() {
mViewModel.setRequest(newAllFalseRequest(mApplication));
final ActivityResult result = new ActivityResult(SetupSkipDialog.RESULT_SKIP, null);
// Run onContinueEnrollActivityResult
mViewModel.onContinueEnrollActivityResult(result, 100);
assertThat(mViewModel.getSetResultLiveData().getValue()).isEqualTo(result);
}
@Test
public void testOnContinueEnrollActivityResult_shouldRelayNullDataTimeoutResult() {
mViewModel.setRequest(newAllFalseRequest(mApplication));
final ActivityResult result = new ActivityResult(RESULT_TIMEOUT, null);
// Run onContinueEnrollActivityResult
mViewModel.onContinueEnrollActivityResult(result, 100);
final ActivityResult setResult = mViewModel.getSetResultLiveData().getValue();
assertThat(setResult).isNotNull();
assertThat(setResult.getResultCode()).isEqualTo(result.getResultCode());
assertThat(setResult.getData()).isEqualTo(result.getData());
}
@Test
public void testOnContinueEnrollActivityResult_shouldRelayWithDataTimeoutResult() {
mViewModel.setRequest(newAllFalseRequest(mApplication));
final Intent intent = new Intent("testAction");
intent.putExtra("testKey", "testValue");
final ActivityResult result = new ActivityResult(RESULT_TIMEOUT, intent);
// Run onContinueEnrollActivityResult
mViewModel.onContinueEnrollActivityResult(result, 100);
final ActivityResult setResult = mViewModel.getSetResultLiveData().getValue();
assertThat(setResult).isNotNull();
assertThat(setResult.getResultCode()).isEqualTo(result.getResultCode());
assertThat(setResult.getData()).isEqualTo(intent);
}
@Test
public void testOnContinueEnrollActivityResult_shouldRelayNullDataFinishResult() {
mViewModel.setRequest(newAllFalseRequest(mApplication));
final ActivityResult result = new ActivityResult(RESULT_FINISHED, null);
// Run onContinueEnrollActivityResult
mViewModel.onContinueEnrollActivityResult(result, 100);
final ActivityResult setResult = mViewModel.getSetResultLiveData().getValue();
assertThat(setResult).isNotNull();
assertThat(setResult.getResultCode()).isEqualTo(result.getResultCode());
assertThat(setResult.getData()).isEqualTo(result.getData());
}
@Test
public void testOnContinueEnrollActivityResult_shouldRelayWithDataFinishResult() {
mViewModel.setRequest(newAllFalseRequest(mApplication));
final Intent intent = new Intent("testAction");
intent.putExtra("testKey", "testValue");
final ActivityResult result = new ActivityResult(RESULT_FINISHED, intent);
// Run onContinueEnrollActivityResult
mViewModel.onContinueEnrollActivityResult(result, 100);
final ActivityResult setResult = mViewModel.getSetResultLiveData().getValue();
assertThat(setResult).isNotNull();
assertThat(setResult.getResultCode()).isEqualTo(result.getResultCode());
assertThat(setResult.getData()).isEqualTo(intent);
}
@Test
public void testOnContinueEnrollActivityResult_shouldRelayNullDataFinishResultAsNewData() {
when(mKeyguardManager.isKeyguardSecure()).thenReturn(true);
final int userId = 111;
final int numOfFp = 4;
setupFingerprintEnrolledFingerprints(mFingerprintManager, userId, numOfFp);
mViewModel.setRequest(newIsSuwRequest(mApplication));
final ActivityResult result = new ActivityResult(RESULT_FINISHED, null);
// Run onContinueEnrollActivityResult
mViewModel.onContinueEnrollActivityResult(result, userId);
final ActivityResult setResult = mViewModel.getSetResultLiveData().getValue();
assertThat(setResult).isNotNull();
assertThat(setResult.getResultCode()).isEqualTo(result.getResultCode());
assertThat(setResult.getData()).isNotNull();
assertThat(setResult.getData().getExtras()).isNotNull();
assertThat(setResult.getData().getExtras().getInt(EXTRA_FINGERPRINT_ENROLLED_COUNT, -1))
.isEqualTo(numOfFp);
}
@Test
public void testOnContinueEnrollActivityResult_shouldRelayWithDataFinishResultAsNewData() {
when(mKeyguardManager.isKeyguardSecure()).thenReturn(true);
final int userId = 20;
final int numOfFp = 9;
setupFingerprintEnrolledFingerprints(mFingerprintManager, userId, numOfFp);
mViewModel.setRequest(newIsSuwRequest(mApplication));
final String action = "testAction";
final String key = "testKey";
final String value = "testValue";
final Intent intent = new Intent(action);
intent.putExtra(key, value);
final ActivityResult result = new ActivityResult(RESULT_FINISHED, intent);
// Run onContinueEnrollActivityResult
mViewModel.onContinueEnrollActivityResult(result, userId);
final ActivityResult setResult = mViewModel.getSetResultLiveData().getValue();
assertThat(setResult).isNotNull();
assertThat(setResult.getResultCode()).isEqualTo(result.getResultCode());
assertThat(setResult.getData()).isNotNull();
assertThat(setResult.getData().getExtras()).isNotNull();
assertThat(setResult.getData().getExtras().getInt(EXTRA_FINGERPRINT_ENROLLED_COUNT, -1))
.isEqualTo(numOfFp);
assertThat(setResult.getData().getExtras().getString(key)).isEqualTo(value);
}
@Test
public void testSetSavedInstanceState() {
final Bundle bundle = new Bundle();
mViewModel.isWaitingActivityResult().set(true);
// setSavedInstanceState() as false
bundle.putBoolean(SAVED_STATE_IS_WAITING_ACTIVITY_RESULT, false);
mViewModel.setSavedInstanceState(bundle);
assertThat(mViewModel.isWaitingActivityResult().get()).isFalse();
// setSavedInstanceState() as false
bundle.putBoolean(SAVED_STATE_IS_WAITING_ACTIVITY_RESULT, true);
mViewModel.setSavedInstanceState(bundle);
assertThat(mViewModel.isWaitingActivityResult().get()).isTrue();
}
@Test
public void testOnSaveInstanceState() {
final Bundle bundle = new Bundle();
// setSavedInstanceState() as false
mViewModel.isWaitingActivityResult().set(false);
mViewModel.onSaveInstanceState(bundle);
assertThat(bundle.getBoolean(SAVED_STATE_IS_WAITING_ACTIVITY_RESULT)).isFalse();
// setSavedInstanceState() as false
mViewModel.isWaitingActivityResult().set(true);
mViewModel.onSaveInstanceState(bundle);
assertThat(bundle.getBoolean(SAVED_STATE_IS_WAITING_ACTIVITY_RESULT)).isTrue();
}
}

View File

@@ -0,0 +1,81 @@
/*
* 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.util;
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY;
import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_DEFERRED_SETUP;
import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_FIRST_RUN;
import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_PORTAL_SETUP;
import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_SETUP_FLOW;
import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW;
import static com.google.android.setupcompat.util.WizardManagerHelper.EXTRA_THEME;
import android.content.Context;
import android.content.Intent;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.android.settings.biometrics2.ui.model.EnrollmentRequest;
public class EnrollmentRequestUtil {
@NonNull
public static EnrollmentRequest newAllFalseRequest(@NonNull Context context) {
return newRequest(context, false, false, false, false, false, false, null);
}
@NonNull
public static EnrollmentRequest newIsSuwRequest(@NonNull Context context) {
return newRequest(context, true, false, false, false, false, false, null);
}
@NonNull
public static EnrollmentRequest newIsSuwDeferredRequest(@NonNull Context context) {
return newRequest(context, true, true, false, false, false, false, null);
}
@NonNull
public static EnrollmentRequest newIsSuwPortalRequest(@NonNull Context context) {
return newRequest(context, true, false, true, false, false, false, null);
}
@NonNull
public static EnrollmentRequest newIsSuwSuggestedActionFlowRequest(
@NonNull Context context) {
return newRequest(context, true, false, false, true, false, false, null);
}
@NonNull
public static EnrollmentRequest newRequest(@NonNull Context context, boolean isSuw,
boolean isSuwDeferred, boolean isSuwPortal, boolean isSuwSuggestedActionFlow,
boolean isSuwFirstRun, boolean isFromSettingsSummery, String theme) {
Intent i = new Intent();
i.putExtra(EXTRA_IS_SETUP_FLOW, isSuw);
i.putExtra(EXTRA_IS_DEFERRED_SETUP, isSuwDeferred);
i.putExtra(EXTRA_IS_PORTAL_SETUP, isSuwPortal);
i.putExtra(EXTRA_IS_SUW_SUGGESTED_ACTION_FLOW, isSuwSuggestedActionFlow);
i.putExtra(EXTRA_IS_FIRST_RUN, isSuwFirstRun);
i.putExtra(EXTRA_FROM_SETTINGS_SUMMARY, isFromSettingsSummery);
if (!TextUtils.isEmpty(theme)) {
i.putExtra(EXTRA_THEME, theme);
}
return new EnrollmentRequest(i, context);
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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.util;
import static org.mockito.Mockito.when;
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 androidx.annotation.NonNull;
import java.util.ArrayList;
public class FingerprintManagerUtil {
public static void setupFingerprintFirstSensor(
@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 */));
when(mockedFingerprintManager.getSensorPropertiesInternal()).thenReturn(props);
}
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,6 +25,7 @@ import com.android.settings.accounts.AccountFeatureProvider;
import com.android.settings.applications.ApplicationFeatureProvider;
import com.android.settings.aware.AwareFeatureProvider;
import com.android.settings.biometrics.face.FaceFeatureProvider;
import com.android.settings.biometrics2.factory.BiometricsRepositoryProvider;
import com.android.settings.bluetooth.BluetoothFeatureProvider;
import com.android.settings.dashboard.DashboardFeatureProvider;
import com.android.settings.dashboard.suggestions.SuggestionFeatureProvider;
@@ -73,6 +74,7 @@ public class FakeFeatureFactory extends FeatureFactory {
public final BluetoothFeatureProvider mBluetoothFeatureProvider;
public final AwareFeatureProvider mAwareFeatureProvider;
public final FaceFeatureProvider mFaceFeatureProvider;
public final BiometricsRepositoryProvider mBiometricsRepositoryProvider;
public PanelFeatureProvider panelFeatureProvider;
public SlicesFeatureProvider slicesFeatureProvider;
@@ -120,6 +122,7 @@ public class FakeFeatureFactory extends FeatureFactory {
mBluetoothFeatureProvider = mock(BluetoothFeatureProvider.class);
mAwareFeatureProvider = mock(AwareFeatureProvider.class);
mFaceFeatureProvider = mock(FaceFeatureProvider.class);
mBiometricsRepositoryProvider = mock(BiometricsRepositoryProvider.class);
wifiTrackerLibProvider = mock(WifiTrackerLibProvider.class);
securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class);
@@ -242,6 +245,11 @@ public class FakeFeatureFactory extends FeatureFactory {
return mFaceFeatureProvider;
}
@Override
public BiometricsRepositoryProvider getBiometricsRepositoryProvider() {
return mBiometricsRepositoryProvider;
}
@Override
public WifiTrackerLibProvider getWifiTrackerLibProvider() {
return wifiTrackerLibProvider;

View File

@@ -0,0 +1,59 @@
/*
* 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.testutils;
import androidx.arch.core.executor.ArchTaskExecutor;
import androidx.arch.core.executor.TaskExecutor;
import org.junit.rules.TestWatcher;
import org.junit.runner.Description;
/**
* A JUnit Test Rule that swaps the background executor used by the Architecture Components with a
* different one which executes each task synchronously.
*
* We can't refer it in prebuilt androidX library.
* Copied it from androidx/arch/core/executor/testing/InstantTaskExecutorRule.java
*/
public class InstantTaskExecutorRule extends TestWatcher {
@Override
protected void starting(Description description) {
super.starting(description);
ArchTaskExecutor.getInstance().setDelegate(new TaskExecutor() {
@Override
public void executeOnDiskIO(Runnable runnable) {
runnable.run();
}
@Override
public void postToMainThread(Runnable runnable) {
runnable.run();
}
@Override
public boolean isMainThread() {
return true;
}
});
}
@Override
protected void finished(Description description) {
super.finished(description);
ArchTaskExecutor.getInstance().setDelegate(null);
}
}