1 /*
2  * Copyright (C) 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.biometrics;
18 
19 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
20 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
21 import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_NEGATIVE_BUTTON;
22 import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED;
23 import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED;
24 import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_NEGATIVE;
25 import static android.hardware.biometrics.BiometricPrompt.DISMISSED_REASON_USER_CANCEL;
26 
27 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_CALLED;
28 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_PAUSED;
29 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED;
30 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_AUTH_STARTED_UI_SHOWING;
31 import static com.android.server.biometrics.BiometricServiceStateProto.STATE_ERROR_PENDING_SYSUI;
32 
33 import static com.google.common.truth.Truth.assertThat;
34 
35 import static junit.framework.Assert.assertEquals;
36 import static junit.framework.Assert.assertFalse;
37 import static junit.framework.Assert.assertTrue;
38 
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.anyObject;
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.times;
48 import static org.mockito.Mockito.verify;
49 import static org.mockito.Mockito.when;
50 
51 import android.annotation.NonNull;
52 import android.app.admin.DevicePolicyManager;
53 import android.app.trust.ITrustManager;
54 import android.content.res.Resources;
55 import android.hardware.biometrics.BiometricConstants;
56 import android.hardware.biometrics.BiometricManager;
57 import android.hardware.biometrics.BiometricManager.Authenticators;
58 import android.hardware.biometrics.BiometricsProtoEnums;
59 import android.hardware.biometrics.ComponentInfoInternal;
60 import android.hardware.biometrics.IBiometricAuthenticator;
61 import android.hardware.biometrics.IBiometricSensorReceiver;
62 import android.hardware.biometrics.IBiometricServiceReceiver;
63 import android.hardware.biometrics.IBiometricSysuiReceiver;
64 import android.hardware.biometrics.PromptInfo;
65 import android.hardware.biometrics.SensorProperties;
66 import android.hardware.fingerprint.FingerprintManager;
67 import android.hardware.fingerprint.FingerprintSensorProperties;
68 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
69 import android.os.Binder;
70 import android.os.IBinder;
71 import android.os.RemoteException;
72 import android.platform.test.annotations.Presubmit;
73 import android.security.KeyStoreAuthorization;
74 import android.testing.TestableContext;
75 
76 import androidx.test.filters.SmallTest;
77 import androidx.test.platform.app.InstrumentationRegistry;
78 
79 import com.android.internal.R;
80 import com.android.internal.statusbar.IStatusBarService;
81 import com.android.internal.util.FrameworkStatsLog;
82 import com.android.server.biometrics.log.BiometricContext;
83 import com.android.server.biometrics.log.BiometricFrameworkStatsLogger;
84 import com.android.server.biometrics.log.OperationContextExt;
85 
86 import org.junit.Before;
87 import org.junit.Rule;
88 import org.junit.Test;
89 import org.mockito.Mock;
90 import org.mockito.MockitoAnnotations;
91 
92 import java.util.ArrayList;
93 import java.util.List;
94 import java.util.Random;
95 import java.util.function.Consumer;
96 
97 @Presubmit
98 @SmallTest
99 public class AuthSessionTest {
100 
101     private static final String TEST_PACKAGE = "test_package";
102     private static final long TEST_REQUEST_ID = 22;
103     private static final String ACQUIRED_STRING = "test_acquired_info_callback";
104     private static final String ACQUIRED_STRING_VENDOR = "test_acquired_info_callback_vendor";
105 
106     @Rule
107     public final TestableContext mContext = new TestableContext(
108             InstrumentationRegistry.getInstrumentation().getTargetContext(), null);
109     @Mock private Resources mResources;
110     @Mock private BiometricContext mBiometricContext;
111     @Mock private ITrustManager mTrustManager;
112     @Mock private DevicePolicyManager mDevicePolicyManager;
113     @Mock private BiometricService.SettingObserver mSettingObserver;
114     @Mock private IBiometricSensorReceiver mSensorReceiver;
115     @Mock private IBiometricServiceReceiver mClientReceiver;
116     @Mock private IStatusBarService mStatusBarService;
117     @Mock private IBiometricSysuiReceiver mSysuiReceiver;
118     @Mock private KeyStoreAuthorization mKeyStoreAuthorization;
119     @Mock private AuthSession.ClientDeathReceiver mClientDeathReceiver;
120     @Mock private BiometricFrameworkStatsLogger mBiometricFrameworkStatsLogger;
121     @Mock private BiometricCameraManager mBiometricCameraManager;
122     @Mock private BiometricManager mBiometricManager;
123 
124     private Random mRandom;
125     private IBinder mToken;
126 
127     // Assume all tests can be done with the same set of sensors for now.
128     @NonNull private List<BiometricSensor> mSensors;
129     @NonNull private List<FingerprintSensorPropertiesInternal> mFingerprintSensorProps;
130 
131     @Before
setUp()132     public void setUp() throws Exception {
133         MockitoAnnotations.initMocks(this);
134         mContext.addMockSystemService(BiometricManager.class, mBiometricManager);
135         mContext.getOrCreateTestableResources().addOverride(R.string.fingerprint_acquired_partial,
136                 ACQUIRED_STRING);
137         mContext.getOrCreateTestableResources().addOverride(R.array.fingerprint_acquired_vendor,
138                 new String[]{ACQUIRED_STRING_VENDOR});
139         when(mClientReceiver.asBinder()).thenReturn(mock(Binder.class));
140         when(mBiometricContext.updateContext(any(), anyBoolean()))
141                 .thenAnswer(invocation -> invocation.getArgument(0));
142         mRandom = new Random();
143         mToken = new Binder();
144         mSensors = new ArrayList<>();
145         mFingerprintSensorProps = new ArrayList<>();
146     }
147 
148     @Test
testNewAuthSession_eligibleSensorsSetToStateUnknown()149     public void testNewAuthSession_eligibleSensorsSetToStateUnknown() throws RemoteException {
150         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_REAR);
151         setupFace(1 /* id */, false /* confirmationAlwaysRequired */,
152                 mock(IBiometricAuthenticator.class));
153 
154         final AuthSession session = createAuthSession(mSensors,
155                 false /* checkDevicePolicyManager */,
156                 Authenticators.BIOMETRIC_STRONG,
157                 TEST_REQUEST_ID,
158                 0 /* operationId */,
159                 0 /* userId */);
160 
161         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
162             assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState());
163         }
164     }
165 
166     @Test
testStartNewAuthSession()167     public void testStartNewAuthSession() throws RemoteException {
168         setupFace(0 /* id */, false /* confirmationAlwaysRequired */,
169                 mock(IBiometricAuthenticator.class));
170         setupFingerprint(1 /* id */, FingerprintSensorProperties.TYPE_REAR);
171 
172         final boolean requireConfirmation = true;
173         final long operationId = 123;
174         final int userId = 10;
175 
176         final AuthSession session = createAuthSession(mSensors,
177                 false /* checkDevicePolicyManager */,
178                 Authenticators.BIOMETRIC_STRONG,
179                 TEST_REQUEST_ID,
180                 operationId,
181                 userId);
182         assertEquals(mSensors.size(), session.mPreAuthInfo.eligibleSensors.size());
183 
184         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
185             assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState());
186             assertEquals(0, sensor.getCookie());
187         }
188 
189         session.goToInitialState();
190         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
191             assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState());
192             assertTrue("Cookie must be >0", sensor.getCookie() > 0);
193             verify(sensor.impl).prepareForAuthentication(
194                     eq(sensor.confirmationSupported() && requireConfirmation),
195                     eq(mToken),
196                     eq(operationId),
197                     eq(userId),
198                     eq(mSensorReceiver),
199                     eq(TEST_PACKAGE),
200                     eq(TEST_REQUEST_ID),
201                     eq(sensor.getCookie()),
202                     anyBoolean() /* allowBackgroundAuthentication */,
203                     anyBoolean() /* isForLegacyFingerprintManager */);
204         }
205 
206         final int cookie1 = session.mPreAuthInfo.eligibleSensors.get(0).getCookie();
207         session.onCookieReceived(cookie1);
208         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
209             if (cookie1 == sensor.getCookie()) {
210                 assertEquals(BiometricSensor.STATE_COOKIE_RETURNED, sensor.getSensorState());
211             } else {
212                 assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState());
213             }
214         }
215         assertFalse(session.allCookiesReceived());
216 
217         final int cookie2 = session.mPreAuthInfo.eligibleSensors.get(1).getCookie();
218         session.onCookieReceived(cookie2);
219         assertTrue(session.allCookiesReceived());
220 
221 
222         // for multi-sensor face then fingerprint is the default policy
223         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
224             if (sensor.modality == TYPE_FACE) {
225                 verify(sensor.impl).startPreparedClient(eq(sensor.getCookie()));
226                 assertEquals(BiometricSensor.STATE_AUTHENTICATING, sensor.getSensorState());
227             } else if (sensor.modality == TYPE_FINGERPRINT) {
228                 assertEquals(BiometricSensor.STATE_COOKIE_RETURNED, sensor.getSensorState());
229             }
230         }
231     }
232 
233     @Test
testOnErrorReceived_lockoutError()234     public void testOnErrorReceived_lockoutError() throws RemoteException {
235         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_REAR);
236         setupFace(1 /* id */, false /* confirmationAlwaysRequired */,
237                 mock(IBiometricAuthenticator.class));
238         final AuthSession session = createAuthSession(mSensors,
239                 false /* checkDevicePolicyManager */,
240                 Authenticators.BIOMETRIC_STRONG,
241                 TEST_REQUEST_ID,
242                 0 /* operationId */,
243                 0 /* userId */);
244         session.goToInitialState();
245         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
246             assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState());
247             session.onCookieReceived(
248                     session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie());
249         }
250         assertTrue(session.allCookiesReceived());
251         assertEquals(STATE_AUTH_STARTED, session.getState());
252 
253         // Either of strong sensor's lockout should cancel both sensors.
254         final int cookie1 = session.mPreAuthInfo.eligibleSensors.get(0).getCookie();
255         session.onErrorReceived(0, cookie1, BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, 0);
256         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
257             assertEquals(BiometricSensor.STATE_CANCELING, sensor.getSensorState());
258         }
259         assertEquals(STATE_ERROR_PENDING_SYSUI, session.getState());
260 
261         // If the sensor is STATE_CANCELING, delayed onAuthenticationRejected() shouldn't change the
262         // session state to STATE_AUTH_PAUSED.
263         session.onAuthenticationRejected(1);
264         assertEquals(STATE_ERROR_PENDING_SYSUI, session.getState());
265     }
266 
267     @Test
testOnErrorReceivedBeforeOnDialogAnimatedIn()268     public void testOnErrorReceivedBeforeOnDialogAnimatedIn() throws RemoteException {
269         final int fingerprintId = 0;
270         final int faceId = 1;
271         setupFingerprint(fingerprintId, FingerprintSensorProperties.TYPE_REAR);
272         setupFace(faceId, true /* confirmationAlwaysRequired */,
273                 mock(IBiometricAuthenticator.class));
274         final AuthSession session = createAuthSession(mSensors,
275                 false /* checkDevicePolicyManager */,
276                 Authenticators.BIOMETRIC_STRONG,
277                 TEST_REQUEST_ID,
278                 0 /* operationId */,
279                 0 /* userId */);
280         session.goToInitialState();
281 
282         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
283             assertThat(sensor.getSensorState()).isEqualTo(BiometricSensor.STATE_WAITING_FOR_COOKIE);
284             session.onCookieReceived(
285                     session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie());
286         }
287         assertThat(session.allCookiesReceived()).isTrue();
288         assertThat(session.getState()).isEqualTo(STATE_AUTH_STARTED);
289 
290         final BiometricSensor faceSensor = session.mPreAuthInfo.eligibleSensors.get(faceId);
291         final BiometricSensor fingerprintSensor = session.mPreAuthInfo.eligibleSensors.get(
292                 fingerprintId);
293         final int cookie = faceSensor.getCookie();
294         session.onErrorReceived(0, cookie, BiometricConstants.BIOMETRIC_ERROR_RE_ENROLL, 0);
295 
296         assertThat(faceSensor.getSensorState()).isEqualTo(BiometricSensor.STATE_STOPPED);
297         assertThat(session.getState()).isEqualTo(STATE_ERROR_PENDING_SYSUI);
298 
299         session.onDialogAnimatedIn(true);
300 
301         assertThat(session.getState()).isEqualTo(STATE_AUTH_STARTED_UI_SHOWING);
302         assertThat(fingerprintSensor.getSensorState()).isEqualTo(
303                 BiometricSensor.STATE_AUTHENTICATING);
304     }
305 
306     @Test
testOnRejectionReceivedBeforeOnDialogAnimatedIn()307     public void testOnRejectionReceivedBeforeOnDialogAnimatedIn() throws RemoteException {
308         final int fingerprintId = 0;
309         final int faceId = 1;
310         setupFingerprint(fingerprintId, FingerprintSensorProperties.TYPE_REAR);
311         setupFace(faceId, false /* confirmationAlwaysRequired */,
312                 mock(IBiometricAuthenticator.class));
313         final AuthSession session = createAuthSession(mSensors,
314                 false /* checkDevicePolicyManager */,
315                 Authenticators.BIOMETRIC_STRONG,
316                 TEST_REQUEST_ID,
317                 0 /* operationId */,
318                 0 /* userId */);
319         session.goToInitialState();
320 
321         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
322             assertThat(sensor.getSensorState()).isEqualTo(BiometricSensor.STATE_WAITING_FOR_COOKIE);
323             session.onCookieReceived(
324                     session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie());
325         }
326         assertThat(session.allCookiesReceived()).isTrue();
327         assertThat(session.getState()).isEqualTo(STATE_AUTH_STARTED);
328 
329         final BiometricSensor faceSensor = session.mPreAuthInfo.eligibleSensors.get(faceId);
330         final BiometricSensor fingerprintSensor = session.mPreAuthInfo.eligibleSensors.get(
331                 fingerprintId);
332         session.onAuthenticationRejected(faceId);
333 
334         assertThat(faceSensor.getSensorState()).isEqualTo(BiometricSensor.STATE_CANCELING);
335         assertThat(session.getState()).isEqualTo(STATE_AUTH_PAUSED);
336 
337         session.onDialogAnimatedIn(true);
338 
339         assertThat(session.getState()).isEqualTo(STATE_AUTH_STARTED_UI_SHOWING);
340         assertThat(fingerprintSensor.getSensorState()).isEqualTo(
341                 BiometricSensor.STATE_AUTHENTICATING);
342     }
343 
344     @Test
testCancelReducesAppetiteForCookies()345     public void testCancelReducesAppetiteForCookies() throws Exception {
346         setupFace(0 /* id */, false /* confirmationAlwaysRequired */,
347                 mock(IBiometricAuthenticator.class));
348         setupFingerprint(1 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
349 
350         final AuthSession session = createAuthSession(mSensors,
351                 false /* checkDevicePolicyManager */,
352                 Authenticators.BIOMETRIC_STRONG,
353                 TEST_REQUEST_ID,
354                 44 /* operationId */,
355                 2 /* userId */);
356 
357         session.goToInitialState();
358 
359         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
360             assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState());
361         }
362 
363         session.onCancelAuthSession(false /* force */);
364 
365         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
366             session.onCookieReceived(sensor.getCookie());
367             assertEquals(BiometricSensor.STATE_CANCELING, sensor.getSensorState());
368         }
369     }
370 
371     @Test
testMultiAuth_singleSensor_fingerprintSensorStartsAfterDialogAnimationCompletes()372     public void testMultiAuth_singleSensor_fingerprintSensorStartsAfterDialogAnimationCompletes()
373             throws Exception {
374         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
375         testMultiAuth_fingerprintSensorStartsAfterUINotifies(true /* startFingerprintNow */);
376     }
377 
378     @Test
testMultiAuth_singleSensor_fingerprintSensorDoesNotStartAfterDialogAnimationCompletes()379     public void testMultiAuth_singleSensor_fingerprintSensorDoesNotStartAfterDialogAnimationCompletes()
380             throws Exception {
381         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
382         testMultiAuth_fingerprintSensorStartsAfterUINotifies(false /* startFingerprintNow */);
383     }
384 
385     @Test
testMultiAuth_fingerprintSensorStartsAfterDialogAnimationCompletes()386     public void testMultiAuth_fingerprintSensorStartsAfterDialogAnimationCompletes()
387             throws Exception {
388         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
389         setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class));
390         testMultiAuth_fingerprintSensorStartsAfterUINotifies(true /* startFingerprintNow */);
391     }
392 
393     @Test
testMultiAuth_fingerprintSensorDoesNotStartAfterDialogAnimationCompletes()394     public void testMultiAuth_fingerprintSensorDoesNotStartAfterDialogAnimationCompletes()
395             throws Exception {
396         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
397         setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class));
398         testMultiAuth_fingerprintSensorStartsAfterUINotifies(false /* startFingerprintNow */);
399     }
400 
testMultiAuth_fingerprintSensorStartsAfterUINotifies(boolean startFingerprintNow)401     public void testMultiAuth_fingerprintSensorStartsAfterUINotifies(boolean startFingerprintNow)
402             throws Exception {
403         final long operationId = 123;
404         final int userId = 10;
405         final int fingerprintSensorId = mSensors.stream()
406                 .filter(s -> s.modality == TYPE_FINGERPRINT)
407                 .map(s -> s.id)
408                 .findFirst()
409                 .orElse(-1);
410 
411         final AuthSession session = createAuthSession(mSensors,
412                 false /* checkDevicePolicyManager */,
413                 Authenticators.BIOMETRIC_STRONG,
414                 TEST_REQUEST_ID,
415                 operationId,
416                 userId);
417         assertEquals(mSensors.size(), session.mPreAuthInfo.eligibleSensors.size());
418 
419         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
420             assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState());
421             assertEquals(0, sensor.getCookie());
422         }
423 
424         session.goToInitialState();
425 
426         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
427             assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState());
428             session.onCookieReceived(
429                     session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie());
430             if (fingerprintSensorId == sensor.id) {
431                 assertEquals(BiometricSensor.STATE_COOKIE_RETURNED, sensor.getSensorState());
432             } else {
433                 assertEquals(BiometricSensor.STATE_AUTHENTICATING, sensor.getSensorState());
434             }
435         }
436         assertTrue(session.allCookiesReceived());
437 
438         // fingerprint sensor does not start even if all cookies are received
439         assertEquals(STATE_AUTH_STARTED, session.getState());
440         verify(mStatusBarService).showAuthenticationDialog(any(), any(), any(),
441                 anyBoolean(), anyBoolean(), anyInt(), anyLong(), any(), anyLong());
442 
443         // Notify AuthSession that the UI is shown. Then, fingerprint sensor should be started.
444         session.onDialogAnimatedIn(startFingerprintNow);
445         assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState());
446         assertEquals(startFingerprintNow ? BiometricSensor.STATE_AUTHENTICATING
447                         : BiometricSensor.STATE_COOKIE_RETURNED,
448                 session.mPreAuthInfo.eligibleSensors.get(fingerprintSensorId).getSensorState());
449         verify(mBiometricContext).updateContext((OperationContextExt) anyObject(),
450                 eq(session.isCrypto()));
451 
452         // start fingerprint sensor if it was delayed
453         if (!startFingerprintNow) {
454             session.onStartFingerprint();
455             assertEquals(BiometricSensor.STATE_AUTHENTICATING,
456                     session.mPreAuthInfo.eligibleSensors.get(fingerprintSensorId).getSensorState());
457         }
458     }
459 
460     @Test
testOnDialogAnimatedInDoesNothingDuringInvalidState()461     public void testOnDialogAnimatedInDoesNothingDuringInvalidState() throws Exception {
462         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
463         final long operationId = 123;
464         final int userId = 10;
465 
466         final AuthSession session = createAuthSession(mSensors,
467                 false /* checkDevicePolicyManager */,
468                 Authenticators.BIOMETRIC_STRONG,
469                 TEST_REQUEST_ID,
470                 operationId,
471                 userId);
472         final IBiometricAuthenticator impl = session.mPreAuthInfo.eligibleSensors.get(0).impl;
473 
474         session.goToInitialState();
475         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
476             assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState());
477             session.onCookieReceived(
478                     session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie());
479         }
480         assertTrue(session.allCookiesReceived());
481         assertEquals(STATE_AUTH_STARTED, session.getState());
482         verify(impl, never()).startPreparedClient(anyInt());
483 
484         // First invocation should start the client monitor.
485         session.onDialogAnimatedIn(true /* startFingerprintNow */);
486         assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState());
487         verify(impl).startPreparedClient(anyInt());
488 
489         // Subsequent invocations should not start the client monitor again.
490         session.onDialogAnimatedIn(true /* startFingerprintNow */);
491         session.onDialogAnimatedIn(false /* startFingerprintNow */);
492         session.onDialogAnimatedIn(true /* startFingerprintNow */);
493         assertEquals(STATE_AUTH_STARTED_UI_SHOWING, session.getState());
494         verify(impl, times(1)).startPreparedClient(anyInt());
495     }
496 
497     @Test
testCancelAuthentication_whenStateAuthCalled_invokesCancel()498     public void testCancelAuthentication_whenStateAuthCalled_invokesCancel()
499             throws RemoteException {
500         testInvokesCancel(session -> session.onCancelAuthSession(false /* force */));
501     }
502 
503     @Test
testCancelAuthentication_whenStateAuthForcedCalled_invokesCancel()504     public void testCancelAuthentication_whenStateAuthForcedCalled_invokesCancel()
505             throws RemoteException {
506         testInvokesCancel(session -> session.onCancelAuthSession(true /* force */));
507     }
508 
509     @Test
testCancelAuthentication_whenDialogDismissed()510     public void testCancelAuthentication_whenDialogDismissed() throws RemoteException {
511         testInvokesCancel(session -> session.onDialogDismissed(DISMISSED_REASON_NEGATIVE, null));
512     }
513 
514     @Test
testCallbackOnAcquired()515     public void testCallbackOnAcquired() throws RemoteException {
516         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_REAR);
517 
518         final AuthSession session = createAuthSession(mSensors,
519                 false /* checkDevicePolicyManager */,
520                 Authenticators.BIOMETRIC_STRONG,
521                 TEST_REQUEST_ID,
522                 0 /* operationId */,
523                 0 /* userId */);
524 
525         session.onAcquired(0, FingerprintManager.FINGERPRINT_ACQUIRED_PARTIAL, 0);
526         verify(mStatusBarService).onBiometricHelp(anyInt(), eq(ACQUIRED_STRING));
527         verify(mClientReceiver).onAcquired(eq(1), eq(ACQUIRED_STRING));
528 
529         session.onAcquired(0, FingerprintManager.FINGERPRINT_ACQUIRED_VENDOR, 0);
530         verify(mStatusBarService).onBiometricHelp(anyInt(), eq(ACQUIRED_STRING_VENDOR));
531         verify(mClientReceiver).onAcquired(
532                 eq(FingerprintManager.FINGERPRINT_ACQUIRED_VENDOR_BASE),
533                 eq(ACQUIRED_STRING_VENDOR));
534     }
535 
536     @Test
testLogOnDialogDismissed_authenticatedWithConfirmation()537     public void testLogOnDialogDismissed_authenticatedWithConfirmation() throws RemoteException {
538         final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
539 
540         setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
541         final AuthSession session = createAuthSession(mSensors,
542                 false /* checkDevicePolicyManager */,
543                 Authenticators.BIOMETRIC_STRONG,
544                 TEST_REQUEST_ID,
545                 0 /* operationId */,
546                 0 /* userId */);
547         session.goToInitialState();
548         assertEquals(STATE_AUTH_CALLED, session.getState());
549 
550         session.onDialogDismissed(DISMISSED_REASON_BIOMETRIC_CONFIRMED, null);
551         verify(mBiometricFrameworkStatsLogger, times(1)).authenticate(
552                 (OperationContextExt) anyObject(),
553                 eq(BiometricsProtoEnums.MODALITY_FACE),
554                 eq(BiometricsProtoEnums.ACTION_UNKNOWN),
555                 eq(BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT),
556                 eq(false), /* debugEnabled */
557                 anyLong(), /* latency */
558                 eq(FrameworkStatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED),
559                 eq(true), /* confirmationRequired */
560                 eq(0) /* userId */,
561                 eq(-1f) /* ambientLightLux */);
562     }
563 
564     @Test
testLogOnDialogDismissed_authenticatedWithoutConfirmation()565     public void testLogOnDialogDismissed_authenticatedWithoutConfirmation() throws RemoteException {
566         final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
567 
568         setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
569         final AuthSession session = createAuthSession(mSensors,
570                 false /* checkDevicePolicyManager */,
571                 Authenticators.BIOMETRIC_STRONG,
572                 TEST_REQUEST_ID,
573                 0 /* operationId */,
574                 0 /* userId */);
575         session.goToInitialState();
576         assertEquals(STATE_AUTH_CALLED, session.getState());
577 
578         session.onDialogDismissed(DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED, null);
579         verify(mBiometricFrameworkStatsLogger, never()).authenticate(
580                 anyObject(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyLong(), anyInt(),
581                 anyBoolean(), anyInt(), eq(-1f));
582         verify(mBiometricFrameworkStatsLogger, never()).error(
583                 anyObject(), anyInt(), anyInt(), anyInt(), anyBoolean(), anyLong(), anyInt(),
584                 anyInt(), anyInt());
585     }
586 
587     @Test
testLogOnDialogDismissed_error()588     public void testLogOnDialogDismissed_error() throws RemoteException {
589         final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
590 
591         setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
592         final AuthSession session = createAuthSession(mSensors,
593                 false /* checkDevicePolicyManager */,
594                 Authenticators.BIOMETRIC_STRONG,
595                 TEST_REQUEST_ID,
596                 0 /* operationId */,
597                 0 /* userId */);
598         session.goToInitialState();
599         assertEquals(STATE_AUTH_CALLED, session.getState());
600 
601         session.onDialogDismissed(DISMISSED_REASON_NEGATIVE, null);
602         verify(mBiometricFrameworkStatsLogger, times(1)).error(
603                 (OperationContextExt) anyObject(),
604                 eq(BiometricsProtoEnums.MODALITY_FACE),
605                 eq(BiometricsProtoEnums.ACTION_AUTHENTICATE),
606                 eq(BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT),
607                 eq(false),
608                 anyLong(),
609                 eq(BIOMETRIC_ERROR_NEGATIVE_BUTTON),
610                 eq(0) /* vendorCode */,
611                 eq(0) /* userId */);
612     }
613 
614     @Test
onErrorReceivedAfterOnTryAgainPressedWhenSensorsAuthenticating()615     public void onErrorReceivedAfterOnTryAgainPressedWhenSensorsAuthenticating() throws Exception {
616         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
617         setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class));
618         final long operationId = 123;
619         final int userId = 10;
620         final AuthSession session = createAuthSession(mSensors,
621                 false /* checkDevicePolicyManager */,
622                 Authenticators.BIOMETRIC_STRONG,
623                 TEST_REQUEST_ID,
624                 operationId,
625                 userId);
626         session.goToInitialState();
627         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
628             session.onCookieReceived(
629                     session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie());
630         }
631         session.onDialogAnimatedIn(true /* startFingerprintNow */);
632 
633         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
634             assertEquals(BiometricSensor.STATE_AUTHENTICATING, sensor.getSensorState());
635         }
636         session.onTryAgainPressed();
637         session.onErrorReceived(0 /* sensorId */,
638                 session.mPreAuthInfo.eligibleSensors.get(0 /* sensorId */).getCookie(),
639                 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT, 0);
640 
641         verify(mStatusBarService).onBiometricError(anyInt(), anyInt(), anyInt());
642     }
643 
644     @Test
onErrorReceivedAfterOnTryAgainPressedWhenSensorStopped()645     public void onErrorReceivedAfterOnTryAgainPressedWhenSensorStopped() throws Exception {
646         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
647         setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class));
648         final long operationId = 123;
649         final int userId = 10;
650         final AuthSession session = createAuthSession(mSensors,
651                 false /* checkDevicePolicyManager */,
652                 Authenticators.BIOMETRIC_STRONG,
653                 TEST_REQUEST_ID,
654                 operationId,
655                 userId);
656         session.goToInitialState();
657         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
658             session.onCookieReceived(
659                     session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie());
660         }
661         session.onDialogAnimatedIn(true /* startFingerprintNow */);
662 
663         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
664             sensor.goToStoppedStateIfCookieMatches(sensor.getCookie(),
665                     BiometricConstants.BIOMETRIC_ERROR_TIMEOUT);
666             assertEquals(BiometricSensor.STATE_STOPPED, sensor.getSensorState());
667         }
668 
669         session.onTryAgainPressed();
670         session.onErrorReceived(0 /* sensorId */,
671                 session.mPreAuthInfo.eligibleSensors.get(0 /* sensorId */).getCookie(),
672                 BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT, 0);
673 
674         verify(mStatusBarService, never()).onBiometricError(anyInt(), anyInt(), anyInt());
675     }
676 
677     @Test
onAuthReceivedWhileWaitingForConfirmation_SFPS()678     public void onAuthReceivedWhileWaitingForConfirmation_SFPS() throws Exception {
679         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_POWER_BUTTON);
680         setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class));
681         final long operationId = 123;
682         final int userId = 10;
683         final AuthSession session = createAuthSession(mSensors,
684                 false /* checkDevicePolicyManager */,
685                 Authenticators.BIOMETRIC_STRONG,
686                 TEST_REQUEST_ID,
687                 operationId,
688                 userId);
689         session.goToInitialState();
690         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
691             session.onCookieReceived(
692                     session.mPreAuthInfo.eligibleSensors.get(sensor.id).getCookie());
693         }
694         session.onDialogAnimatedIn(true /* startFingerprintNow */);
695 
696         // Face succeeds
697         session.onAuthenticationSucceeded(1, true, null);
698         verify(mStatusBarService).onBiometricAuthenticated(TYPE_FACE);
699         for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
700             if (sensor.modality == FingerprintSensorProperties.TYPE_POWER_BUTTON) {
701                 assertEquals(BiometricSensor.STATE_AUTHENTICATING, sensor.getSensorState());
702             }
703         }
704 
705         // SFPS succeeds
706         session.onAuthenticationSucceeded(0, true, null);
707         verify(mStatusBarService).onBiometricAuthenticated(TYPE_FINGERPRINT);
708     }
709 
710     @Test
onDialogDismissedResetLockout_Confirmed()711     public void onDialogDismissedResetLockout_Confirmed() throws Exception {
712         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_POWER_BUTTON);
713         setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class));
714         final long operationId = 123;
715         final int userId = 10;
716         final AuthSession session = createAuthSession(mSensors,
717                 false /* checkDevicePolicyManager */,
718                 Authenticators.BIOMETRIC_STRONG,
719                 TEST_REQUEST_ID,
720                 operationId,
721                 userId);
722         session.goToInitialState();
723         session.onDialogAnimatedIn(true /* startFingerprintNow */);
724 
725         // Face succeeds
726         session.onAuthenticationSucceeded(1, true, new byte[1]);
727 
728         // Dismiss through confirmation
729         session.onDialogDismissed(DISMISSED_REASON_BIOMETRIC_CONFIRMED, null);
730 
731         verify(mBiometricManager).resetLockoutTimeBound(any(), any(), anyInt(), anyInt(), any());
732     }
733 
734     @Test
onDialogDismissedResetLockout_Cancelled()735     public void onDialogDismissedResetLockout_Cancelled() throws Exception {
736         setupFingerprint(0 /* id */, FingerprintSensorProperties.TYPE_POWER_BUTTON);
737         setupFace(1 /* id */, false, mock(IBiometricAuthenticator.class));
738         final long operationId = 123;
739         final int userId = 10;
740         final AuthSession session = createAuthSession(mSensors,
741                 false /* checkDevicePolicyManager */,
742                 Authenticators.BIOMETRIC_STRONG,
743                 TEST_REQUEST_ID,
744                 operationId,
745                 userId);
746         session.goToInitialState();
747         session.onDialogAnimatedIn(true /* startFingerprintNow */);
748 
749         // Face succeeds
750         session.onAuthenticationSucceeded(1, true, new byte[1]);
751 
752         // User cancel after success
753         session.onDialogDismissed(DISMISSED_REASON_USER_CANCEL, null);
754 
755         verify(mBiometricManager).resetLockoutTimeBound(any(), any(), anyInt(), anyInt(), any());
756     }
757 
758     // TODO (b/208484275) : Enable these tests
759     // @Test
760     // public void testPreAuth_canAuthAndPrivacyDisabled() throws Exception {
761     //     SensorPrivacyManager manager = ExtendedMockito.mock(SensorPrivacyManager.class);
762     //     when(manager
763     //             .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, anyInt()))
764     //             .thenReturn(false);
765     //     when(mContext.getSystemService(SensorPrivacyManager.class))
766     //             .thenReturn(manager);
767     //     setupFace(1 /* id */, false /* confirmationAlwaysRequired */,
768     //             mock(IBiometricAuthenticator.class));
769     //     final PromptInfo promptInfo = createPromptInfo(Authenticators.BIOMETRIC_STRONG);
770     //     final PreAuthInfo preAuthInfo = createPreAuthInfo(mSensors, 0, promptInfo, false);
771     //     assertEquals(BiometricManager.BIOMETRIC_SUCCESS, preAuthInfo.getCanAuthenticateResult());
772     //     for (BiometricSensor sensor : preAuthInfo.eligibleSensors) {
773     //         assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState());
774     //     }
775     // }
776 
777     // @Test
778     // public void testPreAuth_cannotAuthAndPrivacyEnabled() throws Exception {
779     //     SensorPrivacyManager manager = ExtendedMockito.mock(SensorPrivacyManager.class);
780     //     when(manager
781     //             .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, anyInt()))
782     //             .thenReturn(true);
783     //     when(mContext.getSystemService(SensorPrivacyManager.class))
784     //             .thenReturn(manager);
785     //     setupFace(1 /* id */, false /* confirmationAlwaysRequired */,
786     //             mock(IBiometricAuthenticator.class));
787     //     final PromptInfo promptInfo = createPromptInfo(Authenticators.BIOMETRIC_STRONG);
788     //     final PreAuthInfo preAuthInfo = createPreAuthInfo(mSensors, 0, promptInfo, false);
789     //     assertEquals(BiometricManager.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED,
790     //             preAuthInfo.getCanAuthenticateResult());
791     //     // Even though canAuth returns privacy enabled, we should still be able to authenticate.
792     //     for (BiometricSensor sensor : preAuthInfo.eligibleSensors) {
793     //         assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState());
794     //     }
795     // }
796 
797     // @Test
798     // public void testPreAuth_canAuthAndPrivacyEnabledCredentialEnabled() throws Exception {
799     //     SensorPrivacyManager manager = ExtendedMockito.mock(SensorPrivacyManager.class);
800     //     when(manager
801     //             .isSensorPrivacyEnabled(SensorPrivacyManager.Sensors.CAMERA, anyInt()))
802     //             .thenReturn(true);
803     //     when(mContext.getSystemService(SensorPrivacyManager.class))
804     //             .thenReturn(manager);
805     //     setupFace(1 /* id */, false /* confirmationAlwaysRequired */,
806     //             mock(IBiometricAuthenticator.class));
807     //     final PromptInfo promptInfo =
808     //             createPromptInfo(Authenticators.BIOMETRIC_STRONG
809     //             | Authenticators. DEVICE_CREDENTIAL);
810     //     final PreAuthInfo preAuthInfo = createPreAuthInfo(mSensors, 0, promptInfo, false);
811     //     assertEquals(BiometricManager.BIOMETRIC_SUCCESS, preAuthInfo.getCanAuthenticateResult());
812     //     for (BiometricSensor sensor : preAuthInfo.eligibleSensors) {
813     //         assertEquals(BiometricSensor.STATE_UNKNOWN, sensor.getSensorState());
814     //     }
815     // }
816 
testInvokesCancel(Consumer<AuthSession> sessionConsumer)817     private void testInvokesCancel(Consumer<AuthSession> sessionConsumer) throws RemoteException {
818         final IBiometricAuthenticator faceAuthenticator = mock(IBiometricAuthenticator.class);
819 
820         setupFace(0 /* id */, false /* confirmationAlwaysRequired */, faceAuthenticator);
821         final AuthSession session = createAuthSession(mSensors,
822                 false /* checkDevicePolicyManager */,
823                 Authenticators.BIOMETRIC_STRONG,
824                 TEST_REQUEST_ID,
825                 0 /* operationId */,
826                 0 /* userId */);
827 
828         session.goToInitialState();
829         assertEquals(STATE_AUTH_CALLED, session.getState());
830 
831         sessionConsumer.accept(session);
832 
833         verify(faceAuthenticator).cancelAuthenticationFromService(
834                 eq(mToken), eq(TEST_PACKAGE), eq(TEST_REQUEST_ID));
835     }
836 
createPreAuthInfo(List<BiometricSensor> sensors, int userId, PromptInfo promptInfo, boolean checkDevicePolicyManager)837     private PreAuthInfo createPreAuthInfo(List<BiometricSensor> sensors, int userId,
838             PromptInfo promptInfo, boolean checkDevicePolicyManager) throws RemoteException {
839         return PreAuthInfo.create(mTrustManager,
840                 mDevicePolicyManager,
841                 mSettingObserver,
842                 sensors,
843                 userId,
844                 promptInfo,
845                 TEST_PACKAGE,
846                 checkDevicePolicyManager,
847                 mContext,
848                 mBiometricCameraManager);
849     }
850 
createAuthSession(List<BiometricSensor> sensors, boolean checkDevicePolicyManager, @Authenticators.Types int authenticators, long requestId, long operationId, int userId)851     private AuthSession createAuthSession(List<BiometricSensor> sensors,
852             boolean checkDevicePolicyManager, @Authenticators.Types int authenticators,
853             long requestId, long operationId, int userId) throws RemoteException {
854 
855         final PromptInfo promptInfo = createPromptInfo(authenticators);
856 
857         final PreAuthInfo preAuthInfo = createPreAuthInfo(sensors, userId, promptInfo,
858                 checkDevicePolicyManager);
859         return new AuthSession(mContext, mBiometricContext, mStatusBarService, mSysuiReceiver,
860                 mKeyStoreAuthorization, mRandom, mClientDeathReceiver, preAuthInfo, mToken,
861                 requestId, operationId, userId, mSensorReceiver, mClientReceiver, TEST_PACKAGE,
862                 promptInfo, false /* debugEnabled */, mFingerprintSensorProps,
863                 mBiometricFrameworkStatsLogger);
864     }
865 
createPromptInfo(@uthenticators.Types int authenticators)866     private PromptInfo createPromptInfo(@Authenticators.Types int authenticators) {
867         PromptInfo promptInfo = new PromptInfo();
868         promptInfo.setAuthenticators(authenticators);
869         return promptInfo;
870     }
871 
setupFingerprint(int id, @FingerprintSensorProperties.SensorType int type)872     private void setupFingerprint(int id, @FingerprintSensorProperties.SensorType int type)
873             throws RemoteException {
874         IBiometricAuthenticator fingerprintAuthenticator = mock(IBiometricAuthenticator.class);
875         when(fingerprintAuthenticator.isHardwareDetected(any())).thenReturn(true);
876         when(fingerprintAuthenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
877         mSensors.add(new BiometricSensor(mContext, id,
878                 TYPE_FINGERPRINT /* modality */,
879                 Authenticators.BIOMETRIC_STRONG /* strength */,
880                 fingerprintAuthenticator) {
881             @Override
882             boolean confirmationAlwaysRequired(int userId) {
883                 return false; // no-op / unsupported
884             }
885 
886             @Override
887             boolean confirmationSupported() {
888                 return false; // fingerprint does not support confirmation
889             }
890         });
891 
892         final List<ComponentInfoInternal> componentInfo = new ArrayList<>();
893         componentInfo.add(new ComponentInfoInternal("faceSensor" /* componentId */,
894                 "vendor/model/revision" /* hardwareVersion */, "1.01" /* firmwareVersion */,
895                 "00000001" /* serialNumber */, "" /* softwareVersion */));
896         componentInfo.add(new ComponentInfoInternal("matchingAlgorithm" /* componentId */,
897                 "" /* hardwareVersion */, "" /* firmwareVersion */, "" /* serialNumber */,
898                 "vendor/version/revision" /* softwareVersion */));
899 
900         mFingerprintSensorProps.add(new FingerprintSensorPropertiesInternal(id,
901                 SensorProperties.STRENGTH_STRONG,
902                 5 /* maxEnrollmentsPerUser */,
903                 componentInfo,
904                 type,
905                 false /* resetLockoutRequiresHardwareAuthToken */));
906 
907         when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
908     }
909 
setupFace(int id, boolean confirmationAlwaysRequired, IBiometricAuthenticator authenticator)910     private void setupFace(int id, boolean confirmationAlwaysRequired,
911             IBiometricAuthenticator authenticator) throws RemoteException {
912         when(authenticator.isHardwareDetected(any())).thenReturn(true);
913         when(authenticator.hasEnrolledTemplates(anyInt(), any())).thenReturn(true);
914         mSensors.add(new BiometricSensor(mContext, id,
915                 TYPE_FACE /* modality */,
916                 Authenticators.BIOMETRIC_STRONG /* strength */,
917                 authenticator) {
918             @Override
919             boolean confirmationAlwaysRequired(int userId) {
920                 return confirmationAlwaysRequired;
921             }
922 
923             @Override
924             boolean confirmationSupported() {
925                 return true;
926             }
927         });
928 
929         when(mSettingObserver.getEnabledForApps(anyInt())).thenReturn(true);
930     }
931 }
932