Capture fingerprint statistics for estimating FRR
Fixes bug 29258254 Change-Id: I10620c9bf07e4cdd7df456548b6516b5e1f1f5ee
This commit is contained in:
@@ -72,6 +72,7 @@ import java.io.PrintWriter;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,10 +91,17 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
|
|||||||
private static final String ACTION_LOCKOUT_RESET =
|
private static final String ACTION_LOCKOUT_RESET =
|
||||||
"com.android.server.fingerprint.ACTION_LOCKOUT_RESET";
|
"com.android.server.fingerprint.ACTION_LOCKOUT_RESET";
|
||||||
|
|
||||||
|
private class PerformanceStats {
|
||||||
|
int accept; // number of accepted fingerprints
|
||||||
|
int reject; // number of rejected fingerprints
|
||||||
|
int acquire; // total number of acquisitions. Should be >= accept+reject due to poor image
|
||||||
|
// acquisition in some cases (too fast, too slow, dirty sensor, etc.)
|
||||||
|
int lockout; // total number of lockouts
|
||||||
|
}
|
||||||
|
|
||||||
private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors =
|
private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors =
|
||||||
new ArrayList<>();
|
new ArrayList<>();
|
||||||
private final AppOpsManager mAppOps;
|
private final AppOpsManager mAppOps;
|
||||||
|
|
||||||
private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
|
private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
|
||||||
private static final int MAX_FAILED_ATTEMPTS = 5;
|
private static final int MAX_FAILED_ATTEMPTS = 5;
|
||||||
private static final long CANCEL_TIMEOUT_LIMIT = 3000; // max wait for onCancel() from HAL,in ms
|
private static final long CANCEL_TIMEOUT_LIMIT = 3000; // max wait for onCancel() from HAL,in ms
|
||||||
@@ -110,6 +118,15 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
|
|||||||
private ClientMonitor mCurrentClient;
|
private ClientMonitor mCurrentClient;
|
||||||
private ClientMonitor mPendingClient;
|
private ClientMonitor mPendingClient;
|
||||||
private long mCurrentAuthenticatorId;
|
private long mCurrentAuthenticatorId;
|
||||||
|
private PerformanceStats mPerformanceStats;
|
||||||
|
|
||||||
|
// Normal fingerprint authentications are tracked by mPerformanceMap.
|
||||||
|
private HashMap<Integer, PerformanceStats> mPerformanceMap
|
||||||
|
= new HashMap<Integer, PerformanceStats>();
|
||||||
|
|
||||||
|
// Transactions that make use of CryptoObjects are tracked by mCryptoPerformaceMap.
|
||||||
|
private HashMap<Integer, PerformanceStats> mCryptoPerformanceMap
|
||||||
|
= new HashMap<Integer, PerformanceStats>();
|
||||||
|
|
||||||
private Handler mHandler = new Handler() {
|
private Handler mHandler = new Handler() {
|
||||||
@Override
|
@Override
|
||||||
@@ -246,6 +263,11 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
|
|||||||
if (client != null && client.onAuthenticated(fingerId, groupId)) {
|
if (client != null && client.onAuthenticated(fingerId, groupId)) {
|
||||||
removeClient(client);
|
removeClient(client);
|
||||||
}
|
}
|
||||||
|
if (fingerId != 0) {
|
||||||
|
mPerformanceStats.accept++;
|
||||||
|
} else {
|
||||||
|
mPerformanceStats.reject++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleAcquired(long deviceId, int acquiredInfo) {
|
protected void handleAcquired(long deviceId, int acquiredInfo) {
|
||||||
@@ -253,6 +275,11 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
|
|||||||
if (client != null && client.onAcquired(acquiredInfo)) {
|
if (client != null && client.onAcquired(acquiredInfo)) {
|
||||||
removeClient(client);
|
removeClient(client);
|
||||||
}
|
}
|
||||||
|
if (mPerformanceStats != null && !inLockoutMode()
|
||||||
|
&& client instanceof AuthenticationClient) {
|
||||||
|
// ignore enrollment acquisitions or acquisitions when we're locked out
|
||||||
|
mPerformanceStats.acquire++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void handleEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
|
protected void handleEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
|
||||||
@@ -505,6 +532,9 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
|
|||||||
@Override
|
@Override
|
||||||
public boolean handleFailedAttempt() {
|
public boolean handleFailedAttempt() {
|
||||||
mFailedAttempts++;
|
mFailedAttempts++;
|
||||||
|
if (mFailedAttempts == MAX_FAILED_ATTEMPTS) {
|
||||||
|
mPerformanceStats.lockout++;
|
||||||
|
}
|
||||||
if (inLockoutMode()) {
|
if (inLockoutMode()) {
|
||||||
// Failing multiple times will continue to push out the lockout time.
|
// Failing multiple times will continue to push out the lockout time.
|
||||||
scheduleLockoutReset();
|
scheduleLockoutReset();
|
||||||
@@ -742,12 +772,24 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
|
|||||||
mHandler.post(new Runnable() {
|
mHandler.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
|
|
||||||
if (!canUseFingerprint(opPackageName, true /* foregroundOnly */,
|
if (!canUseFingerprint(opPackageName, true /* foregroundOnly */,
|
||||||
callingUid, pid)) {
|
callingUid, pid)) {
|
||||||
if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
|
if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
|
||||||
|
|
||||||
|
// Get performance stats object for this user.
|
||||||
|
HashMap<Integer, PerformanceStats> pmap
|
||||||
|
= (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap;
|
||||||
|
PerformanceStats stats = pmap.get(mCurrentUserId);
|
||||||
|
if (stats == null) {
|
||||||
|
stats = new PerformanceStats();
|
||||||
|
pmap.put(mCurrentUserId, stats);
|
||||||
|
}
|
||||||
|
mPerformanceStats = stats;
|
||||||
|
|
||||||
startAuthentication(token, opId, callingUserId, groupId, receiver,
|
startAuthentication(token, opId, callingUserId, groupId, receiver,
|
||||||
flags, restricted, opPackageName);
|
flags, restricted, opPackageName);
|
||||||
}
|
}
|
||||||
@@ -924,9 +966,21 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
|
|||||||
for (UserInfo user : UserManager.get(getContext()).getUsers()) {
|
for (UserInfo user : UserManager.get(getContext()).getUsers()) {
|
||||||
final int userId = user.getUserHandle().getIdentifier();
|
final int userId = user.getUserHandle().getIdentifier();
|
||||||
final int N = mFingerprintUtils.getFingerprintsForUser(mContext, userId).size();
|
final int N = mFingerprintUtils.getFingerprintsForUser(mContext, userId).size();
|
||||||
|
PerformanceStats stats = mPerformanceMap.get(userId);
|
||||||
|
PerformanceStats cryptoStats = mCryptoPerformanceMap.get(userId);
|
||||||
JSONObject set = new JSONObject();
|
JSONObject set = new JSONObject();
|
||||||
set.put("id", userId);
|
set.put("id", userId);
|
||||||
set.put("count", N);
|
set.put("count", N);
|
||||||
|
set.put("accept", (stats != null) ? stats.accept : 0);
|
||||||
|
set.put("reject", (stats != null) ? stats.reject : 0);
|
||||||
|
set.put("acquire", (stats != null) ? stats.acquire : 0);
|
||||||
|
set.put("lockout", (stats != null) ? stats.lockout : 0);
|
||||||
|
// cryptoStats measures statistics about secure fingerprint transactions
|
||||||
|
// (e.g. to unlock password storage, make secure purchases, etc.)
|
||||||
|
set.put("acceptCrypto", (cryptoStats != null) ? cryptoStats.accept : 0);
|
||||||
|
set.put("rejectCrypto", (cryptoStats != null) ? cryptoStats.reject : 0);
|
||||||
|
set.put("acquireCrypto", (cryptoStats != null) ? cryptoStats.acquire : 0);
|
||||||
|
set.put("lockoutCrypto", (cryptoStats != null) ? cryptoStats.lockout : 0);
|
||||||
sets.put(set);
|
sets.put(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -947,6 +1001,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe
|
|||||||
|
|
||||||
private void updateActiveGroup(int userId, String clientPackage) {
|
private void updateActiveGroup(int userId, String clientPackage) {
|
||||||
IFingerprintDaemon daemon = getFingerprintDaemon();
|
IFingerprintDaemon daemon = getFingerprintDaemon();
|
||||||
|
|
||||||
if (daemon != null) {
|
if (daemon != null) {
|
||||||
try {
|
try {
|
||||||
userId = getUserOrWorkProfileId(clientPackage, userId);
|
userId = getUserOrWorkProfileId(clientPackage, userId);
|
||||||
|
|||||||
Reference in New Issue
Block a user