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