diff options
3 files changed, 218 insertions, 3 deletions
diff --git a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java index 82444f0cc299..6bd48802baf5 100644 --- a/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java +++ b/services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java @@ -16,14 +16,22 @@ package com.android.server.biometrics.log; +import android.annotation.NonNull; +import android.annotation.Nullable; import android.hardware.biometrics.BiometricsProtoEnums; import android.hardware.biometrics.IBiometricContextListener; +import android.hardware.biometrics.common.AuthenticateReason; +import android.hardware.biometrics.common.OperationContext; import android.hardware.biometrics.common.OperationReason; +import android.hardware.biometrics.common.WakeReason; import android.util.Slog; import android.view.Surface; +import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.FrameworkStatsLog; +import java.util.stream.Stream; + /** * Wrapper for {@link FrameworkStatsLog} to isolate the testable parts. */ @@ -63,7 +71,7 @@ public class BiometricFrameworkStatsLogger { orientationType(operationContext.getOrientation()), foldType(operationContext.getFoldState()), operationContext.getOrderAndIncrement(), - BiometricsProtoEnums.WAKE_REASON_UNKNOWN); + toProtoWakeReason(operationContext)); } /** {@see FrameworkStatsLog.BIOMETRIC_AUTHENTICATED}. */ @@ -89,7 +97,8 @@ public class BiometricFrameworkStatsLogger { orientationType(operationContext.getOrientation()), foldType(operationContext.getFoldState()), operationContext.getOrderAndIncrement(), - BiometricsProtoEnums.WAKE_REASON_UNKNOWN); + toProtoWakeReason(operationContext), + toProtoWakeReasonDetails(operationContext)); } /** {@see FrameworkStatsLog.BIOMETRIC_AUTHENTICATED}. */ @@ -137,7 +146,81 @@ public class BiometricFrameworkStatsLogger { orientationType(operationContext.getOrientation()), foldType(operationContext.getFoldState()), operationContext.getOrderAndIncrement(), - BiometricsProtoEnums.WAKE_REASON_UNKNOWN); + toProtoWakeReason(operationContext), + toProtoWakeReasonDetails(operationContext)); + } + + @VisibleForTesting + static int[] toProtoWakeReasonDetails(@NonNull OperationContextExt operationContext) { + final OperationContext ctx = operationContext.toAidlContext(); + return Stream.of(toProtoWakeReasonDetails(ctx.authenticateReason)) + .mapToInt(i -> i) + .filter(i -> i != BiometricsProtoEnums.DETAILS_UNKNOWN) + .toArray(); + } + + @VisibleForTesting + static int toProtoWakeReason(@NonNull OperationContextExt operationContext) { + @WakeReason final int reason = operationContext.getWakeReason(); + switch (reason) { + case WakeReason.POWER_BUTTON: + return BiometricsProtoEnums.WAKE_REASON_POWER_BUTTON; + case WakeReason.GESTURE: + return BiometricsProtoEnums.WAKE_REASON_GESTURE; + case WakeReason.WAKE_KEY: + return BiometricsProtoEnums.WAKE_REASON_WAKE_KEY; + case WakeReason.WAKE_MOTION: + return BiometricsProtoEnums.WAKE_REASON_WAKE_MOTION; + case WakeReason.LID: + return BiometricsProtoEnums.WAKE_REASON_LID; + case WakeReason.DISPLAY_GROUP_ADDED: + return BiometricsProtoEnums.WAKE_REASON_DISPLAY_GROUP_ADDED; + case WakeReason.TAP: + return BiometricsProtoEnums.WAKE_REASON_TAP; + case WakeReason.LIFT: + return BiometricsProtoEnums.WAKE_REASON_LIFT; + case WakeReason.BIOMETRIC: + return BiometricsProtoEnums.WAKE_REASON_BIOMETRIC; + default: + return BiometricsProtoEnums.WAKE_REASON_UNKNOWN; + } + } + + private static int toProtoWakeReasonDetails(@Nullable AuthenticateReason reason) { + if (reason != null) { + switch (reason.getTag()) { + case AuthenticateReason.faceAuthenticateReason: + return toProtoWakeReasonDetailsFromFace(reason.getFaceAuthenticateReason()); + } + } + return BiometricsProtoEnums.DETAILS_UNKNOWN; + } + + private static int toProtoWakeReasonDetailsFromFace(@AuthenticateReason.Face int reason) { + switch (reason) { + case AuthenticateReason.Face.STARTED_WAKING_UP: + return BiometricsProtoEnums.DETAILS_FACE_STARTED_WAKING_UP; + case AuthenticateReason.Face.PRIMARY_BOUNCER_SHOWN: + return BiometricsProtoEnums.DETAILS_FACE_PRIMARY_BOUNCER_SHOWN; + case AuthenticateReason.Face.ASSISTANT_VISIBLE: + return BiometricsProtoEnums.DETAILS_FACE_ASSISTANT_VISIBLE; + case AuthenticateReason.Face.ALTERNATE_BIOMETRIC_BOUNCER_SHOWN: + return BiometricsProtoEnums.DETAILS_FACE_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN; + case AuthenticateReason.Face.NOTIFICATION_PANEL_CLICKED: + return BiometricsProtoEnums.DETAILS_FACE_NOTIFICATION_PANEL_CLICKED; + case AuthenticateReason.Face.OCCLUDING_APP_REQUESTED: + return BiometricsProtoEnums.DETAILS_FACE_OCCLUDING_APP_REQUESTED; + case AuthenticateReason.Face.PICK_UP_GESTURE_TRIGGERED: + return BiometricsProtoEnums.DETAILS_FACE_PICK_UP_GESTURE_TRIGGERED; + case AuthenticateReason.Face.QS_EXPANDED: + return BiometricsProtoEnums.DETAILS_FACE_QS_EXPANDED; + case AuthenticateReason.Face.SWIPE_UP_ON_BOUNCER: + return BiometricsProtoEnums.DETAILS_FACE_SWIPE_UP_ON_BOUNCER; + case AuthenticateReason.Face.UDFPS_POINTER_DOWN: + return BiometricsProtoEnums.DETAILS_FACE_UDFPS_POINTER_DOWN; + default: + return BiometricsProtoEnums.DETAILS_UNKNOWN; + } } /** {@see FrameworkStatsLog.BIOMETRIC_SYSTEM_HEALTH_ISSUE_DETECTED}. */ diff --git a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java index ecb7e7ca08fb..293433990cbd 100644 --- a/services/core/java/com/android/server/biometrics/log/OperationContextExt.java +++ b/services/core/java/com/android/server/biometrics/log/OperationContextExt.java @@ -188,10 +188,17 @@ public class OperationContextExt { } /** {@link OperationContext#reason}. */ + @OperationReason public byte getReason() { return mAidlContext.reason; } + /** {@link OperationContext#wakeReason}. */ + @WakeReason + public int getWakeReason() { + return mAidlContext.wakeReason; + } + /** If the screen is currently on. */ public boolean isDisplayOn() { return mIsDisplayOn; diff --git a/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricFrameworkStatsLoggerTest.java b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricFrameworkStatsLoggerTest.java new file mode 100644 index 000000000000..5adf391a1c32 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/biometrics/log/BiometricFrameworkStatsLoggerTest.java @@ -0,0 +1,125 @@ +/* + * 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.server.biometrics.log; + +import static com.google.common.truth.Truth.assertThat; + +import android.hardware.biometrics.BiometricsProtoEnums; +import android.hardware.biometrics.common.AuthenticateReason; +import android.hardware.biometrics.common.OperationContext; +import android.hardware.biometrics.common.WakeReason; +import android.platform.test.annotations.Presubmit; + +import androidx.test.filters.SmallTest; + +import org.junit.Test; + +@Presubmit +@SmallTest +public class BiometricFrameworkStatsLoggerTest { + + @Test + public void testConvertsWakeReason_whenEmpty() { + final OperationContextExt ctx = new OperationContextExt(); + + final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx); + final int[] reasonDetails = BiometricFrameworkStatsLogger + .toProtoWakeReasonDetails(ctx); + + assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_UNKNOWN); + assertThat(reasonDetails).isEmpty(); + } + + @Test + public void testConvertsWakeReason_whenPowerReason() { + final OperationContext context = new OperationContext(); + context.wakeReason = WakeReason.WAKE_MOTION; + final OperationContextExt ctx = new OperationContextExt(context); + + final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx); + final int[] reasonDetails = BiometricFrameworkStatsLogger + .toProtoWakeReasonDetails(new OperationContextExt(context)); + + assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_WAKE_MOTION); + assertThat(reasonDetails).isEmpty(); + } + + @Test + public void testConvertsWakeReason_whenFaceReason() { + final OperationContext context = new OperationContext(); + context.authenticateReason = AuthenticateReason.faceAuthenticateReason( + AuthenticateReason.Face.ASSISTANT_VISIBLE); + final OperationContextExt ctx = new OperationContextExt(context); + + final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx); + final int[] reasonDetails = BiometricFrameworkStatsLogger + .toProtoWakeReasonDetails(ctx); + + assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_UNKNOWN); + assertThat(reasonDetails).asList().containsExactly( + BiometricsProtoEnums.DETAILS_FACE_ASSISTANT_VISIBLE); + } + + @Test + public void testConvertsWakeReason_whenVendorReason() { + final OperationContext context = new OperationContext(); + context.authenticateReason = AuthenticateReason.vendorAuthenticateReason( + new AuthenticateReason.Vendor()); + final OperationContextExt ctx = new OperationContextExt(context); + + final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx); + final int[] reasonDetails = BiometricFrameworkStatsLogger + .toProtoWakeReasonDetails(ctx); + + assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_UNKNOWN); + assertThat(reasonDetails).isEmpty(); + } + + + @Test + public void testConvertsWakeReason_whenPowerAndFaceReason() { + final OperationContext context = new OperationContext(); + context.wakeReason = WakeReason.WAKE_KEY; + context.authenticateReason = AuthenticateReason.faceAuthenticateReason( + AuthenticateReason.Face.PRIMARY_BOUNCER_SHOWN); + final OperationContextExt ctx = new OperationContextExt(context); + + final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx); + final int[] reasonDetails = BiometricFrameworkStatsLogger + .toProtoWakeReasonDetails(ctx); + + assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_WAKE_KEY); + assertThat(reasonDetails).asList().containsExactly( + BiometricsProtoEnums.DETAILS_FACE_PRIMARY_BOUNCER_SHOWN); + } + + @Test + public void testConvertsWakeReason_whenPowerAndVendorReason() { + final OperationContext context = new OperationContext(); + context.wakeReason = WakeReason.LID; + context.authenticateReason = AuthenticateReason.vendorAuthenticateReason( + new AuthenticateReason.Vendor()); + final OperationContextExt ctx = new OperationContextExt(context); + + final int reason = BiometricFrameworkStatsLogger.toProtoWakeReason(ctx); + final int[] reasonDetails = BiometricFrameworkStatsLogger + .toProtoWakeReasonDetails(ctx); + + assertThat(reason).isEqualTo(BiometricsProtoEnums.WAKE_REASON_LID); + assertThat(reasonDetails).isEmpty(); + } +} |