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