Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ab488b3c authored by Milton Wu's avatar Milton Wu
Browse files

Add biometrics v2 test

Add tests into FingerprintEnrollFinishViewModelTest and
FingerprintEnrollProgressViewModelTest. and also remove mDoneLiveData
from FingerprintEnrollProgressViewModel because no one uses it.

Bug: 271220339
Test: atest FingerprintEnrollFinishViewModelTest
      FingerprintEnrollProgressViewModelTest
Change-Id: Id74da29b7730a3e7feb8d0b263c28c8192adad9c
parent 3a4c6feb
Loading
Loading
Loading
Loading
+0 −12
Original line number Diff line number Diff line
@@ -58,7 +58,6 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
    private final MutableLiveData<Boolean> mAcquireLiveData = new MutableLiveData<>();
    private final MutableLiveData<Integer> mPointerDownLiveData = new MutableLiveData<>();
    private final MutableLiveData<Integer> mPointerUpLiveData = new MutableLiveData<>();
    private final MutableLiveData<Boolean> mDoneLiveData = new MutableLiveData<>(false);

    private byte[] mToken = null;
    private final int mUserId;
@@ -78,11 +77,6 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
                        + ", post progress as " + progress);
            }
            mProgressLiveData.postValue(progress);

            final Boolean done = remaining == 0;
            if (!done.equals(mDoneLiveData.getValue())) {
                mDoneLiveData.postValue(done);
            }
        }

        @Override
@@ -143,7 +137,6 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
     * clear progress
     */
    public void clearProgressLiveData() {
        mDoneLiveData.setValue(false);
        mProgressLiveData.setValue(new EnrollmentProgress(INITIAL_STEPS, INITIAL_REMAINING));
        mHelpMessageLiveData.setValue(null);
        mErrorMessageLiveData.setValue(null);
@@ -180,10 +173,6 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {
        return mPointerUpLiveData;
    }

    public LiveData<Boolean> getDoneLiveData() {
        return mDoneLiveData;
    }

    /**
     * Starts enrollment and return latest isEnrolling() result
     */
@@ -202,7 +191,6 @@ public class FingerprintEnrollProgressViewModel extends AndroidViewModel {

        // Clear data
        mProgressLiveData.setValue(new EnrollmentProgress(INITIAL_STEPS, INITIAL_REMAINING));
        mDoneLiveData.setValue(false);
        mHelpMessageLiveData.setValue(null);
        mErrorMessageLiveData.setValue(null);

+134 −0
Original line number Diff line number Diff line
/*
 * 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);
        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();
    }
}
+134 −34
Original line number Diff line number Diff line
@@ -36,11 +36,13 @@ import android.app.Application;
import android.content.res.Resources;
import android.os.CancellationSignal;

import androidx.lifecycle.LiveData;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.android.settings.R;
import com.android.settings.biometrics.fingerprint.FingerprintUpdater;
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;
@@ -64,6 +66,8 @@ public class FingerprintEnrollProgressViewModelTest {
    @Mock private FingerprintUpdater mFingerprintUpdater;

    private FingerprintEnrollProgressViewModel mViewModel;
    private final TestWrapper<CancellationSignal> mCancellationSignalWrapper = new TestWrapper<>();
    private final TestWrapper<EnrollmentCallback> mCallbackWrapper = new TestWrapper<>();

    @Before
    public void setUp() {
@@ -72,6 +76,15 @@ public class FingerprintEnrollProgressViewModelTest {
                .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());
    }

    @Test
@@ -100,64 +113,151 @@ public class FingerprintEnrollProgressViewModelTest {

    @Test
    public void testCancelEnrollment() {
        @EnrollReason final int enrollReason = ENROLL_ENROLL;
        final byte[] token = new byte[] { 1, 2, 3 };
        mViewModel.setToken(token);

        final TestWrapper<CancellationSignal> signalWrapper = new TestWrapper<>();
        doAnswer(invocation -> {
            signalWrapper.mValue = invocation.getArgument(1);
            return null;
        }).when(mFingerprintUpdater).enroll(any(byte[].class), any(CancellationSignal.class),
                eq(TEST_USER_ID), any(EnrollmentCallback.class), anyInt());

        // Start enrollment
        final boolean ret = mViewModel.startEnrollment(enrollReason);
        mViewModel.setToken(new byte[] { 1, 2, 3 });
        final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
        assertThat(ret).isTrue();
        assertThat(signalWrapper.mValue).isNotNull();
        assertThat(mCancellationSignalWrapper.mValue).isNotNull();

        // Cancel enrollment
        mViewModel.cancelEnrollment();

        assertThat(signalWrapper.mValue.isCanceled()).isTrue();
        assertThat(mCancellationSignalWrapper.mValue.isCanceled()).isTrue();
    }

    @Test
    public void testProgressUpdate() {
        @EnrollReason final int enrollReason = ENROLL_ENROLL;
        final byte[] token = new byte[] { 1, 2, 3 };
        mViewModel.setToken(token);

        final TestWrapper<EnrollmentCallback> callbackWrapper = new TestWrapper<>();
        doAnswer(invocation -> {
            callbackWrapper.mValue = invocation.getArgument(3);
            return null;
        }).when(mFingerprintUpdater).enroll(any(byte[].class), any(CancellationSignal.class),
                eq(TEST_USER_ID), any(EnrollmentCallback.class), anyInt());

        // Start enrollment
        final boolean ret = mViewModel.startEnrollment(enrollReason);
        mViewModel.setToken(new byte[] { 1, 2, 3 });
        final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
        assertThat(ret).isTrue();
        assertThat(callbackWrapper.mValue).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
        callbackWrapper.mValue.onEnrollmentProgress(25);
        EnrollmentProgress progress = mViewModel.getProgressLiveData().getValue();
        mCallbackWrapper.mValue.onEnrollmentProgress(25);
        progress = progressLiveData.getValue();
        assertThat(progress).isNotNull();
        assertThat(progress.getSteps()).isEqualTo(25);
        assertThat(progress.getRemaining()).isEqualTo(25);

        // Update second progress
        callbackWrapper.mValue.onEnrollmentProgress(20);
        progress = mViewModel.getProgressLiveData().getValue();
        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 boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
        assertThat(ret).isTrue();
        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 boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
        assertThat(ret).isTrue();
        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);
    }

    // TODO(b/260957933): FingerprintEnrollProgressViewModel::getErrorLiveData() and
    // FingerprintEnrollProgressViewModel::getHelpLiveData() doesn't built into apk because no one
    // uses it. We shall test it when new FingerprintEnrollEnrolling has used these 2 methods.
    @Test
    public void testGetAcquireLiveData() {
        // Start enrollment
        mViewModel.setToken(new byte[] { 1, 2, 3 });
        final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
        assertThat(ret).isTrue();
        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 boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
        assertThat(ret).isTrue();
        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.onPointerDown(value);
        assertThat(liveData.getValue()).isEqualTo(value);
    }

    @Test
    public void testGetPointerUpLiveData() {
        // Start enrollment
        mViewModel.setToken(new byte[] { 1, 2, 3 });
        final boolean ret = mViewModel.startEnrollment(ENROLL_ENROLL);
        assertThat(ret).isTrue();
        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.onPointerUp(value);
        assertThat(liveData.getValue()).isEqualTo(value);
    }

    private static class TestWrapper<T> {
        T mValue;