Floss: Define suspend interface for LE Scan

This defines interfaces needed to implement suspend/resume for LE Scan:
* Internal methods `scan_enter_suspend` and `scan_exit_suspend` to be
  called by suspend module.
* StartScan and StopScan returning BtStatus to indicate the request
  being blocked in suspend mode.
* `SuspendMode` property so that clients can optionally wait for suspend
  to be over rather than retrying arbitrarily.

Bug: 224603540
Tag: #floss
Test: Manual - Build Floss on Linux

Change-Id: Iaaa4dc362d30de491616e9279e6a9d9a9fd35812
diff --git a/system/gd/rust/linux/client/src/callbacks.rs b/system/gd/rust/linux/client/src/callbacks.rs
index 09f884f..a57bf8e 100644
--- a/system/gd/rust/linux/client/src/callbacks.rs
+++ b/system/gd/rust/linux/client/src/callbacks.rs
@@ -21,7 +21,7 @@
 };
 use btstack::suspend::ISuspendCallback;
 use btstack::uuid::UuidWrapper;
-use btstack::RPCProxy;
+use btstack::{RPCProxy, SuspendMode};
 use dbus::nonblock::SyncConnection;
 use dbus_crossroads::Crossroads;
 use dbus_projection::DisconnectWatcher;
@@ -327,6 +327,10 @@
             print_info!("Scan result: {:#?}", scan_result);
         }
     }
+
+    fn on_suspend_mode_change(&self, _suspend_mode: SuspendMode) {
+        // No-op, not interesting for btclient.
+    }
 }
 
 impl RPCProxy for ScannerCallback {
diff --git a/system/gd/rust/linux/client/src/dbus_iface.rs b/system/gd/rust/linux/client/src/dbus_iface.rs
index 1eaa740..24fa53b 100644
--- a/system/gd/rust/linux/client/src/dbus_iface.rs
+++ b/system/gd/rust/linux/client/src/dbus_iface.rs
@@ -22,7 +22,7 @@
     BluetoothServerSocket, BluetoothSocket, CallbackId, IBluetoothSocketManager,
     IBluetoothSocketManagerCallbacks, SocketId, SocketResult,
 };
-use btstack::RPCProxy;
+use btstack::{RPCProxy, SuspendMode};
 
 use btstack::suspend::{ISuspend, ISuspendCallback, SuspendType};
 
@@ -68,6 +68,7 @@
 impl_dbus_arg_enum!(Profile);
 impl_dbus_arg_enum!(ScanType);
 impl_dbus_arg_enum!(SocketType);
+impl_dbus_arg_enum!(SuspendMode);
 impl_dbus_arg_enum!(SuspendType);
 impl_dbus_arg_from_into!(Uuid, Vec<u8>);
 
@@ -242,6 +243,11 @@
     fn on_scan_result(&self, scan_result: ScanResult) {
         dbus_generated!()
     }
+
+    #[dbus_method("OnSuspendModeChange")]
+    fn on_suspend_mode_change(&self, suspend_mode: SuspendMode) {
+        dbus_generated!()
+    }
 }
 
 // Implements RPC-friendly wrapper methods for calling IBluetooth, generated by
@@ -771,12 +777,22 @@
     }
 
     #[dbus_method("StartScan")]
-    fn start_scan(&mut self, _scanner_id: u8, _settings: ScanSettings, _filters: Vec<ScanFilter>) {
+    fn start_scan(
+        &mut self,
+        _scanner_id: u8,
+        _settings: ScanSettings,
+        _filters: Vec<ScanFilter>,
+    ) -> BtStatus {
         dbus_generated!()
     }
 
     #[dbus_method("StopScan")]
-    fn stop_scan(&mut self, _scanner_id: u8) {
+    fn stop_scan(&mut self, _scanner_id: u8) -> BtStatus {
+        dbus_generated!()
+    }
+
+    #[dbus_method("GetScanSuspendMode")]
+    fn get_scan_suspend_mode(&self) -> SuspendMode {
         dbus_generated!()
     }
 
diff --git a/system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs b/system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs
index 2b8ba57..0f4db89 100644
--- a/system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs
+++ b/system/gd/rust/linux/service/src/iface_bluetooth_gatt.rs
@@ -1,4 +1,6 @@
-use bt_topshim::{btif::Uuid128Bit, profiles::gatt::GattStatus};
+use bt_topshim::profiles::gatt::GattStatus;
+
+use bt_topshim::btif::{BtStatus, Uuid128Bit};
 
 use btstack::bluetooth_adv::{
     AdvertiseData, AdvertisingSetParameters, IAdvertisingSetCallback, PeriodicAdvertisingParameters,
@@ -8,7 +10,7 @@
     GattWriteRequestStatus, GattWriteType, IBluetoothGatt, IBluetoothGattCallback,
     IScannerCallback, LePhy, RSSISettings, ScanFilter, ScanResult, ScanSettings, ScanType,
 };
-use btstack::RPCProxy;
+use btstack::{RPCProxy, SuspendMode};
 
 use dbus::arg::RefArg;
 
@@ -165,6 +167,11 @@
     fn on_scan_result(&self, scan_result: ScanResult) {
         dbus_generated!()
     }
+
+    #[dbus_method("OnSuspendModeChange")]
+    fn on_suspend_mode_change(&self, suspend_mode: SuspendMode) {
+        dbus_generated!()
+    }
 }
 
 #[dbus_propmap(BluetoothGattDescriptor)]
@@ -227,6 +234,7 @@
 impl_dbus_arg_enum!(GattWriteType);
 impl_dbus_arg_enum!(LePhy);
 impl_dbus_arg_enum!(ScanType);
+impl_dbus_arg_enum!(SuspendMode);
 
 #[dbus_propmap(ScanFilter)]
 struct ScanFilterDBus {}
@@ -362,12 +370,22 @@
     }
 
     #[dbus_method("StartScan")]
-    fn start_scan(&mut self, scanner_id: u8, settings: ScanSettings, filters: Vec<ScanFilter>) {
+    fn start_scan(
+        &mut self,
+        scanner_id: u8,
+        settings: ScanSettings,
+        filters: Vec<ScanFilter>,
+    ) -> BtStatus {
         dbus_generated!()
     }
 
     #[dbus_method("StopScan")]
-    fn stop_scan(&mut self, scanner_id: u8) {
+    fn stop_scan(&mut self, scanner_id: u8) -> BtStatus {
+        dbus_generated!()
+    }
+
+    #[dbus_method("GetScanSuspendMode")]
+    fn get_scan_suspend_mode(&self) -> SuspendMode {
         dbus_generated!()
     }
 
diff --git a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs
index a382783..6a08e8f 100644
--- a/system/gd/rust/linux/stack/src/bluetooth_gatt.rs
+++ b/system/gd/rust/linux/stack/src/bluetooth_gatt.rs
@@ -3,7 +3,7 @@
 use btif_macros::{btif_callback, btif_callbacks_dispatcher};
 
 use bt_topshim::bindings::root::bluetooth::Uuid;
-use bt_topshim::btif::{BluetoothInterface, RawAddress, Uuid128Bit};
+use bt_topshim::btif::{BluetoothInterface, BtStatus, RawAddress, Uuid128Bit};
 use bt_topshim::profiles::gatt::{
     BtGattDbElement, BtGattNotifyParams, BtGattReadParams, Gatt, GattAdvCallbacks,
     GattAdvCallbacksDispatcher, GattAdvInbandCallbacksDispatcher, GattClientCallbacks,
@@ -20,7 +20,7 @@
 };
 use crate::callbacks::Callbacks;
 use crate::uuid::parse_uuid_string;
-use crate::{Message, RPCProxy};
+use crate::{Message, RPCProxy, SuspendMode};
 use log::{debug, warn};
 use num_traits::cast::{FromPrimitive, ToPrimitive};
 use num_traits::clamp;
@@ -169,10 +169,18 @@
     fn unregister_scanner(&mut self, scanner_id: u8) -> bool;
 
     /// Activate scan of the given scanner id.
-    fn start_scan(&mut self, scanner_id: u8, settings: ScanSettings, filters: Vec<ScanFilter>);
+    fn start_scan(
+        &mut self,
+        scanner_id: u8,
+        settings: ScanSettings,
+        filters: Vec<ScanFilter>,
+    ) -> BtStatus;
 
     /// Deactivate scan of the given scanner id.
-    fn stop_scan(&mut self, scanner_id: u8);
+    fn stop_scan(&mut self, scanner_id: u8) -> BtStatus;
+
+    /// Returns the current suspend mode.
+    fn get_scan_suspend_mode(&self) -> SuspendMode;
 
     // Advertising
 
@@ -533,6 +541,9 @@
     /// shared among all scanner callbacks, clients may receive more advertisements than what is
     /// requested to be filtered in.
     fn on_scan_result(&self, scan_result: ScanResult);
+
+    /// When LE Scan module changes suspend mode due to system suspend/resume.
+    fn on_suspend_mode_change(&self, suspend_mode: SuspendMode);
 }
 
 #[derive(Debug, FromPrimitive, ToPrimitive)]
@@ -749,6 +760,26 @@
         self.scanner_callbacks.remove_callback(callback_id)
     }
 
+    /// Enters suspend mode for LE Scan.
+    ///
+    /// This "pauses" all operations managed by this module to prepare for system suspend. A
+    /// callback is triggered to let clients know that this module is in suspend mode and some
+    /// subsequent API calls will be blocked in this mode.
+    pub fn scan_enter_suspend(&mut self) {
+        // TODO(b/224603540): Implement
+        todo!()
+    }
+
+    /// Exits suspend mode for LE Scan.
+    ///
+    /// To be called after system resume/wake up. This "unpauses" the operations that were "paused"
+    /// due to suspend. A callback is triggered to let clients when this module has exited suspend
+    /// mode.
+    pub fn scan_exit_suspend(&mut self) {
+        // TODO(b/224603540): Implement
+        todo!()
+    }
+
     // Update the topshim's scan state depending on the states of registered scanners. Scan is
     // enabled if there is at least 1 active registered scanner.
     fn update_scan(&mut self) {
@@ -834,7 +865,12 @@
         true
     }
 
-    fn start_scan(&mut self, scanner_id: u8, _settings: ScanSettings, _filters: Vec<ScanFilter>) {
+    fn start_scan(
+        &mut self,
+        scanner_id: u8,
+        _settings: ScanSettings,
+        _filters: Vec<ScanFilter>,
+    ) -> BtStatus {
         // Multiplexing scanners happens at this layer. The implementations of start_scan
         // and stop_scan maintains the state of all registered scanners and based on the states
         // update the scanning and/or filter states of libbluetooth.
@@ -843,21 +879,29 @@
             scanner.is_active = true;
         } else {
             log::warn!("Scanner {} not found", scanner_id);
-            return;
+            return BtStatus::Fail;
         }
 
         self.update_scan();
+        BtStatus::Success
     }
 
-    fn stop_scan(&mut self, scanner_id: u8) {
+    fn stop_scan(&mut self, scanner_id: u8) -> BtStatus {
         if let Some(scanner) = self.find_scanner_by_id(scanner_id) {
             scanner.is_active = false;
         } else {
             log::warn!("Scanner {} not found", scanner_id);
-            return;
+            // Clients can assume success of the removal since the scanner does not exist.
+            return BtStatus::Success;
         }
 
         self.update_scan();
+        BtStatus::Success
+    }
+
+    fn get_scan_suspend_mode(&self) -> SuspendMode {
+        // TODO(b/224603540): Implement.
+        return SuspendMode::Normal;
     }
 
     // Advertising
diff --git a/system/gd/rust/linux/stack/src/lib.rs b/system/gd/rust/linux/stack/src/lib.rs
index e9ffbea..56abe76 100644
--- a/system/gd/rust/linux/stack/src/lib.rs
+++ b/system/gd/rust/linux/stack/src/lib.rs
@@ -78,6 +78,18 @@
     SocketManagerCallbackDisconnected(u32),
 }
 
+/// Represents suspend mode of a module.
+///
+/// Being in suspend mode means that the module pauses some activities if required for suspend and
+/// some subsequent API calls will be blocked with a retryable error.
+#[derive(FromPrimitive, ToPrimitive)]
+pub enum SuspendMode {
+    Normal = 0,
+    Suspending = 1,
+    Suspended = 2,
+    Resuming = 3,
+}
+
 /// Umbrella class for the Bluetooth stack.
 pub struct Stack {}