Loading services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java +86 −3 Original line number Diff line number Diff line Loading @@ -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. */ Loading Loading @@ -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}. */ Loading @@ -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}. */ Loading Loading @@ -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}. */ Loading services/core/java/com/android/server/biometrics/log/OperationContextExt.java +7 −0 Original line number Diff line number Diff line Loading @@ -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; Loading services/tests/servicestests/src/com/android/server/biometrics/log/BiometricFrameworkStatsLoggerTest.java 0 → 100644 +125 −0 Original line number Diff line number Diff line /* * 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(); } } Loading
services/core/java/com/android/server/biometrics/log/BiometricFrameworkStatsLogger.java +86 −3 Original line number Diff line number Diff line Loading @@ -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. */ Loading Loading @@ -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}. */ Loading @@ -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}. */ Loading Loading @@ -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}. */ Loading
services/core/java/com/android/server/biometrics/log/OperationContextExt.java +7 −0 Original line number Diff line number Diff line Loading @@ -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; Loading
services/tests/servicestests/src/com/android/server/biometrics/log/BiometricFrameworkStatsLoggerTest.java 0 → 100644 +125 −0 Original line number Diff line number Diff line /* * 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(); } }