From 69512eb3141723112cc9df3fce290eb72c6bd5bd Mon Sep 17 00:00:00 2001 From: Beverly Date: Thu, 23 Feb 2023 17:16:38 +0000 Subject: [PATCH] Send FaceAuthReason & wakeup reason to FaceManager Each time authenticate or detect is called, send FaceManager the reason face auth/detect was triggered. Test: atest KeyguardUpdateMonitorTest Bug: 259980077 Change-Id: I81633705687bbb91ff853df59498bfa8403fb503 --- .../keyguard/KeyguardUpdateMonitor.java | 17 +++- .../model/SysUiFaceAuthenticateOptions.kt | 99 +++++++++++++++++++ .../keyguard/KeyguardUpdateMonitorTest.java | 47 ++++++++- 3 files changed, 157 insertions(+), 6 deletions(-) create mode 100644 packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java index 4d7a76f1f4d2a..f038c69788b21 100644 --- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -29,6 +29,7 @@ import static android.hardware.biometrics.BiometricConstants.LockoutMode; import static android.hardware.biometrics.BiometricSourceType.FACE; import static android.hardware.biometrics.BiometricSourceType.FINGERPRINT; import static android.os.BatteryManager.BATTERY_STATUS_UNKNOWN; +import static android.os.PowerManager.WAKE_REASON_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; @@ -152,6 +153,7 @@ import com.android.systemui.dagger.qualifiers.Background; import com.android.systemui.dagger.qualifiers.Main; import com.android.systemui.dump.DumpManager; import com.android.systemui.dump.DumpsysTableLogger; +import com.android.systemui.keyguard.shared.model.SysUiFaceAuthenticateOptions; import com.android.systemui.log.SessionTracker; import com.android.systemui.plugins.WeatherData; import com.android.systemui.plugins.statusbar.StatusBarStateController; @@ -3023,6 +3025,14 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab if (unlockPossible) { mFaceCancelSignal = new CancellationSignal(); + final FaceAuthenticateOptions faceAuthenticateOptions = + new SysUiFaceAuthenticateOptions( + userId, + faceAuthUiEvent, + faceAuthUiEvent == FACE_AUTH_UPDATED_STARTED_WAKING_UP + ? faceAuthUiEvent.getExtraInfo() + : WAKE_REASON_UNKNOWN + ).toFaceAuthenticateOptions(); // This would need to be updated for multi-sensor devices final boolean supportsFaceDetection = !mFaceSensorProperties.isEmpty() && mFaceSensorProperties.get(0).supportsFaceDetection; @@ -3033,9 +3043,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab // Run face detection. (If a face is detected, show the bouncer.) mLogger.v("startListeningForFace - detect"); mFaceManager.detectFace(mFaceCancelSignal, mFaceDetectionCallback, - new FaceAuthenticateOptions.Builder() - .setUserId(userId) - .build()); + faceAuthenticateOptions); } else { // Don't run face detection. Instead, inform the user // face auth is unavailable and how to proceed. @@ -3054,7 +3062,8 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener, Dumpab final boolean isBypassEnabled = mKeyguardBypassController != null && mKeyguardBypassController.isBypassEnabled(); mFaceManager.authenticate(null /* crypto */, mFaceCancelSignal, - mFaceAuthenticationCallback, null /* handler */, userId); + mFaceAuthenticationCallback, null /* handler */, + faceAuthenticateOptions); } setFaceRunningState(BIOMETRIC_STATE_RUNNING); } diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt new file mode 100644 index 0000000000000..a79513ebd8672 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/keyguard/shared/model/SysUiFaceAuthenticateOptions.kt @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.shared.model + +import android.hardware.face.FaceAuthenticateOptions +import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN +import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_ASSISTANT_VISIBLE +import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED +import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED +import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED +import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN +import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_STARTED_WAKING_UP +import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER +import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_UDFPS_POINTER_DOWN +import android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_UNKNOWN +import android.hardware.face.FaceAuthenticateOptions.AuthenticateReason +import android.os.PowerManager +import android.os.PowerManager.WAKE_REASON_UNKNOWN +import android.util.Log +import com.android.internal.logging.UiEvent +import com.android.internal.logging.UiEventLogger +import com.android.keyguard.FaceAuthUiEvent + +/** + * Wrapper for [FaceAuthenticateOptions] to convert SystemUI values to their corresponding value in + * [FaceAuthenticateOptions]. + */ +data class SysUiFaceAuthenticateOptions( + val userId: Int, + private val faceAuthUiEvent: UiEventLogger.UiEventEnum, + @PowerManager.WakeReason val wakeReason: Int = WAKE_REASON_UNKNOWN +) { + val authenticateReason = setAuthenticateReason(faceAuthUiEvent) + + /** + * The [FaceAuthUiEvent] for this operation. This method converts the UiEvent to the framework + * [AuthenticateReason]. + */ + @AuthenticateReason + fun setAuthenticateReason(uiEvent: UiEventLogger.UiEventEnum): Int { + return when (uiEvent) { + FaceAuthUiEvent.FACE_AUTH_UPDATED_STARTED_WAKING_UP -> { + AUTHENTICATE_REASON_STARTED_WAKING_UP + } + FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN, + FaceAuthUiEvent.FACE_AUTH_UPDATED_PRIMARY_BOUNCER_SHOWN_OR_WILL_BE_SHOWN -> { + AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN + } + FaceAuthUiEvent.FACE_AUTH_UPDATED_ASSISTANT_VISIBILITY_CHANGED -> { + AUTHENTICATE_REASON_ASSISTANT_VISIBLE + } + FaceAuthUiEvent.FACE_AUTH_TRIGGERED_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN -> { + AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN + } + FaceAuthUiEvent.FACE_AUTH_TRIGGERED_NOTIFICATION_PANEL_CLICKED -> { + AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED + } + FaceAuthUiEvent.FACE_AUTH_TRIGGERED_OCCLUDING_APP_REQUESTED -> { + AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED + } + FaceAuthUiEvent.FACE_AUTH_TRIGGERED_PICK_UP_GESTURE_TRIGGERED -> { + AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED + } + FaceAuthUiEvent.FACE_AUTH_TRIGGERED_SWIPE_UP_ON_BOUNCER -> { + AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER + } + FaceAuthUiEvent.FACE_AUTH_TRIGGERED_UDFPS_POINTER_DOWN -> { + AUTHENTICATE_REASON_UDFPS_POINTER_DOWN + } + else -> { + Log.e("FaceAuthenticateOptions", " unmapped FaceAuthUiEvent $uiEvent") + AUTHENTICATE_REASON_UNKNOWN + } + } + } + + /** Builds the instance. */ + fun toFaceAuthenticateOptions(): FaceAuthenticateOptions { + return FaceAuthenticateOptions.Builder() + .setUserId(userId) + .setAuthenticateReason(authenticateReason) + .setWakeReason(wakeReason) + .build() + } +} diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java index 074c27c80e905..f5107681635ca 100644 --- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java +++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java @@ -20,6 +20,8 @@ import static android.app.StatusBarManager.SESSION_KEYGUARD; import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT; import static android.hardware.biometrics.BiometricFingerprintConstants.FINGERPRINT_ERROR_LOCKOUT_PERMANENT; +import static android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN; +import static android.hardware.face.FaceAuthenticateOptions.AUTHENTICATE_REASON_STARTED_WAKING_UP; import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON; import static android.telephony.SubscriptionManager.DATA_ROAMING_DISABLE; import static android.telephony.SubscriptionManager.NAME_SOURCE_CARRIER_ID; @@ -80,6 +82,7 @@ import android.hardware.biometrics.BiometricSourceType; import android.hardware.biometrics.ComponentInfoInternal; import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; import android.hardware.biometrics.SensorProperties; +import android.hardware.face.FaceAuthenticateOptions; import android.hardware.face.FaceManager; import android.hardware.face.FaceSensorProperties; import android.hardware.face.FaceSensorPropertiesInternal; @@ -2500,7 +2503,46 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { .isEqualTo(BIOMETRIC_STATE_CANCELLING_RESTARTING); } + @Test + public void faceAuthenticateOptions_bouncerAuthenticateReason() { + // GIVEN the bouncer is fully visible + bouncerFullyVisible(); + + // WHEN authenticate is called + ArgumentCaptor captor = + ArgumentCaptor.forClass(FaceAuthenticateOptions.class); + verify(mFaceManager).authenticate(any(), any(), any(), any(), captor.capture()); + + // THEN the authenticate reason is attributed to the bouncer + assertThat(captor.getValue().getAuthenticateReason()) + .isEqualTo(AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN); + } + + @Test + public void faceAuthenticateOptions_wakingUpAuthenticateReason_powerButtonWakeReason() { + // GIVEN keyguard is visible + keyguardIsVisible(); + + // WHEN device wakes up from the power button + mKeyguardUpdateMonitor.dispatchStartedWakingUp(PowerManager.WAKE_REASON_POWER_BUTTON); + mTestableLooper.processAllMessages(); + + // THEN face auth is triggered + ArgumentCaptor captor = + ArgumentCaptor.forClass(FaceAuthenticateOptions.class); + verify(mFaceManager).authenticate(any(), any(), any(), any(), captor.capture()); + + // THEN the authenticate reason is attributed to the waking + assertThat(captor.getValue().getAuthenticateReason()) + .isEqualTo(AUTHENTICATE_REASON_STARTED_WAKING_UP); + + // THEN the wake reason is attributed to the power button + assertThat(captor.getValue().getWakeReason()) + .isEqualTo(PowerManager.WAKE_REASON_POWER_BUTTON); + } + private void verifyFingerprintAuthenticateNeverCalled() { + verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), any()); verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(), anyInt(), anyInt()); } @@ -2519,11 +2561,12 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { } private void verifyFaceAuthenticateNeverCalled() { + verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), any()); verify(mFaceManager, never()).authenticate(any(), any(), any(), any(), anyInt()); } private void verifyFaceAuthenticateCall() { - verify(mFaceManager).authenticate(any(), any(), any(), any(), anyInt()); + verify(mFaceManager).authenticate(any(), any(), any(), any(), any()); } private void verifyFaceDetectNeverCalled() { @@ -2631,7 +2674,7 @@ public class KeyguardUpdateMonitorTest extends SysuiTestCase { any(), mAuthenticationCallbackCaptor.capture(), any(), - anyInt()); + any()); mAuthenticationCallbackCaptor.getValue() .onAuthenticationSucceeded( new FaceManager.AuthenticationResult(null, null, mCurrentUserId, false));