diff options
5 files changed, 131 insertions, 1 deletions
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto index c8e6b46d6cff..13ae41df63f1 100644 --- a/cmds/statsd/src/atoms.proto +++ b/cmds/statsd/src/atoms.proto @@ -133,6 +133,9 @@ message Atom { VibratorStateChanged vibrator_state_changed = 84; DeferredJobStatsReported deferred_job_stats_reported = 85; ThermalThrottlingStateChanged thermal_throttling = 86; + FingerprintAcquired fingerprint_acquired = 87; + FingerprintAuthenticated fingerprint_authenticated = 88; + FingerprintErrorOccurred fingerprint_error_occurred = 89; } // Pulled events will start at field 10000. @@ -169,6 +172,7 @@ message Atom { CategorySize category_size = 10028; android.service.procstats.ProcessStatsSectionProto proc_stats = 10029; BatteryVoltage battery_voltage = 10030; + NumFingerprints num_fingerprints = 10031; } // DO NOT USE field numbers above 100,000 in AOSP. Field numbers above @@ -1832,6 +1836,60 @@ message GenericAtom { optional android.os.statsd.EventType event_id = 2; } +/** + * Logs when a fingerprint acquire event occurs. + * + * Logged from: + * frameworks/base/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java + */ +message FingerprintAcquired { + // The associated user. Eg: 0 for owners, 10+ for others. + // Defined in android/os/UserHandle.java + optional int32 user = 1; + // If this acquire is for a crypto fingerprint. + // e.g. Secure purchases, unlock password storage. + optional bool is_crypto = 2; +} + +/** + * Logs when a fingerprint authentication event occurs. + * + * Logged from: + * frameworks/base/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java + */ +message FingerprintAuthenticated { + // The associated user. Eg: 0 for owners, 10+ for others. + // Defined in android/os/UserHandle.java + optional int32 user = 1; + // If this authentication is for a crypto fingerprint. + // e.g. Secure purchases, unlock password storage. + optional bool is_crypto = 2; + // Whether or not this authentication was successful. + optional bool is_authenticated = 3; +} + +/** + * Logs when a fingerprint error occurs. + * + * Logged from: + * frameworks/base/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java + */ +message FingerprintErrorOccurred { + // The associated user. Eg: 0 for owners, 10+ for others. + // Defined in android/os/UserHandle.java + optional int32 user = 1; + // If this error is for a crypto fingerprint. + // e.g. Secure purchases, unlock password storage. + optional bool is_crypto = 2; + + enum Error { + UNKNOWN = 0; + LOCKOUT = 1; + PERMANENT_LOCKOUT = 2; + } + // The type of error. + optional Error error = 3; +} ////////////////////////////////////////////////////////////////////// // Pulled atoms below this line // ////////////////////////////////////////////////////////////////////// @@ -2408,3 +2466,16 @@ message CategorySize { // Uses System.currentTimeMillis(), which is wall clock time. optional int64 cache_time_millis = 3; } + +/** + * Pulls the number of fingerprints for each user. + * + * Pulled from StatsCompanionService, which queries FingerprintManager. + */ +message NumFingerprints { + // The associated user. Eg: 0 for owners, 10+ for others. + // Defined in android/os/UserHandle.java + optional int32 user = 1; + // Number of fingerprints registered to that user. + optional int32 num_fingerprints = 2; +} diff --git a/cmds/statsd/src/external/StatsPullerManager.cpp b/cmds/statsd/src/external/StatsPullerManager.cpp index 745ff74c2623..c23d65e2d146 100644 --- a/cmds/statsd/src/external/StatsPullerManager.cpp +++ b/cmds/statsd/src/external/StatsPullerManager.cpp @@ -217,6 +217,12 @@ const std::map<int, PullAtomInfo> StatsPullerManager::kAllPullAtomInfo = { {}, 1 * NS_PER_SEC, new StatsCompanionServicePuller(android::util::CATEGORY_SIZE)}}, + // Number of fingerprints registered to each user. + {android::util::NUM_FINGERPRINTS, + {{}, + {}, + 1 * NS_PER_SEC, + new StatsCompanionServicePuller(android::util::NUM_FINGERPRINTS)}}, }; StatsPullerManager::StatsPullerManager() : mNextPullTimeNs(NO_ALARM_UPDATE) { diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java index a181b6105471..d019b6b117c7 100644 --- a/services/core/java/com/android/server/biometrics/BiometricService.java +++ b/services/core/java/com/android/server/biometrics/BiometricService.java @@ -108,6 +108,8 @@ public abstract class BiometricService extends SystemService implements IHwBinde private ClientMonitor mPendingClient; private PerformanceStats mPerformanceStats; protected int mCurrentUserId = UserHandle.USER_NULL; + // Tracks if the current authentication makes use of CryptoObjects. + protected boolean mIsCrypto; // Normal authentications are tracked by mPerformanceMap. protected HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>(); // Transactions that make use of CryptoObjects are tracked by mCryptoPerformaceMap. @@ -715,6 +717,7 @@ public abstract class BiometricService extends SystemService implements IHwBinde pmap.put(mCurrentUserId, stats); } mPerformanceStats = stats; + mIsCrypto = (opId != 0); startAuthentication(client, opPackageName); }); @@ -847,7 +850,7 @@ public abstract class BiometricService extends SystemService implements IHwBinde return mKeyguardPackage.equals(clientPackage); } - private int getLockoutMode() { + protected int getLockoutMode() { final int currentUser = ActivityManager.getCurrentUser(); final int failedAttempts = mFailedAttempts.get(currentUser, 0); if (failedAttempts >= getFailedAttemptsLockoutPermanent()) { diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java index 95fb9e33dded..0a2e588e9ed9 100644 --- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java @@ -50,12 +50,14 @@ import android.os.SELinux; import android.os.UserHandle; import android.os.UserManager; import android.util.Slog; +import android.util.StatsLog; import android.util.proto.ProtoOutputStream; import com.android.internal.annotations.GuardedBy; import com.android.internal.logging.MetricsLogger; import com.android.internal.util.DumpUtils; import com.android.server.SystemServerInitThreadPool; +import com.android.server.biometrics.AuthenticationClient; import com.android.server.biometrics.BiometricService; import com.android.server.biometrics.BiometricUtils; import com.android.server.biometrics.ClientMonitor; @@ -590,6 +592,11 @@ public class FingerprintService extends BiometricService { public void onAcquired(final long deviceId, final int acquiredInfo, final int vendorCode) { mHandler.post(() -> { FingerprintService.super.handleAcquired(deviceId, acquiredInfo, vendorCode); + if (getLockoutMode() == AuthenticationClient.LOCKOUT_NONE + && getCurrentClient() instanceof AuthenticationClient) { + // Ignore enrollment acquisitions or acquisitions when we are locked out. + StatsLog.write(StatsLog.FINGERPRINT_ACQUIRED, mCurrentUserId, mIsCrypto); + } }); } @@ -599,6 +606,22 @@ public class FingerprintService extends BiometricService { mHandler.post(() -> { Fingerprint fp = new Fingerprint("", groupId, fingerId, deviceId); FingerprintService.super.handleAuthenticated(fp, token); + // Send authentication to statsd. + final boolean authenticated = fingerId != 0; + StatsLog.write(StatsLog.FINGERPRINT_AUTHENTICATED, mCurrentUserId, mIsCrypto, + authenticated); + if (!authenticated) { + // If we failed to authenticate because of a lockout, inform statsd. + final int lockoutMode = getLockoutMode(); + if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) { + StatsLog.write(StatsLog.FINGERPRINT_ERROR_OCCURRED, mCurrentUserId, + mIsCrypto, StatsLog.FINGERPRINT_ERROR_OCCURRED__ERROR__LOCKOUT); + } else if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) { + StatsLog.write(StatsLog.FINGERPRINT_ERROR_OCCURRED, mCurrentUserId, + mIsCrypto, + StatsLog.FINGERPRINT_ERROR_OCCURRED__ERROR__PERMANENT_LOCKOUT); + } + } }); } diff --git a/services/core/java/com/android/server/stats/StatsCompanionService.java b/services/core/java/com/android/server/stats/StatsCompanionService.java index a4d42a127cd6..444ac2c041d5 100644 --- a/services/core/java/com/android/server/stats/StatsCompanionService.java +++ b/services/core/java/com/android/server/stats/StatsCompanionService.java @@ -32,6 +32,7 @@ import android.content.IntentSender; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.UserInfo; +import android.hardware.fingerprint.FingerprintManager; import android.net.NetworkStats; import android.net.wifi.IWifiManager; import android.net.wifi.WifiActivityEnergyInfo; @@ -1171,6 +1172,28 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { } } + private void pullNumFingerprints(int tagId, List<StatsLogEventWrapper> pulledData) { + FingerprintManager fingerprintManager = mContext.getSystemService(FingerprintManager.class); + if (fingerprintManager == null) { + return; + } + UserManager userManager = mContext.getSystemService(UserManager.class); + if (userManager == null) { + return; + } + final long token = Binder.clearCallingIdentity(); + long elapsedNanos = SystemClock.elapsedRealtimeNanos(); + for (UserInfo user : userManager.getUsers()) { + final int userId = user.getUserHandle().getIdentifier(); + final int numFingerprints = fingerprintManager.getEnrolledFingerprints(userId).size(); + StatsLogEventWrapper e = new StatsLogEventWrapper(elapsedNanos, tagId, 2 /* fields */); + e.writeInt(userId); + e.writeInt(numFingerprints); + pulledData.add(e); + } + Binder.restoreCallingIdentity(token); + } + /** * Pulls various data. */ @@ -1277,6 +1300,10 @@ public class StatsCompanionService extends IStatsCompanionService.Stub { pullCategorySize(tagId, ret); break; } + case StatsLog.NUM_FINGERPRINTS: { + pullNumFingerprints(tagId, ret); + break; + } default: Slog.w(TAG, "No such tagId data as " + tagId); return null; |