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

Commit 9fc977cf authored by klay_liu's avatar klay_liu Committed by Hsin-chen Chuang
Browse files

Floss: RTL8852 MSFT support



Because RTL8852 supports only one peer for each monitor, it needs a
special handling to make pattern searching via MSFT work.

When a peer device with the matching pattern is scanned, we need to
split that into its own address monitor. At the same time, we also
report device found. This way we can monitor multiple peer devices.
When the address monitor reports device lost, we cancel the address
monitor and reports device lost to the host as well.

Bug: 294961421
Bug: 332438857
Tag: #floss
Test: bluetooth_AdapterAdvMonitor.all_floss
Test: m -j

Change-Id: I2d5679e5395fd04805fc2d83dd73df7b295af7cc
Signed-off-by: default avatarklay_liu <klay_liu@realsil.com.cn>
parent ceca2d93
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -173,3 +173,13 @@ flag {
        purpose: PURPOSE_BUGFIX
    }
}

flag {
    name: "msft_addr_tracking_quirk"
    namespace: "bluetooth"
    description: "Scanning with MSFT paddress tracking for Realtek BT controllers"
    bug: "332438857"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+26 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
#include "hci/msft.h"

#include <android_bluetooth_flags.h>
#include <bluetooth/log.h>
#include <hardware/bt_common_types.h>

@@ -144,6 +145,31 @@ struct MsftExtensionManager::impl {
      return;
    }

    if (IS_FLAG_ENABLED(msft_addr_tracking_quirk)) {
      if (monitor.condition_type != MSFT_CONDITION_TYPE_ADDRESS &&
          monitor.condition_type != MSFT_CONDITION_TYPE_PATTERNS) {
        log::warn("Disallowed as MSFT condition type {} is not supported.", monitor.condition_type);
        return;
      }

      if (monitor.condition_type == MSFT_CONDITION_TYPE_ADDRESS) {
        msft_adv_monitor_add_cb_ = cb;
        Address addr;
        Address::FromString(monitor.addr_info.bd_addr.ToString(), addr);
        hci_layer_->EnqueueCommand(
            MsftLeMonitorAdvConditionAddressBuilder::Create(
                static_cast<OpCode>(msft_.opcode.value()),
                monitor.rssi_threshold_high,
                monitor.rssi_threshold_low,
                monitor.rssi_threshold_low_time_interval,
                monitor.rssi_sampling_period,
                monitor.addr_info.addr_type,
                addr),
            module_handler_->BindOnceOn(this, &impl::on_msft_adv_monitor_add_complete));
        return;
      }
    }

    std::vector<MsftLeMonitorAdvConditionPattern> patterns;
    MsftLeMonitorAdvConditionPattern pattern;
    // The Microsoft Extension specifies 1 octet for the number of patterns.
+239 −13
Original line number Diff line number Diff line
@@ -10,7 +10,7 @@ use bt_topshim::profiles::gatt::{
    GattAdvInbandCallbacksDispatcher, GattClientCallbacks, GattClientCallbacksDispatcher,
    GattScannerCallbacks, GattScannerCallbacksDispatcher, GattScannerInbandCallbacks,
    GattScannerInbandCallbacksDispatcher, GattServerCallbacks, GattServerCallbacksDispatcher,
    GattStatus, LePhy, MsftAdvMonitor, MsftAdvMonitorPattern,
    GattStatus, LePhy, MsftAdvMonitor, MsftAdvMonitorAddress, MsftAdvMonitorPattern,
};
use bt_topshim::sysprop;
use bt_topshim::topstack;
@@ -1241,6 +1241,23 @@ pub struct ScanFilterPattern {
    pub content: Vec<u8>,
}

#[derive(Debug, Clone)]
pub struct ScanFilterAddress {
    pub addr_type: u8,
    pub bd_addr: String,
}

#[derive(Debug, Clone)]
#[repr(u8)]
pub enum ScanFilterConditionType {
    /// [MSFT HCI Extension](https://learn.microsoft.com/en-us/windows-hardware/drivers/bluetooth/microsoft-defined-bluetooth-hci-commands-and-events).
    MsftConditionTypeAll = 0x0,
    MsftConditionTypePatterns = 0x1,
    MsftConditionTypeUuid = 0x2,
    MsftConditionTypeIrkResolution = 0x3,
    MsftConditionTypeAddress = 0x4,
}

/// Represents the condition for matching advertisements.
///
/// Only pattern-based matching is implemented.
@@ -1259,7 +1276,7 @@ pub enum ScanFilterCondition {
    Irk,

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

/// Represents a scan filter to be passed to `IBluetoothGatt::start_scan`.
@@ -1718,6 +1735,84 @@ impl BluetoothGatt {
        self.add_monitor_and_update_scan(scanner_id, filter)
    }

    fn add_child_monitor(&self, scanner_id: u8, scan_filter: ScanFilter) -> BtStatus {
        let gatt_async = self.gatt_async.clone();
        let scanners = self.scanners.clone();
        let is_msft_supported = self.is_msft_supported();

        // Add and enable the monitor filter only when the MSFT extension is supported.
        if !is_msft_supported {
            log::error!("add_child_monitor: MSFT extension is not supported");
            return BtStatus::Fail;
        }
        log::debug!(
            "add_child_monitor: monitoring address, scanner_id={}, filter={:?}",
            scanner_id,
            scan_filter
        );

        tokio::spawn(async move {
            // Add address monitor to track the specified device
            let mut gatt_async = gatt_async.lock().await;

            let monitor_handle = match gatt_async.msft_adv_monitor_add((&scan_filter).into()).await
            {
                Ok((handle, 0)) => handle,
                _ => {
                    log::error!("Error adding advertisement monitor");
                    return;
                }
            };

            if let Some(scanner) =
                Self::find_scanner_by_id(&mut scanners.lock().unwrap(), scanner_id)
            {
                // After hci complete event is received, update the monitor_handle.
                // The address monitor handles are needed in stop_scan().
                let addr_info: MsftAdvMonitorAddress = (&scan_filter.condition).into();

                if scanner.addr_handle_map.contains_key(&addr_info.bd_addr.to_string()) {
                    scanner
                        .addr_handle_map
                        .insert(addr_info.bd_addr.to_string(), Some(monitor_handle));
                    log::debug!(
                        "Added addr monitor {} and updated bd_addr={} to addr filter map",
                        monitor_handle,
                        addr_info.bd_addr.to_string()
                    );
                    return;
                } else {
                    log::debug!("add_child_monitor: bd_addr {} has been removed, removing the addr monitor {}.",
                        addr_info.bd_addr.to_string(),
                        monitor_handle);
                }
            } else {
                log::warn!(
                    "add_child_monitor: scanner has been removed, removing the addr monitor {}",
                    monitor_handle
                );
            }
            let _res = gatt_async.msft_adv_monitor_remove(monitor_handle).await;
        });

        BtStatus::Success
    }

    fn remove_child_monitor(&self, _scanner_id: u8, monitor_handle: u8) -> BtStatus {
        let gatt_async = self.gatt_async.clone();
        let is_msft_supported = self.is_msft_supported();
        tokio::spawn(async move {
            let mut gatt_async = gatt_async.lock().await;

            // Remove and disable the monitor only when the MSFT extension is supported.
            if is_msft_supported {
                let _res = gatt_async.msft_adv_monitor_remove(monitor_handle).await;
                log::debug!("Removed addr monitor {}.", monitor_handle);
            }
        });
        BtStatus::Success
    }

    fn add_monitor_and_update_scan(
        &mut self,
        scanner_id: u8,
@@ -1751,11 +1846,10 @@ impl BluetoothGatt {
                    if let Some(scanner) =
                        Self::find_scanner_by_id(&mut scanners.lock().unwrap(), scanner_id)
                    {
                        // The monitor handle is needed in stop_scan().
                        scanner.monitor_handle = Some(monitor_handle);
                    }

                    log::debug!("Added adv monitor handle = {}", monitor_handle);
                    log::debug!("Added adv pattern monitor handle = {}", monitor_handle);
                }

                let has_enabled_unfiltered_scanner = scanners
@@ -1898,6 +1992,7 @@ pub enum GattWriteRequestStatus {
}

// This structure keeps track of the lifecycle of a scanner.
#[derive(Debug)]
struct ScannerInfo {
    // The callback to which events about this scanner needs to be sent to.
    // Another purpose of keeping track of the callback id is that when a callback is disconnected
@@ -1916,6 +2011,10 @@ struct ScannerInfo {
    is_suspended: bool,
    // The scan parameters to use
    scan_settings: Option<ScanSettings>,
    // Whether the MSFT extension monitor tracking by address filter quirk will be used.
    addr_tracking_quirk: bool,
    // Stores all the monitored handles for pattern and address.
    addr_handle_map: HashMap<String, Option<u8>>,
}

impl ScannerInfo {
@@ -1928,6 +2027,8 @@ impl ScannerInfo {
            monitor_handle: None,
            is_suspended: false,
            scan_settings: None,
            addr_tracking_quirk: sysprop::get_bool(sysprop::PropertyBool::LeAdvMonRtlQuirk),
            addr_handle_map: HashMap::new(),
        }
    }
}
@@ -1953,14 +2054,47 @@ impl Into<Vec<MsftAdvMonitorPattern>> for &ScanFilterCondition {
    }
}

impl Into<MsftAdvMonitorAddress> for &ScanFilterAddress {
    fn into(self) -> MsftAdvMonitorAddress {
        MsftAdvMonitorAddress {
            addr_type: self.addr_type,
            bd_addr: RawAddress::from_string(self.bd_addr.clone()).unwrap(),
        }
    }
}

impl Into<MsftAdvMonitorAddress> for &ScanFilterCondition {
    fn into(self) -> MsftAdvMonitorAddress {
        let addr: RawAddress = RawAddress::empty();
        match self {
            ScanFilterCondition::BluetoothAddress(addr_info) => MsftAdvMonitorAddress {
                addr_type: addr_info.addr_type,
                bd_addr: RawAddress::from_string(addr_info.bd_addr.clone()).unwrap(),
            },
            _ => MsftAdvMonitorAddress { addr_type: 0, bd_addr: addr },
        }
    }
}

impl Into<MsftAdvMonitor> for &ScanFilter {
    fn into(self) -> MsftAdvMonitor {
        let scan_filter_condition_type = match self.condition {
            ScanFilterCondition::Patterns(_) => {
                ScanFilterConditionType::MsftConditionTypePatterns as u8
            }
            ScanFilterCondition::BluetoothAddress(_) => {
                ScanFilterConditionType::MsftConditionTypeAddress as u8
            }
            _ => ScanFilterConditionType::MsftConditionTypeAll as u8,
        };
        MsftAdvMonitor {
            rssi_high_threshold: self.rssi_high_threshold.try_into().unwrap(),
            rssi_low_threshold: self.rssi_low_threshold.try_into().unwrap(),
            rssi_low_timeout: self.rssi_low_timeout.try_into().unwrap(),
            rssi_sampling_period: self.rssi_sampling_period.try_into().unwrap(),
            condition_type: scan_filter_condition_type,
            patterns: (&self.condition).into(),
            addr_info: (&self.condition).into(),
        }
    }
}
@@ -2074,12 +2208,23 @@ impl IBluetoothGatt for BluetoothGatt {
            return BtStatus::Busy;
        }

        let monitor_handle = {
        let monitor_handles = {
            let mut scanners_lock = self.scanners.lock().unwrap();

            if let Some(scanner) = Self::find_scanner_by_id(&mut scanners_lock, scanner_id) {
                scanner.is_enabled = false;
                scanner.monitor_handle
                let mut handles: Vec<u8> = vec![];

                if let Some(handle) = scanner.monitor_handle.take() {
                    handles.push(handle);
                }

                for (_addr, handle) in scanner.addr_handle_map.drain() {
                    if let Some(h) = handle {
                        handles.push(h);
                    }
                }
                handles
            } else {
                log::warn!("Scanner {} not found", scanner_id);
                // Clients can assume success of the removal since the scanner does not exist.
@@ -2099,7 +2244,7 @@ impl IBluetoothGatt for BluetoothGatt {

            // Remove and disable the monitor only when the MSFT extension is supported.
            if is_msft_supported {
                if let Some(handle) = monitor_handle {
                for handle in monitor_handles {
                    let _res = gatt_async.msft_adv_monitor_remove(handle).await;
                }

@@ -4105,11 +4250,34 @@ impl BtifGattScannerCallbacks for BluetoothGatt {
    }

    fn on_track_adv_found_lost(&mut self, track_adv_info: RustAdvertisingTrackInfo) {
        let scanner_id = match self.scanners.lock().unwrap().values().find_map(|scanner| {
            scanner.monitor_handle.and_then(|handle| {
                (handle == track_adv_info.monitor_handle).then(|| scanner.scanner_id).flatten()
            })
        }) {
        let addr = track_adv_info.advertiser_address.to_string();
        let mut binding = self.scanners.lock().unwrap();
        let mut corresponding_scanner: Option<&mut ScannerInfo> =
            binding.values_mut().find_map(|scanner| {
                if scanner.monitor_handle == Some(track_adv_info.monitor_handle) {
                    Some(scanner)
                } else {
                    None
                }
            });
        if corresponding_scanner.is_none() {
            corresponding_scanner = binding.values_mut().find_map(|scanner| {
                if scanner.addr_handle_map.contains_key(&addr) {
                    Some(scanner)
                } else {
                    None
                }
            });
        }

        let corresponding_scanner = match corresponding_scanner {
            Some(scanner) => scanner,
            None => {
                log::warn!("No scanner having monitor handle {}", track_adv_info.monitor_handle);
                return;
            }
        };
        let scanner_id = match corresponding_scanner.scanner_id {
            Some(scanner_id) => scanner_id,
            None => {
                log::warn!("No scanner id having monitor handle {}", track_adv_info.monitor_handle);
@@ -4117,6 +4285,62 @@ impl BtifGattScannerCallbacks for BluetoothGatt {
            }
        };

        let controller_need_separate_pattern_and_address =
            corresponding_scanner.addr_tracking_quirk;

        let mut address_monitor_succeed: bool = false;
        if controller_need_separate_pattern_and_address {
            if track_adv_info.advertiser_state == 0x01 {
                if corresponding_scanner.addr_handle_map.contains_key(&addr) {
                    log::debug!(
                        "on_track_adv_found_lost: this addr {} is already handled, just return",
                        track_adv_info.advertiser_address.to_string()
                    );
                    return;
                }
                log::debug!(
                    "on_track_adv_found_lost: state == 0x01, adding addr {} to map",
                    addr.clone()
                );
                corresponding_scanner.addr_handle_map.insert(addr.clone(), None);

                let scan_filter_addr = ScanFilterAddress {
                    addr_type: track_adv_info.advertiser_address_type,
                    bd_addr: track_adv_info.advertiser_address.to_string(),
                };

                if let Some(saved_filter) = corresponding_scanner.filter.clone() {
                    let scan_filter = ScanFilter {
                        rssi_high_threshold: saved_filter.rssi_high_threshold,
                        rssi_low_threshold: saved_filter.rssi_low_threshold,
                        rssi_low_timeout: saved_filter.rssi_low_timeout,
                        rssi_sampling_period: saved_filter.rssi_sampling_period,
                        condition: ScanFilterCondition::BluetoothAddress(scan_filter_addr),
                    };
                    self.add_child_monitor(scanner_id, scan_filter);
                    address_monitor_succeed = true;
                }
            } else {
                if let Some(handle) = corresponding_scanner.monitor_handle {
                    if handle == track_adv_info.monitor_handle {
                        log::info!(
                            "pattern filter lost, addr={}",
                            track_adv_info.advertiser_address.to_string()
                        );
                        return;
                    }
                }

                if corresponding_scanner.addr_handle_map.remove(&addr).is_some() {
                    log::debug!(
                        "on_track_adv_found_lost: removing addr = {} from map",
                        addr.clone()
                    );
                    self.remove_child_monitor(scanner_id, track_adv_info.monitor_handle);
                }
            }
        }

        self.scanner_callbacks.for_all_callbacks(|callback| {
            let adv_data =
                [&track_adv_info.adv_packet[..], &track_adv_info.scan_response[..]].concat();
@@ -4142,7 +4366,9 @@ impl BtifGattScannerCallbacks for BluetoothGatt {
            };

            if track_adv_info.advertiser_state == 0x01 {
                if !controller_need_separate_pattern_and_address || address_monitor_succeed {
                    callback.on_advertisement_found(scanner_id, scan_result);
                }
            } else {
                callback.on_advertisement_lost(scanner_id, scan_result);
            }
+9 −0
Original line number Diff line number Diff line
@@ -109,13 +109,22 @@ std::vector<MsftAdvMonitorPattern> ConvertAdvMonitorPatterns(const ::rust::Vec<R
  return converted;
}

MsftAdvMonitorAddress ConvertAdvMonitorAddress(RustMsftAdvMonitorAddress rust_addr_info) {
  MsftAdvMonitorAddress addr_info;
  addr_info.addr_type = rust_addr_info.addr_type;
  addr_info.bd_addr = rust_addr_info.bd_addr;
  return addr_info;
}

MsftAdvMonitor ConvertAdvMonitor(const RustMsftAdvMonitor& monitor) {
  MsftAdvMonitor converted = {
      .rssi_threshold_high = monitor.rssi_high_threshold,
      .rssi_threshold_low = monitor.rssi_low_threshold,
      .rssi_threshold_low_time_interval = monitor.rssi_low_timeout,
      .rssi_sampling_period = monitor.rssi_sampling_period,
      .condition_type = monitor.condition_type,
      .patterns = ConvertAdvMonitorPatterns(monitor.patterns),
      .addr_info = ConvertAdvMonitorAddress(monitor.addr_info),
  };
  return converted;
}
+10 −0
Original line number Diff line number Diff line
@@ -99,6 +99,12 @@ pub mod ffi {
        pub pattern: Vec<u8>,
    }

    #[derive(Debug, Clone)]
    pub struct RustMsftAdvMonitorAddress {
        pub addr_type: u8,
        pub bd_addr: RawAddress,
    }

    // Defined in C++ and needs a translation in shim.
    #[derive(Debug, Clone)]
    pub struct RustMsftAdvMonitor {
@@ -106,7 +112,9 @@ pub mod ffi {
        pub rssi_low_threshold: u8,
        pub rssi_low_timeout: u8,
        pub rssi_sampling_period: u8,
        pub condition_type: u8,
        pub patterns: Vec<RustMsftAdvMonitorPattern>,
        pub addr_info: RustMsftAdvMonitorAddress,
    }

    #[derive(Debug, Clone)]
@@ -430,6 +438,8 @@ pub type GattFilterParam = ffi::RustGattFilterParam;
pub type ApcfCommand = ffi::RustApcfCommand;
pub type MsftAdvMonitor = ffi::RustMsftAdvMonitor;
pub type MsftAdvMonitorPattern = ffi::RustMsftAdvMonitorPattern;
pub type MsftAdvMonitorAddress = ffi::RustMsftAdvMonitorAddress;

pub type AdvertiseParameters = ffi::RustAdvertiseParameters;
pub type PeriodicAdvertisingParameters = ffi::RustPeriodicAdvertisingParameters;

Loading