1 /*
2  * Copyright (C) 2023 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 
17 package com.android.server.biometrics;
18 
19 /**
20  * Utility class for on-device biometric authentication data, including total authentication,
21  * rejections, and the number of sent enrollment notifications.
22  */
23 public class AuthenticationStats {
24 
25     private static final float FRR_NOT_ENOUGH_ATTEMPTS = -1.0f;
26 
27     private final int mUserId;
28     private int mTotalAttempts;
29     private int mRejectedAttempts;
30     private int mEnrollmentNotifications;
31     private final int mModality;
32 
AuthenticationStats(final int userId, int totalAttempts, int rejectedAttempts, int enrollmentNotifications, final int modality)33     public AuthenticationStats(final int userId, int totalAttempts, int rejectedAttempts,
34             int enrollmentNotifications, final int modality) {
35         mUserId = userId;
36         mTotalAttempts = totalAttempts;
37         mRejectedAttempts = rejectedAttempts;
38         mEnrollmentNotifications = enrollmentNotifications;
39         mModality = modality;
40     }
41 
AuthenticationStats(final int userId, final int modality)42     public AuthenticationStats(final int userId, final int modality) {
43         mUserId = userId;
44         mTotalAttempts = 0;
45         mRejectedAttempts = 0;
46         mEnrollmentNotifications = 0;
47         mModality = modality;
48     }
49 
getUserId()50     public int getUserId() {
51         return mUserId;
52     }
53 
getTotalAttempts()54     public int getTotalAttempts() {
55         return mTotalAttempts;
56     }
57 
getRejectedAttempts()58     public int getRejectedAttempts() {
59         return mRejectedAttempts;
60     }
61 
getEnrollmentNotifications()62     public int getEnrollmentNotifications() {
63         return mEnrollmentNotifications;
64     }
65 
getModality()66     public int getModality() {
67         return mModality;
68     }
69 
70     /** Calculate FRR. */
getFrr()71     public float getFrr() {
72         if (mTotalAttempts > 0) {
73             return mRejectedAttempts / (float) mTotalAttempts;
74         } else {
75             return FRR_NOT_ENOUGH_ATTEMPTS;
76         }
77     }
78 
79     /** Update total authentication attempts and rejections. */
authenticate(boolean authenticated)80     public void authenticate(boolean authenticated) {
81         if (!authenticated) {
82             mRejectedAttempts++;
83         }
84         mTotalAttempts++;
85     }
86 
87     /** Reset total authentication attempts and rejections. */
resetData()88     public void resetData() {
89         mTotalAttempts = 0;
90         mRejectedAttempts = 0;
91     }
92 
93     /** Update enrollment notification counter after sending a notification. */
updateNotificationCounter()94     public void updateNotificationCounter() {
95         mEnrollmentNotifications++;
96     }
97 
98     @Override
equals(Object obj)99     public boolean equals(Object obj) {
100         if (this == obj) {
101             return true;
102         }
103 
104         if (!(obj instanceof AuthenticationStats)) {
105             return false;
106         }
107 
108         AuthenticationStats target = (AuthenticationStats) obj;
109         return this.getUserId() == target.getUserId()
110                 && this.getTotalAttempts()
111                 == target.getTotalAttempts()
112                 && this.getRejectedAttempts()
113                 == target.getRejectedAttempts()
114                 && this.getEnrollmentNotifications()
115                 == target.getEnrollmentNotifications()
116                 && this.getModality() == target.getModality();
117     }
118 
119     @Override
hashCode()120     public int hashCode() {
121         return String.format("userId: %d, totalAttempts: %d, rejectedAttempts: %d, "
122                 + "enrollmentNotifications: %d, modality: %d", mUserId, mTotalAttempts,
123                 mRejectedAttempts, mEnrollmentNotifications, mModality).hashCode();
124     }
125 }
126