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