blob: 6c7cbc166241f83cdc4ff09d1b5067bfce088180 [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
Kevin Chyn9bc1d492019-06-21 15:31:50 -070036 protected long getFirstAcquireTimeMs() {
37 return mFirstAcquireTimeMs;
38 }
39
Kevin Chyn7782d142019-01-18 12:51:33 -080040 /**
41 * Only valid for AuthenticationClient.
42 * @return true if the client is authenticating for a crypto operation.
43 */
44 protected boolean isCryptoOperation() {
45 return false;
46 }
47
48 /**
49 * @return One of {@link BiometricsProtoEnums} MODALITY_* constants.
50 */
51 protected abstract int statsModality();
52
53 /**
54 * Action == enroll, authenticate, remove, enumerate.
55 * @return One of {@link BiometricsProtoEnums} ACTION_* constants.
56 */
57 protected abstract int statsAction();
58
59 /**
60 * Only matters for AuthenticationClient. Should only be overridden in
61 * {@link BiometricServiceBase}, which determines if a client is for BiometricPrompt, Keyguard,
62 * etc.
63 * @return one of {@link BiometricsProtoEnums} CLIENT_* constants.
64 */
65 protected int statsClient() {
66 return BiometricsProtoEnums.CLIENT_UNKNOWN;
67 }
68
Kevin Chyn4858da42019-04-11 13:02:56 -070069 protected final void logOnAcquired(Context context, int acquiredInfo, int vendorCode,
70 int targetUserId) {
Kevin Chyn7782d142019-01-18 12:51:33 -080071 if (statsModality() == BiometricsProtoEnums.MODALITY_FACE) {
72 if (acquiredInfo == FaceManager.FACE_ACQUIRED_START) {
73 mFirstAcquireTimeMs = System.currentTimeMillis();
74 }
75 } else if (acquiredInfo == BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
76 if (mFirstAcquireTimeMs == 0) {
77 mFirstAcquireTimeMs = System.currentTimeMillis();
78 }
79 }
80 if (DEBUG) {
81 Slog.v(TAG, "Acquired! Modality: " + statsModality()
82 + ", User: " + targetUserId
83 + ", IsCrypto: " + isCryptoOperation()
84 + ", Action: " + statsAction()
85 + ", Client: " + statsClient()
86 + ", AcquiredInfo: " + acquiredInfo
87 + ", VendorCode: " + vendorCode);
88 }
89 StatsLog.write(StatsLog.BIOMETRIC_ACQUIRED,
90 statsModality(),
91 targetUserId,
92 isCryptoOperation(),
93 statsAction(),
94 statsClient(),
95 acquiredInfo,
Kevin Chyn4858da42019-04-11 13:02:56 -070096 0 /* vendorCode */, // Don't log vendorCode for now
97 Utils.isDebugEnabled(context, targetUserId));
Kevin Chyn7782d142019-01-18 12:51:33 -080098 }
99
Kevin Chyn4858da42019-04-11 13:02:56 -0700100 protected final void logOnError(Context context, int error, int vendorCode, int targetUserId) {
Kevin Chyn7fca2362019-06-20 17:20:42 -0700101
102 final long latency = mFirstAcquireTimeMs != 0
103 ? (System.currentTimeMillis() - mFirstAcquireTimeMs) : -1;
104
Kevin Chyn7782d142019-01-18 12:51:33 -0800105 if (DEBUG) {
106 Slog.v(TAG, "Error! Modality: " + statsModality()
107 + ", User: " + targetUserId
108 + ", IsCrypto: " + isCryptoOperation()
109 + ", Action: " + statsAction()
110 + ", Client: " + statsClient()
111 + ", Error: " + error
Kevin Chyn7fca2362019-06-20 17:20:42 -0700112 + ", VendorCode: " + vendorCode
113 + ", Latency: " + latency);
114 } else {
115 Slog.v(TAG, "Error latency: " + latency);
Kevin Chyn7782d142019-01-18 12:51:33 -0800116 }
117 StatsLog.write(StatsLog.BIOMETRIC_ERROR_OCCURRED,
118 statsModality(),
119 targetUserId,
120 isCryptoOperation(),
121 statsAction(),
122 statsClient(),
123 error,
Kevin Chyn4858da42019-04-11 13:02:56 -0700124 vendorCode,
Kevin Chyn7fca2362019-06-20 17:20:42 -0700125 Utils.isDebugEnabled(context, targetUserId),
126 latency);
Kevin Chyn7782d142019-01-18 12:51:33 -0800127 }
128
Kevin Chyn4858da42019-04-11 13:02:56 -0700129 protected final void logOnAuthenticated(Context context, boolean authenticated,
130 boolean requireConfirmation, int targetUserId, boolean isBiometricPrompt) {
Kevin Chyn7782d142019-01-18 12:51:33 -0800131 int authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__UNKNOWN;
132 if (!authenticated) {
133 authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__REJECTED;
134 } else {
135 // Authenticated
136 if (isBiometricPrompt && requireConfirmation) {
137 authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__PENDING_CONFIRMATION;
138 } else {
139 authState = StatsLog.BIOMETRIC_AUTHENTICATED__STATE__CONFIRMED;
140 }
141 }
142
143 // Only valid if we have a first acquired time, otherwise set to -1
144 final long latency = mFirstAcquireTimeMs != 0
145 ? (System.currentTimeMillis() - mFirstAcquireTimeMs)
146 : -1;
147
148 if (DEBUG) {
149 Slog.v(TAG, "Authenticated! Modality: " + statsModality()
150 + ", User: " + targetUserId
151 + ", IsCrypto: " + isCryptoOperation()
152 + ", Client: " + statsClient()
153 + ", RequireConfirmation: " + requireConfirmation
154 + ", State: " + authState
155 + ", Latency: " + latency);
Kevin Chyne5a37fb2019-02-08 13:10:36 -0800156 } else {
157 Slog.v(TAG, "Authentication latency: " + latency);
Kevin Chyn7782d142019-01-18 12:51:33 -0800158 }
159
160 StatsLog.write(StatsLog.BIOMETRIC_AUTHENTICATED,
161 statsModality(),
162 targetUserId,
163 isCryptoOperation(),
164 statsClient(),
165 requireConfirmation,
166 authState,
Kevin Chyn4858da42019-04-11 13:02:56 -0700167 latency,
168 Utils.isDebugEnabled(context, targetUserId));
Kevin Chyn7782d142019-01-18 12:51:33 -0800169 }
joshmccloskey6f952b22019-03-25 20:59:35 -0700170
171 protected final void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) {
172 if (DEBUG) {
173 Slog.v(TAG, "Enrolled! Modality: " + statsModality()
174 + ", User: " + targetUserId
175 + ", Client: " + statsClient()
176 + ", Latency: " + latency
177 + ", Success: " + enrollSuccessful);
178 } else {
179 Slog.v(TAG, "Enroll latency: " + latency);
180 }
181
182 StatsLog.write(StatsLog.BIOMETRIC_ENROLLED,
183 statsModality(),
184 targetUserId,
185 latency,
186 enrollSuccessful);
187 }
188
Kevin Chyn7782d142019-01-18 12:51:33 -0800189}