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