From 6f5d50696a2d0406fa5579bda5a6d0199d94c3bf Mon Sep 17 00:00:00 2001 From: Chandru Date: Wed, 16 Nov 2022 14:30:00 +0000 Subject: [PATCH] Do not run face detection for bypass when the user is authenticated by FP FP authentication always dismisses the lock screen. Fixes: 258323361 Test: atest KeyguardUpdateMonitorTest Test: 1. Enroll face unlock & fp unlock 2. Enable skip lockscreen under face unlock 3. Lock the phone. 4. Fail face auth 3 times to lock it out. 5. Unlock the phone using UDFPS 6. Face scanning animation should not be visible 7. Camera protection ring should not be visible. Change-Id: I809c8c5ce331f57d8a9b3407dd83ee5b8cc59768 --- .../android/keyguard/KeyguardListenModel.kt | 7 ++-- .../keyguard/KeyguardUpdateMonitor.java | 26 ++++++++------- .../keyguard/KeyguardListenQueueTest.kt | 5 +-- .../keyguard/KeyguardUpdateMonitorTest.java | 32 +++++++++++++++++++ 4 files changed, 53 insertions(+), 17 deletions(-) diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt index a0206f1f1e704..819768544b0c9 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt @@ -50,10 +50,9 @@ data class KeyguardFaceListenModel( override val listening: Boolean, // keep sorted val authInterruptActive: Boolean, - val becauseCannotSkipBouncer: Boolean, val biometricSettingEnabledForUser: Boolean, val bouncerFullyShown: Boolean, - val faceAuthenticated: Boolean, + val faceAndFpNotAuthenticated: Boolean, val faceDisabled: Boolean, val faceLockedOut: Boolean, val fpLockedOut: Boolean, @@ -67,7 +66,9 @@ data class KeyguardFaceListenModel( val secureCameraLaunched: Boolean, val switchingUser: Boolean, val udfpsBouncerShowing: Boolean, -) : KeyguardListenModel() + val udfpsFingerDown: Boolean, + val userNotTrustedOrDetectionIsNeeded: Boolean, + ) : KeyguardListenModel() /** * Verbose debug information associated with [KeyguardUpdateMonitor.shouldTriggerActiveUnlock]. */ diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 463c00660787d..b9510f1a476ab 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -808,9 +808,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } // Don't send cancel if authentication succeeds mFingerprintCancelSignal = null; + mLogger.logFingerprintSuccess(userId, isStrongBiometric); updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE, FACE_AUTH_UPDATED_FP_AUTHENTICATED); - mLogger.logFingerprintSuccess(userId, isStrongBiometric); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -2734,9 +2734,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final boolean canBypass = mKeyguardBypassController != null && mKeyguardBypassController.canBypass(); // There's no reason to ask the HAL for authentication when the user can dismiss the - // bouncer, unless we're bypassing and need to auto-dismiss the lock screen even when - // TrustAgents or biometrics are keeping the device unlocked. - final boolean becauseCannotSkipBouncer = !getUserCanSkipBouncer(user) || canBypass; + // bouncer because the user is trusted, unless we're bypassing and need to auto-dismiss + // the lock screen even when TrustAgents are keeping the device unlocked. + final boolean userNotTrustedOrDetectionIsNeeded = !getUserHasTrust(user) || canBypass; // Scan even when encrypted or timeout to show a preemptive bouncer when bypassing. // Lock-down mode shouldn't scan, since it is more explicit. @@ -2753,11 +2753,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab strongAuthAllowsScanning = false; } - // If the face has recently been authenticated do not attempt to authenticate again. - final boolean faceAuthenticated = getIsFaceAuthenticated(); + // If the face or fp has recently been authenticated do not attempt to authenticate again. + final boolean faceAndFpNotAuthenticated = !getUserUnlockedWithBiometric(user); final boolean faceDisabledForUser = isFaceDisabled(user); final boolean biometricEnabledForUser = mBiometricEnabledForUser.get(user); final boolean shouldListenForFaceAssistant = shouldListenForFaceAssistant(); + final boolean isUdfpsFingerDown = mAuthController.isUdfpsFingerDown(); // Only listen if this KeyguardUpdateMonitor belongs to the primary user. There is an // instance of KeyguardUpdateMonitor for each user but KeyguardUpdateMonitor is user-aware. @@ -2767,13 +2768,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab || mOccludingAppRequestingFace || awakeKeyguard || shouldListenForFaceAssistant - || mAuthController.isUdfpsFingerDown() + || isUdfpsFingerDown || mUdfpsBouncerShowing) - && !mSwitchingUser && !faceDisabledForUser && becauseCannotSkipBouncer + && !mSwitchingUser && !faceDisabledForUser && userNotTrustedOrDetectionIsNeeded && !mKeyguardGoingAway && biometricEnabledForUser && strongAuthAllowsScanning && mIsPrimaryUser && (!mSecureCameraLaunched || mOccludingAppRequestingFace) - && !faceAuthenticated + && faceAndFpNotAuthenticated && !mGoingToSleep // We only care about fp locked out state and not face because we still trigger // face auth even when face is locked out to show the user a message that face @@ -2787,10 +2788,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab user, shouldListen, mAuthInterruptActive, - becauseCannotSkipBouncer, biometricEnabledForUser, mPrimaryBouncerFullyShown, - faceAuthenticated, + faceAndFpNotAuthenticated, faceDisabledForUser, isFaceLockedOut(), fpLockedOut, @@ -2803,7 +2803,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab strongAuthAllowsScanning, mSecureCameraLaunched, mSwitchingUser, - mUdfpsBouncerShowing)); + mUdfpsBouncerShowing, + isUdfpsFingerDown, + userNotTrustedOrDetectionIsNeeded)); return shouldListen; } diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt index 131cf7d33e3a7..88396628017b9 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt @@ -84,10 +84,9 @@ private fun faceModel(user: Int) = KeyguardFaceListenModel( userId = user, listening = false, authInterruptActive = false, - becauseCannotSkipBouncer = false, biometricSettingEnabledForUser = false, bouncerFullyShown = false, - faceAuthenticated = false, + faceAndFpNotAuthenticated = false, faceDisabled = false, faceLockedOut = false, fpLockedOut = false, @@ -101,4 +100,6 @@ private fun faceModel(user: Int) = KeyguardFaceListenModel( secureCameraLaunched = false, switchingUser = false, udfpsBouncerShowing = false, + udfpsFingerDown = false, + userNotTrustedOrDetectionIsNeeded = false ) diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 23e3235bd690e..1b4447c91e472 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -1378,6 +1378,29 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); } + @Test + public void testShouldListenForFace_whenFpIsAlreadyAuthenticated_returnsFalse() + throws RemoteException { + // Face auth should run when the following is true. + bouncerFullyVisibleAndNotGoingToSleep(); + keyguardNotGoingAway(); + currentUserIsPrimary(); + strongAuthNotRequired(); + biometricsEnabledForCurrentUser(); + currentUserDoesNotHaveTrust(); + biometricsNotDisabledThroughDevicePolicyManager(); + userNotCurrentlySwitching(); + + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isTrue(); + + successfulFingerprintAuth(); + mTestableLooper.processAllMessages(); + + assertThat(mKeyguardUpdateMonitor.shouldListenForFace()).isFalse(); + } + @Test public void testShouldListenForFace_whenUserIsNotPrimary_returnsFalse() throws RemoteException { cleanupKeyguardUpdateMonitor(); @@ -1932,6 +1955,15 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { .onAuthenticationAcquired(FINGERPRINT_ACQUIRED_START); } + private void successfulFingerprintAuth() { + mKeyguardUpdateMonitor.mFingerprintAuthenticationCallback + .onAuthenticationSucceeded( + new FingerprintManager.AuthenticationResult(null, + null, + mCurrentUserId, + true)); + } + private void triggerSuccessfulFaceAuth() { mKeyguardUpdateMonitor.requestFaceAuth(FaceAuthApiRequestReason.UDFPS_POINTER_DOWN); verify(mFaceManager).authenticate(any(),