Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8e3ef1e authored by Sonny Sasaka's avatar Sonny Sasaka Committed by Automerger Merge Worker
Browse files

Merge "Floss: Modify ScanFilter API to cater for MSFT filters" am: 73ea9319...

Merge "Floss: Modify ScanFilter API to cater for MSFT filters" am: 73ea9319 am: 52249130 am: 521a23b1 am: b4c280cd

Original change: https://android-review.googlesource.com/c/platform/packages/modules/Bluetooth/+/2215996



Change-Id: I07c64b3d159f80be3ee9e217907290e60a835eb4
Signed-off-by: default avatarAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
parents 91c2de59 b4c280cd
Loading
Loading
Loading
Loading
+10 −7
Original line number Diff line number Diff line
@@ -9,7 +9,9 @@ use bt_topshim::btif::{BtConnectionState, BtStatus, BtTransport};
use bt_topshim::profiles::gatt::LePhy;
use btstack::bluetooth::{BluetoothDevice, IBluetooth, IBluetoothQA};
use btstack::bluetooth_adv::{AdvertiseData, AdvertisingSetParameters};
use btstack::bluetooth_gatt::{IBluetoothGatt, RSSISettings, ScanSettings, ScanType};
use btstack::bluetooth_gatt::{
    IBluetoothGatt, ScanFilter, ScanFilterCondition, ScanSettings, ScanType,
};
use btstack::socket_manager::{IBluetoothSocketManager, SocketResult};
use btstack::uuid::{Profile, UuidHelper, UuidWrapper};
use manager_service::iface_bluetooth_manager::IBluetoothManager;
@@ -866,13 +868,14 @@ impl CommandHandler {
                    self.context.lock().unwrap().gatt_dbus.as_mut().unwrap().start_scan(
                        id,
                        // TODO(b/217274432): Construct real settings and filters.
                        ScanSettings {
                            interval: 0,
                            window: 0,
                            rssi_settings: RSSISettings { high_threshold: 0, low_threshold: 0 },
                            scan_type: ScanType::Active,
                        ScanSettings { interval: 0, window: 0, scan_type: ScanType::Active },
                        ScanFilter {
                            condition: ScanFilterCondition::Patterns(vec![]),
                            rssi_low_threshold: 0,
                            rssi_low_timeout: 0,
                            rssi_high_threshold: 0,
                            rssi_sampling_period: 0,
                        },
                        vec![],
                    );
                    self.context.lock().unwrap().active_scanner_ids.insert(id);
                } else {
+94 −10
Original line number Diff line number Diff line
@@ -16,7 +16,8 @@ use btstack::bluetooth_adv::{
use btstack::bluetooth_gatt::{
    BluetoothGattCharacteristic, BluetoothGattDescriptor, BluetoothGattService,
    GattWriteRequestStatus, GattWriteType, IBluetoothGatt, IBluetoothGattCallback,
    IScannerCallback, RSSISettings, ScanFilter, ScanResult, ScanSettings, ScanType,
    IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings,
    ScanType,
};
use btstack::socket_manager::{
    BluetoothServerSocket, BluetoothSocket, CallbackId, IBluetoothSocketManager,
@@ -134,22 +135,105 @@ pub struct BluetoothDeviceDBus {
    name: String,
}

#[dbus_propmap(RSSISettings)]
pub struct RSSISettingsDBus {
    low_threshold: i32,
    high_threshold: i32,
}

#[dbus_propmap(ScanSettings)]
struct ScanSettingsDBus {
    interval: i32,
    window: i32,
    scan_type: ScanType,
    rssi_settings: RSSISettings,
}

#[dbus_propmap(ScanFilterPattern)]
struct ScanFilterPatternDBus {
    start_position: u8,
    ad_type: u8,
    content: Vec<u8>,
}

// Manually converts enum variant from/into D-Bus.
//
// The ScanFilterCondition enum variant is represented as a D-Bus dictionary with one and only one
// member which key determines which variant it refers to and the value determines the data.
//
// For example, ScanFilterCondition::Patterns(data: Vec<u8>) is represented as:
//     array [
//        dict entry(
//           string "patterns"
//           variant array [ ... ]
//        )
//     ]
//
// And ScanFilterCondition::All is represented as:
//     array [
//        dict entry(
//           string "all"
//           variant string "unit"
//        )
//     ]
//
// If enum variant is used many times, we should find a way to avoid boilerplate.
impl DBusArg for ScanFilterCondition {
    type DBusType = dbus::arg::PropMap;
    fn from_dbus(
        data: dbus::arg::PropMap,
        _conn: Option<std::sync::Arc<dbus::nonblock::SyncConnection>>,
        _remote: Option<dbus::strings::BusName<'static>>,
        _disconnect_watcher: Option<
            std::sync::Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>,
        >,
    ) -> Result<ScanFilterCondition, Box<dyn std::error::Error>> {
        let variant = match data.get("patterns") {
            Some(variant) => variant,
            None => {
                return Err(Box::new(DBusArgError::new(String::from(format!(
                    "ScanFilterCondition does not contain any enum variant",
                )))));
            }
        };

        match variant.arg_type() {
            dbus::arg::ArgType::Variant => {}
            _ => {
                return Err(Box::new(DBusArgError::new(String::from(format!(
                    "ScanFilterCondition::Patterns must be a variant",
                )))));
            }
        };

        let patterns =
            <<Vec<ScanFilterPattern> as DBusArg>::DBusType as RefArgToRust>::ref_arg_to_rust(
                variant.as_static_inner(0).unwrap(),
                format!("ScanFilterCondition::Patterns"),
            )?;

        let patterns = Vec::<ScanFilterPattern>::from_dbus(patterns, None, None, None)?;
        return Ok(ScanFilterCondition::Patterns(patterns));
    }

    fn to_dbus(
        condition: ScanFilterCondition,
    ) -> Result<dbus::arg::PropMap, Box<dyn std::error::Error>> {
        let mut map: dbus::arg::PropMap = std::collections::HashMap::new();
        match condition {
            ScanFilterCondition::Patterns(patterns) => {
                map.insert(
                    String::from("patterns"),
                    dbus::arg::Variant(Box::new(DBusArg::to_dbus(patterns)?)),
                );
            }
            _ => {}
        }
        return Ok(map);
    }
}

#[dbus_propmap(ScanFilter)]
struct ScanFilterDBus {}
struct ScanFilterDBus {
    rssi_high_threshold: i16,
    rssi_low_threshold: i16,
    rssi_low_timeout: u16,
    rssi_sampling_period: u16,
    condition: ScanFilterCondition,
}

#[dbus_propmap(ScanResult)]
struct ScanResultDBus {
@@ -781,7 +865,7 @@ impl IBluetoothGatt for BluetoothGattDBus {
        &mut self,
        _scanner_id: u8,
        _settings: ScanSettings,
        _filters: Vec<ScanFilter>,
        _filter: ScanFilter,
    ) -> BtStatus {
        dbus_generated!()
    }
+94 −10
Original line number Diff line number Diff line
@@ -7,7 +7,8 @@ use btstack::bluetooth_adv::{
use btstack::bluetooth_gatt::{
    BluetoothGattCharacteristic, BluetoothGattDescriptor, BluetoothGattService,
    GattWriteRequestStatus, GattWriteType, IBluetoothGatt, IBluetoothGattCallback,
    IScannerCallback, RSSISettings, ScanFilter, ScanResult, ScanSettings, ScanType,
    IScannerCallback, ScanFilter, ScanFilterCondition, ScanFilterPattern, ScanResult, ScanSettings,
    ScanType,
};
use btstack::{RPCProxy, SuspendMode};

@@ -200,18 +201,11 @@ pub struct BluetoothGattServiceDBus {
    included_services: Vec<BluetoothGattService>,
}

#[dbus_propmap(RSSISettings)]
pub struct RSSISettingsDBus {
    low_threshold: i32,
    high_threshold: i32,
}

#[dbus_propmap(ScanSettings)]
struct ScanSettingsDBus {
    interval: i32,
    window: i32,
    scan_type: ScanType,
    rssi_settings: RSSISettings,
}

#[dbus_propmap(ScanResult)]
@@ -235,8 +229,98 @@ impl_dbus_arg_enum!(LePhy);
impl_dbus_arg_enum!(ScanType);
impl_dbus_arg_enum!(SuspendMode);

#[dbus_propmap(ScanFilterPattern)]
struct ScanFilterPatternDBus {
    start_position: u8,
    ad_type: u8,
    content: Vec<u8>,
}

// Manually converts enum variant from/into D-Bus.
//
// The ScanFilterCondition enum variant is represented as a D-Bus dictionary with one and only one
// member which key determines which variant it refers to and the value determines the data.
//
// For example, ScanFilterCondition::Patterns(data: Vec<u8>) is represented as:
//     array [
//        dict entry(
//           string "patterns"
//           variant array [ ... ]
//        )
//     ]
//
// And ScanFilterCondition::All is represented as:
//     array [
//        dict entry(
//           string "all"
//           variant string "unit"
//        )
//     ]
//
// If enum variant is used many times, we should find a way to avoid boilerplate.
impl DBusArg for ScanFilterCondition {
    type DBusType = dbus::arg::PropMap;
    fn from_dbus(
        data: dbus::arg::PropMap,
        _conn: Option<std::sync::Arc<dbus::nonblock::SyncConnection>>,
        _remote: Option<dbus::strings::BusName<'static>>,
        _disconnect_watcher: Option<
            std::sync::Arc<std::sync::Mutex<dbus_projection::DisconnectWatcher>>,
        >,
    ) -> Result<ScanFilterCondition, Box<dyn std::error::Error>> {
        let variant = match data.get("patterns") {
            Some(variant) => variant,
            None => {
                return Err(Box::new(DBusArgError::new(String::from(format!(
                    "ScanFilterCondition does not contain any enum variant",
                )))));
            }
        };

        match variant.arg_type() {
            dbus::arg::ArgType::Variant => {}
            _ => {
                return Err(Box::new(DBusArgError::new(String::from(format!(
                    "ScanFilterCondition::Patterns must be a variant",
                )))));
            }
        };

        let patterns =
            <<Vec<ScanFilterPattern> as DBusArg>::DBusType as RefArgToRust>::ref_arg_to_rust(
                variant.as_static_inner(0).unwrap(),
                format!("ScanFilterCondition::Patterns"),
            )?;

        let patterns = Vec::<ScanFilterPattern>::from_dbus(patterns, None, None, None)?;
        return Ok(ScanFilterCondition::Patterns(patterns));
    }

    fn to_dbus(
        condition: ScanFilterCondition,
    ) -> Result<dbus::arg::PropMap, Box<dyn std::error::Error>> {
        let mut map: dbus::arg::PropMap = std::collections::HashMap::new();
        match condition {
            ScanFilterCondition::Patterns(patterns) => {
                map.insert(
                    String::from("patterns"),
                    dbus::arg::Variant(Box::new(DBusArg::to_dbus(patterns)?)),
                );
            }
            _ => {}
        }
        return Ok(map);
    }
}

#[dbus_propmap(ScanFilter)]
struct ScanFilterDBus {}
struct ScanFilterDBus {
    rssi_high_threshold: i16,
    rssi_low_threshold: i16,
    rssi_low_timeout: u16,
    rssi_sampling_period: u16,
    condition: ScanFilterCondition,
}

#[allow(dead_code)]
struct AdvertisingSetCallbackDBus {}
@@ -373,7 +457,7 @@ impl IBluetoothGatt for IBluetoothGattDBus {
        &mut self,
        scanner_id: u8,
        settings: ScanSettings,
        filters: Vec<ScanFilter>,
        filter: ScanFilter,
    ) -> BtStatus {
        dbus_generated!()
    }
+62 −13
Original line number Diff line number Diff line
@@ -203,7 +203,7 @@ pub trait IBluetoothGatt {
        &mut self,
        scanner_id: u8,
        settings: ScanSettings,
        filters: Vec<ScanFilter>,
        filter: ScanFilter,
    ) -> BtStatus;

    /// Deactivate scan of the given scanner id.
@@ -617,21 +617,15 @@ impl Default for ScanType {
    }
}

/// Represents RSSI configurations for hardware offloaded scanning.
// TODO(b/200066804): This is still a placeholder struct, not yet complete.
#[derive(Debug, Default)]
pub struct RSSISettings {
    pub low_threshold: i32,
    pub high_threshold: i32,
}

/// Represents scanning configurations to be passed to `IBluetoothGatt::start_scan`.
///
/// This configuration is general and supported on all Bluetooth hardware, irrelevant of the
/// hardware filter offload (APCF or MSFT).
#[derive(Debug, Default)]
pub struct ScanSettings {
    pub interval: i32,
    pub window: i32,
    pub scan_type: ScanType,
    pub rssi_settings: RSSISettings,
}

/// Represents scan result
@@ -649,9 +643,64 @@ pub struct ScanResult {
    pub adv_data: Vec<u8>,
}

#[derive(Debug)]
pub struct ScanFilterPattern {
    /// Specifies the starting byte position of the pattern immediately following AD Type.
    pub start_position: u8,

    /// Advertising Data type (https://www.bluetooth.com/specifications/assigned-numbers/).
    pub ad_type: u8,

    /// The pattern to be matched for the specified AD Type within the advertisement packet from
    /// the specified starting byte.
    pub content: Vec<u8>,
}

/// Represents the condition for matching advertisements.
///
/// Only pattern-based matching is implemented.
#[derive(Debug)]
pub enum ScanFilterCondition {
    /// All advertisements are matched.
    All,

    /// Match by pattern anywhere in the advertisement data. Multiple patterns are "OR"-ed.
    Patterns(Vec<ScanFilterPattern>),

    /// Match by UUID (not implemented).
    Uuid,

    /// Match if the IRK resolves an advertisement (not implemented).
    Irk,

    /// Match by Bluetooth address (not implemented).
    BluetoothAddress,
}

/// Represents a scan filter to be passed to `IBluetoothGatt::start_scan`.
#[derive(Debug, Default)]
pub struct ScanFilter {}
///
/// This filter is intentionally modelled close to the MSFT hardware offload filter.
/// Reference:
/// https://learn.microsoft.com/en-us/windows-hardware/drivers/bluetooth/microsoft-defined-bluetooth-hci-commands-and-events
#[derive(Debug)]
pub struct ScanFilter {
    /// Advertisements with RSSI above or equal this value is considered "found".
    pub rssi_high_threshold: i16,

    /// Advertisements with RSSI below or equal this value (for a period of rssi_low_timeout) is
    /// considered "lost".
    pub rssi_low_threshold: i16,

    /// The time in seconds over which the RSSI value should be below rssi_low_threshold before
    /// being considered "lost".
    pub rssi_low_timeout: u16,

    /// The sampling interval in milliseconds.
    pub rssi_sampling_period: u16,

    /// The condition to match advertisements with.
    pub condition: ScanFilterCondition,
}

/// Implementation of the GATT API (IBluetoothGatt).
pub struct BluetoothGatt {
@@ -901,7 +950,7 @@ impl IBluetoothGatt for BluetoothGatt {
        &mut self,
        scanner_id: u8,
        _settings: ScanSettings,
        _filters: Vec<ScanFilter>,
        _filter: 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