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 21 import static junit.framework.Assert.assertEquals; 22 import static junit.framework.Assert.assertFalse; 23 import static junit.framework.Assert.assertTrue; 24 25 import android.hardware.biometrics.BiometricAuthenticator; 26 import android.hardware.biometrics.BiometricConstants; 27 import android.hardware.biometrics.BiometricManager; 28 import android.hardware.biometrics.BiometricPrompt; 29 import android.hardware.biometrics.PromptInfo; 30 import android.platform.test.annotations.Presubmit; 31 32 import androidx.test.filters.SmallTest; 33 34 import org.junit.Test; 35 36 @Presubmit 37 @SmallTest 38 public class UtilsTest { 39 40 @Test testCombineAuthenticatorBundles_withKeyDeviceCredential_andKeyAuthenticators()41 public void testCombineAuthenticatorBundles_withKeyDeviceCredential_andKeyAuthenticators() { 42 final boolean allowDeviceCredential = false; 43 final @Authenticators.Types int authenticators = 44 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK; 45 final PromptInfo promptInfo = new PromptInfo(); 46 47 promptInfo.setDeviceCredentialAllowed(allowDeviceCredential); 48 promptInfo.setAuthenticators(authenticators); 49 Utils.combineAuthenticatorBundles(promptInfo); 50 51 assertFalse(promptInfo.isDeviceCredentialAllowed()); 52 assertEquals(authenticators, promptInfo.getAuthenticators()); 53 } 54 55 @Test testCombineAuthenticatorBundles_withNoKeyDeviceCredential_andKeyAuthenticators()56 public void testCombineAuthenticatorBundles_withNoKeyDeviceCredential_andKeyAuthenticators() { 57 final @Authenticators.Types int authenticators = 58 Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK; 59 final PromptInfo promptInfo = new PromptInfo(); 60 61 promptInfo.setAuthenticators(authenticators); 62 Utils.combineAuthenticatorBundles(promptInfo); 63 64 assertFalse(promptInfo.isDeviceCredentialAllowed()); 65 assertEquals(authenticators, promptInfo.getAuthenticators()); 66 } 67 68 @Test testCombineAuthenticatorBundles_withKeyDeviceCredential_andNoKeyAuthenticators()69 public void testCombineAuthenticatorBundles_withKeyDeviceCredential_andNoKeyAuthenticators() { 70 final boolean allowDeviceCredential = true; 71 final PromptInfo promptInfo = new PromptInfo(); 72 73 promptInfo.setDeviceCredentialAllowed(allowDeviceCredential); 74 Utils.combineAuthenticatorBundles(promptInfo); 75 76 assertFalse(promptInfo.isDeviceCredentialAllowed()); 77 assertEquals(Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK, 78 promptInfo.getAuthenticators()); 79 } 80 81 @Test testCombineAuthenticatorBundles_withNoKeyDeviceCredential_andNoKeyAuthenticators()82 public void testCombineAuthenticatorBundles_withNoKeyDeviceCredential_andNoKeyAuthenticators() { 83 final PromptInfo promptInfo = new PromptInfo(); 84 85 Utils.combineAuthenticatorBundles(promptInfo); 86 87 assertFalse(promptInfo.isDeviceCredentialAllowed()); 88 assertEquals(Authenticators.BIOMETRIC_WEAK, promptInfo.getAuthenticators()); 89 } 90 91 @Test testIsDeviceCredentialAllowed_withIntegerFlags()92 public void testIsDeviceCredentialAllowed_withIntegerFlags() { 93 int authenticators = 0; 94 assertFalse(Utils.isCredentialRequested(authenticators)); 95 96 authenticators |= Authenticators.DEVICE_CREDENTIAL; 97 assertTrue(Utils.isCredentialRequested(authenticators)); 98 99 authenticators |= Authenticators.BIOMETRIC_WEAK; 100 assertTrue(Utils.isCredentialRequested(authenticators)); 101 } 102 103 @Test testIsDeviceCredentialAllowed_withBundle()104 public void testIsDeviceCredentialAllowed_withBundle() { 105 PromptInfo promptInfo = new PromptInfo(); 106 assertFalse(Utils.isCredentialRequested(promptInfo)); 107 108 int authenticators = 0; 109 promptInfo.setAuthenticators(authenticators); 110 assertFalse(Utils.isCredentialRequested(promptInfo)); 111 112 authenticators |= Authenticators.DEVICE_CREDENTIAL; 113 promptInfo.setAuthenticators(authenticators); 114 assertTrue(Utils.isCredentialRequested(promptInfo)); 115 116 authenticators |= Authenticators.BIOMETRIC_WEAK; 117 promptInfo.setAuthenticators(authenticators); 118 assertTrue(Utils.isCredentialRequested(promptInfo)); 119 } 120 121 @Test testGetBiometricStrength_removeUnrelatedBits()122 public void testGetBiometricStrength_removeUnrelatedBits() { 123 // BIOMETRIC_MIN_STRENGTH uses all of the allowed bits for biometric strength, so any other 124 // bits aside from these should be clipped off. 125 126 int authenticators = Integer.MAX_VALUE; 127 assertEquals(Authenticators.BIOMETRIC_WEAK, 128 Utils.getPublicBiometricStrength(authenticators)); 129 130 PromptInfo promptInfo = new PromptInfo(); 131 promptInfo.setAuthenticators(authenticators); 132 assertEquals(Authenticators.BIOMETRIC_WEAK, Utils.getPublicBiometricStrength(promptInfo)); 133 } 134 135 @Test testIsBiometricAllowed()136 public void testIsBiometricAllowed() { 137 // Only the lowest 8 bits (BIOMETRIC_WEAK mask) are allowed to integrate with the 138 // Biometric APIs 139 PromptInfo promptInfo = new PromptInfo(); 140 for (int i = 0; i <= 7; i++) { 141 int authenticators = 1 << i; 142 promptInfo.setAuthenticators(authenticators); 143 assertTrue(Utils.isBiometricRequested(promptInfo)); 144 } 145 146 // The rest of the bits are not allowed to integrate with the public APIs 147 for (int i = 8; i < 32; i++) { 148 int authenticators = 1 << i; 149 promptInfo.setAuthenticators(authenticators); 150 assertFalse(Utils.isBiometricRequested(promptInfo)); 151 } 152 } 153 154 @Test testIsValidAuthenticatorConfig()155 public void testIsValidAuthenticatorConfig() { 156 assertTrue(Utils.isValidAuthenticatorConfig(Authenticators.EMPTY_SET)); 157 158 assertTrue(Utils.isValidAuthenticatorConfig(Authenticators.BIOMETRIC_STRONG)); 159 160 assertTrue(Utils.isValidAuthenticatorConfig(Authenticators.BIOMETRIC_WEAK)); 161 162 assertTrue(Utils.isValidAuthenticatorConfig(Authenticators.DEVICE_CREDENTIAL)); 163 164 assertTrue(Utils.isValidAuthenticatorConfig(Authenticators.DEVICE_CREDENTIAL 165 | Authenticators.BIOMETRIC_STRONG)); 166 167 assertTrue(Utils.isValidAuthenticatorConfig(Authenticators.DEVICE_CREDENTIAL 168 | Authenticators.BIOMETRIC_WEAK)); 169 170 assertFalse(Utils.isValidAuthenticatorConfig(Authenticators.BIOMETRIC_CONVENIENCE)); 171 172 assertFalse(Utils.isValidAuthenticatorConfig(Authenticators.BIOMETRIC_CONVENIENCE 173 | Authenticators.DEVICE_CREDENTIAL)); 174 175 assertFalse(Utils.isValidAuthenticatorConfig(Authenticators.BIOMETRIC_MAX_STRENGTH)); 176 177 assertFalse(Utils.isValidAuthenticatorConfig(Authenticators.BIOMETRIC_MIN_STRENGTH)); 178 179 // The rest of the bits are not allowed to integrate with the public APIs 180 for (int i = 8; i < 32; i++) { 181 final int authenticator = 1 << i; 182 if (authenticator == Authenticators.DEVICE_CREDENTIAL) { 183 continue; 184 } 185 assertFalse(Utils.isValidAuthenticatorConfig(1 << i)); 186 } 187 } 188 189 @Test testIsAtLeastStrength()190 public void testIsAtLeastStrength() { 191 int sensorStrength = Authenticators.BIOMETRIC_STRONG; 192 int requestedStrength = Authenticators.BIOMETRIC_WEAK; 193 assertTrue(Utils.isAtLeastStrength(sensorStrength, requestedStrength)); 194 195 requestedStrength = Authenticators.BIOMETRIC_STRONG; 196 assertTrue(Utils.isAtLeastStrength(sensorStrength, requestedStrength)); 197 198 sensorStrength = Authenticators.BIOMETRIC_WEAK; 199 requestedStrength = Authenticators.BIOMETRIC_STRONG; 200 assertFalse(Utils.isAtLeastStrength(sensorStrength, requestedStrength)); 201 202 requestedStrength = Authenticators.BIOMETRIC_WEAK; 203 assertTrue(Utils.isAtLeastStrength(sensorStrength, requestedStrength)); 204 205 206 // Test invalid inputs 207 208 sensorStrength = Authenticators.BIOMETRIC_STRONG; 209 requestedStrength = Authenticators.DEVICE_CREDENTIAL; 210 assertFalse(Utils.isAtLeastStrength(sensorStrength, requestedStrength)); 211 212 requestedStrength = 1 << 2; 213 assertFalse(Utils.isAtLeastStrength(sensorStrength, requestedStrength)); 214 } 215 216 @Test testBiometricConstantsConversion()217 public void testBiometricConstantsConversion() { 218 final int[][] testCases = { 219 {BiometricConstants.BIOMETRIC_SUCCESS, 220 BiometricManager.BIOMETRIC_SUCCESS}, 221 {BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS, 222 BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED}, 223 {BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL, 224 BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED}, 225 {BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE, 226 BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE}, 227 {BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT, 228 BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE}, 229 {BiometricConstants.BIOMETRIC_ERROR_LOCKOUT, 230 BiometricManager.BIOMETRIC_SUCCESS}, 231 {BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT, 232 BiometricManager.BIOMETRIC_SUCCESS} 233 }; 234 235 for (int i = 0; i < testCases.length; i++) { 236 assertEquals(testCases[i][1], 237 Utils.biometricConstantsToBiometricManager(testCases[i][0])); 238 } 239 } 240 241 @Test testGetAuthenticationTypeForResult_getsCorrectType()242 public void testGetAuthenticationTypeForResult_getsCorrectType() { 243 assertEquals(Utils.getAuthenticationTypeForResult( 244 BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED), 245 BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL); 246 assertEquals(Utils.getAuthenticationTypeForResult( 247 BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED), 248 BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC); 249 assertEquals(Utils.getAuthenticationTypeForResult( 250 BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED), 251 BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC); 252 } 253 254 @Test(expected = IllegalArgumentException.class) testGetAuthResultType_throwsForInvalidReason()255 public void testGetAuthResultType_throwsForInvalidReason() { 256 Utils.getAuthenticationTypeForResult(BiometricPrompt.DISMISSED_REASON_NEGATIVE); 257 } 258 259 @Test testConfirmationSupported()260 public void testConfirmationSupported() { 261 assertTrue(Utils.isConfirmationSupported(BiometricAuthenticator.TYPE_FACE)); 262 assertTrue(Utils.isConfirmationSupported(BiometricAuthenticator.TYPE_IRIS)); 263 assertFalse(Utils.isConfirmationSupported(BiometricAuthenticator.TYPE_FINGERPRINT)); 264 } 265 266 @Test testRemoveBiometricBits()267 public void testRemoveBiometricBits() { 268 @Authenticators.Types int authenticators = Integer.MAX_VALUE; 269 authenticators = Utils.removeBiometricBits(authenticators); 270 // All biometric bits are removed 271 assertEquals(0, authenticators & Authenticators.BIOMETRIC_MIN_STRENGTH); 272 } 273 } 274