diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt index 5953611b454a3..db2b4ac2c669c 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardListenModel.kt @@ -63,7 +63,8 @@ data class KeyguardFaceListenModel( val primaryUser: Boolean, val scanningAllowedByStrongAuth: Boolean, val secureCameraLaunched: Boolean, - val switchingUser: Boolean + val switchingUser: Boolean, + val udfpsBouncerShowing: Boolean ) : KeyguardListenModel() /** * Verbose debug information associated with [KeyguardUpdateMonitor.shouldTriggerActiveUnlock]. @@ -73,6 +74,7 @@ data class KeyguardActiveUnlockModel( override val userId: Int, override val listening: Boolean, // keep sorted + val awakeKeyguard: Boolean, val authInterruptActive: Boolean, val encryptedOrTimedOut: Boolean, val fpLockout: Boolean, diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java index 1a325d3586f4c..ce4aad882df94 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityContainerController.java @@ -219,6 +219,11 @@ public class KeyguardSecurityContainerController extends ViewController 0) { - message = trustGrantedMessages.get(0); // for now only shows the first in the list + final boolean userHasTrust = getUserHasTrust(userId); + if (userHasTrust && trustGrantedMessages != null) { + for (String msg : trustGrantedMessages) { + if (!TextUtils.isEmpty(msg)) { + message = msg; + break; + } + } } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); @@ -463,6 +478,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } } } + } @Override @@ -1354,8 +1370,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab void setAssistantVisible(boolean assistantVisible) { mAssistantVisible = assistantVisible; updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); - if (mAssistantVisible) { - requestActiveUnlock(); + if (mAssistantVisible && mRequestActiveUnlockOnAssistant) { + requestActiveUnlock("assistant", false); } } @@ -1502,11 +1518,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onAuthenticationFailed() { + if (mRequestActiveUnlockOnBioFail) { + requestActiveUnlock("biometric-failure, extra=fingerprintFailure", + true); + } handleFingerprintAuthFailed(); - - // TODO(b/225231929): Refactor as needed, add tests, etc. - mTrustManager.reportUserRequestedUnlock( - KeyguardUpdateMonitor.getCurrentUser(), true); } @Override @@ -1564,6 +1580,15 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab @Override public void onAuthenticationFailed() { + if (shouldRequestActiveUnlockOnFaceError()) { + String reason = + mKeyguardBypassController.canBypass() ? "bypass" + : mUdfpsBouncerShowing ? "udfpsBouncer" : + mBouncerFullyShown ? "bouncer" : "udfpsFpDown"; + requestActiveUnlock("biometric-failure" + + ", extra=faceFailure-" + reason, true); + } + handleFaceAuthFailed(); if (mKeyguardBypassController != null) { mKeyguardBypassController.setUserHasDeviceEntryIntent(false); @@ -1592,12 +1617,23 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab if (mKeyguardBypassController != null) { mKeyguardBypassController.setUserHasDeviceEntryIntent(false); } + if (errMsgId == BiometricFaceConstants.FACE_ERROR_TIMEOUT + && shouldRequestActiveUnlockOnFaceError()) { + requestActiveUnlock("biometric-failure" + + ", extra=faceError-" + errMsgId, true); + } } @Override public void onAuthenticationAcquired(int acquireInfo) { handleFaceAcquired(acquireInfo); } + + private boolean shouldRequestActiveUnlockOnFaceError() { + return mRequestActiveUnlockOnBioFail + && (mKeyguardBypassController.canBypass() || mBouncerFullyShown + || mUdfpsBouncerShowing || mAuthController.isUdfpsFingerDown()); + } }; @VisibleForTesting @@ -1713,7 +1749,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp"); Assert.isMainThread(); updateBiometricListeningState(BIOMETRIC_ACTION_UPDATE); - requestActiveUnlock(); + if (mRequestActiveUnlockOnWakeup) { + requestActiveUnlock("wake-unlock"); + } else if (mInitiateActiveUnlockOnWakeup) { + initiateActiveUnlock("wake-initiate"); + } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -1860,6 +1900,18 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab dumpManager.registerDumpable(getClass().getName(), this); mSensorPrivacyManager = context.getSystemService(SensorPrivacyManager.class); + // TODO, b/222459888: add official configurable names to Settings.java + mRequestActiveUnlockOnWakeup = Settings.Global.getInt( + mContext.getContentResolver(), "wake-unlock", 0) == 1; + mInitiateActiveUnlockOnWakeup = Settings.Global.getInt( + mContext.getContentResolver(), "wake-initiate", 1) == 1; + mRequestActiveUnlockOnUnlockIntent = Settings.Global.getInt( + mContext.getContentResolver(), "unlock-intent", 0) == 1; + mRequestActiveUnlockOnBioFail = Settings.Global.getInt( + mContext.getContentResolver(), "bio-fail", 0) == 1; + mRequestActiveUnlockOnAssistant = Settings.Global.getInt( + mContext.getContentResolver(), "assistant", 0) == 1; + mHandler = new Handler(mainLooper) { @Override public void handleMessage(Message msg) { @@ -2240,7 +2292,11 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } mAuthInterruptActive = active; updateFaceListeningState(BIOMETRIC_ACTION_UPDATE); - requestActiveUnlock(); + if (mRequestActiveUnlockOnWakeup) { + requestActiveUnlock("wake-unlock, extra=onReach"); + } else if (mInitiateActiveUnlockOnWakeup) { + initiateActiveUnlock("wake-initiate, extra=onReach"); + } } /** @@ -2290,25 +2346,69 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } /** - * Attempts to trigger active unlock. + * Initiates active unlock to get the unlock token ready. */ - public void requestActiveUnlock() { + public void initiateActiveUnlock(String reason) { // If this message exists, FP has already authenticated, so wait until that is handled if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) { return; } if (shouldTriggerActiveUnlock()) { - // TODO(b/225231929): Refactor surrounding code to reflect calling of new method + if (DEBUG) { + Log.d("ActiveUnlock", "initiate active unlock triggerReason=" + reason); + } mTrustManager.reportUserMayRequestUnlock(KeyguardUpdateMonitor.getCurrentUser()); } } + /** + * Attempts to trigger active unlock from trust agent. + */ + public void requestActiveUnlock(String reason, boolean dismissKeyguard) { + // If this message exists, FP has already authenticated, so wait until that is handled + if (mHandler.hasMessages(MSG_BIOMETRIC_AUTHENTICATION_CONTINUE)) { + return; + } + + if (shouldTriggerActiveUnlock()) { + if (DEBUG) { + Log.d("ActiveUnlock", "reportUserRequestedUnlock triggerReason=" + reason + + " dismissKeyguard=" + dismissKeyguard); + } + mTrustManager.reportUserRequestedUnlock(KeyguardUpdateMonitor.getCurrentUser(), + dismissKeyguard); + } + } + + /** + * Attempts to trigger active unlock from trust agent. + * Only dismisses the keyguard if only face is enrolled (no FP) and bypass is enabled. + */ + public void requestActiveUnlock(String reason) { + requestActiveUnlock(reason, isFaceEnrolled() && !isUdfpsEnrolled() + && mKeyguardBypassController.getBypassEnabled()); + } + + /** + * Whether the UDFPS bouncer is showing. + */ + public void setUdfpsBouncerShowing(boolean showing) { + mUdfpsBouncerShowing = showing; + if (mUdfpsBouncerShowing) { + updateFaceListeningState(BIOMETRIC_ACTION_START); + if (mRequestActiveUnlockOnUnlockIntent) { + requestActiveUnlock("unlock-intent, extra=udfpsBouncer", true); + } + } + } + private boolean shouldTriggerActiveUnlock() { // Triggers: final boolean triggerActiveUnlockForAssistant = shouldTriggerActiveUnlockForAssistant(); - final boolean awakeKeyguard = mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep - && mStatusBarState != StatusBarState.SHADE_LOCKED; + final boolean awakeKeyguard = mBouncerFullyShown || mUdfpsBouncerShowing + || (mKeyguardIsVisible && mDeviceInteractive && !mGoingToSleep + && mStatusBarState != StatusBarState.SHADE_LOCKED); // Gates: final int user = getCurrentUser(); @@ -2341,20 +2441,19 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab && !mSecureCameraLaunched; // Aggregate relevant fields for debug logging. - if (DEBUG_ACTIVE_UNLOCK || DEBUG_SPEW) { - maybeLogListenerModelData( - new KeyguardActiveUnlockModel( - System.currentTimeMillis(), - user, - shouldTriggerActiveUnlock, - mAuthInterruptActive, - isEncryptedOrTimedOut, - fpLockedout, - isLockDown, - mSwitchingUser, - triggerActiveUnlockForAssistant, - userCanDismissLockScreen)); - } + maybeLogListenerModelData( + new KeyguardActiveUnlockModel( + System.currentTimeMillis(), + user, + shouldTriggerActiveUnlock, + awakeKeyguard, + mAuthInterruptActive, + isEncryptedOrTimedOut, + fpLockedout, + isLockDown, + mSwitchingUser, + triggerActiveUnlockForAssistant, + userCanDismissLockScreen)); return shouldTriggerActiveUnlock; } @@ -2507,7 +2606,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab || mOccludingAppRequestingFace || awakeKeyguard || shouldListenForFaceAssistant - || mAuthController.isUdfpsFingerDown()) + || mAuthController.isUdfpsFingerDown() + || mUdfpsBouncerShowing) && !mSwitchingUser && !faceDisabledForUser && becauseCannotSkipBouncer && !mKeyguardGoingAway && biometricEnabledForUser && !mLockIconPressed && strongAuthAllowsScanning && mIsPrimaryUser @@ -2537,7 +2637,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab mIsPrimaryUser, strongAuthAllowsScanning, mSecureCameraLaunched, - mSwitchingUser)); + mSwitchingUser, + mUdfpsBouncerShowing)); } return shouldListen; @@ -2550,8 +2651,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } if (DEBUG_ACTIVE_UNLOCK - && model instanceof KeyguardActiveUnlockModel - && model.getListening()) { + && model instanceof KeyguardActiveUnlockModel) { mListenModels.add(model); return; } @@ -3133,6 +3233,9 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } if (wasBouncerFullyShown != mBouncerFullyShown) { + if (mBouncerFullyShown && mRequestActiveUnlockOnUnlockIntent) { + requestActiveUnlock("unlock-intent, reason=bouncerFullyShown", true); + } for (int i = 0; i < mCallbacks.size(); i++) { KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get(); if (cb != null) { @@ -3641,6 +3744,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab pw.println(" shouldListenForUdfps=" + shouldListenForFingerprint(true)); pw.println(" mBouncerIsOrWillBeShowing=" + mBouncerIsOrWillBeShowing); pw.println(" mStatusBarState=" + StatusBarState.toString(mStatusBarState)); + pw.println(" mUdfpsBouncerShowing=" + mUdfpsBouncerShowing); } } if (mFaceManager != null && mFaceManager.isHardwareDetected()) { @@ -3667,6 +3771,13 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab } mListenModels.print(pw); + pw.println("Enabled active unlock triggers:"); + pw.println(" mRequestActiveUnlockOnWakeup=" + mRequestActiveUnlockOnWakeup); + pw.println(" mInitiateActiveUnlockOnWakeup=" + mInitiateActiveUnlockOnWakeup); + pw.println(" mRequestActiveUnlockOnUnlockIntent=" + mRequestActiveUnlockOnUnlockIntent); + pw.println(" mRequestActiveUnlockOnBiometricFail=" + mRequestActiveUnlockOnBioFail); + pw.println(" mRequestActiveUnlockOnAssistant=" + mRequestActiveUnlockOnAssistant); + if (mIsAutomotive) { pw.println(" Running on Automotive build"); } diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java index 2ac240885faa0..eba87e49d35b0 100644 --- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java +++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java @@ -799,6 +799,11 @@ public class UdfpsController implements DozeReceiver { if (!mKeyguardUpdateMonitor.isFaceDetectionRunning()) { mKeyguardUpdateMonitor.requestFaceAuth(/* userInitiatedRequest */ false); } + + if (mKeyguardUpdateMonitor.mRequestActiveUnlockOnUnlockIntent) { + mKeyguardUpdateMonitor.requestActiveUnlock("unlock-intent extra=udfpsFingerDown", + true); + } } mOnFingerDown = true; mFingerprintManager.onPointerDown(requestId, mSensorProps.sensorId, x, y, minor, major); diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java index 83138f0666c14..551e8b51ae115 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java @@ -502,8 +502,8 @@ public class KeyguardIndicationController { private void updateLockScreenTrustMsg(int userId, CharSequence trustGrantedIndication, CharSequence trustManagedIndication) { - if (!TextUtils.isEmpty(trustGrantedIndication) - && mKeyguardUpdateMonitor.getUserHasTrust(userId)) { + final boolean userHasTrust = mKeyguardUpdateMonitor.getUserHasTrust(userId); + if (!TextUtils.isEmpty(trustGrantedIndication) && userHasTrust) { mRotateTextViewController.updateIndication( INDICATION_TYPE_TRUST, new KeyguardIndication.Builder() @@ -513,7 +513,7 @@ public class KeyguardIndicationController { false); } else if (!TextUtils.isEmpty(trustManagedIndication) && mKeyguardUpdateMonitor.getUserTrustIsManaged(userId) - && !mKeyguardUpdateMonitor.getUserHasTrust(userId)) { + && !userHasTrust) { mRotateTextViewController.updateIndication( INDICATION_TYPE_TRUST, new KeyguardIndication.Builder() diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt index 7db677ab6305b..3e32b64ebe3ab 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt @@ -71,7 +71,13 @@ class KeyguardLiftController @Inject constructor( isListening = false updateListeningState() keyguardUpdateMonitor.requestFaceAuth(true) - keyguardUpdateMonitor.requestActiveUnlock() + if (keyguardUpdateMonitor.mRequestActiveUnlockOnWakeup) { + keyguardUpdateMonitor.requestActiveUnlock("wake-unlock," + + " extra=KeyguardLiftController") + } else if (keyguardUpdateMonitor.mInitiateActiveUnlockOnWakeup) { + keyguardUpdateMonitor.initiateActiveUnlock("wake-initiate," + + " extra=KeyguardLiftController") + } } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java index a6b5c4d2c92c4..f7d0f7b79ca86 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java @@ -3341,6 +3341,12 @@ public class NotificationPanelViewController extends PanelViewController { .log(LockscreenUiEvent.LOCKSCREEN_LOCK_SHOW_HINT); startUnlockHintAnimation(); } + if (mUpdateMonitor.isFaceEnrolled() + && mUpdateMonitor.mRequestActiveUnlockOnUnlockIntent + && mKeyguardBypassController.canBypass()) { + mUpdateMonitor.requestActiveUnlock("unlock-intent," + + " extra=lockScreenEmptySpaceTap", true); + } } return true; case StatusBarState.SHADE_LOCKED: diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java index ce1289e0885cd..51d421279051b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java @@ -591,10 +591,12 @@ public class StatusBarKeyguardViewManager implements RemoteInputController.Callb } private void updateAlternateAuthShowing(boolean updateScrim) { + final boolean isShowingAltAuth = isShowingAlternateAuth(); if (mKeyguardMessageAreaController != null) { - mKeyguardMessageAreaController.setAltBouncerShowing(isShowingAlternateAuth()); + mKeyguardMessageAreaController.setAltBouncerShowing(isShowingAltAuth); } - mBypassController.setAltBouncerShowing(isShowingAlternateAuth()); + mBypassController.setAltBouncerShowing(isShowingAltAuth); + mKeyguardUpdateManager.setUdfpsBouncerShowing(isShowingAltAuth); if (updateScrim) { mCentralSurfaces.updateScrimController(); diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt index cc606de1b0b9f..b1e2012ecd40e 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardListenQueueTest.kt @@ -97,5 +97,6 @@ private fun faceModel(user: Int) = KeyguardFaceListenModel( primaryUser = false, scanningAllowedByStrongAuth = false, secureCameraLaunched = false, - switchingUser = false + switchingUser = false, + udfpsBouncerShowing = false )