blob: 9c040884772c1d35b878f939d1be9571e0275b00 [file] [log] [blame]
Kevin Chyn7782d142019-01-18 12:51:33 -08001/*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.biometrics;
18
Kevin Chyn4858da42019-04-11 13:02:56 -070019import android.content.Context;
Kevin Chyn7782d142019-01-18 12:51:33 -080020import android.hardware.biometrics.BiometricConstants;
21import android.hardware.biometrics.BiometricsProtoEnums;
22import android.hardware.face.FaceManager;
23import android.util.Slog;
24import android.util.StatsLog;
25
26/**
27 * Abstract class that adds logging functionality to the ClientMonitor classes.
28 */
29public abstract class LoggableMonitor {
30
31 public static final String TAG = "BiometricStats";
Kevin Chyne5a37fb2019-02-08 13:10:36 -080032 public static final boolean DEBUG = false;
Kevin Chyn7782d142019-01-18 12:51:33 -080033
34 private long mFirstAcquireTimeMs;
35
36 /**
37 * Only valid for AuthenticationClient.
38 * @return true if the client is authenticating for a crypto operation.
39 */
40 protected boolean isCryptoOperation() {
41 return false;
42 }
43
44 /**
45 * @return One of {@link BiometricsProtoEnums} MODALITY_* constants.
46 */
47 protected abstract int statsModality();
48
49 /**
50 * Action == enroll, authenticate, remove, enumerate.
51 * @return One of {@link BiometricsProtoEnums} ACTION_* constants.
52 */
53 protected abstract int statsAction();
54
55 /**
56 * Only matters for AuthenticationClient. Should only be overridden in
57 * {@link BiometricServiceBase}, which determines if a client is for BiometricPrompt, Keyguard,
58 * etc.
59 * @return one of {@link BiometricsProtoEnums} CLIENT_* constants.
60 */
61 protected int statsClient() {
62 return BiometricsProtoEnums.CLIENT_UNKNOWN;
63 }
64
Kevin Chyn4858da42019-04-11 13:02:56 -070065 protected final void logOnAcquired(Context context, int acquiredInfo, int vendorCode,
66 int targetUserId) {
Kevin Chyn7782d142019-01-18 12:51:33 -080067 if (statsModality() == BiometricsProtoEnums.MODALITY_FACE) {
68 if (acquiredInfo == FaceManager.FACE_ACQUIRED_START) {
69 mFirstAcquireTimeMs = System.currentTimeMillis();
70 }
71 } else if (acquiredInfo == BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
72 if (mFirstAcquireTimeMs == 0) {
73 mFirstAcquireTimeMs = System.currentTimeMillis();
74 }
75 }
76 if (DEBUG) {
77 Slog.v(TAG, "Acquired! Modality: " + statsModality()
78 + ", User: " + targetUserId
79 + ", IsCrypto: " + isCryptoOperation()
80 + ", Action: " + statsAction()
81 + ", Client: " + statsClient()
82 + ", AcquiredInfo: " + acquiredInfo
83 + ", VendorCode: " + vendorCode);
84 }
85 StatsLog.write(StatsLog.BIOMETRIC_ACQUIRED,
86 statsModality(),
87 targetUserId,
88 isCryptoOperation(),
89 statsAction(),
90 statsClient(),
91 acquiredInfo,
Kevin Chyn4858da42019-04-11 13:02:56 -070092 0 /* vendorCode */, // Don't log vendorCode for now
93 Utils.isDebugEnabled(context, targetUserId));
Kevin Chyn7782d142019-01-18 12:51:33 -080094 }
95
Kevin Chyn4858da42019-04-11 13:02:56 -070096 protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) {
Kevin Chyn7782d142019-01-18 12:51:33 -080097 if (DEBUG) {
98 Slog.v(TAG, "Error! Modality: " + statsModality()
99 + ", User: " + targetUserId
100 + ", IsCrypto: " + isCryptoOperation()
101 + ", Action: " + statsAction()
102 + ", Client: " + statsClient()
103 + ", Error: " + error
104 + ", VendorCode: " + vendorCode);
105 }
106 StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED,
107 statsModality(),
108 targetUserId,
109 isCryptoOperation(),
110 statsAction(),
111 statsClient(),
112 error,
Kevin Chyn4858da42019-04-11 13:02:56 -0700113 vendorCode,
114 Utils.isDebugEnabled(context, targetUserId));
Kevin Chyn7782d142019-01-18 12:51:33 -0800115 }
116
Kevin Chyn4858da42019-04-11 13:02:56 -0700117 protected final void logOnAuthenticated(Context context, boolean authenticated,
118 boolean requireConfirmation, int targetUserId, boolean isBiometricPrompt) {
Kevin Chyn7782d142019-01-18 12:51:33 -0800119 int authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__UNKNOWN;
120 if (!authenticated) {
121 authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__REJECTED;
122 } else {
123 // Authenticated
124 if (isBiometricPrompt && requireConfirmation) {
125 authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__PENDING_CONFIRMATION;
126 } else {
127 authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED;
128 }
129 }
130
131 // Only valid if we have a first acquired time, otherwise set to -1
132 final long latency = mFirstAcquireTimeMs != 0
133 ? (System.currentTimeMillis() - mFirstAcquireTimeMs)
134 : -1;
135
136 if (DEBUG) {
137 Slog.v(TAG, "Authenticated! Modality: " + statsModality()
138 + ", User: " + targetUserId
139 + ", IsCrypto: " + isCryptoOperation()
140 + ", Client: " + statsClient()
141 + ", RequireConfirmation: " + requireConfirmation
142 + ", State: " + authState
143 + ", Latency: " + latency);
Kevin Chyne5a37fb2019-02-08 13:10:36 -0800144 } else {
145 Slog.v(TAG, "Authentication latency: " + latency);
Kevin Chyn7782d142019-01-18 12:51:33 -0800146 }
147
148 StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED,
149 statsModality(),
150 targetUserId,
151 isCryptoOperation(),
152 statsClient(),
153 requireConfirmation,
154 authState,
Kevin Chyn4858da42019-04-11 13:02:56 -0700155 latency,
156 Utils.isDebugEnabled(context, targetUserId));
Kevin Chyn7782d142019-01-18 12:51:33 -0800157 }
joshmccloskey6f952b22019-03-25 20:59:35 -0700158
159 protected final void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) {
160 if (DEBUG) {
161 Slog.v(TAG, "Enrolled! Modality: " + statsModality()
162 + ", User: " + targetUserId
163 + ", Client: " + statsClient()
164 + ", Latency: " + latency
165 + ", Success: " + enrollSuccessful);
166 } else {
167 Slog.v(TAG, "Enroll latency: " + latency);
168 }
169
170 StatsLog.write(StatsLog.BIOMETRIC_ENROLLED,
171 statsModality(),
172 targetUserId,
173 latency,
174 enrollSuccessful);
175 }
176
Kevin Chyn7782d142019-01-18 12:51:33 -0800177}