Merge "For non-udfps, detectFP if primaryAuth required"

This commit is contained in:
TreeHugger Robot
2022-11-29 19:57:29 +00:00
committed by Android (Google) Code Review
11 changed files with 164 additions and 125 deletions

View File

@@ -26,7 +26,6 @@ data class KeyguardFingerprintListenModel(
val credentialAttempted: Boolean,
val deviceInteractive: Boolean,
val dreaming: Boolean,
val encryptedOrLockdown: Boolean,
val fingerprintDisabled: Boolean,
val fingerprintLockedOut: Boolean,
val goingToSleep: Boolean,
@@ -37,6 +36,7 @@ data class KeyguardFingerprintListenModel(
val primaryUser: Boolean,
val shouldListenSfpsState: Boolean,
val shouldListenForFingerprintAssistant: Boolean,
val strongerAuthRequired: Boolean,
val switchingUser: Boolean,
val udfps: Boolean,
val userDoesNotHaveTrust: Boolean

View File

@@ -363,16 +363,18 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
final boolean sfpsEnabled = getResources().getBoolean(
R.bool.config_show_sidefps_hint_on_bouncer);
final boolean fpsDetectionRunning = mUpdateMonitor.isFingerprintDetectionRunning();
final boolean needsStrongAuth = mUpdateMonitor.userNeedsStrongAuth();
final boolean isUnlockingWithFpAllowed =
mUpdateMonitor.isUnlockingWithFingerprintAllowed();
boolean toShow = mBouncerVisible && sfpsEnabled && fpsDetectionRunning && !needsStrongAuth;
boolean toShow = mBouncerVisible && sfpsEnabled && fpsDetectionRunning
&& isUnlockingWithFpAllowed;
if (DEBUG) {
Log.d(TAG, "sideFpsToShow=" + toShow + ", "
+ "mBouncerVisible=" + mBouncerVisible + ", "
+ "configEnabled=" + sfpsEnabled + ", "
+ "fpsDetectionRunning=" + fpsDetectionRunning + ", "
+ "needsStrongAuth=" + needsStrongAuth);
+ "isUnlockingWithFpAllowed=" + isUnlockingWithFpAllowed);
}
if (toShow) {
mSideFpsController.get().show(SideFpsUiRequestSource.PRIMARY_BOUNCER);

View File

@@ -27,6 +27,8 @@ import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_P
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_LOCKOUT_TIMED;
import static android.hardware.biometrics.BiometricConstants.LockoutMode;
import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_START;
import static android.hardware.biometrics.BiometricSourceType.FACE;
import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT;
import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
@@ -228,7 +230,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
* Biometric authentication: Cancelling and waiting for the relevant biometric service to
* send us the confirmation that cancellation has happened.
*/
private static final int BIOMETRIC_STATE_CANCELLING = 2;
@VisibleForTesting
protected static final int BIOMETRIC_STATE_CANCELLING = 2;
/**
* Biometric state: During cancelling we got another request to start listening, so when we
* receive the cancellation done signal, we should start listening again.
*/
@VisibleForTesting
protected static final int BIOMETRIC_STATE_CANCELLING_RESTARTING = 3;
/**
* Action indicating keyguard *can* start biometric authentiation.
@@ -243,12 +253,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
*/
private static final int BIOMETRIC_ACTION_UPDATE = 2;
/**
* Biometric state: During cancelling we got another request to start listening, so when we
* receive the cancellation done signal, we should start listening again.
*/
private static final int BIOMETRIC_STATE_CANCELLING_RESTARTING = 3;
@VisibleForTesting
public static final int BIOMETRIC_HELP_FINGERPRINT_NOT_RECOGNIZED = -1;
public static final int BIOMETRIC_HELP_FACE_NOT_RECOGNIZED = -2;
@@ -356,7 +360,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
private KeyguardBypassController mKeyguardBypassController;
private List<SubscriptionInfo> mSubscriptionInfo;
private int mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
@VisibleForTesting
protected int mFingerprintRunningState = BIOMETRIC_STATE_STOPPED;
private int mFaceRunningState = BIOMETRIC_STATE_STOPPED;
private boolean mIsDreaming;
private boolean mLogoutEnabled;
@@ -790,7 +795,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
new BiometricAuthenticated(true, isStrongBiometric));
// Update/refresh trust state only if user can skip bouncer
if (getUserCanSkipBouncer(userId)) {
mTrustManager.unlockedByBiometricForUser(userId, BiometricSourceType.FINGERPRINT);
mTrustManager.unlockedByBiometricForUser(userId, FINGERPRINT);
}
// Don't send cancel if authentication succeeds
mFingerprintCancelSignal = null;
@@ -800,7 +805,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricAuthenticated(userId, BiometricSourceType.FINGERPRINT,
cb.onBiometricAuthenticated(userId, FINGERPRINT,
isStrongBiometric);
}
}
@@ -833,7 +838,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
cb.onBiometricAuthFailed(FINGERPRINT);
}
}
if (isUdfpsSupported()) {
@@ -858,7 +863,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricAcquired(BiometricSourceType.FINGERPRINT, acquireInfo);
cb.onBiometricAcquired(FINGERPRINT, acquireInfo);
}
}
}
@@ -892,7 +897,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricHelp(msgId, helpString, BiometricSourceType.FINGERPRINT);
cb.onBiometricHelp(msgId, helpString, FINGERPRINT);
}
}
}
@@ -944,7 +949,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
if (msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
lockedOutStateChanged = !mFingerprintLockedOutPermanent;
mFingerprintLockedOutPermanent = true;
mLogger.d("Fingerprint locked out - requiring strong auth");
mLogger.d("Fingerprint permanently locked out - requiring stronger auth");
mLockPatternUtils.requireStrongAuth(
STRONG_AUTH_REQUIRED_AFTER_LOCKOUT, getCurrentUser());
}
@@ -953,6 +958,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
|| msgId == FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT) {
lockedOutStateChanged |= !mFingerprintLockedOut;
mFingerprintLockedOut = true;
mLogger.d("Fingerprint temporarily locked out - requiring stronger auth");
if (isUdfpsEnrolled()) {
updateFingerprintListeningState(BIOMETRIC_ACTION_UPDATE);
}
@@ -963,12 +969,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricError(msgId, errString, BiometricSourceType.FINGERPRINT);
cb.onBiometricError(msgId, errString, FINGERPRINT);
}
}
if (lockedOutStateChanged) {
notifyLockedOutStateChanged(BiometricSourceType.FINGERPRINT);
notifyLockedOutStateChanged(FINGERPRINT);
}
}
@@ -996,7 +1002,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
if (changed) {
notifyLockedOutStateChanged(BiometricSourceType.FINGERPRINT);
notifyLockedOutStateChanged(FINGERPRINT);
}
}
@@ -1019,7 +1025,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricRunningStateChanged(isFingerprintDetectionRunning(),
BiometricSourceType.FINGERPRINT);
FINGERPRINT);
}
}
}
@@ -1032,7 +1038,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
new BiometricAuthenticated(true, isStrongBiometric));
// Update/refresh trust state only if user can skip bouncer
if (getUserCanSkipBouncer(userId)) {
mTrustManager.unlockedByBiometricForUser(userId, BiometricSourceType.FACE);
mTrustManager.unlockedByBiometricForUser(userId, FACE);
}
// Don't send cancel if authentication succeeds
mFaceCancelSignal = null;
@@ -1043,7 +1049,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricAuthenticated(userId,
BiometricSourceType.FACE,
FACE,
isStrongBiometric);
}
}
@@ -1065,7 +1071,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricAuthFailed(BiometricSourceType.FACE);
cb.onBiometricAuthFailed(FACE);
}
}
handleFaceHelp(BIOMETRIC_HELP_FACE_NOT_RECOGNIZED,
@@ -1078,7 +1084,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricAcquired(BiometricSourceType.FACE, acquireInfo);
cb.onBiometricAcquired(FACE, acquireInfo);
}
}
}
@@ -1113,7 +1119,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
for (int i = 0; i < mCallbacks.size(); i++) {
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricHelp(msgId, helpString, BiometricSourceType.FACE);
cb.onBiometricHelp(msgId, helpString, FACE);
}
}
}
@@ -1181,12 +1187,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricError(msgId, errString,
BiometricSourceType.FACE);
FACE);
}
}
if (lockedOutStateChanged) {
notifyLockedOutStateChanged(BiometricSourceType.FACE);
notifyLockedOutStateChanged(FACE);
}
}
@@ -1200,7 +1206,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
FACE_AUTH_TRIGGERED_FACE_LOCKOUT_RESET), getBiometricLockoutDelay());
if (changed) {
notifyLockedOutStateChanged(BiometricSourceType.FACE);
notifyLockedOutStateChanged(FACE);
}
}
@@ -1223,7 +1229,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
if (cb != null) {
cb.onBiometricRunningStateChanged(isFaceDetectionRunning(),
BiometricSourceType.FACE);
FACE);
}
}
}
@@ -1364,7 +1370,39 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) {
return mStrongAuthTracker.isUnlockingWithBiometricAllowed(isStrongBiometric);
// StrongAuthTracker#isUnlockingWithBiometricAllowed includes
// STRONG_AUTH_REQUIRED_AFTER_LOCKOUT which is the same as mFingerprintLockedOutPermanent;
// however the strong auth tracker does not include the temporary lockout
// mFingerprintLockedOut.
return mStrongAuthTracker.isUnlockingWithBiometricAllowed(isStrongBiometric)
&& !mFingerprintLockedOut;
}
private boolean isUnlockingWithFaceAllowed() {
return mStrongAuthTracker.isUnlockingWithBiometricAllowed(false);
}
/**
* Whether fingerprint is allowed ot be used for unlocking based on the strongAuthTracker
* and temporary lockout state (tracked by FingerprintManager via error codes).
*/
public boolean isUnlockingWithFingerprintAllowed() {
return isUnlockingWithBiometricAllowed(true);
}
/**
* Whether the given biometric is allowed based on strongAuth & lockout states.
*/
public boolean isUnlockingWithBiometricAllowed(
@NonNull BiometricSourceType biometricSourceType) {
switch (biometricSourceType) {
case FINGERPRINT:
return isUnlockingWithFingerprintAllowed();
case FACE:
return isUnlockingWithFaceAllowed();
default:
return false;
}
}
public boolean isUserInLockdown(int userId) {
@@ -1386,11 +1424,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
return isEncrypted || isLockDown;
}
public boolean userNeedsStrongAuth() {
return mStrongAuthTracker.getStrongAuthForUser(getCurrentUser())
!= LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
}
private boolean containsFlag(int haystack, int needle) {
return (haystack & needle) != 0;
}
@@ -1560,12 +1593,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
};
private final FingerprintManager.FingerprintDetectionCallback mFingerprintDetectionCallback
= (sensorId, userId, isStrongBiometric) -> {
// Trigger the fingerprint success path so the bouncer can be shown
handleFingerprintAuthenticated(userId, isStrongBiometric);
};
/**
* Propagates a pointer down event to keyguard.
*/
@@ -2636,27 +2663,25 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
&& (!mKeyguardGoingAway || !mDeviceInteractive)
&& mIsPrimaryUser
&& biometricEnabledForUser;
final boolean shouldListenBouncerState = !(mFingerprintLockedOut
&& mPrimaryBouncerIsOrWillBeShowing && mCredentialAttempted);
final boolean isEncryptedOrLockdownForUser = isEncryptedOrLockdown(user);
final boolean strongerAuthRequired = !isUnlockingWithFingerprintAllowed();
final boolean isSideFps = isSfpsSupported() && isSfpsEnrolled();
final boolean shouldListenBouncerState =
!strongerAuthRequired || !mPrimaryBouncerIsOrWillBeShowing;
final boolean shouldListenUdfpsState = !isUdfps
|| (!userCanSkipBouncer
&& !isEncryptedOrLockdownForUser
&& !strongerAuthRequired
&& userDoesNotHaveTrust);
boolean shouldListenSideFpsState = true;
if (isSfpsSupported() && isSfpsEnrolled()) {
if (isSideFps) {
shouldListenSideFpsState =
mSfpsRequireScreenOnToAuthPrefEnabled ? isDeviceInteractive() : true;
}
boolean shouldListen = shouldListenKeyguardState && shouldListenUserState
&& shouldListenBouncerState && shouldListenUdfpsState && !isFingerprintLockedOut()
&& shouldListenBouncerState && shouldListenUdfpsState
&& shouldListenSideFpsState;
maybeLogListenerModelData(
new KeyguardFingerprintListenModel(
System.currentTimeMillis(),
@@ -2668,7 +2693,6 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mCredentialAttempted,
mDeviceInteractive,
mIsDreaming,
isEncryptedOrLockdownForUser,
fingerprintDisabledForUser,
mFingerprintLockedOut,
mGoingToSleep,
@@ -2679,6 +2703,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
mIsPrimaryUser,
shouldListenSideFpsState,
shouldListenForFingerprintAssistant,
strongerAuthRequired,
mSwitchingUser,
isUdfps,
userDoesNotHaveTrust));
@@ -2706,10 +2731,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
final boolean isEncryptedOrTimedOut =
containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT)
|| containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT);
// TODO: always disallow when fp is already locked out?
final boolean fpLockedOut = mFingerprintLockedOut || mFingerprintLockedOutPermanent;
final boolean fpLockedOut = isFingerprintLockedOut();
final boolean canBypass = mKeyguardBypassController != null
&& mKeyguardBypassController.canBypass();
// There's no reason to ask the HAL for authentication when the user can dismiss the
@@ -2831,15 +2853,22 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
// Waiting for restart via handleFingerprintError().
return;
}
mLogger.v("startListeningForFingerprint()");
if (unlockPossible) {
mFingerprintCancelSignal = new CancellationSignal();
if (isEncryptedOrLockdown(userId)) {
mFpm.detectFingerprint(mFingerprintCancelSignal, mFingerprintDetectionCallback,
if (!isUnlockingWithFingerprintAllowed()) {
mLogger.v("startListeningForFingerprint - detect");
mFpm.detectFingerprint(
mFingerprintCancelSignal,
(sensorId, user, isStrongBiometric) -> {
mLogger.d("fingerprint detected");
// Trigger the fingerprint success path so the bouncer can be shown
handleFingerprintAuthenticated(user, isStrongBiometric);
},
userId);
} else {
mLogger.v("startListeningForFingerprint - authenticate");
mFpm.authenticate(null /* crypto */, mFingerprintCancelSignal,
mFingerprintAuthenticationCallback, null /* handler */,
FingerprintManager.SENSOR_ID_ANY, userId, 0 /* flags */);
@@ -3056,11 +3085,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
}
}
// Immediately stop previous biometric listening states.
// Resetting lockout states updates the biometric listening states.
if (mFaceManager != null && !mFaceSensorProperties.isEmpty()) {
stopListeningForFace(FACE_AUTH_UPDATED_USER_SWITCHING);
handleFaceLockoutReset(mFaceManager.getLockoutModeForUser(
mFaceSensorProperties.get(0).sensorId, userId));
}
if (mFpm != null && !mFingerprintSensorProperties.isEmpty()) {
stopListeningForFingerprint();
handleFingerprintLockoutReset(mFpm.getLockoutModeForUser(
mFingerprintSensorProperties.get(0).sensorId, userId));
}
@@ -3467,7 +3500,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
@AnyThread
public void setSwitchingUser(boolean switching) {
mSwitchingUser = switching;
// Since this comes in on a binder thread, we need to post if first
// Since this comes in on a binder thread, we need to post it first
mHandler.post(() -> updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE,
FACE_AUTH_UPDATED_USER_SWITCHING));
}
@@ -3559,8 +3592,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab
Assert.isMainThread();
mUserFingerprintAuthenticated.clear();
mUserFaceAuthenticated.clear();
mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FINGERPRINT, unlockedUser);
mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FACE, unlockedUser);
mTrustManager.clearAllBiometricRecognized(FINGERPRINT, unlockedUser);
mTrustManager.clearAllBiometricRecognized(FACE, unlockedUser);
mLogger.d("clearBiometricRecognized");
for (int i = 0; i < mCallbacks.size(); i++) {

View File

@@ -116,9 +116,9 @@ class AuthRippleController @Inject constructor(
notificationShadeWindowController.setForcePluginOpen(false, this)
}
fun showUnlockRipple(biometricSourceType: BiometricSourceType?) {
fun showUnlockRipple(biometricSourceType: BiometricSourceType) {
if (!keyguardStateController.isShowing ||
keyguardUpdateMonitor.userNeedsStrongAuth()) {
!keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(biometricSourceType)) {
return
}
@@ -246,7 +246,7 @@ class AuthRippleController @Inject constructor(
object : KeyguardUpdateMonitorCallback() {
override fun onBiometricAuthenticated(
userId: Int,
biometricSourceType: BiometricSourceType?,
biometricSourceType: BiometricSourceType,
isStrongBiometric: Boolean
) {
if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
@@ -255,14 +255,14 @@ class AuthRippleController @Inject constructor(
showUnlockRipple(biometricSourceType)
}
override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType?) {
override fun onBiometricAuthFailed(biometricSourceType: BiometricSourceType) {
if (biometricSourceType == BiometricSourceType.FINGERPRINT) {
mView.retractDwellRipple()
}
}
override fun onBiometricAcquired(
biometricSourceType: BiometricSourceType?,
biometricSourceType: BiometricSourceType,
acquireInfo: Int
) {
if (biometricSourceType == BiometricSourceType.FINGERPRINT &&

View File

@@ -17,6 +17,7 @@
package com.android.systemui.keyguard.domain.interactor
import android.content.res.ColorStateList
import android.hardware.biometrics.BiometricSourceType
import android.os.Handler
import android.os.Trace
import android.os.UserHandle
@@ -71,7 +72,7 @@ constructor(
KeyguardUpdateMonitor.getCurrentUser()
) &&
!needsFullscreenBouncer() &&
!keyguardUpdateMonitor.userNeedsStrongAuth() &&
keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE) &&
!keyguardBypassController.bypassEnabled
/** Runnable to show the primary bouncer. */

View File

@@ -240,8 +240,8 @@ public class KeyguardBouncer {
&& !mKeyguardUpdateMonitor.getCachedIsUnlockWithFingerprintPossible(
KeyguardUpdateMonitor.getCurrentUser())
&& !needsFullscreenBouncer()
&& !mKeyguardUpdateMonitor.isFaceLockedOut()
&& !mKeyguardUpdateMonitor.userNeedsStrongAuth()
&& mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
BiometricSourceType.FACE)
&& !mKeyguardBypassController.getBypassEnabled()) {
mHandler.postDelayed(mShowRunnable, BOUNCER_FACE_DELAY);
} else {

View File

@@ -63,7 +63,6 @@ private fun fingerprintModel(user: Int) = KeyguardFingerprintListenModel(
credentialAttempted = false,
deviceInteractive = false,
dreaming = false,
encryptedOrLockdown = false,
fingerprintDisabled = false,
fingerprintLockedOut = false,
goingToSleep = false,
@@ -74,6 +73,7 @@ private fun fingerprintModel(user: Int) = KeyguardFingerprintListenModel(
primaryUser = false,
shouldListenSfpsState = false,
shouldListenForFingerprintAssistant = false,
strongerAuthRequired = false,
switchingUser = false,
udfps = false,
userDoesNotHaveTrust = false

View File

@@ -379,9 +379,9 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
}
@Test
public void onBouncerVisibilityChanged_needsStrongAuth_sideFpsHintHidden() {
public void onBouncerVisibilityChanged_unlockingWithFingerprintNotAllowed_sideFpsHintHidden() {
setupConditionsToEnableSideFpsHint();
setNeedsStrongAuth(true);
setUnlockingWithFingerprintAllowed(false);
reset(mSideFpsController);
mKeyguardSecurityContainerController.onBouncerVisibilityChanged(View.VISIBLE);
@@ -574,7 +574,7 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
attachView();
setSideFpsHintEnabledFromResources(true);
setFingerprintDetectionRunning(true);
setNeedsStrongAuth(false);
setUnlockingWithFingerprintAllowed(true);
}
private void attachView() {
@@ -593,9 +593,8 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
enabled);
}
private void setNeedsStrongAuth(boolean needed) {
when(mKeyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(needed);
mKeyguardUpdateMonitorCallback.getValue().onStrongAuthStateChanged(/* userId= */ 0);
private void setUnlockingWithFingerprintAllowed(boolean allowed) {
when(mKeyguardUpdateMonitor.isUnlockingWithFingerprintAllowed()).thenReturn(allowed);
}
private void setupGetSecurityView() {

View File

@@ -28,6 +28,7 @@ import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT;
import static com.android.keyguard.FaceAuthApiRequestReason.NOTIFICATION_PANEL_CLICKED;
import static com.android.keyguard.KeyguardUpdateMonitor.BIOMETRIC_STATE_CANCELLING_RESTARTING;
import static com.android.keyguard.KeyguardUpdateMonitor.DEFAULT_CANCEL_SIGNAL_TIMEOUT;
import static com.android.keyguard.KeyguardUpdateMonitor.getCurrentUser;
@@ -281,7 +282,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
componentInfo, FaceSensorProperties.TYPE_UNKNOWN,
false /* supportsFaceDetection */, true /* supportsSelfIllumination */,
false /* resetLockoutRequiresChallenge */));
when(mFingerprintManager.isHardwareDetected()).thenReturn(true);
when(mFingerprintManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
when(mFingerprintManager.getSensorPropertiesInternal()).thenReturn(List.of(
@@ -594,30 +594,13 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
}
@Test
public void testFingerprintDoesNotAuth_whenEncrypted() {
testFingerprintWhenStrongAuth(
STRONG_AUTH_REQUIRED_AFTER_BOOT);
}
@Test
public void testFingerprintDoesNotAuth_whenDpmLocked() {
testFingerprintWhenStrongAuth(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW);
}
@Test
public void testFingerprintDoesNotAuth_whenUserLockdown() {
testFingerprintWhenStrongAuth(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
}
private void testFingerprintWhenStrongAuth(int strongAuth) {
public void testOnlyDetectFingerprint_whenFingerprintUnlockNotAllowed() {
// Clear invocations, since previous setup (e.g. registering BiometricManager callbacks)
// will trigger updateBiometricListeningState();
clearInvocations(mFingerprintManager);
mKeyguardUpdateMonitor.resetBiometricListeningState();
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(strongAuth);
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
mKeyguardUpdateMonitor.dispatchStartedGoingToSleep(0 /* why */);
mTestableLooper.processAllMessages();
@@ -928,10 +911,6 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
faceLockoutMode != BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
final boolean fpLocked =
fingerprintLockoutMode != BiometricConstants.BIOMETRIC_LOCKOUT_NONE;
when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), eq(newUser)))
.thenReturn(fingerprintLockoutMode);
when(mFaceManager.getLockoutModeForUser(eq(FACE_SENSOR_ID), eq(newUser)))
.thenReturn(faceLockoutMode);
mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON);
mTestableLooper.processAllMessages();
@@ -940,7 +919,13 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt(), anyBoolean());
verify(mFingerprintManager).authenticate(any(), any(), any(), any(), anyInt(), anyInt(),
anyInt());
// resetFaceManager();
// resetFingerprintManager();
when(mFingerprintManager.getLockoutModeForUser(eq(FINGERPRINT_SENSOR_ID), eq(newUser)))
.thenReturn(fingerprintLockoutMode);
when(mFaceManager.getLockoutModeForUser(eq(FACE_SENSOR_ID), eq(newUser)))
.thenReturn(faceLockoutMode);
final CancellationSignal faceCancel = spy(mKeyguardUpdateMonitor.mFaceCancelSignal);
final CancellationSignal fpCancel = spy(mKeyguardUpdateMonitor.mFingerprintCancelSignal);
mKeyguardUpdateMonitor.mFaceCancelSignal = faceCancel;
@@ -951,14 +936,22 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
mKeyguardUpdateMonitor.handleUserSwitchComplete(newUser);
mTestableLooper.processAllMessages();
verify(faceCancel, faceLocked ? times(1) : never()).cancel();
verify(fpCancel, fpLocked ? times(1) : never()).cancel();
verify(callback, faceLocked ? times(1) : never()).onBiometricRunningStateChanged(
// THEN face and fingerprint listening are always cancelled immediately
verify(faceCancel).cancel();
verify(callback).onBiometricRunningStateChanged(
eq(false), eq(BiometricSourceType.FACE));
verify(callback, fpLocked ? times(1) : never()).onBiometricRunningStateChanged(
verify(fpCancel).cancel();
verify(callback).onBiometricRunningStateChanged(
eq(false), eq(BiometricSourceType.FINGERPRINT));
// THEN locked out states are updated
assertThat(mKeyguardUpdateMonitor.isFingerprintLockedOut()).isEqualTo(fpLocked);
assertThat(mKeyguardUpdateMonitor.isFaceLockedOut()).isEqualTo(faceLocked);
// Fingerprint should be restarted once its cancelled bc on lockout, the device
// can still detectFingerprint (and if it's not locked out, fingerprint can listen)
assertThat(mKeyguardUpdateMonitor.mFingerprintRunningState)
.isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING);
}
@Test
@@ -1144,9 +1137,8 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
// GIVEN status bar state is on the keyguard
mStatusBarStateListener.onStateChanged(StatusBarState.KEYGUARD);
// WHEN user hasn't authenticated since last boot
when(mStrongAuthTracker.getStrongAuthForUser(KeyguardUpdateMonitor.getCurrentUser()))
.thenReturn(STRONG_AUTH_REQUIRED_AFTER_BOOT);
// WHEN user hasn't authenticated since last boot, cannot unlock with FP
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
// THEN we shouldn't listen for udfps
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);
@@ -1258,8 +1250,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase {
when(mStrongAuthTracker.hasUserAuthenticatedSinceBoot()).thenReturn(true);
// WHEN device in lock down
when(mStrongAuthTracker.getStrongAuthForUser(anyInt())).thenReturn(
KeyguardUpdateMonitor.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
// THEN we shouldn't listen for udfps
assertThat(mKeyguardUpdateMonitor.shouldListenForFingerprint(true)).isEqualTo(false);

View File

@@ -37,7 +37,7 @@ import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.leak.RotationUtils
import javax.inject.Provider
import com.android.systemui.util.mockito.any
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertTrue
@@ -46,15 +46,16 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.ArgumentMatchers
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mock
import org.mockito.Mockito.any
import org.mockito.Mockito.`when`
import org.mockito.Mockito.never
import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.MockitoAnnotations
import org.mockito.MockitoSession
import org.mockito.quality.Strictness
import javax.inject.Provider
@SmallTest
@RunWith(AndroidTestingRunner::class)
@@ -118,12 +119,13 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
fun testFingerprintTrigger_KeyguardShowing_Ripple() {
// GIVEN fp exists, keyguard is showing, user doesn't need strong auth
// GIVEN fp exists, keyguard is showing, unlocking with fp allowed
val fpsLocation = Point(5, 5)
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardStateController.isShowing).thenReturn(true)
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
eq(BiometricSourceType.FINGERPRINT))).thenReturn(true)
// WHEN fingerprint authenticated
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
@@ -140,11 +142,12 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
fun testFingerprintTrigger_KeyguardNotShowing_NoRipple() {
// GIVEN fp exists & user doesn't need strong auth
// GIVEN fp exists & unlocking with fp allowed
val fpsLocation = Point(5, 5)
`when`(authController.udfpsLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
eq(BiometricSourceType.FINGERPRINT))).thenReturn(true)
// WHEN keyguard is NOT showing & fingerprint authenticated
`when`(keyguardStateController.isShowing).thenReturn(false)
@@ -160,15 +163,16 @@ class AuthRippleControllerTest : SysuiTestCase() {
}
@Test
fun testFingerprintTrigger_StrongAuthRequired_NoRipple() {
fun testFingerprintTrigger_biometricUnlockNotAllowed_NoRipple() {
// GIVEN fp exists & keyguard is showing
val fpsLocation = Point(5, 5)
`when`(authController.udfpsLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardStateController.isShowing).thenReturn(true)
// WHEN user needs strong auth & fingerprint authenticated
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(true)
// WHEN unlocking with fingerprint is NOT allowed & fingerprint authenticated
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
eq(BiometricSourceType.FINGERPRINT))).thenReturn(false)
val captor = ArgumentCaptor.forClass(KeyguardUpdateMonitorCallback::class.java)
verify(keyguardUpdateMonitor).registerCallback(captor.capture())
captor.value.onBiometricAuthenticated(
@@ -182,13 +186,14 @@ class AuthRippleControllerTest : SysuiTestCase() {
@Test
fun testFaceTriggerBypassEnabled_Ripple() {
// GIVEN face auth sensor exists, keyguard is showing & strong auth isn't required
// GIVEN face auth sensor exists, keyguard is showing & unlocking with face is allowed
val faceLocation = Point(5, 5)
`when`(authController.faceSensorLocation).thenReturn(faceLocation)
controller.onViewAttached()
`when`(keyguardStateController.isShowing).thenReturn(true)
`when`(keyguardUpdateMonitor.userNeedsStrongAuth()).thenReturn(false)
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
BiometricSourceType.FACE)).thenReturn(true)
// WHEN bypass is enabled & face authenticated
`when`(bypassController.canBypass()).thenReturn(true)
@@ -275,6 +280,8 @@ class AuthRippleControllerTest : SysuiTestCase() {
`when`(authController.fingerprintSensorLocation).thenReturn(fpsLocation)
controller.onViewAttached()
`when`(keyguardStateController.isShowing).thenReturn(true)
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
BiometricSourceType.FINGERPRINT)).thenReturn(true)
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
controller.showUnlockRipple(BiometricSourceType.FINGERPRINT)
@@ -295,6 +302,8 @@ class AuthRippleControllerTest : SysuiTestCase() {
`when`(keyguardStateController.isShowing).thenReturn(true)
`when`(biometricUnlockController.isWakeAndUnlock).thenReturn(true)
`when`(authController.isUdfpsFingerDown).thenReturn(true)
`when`(keyguardUpdateMonitor.isUnlockingWithBiometricAllowed(
eq(BiometricSourceType.FACE))).thenReturn(true)
controller.showUnlockRipple(BiometricSourceType.FACE)
assertTrue("reveal didn't start on keyguardFadingAway",

View File

@@ -39,6 +39,7 @@ import static org.mockito.Mockito.when;
import android.content.res.ColorStateList;
import android.graphics.Color;
import android.hardware.biometrics.BiometricSourceType;
import android.os.Handler;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
@@ -398,6 +399,8 @@ public class KeyguardBouncerTest extends SysuiTestCase {
@Test
public void testShow_delaysIfFaceAuthIsRunning() {
when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE))
.thenReturn(true);
when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true);
mBouncer.show(true /* reset */);
@@ -410,9 +413,10 @@ public class KeyguardBouncerTest extends SysuiTestCase {
}
@Test
public void testShow_doesNotDelaysIfFaceAuthIsLockedOut() {
public void testShow_doesNotDelaysIfFaceAuthIsNotAllowed() {
when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true);
when(mKeyguardUpdateMonitor.isFaceLockedOut()).thenReturn(true);
when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(BiometricSourceType.FACE))
.thenReturn(false);
mBouncer.show(true /* reset */);
verify(mHandler, never()).postDelayed(any(), anyLong());