Log metrics related to Remote Key Provisioning (RKP).

This CL adds metrics related to attestation pool status and out of key
error, from keystore side.

Ignore-AOSP-First: No mergepath to AOSP.
Bug: 184301651
Test: Statsd test drive script.
Change-Id: I7025c897449e050dda42e2b290dea336c5ad0d52
diff --git a/keystore2/aidl/android/security/metrics/RkpPoolStats.aidl b/keystore2/aidl/android/security/metrics/RkpPoolStats.aidl
index b233842..016b6ff 100644
--- a/keystore2/aidl/android/security/metrics/RkpPoolStats.aidl
+++ b/keystore2/aidl/android/security/metrics/RkpPoolStats.aidl
@@ -16,14 +16,17 @@
 
 package android.security.metrics;
 
-import android.security.metrics.PoolStatus;
+import android.security.metrics.SecurityLevel;
 
 /**
- * Count of keys in the key pool related to Remote Key Provisioning (RKP).
+ * Count of keys in the attestation key pool related to Remote Key Provisioning (RKP).
  * @hide
  */
 @RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
 parcelable RkpPoolStats {
-    PoolStatus pool_status;
-    int count_of_keys;
+    SecurityLevel security_level;
+    int expiring;
+    int unassigned;
+    int attested;
+    int total;
 }
\ No newline at end of file
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index ca346e0..c788720 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -47,6 +47,7 @@
 
 use crate::impl_metadata; // This is in db_utils.rs
 use crate::key_parameter::{KeyParameter, Tag};
+use crate::metrics_store::log_rkp_error_stats;
 use crate::permission::KeyPermSet;
 use crate::utils::{get_current_time_in_milliseconds, watchdog as wd, AID_USER_OFFSET};
 use crate::{
@@ -72,6 +73,7 @@
 use android_security_metrics::aidl::android::security::metrics::{
     StorageStats::StorageStats,
     Storage::Storage as MetricsStorage,
+    RkpError::RkpError as MetricsRkpError,
 };
 
 use keystore2_crypto::ZVec;
@@ -1829,6 +1831,7 @@
                 )
                 .context("Failed to assign attestation key")?;
             if result == 0 {
+                log_rkp_error_stats(MetricsRkpError::OUT_OF_KEYS);
                 return Err(KsError::Rc(ResponseCode::OUT_OF_KEYS)).context("Out of keys.");
             } else if result > 1 {
                 return Err(KsError::sys())
diff --git a/keystore2/src/metrics_store.rs b/keystore2/src/metrics_store.rs
index e3de035..32fe353 100644
--- a/keystore2/src/metrics_store.rs
+++ b/keystore2/src/metrics_store.rs
@@ -21,6 +21,7 @@
 use crate::globals::DB;
 use crate::key_parameter::KeyParameterValue as KsKeyParamValue;
 use crate::operation::Outcome;
+use crate::remote_provisioning::get_pool_status;
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
     Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
     HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
@@ -38,12 +39,15 @@
     KeyOrigin::KeyOrigin as MetricsKeyOrigin, Keystore2AtomWithOverflow::Keystore2AtomWithOverflow,
     KeystoreAtom::KeystoreAtom, KeystoreAtomPayload::KeystoreAtomPayload,
     Outcome::Outcome as MetricsOutcome, Purpose::Purpose as MetricsPurpose,
-    SecurityLevel::SecurityLevel as MetricsSecurityLevel, Storage::Storage as MetricsStorage,
+    RkpError::RkpError as MetricsRkpError, RkpErrorStats::RkpErrorStats,
+    RkpPoolStats::RkpPoolStats, SecurityLevel::SecurityLevel as MetricsSecurityLevel,
+    Storage::Storage as MetricsStorage,
 };
 use anyhow::Result;
 use lazy_static::lazy_static;
 use std::collections::HashMap;
 use std::sync::Mutex;
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
 
 lazy_static! {
     /// Singleton for MetricsStore.
@@ -83,7 +87,10 @@
             return pull_storage_stats();
         }
 
-        // TODO (b/184301651): process and return RKP pool stats.
+        // Process and return RKP pool stats.
+        if AtomID::RKP_POOL_STATS == atom_id {
+            return pull_attestation_pool_stats();
+        }
 
         // It is safe to call unwrap here since the lock can not be poisoned based on its usage
         // in this module and the lock is not acquired in the same thread before.
@@ -534,6 +541,47 @@
     Ok(atom_vec)
 }
 
+fn pull_attestation_pool_stats() -> Result<Vec<KeystoreAtom>> {
+    let mut atoms = Vec::<KeystoreAtom>::new();
+    for sec_level in &[SecurityLevel::TRUSTED_ENVIRONMENT, SecurityLevel::STRONGBOX] {
+        let expired_by = SystemTime::now()
+            .duration_since(UNIX_EPOCH)
+            .unwrap_or_else(|_| Duration::new(0, 0))
+            .as_secs() as i64;
+
+        let result = get_pool_status(expired_by, *sec_level);
+
+        if let Ok(pool_status) = result {
+            let rkp_pool_stats = RkpPoolStats {
+                security_level: process_security_level(*sec_level),
+                expiring: pool_status.expiring,
+                unassigned: pool_status.unassigned,
+                attested: pool_status.attested,
+                total: pool_status.total,
+            };
+            atoms.push(KeystoreAtom {
+                payload: KeystoreAtomPayload::RkpPoolStats(rkp_pool_stats),
+                ..Default::default()
+            });
+        } else {
+            log::error!(
+                concat!(
+                    "In pull_attestation_pool_stats: Failed to retrieve pool status",
+                    " for security level: {:?}"
+                ),
+                sec_level
+            );
+        }
+    }
+    Ok(atoms)
+}
+
+/// Log error events related to Remote Key Provisioning (RKP).
+pub fn log_rkp_error_stats(rkp_error: MetricsRkpError) {
+    let rkp_error_stats = KeystoreAtomPayload::RkpErrorStats(RkpErrorStats { rkpError: rkp_error });
+    METRICS_STORE.insert_atom(AtomID::RKP_ERROR_STATS, rkp_error_stats);
+}
+
 /// Enum defining the bit position for each padding mode. Since padding mode can be repeatable, it
 /// is represented using a bitmap.
 #[allow(non_camel_case_types)]
diff --git a/keystore2/src/remote_provisioning.rs b/keystore2/src/remote_provisioning.rs
index 1f3f8e8..aa0d218 100644
--- a/keystore2/src/remote_provisioning.rs
+++ b/keystore2/src/remote_provisioning.rs
@@ -234,26 +234,6 @@
         Ok(BnRemoteProvisioning::new_binder(result, BinderFeatures::default()))
     }
 
-    /// Populates the AttestationPoolStatus parcelable with information about how many
-    /// certs will be expiring by the date provided in `expired_by` along with how many
-    /// keys have not yet been assigned.
-    pub fn get_pool_status(
-        &self,
-        expired_by: i64,
-        sec_level: SecurityLevel,
-    ) -> Result<AttestationPoolStatus> {
-        let (_, _, uuid) = get_keymint_device(&sec_level)?;
-        DB.with::<_, Result<AttestationPoolStatus>>(|db| {
-            let mut db = db.borrow_mut();
-            // delete_expired_attestation_keys is always safe to call, and will remove anything
-            // older than the date at the time of calling. No work should be done on the
-            // attestation keys unless the pool status is checked first, so this call should be
-            // enough to routinely clean out expired keys.
-            db.delete_expired_attestation_keys()?;
-            db.get_attestation_pool_status(expired_by, &uuid)
-        })
-    }
-
     /// Generates a CBOR blob which will be assembled by the calling code into a larger
     /// CBOR blob intended for delivery to a provisioning serever. This blob will contain
     /// `num_csr` certificate signing requests for attestation keys generated in the TEE,
@@ -381,6 +361,22 @@
     }
 }
 
+/// Populates the AttestationPoolStatus parcelable with information about how many
+/// certs will be expiring by the date provided in `expired_by` along with how many
+/// keys have not yet been assigned.
+pub fn get_pool_status(expired_by: i64, sec_level: SecurityLevel) -> Result<AttestationPoolStatus> {
+    let (_, _, uuid) = get_keymint_device(&sec_level)?;
+    DB.with::<_, Result<AttestationPoolStatus>>(|db| {
+        let mut db = db.borrow_mut();
+        // delete_expired_attestation_keys is always safe to call, and will remove anything
+        // older than the date at the time of calling. No work should be done on the
+        // attestation keys unless the pool status is checked first, so this call should be
+        // enough to routinely clean out expired keys.
+        db.delete_expired_attestation_keys()?;
+        db.get_attestation_pool_status(expired_by, &uuid)
+    })
+}
+
 impl binder::Interface for RemoteProvisioningService {}
 
 // Implementation of IRemoteProvisioning. See AIDL spec at
@@ -392,7 +388,7 @@
         sec_level: SecurityLevel,
     ) -> binder::public_api::Result<AttestationPoolStatus> {
         let _wp = wd::watch_millis("IRemoteProvisioning::getPoolStatus", 500);
-        map_or_log_err(self.get_pool_status(expired_by, sec_level), Ok)
+        map_or_log_err(get_pool_status(expired_by, sec_level), Ok)
     }
 
     fn generateCsr(