1 /* 2 * Copyright (C) 2020 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.BiometricAuthenticator.TYPE_CREDENTIAL; 20 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE; 21 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; 22 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS; 23 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_NONE; 24 25 import android.annotation.IntDef; 26 import android.annotation.NonNull; 27 import android.app.admin.DevicePolicyManager; 28 import android.app.trust.ITrustManager; 29 import android.content.Context; 30 import android.hardware.biometrics.BiometricAuthenticator; 31 import android.hardware.biometrics.BiometricManager; 32 import android.hardware.biometrics.Flags; 33 import android.hardware.biometrics.PromptInfo; 34 import android.os.RemoteException; 35 import android.os.UserManager; 36 import android.util.Pair; 37 import android.util.Slog; 38 39 import com.android.internal.R; 40 import com.android.server.biometrics.sensors.LockoutTracker; 41 42 import java.lang.annotation.Retention; 43 import java.lang.annotation.RetentionPolicy; 44 import java.util.ArrayList; 45 import java.util.List; 46 47 /** 48 * Class representing the calling client's request. Additionally, derives/calculates 49 * preliminary info that would be useful in helping serve this request. Note that generating 50 * the PreAuthInfo should not change any sensor state. 51 */ 52 class PreAuthInfo { 53 static final int AUTHENTICATOR_OK = 1; 54 static final int BIOMETRIC_NO_HARDWARE = 2; 55 static final int BIOMETRIC_DISABLED_BY_DEVICE_POLICY = 3; 56 static final int BIOMETRIC_INSUFFICIENT_STRENGTH = 4; 57 static final int BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE = 5; 58 static final int BIOMETRIC_HARDWARE_NOT_DETECTED = 6; 59 static final int BIOMETRIC_NOT_ENROLLED = 7; 60 static final int BIOMETRIC_NOT_ENABLED_FOR_APPS = 8; 61 static final int CREDENTIAL_NOT_ENROLLED = 9; 62 static final int BIOMETRIC_LOCKOUT_TIMED = 10; 63 static final int BIOMETRIC_LOCKOUT_PERMANENT = 11; 64 static final int BIOMETRIC_SENSOR_PRIVACY_ENABLED = 12; 65 static final int MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR = 13; 66 private static final String TAG = "BiometricService/PreAuthInfo"; 67 final boolean credentialRequested; 68 // Sensors that can be used for this request (e.g. strong enough, enrolled, enabled). 69 final List<BiometricSensor> eligibleSensors; 70 // Sensors that cannot be used for this request. Pair<BiometricSensor, AuthenticatorStatus> 71 final List<Pair<BiometricSensor, Integer>> ineligibleSensors; 72 final boolean credentialAvailable; 73 final boolean confirmationRequested; 74 final boolean ignoreEnrollmentState; 75 final int userId; 76 final int callingUserId; 77 final Context context; 78 private final boolean mBiometricRequested; 79 private final int mBiometricStrengthRequested; 80 private final BiometricCameraManager mBiometricCameraManager; 81 private final boolean mOnlyMandatoryBiometricsRequested; 82 private final boolean mIsMandatoryBiometricsAuthentication; 83 PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested, boolean credentialRequested, List<BiometricSensor> eligibleSensors, List<Pair<BiometricSensor, Integer>> ineligibleSensors, boolean credentialAvailable, PromptInfo promptInfo, int userId, int callingUserId, Context context, BiometricCameraManager biometricCameraManager, boolean isOnlyMandatoryBiometricsRequested, boolean isMandatoryBiometricsAuthentication)84 private PreAuthInfo(boolean biometricRequested, int biometricStrengthRequested, 85 boolean credentialRequested, List<BiometricSensor> eligibleSensors, 86 List<Pair<BiometricSensor, Integer>> ineligibleSensors, boolean credentialAvailable, 87 PromptInfo promptInfo, int userId, int callingUserId, Context context, 88 BiometricCameraManager biometricCameraManager, 89 boolean isOnlyMandatoryBiometricsRequested, 90 boolean isMandatoryBiometricsAuthentication) { 91 mBiometricRequested = biometricRequested; 92 mBiometricStrengthRequested = biometricStrengthRequested; 93 mBiometricCameraManager = biometricCameraManager; 94 this.credentialRequested = credentialRequested; 95 96 this.eligibleSensors = eligibleSensors; 97 this.ineligibleSensors = ineligibleSensors; 98 this.credentialAvailable = credentialAvailable; 99 this.confirmationRequested = promptInfo.isConfirmationRequested(); 100 this.ignoreEnrollmentState = promptInfo.isIgnoreEnrollmentState(); 101 this.userId = userId; 102 this.callingUserId = callingUserId; 103 this.context = context; 104 this.mOnlyMandatoryBiometricsRequested = isOnlyMandatoryBiometricsRequested; 105 this.mIsMandatoryBiometricsAuthentication = isMandatoryBiometricsAuthentication; 106 } 107 create(ITrustManager trustManager, DevicePolicyManager devicePolicyManager, BiometricService.SettingObserver settingObserver, List<BiometricSensor> sensors, int userId, PromptInfo promptInfo, String opPackageName, boolean checkDevicePolicyManager, Context context, BiometricCameraManager biometricCameraManager, UserManager userManager)108 static PreAuthInfo create(ITrustManager trustManager, 109 DevicePolicyManager devicePolicyManager, 110 BiometricService.SettingObserver settingObserver, 111 List<BiometricSensor> sensors, 112 int userId, PromptInfo promptInfo, String opPackageName, 113 boolean checkDevicePolicyManager, Context context, 114 BiometricCameraManager biometricCameraManager, 115 UserManager userManager) 116 throws RemoteException { 117 118 final boolean isOnlyMandatoryBiometricsRequested = promptInfo.getAuthenticators() 119 == BiometricManager.Authenticators.IDENTITY_CHECK; 120 boolean isMandatoryBiometricsAuthentication = false; 121 122 final int effectiveUserId; 123 if (Flags.effectiveUserBp()) { 124 effectiveUserId = userManager.getCredentialOwnerProfile(userId); 125 } else { 126 effectiveUserId = userId; 127 } 128 129 if (dropCredentialFallback(promptInfo.getAuthenticators(), 130 settingObserver.getMandatoryBiometricsEnabledAndRequirementsSatisfiedForUser( 131 effectiveUserId), trustManager)) { 132 isMandatoryBiometricsAuthentication = true; 133 promptInfo.setAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG); 134 if (promptInfo.getNegativeButtonText() == null) { 135 promptInfo.setNegativeButtonText(context.getString(R.string.cancel)); 136 } 137 } 138 139 final boolean biometricRequested = Utils.isBiometricRequested(promptInfo); 140 final int requestedStrength = Utils.getPublicBiometricStrength(promptInfo); 141 final boolean credentialRequested = Utils.isCredentialRequested(promptInfo); 142 143 final boolean credentialAvailable = trustManager.isDeviceSecure(userId, 144 context.getDeviceId()); 145 146 // Assuming that biometric authenticators are listed in priority-order, the rest of this 147 // function will attempt to find the first authenticator that's as strong or stronger than 148 // the requested strength, available, enrolled, and enabled. The tricky part is returning 149 // the correct error. Error strings that are modality-specific should also respect the 150 // priority-order. 151 152 final List<BiometricSensor> eligibleSensors = new ArrayList<>(); 153 final List<Pair<BiometricSensor, Integer>> ineligibleSensors = new ArrayList<>(); 154 155 if (biometricRequested) { 156 for (BiometricSensor sensor : sensors) { 157 158 @AuthenticatorStatus int status = getStatusForBiometricAuthenticator( 159 devicePolicyManager, settingObserver, sensor, effectiveUserId, 160 opPackageName, checkDevicePolicyManager, requestedStrength, 161 promptInfo.getAllowedSensorIds(), promptInfo.isIgnoreEnrollmentState(), 162 biometricCameraManager); 163 164 Slog.d(TAG, "Package: " + opPackageName 165 + " Sensor ID: " + sensor.id 166 + " Modality: " + sensor.modality 167 + " User id: " + effectiveUserId 168 + " Status: " + status); 169 170 // A sensor with privacy enabled will still be eligible to 171 // authenticate with biometric prompt. This is so the framework can display 172 // a sensor privacy error message to users after briefly showing the 173 // Biometric Prompt. 174 // 175 // Note: if only a certain sensor is required and the privacy is enabled, 176 // canAuthenticate() will return false. 177 if (status == AUTHENTICATOR_OK) { 178 eligibleSensors.add(sensor); 179 } else { 180 ineligibleSensors.add(new Pair<>(sensor, status)); 181 } 182 } 183 } 184 185 return new PreAuthInfo(biometricRequested, requestedStrength, credentialRequested, 186 eligibleSensors, ineligibleSensors, credentialAvailable, promptInfo, 187 effectiveUserId, userId, context, biometricCameraManager, 188 isOnlyMandatoryBiometricsRequested, isMandatoryBiometricsAuthentication); 189 } 190 dropCredentialFallback(int authenticators, boolean isMandatoryBiometricsEnabled, ITrustManager trustManager)191 private static boolean dropCredentialFallback(int authenticators, 192 boolean isMandatoryBiometricsEnabled, ITrustManager trustManager) { 193 final boolean isMandatoryBiometricsRequested = 194 (authenticators & BiometricManager.Authenticators.IDENTITY_CHECK) 195 == BiometricManager.Authenticators.IDENTITY_CHECK; 196 if (Flags.mandatoryBiometrics() && isMandatoryBiometricsEnabled 197 && isMandatoryBiometricsRequested) { 198 try { 199 final boolean isInSignificantPlace = trustManager.isInSignificantPlace(); 200 return !isInSignificantPlace; 201 } catch (RemoteException e) { 202 Slog.e(TAG, "Remote exception while trying to check " 203 + "if user is in a trusted location."); 204 } 205 } 206 207 return false; 208 } 209 210 /** 211 * Returns the status of the authenticator, with errors returned in a specific priority order. 212 * For example, {@link #BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE} is only returned 213 * if it has enrollments, and is enabled for apps. 214 * 215 * @return @AuthenticatorStatus 216 */ 217 private static @AuthenticatorStatus getStatusForBiometricAuthenticator( DevicePolicyManager devicePolicyManager, BiometricService.SettingObserver settingObserver, BiometricSensor sensor, int userId, String opPackageName, boolean checkDevicePolicyManager, int requestedStrength, @NonNull List<Integer> requestedSensorIds, boolean ignoreEnrollmentState, BiometricCameraManager biometricCameraManager)218 int getStatusForBiometricAuthenticator( 219 DevicePolicyManager devicePolicyManager, 220 BiometricService.SettingObserver settingObserver, 221 BiometricSensor sensor, int userId, String opPackageName, 222 boolean checkDevicePolicyManager, int requestedStrength, 223 @NonNull List<Integer> requestedSensorIds, 224 boolean ignoreEnrollmentState, BiometricCameraManager biometricCameraManager) { 225 226 if (!requestedSensorIds.isEmpty() && !requestedSensorIds.contains(sensor.id)) { 227 return BIOMETRIC_NO_HARDWARE; 228 } 229 230 final boolean wasStrongEnough = 231 Utils.isAtLeastStrength(sensor.oemStrength, requestedStrength); 232 final boolean isStrongEnough = 233 Utils.isAtLeastStrength(sensor.getCurrentStrength(), requestedStrength); 234 235 if (wasStrongEnough && !isStrongEnough) { 236 return BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE; 237 } else if (!wasStrongEnough) { 238 return BIOMETRIC_INSUFFICIENT_STRENGTH; 239 } 240 241 if (sensor.modality == TYPE_FACE && biometricCameraManager.isAnyCameraUnavailable()) { 242 return BIOMETRIC_HARDWARE_NOT_DETECTED; 243 } 244 245 try { 246 if (!sensor.impl.isHardwareDetected(opPackageName)) { 247 return BIOMETRIC_HARDWARE_NOT_DETECTED; 248 } 249 250 if (!sensor.impl.hasEnrolledTemplates(userId, opPackageName) 251 && !ignoreEnrollmentState) { 252 return BIOMETRIC_NOT_ENROLLED; 253 } 254 255 if (biometricCameraManager != null && sensor.modality == TYPE_FACE) { 256 if (biometricCameraManager.isCameraPrivacyEnabled()) { 257 //Camera privacy is enabled as the access is disabled 258 return BIOMETRIC_SENSOR_PRIVACY_ENABLED; 259 } 260 } 261 262 final @LockoutTracker.LockoutMode int lockoutMode = 263 sensor.impl.getLockoutModeForUser(userId); 264 if (lockoutMode == LockoutTracker.LOCKOUT_TIMED) { 265 return BIOMETRIC_LOCKOUT_TIMED; 266 } else if (lockoutMode == LockoutTracker.LOCKOUT_PERMANENT) { 267 return BIOMETRIC_LOCKOUT_PERMANENT; 268 } 269 } catch (RemoteException e) { 270 return BIOMETRIC_HARDWARE_NOT_DETECTED; 271 } 272 273 if (!isEnabledForApp(settingObserver, sensor.modality, userId)) { 274 return BIOMETRIC_NOT_ENABLED_FOR_APPS; 275 } 276 277 if (checkDevicePolicyManager) { 278 if (isBiometricDisabledByDevicePolicy(devicePolicyManager, sensor.modality, userId)) { 279 return BIOMETRIC_DISABLED_BY_DEVICE_POLICY; 280 } 281 } 282 283 return AUTHENTICATOR_OK; 284 } 285 isEnabledForApp(BiometricService.SettingObserver settingObserver, @BiometricAuthenticator.Modality int modality, int userId)286 private static boolean isEnabledForApp(BiometricService.SettingObserver settingObserver, 287 @BiometricAuthenticator.Modality int modality, int userId) { 288 return settingObserver.getEnabledForApps(userId, modality); 289 } 290 isBiometricDisabledByDevicePolicy( DevicePolicyManager devicePolicyManager, @BiometricAuthenticator.Modality int modality, int effectiveUserId)291 private static boolean isBiometricDisabledByDevicePolicy( 292 DevicePolicyManager devicePolicyManager, @BiometricAuthenticator.Modality int modality, 293 int effectiveUserId) { 294 final int biometricToCheck = mapModalityToDevicePolicyType(modality); 295 if (biometricToCheck == DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE) { 296 throw new IllegalStateException("Modality unknown to devicePolicyManager: " + modality); 297 } 298 final int devicePolicyDisabledFeatures = 299 devicePolicyManager.getKeyguardDisabledFeatures(null, effectiveUserId); 300 final boolean isBiometricDisabled = 301 (biometricToCheck & devicePolicyDisabledFeatures) != 0; 302 Slog.w(TAG, "isBiometricDisabledByDevicePolicy(" + modality + "," + effectiveUserId 303 + ")=" + isBiometricDisabled); 304 return isBiometricDisabled; 305 } 306 307 /** 308 * @param modality one of {@link BiometricAuthenticator#TYPE_FINGERPRINT}, 309 * {@link BiometricAuthenticator#TYPE_IRIS} or 310 * {@link BiometricAuthenticator#TYPE_FACE} 311 */ mapModalityToDevicePolicyType(int modality)312 private static int mapModalityToDevicePolicyType(int modality) { 313 switch (modality) { 314 case TYPE_FINGERPRINT: 315 return DevicePolicyManager.KEYGUARD_DISABLE_FINGERPRINT; 316 case TYPE_IRIS: 317 return DevicePolicyManager.KEYGUARD_DISABLE_IRIS; 318 case TYPE_FACE: 319 return DevicePolicyManager.KEYGUARD_DISABLE_FACE; 320 default: 321 Slog.e(TAG, "Error modality=" + modality); 322 return DevicePolicyManager.KEYGUARD_DISABLE_FEATURES_NONE; 323 } 324 } 325 calculateErrorByPriority()326 private Pair<BiometricSensor, Integer> calculateErrorByPriority() { 327 Pair<BiometricSensor, Integer> sensorNotEnrolled = null; 328 Pair<BiometricSensor, Integer> sensorLockout = null; 329 Pair<BiometricSensor, Integer> hardwareNotDetected = null; 330 Pair<BiometricSensor, Integer> biometricAppNotAllowed = null; 331 for (Pair<BiometricSensor, Integer> pair : ineligibleSensors) { 332 final int status = pair.second; 333 if (status == BIOMETRIC_LOCKOUT_TIMED || status == BIOMETRIC_LOCKOUT_PERMANENT) { 334 sensorLockout = pair; 335 } 336 if (status == BIOMETRIC_NOT_ENROLLED) { 337 sensorNotEnrolled = pair; 338 } 339 if (status == BIOMETRIC_HARDWARE_NOT_DETECTED) { 340 hardwareNotDetected = pair; 341 } 342 if (status == BIOMETRIC_NOT_ENABLED_FOR_APPS) { 343 biometricAppNotAllowed = pair; 344 } 345 } 346 347 // If there is a sensor locked out, prioritize lockout over other sensor's error. 348 // See b/286923477. 349 if (sensorLockout != null) { 350 return sensorLockout; 351 } 352 353 if (hardwareNotDetected != null) { 354 return hardwareNotDetected; 355 } 356 357 if (Flags.mandatoryBiometrics() && biometricAppNotAllowed != null) { 358 return biometricAppNotAllowed; 359 } 360 361 // If the caller requested STRONG, and the device contains both STRONG and non-STRONG 362 // sensors, prioritize BIOMETRIC_NOT_ENROLLED over the weak sensor's 363 // BIOMETRIC_INSUFFICIENT_STRENGTH error. 364 if (sensorNotEnrolled != null) { 365 return sensorNotEnrolled; 366 } 367 return ineligibleSensors.get(0); 368 } 369 370 /** 371 * With {@link PreAuthInfo} generated with the requested authenticators from the public API 372 * surface, combined with the actual sensor/credential and user/system settings, calculate the 373 * internal {@link AuthenticatorStatus} that should be returned to the client. Note that this 374 * will need to be converted into the public API constant. 375 * 376 * @return Pair<Modality, Error> with error being the internal {@link AuthenticatorStatus} code 377 */ getInternalStatus()378 private Pair<Integer, Integer> getInternalStatus() { 379 @AuthenticatorStatus final int status; 380 @BiometricAuthenticator.Modality int modality = TYPE_NONE; 381 382 boolean cameraPrivacyEnabled = false; 383 if (mBiometricCameraManager != null) { 384 cameraPrivacyEnabled = mBiometricCameraManager.isCameraPrivacyEnabled(); 385 } 386 387 if (mBiometricRequested && credentialRequested) { 388 if (credentialAvailable || !eligibleSensors.isEmpty()) { 389 for (BiometricSensor sensor : eligibleSensors) { 390 modality |= sensor.modality; 391 } 392 393 if (credentialAvailable) { 394 modality |= TYPE_CREDENTIAL; 395 status = AUTHENTICATOR_OK; 396 } else if (modality == TYPE_FACE && cameraPrivacyEnabled) { 397 // If the only modality requested is face, credential is unavailable, 398 // and the face sensor privacy is enabled then return 399 // BIOMETRIC_SENSOR_PRIVACY_ENABLED. 400 // 401 // Note: This sensor will not be eligible for calls to authenticate. 402 status = BIOMETRIC_SENSOR_PRIVACY_ENABLED; 403 } else { 404 status = AUTHENTICATOR_OK; 405 } 406 } else { 407 // Pick the first sensor error if it exists 408 if (!ineligibleSensors.isEmpty()) { 409 final Pair<BiometricSensor, Integer> pair = calculateErrorByPriority(); 410 modality |= pair.first.modality; 411 status = pair.second; 412 } else { 413 modality |= TYPE_CREDENTIAL; 414 status = CREDENTIAL_NOT_ENROLLED; 415 } 416 } 417 } else if (mBiometricRequested) { 418 if (!eligibleSensors.isEmpty()) { 419 for (BiometricSensor sensor : eligibleSensors) { 420 modality |= sensor.modality; 421 } 422 if (modality == TYPE_FACE && cameraPrivacyEnabled) { 423 // If the only modality requested is face and the privacy is enabled 424 // then return BIOMETRIC_SENSOR_PRIVACY_ENABLED. 425 // 426 // Note: This sensor will not be eligible for calls to authenticate. 427 status = BIOMETRIC_SENSOR_PRIVACY_ENABLED; 428 } else { 429 status = AUTHENTICATOR_OK; 430 } 431 } else { 432 // Pick the first sensor error if it exists 433 if (!ineligibleSensors.isEmpty()) { 434 final Pair<BiometricSensor, Integer> pair = calculateErrorByPriority(); 435 modality |= pair.first.modality; 436 status = pair.second; 437 } else { 438 modality |= TYPE_NONE; 439 status = BIOMETRIC_NO_HARDWARE; 440 } 441 } 442 } else if (credentialRequested) { 443 modality |= TYPE_CREDENTIAL; 444 status = credentialAvailable ? AUTHENTICATOR_OK : CREDENTIAL_NOT_ENROLLED; 445 } else if (Flags.mandatoryBiometrics() && mOnlyMandatoryBiometricsRequested 446 && !mIsMandatoryBiometricsAuthentication) { 447 status = MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR; 448 } else { 449 // This should not be possible via the public API surface and is here mainly for 450 // "correctness". An exception should have been thrown before getting here. 451 Slog.e(TAG, "No authenticators requested"); 452 status = BIOMETRIC_NO_HARDWARE; 453 } 454 Slog.d(TAG, "getCanAuthenticateInternal Modality: " + modality 455 + " AuthenticatorStatus: " + status); 456 457 return new Pair<>(modality, status); 458 } 459 460 /** 461 * @return public BiometricManager result for the current request. 462 */ 463 @BiometricManager.BiometricError getCanAuthenticateResult()464 int getCanAuthenticateResult() { 465 // TODO: Convert this directly 466 return Utils.biometricConstantsToBiometricManager( 467 Utils.authenticatorStatusToBiometricConstant( 468 getInternalStatus().second)); 469 } 470 471 /** Returns if mandatory biometrics authentication is in effect */ getIsMandatoryBiometricsAuthentication()472 boolean getIsMandatoryBiometricsAuthentication() { 473 return mIsMandatoryBiometricsAuthentication; 474 } 475 476 477 /** 478 * For the given request, generate the appropriate reason why authentication cannot be started. 479 * Note that for some errors, modality is intentionally cleared. 480 * 481 * @return Pair<Modality, Error> with modality being filtered if necessary, and error 482 * being one of the public {@link android.hardware.biometrics.BiometricConstants} codes. 483 */ getPreAuthenticateStatus()484 Pair<Integer, Integer> getPreAuthenticateStatus() { 485 final Pair<Integer, Integer> internalStatus = getInternalStatus(); 486 487 final int publicError = Utils.authenticatorStatusToBiometricConstant(internalStatus.second); 488 int modality = internalStatus.first; 489 switch (internalStatus.second) { 490 case AUTHENTICATOR_OK: 491 case BIOMETRIC_NO_HARDWARE: 492 case BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE: 493 case BIOMETRIC_HARDWARE_NOT_DETECTED: 494 case BIOMETRIC_NOT_ENROLLED: 495 case CREDENTIAL_NOT_ENROLLED: 496 case BIOMETRIC_LOCKOUT_TIMED: 497 case BIOMETRIC_LOCKOUT_PERMANENT: 498 case BIOMETRIC_SENSOR_PRIVACY_ENABLED: 499 break; 500 501 case BIOMETRIC_DISABLED_BY_DEVICE_POLICY: 502 case BIOMETRIC_INSUFFICIENT_STRENGTH: 503 case BIOMETRIC_NOT_ENABLED_FOR_APPS: 504 default: 505 modality = TYPE_NONE; 506 break; 507 } 508 509 return new Pair<>(modality, publicError); 510 } 511 512 /** 513 * @return true if SystemUI should show the credential UI. 514 */ shouldShowCredential()515 boolean shouldShowCredential() { 516 return credentialRequested && credentialAvailable; 517 } 518 519 /** 520 * @return bitmask representing the modalities that are running or could be running for the 521 * current session. 522 */ 523 @BiometricAuthenticator.Modality getEligibleModalities()524 int getEligibleModalities() { 525 @BiometricAuthenticator.Modality int modalities = 0; 526 for (BiometricSensor sensor : eligibleSensors) { 527 modalities |= sensor.modality; 528 } 529 530 if (credentialRequested && credentialAvailable) { 531 modalities |= TYPE_CREDENTIAL; 532 } 533 return modalities; 534 } 535 numSensorsWaitingForCookie()536 int numSensorsWaitingForCookie() { 537 int numWaiting = 0; 538 for (BiometricSensor sensor : eligibleSensors) { 539 if (sensor.getSensorState() == BiometricSensor.STATE_WAITING_FOR_COOKIE) { 540 Slog.d(TAG, "Sensor ID: " + sensor.id 541 + " Waiting for cookie: " + sensor.getCookie()); 542 numWaiting++; 543 } 544 } 545 return numWaiting; 546 } 547 548 @Override toString()549 public String toString() { 550 StringBuilder string = new StringBuilder( 551 "BiometricRequested: " + mBiometricRequested 552 + ", StrengthRequested: " + mBiometricStrengthRequested 553 + ", CredentialRequested: " + credentialRequested); 554 string.append(", Eligible:{"); 555 for (BiometricSensor sensor : eligibleSensors) { 556 string.append(sensor.id).append(" "); 557 } 558 string.append("}"); 559 560 string.append(", Ineligible:{"); 561 for (Pair<BiometricSensor, Integer> ineligible : ineligibleSensors) { 562 string.append(ineligible.first).append(":").append(ineligible.second).append(" "); 563 } 564 string.append("}"); 565 566 string.append(", CredentialAvailable: ").append(credentialAvailable); 567 string.append(", "); 568 return string.toString(); 569 } 570 571 @IntDef({AUTHENTICATOR_OK, 572 BIOMETRIC_NO_HARDWARE, 573 BIOMETRIC_DISABLED_BY_DEVICE_POLICY, 574 BIOMETRIC_INSUFFICIENT_STRENGTH, 575 BIOMETRIC_INSUFFICIENT_STRENGTH_AFTER_DOWNGRADE, 576 BIOMETRIC_HARDWARE_NOT_DETECTED, 577 BIOMETRIC_NOT_ENROLLED, 578 BIOMETRIC_NOT_ENABLED_FOR_APPS, 579 CREDENTIAL_NOT_ENROLLED, 580 BIOMETRIC_LOCKOUT_TIMED, 581 BIOMETRIC_LOCKOUT_PERMANENT, 582 BIOMETRIC_SENSOR_PRIVACY_ENABLED, 583 MANDATORY_BIOMETRIC_UNAVAILABLE_ERROR}) 584 @Retention(RetentionPolicy.SOURCE) 585 @interface AuthenticatorStatus { 586 } 587 } 588