Adding latency biometric for enroll.

Bug: 129298461
Test: Verified that logs are correct on a C1 device.
Change-Id: Ifd7ea9862860c7ec4ebdbd5e281de9897b9dd6b2
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 1ffde97..f182c32 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -255,6 +255,7 @@
         AppInstallOnExternalStorageReported app_install_on_external_storage_reported = 181;
         NetworkStackReported network_stack_reported = 182;
         AppMovedStorageReported app_moved_storage_reported = 183;
+        BiometricEnrolled biometric_enrolled = 184;
     }
 
     // Pulled events will start at field 10000.
@@ -3154,6 +3155,23 @@
     optional android.hardware.biometrics.IssueEnum issue = 2;
 }
 
+/**
+ * Logs when a biometric enrollment occurs.
+ *
+ * Logged from:
+ *   frameworks/base/services/core/java/com/android/server/biometrics
+ */
+message BiometricEnrolled {
+    // Biometric modality that was used.
+    optional android.hardware.biometrics.ModalityEnum modality = 1;
+    // The associated user. Eg: 0 for owners, 10+ for others. Defined in android/os/UserHandle.java
+    optional int32 user = 2;
+    // The amount of time the enrollment took in milliseconds.
+    optional int64 latency_millis = 3;
+    // Whether or not the enrollment was successful.
+    optional bool success = 4;
+}
+
 message Notification {
 
     // Type of notification event.
diff --git a/services/core/java/com/android/server/biometrics/EnrollClient.java b/services/core/java/com/android/server/biometrics/EnrollClient.java
index d5e626a..e656d98 100644
--- a/services/core/java/com/android/server/biometrics/EnrollClient.java
+++ b/services/core/java/com/android/server/biometrics/EnrollClient.java
@@ -36,6 +36,7 @@
     private final byte[] mCryptoToken;
     private final BiometricUtils mBiometricUtils;
     private final int[] mDisabledFeatures;
+    private long mEnrollmentStartTimeMs;
 
     public abstract boolean shouldVibrate();
 
@@ -61,6 +62,9 @@
             int remaining) {
         if (remaining == 0) {
             mBiometricUtils.addBiometricForUser(getContext(), getTargetUserId(), identifier);
+            logOnEnrolled(getTargetUserId(),
+                    System.currentTimeMillis() - mEnrollmentStartTimeMs,
+                    true /* enrollSuccessful */);
         }
         notifyUserActivity();
         return sendEnrollResult(identifier, remaining);
@@ -89,6 +93,7 @@
 
     @Override
     public int start() {
+        mEnrollmentStartTimeMs = System.currentTimeMillis();
         final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC);
         try {
             final ArrayList<Integer> disabledFeatures = new ArrayList<>();
@@ -127,10 +132,6 @@
         } catch (RemoteException e) {
             Slog.e(getLogTag(), "stopEnrollment failed", e);
         }
-        if (initiatedByClient) {
-            onError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_CANCELED,
-                    0 /* vendorCode */);
-        }
         mAlreadyCancelled = true;
         return 0;
     }
@@ -155,4 +156,17 @@
         return true; // Invalid for EnrollClient
     }
 
+    /**
+     * Called when we get notification from the biometric's HAL that an error has occurred with the
+     * current operation. Common to authenticate, enroll, enumerate and remove.
+     * @param error
+     * @return true if client should be removed
+     */
+    @Override
+    public boolean onError(long deviceId, int error, int vendorCode) {
+        logOnEnrolled(getTargetUserId(), System.currentTimeMillis() - mEnrollmentStartTimeMs,
+                false /* enrollSuccessful */);
+        return super.onError(deviceId, error, vendorCode);
+    }
+
 }
diff --git a/services/core/java/com/android/server/biometrics/LoggableMonitor.java b/services/core/java/com/android/server/biometrics/LoggableMonitor.java
index 3b75b95..b0577cd 100644
--- a/services/core/java/com/android/server/biometrics/LoggableMonitor.java
+++ b/services/core/java/com/android/server/biometrics/LoggableMonitor.java
@@ -150,4 +150,23 @@
                 authState,
                 latency);
     }
+
+    protected final void logOnEnrolled(int targetUserId, long latency, boolean enrollSuccessful) {
+        if (DEBUG) {
+            Slog.v(TAG, "Enrolled! Modality: " + statsModality()
+                    + ", User: " + targetUserId
+                    + ", Client: " + statsClient()
+                    + ", Latency: " + latency
+                    + ", Success: " + enrollSuccessful);
+        } else {
+            Slog.v(TAG, "Enroll latency: " + latency);
+        }
+
+        StatsLog.write(StatsLog.BIOMETRIC_ENROLLED,
+                statsModality(),
+                targetUserId,
+                latency,
+                enrollSuccessful);
+    }
+
 }