From 5e844042a12233ff86f04ac04516119a6765b1b2 Mon Sep 17 00:00:00 2001 From: Beverly Date: Wed, 30 Nov 2022 16:24:10 +0000 Subject: On strongAuthChanges, update fp & face states Previously, we relied on other state to update which would trigger updateBiometricListeningState. Instead of relying on other triggers, directly update the biometric listening state if strong auth or non-strong auth allowed states change. Don't run face auth or detect if device is locked down by the user. However, if bypass is enabled and the other strongauth requirements are triggered (ie: idle timeout, timeout, encrypted, dpm lockdown, after boot), then run detectFace if its supported. Bug: 259908246 Bug: 258513069 Bug: 260682144 Test: atest KeyguardUpdateMonitorTest Change-Id: If03a1525832dfb8366c36757ebc84c0dead51b9f --- .../src/com/android/keyguard/FaceAuthReason.kt | 11 +- .../com/android/keyguard/KeyguardListenModel.kt | 9 +- .../android/keyguard/KeyguardUpdateMonitor.java | 127 ++++++++++----------- 3 files changed, 76 insertions(+), 71 deletions(-) (limited to 'packages/SystemUI/src') diff --git a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt index 4a41b3fe2589..5bb9367fa4a5 100644 --- a/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt +++ b/packages/SystemUI/src/com/android/keyguard/FaceAuthReason.kt @@ -48,11 +48,13 @@ import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_INIT import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_OCCLUSION_CHANGED import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_RESET import com.android.keyguard.InternalFaceAuthReasons.KEYGUARD_VISIBILITY_CHANGED +import com.android.keyguard.InternalFaceAuthReasons.NON_STRONG_BIOMETRIC_ALLOWED_CHANGED import com.android.keyguard.InternalFaceAuthReasons.OCCLUDING_APP_REQUESTED import com.android.keyguard.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN import com.android.keyguard.InternalFaceAuthReasons.PRIMARY_BOUNCER_SHOWN_OR_WILL_BE_SHOWN import com.android.keyguard.InternalFaceAuthReasons.RETRY_AFTER_HW_UNAVAILABLE import com.android.keyguard.InternalFaceAuthReasons.STARTED_WAKING_UP +import com.android.keyguard.InternalFaceAuthReasons.STRONG_AUTH_ALLOWED_CHANGED import com.android.keyguard.InternalFaceAuthReasons.TRUST_DISABLED import com.android.keyguard.InternalFaceAuthReasons.TRUST_ENABLED import com.android.keyguard.InternalFaceAuthReasons.USER_SWITCHING @@ -121,6 +123,9 @@ private object InternalFaceAuthReasons { const val FACE_AUTHENTICATED = "Face auth started/stopped because face is authenticated" const val BIOMETRIC_ENABLED = "Face auth started/stopped because biometric is enabled on keyguard" + const val STRONG_AUTH_ALLOWED_CHANGED = "Face auth stopped because strong auth allowed changed" + const val NON_STRONG_BIOMETRIC_ALLOWED_CHANGED = + "Face auth stopped because non strong biometric allowed changed" } /** @@ -204,7 +209,11 @@ constructor(private val id: Int, val reason: String, var extraInfo: Int = 0) : @UiEvent(doc = FACE_AUTHENTICATED) FACE_AUTH_UPDATED_ON_FACE_AUTHENTICATED(1187, FACE_AUTHENTICATED), @UiEvent(doc = BIOMETRIC_ENABLED) - FACE_AUTH_UPDATED_BIOMETRIC_ENABLED_ON_KEYGUARD(1188, BIOMETRIC_ENABLED); + FACE_AUTH_UPDATED_BIOMETRIC_ENABLED_ON_KEYGUARD(1188, BIOMETRIC_ENABLED), + @UiEvent(doc = STRONG_AUTH_ALLOWED_CHANGED) + FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED(1255, STRONG_AUTH_ALLOWED_CHANGED), + @UiEvent(doc = NON_STRONG_BIOMETRIC_ALLOWED_CHANGED) + FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED(1256, NON_STRONG_BIOMETRIC_ALLOWED_CHANGED); override fun getId(): Int = this.id diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt index e6283b86283b..52ca1668e4c9 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt @@ -53,17 +53,17 @@ data class KeyguardFaceListenModel( val biometricSettingEnabledForUser: Boolean, val bouncerFullyShown: Boolean, val faceAndFpNotAuthenticated: Boolean, + val faceAuthAllowed: Boolean, val faceDisabled: Boolean, val faceLockedOut: Boolean, - val fpLockedOut: Boolean, val goingToSleep: Boolean, val keyguardAwake: Boolean, val keyguardGoingAway: Boolean, val listeningForFaceAssistant: Boolean, val occludingAppRequestingFaceAuth: Boolean, val primaryUser: Boolean, - val scanningAllowedByStrongAuth: Boolean, val secureCameraLaunched: Boolean, + val supportsDetect: Boolean, val switchingUser: Boolean, val udfpsBouncerShowing: Boolean, val udfpsFingerDown: Boolean, @@ -79,9 +79,8 @@ data class KeyguardActiveUnlockModel( // keep sorted val awakeKeyguard: Boolean, val authInterruptActive: Boolean, - val encryptedOrTimedOut: Boolean, - val fpLockout: Boolean, - val lockDown: Boolean, + val fpLockedOut: Boolean, + val primaryAuthRequired: Boolean, val switchingUser: Boolean, val triggerActiveUnlockForAssistant: Boolean, val userCanDismissLockScreen: Boolean diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 64fa15e0cd20..479d4549016c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -34,9 +34,9 @@ import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT; -import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT; import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN; import static com.android.keyguard.FaceAuthReasonKt.apiRequestReasonToUiEvent; +import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_DREAM_STARTED; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_FACE_CANCEL_NOT_RECEIVED; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_STOPPED_FINISHED_GOING_TO_SLEEP; @@ -65,6 +65,7 @@ import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_ON_FACE_AUT import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_ON_KEYGUARD_INIT; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP; +import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED; import static com.android.keyguard.FaceAuthUiEvent.FACE_AUTH_UPDATED_USER_SWITCHING; import static com.android.systemui.DejankUtils.whitelistIpcs; @@ -170,7 +171,6 @@ import java.util.Map.Entry; import java.util.Set; import java.util.TimeZone; import java.util.concurrent.Executor; -import java.util.function.Consumer; import java.util.stream.Collectors; import javax.inject.Inject; @@ -1401,6 +1401,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } + /** + * Whether the user locked down the device. This doesn't include device policy manager lockdown. + */ public boolean isUserInLockdown(int userId) { return containsFlag(mStrongAuthTracker.getStrongAuthForUser(userId), STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); @@ -1432,7 +1435,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab return mStrongAuthTracker; } - private void notifyStrongAuthStateChanged(int userId) { + @VisibleForTesting + void notifyStrongAuthAllowedChanged(int userId) { Assert.isMainThread(); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); @@ -1440,6 +1444,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab cb.onStrongAuthStateChanged(userId); } } + if (userId == getCurrentUser()) { + FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED.setExtraInfo( + mStrongAuthTracker.getStrongAuthForUser(getCurrentUser())); + + // Strong auth is only reset when primary auth is used to enter the device, + // so we only check whether to stop biometric listening states here + updateBiometricListeningState( + BIOMETRIC_ACTION_STOP, FACE_AUTH_UPDATED_STRONG_AUTH_CHANGED); + } } private void notifyLockedOutStateChanged(BiometricSourceType type) { @@ -1451,8 +1464,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } } - - private void notifyNonStrongBiometricStateChanged(int userId) { + @VisibleForTesting + void notifyNonStrongBiometricAllowedChanged(int userId) { Assert.isMainThread(); for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); @@ -1460,6 +1473,16 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab cb.onNonStrongBiometricAllowedChanged(userId); } } + if (userId == getCurrentUser()) { + FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED.setExtraInfo( + mStrongAuthTracker.isNonStrongBiometricAllowedAfterIdleTimeout( + getCurrentUser()) ? -1 : 1); + + // This is only reset when primary auth is used to enter the device, so we only check + // whether to stop biometric listening states here + updateBiometricListeningState(BIOMETRIC_ACTION_STOP, + FACE_AUTH_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED); + } } private void dispatchErrorMessage(CharSequence message) { @@ -1805,16 +1828,12 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } - public static class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker { - private final Consumer mStrongAuthRequiredChangedCallback; - private final Consumer mNonStrongBiometricAllowedChanged; - - public StrongAuthTracker(Context context, - Consumer strongAuthRequiredChangedCallback, - Consumer nonStrongBiometricAllowedChanged) { + /** + * Updates callbacks when strong auth requirements change. + */ + public class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker { + public StrongAuthTracker(Context context) { super(context); - mStrongAuthRequiredChangedCallback = strongAuthRequiredChangedCallback; - mNonStrongBiometricAllowedChanged = nonStrongBiometricAllowedChanged; } public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) { @@ -1830,7 +1849,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onStrongAuthRequiredChanged(int userId) { - mStrongAuthRequiredChangedCallback.accept(userId); + notifyStrongAuthAllowedChanged(userId); } // TODO(b/247091681): Renaming the inappropriate onIsNonStrongBiometricAllowedChanged @@ -1838,7 +1857,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // Strong-Auth @Override public void onIsNonStrongBiometricAllowedChanged(int userId) { - mNonStrongBiometricAllowedChanged.accept(userId); + notifyNonStrongBiometricAllowedChanged(userId); } } @@ -1999,8 +2018,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mUserTracker = userTracker; mTelephonyListenerManager = telephonyListenerManager; mDeviceProvisioned = isDeviceProvisionedInSettingsDb(); - mStrongAuthTracker = new StrongAuthTracker(context, this::notifyStrongAuthStateChanged, - this::notifyNonStrongBiometricStateChanged); + mStrongAuthTracker = new StrongAuthTracker(context); mBackgroundExecutor = backgroundExecutor; mBroadcastDispatcher = broadcastDispatcher; mInteractionJankMonitor = interactionJankMonitor; @@ -2575,24 +2593,17 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab || !mLockPatternUtils.isSecure(user); // Don't trigger active unlock if fp is locked out - final boolean fpLockedout = mFingerprintLockedOut || mFingerprintLockedOutPermanent; + final boolean fpLockedOut = mFingerprintLockedOut || mFingerprintLockedOutPermanent; // Don't trigger active unlock if primary auth is required - final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user); - final boolean isLockDown = - containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) - || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); - final boolean isEncryptedOrTimedOut = - containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT) - || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT); + final boolean primaryAuthRequired = !isUnlockingWithBiometricAllowed(true); final boolean shouldTriggerActiveUnlock = (mAuthInterruptActive || triggerActiveUnlockForAssistant || awakeKeyguard) && !mSwitchingUser && !userCanDismissLockScreen - && !fpLockedout - && !isLockDown - && !isEncryptedOrTimedOut + && !fpLockedOut + && !primaryAuthRequired && !mKeyguardGoingAway && !mSecureCameraLaunched; @@ -2604,9 +2615,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab shouldTriggerActiveUnlock, awakeKeyguard, mAuthInterruptActive, - isEncryptedOrTimedOut, - fpLockedout, - isLockDown, + fpLockedOut, + primaryAuthRequired, mSwitchingUser, triggerActiveUnlockForAssistant, userCanDismissLockScreen)); @@ -2658,7 +2668,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab && !fingerprintDisabledForUser && (!mKeyguardGoingAway || !mDeviceInteractive) && mIsPrimaryUser - && biometricEnabledForUser; + && biometricEnabledForUser + && !isUserInLockdown(user); final boolean strongerAuthRequired = !isUnlockingWithFingerprintAllowed(); final boolean isSideFps = isSfpsSupported() && isSfpsEnrolled(); final boolean shouldListenBouncerState = @@ -2720,14 +2731,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final boolean awakeKeyguard = isKeyguardVisible() && mDeviceInteractive && !statusBarShadeLocked; final int user = getCurrentUser(); - final int strongAuth = mStrongAuthTracker.getStrongAuthForUser(user); - final boolean isLockDown = - containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW) - || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN); - final boolean isEncryptedOrTimedOut = - containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_BOOT) - || containsFlag(strongAuth, STRONG_AUTH_REQUIRED_AFTER_TIMEOUT); - final boolean fpLockedOut = isFingerprintLockedOut(); + final boolean faceAuthAllowed = isUnlockingWithBiometricAllowed(FACE); final boolean canBypass = mKeyguardBypassController != null && mKeyguardBypassController.canBypass(); // There's no reason to ask the HAL for authentication when the user can dismiss the @@ -2735,20 +2739,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // 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. - boolean strongAuthAllowsScanning = (!isEncryptedOrTimedOut || canBypass - && !mPrimaryBouncerFullyShown); - - // If the device supports face detection (without authentication) and bypass is enabled, - // allow face scanning to happen if the device is in lockdown mode. - // Otherwise, prevent scanning. - final boolean supportsDetectOnly = !mFaceSensorProperties.isEmpty() - && canBypass - && mFaceSensorProperties.get(0).supportsFaceDetection; - if (isLockDown && !supportsDetectOnly) { - strongAuthAllowsScanning = false; - } + // If the device supports face detection (without authentication), if bypass is enabled, + // allow face detection to happen even if stronger auth is required. When face is detected, + // we show the bouncer. However, if the user manually locked down the device themselves, + // never attempt to detect face. + final boolean supportsDetect = !mFaceSensorProperties.isEmpty() + && mFaceSensorProperties.get(0).supportsFaceDetection + && canBypass && !mPrimaryBouncerIsOrWillBeShowing + && !isUserInLockdown(user); + final boolean faceAuthAllowedOrDetectionIsNeeded = faceAuthAllowed || supportsDetect; // If the face or fp has recently been authenticated do not attempt to authenticate again. final boolean faceAndFpNotAuthenticated = !getUserUnlockedWithBiometric(user); @@ -2769,14 +2768,10 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab || mUdfpsBouncerShowing) && !mSwitchingUser && !faceDisabledForUser && userNotTrustedOrDetectionIsNeeded && !mKeyguardGoingAway && biometricEnabledForUser - && strongAuthAllowsScanning && mIsPrimaryUser + && faceAuthAllowedOrDetectionIsNeeded && mIsPrimaryUser && (!mSecureCameraLaunched || mOccludingAppRequestingFace) && 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 - // unlock was supposed to run but didn't - && !fpLockedOut; + && !mGoingToSleep; // Aggregate relevant fields for debug logging. maybeLogListenerModelData( @@ -2786,19 +2781,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab shouldListen, mAuthInterruptActive, biometricEnabledForUser, - mPrimaryBouncerFullyShown, + mPrimaryBouncerFullyShown, faceAndFpNotAuthenticated, + faceAuthAllowed, faceDisabledForUser, isFaceLockedOut(), - fpLockedOut, mGoingToSleep, awakeKeyguard, mKeyguardGoingAway, shouldListenForFaceAssistant, mOccludingAppRequestingFace, mIsPrimaryUser, - strongAuthAllowsScanning, mSecureCameraLaunched, + supportsDetect, mSwitchingUser, mUdfpsBouncerShowing, isUdfpsFingerDown, @@ -2902,9 +2897,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // This would need to be updated for multi-sensor devices final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty() && mFaceSensorProperties.get(0).supportsFaceDetection; - if (isEncryptedOrLockdown(userId) && supportsFaceDetection) { + if (!isUnlockingWithBiometricAllowed(FACE) && supportsFaceDetection) { + mLogger.v("startListeningForFace - detect"); mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, userId); } else { + mLogger.v("startListeningForFace - authenticate"); final boolean isBypassEnabled = mKeyguardBypassController != null && mKeyguardBypassController.isBypassEnabled(); mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal, -- cgit v1.2.3-59-g8ed1b