1 /*
2  * Copyright (C) 2019 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.server.biometrics;
18 
19 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_CREDENTIAL;
20 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
21 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
22 import static android.hardware.biometrics.BiometricManager.Authenticators;
23 import static android.view.DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS;
24 
25 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTHENTICATED_PENDING_SYSUI;
26 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_CALLED;
27 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_PAUSED;
28 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_PAUSED_RESUMING;
29 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_PENDING_CONFIRM;
30 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED;
31 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_CLIENT_DIED_CANCELLING;
32 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_ERROR_PENDING_SYSUI;
33 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_SHOWING_DEVICE_CREDENTIAL;
34 
35 import static junit.framework.Assert.assertEquals;
36 import static junit.framework.Assert.assertFalse;
37 import static junit.framework.Assert.assertTrue;
38 import static junit.framework.TestCase.assertNotNull;
39 
40 import static org.junit.Assert.assertNotEquals;
41 import static org.junit.Assert.assertNull;
42 import static org.mockito.ArgumentMatchers.any;
43 import static org.mockito.ArgumentMatchers.anyBoolean;
44 import static org.mockito.ArgumentMatchers.anyInt;
45 import static org.mockito.ArgumentMatchers.anyLong;
46 import static org.mockito.ArgumentMatchers.anyString;
47 import static org.mockito.ArgumentMatchers.eq;
48 import static org.mockito.Mockito.mock;
49 import static org.mockito.Mockito.never;
50 import static org.mockito.Mockito.verify;
51 import static org.mockito.Mockito.verifyNoMoreInteractions;
52 import static org.mockito.Mockito.when;
53 
54 import android.app.IActivityManager;
55 import android.app.admin.DevicePolicyManager;
56 import android.app.trust.ITrustManager;
57 import android.content.ContentResolver;
58 import android.content.Context;
59 import android.content.pm.UserInfo;
60 import android.content.res.Resources;
61 import android.hardware.biometrics.BiometricAuthenticator;
62 import android.hardware.biometrics.BiometricConstants;
63 import android.hardware.biometrics.BiometricManager;
64 import android.hardware.biometrics.BiometricPrompt;
65 import android.hardware.biometrics.IBiometricAuthenticator;
66 import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
67 import android.hardware.biometrics.IBiometricSensorReceiver;
68 import android.hardware.biometrics.IBiometricService;
69 import android.hardware.biometrics.IBiometricServiceReceiver;
70 import android.hardware.biometrics.IBiometricSysuiReceiver;
71 import android.hardware.biometrics.PromptInfo;
72 import android.hardware.display.DisplayManagerGlobal;
73 import android.hardware.fingerprint.FingerprintManager;
74 import android.os.Binder;
75 import android.os.IBinder;
76 import android.os.RemoteException;
77 import android.os.UserManager;
78 import android.platform.test.annotations.Presubmit;
79 import android.security.KeyStore;
80 import android.view.Display;
81 import android.view.DisplayInfo;
82 import android.view.WindowManager;
83 
84 import androidx.test.InstrumentationRegistry;
85 import androidx.test.filters.SmallTest;
86 
87 import com.android.internal.R;
88 import com.android.internal.statusbar.ISessionListener;
89 import com.android.internal.statusbar.IStatusBarService;
90 import com.android.server.biometrics.log.BiometricContextProvider;
91 import com.android.server.biometrics.sensors.AuthSessionCoordinator;
92 import com.android.server.biometrics.sensors.LockoutTracker;
93 
94 import org.junit.Before;
95 import org.junit.Test;
96 import org.mockito.AdditionalMatchers;
97 import org.mockito.ArgumentCaptor;
98 import org.mockito.Mock;
99 import org.mockito.MockitoAnnotations;
100 
101 import java.util.List;
102 import java.util.Random;
103 
104 @Presubmit
105 @SmallTest
106 public class BiometricServiceTest {
107 
108     private static final String TEST_PACKAGE_NAME = "test_package";
109     private static final long TEST_REQUEST_ID = 44;
110 
111     private static final String ERROR_HW_UNAVAILABLE = "hw_unavailable";
112     private static final String ERROR_NOT_RECOGNIZED = "not_recognized";
113     private static final String ERROR_TIMEOUT = "error_timeout";
114     private static final String ERROR_CANCELED = "error_canceled";
115     private static final String ERROR_UNABLE_TO_PROCESS = "error_unable_to_process";
116     private static final String ERROR_USER_CANCELED = "error_user_canceled";
117     private static final String ERROR_LOCKOUT = "error_lockout";
118     private static final String FACE_SUBTITLE = "face_subtitle";
119     private static final String FINGERPRINT_SUBTITLE = "fingerprint_subtitle";
120     private static final String CREDENTIAL_SUBTITLE = "credential_subtitle";
121     private static final String DEFAULT_SUBTITLE = "default_subtitle";
122 
123     private static final String FINGERPRINT_ACQUIRED_SENSOR_DIRTY = "sensor_dirty";
124 
125     private static final int SENSOR_ID_FINGERPRINT = 0;
126     private static final int SENSOR_ID_FACE = 1;
127 
128     private BiometricService mBiometricService;
129 
130     @Mock
131     private Context mContext;
132     @Mock
133     private ContentResolver mContentResolver;
134     @Mock
135     private Resources mResources;
136     @Mock
137     IBiometricServiceReceiver mReceiver1;
138     @Mock
139     IBiometricServiceReceiver mReceiver2;
140     @Mock
141     BiometricService.Injector mInjector;
142     @Mock
143     IBiometricAuthenticator mFingerprintAuthenticator;
144     @Mock
145     IBiometricAuthenticator mFaceAuthenticator;
146     @Mock
147     IBiometricAuthenticator mCredentialAuthenticator;
148     @Mock
149     ITrustManager mTrustManager;
150     @Mock
151     DevicePolicyManager mDevicePolicyManager;
152     @Mock
153     private WindowManager mWindowManager;
154     @Mock
155     private IStatusBarService mStatusBarService;
156     @Mock
157     private ISessionListener mSessionListener;
158     @Mock
159     private AuthSessionCoordinator mAuthSessionCoordinator;
160     @Mock
161     private UserManager mUserManager;
162     @Mock
163     private BiometricCameraManager mBiometricCameraManager;
164 
165     BiometricContextProvider mBiometricContextProvider;
166 
167     @Before
setUp()168     public void setUp() {
169         MockitoAnnotations.initMocks(this);
170 
171         resetReceivers();
172 
173         when(mContext.getContentResolver()).thenReturn(mContentResolver);
174         when(mContext.getResources()).thenReturn(mResources);
175         when(mContext.getSystemService(Context.DEVICE_POLICY_SERVICE))
176                 .thenReturn(mDevicePolicyManager);
177 
178         when(mInjector.getActivityManagerService()).thenReturn(mock(IActivityManager.class));
179         when(mInjector.getStatusBarService()).thenReturn(mock(IStatusBarService.class));
180         when(mInjector.getSettingObserver(any(), any(), any()))
181                 .thenReturn(mock(BiometricService.SettingObserver.class));
182         when(mInjector.getKeyStore()).thenReturn(mock(KeyStore.class));
183         when(mInjector.isDebugEnabled(any(), anyInt())).thenReturn(false);
184         when(mInjector.getBiometricStrengthController(any()))
185                 .thenReturn(mock(BiometricStrengthController.class));
186         when(mInjector.getTrustManager()).thenReturn(mTrustManager);
187         when(mInjector.getDevicePolicyManager(any())).thenReturn(mDevicePolicyManager);
188         when(mInjector.getRequestGenerator()).thenReturn(() -> TEST_REQUEST_ID);
189         when(mInjector.getUserManager(any())).thenReturn(mUserManager);
190         when(mInjector.getBiometricCameraManager(any())).thenReturn(mBiometricCameraManager);
191 
192         when(mResources.getString(R.string.biometric_error_hw_unavailable))
193                 .thenReturn(ERROR_HW_UNAVAILABLE);
194         when(mResources.getString(R.string.biometric_not_recognized))
195                 .thenReturn(ERROR_NOT_RECOGNIZED);
196         when(mResources.getString(R.string.biometric_face_not_recognized))
197                 .thenReturn(ERROR_NOT_RECOGNIZED);
198         when(mResources.getString(R.string.fingerprint_error_not_match))
199                 .thenReturn(ERROR_NOT_RECOGNIZED);
200         when(mResources.getString(R.string.biometric_error_user_canceled))
201                 .thenReturn(ERROR_USER_CANCELED);
202         when(mContext.getString(R.string.face_dialog_default_subtitle))
203                 .thenReturn(FACE_SUBTITLE);
204         when(mContext.getString(R.string.fingerprint_dialog_default_subtitle))
205                 .thenReturn(FINGERPRINT_SUBTITLE);
206         when(mContext.getString(R.string.screen_lock_dialog_default_subtitle))
207                 .thenReturn(CREDENTIAL_SUBTITLE);
208         when(mContext.getString(R.string.biometric_dialog_default_subtitle))
209                 .thenReturn(DEFAULT_SUBTITLE);
210 
211         when(mWindowManager.getDefaultDisplay()).thenReturn(
212                 new Display(DisplayManagerGlobal.getInstance(), Display.DEFAULT_DISPLAY,
213                         new DisplayInfo(), DEFAULT_DISPLAY_ADJUSTMENTS));
214         mBiometricContextProvider = new BiometricContextProvider(mContext, mWindowManager,
215                 mStatusBarService, null /* handler */,
216                 mAuthSessionCoordinator);
217         when(mInjector.getBiometricContext(any())).thenReturn(mBiometricContextProvider);
218 
219         final String[] config = {
220                 "0:2:15",  // ID0:Fingerprint:Strong
221                 "1:8:15",  // ID1:Face:Strong
222                 "2:4:255", // ID2:Iris:Weak
223         };
224 
225         when(mInjector.getConfiguration(any())).thenReturn(config);
226     }
227 
228     @Test
testClientBinderDied_whenPaused()229     public void testClientBinderDied_whenPaused() throws Exception {
230         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
231 
232         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
233                 true /* requireConfirmation */, null /* authenticators */);
234         waitForIdle();
235         verify(mReceiver1.asBinder()).linkToDeath(eq(mBiometricService.mAuthSession),
236                 anyInt());
237 
238         mBiometricService.mAuthSession.mSensorReceiver.onError(
239                 SENSOR_ID_FACE,
240                 getCookieForCurrentSession(mBiometricService.mAuthSession),
241                 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT,
242                 0 /* vendorCode */);
243         waitForIdle();
244 
245         assertEquals(STATE_AUTH_PAUSED, mBiometricService.mAuthSession.getState());
246 
247         mBiometricService.mAuthSession.binderDied();
248         waitForIdle();
249 
250         assertNull(mBiometricService.mAuthSession);
251         verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(eq(TEST_REQUEST_ID));
252         verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
253     }
254 
255     @Test
testClientBinderDied_whenAuthenticating()256     public void testClientBinderDied_whenAuthenticating() throws Exception {
257         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
258 
259         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
260                 true /* requireConfirmation */, null /* authenticators */);
261         waitForIdle();
262         verify(mReceiver1.asBinder()).linkToDeath(eq(mBiometricService.mAuthSession),
263                 anyInt());
264 
265         assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState());
266         mBiometricService.mAuthSession.binderDied();
267         waitForIdle();
268 
269         assertNotNull(mBiometricService.mAuthSession);
270         verify(mBiometricService.mStatusBarService, never())
271                 .hideAuthenticationDialog(eq(TEST_REQUEST_ID));
272         assertEquals(STATE_CLIENT_DIED_CANCELLING,
273                 mBiometricService.mAuthSession.getState());
274 
275         verify(mBiometricService.mAuthSession.mPreAuthInfo.eligibleSensors.get(0).impl)
276                 .cancelAuthenticationFromService(any(), any(), anyLong());
277 
278         // Simulate ERROR_CANCELED received from HAL
279         mBiometricService.mAuthSession.mSensorReceiver.onError(
280                 SENSOR_ID_FACE,
281                 getCookieForCurrentSession(mBiometricService.mAuthSession),
282                 BiometricConstants.BIOMETRIC_ERROR_CANCELED,
283                 0 /* vendorCode */);
284         waitForIdle();
285         verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(eq(TEST_REQUEST_ID));
286         verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
287         assertNull(mBiometricService.mAuthSession);
288     }
289 
290     @Test
testAuthenticate_credentialAllowedButNotSetup_returnsNoDeviceCredential()291     public void testAuthenticate_credentialAllowedButNotSetup_returnsNoDeviceCredential()
292             throws Exception {
293         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
294                 .thenReturn(false);
295 
296         mBiometricService = new BiometricService(mContext, mInjector);
297         mBiometricService.onStart();
298 
299         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
300                 Authenticators.DEVICE_CREDENTIAL, false /* useDefaultSubtitle */,
301                 false /* deviceCredentialAllowed */);
302         waitForIdle();
303         verify(mReceiver1).onError(
304                 eq(BiometricAuthenticator.TYPE_CREDENTIAL),
305                 eq(BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL),
306                 eq(0 /* vendorCode */));
307     }
308 
309     @Test
testAuthenticate_credentialAllowedAndSetup_callsSystemUI()310     public void testAuthenticate_credentialAllowedAndSetup_callsSystemUI() throws Exception {
311         // When no biometrics are enrolled, but credentials are set up, status bar should be
312         // invoked right away with showAuthenticationDialog
313 
314         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
315                 .thenReturn(true);
316 
317         mBiometricService = new BiometricService(mContext, mInjector);
318         mBiometricService.onStart();
319 
320         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
321                 Authenticators.DEVICE_CREDENTIAL, false /* useDefaultSubtitle */,
322                 false /* deviceCredentialAllowed */);
323         waitForIdle();
324 
325         assertNotNull(mBiometricService.mAuthSession);
326         assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL,
327                 mBiometricService.mAuthSession.getState());
328         // StatusBar showBiometricDialog invoked
329         verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
330                 eq(mBiometricService.mAuthSession.mPromptInfo),
331                 any(IBiometricSysuiReceiver.class),
332                 AdditionalMatchers.aryEq(new int[0]) /* sensorIds */,
333                 eq(true) /* credentialAllowed */,
334                 anyBoolean() /* requireConfirmation */,
335                 anyInt() /* userId */,
336                 anyLong() /* operationId */,
337                 eq(TEST_PACKAGE_NAME),
338                 eq(TEST_REQUEST_ID));
339     }
340 
341     @Test
testAuthenticate_withoutHardware_returnsErrorHardwareNotPresent()342     public void testAuthenticate_withoutHardware_returnsErrorHardwareNotPresent() throws
343             Exception {
344         mBiometricService = new BiometricService(mContext, mInjector);
345         mBiometricService.onStart();
346 
347         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
348                 null /* authenticators */, false /* useDefaultSubtitle */,
349                 false /* deviceCredentialAllowed */);
350         waitForIdle();
351         verify(mReceiver1).onError(
352                 eq(BiometricAuthenticator.TYPE_NONE),
353                 eq(BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT),
354                 eq(0 /* vendorCode */));
355     }
356 
357     @Test
testAuthenticate_withoutEnrolled_returnsErrorNoBiometrics()358     public void testAuthenticate_withoutEnrolled_returnsErrorNoBiometrics() throws Exception {
359         when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true);
360 
361         mBiometricService = new BiometricService(mContext, mInjector);
362         mBiometricService.onStart();
363         mBiometricService.mImpl.registerAuthenticator(0 /* id */,
364                 TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG,
365                 mFingerprintAuthenticator);
366 
367         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
368                 null /* authenticators */, false /* useDefaultSubtitle */,
369                 false /* deviceCredentialAllowed */);
370         waitForIdle();
371         verify(mReceiver1).onError(
372                 eq(TYPE_FINGERPRINT),
373                 eq(BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS),
374                 eq(0 /* vendorCode */));
375     }
376 
377     @Test
testAuthenticate_notStrongEnough_returnsHardwareNotPresent()378     public void testAuthenticate_notStrongEnough_returnsHardwareNotPresent() throws Exception {
379         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_WEAK);
380 
381         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
382                 Authenticators.BIOMETRIC_STRONG, false /* useDefaultSubtitle */,
383                 false /* deviceCredentialAllowed */);
384         waitForIdle();
385         verify(mReceiver1).onError(
386                 eq(BiometricAuthenticator.TYPE_NONE),
387                 eq(BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT),
388                 eq(0 /* vendorCode */));
389     }
390 
391     @Test
testAuthenticate_picksStrongIfAvailable()392     public void testAuthenticate_picksStrongIfAvailable() throws Exception {
393         // If both strong and weak are available, and the caller requires STRONG, authentication
394         // is able to proceed.
395 
396         final int[] modalities = new int[] {
397                 TYPE_FINGERPRINT,
398                 TYPE_FACE,
399         };
400 
401         final int[] strengths = new int[] {
402                 Authenticators.BIOMETRIC_WEAK,
403                 Authenticators.BIOMETRIC_STRONG,
404         };
405 
406         setupAuthForMultiple(modalities, strengths);
407 
408         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
409                 false /* requireConfirmation */, Authenticators.BIOMETRIC_STRONG);
410         waitForIdle();
411         verify(mReceiver1, never()).onError(
412                 anyInt(),
413                 anyInt(),
414                 anyInt() /* vendorCode */);
415 
416         // StatusBar showBiometricDialog invoked with face, which was set up to be STRONG
417         verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
418                 eq(mBiometricService.mAuthSession.mPromptInfo),
419                 any(IBiometricSysuiReceiver.class),
420                 AdditionalMatchers.aryEq(new int[] {SENSOR_ID_FACE}),
421                 eq(false) /* credentialAllowed */,
422                 eq(false) /* requireConfirmation */,
423                 anyInt() /* userId */,
424                 anyLong() /* operationId */,
425                 eq(TEST_PACKAGE_NAME),
426                 eq(TEST_REQUEST_ID));
427     }
428 
429     @Test
testAuthenticate_whenHalIsDead_returnsErrorHardwareUnavailable()430     public void testAuthenticate_whenHalIsDead_returnsErrorHardwareUnavailable() throws
431             Exception {
432         when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
433         when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(false);
434 
435         mBiometricService = new BiometricService(mContext, mInjector);
436         mBiometricService.onStart();
437         mBiometricService.mImpl.registerAuthenticator(0 /* id */,
438                 TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG,
439                 mFingerprintAuthenticator);
440 
441         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
442                 null /* authenticators */, false /* useDefaultSubtitle */,
443                 false /* deviceCredentialAllowed */);
444         waitForIdle();
445         verify(mReceiver1).onError(
446                 eq(TYPE_FINGERPRINT),
447                 eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE),
448                 eq(0 /* vendorCode */));
449     }
450 
451     @Test
testAuthenticateFace_shouldShowSubtitleForFace()452     public void testAuthenticateFace_shouldShowSubtitleForFace() throws Exception {
453         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
454 
455         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
456                 null /* authenticators */, true /* useDefaultSubtitle */,
457                 false /* deviceCredentialAllowed */);
458         waitForIdle();
459 
460         assertEquals(FACE_SUBTITLE, mBiometricService.mAuthSession.mPromptInfo.getSubtitle());
461     }
462 
463     @Test
testAuthenticateFingerprint_shouldShowSubtitleForFingerprint()464     public void testAuthenticateFingerprint_shouldShowSubtitleForFingerprint() throws Exception {
465         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
466 
467         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
468                 null /* authenticators */, true /* useDefaultSubtitle */,
469                 false /* deviceCredentialAllowed */);
470         waitForIdle();
471 
472         assertEquals(FINGERPRINT_SUBTITLE,
473                 mBiometricService.mAuthSession.mPromptInfo.getSubtitle());
474     }
475 
476     @Test
testAuthenticateFingerprint_shouldShowSubtitleForCredential()477     public void testAuthenticateFingerprint_shouldShowSubtitleForCredential() throws Exception {
478         setupAuthForOnly(TYPE_CREDENTIAL, Authenticators.DEVICE_CREDENTIAL);
479 
480         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
481                 null /* authenticators */, true /* useDefaultSubtitle */,
482                 true /* deviceCredentialAllowed */);
483         waitForIdle();
484 
485         assertEquals(CREDENTIAL_SUBTITLE,
486                 mBiometricService.mAuthSession.mPromptInfo.getSubtitle());
487     }
488 
489     @Test
testAuthenticateBothFpAndFace_shouldShowDefaultSubtitle()490     public void testAuthenticateBothFpAndFace_shouldShowDefaultSubtitle() throws Exception {
491         final int[] modalities = new int[] {
492                 TYPE_FINGERPRINT,
493                 TYPE_FACE,
494         };
495 
496         final int[] strengths = new int[] {
497                 Authenticators.BIOMETRIC_WEAK,
498                 Authenticators.BIOMETRIC_STRONG,
499         };
500 
501         setupAuthForMultiple(modalities, strengths);
502 
503         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
504                 null /* authenticators */, true /* useDefaultSubtitle */,
505                 false /* deviceCredentialAllowed */);
506         waitForIdle();
507 
508         assertEquals(DEFAULT_SUBTITLE, mBiometricService.mAuthSession.mPromptInfo.getSubtitle());
509     }
510 
511     @Test
testAuthenticateFace_respectsUserSetting()512     public void testAuthenticateFace_respectsUserSetting()
513             throws Exception {
514         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
515 
516         // Disabled in user settings receives onError
517         when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false);
518         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
519                 null /* authenticators */, false /* useDefaultSubtitle */,
520                 false /* deviceCredentialAllowed */);
521         waitForIdle();
522         verify(mReceiver1).onError(
523                 eq(BiometricAuthenticator.TYPE_NONE),
524                 eq(BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE),
525                 eq(0 /* vendorCode */));
526 
527         // Enrolled, not disabled in settings, user requires confirmation in settings
528         resetReceivers();
529         when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
530         when(mBiometricService.mSettingObserver.getConfirmationAlwaysRequired(
531                 anyInt() /* modality */, anyInt() /* userId */))
532                 .thenReturn(true);
533         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
534                 null /* authenticators */, false /* useDefaultSubtitle */,
535                 false /* deviceCredentialAllowed */);
536         waitForIdle();
537         verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
538         final byte[] HAT = generateRandomHAT();
539         mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationSucceeded(
540                 SENSOR_ID_FACE,
541                 HAT);
542         waitForIdle();
543         // Confirmation is required
544         assertEquals(STATE_AUTH_PENDING_CONFIRM,
545                 mBiometricService.mAuthSession.getState());
546 
547         // Enrolled, not disabled in settings, user doesn't require confirmation in settings
548         resetReceivers();
549         when(mBiometricService.mSettingObserver.getConfirmationAlwaysRequired(
550                 anyInt() /* modality */, anyInt() /* userId */))
551                 .thenReturn(false);
552         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
553                 null /* authenticators */, false /* useDefaultSubtitle */,
554                 false /* deviceCredentialAllowed */);
555         waitForIdle();
556         mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationSucceeded(
557                 SENSOR_ID_FACE,
558                 HAT);
559         waitForIdle();
560         // Confirmation not required, waiting for dialog to dismiss
561         assertEquals(STATE_AUTHENTICATED_PENDING_SYSUI,
562                 mBiometricService.mAuthSession.getState());
563 
564     }
565 
566     @Test
testAuthenticate_happyPathWithoutConfirmation_strongBiometric()567     public void testAuthenticate_happyPathWithoutConfirmation_strongBiometric() throws Exception {
568         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
569         testAuthenticate_happyPathWithoutConfirmation(true /* isStrongBiometric */);
570     }
571 
572     @Test
testAuthenticate_happyPathWithoutConfirmation_weakBiometric()573     public void testAuthenticate_happyPathWithoutConfirmation_weakBiometric() throws Exception {
574         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_WEAK);
575         testAuthenticate_happyPathWithoutConfirmation(false /* isStrongBiometric */);
576     }
577 
testAuthenticate_happyPathWithoutConfirmation(boolean isStrongBiometric)578     private void testAuthenticate_happyPathWithoutConfirmation(boolean isStrongBiometric)
579             throws Exception {
580         // Start testing the happy path
581         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
582                 null /* authenticators */, false /* useDefaultSubtitle */,
583                 false /* deviceCredentialAllowed */);
584         waitForIdle();
585 
586         // Creates a pending auth session with the correct initial states
587         assertEquals(STATE_AUTH_CALLED, mBiometricService.mAuthSession.getState());
588 
589         // Invokes <Modality>Service#prepareForAuthentication
590         ArgumentCaptor<Integer> cookieCaptor = ArgumentCaptor.forClass(Integer.class);
591         verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
592         verify(mBiometricService.mSensors.get(0).impl).prepareForAuthentication(
593                 eq(false) /* requireConfirmation */,
594                 any(IBinder.class),
595                 anyLong() /* sessionId */,
596                 anyInt() /* userId */,
597                 any(IBiometricSensorReceiver.class),
598                 anyString() /* opPackageName */,
599                 eq(TEST_REQUEST_ID),
600                 cookieCaptor.capture() /* cookie */,
601                 anyBoolean() /* allowBackgroundAuthentication */,
602                 anyBoolean() /* isForLegacyFingerprintManager */);
603 
604         // onReadyForAuthentication, mAuthSession state OK
605         mBiometricService.mImpl.onReadyForAuthentication(TEST_REQUEST_ID, cookieCaptor.getValue());
606         waitForIdle();
607         assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState());
608 
609         // startPreparedClient invoked
610         mBiometricService.mAuthSession.onDialogAnimatedIn(true /* startFingerprintNow */);
611         verify(mBiometricService.mSensors.get(0).impl)
612                 .startPreparedClient(cookieCaptor.getValue());
613 
614         // StatusBar showBiometricDialog invoked
615         verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
616                 eq(mBiometricService.mAuthSession.mPromptInfo),
617                 any(IBiometricSysuiReceiver.class),
618                 any(),
619                 eq(false) /* credentialAllowed */,
620                 anyBoolean() /* requireConfirmation */,
621                 anyInt() /* userId */,
622                 anyLong() /* operationId */,
623                 eq(TEST_PACKAGE_NAME),
624                 eq(TEST_REQUEST_ID));
625 
626         // Hardware authenticated
627         final byte[] HAT = generateRandomHAT();
628         mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationSucceeded(
629                 SENSOR_ID_FINGERPRINT,
630                 HAT);
631         waitForIdle();
632         // Waiting for SystemUI to send dismissed callback
633         assertEquals(STATE_AUTHENTICATED_PENDING_SYSUI,
634                 mBiometricService.mAuthSession.getState());
635         // Notify SystemUI hardware authenticated
636         verify(mBiometricService.mStatusBarService).onBiometricAuthenticated(TYPE_FINGERPRINT);
637 
638         // SystemUI sends callback with dismissed reason
639         mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed(
640                 BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED,
641                 null /* credentialAttestation */);
642         waitForIdle();
643         // HAT sent to keystore
644         if (isStrongBiometric) {
645             verify(mBiometricService.mKeyStore).addAuthToken(AdditionalMatchers.aryEq(HAT));
646         } else {
647             verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class));
648         }
649         // Send onAuthenticated to client
650         verify(mReceiver1).onAuthenticationSucceeded(
651                 BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC);
652         // Current session becomes null
653         assertNull(mBiometricService.mAuthSession);
654     }
655 
656     @Test
testAuthenticate_noBiometrics_credentialAllowed()657     public void testAuthenticate_noBiometrics_credentialAllowed() throws Exception {
658         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
659         when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false);
660         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
661                 .thenReturn(true);
662         invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
663                 true /* requireConfirmation */,
664                 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK,
665                 false /* useDefaultSubtitle*/, false /* deviceCredentialAllowed */);
666         waitForIdle();
667 
668         assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL,
669                 mBiometricService.mAuthSession.getState());
670         assertEquals(Authenticators.DEVICE_CREDENTIAL,
671                 mBiometricService.mAuthSession.mPromptInfo.getAuthenticators());
672         verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
673                 eq(mBiometricService.mAuthSession.mPromptInfo),
674                 any(IBiometricSysuiReceiver.class),
675                 AdditionalMatchers.aryEq(new int[0]) /* sensorIds */,
676                 eq(true) /* credentialAllowed */,
677                 anyBoolean() /* requireConfirmation */,
678                 anyInt() /* userId */,
679                 anyLong() /* operationId */,
680                 eq(TEST_PACKAGE_NAME),
681                 eq(TEST_REQUEST_ID));
682     }
683 
684     @Test
testAuthenticate_happyPathWithConfirmation_strongBiometric()685     public void testAuthenticate_happyPathWithConfirmation_strongBiometric() throws Exception {
686         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
687         testAuthenticate_happyPathWithConfirmation(true /* isStrongBiometric */);
688     }
689 
690     @Test
testAuthenticate_happyPathWithConfirmation_weakBiometric()691     public void testAuthenticate_happyPathWithConfirmation_weakBiometric() throws Exception {
692         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_WEAK);
693         testAuthenticate_happyPathWithConfirmation(false /* isStrongBiometric */);
694     }
695 
testAuthenticate_happyPathWithConfirmation(boolean isStrongBiometric)696     private void testAuthenticate_happyPathWithConfirmation(boolean isStrongBiometric)
697             throws Exception {
698         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
699                 true /* requireConfirmation */, null /* authenticators */);
700 
701         // Test authentication succeeded goes to PENDING_CONFIRMATION and that the HAT is not
702         // sent to KeyStore yet
703         final byte[] HAT = generateRandomHAT();
704         mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationSucceeded(
705                 SENSOR_ID_FACE,
706                 HAT);
707         waitForIdle();
708         // Waiting for SystemUI to send confirmation callback
709         assertEquals(STATE_AUTH_PENDING_CONFIRM, mBiometricService.mAuthSession.getState());
710         verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class));
711 
712         // SystemUI sends confirm, HAT is sent to keystore and client is notified.
713         mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed(
714                 BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED,
715                 null /* credentialAttestation */);
716         waitForIdle();
717         if (isStrongBiometric) {
718             verify(mBiometricService.mKeyStore).addAuthToken(AdditionalMatchers.aryEq(HAT));
719         } else {
720             verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class));
721         }
722         verify(mReceiver1).onAuthenticationSucceeded(
723                 BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC);
724     }
725 
726     @Test
testAuthenticate_no_Biometrics_noCredential()727     public void testAuthenticate_no_Biometrics_noCredential() throws Exception {
728         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
729         when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false);
730         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
731                 .thenReturn(false);
732 
733         invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
734                 true /* requireConfirmation */,
735                 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG,
736                 false /* useDefaultSubtitle */, false /* deviceCredentialAllowed */);
737         waitForIdle();
738 
739         verify(mReceiver1).onError(anyInt() /* modality */,
740                 eq(BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS)/* error */,
741                 eq(0) /* vendorCode */);
742     }
743 
744     @Test
testRejectFace_whenAuthenticating_notifiesSystemUIAndClient_thenPaused()745     public void testRejectFace_whenAuthenticating_notifiesSystemUIAndClient_thenPaused()
746             throws Exception {
747         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
748         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
749                 false /* requireConfirmation */, null /* authenticators */);
750 
751         mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationFailed(SENSOR_ID_FACE);
752         waitForIdle();
753 
754         verify(mBiometricService.mStatusBarService).onBiometricError(
755                 eq(TYPE_FACE),
756                 eq(BiometricConstants.BIOMETRIC_PAUSED_REJECTED),
757                 eq(0 /* vendorCode */));
758         verify(mReceiver1).onAuthenticationFailed();
759         assertEquals(STATE_AUTH_PAUSED, mBiometricService.mAuthSession.getState());
760     }
761 
762     @Test
testRejectFingerprint_whenAuthenticating_notifiesAndKeepsAuthenticating()763     public void testRejectFingerprint_whenAuthenticating_notifiesAndKeepsAuthenticating()
764             throws Exception {
765         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
766         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
767                 false /* requireConfirmation */, null /* authenticators */);
768 
769         mBiometricService.mAuthSession.mSensorReceiver
770                 .onAuthenticationFailed(SENSOR_ID_FINGERPRINT);
771         waitForIdle();
772 
773         verify(mBiometricService.mStatusBarService).onBiometricError(
774                 eq(TYPE_FINGERPRINT),
775                 eq(BiometricConstants.BIOMETRIC_PAUSED_REJECTED),
776                 eq(0 /* vendorCode */));
777         verify(mReceiver1).onAuthenticationFailed();
778         assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState());
779     }
780 
781     @Test
testRequestAuthentication_whenAlreadyAuthenticating()782     public void testRequestAuthentication_whenAlreadyAuthenticating() throws Exception {
783         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
784         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
785                 false /* requireConfirmation */, null /* authenticators */);
786 
787         invokeAuthenticate(mBiometricService.mImpl, mReceiver2, false /* requireConfirmation */,
788                 null /* authenticators */, false /* useDefaultSubtitle */,
789                 false /* deviceCredentialAllowed */);
790         waitForIdle();
791 
792         verify(mReceiver1).onError(
793                 eq(TYPE_FACE),
794                 eq(BiometricPrompt.BIOMETRIC_ERROR_CANCELED),
795                 eq(0) /* vendorCode */);
796         verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(eq(TEST_REQUEST_ID));
797 
798         verify(mReceiver2, never()).onError(anyInt(), anyInt(), anyInt());
799     }
800 
801     @Test
testErrorHalTimeout_whenAuthenticating_entersPausedState()802     public void testErrorHalTimeout_whenAuthenticating_entersPausedState() throws Exception {
803         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
804         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
805                 false /* requireConfirmation */, null /* authenticators */);
806 
807         mBiometricService.mAuthSession.mSensorReceiver.onError(
808                 SENSOR_ID_FACE,
809                 getCookieForCurrentSession(mBiometricService.mAuthSession),
810                 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT,
811                 0 /* vendorCode */);
812         waitForIdle();
813 
814         assertEquals(STATE_AUTH_PAUSED, mBiometricService.mAuthSession.getState());
815         verify(mBiometricService.mStatusBarService).onBiometricError(
816                 eq(TYPE_FACE),
817                 eq(BiometricConstants.BIOMETRIC_ERROR_TIMEOUT),
818                 eq(0 /* vendorCode */));
819         // Timeout does not count as fail as per BiometricPrompt documentation.
820         verify(mReceiver1, never()).onAuthenticationFailed();
821 
822         // No auth session. Pressing try again will create one.
823         assertEquals(STATE_AUTH_PAUSED, mBiometricService.mAuthSession.getState());
824 
825         // Pressing "Try again" on SystemUI
826         mBiometricService.mAuthSession.mSysuiReceiver.onTryAgainPressed();
827         waitForIdle();
828         verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
829 
830         // AuthSession is now resuming
831         assertEquals(STATE_AUTH_PAUSED_RESUMING, mBiometricService.mAuthSession.getState());
832 
833         // Test resuming when hardware becomes ready. SystemUI should not be requested to
834         // show another dialog since it's already showing.
835         resetStatusBar();
836         startPendingAuthSession(mBiometricService);
837         waitForIdle();
838         verify(mBiometricService.mStatusBarService, never()).showAuthenticationDialog(
839                 any(PromptInfo.class),
840                 any(IBiometricSysuiReceiver.class),
841                 any() /* sensorIds */,
842                 anyBoolean() /* credentialAllowed */,
843                 anyBoolean() /* requireConfirmation */,
844                 anyInt() /* userId */,
845                 anyLong() /* operationId */,
846                 anyString(),
847                 anyLong() /* requestId */);
848     }
849 
850     @Test
testErrorFromHal_whenPaused_notifiesSystemUIAndClient()851     public void testErrorFromHal_whenPaused_notifiesSystemUIAndClient() throws Exception {
852         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
853         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
854                 false /* requireConfirmation */, null /* authenticators */);
855 
856         mBiometricService.mAuthSession.mSensorReceiver.onError(
857                 SENSOR_ID_FACE,
858                 getCookieForCurrentSession(mBiometricService.mAuthSession),
859                 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT,
860                 0 /* vendorCode */);
861         mBiometricService.mAuthSession.mSensorReceiver.onError(
862                 SENSOR_ID_FACE,
863                 getCookieForCurrentSession(mBiometricService.mAuthSession),
864                 BiometricConstants.BIOMETRIC_ERROR_CANCELED,
865                 0 /* vendorCode */);
866         waitForIdle();
867 
868         // Client receives error immediately
869         verify(mReceiver1).onError(
870                 eq(TYPE_FACE),
871                 eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED),
872                 eq(0 /* vendorCode */));
873         // Dialog is hidden immediately
874         verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(eq(TEST_REQUEST_ID));
875         // Auth session is over
876         assertNull(mBiometricService.mAuthSession);
877     }
878 
879     @Test
testErrorFromHal_whileAuthenticating_waitsForSysUIBeforeNotifyingClient()880     public void testErrorFromHal_whileAuthenticating_waitsForSysUIBeforeNotifyingClient()
881             throws Exception {
882         // For errors that show in SystemUI, BiometricService stays in STATE_ERROR_PENDING_SYSUI
883         // until SystemUI notifies us that the dialog is dismissed at which point the current
884         // session is done.
885         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
886         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
887                 false /* requireConfirmation */, null /* authenticators */);
888 
889         mBiometricService.mAuthSession.mSensorReceiver.onError(
890                 SENSOR_ID_FINGERPRINT,
891                 getCookieForCurrentSession(mBiometricService.mAuthSession),
892                 BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS,
893                 0 /* vendorCode */);
894         waitForIdle();
895 
896         // Sends error to SystemUI and does not notify client yet
897         assertEquals(STATE_ERROR_PENDING_SYSUI, mBiometricService.mAuthSession.getState());
898         verify(mBiometricService.mStatusBarService).onBiometricError(
899                 eq(TYPE_FINGERPRINT),
900                 eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS),
901                 eq(0 /* vendorCode */));
902         verify(mBiometricService.mStatusBarService, never())
903                 .hideAuthenticationDialog(eq(TEST_REQUEST_ID));
904         verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
905 
906         // SystemUI animation completed, client is notified, auth session is over
907         mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed(
908                 BiometricPrompt.DISMISSED_REASON_ERROR, null /* credentialAttestation */);
909         waitForIdle();
910         verify(mReceiver1).onError(
911                 eq(TYPE_FINGERPRINT),
912                 eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS),
913                 eq(0 /* vendorCode */));
914         assertNull(mBiometricService.mAuthSession);
915     }
916 
917     @Test
testErrorFromHal_whilePreparingAuthentication_credentialAllowed()918     public void testErrorFromHal_whilePreparingAuthentication_credentialAllowed() throws Exception {
919         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
920         invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
921                 false /* requireConfirmation */,
922                 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK,
923                 false /* useDefaultSubtitle */, false /* deviceCredentialAllowed */);
924         waitForIdle();
925 
926         assertEquals(STATE_AUTH_CALLED, mBiometricService.mAuthSession.getState());
927         mBiometricService.mAuthSession.mSensorReceiver.onError(
928                 SENSOR_ID_FINGERPRINT,
929                 getCookieForPendingSession(mBiometricService.mAuthSession),
930                 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
931                 0 /* vendorCode */);
932         waitForIdle();
933 
934         // We should be showing device credential now
935         assertNotNull(mBiometricService.mAuthSession);
936         assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL,
937                 mBiometricService.mAuthSession.getState());
938         assertEquals(Authenticators.DEVICE_CREDENTIAL,
939                 mBiometricService.mAuthSession.mPromptInfo.getAuthenticators());
940         verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
941                 eq(mBiometricService.mAuthSession.mPromptInfo),
942                 any(IBiometricSysuiReceiver.class),
943                 AdditionalMatchers.aryEq(new int[0]) /* sensorIds */,
944                 eq(true) /* credentialAllowed */,
945                 anyBoolean() /* requireConfirmation */,
946                 anyInt() /* userId */,
947                 anyLong() /* operationId */,
948                 eq(TEST_PACKAGE_NAME),
949                 eq(TEST_REQUEST_ID));
950     }
951 
952     @Test
testErrorFromHal_whilePreparingAuthentication_credentialNotAllowed()953     public void testErrorFromHal_whilePreparingAuthentication_credentialNotAllowed()
954             throws Exception {
955         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
956         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
957                 null /* authenticators */, false /* useDefaultSubtitle */,
958                 false /* deviceCredentialAllowed */);
959         waitForIdle();
960 
961         mBiometricService.mAuthSession.mSensorReceiver.onError(
962                 SENSOR_ID_FINGERPRINT,
963                 getCookieForPendingSession(mBiometricService.mAuthSession),
964                 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
965                 0 /* vendorCode */);
966         waitForIdle();
967 
968         // Error is sent to client
969         verify(mReceiver1).onError(eq(TYPE_FINGERPRINT),
970                 eq(BiometricConstants.BIOMETRIC_ERROR_LOCKOUT),
971                 eq(0) /* vendorCode */);
972         assertNull(mBiometricService.mAuthSession);
973     }
974 
975     @Test
testBiometricAuth_whenBiometricLockoutTimed_sendsErrorAndModality()976     public void testBiometricAuth_whenBiometricLockoutTimed_sendsErrorAndModality()
977             throws Exception {
978         testBiometricAuth_whenLockout(LockoutTracker.LOCKOUT_TIMED,
979                 BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT);
980     }
981 
982     @Test
testBiometricAuth_whenBiometricLockoutPermanent_sendsErrorAndModality()983     public void testBiometricAuth_whenBiometricLockoutPermanent_sendsErrorAndModality()
984             throws Exception {
985         testBiometricAuth_whenLockout(LockoutTracker.LOCKOUT_PERMANENT,
986                 BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT_PERMANENT);
987     }
988 
testBiometricAuth_whenLockout(@ockoutTracker.LockoutMode int lockoutMode, int biometricPromptError)989     private void testBiometricAuth_whenLockout(@LockoutTracker.LockoutMode int lockoutMode,
990             int biometricPromptError) throws Exception {
991         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
992         when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
993                 .thenReturn(lockoutMode);
994         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
995                 null /* authenticators */, false /* useDefaultSubtitle */,
996                 false /* deviceCredentialAllowed */);
997         waitForIdle();
998 
999         // Modality and error are sent
1000         verify(mReceiver1).onError(eq(TYPE_FINGERPRINT),
1001                 eq(biometricPromptError), eq(0) /* vendorCode */);
1002     }
1003 
1004     @Test
testMultiBiometricAuth_whenLockoutTimed_sendsErrorAndModality()1005     public void testMultiBiometricAuth_whenLockoutTimed_sendsErrorAndModality()
1006             throws Exception {
1007         testMultiBiometricAuth_whenLockout(LockoutTracker.LOCKOUT_TIMED,
1008                 BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT);
1009     }
1010 
1011     @Test
testMultiBiometricAuth_whenLockoutPermanent_sendsErrorAndModality()1012     public void testMultiBiometricAuth_whenLockoutPermanent_sendsErrorAndModality()
1013             throws Exception {
1014         testMultiBiometricAuth_whenLockout(LockoutTracker.LOCKOUT_PERMANENT,
1015                 BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT_PERMANENT);
1016     }
1017 
testMultiBiometricAuth_whenLockout(@ockoutTracker.LockoutMode int lockoutMode, int biometricPromptError)1018     private void testMultiBiometricAuth_whenLockout(@LockoutTracker.LockoutMode int lockoutMode,
1019             int biometricPromptError) throws Exception {
1020         final int[] modalities = new int[] {
1021                 TYPE_FINGERPRINT,
1022                 TYPE_FACE,
1023         };
1024 
1025         final int[] strengths = new int[] {
1026                 Authenticators.BIOMETRIC_STRONG,
1027                 Authenticators.BIOMETRIC_STRONG,
1028         };
1029         setupAuthForMultiple(modalities, strengths);
1030 
1031         when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
1032                 .thenReturn(lockoutMode);
1033         when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(false);
1034         invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
1035                 null /* authenticators */, false /* useDefaultSubtitle */,
1036                 false /* deviceCredentialAllowed */);
1037         waitForIdle();
1038 
1039         // The lockout error should be sent, instead of ERROR_NONE_ENROLLED. See b/286923477.
1040         verify(mReceiver1).onError(eq(TYPE_FINGERPRINT),
1041                 eq(biometricPromptError), eq(0) /* vendorCode */);
1042     }
1043 
1044     @Test
testBiometricOrCredentialAuth_whenBiometricLockout_showsCredential()1045     public void testBiometricOrCredentialAuth_whenBiometricLockout_showsCredential()
1046             throws Exception {
1047         when(mTrustManager.isDeviceSecure(anyInt(), anyInt())).thenReturn(true);
1048         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
1049         when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
1050                 .thenReturn(LockoutTracker.LOCKOUT_PERMANENT);
1051         invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
1052                 false /* requireConfirmation */,
1053                 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_STRONG,
1054                 false /* useDefaultSubtitle */, false /* deviceCredentialAllowed */);
1055         waitForIdle();
1056 
1057         verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
1058         assertNotNull(mBiometricService.mAuthSession);
1059         assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL,
1060                 mBiometricService.mAuthSession.getState());
1061         assertEquals(Authenticators.DEVICE_CREDENTIAL,
1062                 mBiometricService.mAuthSession.mPromptInfo.getAuthenticators());
1063         verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
1064                 eq(mBiometricService.mAuthSession.mPromptInfo),
1065                 any(IBiometricSysuiReceiver.class),
1066                 AdditionalMatchers.aryEq(new int[0]) /* sensorIds */,
1067                 eq(true) /* credentialAllowed */,
1068                 anyBoolean() /* requireConfirmation */,
1069                 anyInt() /* userId */,
1070                 anyLong() /* operationId */,
1071                 eq(TEST_PACKAGE_NAME),
1072                 eq(TEST_REQUEST_ID));
1073     }
1074 
1075     @Test
testCombineAuthenticatorBundles_withKeyDeviceCredential_andKeyAuthenticators()1076     public void testCombineAuthenticatorBundles_withKeyDeviceCredential_andKeyAuthenticators() {
1077         final boolean allowDeviceCredential = false;
1078         final @Authenticators.Types int authenticators =
1079                 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK;
1080         final PromptInfo promptInfo = new PromptInfo();
1081 
1082         promptInfo.setDeviceCredentialAllowed(allowDeviceCredential);
1083         promptInfo.setAuthenticators(authenticators);
1084         Utils.combineAuthenticatorBundles(promptInfo);
1085 
1086         assertFalse(promptInfo.isDeviceCredentialAllowed());
1087         assertEquals(authenticators, promptInfo.getAuthenticators());
1088     }
1089 
1090     @Test
testCombineAuthenticatorBundles_withNoKeyDeviceCredential_andKeyAuthenticators()1091     public void testCombineAuthenticatorBundles_withNoKeyDeviceCredential_andKeyAuthenticators() {
1092         final @Authenticators.Types int authenticators =
1093                 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK;
1094         final PromptInfo promptInfo = new PromptInfo();
1095 
1096         promptInfo.setAuthenticators(authenticators);
1097         Utils.combineAuthenticatorBundles(promptInfo);
1098 
1099         assertFalse(promptInfo.isDeviceCredentialAllowed());
1100         assertEquals(authenticators, promptInfo.getAuthenticators());
1101     }
1102 
1103     @Test
testCombineAuthenticatorBundles_withKeyDeviceCredential_andNoKeyAuthenticators()1104     public void testCombineAuthenticatorBundles_withKeyDeviceCredential_andNoKeyAuthenticators() {
1105         final boolean allowDeviceCredential = true;
1106         final PromptInfo promptInfo = new PromptInfo();
1107 
1108         promptInfo.setDeviceCredentialAllowed(allowDeviceCredential);
1109         Utils.combineAuthenticatorBundles(promptInfo);
1110 
1111         assertFalse(promptInfo.isDeviceCredentialAllowed());
1112         assertEquals(Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK,
1113                 promptInfo.getAuthenticators());
1114     }
1115 
1116     @Test
testCombineAuthenticatorBundles_withNoKeyDeviceCredential_andNoKeyAuthenticators()1117     public void testCombineAuthenticatorBundles_withNoKeyDeviceCredential_andNoKeyAuthenticators() {
1118         final PromptInfo promptInfo = new PromptInfo();
1119 
1120         Utils.combineAuthenticatorBundles(promptInfo);
1121 
1122         assertFalse(promptInfo.isDeviceCredentialAllowed());
1123         assertEquals(Authenticators.BIOMETRIC_WEAK, promptInfo.getAuthenticators());
1124     }
1125 
1126     @Test
testErrorFromHal_whileShowingDeviceCredential_doesntNotifySystemUI()1127     public void testErrorFromHal_whileShowingDeviceCredential_doesntNotifySystemUI()
1128             throws Exception {
1129         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
1130         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
1131                 false /* requireConfirmation */,
1132                 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK);
1133 
1134         mBiometricService.mAuthSession.mSysuiReceiver.onDeviceCredentialPressed();
1135         waitForIdle();
1136 
1137         assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL,
1138                 mBiometricService.mAuthSession.getState());
1139         verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
1140 
1141         mBiometricService.mAuthSession.mSensorReceiver.onError(
1142                 SENSOR_ID_FINGERPRINT,
1143                 getCookieForCurrentSession(mBiometricService.mAuthSession),
1144                 BiometricConstants.BIOMETRIC_ERROR_CANCELED,
1145                 0 /* vendorCode */);
1146         waitForIdle();
1147 
1148         assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL,
1149                 mBiometricService.mAuthSession.getState());
1150         verify(mReceiver1, never()).onError(anyInt(), anyInt(), anyInt());
1151     }
1152 
1153     @Test
testLockout_whileAuthenticating_credentialAllowed()1154     public void testLockout_whileAuthenticating_credentialAllowed() throws Exception {
1155         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
1156         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
1157                 false /* requireConfirmation */,
1158                 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK);
1159 
1160         assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState());
1161 
1162         mBiometricService.mAuthSession.mSensorReceiver.onError(
1163                 SENSOR_ID_FINGERPRINT,
1164                 getCookieForCurrentSession(mBiometricService.mAuthSession),
1165                 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
1166                 0 /* vendorCode */);
1167         waitForIdle();
1168 
1169         assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL,
1170                 mBiometricService.mAuthSession.getState());
1171         verify(mBiometricService.mStatusBarService).onBiometricError(
1172                 eq(TYPE_FINGERPRINT),
1173                 eq(BiometricConstants.BIOMETRIC_ERROR_LOCKOUT),
1174                 eq(0 /* vendorCode */));
1175     }
1176 
1177     @Test
testLockout_whenAuthenticating_credentialNotAllowed()1178     public void testLockout_whenAuthenticating_credentialNotAllowed() throws Exception {
1179         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
1180         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
1181                 false /* requireConfirmation */, null /* authenticators */);
1182 
1183         assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState());
1184 
1185         mBiometricService.mAuthSession.mSensorReceiver.onError(
1186                 SENSOR_ID_FINGERPRINT,
1187                 getCookieForCurrentSession(mBiometricService.mAuthSession),
1188                 BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS,
1189                 0 /* vendorCode */);
1190         waitForIdle();
1191 
1192         assertEquals(STATE_ERROR_PENDING_SYSUI,
1193                 mBiometricService.mAuthSession.getState());
1194         verify(mBiometricService.mStatusBarService).onBiometricError(
1195                 eq(TYPE_FINGERPRINT),
1196                 eq(BiometricConstants.BIOMETRIC_ERROR_UNABLE_TO_PROCESS),
1197                 eq(0 /* vendorCode */));
1198     }
1199 
1200     @Test
testDismissedReasonUserCancel_whileAuthenticating_cancelsHalAuthentication()1201     public void testDismissedReasonUserCancel_whileAuthenticating_cancelsHalAuthentication()
1202             throws Exception {
1203         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
1204         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
1205                 false /* requireConfirmation */, null /* authenticators */);
1206 
1207         mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed(
1208                 BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */);
1209         waitForIdle();
1210         verify(mReceiver1).onError(
1211                 eq(TYPE_FINGERPRINT),
1212                 eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
1213                 eq(0 /* vendorCode */));
1214         verify(mBiometricService.mSensors.get(0).impl).cancelAuthenticationFromService(
1215                 any(), any(), anyLong());
1216         assertNull(mBiometricService.mAuthSession);
1217     }
1218 
1219     @Test
testDismissedReasonNegative_whilePaused_invokeHalCancel()1220     public void testDismissedReasonNegative_whilePaused_invokeHalCancel() throws Exception {
1221         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
1222         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
1223                 false /* requireConfirmation */, null /* authenticators */);
1224 
1225         mBiometricService.mAuthSession.mSensorReceiver.onError(
1226                 SENSOR_ID_FACE,
1227                 getCookieForCurrentSession(mBiometricService.mAuthSession),
1228                 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT,
1229                 0 /* vendorCode */);
1230         mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed(
1231                 BiometricPrompt.DISMISSED_REASON_NEGATIVE, null /* credentialAttestation */);
1232         waitForIdle();
1233 
1234         verify(mBiometricService.mSensors.get(0).impl)
1235                 .cancelAuthenticationFromService(any(), any(), anyLong());
1236     }
1237 
1238     @Test
testDismissedReasonUserCancel_whilePaused_invokesHalCancel()1239     public void testDismissedReasonUserCancel_whilePaused_invokesHalCancel() throws Exception {
1240         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
1241         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
1242                 false /* requireConfirmation */, null /* authenticators */);
1243 
1244         mBiometricService.mAuthSession.mSensorReceiver.onError(
1245                 SENSOR_ID_FACE,
1246                 getCookieForCurrentSession(mBiometricService.mAuthSession),
1247                 BiometricConstants.BIOMETRIC_ERROR_TIMEOUT,
1248                 0 /* vendorCode */);
1249         mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed(
1250                 BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */);
1251         waitForIdle();
1252 
1253         verify(mBiometricService.mSensors.get(0).impl)
1254                 .cancelAuthenticationFromService(any(), any(), anyLong());
1255     }
1256 
1257     @Test
testDismissedReasonUserCancel_whenPendingConfirmation()1258     public void testDismissedReasonUserCancel_whenPendingConfirmation() throws Exception {
1259         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
1260         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
1261                 true /* requireConfirmation */, null /* authenticators */);
1262 
1263         mBiometricService.mAuthSession.mSensorReceiver.onAuthenticationSucceeded(
1264                 SENSOR_ID_FACE,
1265                 new byte[69] /* HAT */);
1266         mBiometricService.mAuthSession.mSysuiReceiver.onDialogDismissed(
1267                 BiometricPrompt.DISMISSED_REASON_USER_CANCEL, null /* credentialAttestation */);
1268         waitForIdle();
1269 
1270         verify(mBiometricService.mSensors.get(0).impl)
1271                 .cancelAuthenticationFromService(any(), any(), anyLong());
1272         verify(mReceiver1).onError(
1273                 eq(TYPE_FACE),
1274                 eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
1275                 eq(0 /* vendorCode */));
1276         verify(mBiometricService.mKeyStore, never()).addAuthToken(any(byte[].class));
1277         assertNull(mBiometricService.mAuthSession);
1278     }
1279 
1280     @Test
testAcquire_whenAuthenticating_sentToSystemUI()1281     public void testAcquire_whenAuthenticating_sentToSystemUI() throws Exception {
1282         when(mContext.getResources().getString(anyInt())).thenReturn("test string");
1283 
1284         final int modality = TYPE_FINGERPRINT;
1285         setupAuthForOnly(modality, Authenticators.BIOMETRIC_STRONG);
1286         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
1287                 false /* requireConfirmation */, null /* authenticators */);
1288 
1289         mBiometricService.mAuthSession.mSensorReceiver.onAcquired(
1290                 SENSOR_ID_FINGERPRINT,
1291                 FingerprintManager.FINGERPRINT_ACQUIRED_IMAGER_DIRTY,
1292                 0 /* vendorCode */);
1293         waitForIdle();
1294 
1295         // Sends to SysUI and stays in authenticating state. We don't test that the correct
1296         // string is retrieved for now, but it's also very unlikely to break anyway.
1297         verify(mBiometricService.mStatusBarService)
1298                 .onBiometricHelp(eq(modality), anyString());
1299         assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState());
1300     }
1301 
1302     @Test
testCancel_whenAuthenticating()1303     public void testCancel_whenAuthenticating() throws Exception {
1304         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
1305         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
1306                 false /* requireConfirmation */, null /* authenticators */);
1307 
1308         mBiometricService.mImpl.cancelAuthentication(mBiometricService.mAuthSession.mToken,
1309                 TEST_PACKAGE_NAME, TEST_REQUEST_ID);
1310         waitForIdle();
1311 
1312         // Pretend that the HAL has responded to cancel with ERROR_CANCELED
1313         mBiometricService.mAuthSession.mSensorReceiver.onError(
1314                 SENSOR_ID_FINGERPRINT,
1315                 getCookieForCurrentSession(mBiometricService.mAuthSession),
1316                 BiometricConstants.BIOMETRIC_ERROR_CANCELED,
1317                 0 /* vendorCode */);
1318         waitForIdle();
1319 
1320         // Hides system dialog and invokes the onError callback
1321         verify(mReceiver1).onError(eq(TYPE_FINGERPRINT),
1322                 eq(BiometricConstants.BIOMETRIC_ERROR_CANCELED),
1323                 eq(0 /* vendorCode */));
1324         verify(mBiometricService.mStatusBarService).hideAuthenticationDialog(eq(TEST_REQUEST_ID));
1325     }
1326 
1327     @Test
testCanAuthenticate_whenDeviceHasRequestedBiometricStrength()1328     public void testCanAuthenticate_whenDeviceHasRequestedBiometricStrength() throws Exception {
1329         // When only biometric is requested, and sensor is strong enough
1330         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
1331 
1332         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
1333                 invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG));
1334     }
1335 
1336     @Test
testCanAuthenticate_whenDeviceDoesNotHaveRequestedBiometricStrength()1337     public void testCanAuthenticate_whenDeviceDoesNotHaveRequestedBiometricStrength()
1338             throws Exception {
1339         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_WEAK);
1340 
1341         // When only biometric is requested, and sensor is not strong enough
1342         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
1343                 .thenReturn(false);
1344         int authenticators = Authenticators.BIOMETRIC_STRONG;
1345         assertEquals(BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE,
1346                 invokeCanAuthenticate(mBiometricService, authenticators));
1347 
1348         // When credential and biometric are requested, and sensor is not strong enough
1349         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
1350                 .thenReturn(true);
1351         authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL;
1352         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
1353                 invokeCanAuthenticate(mBiometricService, authenticators));
1354     }
1355 
1356     @Test
testCanAuthenticate_onlyCredentialRequested()1357     public void testCanAuthenticate_onlyCredentialRequested() throws Exception {
1358         mBiometricService = new BiometricService(mContext, mInjector);
1359         mBiometricService.onStart();
1360 
1361         // Credential requested but not set up
1362         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
1363                 .thenReturn(false);
1364         assertEquals(BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED,
1365                 invokeCanAuthenticate(mBiometricService, Authenticators.DEVICE_CREDENTIAL));
1366 
1367         // Credential requested and set up
1368         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
1369                 .thenReturn(true);
1370         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
1371                 invokeCanAuthenticate(mBiometricService, Authenticators.DEVICE_CREDENTIAL));
1372     }
1373 
1374     @Test
testCanAuthenticate_whenNoBiometricsEnrolled()1375     public void testCanAuthenticate_whenNoBiometricsEnrolled() throws Exception {
1376         // With credential set up, test the following.
1377         when(mTrustManager.isDeviceSecure(anyInt(), anyInt())).thenReturn(true);
1378         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG,
1379                 false /* enrolled */);
1380 
1381         // When only biometric is requested
1382         int authenticators = Authenticators.BIOMETRIC_STRONG;
1383         assertEquals(BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED,
1384                 invokeCanAuthenticate(mBiometricService, authenticators));
1385 
1386         // When credential and biometric are requested
1387         authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL;
1388         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
1389                 invokeCanAuthenticate(mBiometricService, authenticators));
1390     }
1391 
1392     @Test
testCanAuthenticate_whenBiometricsNotEnabledForApps()1393     public void testCanAuthenticate_whenBiometricsNotEnabledForApps() throws Exception {
1394         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
1395         when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(false);
1396         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
1397                 .thenReturn(true);
1398 
1399         // When only biometric is requested
1400         int authenticators = Authenticators.BIOMETRIC_STRONG;
1401         assertEquals(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE,
1402                 invokeCanAuthenticate(mBiometricService, authenticators));
1403 
1404         // When credential and biometric are requested
1405         authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL;
1406         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
1407                 invokeCanAuthenticate(mBiometricService, authenticators));
1408     }
1409 
1410     @Test
testCanAuthenticate_whenNoBiometricSensor()1411     public void testCanAuthenticate_whenNoBiometricSensor() throws Exception {
1412         mBiometricService = new BiometricService(mContext, mInjector);
1413         mBiometricService.onStart();
1414 
1415         // When only biometric is requested
1416         int authenticators = Authenticators.BIOMETRIC_STRONG;
1417         assertEquals(BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE,
1418                 invokeCanAuthenticate(mBiometricService, authenticators));
1419 
1420         // When credential and biometric are requested, and credential is not set up
1421         authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL;
1422         assertEquals(BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED,
1423                 invokeCanAuthenticate(mBiometricService, authenticators));
1424 
1425         // When credential and biometric are requested, and credential is set up
1426         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
1427                 .thenReturn(true);
1428         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
1429                 invokeCanAuthenticate(mBiometricService, authenticators));
1430     }
1431 
1432     @Test
testCanAuthenticate_whenLockoutTimed()1433     public void testCanAuthenticate_whenLockoutTimed() throws Exception {
1434         testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_TIMED);
1435     }
1436 
1437     @Test
testCanAuthenticate_whenLockoutPermanent()1438     public void testCanAuthenticate_whenLockoutPermanent() throws Exception {
1439         testCanAuthenticate_whenLockedOut(LockoutTracker.LOCKOUT_PERMANENT);
1440     }
1441 
testCanAuthenticate_whenLockedOut(@ockoutTracker.LockoutMode int lockoutMode)1442     private void testCanAuthenticate_whenLockedOut(@LockoutTracker.LockoutMode int lockoutMode)
1443             throws Exception {
1444         // When only biometric is requested, and sensor is strong enough
1445         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
1446 
1447         when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
1448                 .thenReturn(lockoutMode);
1449 
1450         // Lockout is not considered an error for BiometricManager#canAuthenticate
1451         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
1452                 invokeCanAuthenticate(mBiometricService, Authenticators.BIOMETRIC_STRONG));
1453     }
1454 
1455     @Test
testAuthenticatorActualStrength()1456     public void testAuthenticatorActualStrength() {
1457         // Tuple of OEM config, updatedStrength, and expectedStrength
1458         final int[][] testCases = {
1459                 // Downgrades to the specified strength
1460                 {Authenticators.BIOMETRIC_STRONG, Authenticators.BIOMETRIC_WEAK,
1461                         Authenticators.BIOMETRIC_WEAK},
1462 
1463                 // Cannot be upgraded
1464                 {Authenticators.BIOMETRIC_WEAK, Authenticators.BIOMETRIC_STRONG,
1465                         Authenticators.BIOMETRIC_WEAK},
1466 
1467                 // Downgrades to convenience
1468                 {Authenticators.BIOMETRIC_WEAK, Authenticators.BIOMETRIC_CONVENIENCE,
1469                         Authenticators.BIOMETRIC_CONVENIENCE},
1470 
1471                 // EMPTY_SET does not modify specified strength
1472                 {Authenticators.BIOMETRIC_WEAK, Authenticators.EMPTY_SET,
1473                         Authenticators.BIOMETRIC_WEAK},
1474         };
1475 
1476         for (int i = 0; i < testCases.length; i++) {
1477             final BiometricSensor sensor =
1478                     new BiometricSensor(mContext, 0 /* id */,
1479                             TYPE_FINGERPRINT,
1480                             testCases[i][0],
1481                             mock(IBiometricAuthenticator.class)) {
1482                         @Override
1483                         boolean confirmationAlwaysRequired(int userId) {
1484                             return false;
1485                         }
1486 
1487                         @Override
1488                         boolean confirmationSupported() {
1489                             return false;
1490                         }
1491                     };
1492             sensor.updateStrength(testCases[i][1]);
1493             assertEquals(testCases[i][2], sensor.getCurrentStrength());
1494         }
1495     }
1496 
1497     @Test
testRegisterAuthenticator_updatesStrengths()1498     public void testRegisterAuthenticator_updatesStrengths() throws Exception {
1499         mBiometricService = new BiometricService(mContext, mInjector);
1500         mBiometricService.onStart();
1501 
1502         verify(mBiometricService.mBiometricStrengthController).startListening();
1503         verify(mBiometricService.mBiometricStrengthController, never()).updateStrengths();
1504 
1505         when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any()))
1506                 .thenReturn(true);
1507         when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true);
1508         mBiometricService.mImpl.registerAuthenticator(0 /* testId */,
1509                 TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG,
1510                 mFingerprintAuthenticator);
1511 
1512         verify(mBiometricService.mBiometricStrengthController).updateStrengths();
1513     }
1514 
1515     @Test
testWithDowngradedAuthenticator()1516     public void testWithDowngradedAuthenticator() throws Exception {
1517         mBiometricService = new BiometricService(mContext, mInjector);
1518         mBiometricService.onStart();
1519 
1520         final int testId = 0;
1521 
1522         when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
1523 
1524         when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any()))
1525                 .thenReturn(true);
1526         when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true);
1527         mBiometricService.mImpl.registerAuthenticator(testId /* id */,
1528                 TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG,
1529                 mFingerprintAuthenticator);
1530 
1531         // Downgrade the authenticator
1532         for (BiometricSensor sensor : mBiometricService.mSensors) {
1533             if (sensor.id == testId) {
1534                 sensor.updateStrength(Authenticators.BIOMETRIC_WEAK);
1535             }
1536         }
1537 
1538         // STRONG-only auth is not available
1539         int authenticators = Authenticators.BIOMETRIC_STRONG;
1540         assertEquals(BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED,
1541                 invokeCanAuthenticate(mBiometricService, authenticators));
1542         long requestId = invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
1543                 false /* requireConfirmation */, authenticators, false /* useDefaultSubtitle */,
1544                 false /* deviceCredentialAllowed */);
1545         waitForIdle();
1546         verify(mReceiver1).onError(
1547                 eq(TYPE_FINGERPRINT),
1548                 eq(BiometricPrompt.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED),
1549                 eq(0) /* vendorCode */);
1550 
1551         // Request for weak auth works
1552         resetReceivers();
1553         authenticators = Authenticators.BIOMETRIC_WEAK;
1554         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
1555                 invokeCanAuthenticate(mBiometricService, authenticators));
1556         requestId = invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
1557                 false /* requireConfirmation */,
1558                 authenticators);
1559         waitForIdle();
1560         verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
1561                 eq(mBiometricService.mAuthSession.mPromptInfo),
1562                 any(IBiometricSysuiReceiver.class),
1563                 AdditionalMatchers.aryEq(new int[] {testId}),
1564                 eq(false) /* credentialAllowed */,
1565                 anyBoolean() /* requireConfirmation */,
1566                 anyInt() /* userId */,
1567                 anyLong() /* operationId */,
1568                 eq(TEST_PACKAGE_NAME),
1569                 eq(requestId));
1570 
1571         // Requesting strong and credential, when credential is setup
1572         resetReceivers();
1573         authenticators = Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL;
1574         when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
1575                 .thenReturn(true);
1576         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
1577                 invokeCanAuthenticate(mBiometricService, authenticators));
1578         requestId = invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
1579                 false /* requireConfirmation */,
1580                 authenticators, false /* useDefaultSubtitle */,
1581                 false /* deviceCredentialAllowed */);
1582         waitForIdle();
1583         assertTrue(Utils.isCredentialRequested(mBiometricService.mAuthSession.mPromptInfo));
1584         verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
1585                 eq(mBiometricService.mAuthSession.mPromptInfo),
1586                 any(IBiometricSysuiReceiver.class),
1587                 AdditionalMatchers.aryEq(new int[0]) /* sensorIds */,
1588                 eq(true) /* credentialAllowed */,
1589                 anyBoolean() /* requireConfirmation */,
1590                 anyInt() /* userId */,
1591                 anyLong() /* operationId */,
1592                 eq(TEST_PACKAGE_NAME),
1593                 eq(requestId));
1594 
1595         // Un-downgrading the authenticator allows successful strong auth
1596         for (BiometricSensor sensor : mBiometricService.mSensors) {
1597             if (sensor.id == testId) {
1598                 sensor.updateStrength(Authenticators.BIOMETRIC_STRONG);
1599             }
1600         }
1601 
1602         resetReceivers();
1603         authenticators = Authenticators.BIOMETRIC_STRONG;
1604         assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
1605                 invokeCanAuthenticate(mBiometricService, authenticators));
1606         requestId = invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
1607                 false /* requireConfirmation */, authenticators);
1608         waitForIdle();
1609         verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
1610                 eq(mBiometricService.mAuthSession.mPromptInfo),
1611                 any(IBiometricSysuiReceiver.class),
1612                 AdditionalMatchers.aryEq(new int[] {testId}) /* sensorIds */,
1613                 eq(false) /* credentialAllowed */,
1614                 anyBoolean() /* requireConfirmation */,
1615                 anyInt() /* userId */,
1616                 anyLong() /* operationId */,
1617                 eq(TEST_PACKAGE_NAME),
1618                 eq(requestId));
1619     }
1620 
1621     @Test(expected = IllegalStateException.class)
testRegistrationWithDuplicateId_throwsIllegalStateException()1622     public void testRegistrationWithDuplicateId_throwsIllegalStateException() throws Exception {
1623         mBiometricService = new BiometricService(mContext, mInjector);
1624         mBiometricService.onStart();
1625 
1626         mBiometricService.mImpl.registerAuthenticator(
1627                 0 /* id */, 2 /* modality */, 15 /* strength */,
1628                 mFingerprintAuthenticator);
1629         mBiometricService.mImpl.registerAuthenticator(
1630                 0 /* id */, 2 /* modality */, 15 /* strength */,
1631                 mFingerprintAuthenticator);
1632     }
1633 
1634     @Test(expected = IllegalArgumentException.class)
testRegistrationWithNullAuthenticator_throwsIllegalArgumentException()1635     public void testRegistrationWithNullAuthenticator_throwsIllegalArgumentException()
1636             throws Exception {
1637         mBiometricService = new BiometricService(mContext, mInjector);
1638         mBiometricService.onStart();
1639 
1640         mBiometricService.mImpl.registerAuthenticator(
1641                 0 /* id */, 2 /* modality */,
1642                 Authenticators.BIOMETRIC_STRONG /* strength */,
1643                 null /* authenticator */);
1644     }
1645 
1646     @Test
testRegistrationHappyPath_isOk()1647     public void testRegistrationHappyPath_isOk() throws Exception {
1648         // This is being tested in many of the other cases, but here's the base case.
1649         mBiometricService = new BiometricService(mContext, mInjector);
1650         mBiometricService.onStart();
1651 
1652         for (String s : mInjector.getConfiguration(null)) {
1653             SensorConfig config = new SensorConfig(s);
1654             mBiometricService.mImpl.registerAuthenticator(config.id, config.modality,
1655                 config.strength, mFingerprintAuthenticator);
1656         }
1657     }
1658 
1659     @Test
testWorkAuthentication_fingerprintWorksIfNotDisabledByDevicePolicyManager()1660     public void testWorkAuthentication_fingerprintWorksIfNotDisabledByDevicePolicyManager()
1661             throws Exception {
1662         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
1663         when(mDevicePolicyManager
1664                 .getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */))
1665                 .thenReturn(~DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
1666         invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1,
1667                 Authenticators.BIOMETRIC_STRONG);
1668         waitForIdle();
1669         assertEquals(STATE_AUTH_CALLED, mBiometricService.mAuthSession.getState());
1670         startPendingAuthSession(mBiometricService);
1671         waitForIdle();
1672         assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState());
1673     }
1674 
1675     @Test
testAuthentication_normalAppIgnoresDevicePolicy()1676     public void testAuthentication_normalAppIgnoresDevicePolicy() throws Exception {
1677         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
1678         when(mDevicePolicyManager
1679                 .getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */))
1680                 .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
1681         invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
1682                 false /* requireConfirmation */, Authenticators.BIOMETRIC_STRONG);
1683         waitForIdle();
1684         assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState());
1685     }
1686 
1687     @Test
testWorkAuthentication_faceWorksIfNotDisabledByDevicePolicyManager()1688     public void testWorkAuthentication_faceWorksIfNotDisabledByDevicePolicyManager()
1689             throws Exception {
1690         setupAuthForOnly(TYPE_FACE, Authenticators.BIOMETRIC_STRONG);
1691         when(mDevicePolicyManager
1692                 .getKeyguardDisabledFeatures(any() /* admin*/, anyInt() /* userHandle */))
1693                 .thenReturn(~DevicePolicyManager.KEYGUARD_DISABLE_FACE);
1694         invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1,
1695                 Authenticators.BIOMETRIC_STRONG);
1696         waitForIdle();
1697         assertEquals(STATE_AUTH_CALLED, mBiometricService.mAuthSession.getState());
1698         startPendingAuthSession(mBiometricService);
1699         waitForIdle();
1700         assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState());
1701     }
1702 
1703     @Test
testWorkAuthentication_fingerprintFailsIfDisabledByDevicePolicyManager()1704     public void testWorkAuthentication_fingerprintFailsIfDisabledByDevicePolicyManager()
1705             throws Exception {
1706         setupAuthForOnly(TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG);
1707         when(mTrustManager.isDeviceSecure(anyInt(), anyInt())).thenReturn(true);
1708         when(mDevicePolicyManager
1709                 .getKeyguardDisabledFeatures(any() /* admin */, anyInt() /* userHandle */))
1710                 .thenReturn(DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT);
1711 
1712         invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver1,
1713                 Authenticators.BIOMETRIC_STRONG);
1714         waitForIdle();
1715         verify(mReceiver1).onError(eq(BiometricAuthenticator.TYPE_NONE),
1716                 eq(BiometricPrompt.BIOMETRIC_ERROR_HW_UNAVAILABLE), eq(0) /* vendorCode */);
1717 
1718         invokeAuthenticateForWorkApp(mBiometricService.mImpl, mReceiver2,
1719                 Authenticators.BIOMETRIC_STRONG | Authenticators.DEVICE_CREDENTIAL);
1720         waitForIdle();
1721         assertNotNull(mBiometricService.mAuthSession);
1722         assertEquals(STATE_SHOWING_DEVICE_CREDENTIAL,
1723                 mBiometricService.mAuthSession.getState());
1724         verify(mReceiver2, never()).onError(anyInt(), anyInt(), anyInt());
1725     }
1726 
1727     @Test
testRegisterEnabledOnKeyguardCallback()1728     public void testRegisterEnabledOnKeyguardCallback() throws RemoteException {
1729         final UserInfo userInfo1 = new UserInfo(0 /* userId */, "user1" /* name */, 0 /* flags */);
1730         final UserInfo userInfo2 = new UserInfo(10 /* userId */, "user2" /* name */, 0 /* flags */);
1731         final List<UserInfo> aliveUsers = List.of(userInfo1, userInfo2);
1732         final IBiometricEnabledOnKeyguardCallback callback =
1733                 mock(IBiometricEnabledOnKeyguardCallback.class);
1734 
1735         mBiometricService = new BiometricService(mContext, mInjector);
1736 
1737         when(mUserManager.getAliveUsers()).thenReturn(aliveUsers);
1738         when(mBiometricService.mSettingObserver.getEnabledOnKeyguard(userInfo1.id))
1739                 .thenReturn(true);
1740         when(mBiometricService.mSettingObserver.getEnabledOnKeyguard(userInfo2.id))
1741                 .thenReturn(false);
1742         when(callback.asBinder()).thenReturn(mock(IBinder.class));
1743 
1744         mBiometricService.mImpl.registerEnabledOnKeyguardCallback(callback);
1745 
1746         waitForIdle();
1747 
1748         verify(callback).asBinder();
1749         verify(callback).onChanged(true, userInfo1.id);
1750         verify(callback).onChanged(false, userInfo2.id);
1751         verifyNoMoreInteractions(callback);
1752     }
1753 
1754     // Helper methods
1755 
invokeCanAuthenticate(BiometricService service, int authenticators)1756     private int invokeCanAuthenticate(BiometricService service, int authenticators)
1757             throws Exception {
1758         return service.mImpl.canAuthenticate(
1759                 TEST_PACKAGE_NAME, 0 /* userId */, 0 /* callingUserId */, authenticators);
1760     }
1761 
setupAuthForOnly(int modality, int strength)1762     private void setupAuthForOnly(int modality, int strength) throws Exception {
1763         setupAuthForOnly(modality, strength, true /* enrolled */);
1764     }
1765 
1766     // TODO: Reconcile the registration strength with the injector
setupAuthForOnly(int modality, int strength, boolean enrolled)1767     private void setupAuthForOnly(int modality, int strength, boolean enrolled) throws Exception {
1768         mBiometricService = new BiometricService(mContext, mInjector);
1769         mBiometricService.onStart();
1770 
1771         when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
1772 
1773         if ((modality & TYPE_FINGERPRINT) != 0) {
1774             when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any()))
1775                     .thenReturn(enrolled);
1776             when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true);
1777             when(mFingerprintAuthenticator.getLockoutModeForUser(anyInt()))
1778                     .thenReturn(LockoutTracker.LOCKOUT_NONE);
1779             mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FINGERPRINT, modality, strength,
1780                     mFingerprintAuthenticator);
1781         }
1782 
1783         if ((modality & TYPE_FACE) != 0) {
1784             when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(enrolled);
1785             when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true);
1786             when(mFaceAuthenticator.getLockoutModeForUser(anyInt()))
1787                     .thenReturn(LockoutTracker.LOCKOUT_NONE);
1788             mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FACE, modality, strength,
1789                     mFaceAuthenticator);
1790         }
1791 
1792         if ((modality & TYPE_CREDENTIAL) != 0) {
1793             when(mTrustManager.isDeviceSecure(anyInt(), anyInt()))
1794                     .thenReturn(true);
1795         }
1796     }
1797 
1798     // TODO: Reduce duplicated code, currently we cannot start the BiometricService in setUp() for
1799     // all tests.
setupAuthForMultiple(int[] modalities, int[] strengths)1800     private void setupAuthForMultiple(int[] modalities, int[] strengths) throws RemoteException {
1801         mBiometricService = new BiometricService(mContext, mInjector);
1802         mBiometricService.onStart();
1803 
1804         when(mBiometricService.mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
1805 
1806         assertEquals(modalities.length, strengths.length);
1807 
1808         for (int i = 0; i < modalities.length; i++) {
1809             final int modality = modalities[i];
1810             final int strength = strengths[i];
1811 
1812             if ((modality & TYPE_FINGERPRINT) != 0) {
1813                 when(mFingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any()))
1814                         .thenReturn(true);
1815                 when(mFingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true);
1816                 mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FINGERPRINT, modality,
1817                         strength, mFingerprintAuthenticator);
1818             }
1819 
1820             if ((modality & TYPE_FACE) != 0) {
1821                 when(mFaceAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
1822                 when(mFaceAuthenticator.isHardwareDetected(any())).thenReturn(true);
1823                 mBiometricService.mImpl.registerAuthenticator(SENSOR_ID_FACE, modality,
1824                         strength, mFaceAuthenticator);
1825             }
1826         }
1827     }
1828 
resetReceivers()1829     private void resetReceivers() {
1830         mReceiver1 = mock(IBiometricServiceReceiver.class);
1831         mReceiver2 = mock(IBiometricServiceReceiver.class);
1832 
1833         when(mReceiver1.asBinder()).thenReturn(mock(Binder.class));
1834         when(mReceiver2.asBinder()).thenReturn(mock(Binder.class));
1835     }
1836 
resetStatusBar()1837     private void resetStatusBar() {
1838         mBiometricService.mStatusBarService = mock(IStatusBarService.class);
1839     }
1840 
invokeAuthenticateAndStart(IBiometricService.Stub service, IBiometricServiceReceiver receiver, boolean requireConfirmation, Integer authenticators)1841     private long invokeAuthenticateAndStart(IBiometricService.Stub service,
1842             IBiometricServiceReceiver receiver, boolean requireConfirmation,
1843             Integer authenticators) throws Exception {
1844         // Request auth, creates a pending session
1845         final long requestId = invokeAuthenticate(
1846                 service, receiver, requireConfirmation, authenticators,
1847                 false /* useDefaultSubtitle */, false /* deviceCredentialAllowed */);
1848         waitForIdle();
1849 
1850         startPendingAuthSession(mBiometricService);
1851         waitForIdle();
1852 
1853         assertNotNull(mBiometricService.mAuthSession);
1854         assertEquals(TEST_REQUEST_ID, mBiometricService.mAuthSession.getRequestId());
1855         assertEquals(STATE_AUTH_STARTED, mBiometricService.mAuthSession.getState());
1856 
1857         return requestId;
1858     }
1859 
startPendingAuthSession(BiometricService service)1860     private static void startPendingAuthSession(BiometricService service) throws Exception {
1861         // Get the cookie so we can pretend the hardware is ready to authenticate
1862         // Currently we only support single modality per auth
1863         final PreAuthInfo preAuthInfo = service.mAuthSession.mPreAuthInfo;
1864         assertEquals(preAuthInfo.eligibleSensors.size(), 1);
1865         assertEquals(preAuthInfo.numSensorsWaitingForCookie(), 1);
1866 
1867         final int cookie = preAuthInfo.eligibleSensors.get(0).getCookie();
1868         assertNotEquals(cookie, 0);
1869 
1870         service.mImpl.onReadyForAuthentication(TEST_REQUEST_ID, cookie);
1871     }
1872 
invokeAuthenticate(IBiometricService.Stub service, IBiometricServiceReceiver receiver, boolean requireConfirmation, Integer authenticators, boolean useDefaultSubtitle, boolean deviceCredentialAllowed)1873     private static long invokeAuthenticate(IBiometricService.Stub service,
1874             IBiometricServiceReceiver receiver, boolean requireConfirmation,
1875             Integer authenticators, boolean useDefaultSubtitle,
1876             boolean deviceCredentialAllowed) throws Exception {
1877         return service.authenticate(
1878                 new Binder() /* token */,
1879                 0 /* operationId */,
1880                 0 /* userId */,
1881                 receiver,
1882                 TEST_PACKAGE_NAME /* packageName */,
1883                 createTestPromptInfo(requireConfirmation, authenticators,
1884                         false /* checkDevicePolicy */, useDefaultSubtitle,
1885                         deviceCredentialAllowed));
1886     }
1887 
invokeAuthenticateForWorkApp(IBiometricService.Stub service, IBiometricServiceReceiver receiver, Integer authenticators)1888     private static long invokeAuthenticateForWorkApp(IBiometricService.Stub service,
1889             IBiometricServiceReceiver receiver, Integer authenticators) throws Exception {
1890         return service.authenticate(
1891                 new Binder() /* token */,
1892                 0 /* operationId */,
1893                 0 /* userId */,
1894                 receiver,
1895                 TEST_PACKAGE_NAME /* packageName */,
1896                 createTestPromptInfo(false /* requireConfirmation */, authenticators,
1897                         true /* checkDevicePolicy */, false /* useDefaultSubtitle */,
1898                         false /* deviceCredentialAllowed */));
1899     }
1900 
createTestPromptInfo( boolean requireConfirmation, Integer authenticators, boolean checkDevicePolicy, boolean useDefaultSubtitle, boolean deviceCredentialAllowed)1901     private static PromptInfo createTestPromptInfo(
1902             boolean requireConfirmation,
1903             Integer authenticators,
1904             boolean checkDevicePolicy,
1905             boolean useDefaultSubtitle,
1906             boolean deviceCredentialAllowed) {
1907         final PromptInfo promptInfo = new PromptInfo();
1908         promptInfo.setConfirmationRequested(requireConfirmation);
1909         promptInfo.setUseDefaultSubtitle(useDefaultSubtitle);
1910 
1911         if (authenticators != null) {
1912             promptInfo.setAuthenticators(authenticators);
1913         }
1914         if (checkDevicePolicy) {
1915             promptInfo.setDisallowBiometricsIfPolicyExists(checkDevicePolicy);
1916         }
1917         promptInfo.setDeviceCredentialAllowed(deviceCredentialAllowed);
1918         return promptInfo;
1919     }
1920 
getCookieForCurrentSession(AuthSession session)1921     private static int getCookieForCurrentSession(AuthSession session) {
1922         // Currently only tests authentication with a single sensor
1923         final PreAuthInfo preAuthInfo = session.mPreAuthInfo;
1924 
1925         assertEquals(preAuthInfo.eligibleSensors.size(), 1);
1926         return preAuthInfo.eligibleSensors.get(0).getCookie();
1927     }
1928 
getCookieForPendingSession(AuthSession session)1929     private static int getCookieForPendingSession(AuthSession session) {
1930         // Currently only tests authentication with a single sensor
1931         final PreAuthInfo requestWrapper = session.mPreAuthInfo;
1932 
1933         assertEquals(requestWrapper.eligibleSensors.size(), 1);
1934         assertEquals(requestWrapper.eligibleSensors.get(0).getSensorState(),
1935                 BiometricSensor.STATE_WAITING_FOR_COOKIE);
1936         return requestWrapper.eligibleSensors.get(0).getCookie();
1937     }
1938 
waitForIdle()1939     private static void waitForIdle() {
1940         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
1941     }
1942 
generateRandomHAT()1943     private byte[] generateRandomHAT() {
1944         byte[] HAT = new byte[69];
1945         Random random = new Random();
1946         random.nextBytes(HAT);
1947         return HAT;
1948     }
1949 }
1950