1 /* 2 * Copyright (C) 2021 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 org.mockito.ArgumentMatchers.any; 20 import static org.mockito.ArgumentMatchers.anyInt; 21 import static org.mockito.ArgumentMatchers.eq; 22 import static org.mockito.Mockito.mock; 23 import static org.mockito.Mockito.never; 24 import static org.mockito.Mockito.verify; 25 import static org.mockito.Mockito.when; 26 27 import android.annotation.NonNull; 28 import android.content.Context; 29 import android.hardware.biometrics.BiometricAuthenticator; 30 import android.hardware.biometrics.BiometricManager.Authenticators; 31 import android.hardware.biometrics.IBiometricAuthenticator; 32 import android.hardware.biometrics.IInvalidationCallback; 33 import android.platform.test.annotations.Presubmit; 34 35 import androidx.test.filters.SmallTest; 36 37 import com.android.server.biometrics.BiometricService.InvalidationTracker; 38 39 import org.junit.Before; 40 import org.junit.Test; 41 import org.mockito.Mock; 42 import org.mockito.MockitoAnnotations; 43 44 import java.util.ArrayList; 45 46 @Presubmit 47 @SmallTest 48 public class InvalidationTrackerTest { 49 50 @Mock 51 private Context mContext; 52 53 @Before setUp()54 public void setUp() { 55 MockitoAnnotations.initMocks(this); 56 } 57 58 @Test testCallbackReceived_whenAllStrongSensorsInvalidated()59 public void testCallbackReceived_whenAllStrongSensorsInvalidated() throws Exception { 60 final IBiometricAuthenticator authenticator1 = mock(IBiometricAuthenticator.class); 61 when(authenticator1.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); 62 final TestSensor sensor1 = new TestSensor(mContext, 0 /* id */, 63 BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG, 64 authenticator1); 65 66 final IBiometricAuthenticator authenticator2 = mock(IBiometricAuthenticator.class); 67 when(authenticator2.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); 68 final TestSensor sensor2 = new TestSensor(mContext, 1 /* id */, 69 BiometricAuthenticator.TYPE_FINGERPRINT, Authenticators.BIOMETRIC_STRONG, 70 authenticator2); 71 72 final IBiometricAuthenticator authenticator3 = mock(IBiometricAuthenticator.class); 73 when(authenticator3.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); 74 final TestSensor sensor3 = new TestSensor(mContext, 2 /* id */, 75 BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_STRONG, 76 authenticator3); 77 78 final IBiometricAuthenticator authenticator4 = mock(IBiometricAuthenticator.class); 79 when(authenticator4.hasEnrolledTemplates(anyInt(), any())).thenReturn(true); 80 final TestSensor sensor4 = new TestSensor(mContext, 3 /* id */, 81 BiometricAuthenticator.TYPE_FACE, Authenticators.BIOMETRIC_WEAK, 82 authenticator4); 83 84 final ArrayList<BiometricSensor> sensors = new ArrayList<>(); 85 sensors.add(sensor1); 86 sensors.add(sensor2); 87 sensors.add(sensor3); 88 sensors.add(sensor4); 89 90 final IInvalidationCallback callback = mock(IInvalidationCallback.class); 91 final InvalidationTracker tracker = 92 InvalidationTracker.start(mock(Context.class), sensors, 0 /* userId */, 93 0 /* fromSensorId */, callback); 94 95 // The sensor which the request originated from should not be requested to invalidate 96 // its authenticatorId. 97 verify(authenticator1, never()).invalidateAuthenticatorId(anyInt(), any()); 98 99 // All other strong sensors should be requested to invalidate authenticatorId 100 verify(authenticator2).invalidateAuthenticatorId(eq(0) /* userId */, any()); 101 verify(authenticator3).invalidateAuthenticatorId(eq(0) /* userId */, any()); 102 103 // Weak sensors are not requested to invalidate authenticatorId 104 verify(authenticator4, never()).invalidateAuthenticatorId(anyInt(), any()); 105 106 // Client is not notified until invalidation for all required sensors have completed 107 verify(callback, never()).onCompleted(); 108 tracker.onInvalidated(1); 109 verify(callback, never()).onCompleted(); 110 tracker.onInvalidated(2); 111 verify(callback).onCompleted(); 112 } 113 114 private static class TestSensor extends BiometricSensor { 115 TestSensor(@onNull Context context, int id, int modality, int strength, @NonNull IBiometricAuthenticator impl)116 TestSensor(@NonNull Context context, int id, int modality, int strength, 117 @NonNull IBiometricAuthenticator impl) { 118 super(context, id, modality, strength, impl); 119 } 120 121 @Override confirmationAlwaysRequired(int userId)122 boolean confirmationAlwaysRequired(int userId) { 123 return false; 124 } 125 126 @Override confirmationSupported()127 boolean confirmationSupported() { 128 return false; 129 } 130 } 131 } 132