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