Merge "Keystore 2.0: Add watch dog instrumentations in the calls into keystore."
diff --git a/keystore2/src/enforcements.rs b/keystore2/src/enforcements.rs
index 378b72f..04d1f77 100644
--- a/keystore2/src/enforcements.rs
+++ b/keystore2/src/enforcements.rs
@@ -682,9 +682,10 @@
             // So the HAT cannot be presented on create. So on update/finish we present both
             // an per-op-bound auth token and a timestamp token.
             (Some(_), true, true) => (None, DeferredAuthState::TimeStampedOpAuthRequired),
-            (Some(hat), true, false) => {
-                (None, DeferredAuthState::TimeStampRequired(hat.take_auth_token()))
-            }
+            (Some(hat), true, false) => (
+                Some(hat.auth_token().clone()),
+                DeferredAuthState::TimeStampRequired(hat.take_auth_token()),
+            ),
             (Some(hat), false, true) => {
                 (Some(hat.take_auth_token()), DeferredAuthState::OpAuthRequired)
             }
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index b640326b..54fceab 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -174,7 +174,7 @@
         &DB_PATH.lock().expect("Could not get the database path for legacy blob loader.")));
     /// Legacy migrator. Atomically migrates legacy blobs to the database.
     pub static ref LEGACY_MIGRATOR: Arc<LegacyMigrator> =
-        Arc::new(LegacyMigrator::new(ASYNC_TASK.clone()));
+        Arc::new(LegacyMigrator::new(Arc::new(Default::default())));
     /// Background thread which handles logging via statsd and logd
     pub static ref LOGS_HANDLER: Arc<AsyncTask> = Default::default();
 }
diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp
index 4141b1c..bdc3f2a 100644
--- a/keystore2/src/km_compat/km_compat.cpp
+++ b/keystore2/src/km_compat/km_compat.cpp
@@ -687,6 +687,14 @@
     return convertErrorCode(km_error);
 }
 
+ScopedAStatus
+KeyMintDevice::getKeyCharacteristics(const std::vector<uint8_t>& /* storageKeyBlob */,
+                                     const std::vector<uint8_t>& /* appId */,
+                                     const std::vector<uint8_t>& /* appData */,
+                                     std::vector<KeyCharacteristics>* /* keyCharacteristics */) {
+    return convertErrorCode(KMV1::ErrorCode::UNIMPLEMENTED);
+}
+
 ScopedAStatus KeyMintOperation::updateAad(const std::vector<uint8_t>& input,
                                           const std::optional<HardwareAuthToken>& optAuthToken,
                                           const std::optional<TimeStampToken>& optTimeStampToken) {
diff --git a/keystore2/src/km_compat/km_compat.h b/keystore2/src/km_compat/km_compat.h
index cd2b804..09c9157 100644
--- a/keystore2/src/km_compat/km_compat.h
+++ b/keystore2/src/km_compat/km_compat.h
@@ -118,6 +118,11 @@
     ScopedAStatus convertStorageKeyToEphemeral(const std::vector<uint8_t>& storageKeyBlob,
                                                std::vector<uint8_t>* ephemeralKeyBlob) override;
 
+    ScopedAStatus
+    getKeyCharacteristics(const std::vector<uint8_t>& storageKeyBlob,
+                          const std::vector<uint8_t>& appId, const std::vector<uint8_t>& appData,
+                          std::vector<KeyCharacteristics>* keyCharacteristics) override;
+
     // These are public to allow testing code to use them directly.
     // This class should not be used publicly anyway.
     std::variant<std::vector<Certificate>, KMV1_ErrorCode>
diff --git a/keystore2/src/watchdog.rs b/keystore2/src/watchdog.rs
index 0ed522f..9cca171 100644
--- a/keystore2/src/watchdog.rs
+++ b/keystore2/src/watchdog.rs
@@ -66,18 +66,19 @@
     thread: Option<thread::JoinHandle<()>>,
     timeout: Duration,
     records: HashMap<Index, Record>,
+    last_report: Instant,
     has_overdue: bool,
 }
 
 impl WatchdogState {
-    fn update_overdue_and_find_next_timeout(&mut self) -> Option<Duration> {
+    fn update_overdue_and_find_next_timeout(&mut self) -> (bool, Option<Duration>) {
         let now = Instant::now();
         let mut next_timeout: Option<Duration> = None;
-        self.has_overdue = false;
+        let mut has_overdue = false;
         for (_, r) in self.records.iter() {
             let timeout = r.deadline.saturating_duration_since(now);
             if timeout == Duration::new(0, 0) {
-                self.has_overdue = true;
+                has_overdue = true;
                 continue;
             }
             next_timeout = match next_timeout {
@@ -91,13 +92,25 @@
                 None => Some(timeout),
             };
         }
-        next_timeout
+        (has_overdue, next_timeout)
     }
 
-    fn log_report(&self) -> bool {
-        if !self.has_overdue {
-            return false;
+    fn log_report(&mut self, has_overdue: bool) -> bool {
+        match (self.has_overdue, has_overdue) {
+            (true, true) => {
+                if self.last_report.elapsed() < Watchdog::NOISY_REPORT_TIMEOUT {
+                    self.has_overdue = false;
+                    return false;
+                }
+            }
+            (_, false) => {
+                self.has_overdue = false;
+                return false;
+            }
+            (false, true) => {}
         }
+        self.last_report = Instant::now();
+        self.has_overdue = has_overdue;
         log::warn!("Keystore Watchdog report:");
         log::warn!("Overdue records:");
         let now = Instant::now();
@@ -164,6 +177,7 @@
                     thread: None,
                     timeout,
                     records: HashMap::new(),
+                    last_report: Instant::now(),
                     has_overdue: false,
                 }),
             )),
@@ -249,8 +263,8 @@
             let mut state = state.lock().unwrap();
 
             loop {
-                let next_timeout = state.update_overdue_and_find_next_timeout();
-                let has_overdue = state.log_report();
+                let (has_overdue, next_timeout) = state.update_overdue_and_find_next_timeout();
+                state.log_report(has_overdue);
                 let (next_timeout, idle) = match (has_overdue, next_timeout) {
                     (true, Some(next_timeout)) => {
                         (min(next_timeout, Self::NOISY_REPORT_TIMEOUT), false)