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.app.ActivityTaskManager; 43 import android.content.ComponentName; 44 import android.content.Context; 45 import android.content.pm.PackageManager; 46 import android.hardware.biometrics.BiometricAuthenticator; 47 import android.hardware.biometrics.BiometricConstants; 48 import android.hardware.biometrics.BiometricManager; 49 import android.hardware.biometrics.BiometricPrompt; 50 import android.hardware.biometrics.BiometricPrompt.AuthenticationResultType; 51 import android.hardware.biometrics.IBiometricService; 52 import android.hardware.biometrics.PromptInfo; 53 import android.hardware.biometrics.SensorProperties; 54 import android.hardware.biometrics.SensorPropertiesInternal; 55 import android.os.Binder; 56 import android.os.Build; 57 import android.os.RemoteException; 58 import android.os.ServiceManager; 59 import android.os.UserHandle; 60 import android.os.UserManager; 61 import android.provider.Settings; 62 import android.util.Slog; 63 64 import com.android.internal.R; 65 import com.android.internal.widget.LockPatternUtils; 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 case BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED: 284 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; 285 break; 286 default: 287 Slog.e(BiometricService.TAG, "Unhandled result code: " + biometricConstantsCode); 288 biometricManagerCode = BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE; 289 break; 290 } 291 return biometricManagerCode; 292 } 293 294 /** 295 * Converts a {@link BiometricPrompt} dismissal reason to an authentication type at the level of 296 * granularity supported by {@link BiometricPrompt.AuthenticationResult}. 297 * 298 * @param reason The reason that the {@link BiometricPrompt} was dismissed. Must be one of: 299 * {@link BiometricPrompt#DISMISSED_REASON_CREDENTIAL_CONFIRMED}, 300 * {@link BiometricPrompt#DISMISSED_REASON_BIOMETRIC_CONFIRMED}, or 301 * {@link BiometricPrompt#DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED} 302 * @return An integer representing the authentication type for {@link 303 * BiometricPrompt.AuthenticationResult}. 304 * @throws IllegalArgumentException if given an invalid dismissal reason. 305 */ getAuthenticationTypeForResult(int reason)306 static @AuthenticationResultType int getAuthenticationTypeForResult(int reason) { 307 switch (reason) { 308 case BiometricPrompt.DISMISSED_REASON_CREDENTIAL_CONFIRMED: 309 return BiometricPrompt.AUTHENTICATION_RESULT_TYPE_DEVICE_CREDENTIAL; 310 311 case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRMED: 312 case BiometricPrompt.DISMISSED_REASON_BIOMETRIC_CONFIRM_NOT_REQUIRED: 313 return BiometricPrompt.AUTHENTICATION_RESULT_TYPE_BIOMETRIC; 314 315 default: 316 throw new IllegalArgumentException("Unsupported dismissal reason: " + reason); 317 } 318 } 319 320 authenticatorStatusToBiometricConstant( @reAuthInfo.AuthenticatorStatus int status)321 static int authenticatorStatusToBiometricConstant( 322 @PreAuthInfo.AuthenticatorStatus int status) { 323 switch (status) { 324 case BIOMETRIC_NO_HARDWARE: 325 case BIOMETRIC_INSUFFICIENT_STRENGTH: 326 return BiometricConstants.BIOMETRIC_ERROR_HW_NOT_PRESENT; 327 328 case AUTHENTICATOR_OK: 329 return BiometricConstants.BIOMETRIC_SUCCESS; 330 331 case BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE: 332 return BiometricConstants.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED; 333 334 case BIOMETRIC_NOT_ENROLLED: 335 return BiometricConstants.BIOMETRIC_ERROR_NO_BIOMETRICS; 336 337 case CREDENTIAL_NOT_ENROLLED: 338 return BiometricConstants.BIOMETRIC_ERROR_NO_DEVICE_CREDENTIAL; 339 340 case BIOMETRIC_LOCKOUT_TIMED: 341 return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT; 342 343 case BIOMETRIC_LOCKOUT_PERMANENT: 344 return BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT; 345 case BIOMETRIC_SENSOR_PRIVACY_ENABLED: 346 return BiometricConstants.BIOMETRIC_ERROR_SENSOR_PRIVACY_ENABLED; 347 case BIOMETRIC_DISABLED_BY_DEVICE_POLICY: 348 case BIOMETRIC_HARDWARE_NOT_DETECTED: 349 case BIOMETRIC_NOT_ENABLED_FOR_APPS: 350 default: 351 return BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE; 352 } 353 } 354 isConfirmationSupported(@iometricAuthenticator.Modality int modality)355 static boolean isConfirmationSupported(@BiometricAuthenticator.Modality int modality) { 356 switch (modality) { 357 case BiometricAuthenticator.TYPE_FACE: 358 case BiometricAuthenticator.TYPE_IRIS: 359 return true; 360 default: 361 return false; 362 } 363 } 364 removeBiometricBits(@uthenticators.Types int authenticators)365 static int removeBiometricBits(@Authenticators.Types int authenticators) { 366 return authenticators & ~Authenticators.BIOMETRIC_MIN_STRENGTH; 367 } 368 listContains(int[] haystack, int needle)369 public static boolean listContains(int[] haystack, int needle) { 370 for (int i = 0; i < haystack.length; i++) { 371 if (haystack[i] == needle) { 372 return true; 373 } 374 } 375 return false; 376 } 377 checkPermission(Context context, String permission)378 public static void checkPermission(Context context, String permission) { 379 context.enforceCallingOrSelfPermission(permission, 380 "Must have " + permission + " permission."); 381 } 382 isCurrentUserOrProfile(Context context, int userId)383 public static boolean isCurrentUserOrProfile(Context context, int userId) { 384 UserManager um = UserManager.get(context); 385 if (um == null) { 386 Slog.e(TAG, "Unable to get UserManager"); 387 return false; 388 } 389 390 final long token = Binder.clearCallingIdentity(); 391 try { 392 // Allow current user or profiles of the current user... 393 for (int profileId : um.getEnabledProfileIds(ActivityManager.getCurrentUser())) { 394 if (profileId == userId) { 395 return true; 396 } 397 } 398 } finally { 399 Binder.restoreCallingIdentity(token); 400 } 401 402 return false; 403 } 404 isStrongBiometric(int sensorId)405 public static boolean isStrongBiometric(int sensorId) { 406 IBiometricService service = IBiometricService.Stub.asInterface( 407 ServiceManager.getService(Context.BIOMETRIC_SERVICE)); 408 try { 409 return Utils.isAtLeastStrength(service.getCurrentStrength(sensorId), 410 Authenticators.BIOMETRIC_STRONG); 411 } catch (RemoteException e) { 412 Slog.e(TAG, "RemoteException", e); 413 return false; 414 } 415 } 416 417 /** 418 * Returns the sensor's current strength, taking any updated strengths into effect. 419 * 420 * @param sensorId The sensor Id 421 * @return see {@link BiometricManager.Authenticators} 422 */ getCurrentStrength(int sensorId)423 public static @Authenticators.Types int getCurrentStrength(int sensorId) { 424 IBiometricService service = IBiometricService.Stub.asInterface( 425 ServiceManager.getService(Context.BIOMETRIC_SERVICE)); 426 try { 427 return service.getCurrentStrength(sensorId); 428 } catch (RemoteException e) { 429 Slog.e(TAG, "RemoteException", e); 430 return Authenticators.EMPTY_SET; 431 } 432 } 433 434 /** 435 * Checks if a client package matches Keyguard and can perform internal biometric operations. 436 * 437 * @param context The system context. 438 * @param clientPackage The name of the package to be checked against Keyguard. 439 * @return Whether the given package matches Keyguard. 440 */ isKeyguard(@onNull Context context, @Nullable String clientPackage)441 public static boolean isKeyguard(@NonNull Context context, @Nullable String clientPackage) { 442 final boolean hasPermission = hasInternalPermission(context); 443 final ComponentName keyguardComponent = ComponentName.unflattenFromString( 444 context.getResources().getString(R.string.config_keyguardComponent)); 445 final String keyguardPackage = keyguardComponent != null 446 ? keyguardComponent.getPackageName() : null; 447 return hasPermission && keyguardPackage != null && keyguardPackage.equals(clientPackage); 448 } 449 450 /** 451 * Checks if a client package matches the Android system and can perform internal biometric 452 * operations. 453 * 454 * @param context The system context. 455 * @param clientPackage The name of the package to be checked against the Android system. 456 * @return Whether the given package matches the Android system. 457 */ isSystem(@onNull Context context, @Nullable String clientPackage)458 public static boolean isSystem(@NonNull Context context, @Nullable String clientPackage) { 459 return hasInternalPermission(context) && "android".equals(clientPackage); 460 } 461 462 /** 463 * Checks if a client package matches Settings and can perform internal biometric operations. 464 * 465 * @param context The system context. 466 * @param clientPackage The name of the package to be checked against Settings. 467 * @return Whether the given package matches Settings. 468 */ isSettings(@onNull Context context, @Nullable String clientPackage)469 public static boolean isSettings(@NonNull Context context, @Nullable String clientPackage) { 470 return hasInternalPermission(context) && "com.android.settings".equals(clientPackage); 471 } 472 hasInternalPermission(@onNull Context context)473 private static boolean hasInternalPermission(@NonNull Context context) { 474 return context.checkCallingOrSelfPermission(USE_BIOMETRIC_INTERNAL) 475 == PackageManager.PERMISSION_GRANTED; 476 } 477 getClientName(@ullable BaseClientMonitor client)478 public static String getClientName(@Nullable BaseClientMonitor client) { 479 return client != null ? client.getClass().getSimpleName() : "null"; 480 } 481 containsFlag(int haystack, int needle)482 private static boolean containsFlag(int haystack, int needle) { 483 return (haystack & needle) != 0; 484 } 485 isUserEncryptedOrLockdown(@onNull LockPatternUtils lpu, int user)486 public static boolean isUserEncryptedOrLockdown(@NonNull LockPatternUtils lpu, int user) { 487 final int strongAuth = lpu.getStrongAuthForUser(user); 488 final boolean isEncrypted = containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT); 489 final boolean isLockDown = containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) 490 || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); 491 Slog.d(TAG, "isEncrypted: " + isEncrypted + " isLockdown: " + isLockDown); 492 return isEncrypted || isLockDown; 493 } 494 isForeground(int callingUid, int callingPid)495 public static boolean isForeground(int callingUid, int callingPid) { 496 try { 497 final List<ActivityManager.RunningAppProcessInfo> procs = 498 ActivityManager.getService().getRunningAppProcesses(); 499 if (procs == null) { 500 Slog.e(TAG, "No running app processes found, defaulting to true"); 501 return true; 502 } 503 504 for (int i = 0; i < procs.size(); i++) { 505 ActivityManager.RunningAppProcessInfo proc = procs.get(i); 506 if (proc.pid == callingPid && proc.uid == callingUid 507 && proc.importance <= IMPORTANCE_FOREGROUND_SERVICE) { 508 return true; 509 } 510 } 511 } catch (RemoteException e) { 512 Slog.w(TAG, "am.getRunningAppProcesses() failed"); 513 } 514 return false; 515 } 516 517 /** 518 * Converts from {@link BiometricManager.Authenticators} biometric strength to the internal 519 * {@link SensorPropertiesInternal} strength. 520 */ authenticatorStrengthToPropertyStrength( @uthenticators.Types int strength)521 public static @SensorProperties.Strength int authenticatorStrengthToPropertyStrength( 522 @Authenticators.Types int strength) { 523 switch (strength) { 524 case BiometricManager.Authenticators.BIOMETRIC_CONVENIENCE: 525 return SensorProperties.STRENGTH_CONVENIENCE; 526 case BiometricManager.Authenticators.BIOMETRIC_WEAK: 527 return SensorProperties.STRENGTH_WEAK; 528 case BiometricManager.Authenticators.BIOMETRIC_STRONG: 529 return SensorProperties.STRENGTH_STRONG; 530 default: 531 throw new IllegalArgumentException("Unknown strength: " + strength); 532 } 533 } 534 propertyStrengthToAuthenticatorStrength( @ensorProperties.Strength int strength)535 public static @Authenticators.Types int propertyStrengthToAuthenticatorStrength( 536 @SensorProperties.Strength int strength) { 537 switch (strength) { 538 case SensorProperties.STRENGTH_CONVENIENCE: 539 return Authenticators.BIOMETRIC_CONVENIENCE; 540 case SensorProperties.STRENGTH_WEAK: 541 return Authenticators.BIOMETRIC_WEAK; 542 case SensorProperties.STRENGTH_STRONG: 543 return Authenticators.BIOMETRIC_STRONG; 544 default: 545 throw new IllegalArgumentException("Unknown strength: " + strength); 546 } 547 } 548 549 /** 550 * Checks if a client package is running in the background. 551 * 552 * @param clientPackage The name of the package to be checked. 553 * @return Whether the client package is running in background 554 */ isBackground(String clientPackage)555 public static boolean isBackground(String clientPackage) { 556 Slog.v(TAG, "Checking if the authenticating is in background," 557 + " clientPackage:" + clientPackage); 558 final List<ActivityManager.RunningTaskInfo> tasks = 559 ActivityTaskManager.getInstance().getTasks(Integer.MAX_VALUE); 560 561 if (tasks == null || tasks.isEmpty()) { 562 Slog.d(TAG, "No running tasks reported"); 563 return true; 564 } 565 566 for (ActivityManager.RunningTaskInfo taskInfo : tasks) { 567 final ComponentName topActivity = taskInfo.topActivity; 568 if (topActivity != null) { 569 final String topPackage = topActivity.getPackageName(); 570 if (topPackage.contentEquals(clientPackage) && taskInfo.isVisible()) { 571 return false; 572 } else { 573 Slog.i(TAG, "Running task, top: " + topPackage 574 + ", isVisible: " + taskInfo.isVisible()); 575 } 576 } 577 } 578 579 return true; 580 } 581 } 582