floss: skip resume flow if no suspend id is recorded

If there is no suspend id recorded during resume, it means nothing is
done during suspend. Log the metrics and return.

Bug: 310077261
Test: mma -j32
Flag: EXEMPT Floss only changes and chromeos metrics.
Cq-Depend: chromium:5179124

Change-Id: I65f88b70b028865000ef3d9f9a6491687ee4844c
diff --git a/system/gd/metrics/chromeos/metrics.cc b/system/gd/metrics/chromeos/metrics.cc
index dea7fe8..1b9bca0 100644
--- a/system/gd/metrics/chromeos/metrics.cc
+++ b/system/gd/metrics/chromeos/metrics.cc
@@ -318,5 +318,24 @@
   }
 }
 
+void LogMetricsSuspendIdState(uint32_t state) {
+  int64_t suspend_id_state = 0;
+  int64_t boot_time;
+  std::string boot_id;
+
+  if (!GetBootId(&boot_id)) return;
+
+  boot_time = bluetooth::common::time_get_os_boottime_us();
+
+  suspend_id_state = (int64_t)ToSuspendIdState(state);
+  LOG_DEBUG("SuspendIdState: %s, %d, %d", boot_id.c_str(), boot_time, suspend_id_state);
+
+  ::metrics::structured::events::bluetooth::BluetoothSuspendIdStateChanged()
+      .SetBootId(boot_id)
+      .SetSystemTime(boot_time)
+      .SetSuspendIdState(suspend_id_state)
+      .Record();
+}
+
 }  // namespace metrics
 }  // namespace bluetooth
diff --git a/system/gd/metrics/chromeos/metrics_event.cc b/system/gd/metrics/chromeos/metrics_event.cc
index 9db8097..f884c0b 100644
--- a/system/gd/metrics/chromeos/metrics_event.cc
+++ b/system/gd/metrics/chromeos/metrics_event.cc
@@ -234,6 +234,10 @@
   return state == 1 ? AdapterState::ON : AdapterState::OFF;
 }
 
+SuspendIdState ToSuspendIdState(uint32_t state) {
+  return state == 1 ? SuspendIdState::Recorded : SuspendIdState::NoRecord;
+}
+
 ConnectionType ToPairingDeviceType(std::string addr, uint32_t device_type) {
   // A map stores the pending ConnectionType used to match a pairing event with unknown type.
   // map<address, type>
diff --git a/system/gd/metrics/chromeos/metrics_event.h b/system/gd/metrics/chromeos/metrics_event.h
index 3a641f8..b67ee2c 100644
--- a/system/gd/metrics/chromeos/metrics_event.h
+++ b/system/gd/metrics/chromeos/metrics_event.h
@@ -195,6 +195,10 @@
   TRANSPORT_TYPE_SDIO = 3,
 };
 
+// ENUM definition for suspend id state that in sync with ChromeOS structured metrics
+// BluetoothSuspendIdStateChanged/SuspendIdState.
+enum class SuspendIdState : int64_t { NoRecord = 0, Recorded = 1 };
+
 // A struct holds the parsed profile connection event.
 struct ProfileConnectionEvent {
   int64_t type;
@@ -205,6 +209,9 @@
 // Convert topshim::btif::BtState to AdapterState.
 AdapterState ToAdapterState(uint32_t state);
 
+// Convert to SuspendIdState.
+SuspendIdState ToSuspendIdState(uint32_t state);
+
 // Convert topshim::btif::BtDeviceType to ConnectionType
 ConnectionType ToPairingDeviceType(std::string addr, uint32_t device_type);
 
diff --git a/system/gd/metrics/linux/metrics.cc b/system/gd/metrics/linux/metrics.cc
index 648329a..9792edf 100644
--- a/system/gd/metrics/linux/metrics.cc
+++ b/system/gd/metrics/linux/metrics.cc
@@ -51,5 +51,7 @@
 
 void LogMetricsChipsetInfoReport() {}
 
+void LogMetricsSuspendIdState(uint32_t state){};
+
 }  // namespace metrics
 }  // namespace bluetooth
diff --git a/system/gd/metrics/metrics.h b/system/gd/metrics/metrics.h
index 6e22318..16b95a1 100644
--- a/system/gd/metrics/metrics.h
+++ b/system/gd/metrics/metrics.h
@@ -40,5 +40,7 @@
     RawAddress* addr, uint32_t transport, uint32_t status, uint32_t acl_state, uint32_t direction, uint32_t hci_reason);
 void LogMetricsChipsetInfoReport();
 
+void LogMetricsSuspendIdState(uint32_t state);
+
 }  // namespace metrics
 }  // namespace bluetooth
diff --git a/system/gd/rust/linux/stack/src/suspend.rs b/system/gd/rust/linux/stack/src/suspend.rs
index 221ae2a..99971eb 100644
--- a/system/gd/rust/linux/stack/src/suspend.rs
+++ b/system/gd/rust/linux/stack/src/suspend.rs
@@ -7,6 +7,7 @@
 use crate::callbacks::Callbacks;
 use crate::{BluetoothGatt, Message, RPCProxy};
 use bt_topshim::btif::{BluetoothInterface, BtDiscMode};
+use bt_topshim::metrics;
 use log::warn;
 use num_derive::{FromPrimitive, ToPrimitive};
 use std::sync::{Arc, Mutex};
@@ -292,6 +293,22 @@
     }
 
     fn resume(&mut self) -> bool {
+        // Suspend ID state 0: NoRecord, 1: Recorded
+        let suspend_id_state = match self.suspend_state.lock().unwrap().suspend_id {
+            None => {
+                log::error!("No suspend id saved at resume.");
+                0
+            }
+            Some(_) => 1,
+        };
+        metrics::suspend_complete_state(suspend_id_state);
+        // If no suspend id is saved here, it means floss did not receive the SuspendImminent
+        // signal and as a result, the suspend flow was not run.
+        // Skip the resume flow and return after logging the metrics.
+        if suspend_id_state == 0 {
+            return true;
+        }
+
         let hci_index = self.bt.lock().unwrap().get_hci_index();
         notify_suspend_state(hci_index, false);
 
diff --git a/system/gd/rust/topshim/metrics/metrics_shim.cc b/system/gd/rust/topshim/metrics/metrics_shim.cc
index a513a56..2e9b019 100644
--- a/system/gd/rust/topshim/metrics/metrics_shim.cc
+++ b/system/gd/rust/topshim/metrics/metrics_shim.cc
@@ -65,6 +65,10 @@
   metrics::LogMetricsAclConnectionStateChanged(&addr, transport, status, acl_state, direction, hci_reason);
 }
 
+void suspend_complete_state(uint32_t state) {
+  metrics::LogMetricsSuspendIdState(state);
+}
+
 }  // namespace rust
 }  // namespace topshim
 }  // namespace bluetooth
diff --git a/system/gd/rust/topshim/metrics/metrics_shim.h b/system/gd/rust/topshim/metrics/metrics_shim.h
index ed8fa2b..d2e8fb9 100644
--- a/system/gd/rust/topshim/metrics/metrics_shim.h
+++ b/system/gd/rust/topshim/metrics/metrics_shim.h
@@ -42,6 +42,7 @@
 void acl_connect_attempt(RawAddress addr, uint32_t acl_state);
 void acl_connection_state_changed(
     RawAddress addr, uint32_t transport, uint32_t status, uint32_t acl_state, uint32_t direction, uint32_t hci_reason);
+void suspend_complete_state(uint32_t state);
 
 }  // namespace rust
 }  // namespace topshim
diff --git a/system/gd/rust/topshim/src/metrics.rs b/system/gd/rust/topshim/src/metrics.rs
index edca7d1..9c1aa7c 100644
--- a/system/gd/rust/topshim/src/metrics.rs
+++ b/system/gd/rust/topshim/src/metrics.rs
@@ -47,6 +47,7 @@
             direction: u32,
             hci_reason: u32,
         );
+        fn suspend_complete_state(state: u32);
     }
 }
 
@@ -126,3 +127,7 @@
         hci_reason as u32,
     );
 }
+
+pub fn suspend_complete_state(state: u32) {
+    ffi::suspend_complete_state(state);
+}