From 1021b58ae539fe32c1b6d5433acc8039ad6d30ef Mon Sep 17 00:00:00 2001 From: Diya Bera Date: Thu, 12 Jan 2023 18:18:09 +0000 Subject: [PATCH] Tests for SUW in work mode Bug: 247049655 Test: m RunSettingsRoboTests -j30 ROBOTEST_FILTER=MultiBiometricEnrollHelperTest Change-Id: Ifabb96a90c340bc9306cc0f033ba103c614f32a9 --- .../MultiBiometricEnrollHelper.java | 80 ++++++---- .../MultiBiometricEnrollHelperTest.java | 148 ++++++++++++++++++ 2 files changed, 199 insertions(+), 29 deletions(-) create mode 100644 tests/robotests/src/com/android/settings/biometrics/MultiBiometricEnrollHelperTest.java diff --git a/src/com/android/settings/biometrics/MultiBiometricEnrollHelper.java b/src/com/android/settings/biometrics/MultiBiometricEnrollHelper.java index a994b9564d9..d85f446d1a3 100644 --- a/src/com/android/settings/biometrics/MultiBiometricEnrollHelper.java +++ b/src/com/android/settings/biometrics/MultiBiometricEnrollHelper.java @@ -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 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 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); })); } } diff --git a/tests/robotests/src/com/android/settings/biometrics/MultiBiometricEnrollHelperTest.java b/tests/robotests/src/com/android/settings/biometrics/MultiBiometricEnrollHelperTest.java new file mode 100644 index 00000000000..03b3b48461d --- /dev/null +++ b/tests/robotests/src/com/android/settings/biometrics/MultiBiometricEnrollHelperTest.java @@ -0,0 +1,148 @@ +/* + * 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 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()); + } +}