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

Commit 31406c04 authored by Diya Bera's avatar Diya Bera Committed by Android (Google) Code Review
Browse files

Merge "Tests for SUW in work mode" into tm-qpr-dev

parents b5215abd 1021b58a
Loading
Loading
Loading
Loading
+51 −29
Original line number Diff line number Diff line
@@ -24,8 +24,11 @@ import android.hardware.fingerprint.FingerprintManager;
import androidx.annotation.NonNull;
import androidx.fragment.app.FragmentActivity;

import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.password.ChooseLockSettingsHelper;

import java.util.function.Function;

/**
 * Helper for {@link BiometricEnrollActivity} when multiple sensors exist on a device.
 */
@@ -45,14 +48,39 @@ public class MultiBiometricEnrollHelper {
    private final int mUserId;
    private final boolean mRequestEnrollFace;
    private final boolean mRequestEnrollFingerprint;
    private final FingerprintManager mFingerprintManager;
    private final FaceManager mFaceManager;
    private final Intent mFingerprintEnrollIntroductionIntent;
    private final Intent mFaceEnrollIntroductionIntent;
    private Function<Long, byte[]> mGatekeeperHatSupplier;

    @VisibleForTesting
    MultiBiometricEnrollHelper(@NonNull FragmentActivity activity, int userId,
            boolean enrollFace, boolean enrollFingerprint, long gkPwHandle) {
            boolean enrollFace, boolean enrollFingerprint, long gkPwHandle,
            FingerprintManager fingerprintManager,
            FaceManager faceManager, Intent fingerprintEnrollIntroductionIntent,
            Intent faceEnrollIntroductionIntent, Function<Long, byte[]> gatekeeperHatSupplier) {
        mActivity = activity;
        mUserId = userId;
        mGkPwHandle = gkPwHandle;
        mRequestEnrollFace = enrollFace;
        mRequestEnrollFingerprint = enrollFingerprint;
        mFingerprintManager = fingerprintManager;
        mFaceManager = faceManager;
        mFingerprintEnrollIntroductionIntent = fingerprintEnrollIntroductionIntent;
        mFaceEnrollIntroductionIntent = faceEnrollIntroductionIntent;
        mGatekeeperHatSupplier = gatekeeperHatSupplier;
    }

    MultiBiometricEnrollHelper(@NonNull FragmentActivity activity, int userId,
            boolean enrollFace, boolean enrollFingerprint, long gkPwHandle) {
        this(activity, userId, enrollFace, enrollFingerprint, gkPwHandle,
                activity.getSystemService(FingerprintManager.class),
                activity.getSystemService(FaceManager.class),
                BiometricUtils.getFingerprintIntroIntent(activity, activity.getIntent()),
                BiometricUtils.getFaceIntroIntent(activity, activity.getIntent()),
                (challenge) ->  BiometricUtils.requestGatekeeperHat(activity, gkPwHandle,
                        userId, challenge));
    }

    void startNextStep() {
@@ -67,45 +95,39 @@ public class MultiBiometricEnrollHelper {
    }

    private void launchFaceEnroll() {
        final FaceManager faceManager = mActivity.getSystemService(FaceManager.class);
        faceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
            final byte[] hardwareAuthToken = BiometricUtils.requestGatekeeperHat(mActivity,
                    mGkPwHandle, mUserId, challenge);
            final Intent faceIntent = BiometricUtils.getFaceIntroIntent(mActivity,
                    mActivity.getIntent());
            faceIntent.putExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
            faceIntent.putExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
            BiometricUtils.launchEnrollForResult(mActivity, faceIntent, REQUEST_FACE_ENROLL,
                    hardwareAuthToken, mGkPwHandle, mUserId);
        mFaceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
            final byte[] hardwareAuthToken = mGatekeeperHatSupplier.apply(challenge);
            mFaceEnrollIntroductionIntent.putExtra(
                    BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
            mFaceEnrollIntroductionIntent.putExtra(
                    BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
            BiometricUtils.launchEnrollForResult(mActivity, mFaceEnrollIntroductionIntent,
                    REQUEST_FACE_ENROLL, hardwareAuthToken, mGkPwHandle, mUserId);
        });
    }

    private void launchFingerprintEnroll() {
        final FingerprintManager fingerprintManager = mActivity
                .getSystemService(FingerprintManager.class);
        fingerprintManager.generateChallenge(mUserId, ((sensorId, userId, challenge) -> {
            final byte[] hardwareAuthToken = BiometricUtils.requestGatekeeperHat(mActivity,
                    mGkPwHandle, mUserId, challenge);
            final Intent intent = BiometricUtils.getFingerprintIntroIntent(mActivity,
                    mActivity.getIntent());
            intent.putExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
            intent.putExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
        mFingerprintManager.generateChallenge(mUserId, ((sensorId, userId, challenge) -> {
            final byte[] hardwareAuthToken = mGatekeeperHatSupplier.apply(challenge);
            mFingerprintEnrollIntroductionIntent.putExtra(
                    BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
            mFingerprintEnrollIntroductionIntent.putExtra(
                    BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
            if (mRequestEnrollFace) {
                // Give FingerprintEnroll a pendingIntent pointing to face enrollment, so that it
                // can be started when user skips or finishes fingerprint enrollment.
                // FLAG_UPDATE_CURRENT ensures it is launched with the most recent values.
                final Intent faceIntent = BiometricUtils.getFaceIntroIntent(mActivity,
                        mActivity.getIntent());
                faceIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
                faceIntent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
                        mGkPwHandle);
                mFaceEnrollIntroductionIntent.putExtra(Intent.EXTRA_USER_ID, mUserId);
                mFaceEnrollIntroductionIntent.putExtra(
                        ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, mGkPwHandle);
                final PendingIntent faceAfterFp = PendingIntent.getActivity(mActivity,
                        0 /* requestCode */, faceIntent,
                        0 /* requestCode */, mFaceEnrollIntroductionIntent,
                        PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
                intent.putExtra(EXTRA_ENROLL_AFTER_FINGERPRINT, faceAfterFp);
                mFingerprintEnrollIntroductionIntent.putExtra(EXTRA_ENROLL_AFTER_FINGERPRINT,
                        faceAfterFp);
            }
            BiometricUtils.launchEnrollForResult(mActivity, intent, REQUEST_FINGERPRINT_ENROLL,
                    hardwareAuthToken, mGkPwHandle, mUserId);
            BiometricUtils.launchEnrollForResult(mActivity, mFingerprintEnrollIntroductionIntent,
                    REQUEST_FINGERPRINT_ENROLL, hardwareAuthToken, mGkPwHandle, mUserId);
        }));
    }
}
+148 −0
Original line number Diff line number Diff line
/*
 * 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.biometrics;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import static org.robolectric.Shadows.shadowOf;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.RemoteException;

import androidx.fragment.app.FragmentActivity;

import com.android.settings.biometrics.face.FaceEnrollIntroduction;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroduction;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.testutils.shadow.ShadowUtils;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.android.controller.ActivityController;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowPackageManager;

@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
        ShadowUtils.class,
        ShadowUserManager.class,
        ShadowRestrictedLockUtilsInternal.class,
        ShadowSensorPrivacyManager.class,
        ShadowLockPatternUtils.class
})
public class MultiBiometricEnrollHelperTest {
    @Rule
    public final MockitoRule mockito = MockitoJUnit.rule();

    @Mock
    private FragmentActivity mActivity;
    @Mock
    private FingerprintManager mFingerprintManager;
    @Mock
    private FaceManager mFaceManager;

    private Context mContext;

    @Captor
    private ArgumentCaptor<FingerprintManager.GenerateChallengeCallback> mFingerprintCaptor;

    private final int mUserId = 10;
    private final long mChallenge = 0L;
    private final int mSensorId = 0;
    private final long mGkPwHandle = 0L;

    private MultiBiometricEnrollHelper mMultiBiometricEnrollHelper;
    private Intent mFingerprintIntent;
    private Intent mFaceIntent;

    @Before
    public void setUp() throws RemoteException {
        mContext = RuntimeEnvironment.application.getApplicationContext();
        mFingerprintIntent = new Intent(mContext, FingerprintEnrollIntroduction.class);
        mFaceIntent = new Intent(mContext, FaceEnrollIntroduction.class);
        mMultiBiometricEnrollHelper = new MultiBiometricEnrollHelper(
                mActivity, mUserId, true /* enrollFace */, true /* enrollFingerprint */,
                mGkPwHandle, mFingerprintManager, mFaceManager, mFingerprintIntent, mFaceIntent,
                (challenge) -> null);
    }

    @Test
    public void launchFaceAndFingerprintEnroll_testFingerprint() {
        mMultiBiometricEnrollHelper.startNextStep();

        verify(mFingerprintManager).generateChallenge(anyInt(), mFingerprintCaptor.capture());

        FingerprintManager.GenerateChallengeCallback generateChallengeCallback =
                mFingerprintCaptor.getValue();
        generateChallengeCallback.onChallengeGenerated(mSensorId, mUserId, mChallenge);

        assertThat(mFingerprintIntent.hasExtra(
                MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FINGERPRINT)).isTrue();
        assertThat(mFingerprintIntent.getExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID,
                -1 /* defaultValue */)).isEqualTo(mSensorId);
        assertThat(mFingerprintIntent.getExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE,
                -1 /* defaultValue */)).isEqualTo(mChallenge);
        assertThat(mFingerprintIntent.getExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
                -1 /* defaultValue */)).isEqualTo(mGkPwHandle);
    }

    @Test
    public void launchFaceAndFingerprintEnroll_testFace() {
        mMultiBiometricEnrollHelper.startNextStep();

        verify(mFingerprintManager).generateChallenge(anyInt(), mFingerprintCaptor.capture());

        FingerprintManager.GenerateChallengeCallback fingerprintGenerateChallengeCallback =
                mFingerprintCaptor.getValue();
        fingerprintGenerateChallengeCallback.onChallengeGenerated(
                mSensorId, mUserId, mChallenge);

        assertThat(mFaceIntent.getExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE,
                -1 /* defaultValue */)).isEqualTo(mGkPwHandle);
        assertThat(mFaceIntent.getIntExtra(Intent.EXTRA_USER_ID, -1 /* defaultValue */))
                .isEqualTo(mUserId);

        final ShadowPackageManager shadowPackageManager = shadowOf(mContext.getPackageManager());
        shadowPackageManager.setSystemFeature(PackageManager.FEATURE_FACE, true);
        ShadowUtils.setFaceManager(mFaceManager);
        ActivityController.of(new FaceEnrollIntroduction(), mFaceIntent)
                .create(mFaceIntent.getExtras()).get();

        verify(mFaceManager).generateChallenge(eq(mUserId), any());
    }
}