1 /* 2 * Copyright (C) 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.biometrics; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.ArgumentMatchers.any; 22 import static org.mockito.ArgumentMatchers.anyInt; 23 import static org.mockito.ArgumentMatchers.eq; 24 import static org.mockito.Mockito.verify; 25 import static org.robolectric.Shadows.shadowOf; 26 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.pm.PackageManager; 30 import android.hardware.face.FaceManager; 31 import android.hardware.fingerprint.FingerprintManager; 32 import android.os.RemoteException; 33 34 import androidx.fragment.app.FragmentActivity; 35 36 import com.android.settings.biometrics.face.FaceEnrollIntroduction; 37 import com.android.settings.biometrics.fingerprint.FingerprintEnrollIntroduction; 38 import com.android.settings.password.ChooseLockSettingsHelper; 39 import com.android.settings.testutils.shadow.ShadowLockPatternUtils; 40 import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal; 41 import com.android.settings.testutils.shadow.ShadowSensorPrivacyManager; 42 import com.android.settings.testutils.shadow.ShadowUserManager; 43 import com.android.settings.testutils.shadow.ShadowUtils; 44 45 import org.junit.Before; 46 import org.junit.Rule; 47 import org.junit.Test; 48 import org.junit.runner.RunWith; 49 import org.mockito.ArgumentCaptor; 50 import org.mockito.Captor; 51 import org.mockito.Mock; 52 import org.mockito.junit.MockitoJUnit; 53 import org.mockito.junit.MockitoRule; 54 import org.robolectric.RobolectricTestRunner; 55 import org.robolectric.RuntimeEnvironment; 56 import org.robolectric.android.controller.ActivityController; 57 import org.robolectric.annotation.Config; 58 import org.robolectric.shadows.ShadowPackageManager; 59 60 @RunWith(RobolectricTestRunner.class) 61 @Config(shadows = { 62 ShadowUtils.class, 63 ShadowUserManager.class, 64 ShadowRestrictedLockUtilsInternal.class, 65 ShadowSensorPrivacyManager.class, 66 ShadowLockPatternUtils.class 67 }) 68 public class MultiBiometricEnrollHelperTest { 69 @Rule 70 public final MockitoRule mockito = MockitoJUnit.rule(); 71 72 @Mock 73 private FragmentActivity mActivity; 74 @Mock 75 private FingerprintManager mFingerprintManager; 76 @Mock 77 private FaceManager mFaceManager; 78 79 private Context mContext; 80 81 @Captor 82 private ArgumentCaptor<FingerprintManager.GenerateChallengeCallback> mFingerprintCaptor; 83 84 private final int mUserId = 10; 85 private final long mChallenge = 0L; 86 private final int mSensorId = 0; 87 private final long mGkPwHandle = 0L; 88 89 private MultiBiometricEnrollHelper mMultiBiometricEnrollHelper; 90 private Intent mFingerprintIntent; 91 private Intent mFaceIntent; 92 93 @Before setUp()94 public void setUp() throws RemoteException { 95 mContext = RuntimeEnvironment.application.getApplicationContext(); 96 mFingerprintIntent = new Intent(mContext, FingerprintEnrollIntroduction.class); 97 mFaceIntent = new Intent(mContext, FaceEnrollIntroduction.class); 98 mMultiBiometricEnrollHelper = new MultiBiometricEnrollHelper( 99 mActivity, mUserId, true /* enrollFace */, true /* enrollFingerprint */, 100 mGkPwHandle, mFingerprintManager, mFaceManager, mFingerprintIntent, mFaceIntent, 101 (challenge) -> null); 102 } 103 104 @Test launchFaceAndFingerprintEnroll_testFingerprint()105 public void launchFaceAndFingerprintEnroll_testFingerprint() { 106 mMultiBiometricEnrollHelper.startNextStep(); 107 108 verify(mFingerprintManager).generateChallenge(anyInt(), mFingerprintCaptor.capture()); 109 110 FingerprintManager.GenerateChallengeCallback generateChallengeCallback = 111 mFingerprintCaptor.getValue(); 112 generateChallengeCallback.onChallengeGenerated(mSensorId, mUserId, mChallenge); 113 114 assertThat(mFingerprintIntent.hasExtra( 115 MultiBiometricEnrollHelper.EXTRA_ENROLL_AFTER_FINGERPRINT)).isTrue(); 116 assertThat(mFingerprintIntent.getExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, 117 -1 /* defaultValue */)).isEqualTo(mSensorId); 118 assertThat(mFingerprintIntent.getExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, 119 -1 /* defaultValue */)).isEqualTo(mChallenge); 120 assertThat(mFingerprintIntent.getExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 121 -1 /* defaultValue */)).isEqualTo(mGkPwHandle); 122 } 123 124 @Test launchFaceAndFingerprintEnroll_testFace()125 public void launchFaceAndFingerprintEnroll_testFace() { 126 mMultiBiometricEnrollHelper.startNextStep(); 127 128 verify(mFingerprintManager).generateChallenge(anyInt(), mFingerprintCaptor.capture()); 129 130 FingerprintManager.GenerateChallengeCallback fingerprintGenerateChallengeCallback = 131 mFingerprintCaptor.getValue(); 132 fingerprintGenerateChallengeCallback.onChallengeGenerated( 133 mSensorId, mUserId, mChallenge); 134 135 assertThat(mFaceIntent.getExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 136 -1 /* defaultValue */)).isEqualTo(mGkPwHandle); 137 assertThat(mFaceIntent.getIntExtra(Intent.EXTRA_USER_ID, -1 /* defaultValue */)) 138 .isEqualTo(mUserId); 139 140 final ShadowPackageManager shadowPackageManager = shadowOf(mContext.getPackageManager()); 141 shadowPackageManager.setSystemFeature(PackageManager.FEATURE_FACE, true); 142 ShadowUtils.setFaceManager(mFaceManager); 143 ActivityController.of(new FaceEnrollIntroduction(), mFaceIntent) 144 .create(mFaceIntent.getExtras()).get(); 145 146 verify(mFaceManager).generateChallenge(eq(mUserId), any()); 147 } 148 } 149