diff options
| -rw-r--r-- | services/core/java/com/android/server/fingerprint/FingerprintService.java | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index be8e300c9352..1066434f10f1 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -72,6 +72,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; /** @@ -90,10 +91,17 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe private static final String 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 = new ArrayList<>(); private final AppOpsManager mAppOps; - private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000; private static final int MAX_FAILED_ATTEMPTS = 5; 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 mPendingClient; 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() { @Override @@ -246,6 +263,11 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe if (client != null && client.onAuthenticated(fingerId, groupId)) { removeClient(client); } + if (fingerId != 0) { + mPerformanceStats.accept++; + } else { + mPerformanceStats.reject++; + } } 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)) { 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) { @@ -505,6 +532,9 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe @Override public boolean handleFailedAttempt() { mFailedAttempts++; + if (mFailedAttempts == MAX_FAILED_ATTEMPTS) { + mPerformanceStats.lockout++; + } if (inLockoutMode()) { // Failing multiple times will continue to push out the lockout time. scheduleLockoutReset(); @@ -742,12 +772,24 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe mHandler.post(new Runnable() { @Override public void run() { - MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0); if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, callingUid, pid)) { if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName); 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, flags, restricted, opPackageName); } @@ -924,9 +966,21 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe for (UserInfo user : UserManager.get(getContext()).getUsers()) { final int userId = user.getUserHandle().getIdentifier(); final int N = mFingerprintUtils.getFingerprintsForUser(mContext, userId).size(); + PerformanceStats stats = mPerformanceMap.get(userId); + PerformanceStats cryptoStats = mCryptoPerformanceMap.get(userId); JSONObject set = new JSONObject(); set.put("id", userId); 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); } @@ -947,6 +1001,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe private void updateActiveGroup(int userId, String clientPackage) { IFingerprintDaemon daemon = getFingerprintDaemon(); + if (daemon != null) { try { userId = getUserOrWorkProfileId(clientPackage, userId); |