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.Manifest.permission.USE_BIOMETRIC_INTERNAL; 20 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE; 21 import static android.hardware.biometrics.BiometricManager.Authenticators; 22 23 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; 24 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; 25 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; 26 import static com.android.server.biometrics.PreAuthInfo.AUTHENTICATOR_OK; 27 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_DISABLED_BY_DEVICE_POLICY; 28 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_HARDWARE_NOT_DETECTED; 29 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_INSUFFICIENT_STRENGTH; 30 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE; 31 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_LOCKOUT_PERMANENT; 32 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_LOCKOUT_TIMED; 33 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENABLED_FOR_APPS; 34 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NOT_ENROLLED; 35 import static com.android.server.biometrics.PreAuthInfo.BIOMETRIC_NO_HARDWARE; 36 import static com.android.server.biometrics.PreAuthInfo.CREDENTIAL_NOT_ENROLLED; 37 38 import android.annotation.NonNull; 39 import android.annotation.Nullable; 40 import android.app.ActivityManager; 41 import android.content.ComponentName; 42 import android.content.Context; 43 import android.content.pm.PackageManager; 44 import android.hardware.biometrics.BiometricAuthenticator; 45 import android.hardware.biometrics.BiometricConstants; 46 import android.hardware.biometrics.BiometricManager; 47 import android.hardware.biometrics.BiometricPrompt; 48 import android.hardware.biometrics.BiometricPrompt.AuthenticationResultType; 49 import android.hardware.biometrics.IBiometricService; 50 import android.hardware.biometrics.PromptInfo; 51 import android.hardware.biometrics.SensorProperties; 52 import android.hardware.biometrics.SensorPropertiesInternal; 53 import android.hardware.fingerprint.IUdfpsOverlayController; 54 import android.os.Binder; 55 import android.os.Build; 56 import android.os.RemoteException; 57 import android.os.ServiceManager; 58 import android.os.UserHandle; 59 import android.os.UserManager; 60 import android.provider.Settings; 61 import android.util.Slog; 62 63 import com.android.internal.R; 64 import com.android.internal.widget.LockPatternUtils; 65 import com.android.server.biometrics.sensors.AuthenticationClient; 66 import com.android.server.biometrics.sensors.BaseClientMonitor; 67 68 import java.util.List; 69 70 public class Utils { 71 72 private static final String TAG = "BiometricUtils"; 73 isDebugEnabled(Context context, int targetUserId)74 public static boolean isDebugEnabled(Context context, int targetUserId) { 75 if (targetUserId == UserHandle.USER_NULL) { 76 return false; 77 } 78 79 if (!(Build.IS_ENG || Build.IS_USERDEBUG)) { 80 return false; 81 } 82 83 if (Settings.Secure.getIntForUser(context.getContentResolver(), 84 Settings.Secure.BIOMETRIC_DEBUG_ENABLED, 0, 85 targetUserId) == 0) { 86 return false; 87 } 88 return true; 89 } 90 91 /** 92 * Combines {@link PromptInfo#setDeviceCredentialAllowed(boolean)} with 93 * {@link PromptInfo#setAuthenticators(int)}, as the former is not flexible enough. 94 */ combineAuthenticatorBundles(PromptInfo promptInfo)95 static void combineAuthenticatorBundles(PromptInfo promptInfo) { 96 // Cache and remove explicit ALLOW_DEVICE_CREDENTIAL boolean flag from the bundle. 97 final boolean deviceCredentialAllowed = promptInfo.isDeviceCredentialAllowed(); 98 promptInfo.setDeviceCredentialAllowed(false); 99 100 final @Authenticators.Types int authenticators; 101 if (promptInfo.getAuthenticators() != 0) { 102 // Ignore ALLOW_DEVICE_CREDENTIAL flag if AUTH_TYPES_ALLOWED is defined. 103 authenticators = promptInfo.getAuthenticators(); 104 } else { 105 // Otherwise, use ALLOW_DEVICE_CREDENTIAL flag along with Weak+ biometrics by default. 106 authenticators = deviceCredentialAllowed 107 ? Authenticators.DEVICE_CREDENTIAL | Authenticators.BIOMETRIC_WEAK 108 : Authenticators.BIOMETRIC_WEAK; 109 } 110 111 promptInfo.setAuthenticators(authenticators); 112 } 113 114 /** 115 * @param authenticators composed of one or more values from {@link Authenticators} 116 * @return true if device credential is allowed. 117 */ isCredentialRequested(@uthenticators.Types int authenticators)118 static boolean isCredentialRequested(@Authenticators.Types int authenticators) { 119 return (authenticators & Authenticators.DEVICE_CREDENTIAL) != 0; 120 } 121 122 /** 123 * @param promptInfo should be first processed by 124 * {@link #combineAuthenticatorBundles(PromptInfo)} 125 * @return true if device credential is allowed. 126 */ isCredentialRequested(PromptInfo promptInfo)127 static boolean isCredentialRequested(PromptInfo promptInfo) { 128 return isCredentialRequested(promptInfo.getAuthenticators()); 129 } 130 131 /** 132 * Checks if any of the publicly defined strengths are set. 133 * 134 * @param authenticators composed of one or more values from {@link Authenticators} 135 * @return minimal allowed biometric strength or 0 if biometric authentication is not allowed. 136 */ getPublicBiometricStrength(@uthenticators.Types int authenticators)137 static int getPublicBiometricStrength(@Authenticators.Types int authenticators) { 138 // Only biometrics WEAK and above are allowed to integrate with the public APIs. 139 return authenticators & Authenticators.BIOMETRIC_WEAK; 140 } 141 142 /** 143 * Checks if any of the publicly defined strengths are set. 144 * 145 * @param promptInfo should be first processed by 146 * {@link #combineAuthenticatorBundles(PromptInfo)} 147 * @return minimal allowed biometric strength or 0 if biometric authentication is not allowed. 148 */ getPublicBiometricStrength(PromptInfo promptInfo)149 static int getPublicBiometricStrength(PromptInfo promptInfo) { 150 return getPublicBiometricStrength(promptInfo.getAuthenticators()); 151 } 152 153 /** 154 * Checks if any of the publicly defined strengths are set. 155 * 156 * @param authenticators composed of one or more values from {@link Authenticators} 157 * @return true if biometric authentication is allowed. 158 */ isBiometricRequested(@uthenticators.Types int authenticators)159 static boolean isBiometricRequested(@Authenticators.Types int authenticators) { 160 return getPublicBiometricStrength(authenticators) != 0; 161 } 162 163 /** 164 * Checks if any of the publicly defined strengths are set. 165 * 166 * @param promptInfo should be first processed by 167 * {@link #combineAuthenticatorBundles(PromptInfo)} 168 * @return true if biometric authentication is allowed. 169 */ isBiometricRequested(PromptInfo promptInfo)170 static boolean isBiometricRequested(PromptInfo promptInfo) { 171 return getPublicBiometricStrength(promptInfo) != 0; 172 } 173 174 /** 175 * @param sensorStrength the strength of the sensor 176 * @param requestedStrength the strength that it must meet 177 * @return true only if the sensor is at least as strong as the requested strength 178 */ isAtLeastStrength(@uthenticators.Types int sensorStrength, @Authenticators.Types int requestedStrength)179 public static boolean isAtLeastStrength(@Authenticators.Types int sensorStrength, 180 @Authenticators.Types int requestedStrength) { 181 // Clear out any bits that are not reserved for biometric 182 sensorStrength &= Authenticators.BIOMETRIC_MIN_STRENGTH; 183 184 // If the authenticator contains bits outside of the requested strength, it is too weak. 185 if ((sensorStrength & ~requestedStrength) != 0) { 186 return false; 187 } 188 189 for (int i = Authenticators.BIOMETRIC_MAX_STRENGTH; 190 i <= requestedStrength; i = (i << 1) | 1) { 191 if (i == sensorStrength) { 192 return true; 193 } 194 } 195 196 Slog.e(BiometricService.TAG, "Unknown sensorStrength: " + sensorStrength 197 + ", requestedStrength: " + requestedStrength); 198 return false; 199 } 200 201 /** 202 * Checks if the authenticator configuration is a valid combination of the public APIs 203 * @param promptInfo 204 * @return 205 */ isValidAuthenticatorConfig(PromptInfo promptInfo)206 static boolean isValidAuthenticatorConfig(PromptInfo promptInfo) { 207 final int authenticators = promptInfo.getAuthenticators(); 208 return isValidAuthenticatorConfig(authenticators); 209 } 210 211 /** 212 * Checks if the authenticator configuration is a valid combination of the public APIs 213 * @param authenticators 214 * @return 215 */ isValidAuthenticatorConfig(int authenticators)216 static boolean isValidAuthenticatorConfig(int authenticators) { 217 // The caller is not required to set the authenticators. But if they do, check the below. 218 if (authenticators == 0) { 219 return true; 220 } 221 222 // Check if any of the non-biometric and non-credential bits are set. If so, this is 223 // invalid. 224 final int testBits = ~(Authenticators.DEVICE_CREDENTIAL 225 | Authenticators.BIOMETRIC_MIN_STRENGTH); 226 if ((authenticators & testBits) != 0) { 227 Slog.e(BiometricService.TAG, "Non-biometric, non-credential bits found." 228 + " Authenticators: " + authenticators); 229 return false; 230 } 231 232 // Check that biometrics bits are either NONE, WEAK, or STRONG. If NONE, DEVICE_CREDENTIAL 233 // should be set. 234 final int biometricBits = authenticators & Authenticators.BIOMETRIC_MIN_STRENGTH; 235 if (biometricBits == Authenticators.EMPTY_SET 236 && isCredentialRequested(authenticators)) { 237 return true; 238 } else if (biometricBits == Authenticators.BIOMETRIC_STRONG) { 239 return true; 240 } else if (biometricBits == Authenticators.BIOMETRIC_WEAK) { 241 return true; 242 } 243 244 Slog.e(BiometricService.TAG, "Unsupported biometric flags. Authenticators: " 245 + authenticators); 246 // Non-supported biometric flags are being used 247 return false; 248 } 249 250 /** 251 * Converts error codes from BiometricConstants, which are used in most of the internal plumbing 252 * and eventually returned to {@link BiometricPrompt.AuthenticationCallback} to public 253 * {@link BiometricManager} constants, which are used by APIs such as 254 * {@link BiometricManager#canAuthenticate(int)} 255 * 256 * @param biometricConstantsCode see {@link BiometricConstants} 257 * @return see {@link BiometricManager} 258 */ biometricConstantsToBiometricManager(int biometricConstantsCode)259 static int biometricConstantsToBiometricManager(int biometricConstantsCode) { 260 final int biometricManagerCode; 261 262 switch (biometricConstantsCode) { 263 case BiometricConstants.BIOMETRIC_SUCCESS: 264 biometricManagerCode = BiometricManager.BIOMETRIC_SUCCESS; 265 break; 266 case BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS: 267 case BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL: 268 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_NONE_ENROLLED; 269 break; 270 case BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE: 271 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; 272 break; 273 case BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT: 274 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_NO_HARDWARE; 275 break; 276 case BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED: 277 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED; 278 break; 279 case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT: 280 case BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT: 281 biometricManagerCode = BiometricManager.BIOMETRIC_SUCCESS; 282 break; 283 default: 284 Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode); 285 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; 286 break; 287 } 288 return biometricManagerCode; 289 } 290 291 /** 292 * Converts a {@link BiometricPrompt} dismissal reason to an authentication type at the level of 293 * granularity supported by {@link BiometricPrompt.AuthenticationResult}. 294 * 295 * @param reason The reason that the {@link BiometricPrompt} was dismissed. Must be one of: 296 * {@link BiometricPrompt#DISMISSED_REASON_CREDENTIAL_CONFIRMED}, 297 * {@link BiometricPrompt#DISMISSED_REASON_BIOMETRIC_CONFIRMED}, or 298 * {@link BiometricPrompt#DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED} 299 * @return An integer representing the authentication type for {@link 300 * BiometricPrompt.AuthenticationResult}. 301 * @throws IllegalArgumentException if given an invalid dismissal reason. 302 */ getAuthenticationTypeForResult(int reason)303 static @AuthenticationResultType int getAuthenticationTypeForResult(int reason) { 304 switch (reason) { 305 case BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED: 306 return BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL; 307 308 case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED: 309 case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED: 310 return BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC; 311 312 default: 313 throw new IllegalArgumentException("Unsupported dismissal reason: " + reason); 314 } 315 } 316 317 authenticatorStatusToBiometricConstant( @reAuthInfo.AuthenticatorStatus int status)318 static int authenticatorStatusToBiometricConstant( 319 @PreAuthInfo.AuthenticatorStatus int status) { 320 switch (status) { 321 case BIOMETRIC_NO_HARDWARE: 322 case BIOMETRIC_INSUFFICIENT_STRENGTH: 323 return BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT; 324 325 case AUTHENTICATOR_OK: 326 return BiometricConstants.BIOMETRIC_SUCCESS; 327 328 case BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE: 329 return BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED; 330 331 case BIOMETRIC_NOT_ENROLLED: 332 return BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS; 333 334 case CREDENTIAL_NOT_ENROLLED: 335 return BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL; 336 337 case BIOMETRIC_LOCKOUT_TIMED: 338 return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT; 339 340 case BIOMETRIC_LOCKOUT_PERMANENT: 341 return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; 342 343 case BIOMETRIC_DISABLED_BY_DEVICE_POLICY: 344 case BIOMETRIC_HARDWARE_NOT_DETECTED: 345 case BIOMETRIC_NOT_ENABLED_FOR_APPS: 346 default: 347 return BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE; 348 } 349 } 350 isConfirmationSupported(@iometricAuthenticator.Modality int modality)351 static boolean isConfirmationSupported(@BiometricAuthenticator.Modality int modality) { 352 switch (modality) { 353 case BiometricAuthenticator.TYPE_FACE: 354 case BiometricAuthenticator.TYPE_IRIS: 355 return true; 356 default: 357 return false; 358 } 359 } 360 removeBiometricBits(@uthenticators.Types int authenticators)361 static int removeBiometricBits(@Authenticators.Types int authenticators) { 362 return authenticators & ~Authenticators.BIOMETRIC_MIN_STRENGTH; 363 } 364 listContains(int[] haystack, int needle)365 public static boolean listContains(int[] haystack, int needle) { 366 for (int i = 0; i < haystack.length; i++) { 367 if (haystack[i] == needle) { 368 return true; 369 } 370 } 371 return false; 372 } 373 checkPermission(Context context, String permission)374 public static void checkPermission(Context context, String permission) { 375 context.enforceCallingOrSelfPermission(permission, 376 "Must have " + permission + " permission."); 377 } 378 isCurrentUserOrProfile(Context context, int userId)379 public static boolean isCurrentUserOrProfile(Context context, int userId) { 380 UserManager um = UserManager.get(context); 381 if (um == null) { 382 Slog.e(TAG, "Unable to get UserManager"); 383 return false; 384 } 385 386 final long token = Binder.clearCallingIdentity(); 387 try { 388 // Allow current user or profiles of the current user... 389 for (int profileId : um.getEnabledProfileIds(ActivityManager.getCurrentUser())) { 390 if (profileId == userId) { 391 return true; 392 } 393 } 394 } finally { 395 Binder.restoreCallingIdentity(token); 396 } 397 398 return false; 399 } 400 isStrongBiometric(int sensorId)401 public static boolean isStrongBiometric(int sensorId) { 402 IBiometricService service = IBiometricService.Stub.asInterface( 403 ServiceManager.getService(Context.BIOMETRIC_SERVICE)); 404 try { 405 return Utils.isAtLeastStrength(service.getCurrentStrength(sensorId), 406 Authenticators.BIOMETRIC_STRONG); 407 } catch (RemoteException e) { 408 Slog.e(TAG, "RemoteException", e); 409 return false; 410 } 411 } 412 413 /** 414 * Returns the sensor's current strength, taking any updated strengths into effect. 415 * 416 * @param sensorId The sensor Id 417 * @return see {@link BiometricManager.Authenticators} 418 */ getCurrentStrength(int sensorId)419 public static @Authenticators.Types int getCurrentStrength(int sensorId) { 420 IBiometricService service = IBiometricService.Stub.asInterface( 421 ServiceManager.getService(Context.BIOMETRIC_SERVICE)); 422 try { 423 return service.getCurrentStrength(sensorId); 424 } catch (RemoteException e) { 425 Slog.e(TAG, "RemoteException", e); 426 return Authenticators.EMPTY_SET; 427 } 428 } 429 430 /** 431 * Checks if a client package matches Keyguard and can perform internal biometric operations. 432 * 433 * @param context The system context. 434 * @param clientPackage The name of the package to be checked against Keyguard. 435 * @return Whether the given package matches Keyguard. 436 */ isKeyguard(@onNull Context context, @Nullable String clientPackage)437 public static boolean isKeyguard(@NonNull Context context, @Nullable String clientPackage) { 438 final boolean hasPermission = hasInternalPermission(context); 439 final ComponentName keyguardComponent = ComponentName.unflattenFromString( 440 context.getResources().getString(R.string.config_keyguardComponent)); 441 final String keyguardPackage = keyguardComponent != null 442 ? keyguardComponent.getPackageName() : null; 443 return hasPermission && keyguardPackage != null && keyguardPackage.equals(clientPackage); 444 } 445 446 /** 447 * Checks if a client package matches the Android system and can perform internal biometric 448 * operations. 449 * 450 * @param context The system context. 451 * @param clientPackage The name of the package to be checked against the Android system. 452 * @return Whether the given package matches the Android system. 453 */ isSystem(@onNull Context context, @Nullable String clientPackage)454 public static boolean isSystem(@NonNull Context context, @Nullable String clientPackage) { 455 return hasInternalPermission(context) && "android".equals(clientPackage); 456 } 457 458 /** 459 * Checks if a client package matches Settings and can perform internal biometric operations. 460 * 461 * @param context The system context. 462 * @param clientPackage The name of the package to be checked against Settings. 463 * @return Whether the given package matches Settings. 464 */ isSettings(@onNull Context context, @Nullable String clientPackage)465 public static boolean isSettings(@NonNull Context context, @Nullable String clientPackage) { 466 return hasInternalPermission(context) && "com.android.settings".equals(clientPackage); 467 } 468 hasInternalPermission(@onNull Context context)469 private static boolean hasInternalPermission(@NonNull Context context) { 470 return context.checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL) 471 == PackageManager.PERMISSION_GRANTED; 472 } 473 getClientName(@ullable BaseClientMonitor client)474 public static String getClientName(@Nullable BaseClientMonitor client) { 475 return client != null ? client.getClass().getSimpleName() : "null"; 476 } 477 containsFlag(int haystack, int needle)478 private static boolean containsFlag(int haystack, int needle) { 479 return (haystack & needle) != 0; 480 } 481 isUserEncryptedOrLockdown(@onNull LockPatternUtils lpu, int user)482 public static boolean isUserEncryptedOrLockdown(@NonNull LockPatternUtils lpu, int user) { 483 final int strongAuth = lpu.getStrongAuthForUser(user); 484 final boolean isEncrypted = containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT); 485 final boolean isLockDown = containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) 486 || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); 487 Slog.d(TAG, "isEncrypted: " + isEncrypted + " isLockdown: " + isLockDown); 488 return isEncrypted || isLockDown; 489 } 490 isForeground(int callingUid, int callingPid)491 public static boolean isForeground(int callingUid, int callingPid) { 492 try { 493 final List<ActivityManager.RunningAppProcessInfo> procs = 494 ActivityManager.getService().getRunningAppProcesses(); 495 if (procs == null) { 496 Slog.e(TAG, "No running app processes found, defaulting to true"); 497 return true; 498 } 499 500 for (int i = 0; i < procs.size(); i++) { 501 ActivityManager.RunningAppProcessInfo proc = procs.get(i); 502 if (proc.pid == callingPid && proc.uid == callingUid 503 && proc.importance <= IMPORTANCE_FOREGROUND_SERVICE) { 504 return true; 505 } 506 } 507 } catch (RemoteException e) { 508 Slog.w(TAG, "am.getRunningAppProcesses() failed"); 509 } 510 return false; 511 } 512 513 /** 514 * Converts from {@link BiometricManager.Authenticators} biometric strength to the internal 515 * {@link SensorPropertiesInternal} strength. 516 */ authenticatorStrengthToPropertyStrength( @uthenticators.Types int strength)517 public static @SensorProperties.Strength int authenticatorStrengthToPropertyStrength( 518 @Authenticators.Types int strength) { 519 switch (strength) { 520 case BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE: 521 return SensorProperties.STRENGTH_CONVENIENCE; 522 case BiometricManager.Authenticators.BIOMETRIC_WEAK: 523 return SensorProperties.STRENGTH_WEAK; 524 case BiometricManager.Authenticators.BIOMETRIC_STRONG: 525 return SensorProperties.STRENGTH_STRONG; 526 default: 527 throw new IllegalArgumentException("Unknown strength: " + strength); 528 } 529 } 530 propertyStrengthToAuthenticatorStrength( @ensorProperties.Strength int strength)531 public static @Authenticators.Types int propertyStrengthToAuthenticatorStrength( 532 @SensorProperties.Strength int strength) { 533 switch (strength) { 534 case SensorProperties.STRENGTH_CONVENIENCE: 535 return Authenticators.BIOMETRIC_CONVENIENCE; 536 case SensorProperties.STRENGTH_WEAK: 537 return Authenticators.BIOMETRIC_WEAK; 538 case SensorProperties.STRENGTH_STRONG: 539 return Authenticators.BIOMETRIC_STRONG; 540 default: 541 throw new IllegalArgumentException("Unknown strength: " + strength); 542 } 543 } 544 getUdfpsAuthReason(@onNull AuthenticationClient<?> client)545 public static int getUdfpsAuthReason(@NonNull AuthenticationClient<?> client) { 546 if (client.isKeyguard()) { 547 return IUdfpsOverlayController.REASON_AUTH_FPM_KEYGUARD; 548 } else if (client.isBiometricPrompt()) { 549 return IUdfpsOverlayController.REASON_AUTH_BP; 550 } else { 551 return IUdfpsOverlayController.REASON_AUTH_FPM_OTHER; 552 } 553 } 554 } 555