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

Commit e56bc24a authored by Myles Watson's avatar Myles Watson Committed by Gerrit Code Review
Browse files

Merge "rootcanal: Implements filter duplicates feature when scanning"

parents d2189294 52d83462
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -33,7 +33,7 @@ Iterator<little_endian>::Iterator(const std::forward_list<View>& data, size_t of
}

template <bool little_endian>
Iterator<little_endian> Iterator<little_endian>::operator+(int offset) {
Iterator<little_endian> Iterator<little_endian>::operator+(int offset) const {
  auto itr(*this);

  return itr += offset;
@@ -52,14 +52,14 @@ Iterator<little_endian>& Iterator<little_endian>::operator++() {
}

template <bool little_endian>
Iterator<little_endian> Iterator<little_endian>::operator-(int offset) {
Iterator<little_endian> Iterator<little_endian>::operator-(int offset) const {
  auto itr(*this);

  return itr -= offset;
}

template <bool little_endian>
int Iterator<little_endian>::operator-(Iterator<little_endian>& itr) {
int Iterator<little_endian>::operator-(const Iterator<little_endian>& itr) const {
  return index_ - itr.index_;
}

+3 −3
Original line number Diff line number Diff line
@@ -50,12 +50,12 @@ class Iterator : public IteratorTraits {
  virtual ~Iterator() = default;

  // All addition and subtraction operators are unbounded.
  Iterator operator+(int offset);
  Iterator operator+(int offset) const;
  Iterator& operator+=(int offset);
  Iterator& operator++();

  Iterator operator-(int offset);
  int operator-(Iterator& itr);
  Iterator operator-(int offset) const;
  int operator-(const Iterator& itr) const;
  Iterator& operator-=(int offset);
  Iterator& operator--();

+1 −0
Original line number Diff line number Diff line
@@ -143,6 +143,7 @@ cc_test_host {
        "test/controller/le/le_set_extended_advertising_data_test.cc",
        "test/controller/le/le_set_extended_scan_response_data_test.cc",
        "test/controller/le/le_set_extended_advertising_enable_test.cc",
        "test/controller/le/le_scanning_filter_duplicates_test.cc",
    ],
    header_libs: [
        "libbluetooth_headers",
+95 −14
Original line number Diff line number Diff line
@@ -609,6 +609,7 @@ ErrorCode LinkLayerController::LeSetScanEnable(bool enable,

  if (!enable) {
    scanner_.scan_enable = false;
    scanner_.history.clear();
    return ErrorCode::SUCCESS;
  }

@@ -633,7 +634,9 @@ ErrorCode LinkLayerController::LeSetScanEnable(bool enable,
  }

  scanner_.scan_enable = true;
  scanner_.history.clear();
  scanner_.timeout = {};
  scanner_.periodical_timeout = {};
  scanner_.filter_duplicates = filter_duplicates
                                   ? bluetooth::hci::FilterDuplicates::ENABLED
                                   : bluetooth::hci::FilterDuplicates::DISABLED;
@@ -760,6 +763,7 @@ ErrorCode LinkLayerController::LeSetExtendedScanEnable(

  if (!enable) {
    scanner_.scan_enable = false;
    scanner_.history.clear();
    return ErrorCode::SUCCESS;
  }

@@ -780,10 +784,13 @@ ErrorCode LinkLayerController::LeSetExtendedScanEnable(
    return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
  }

  auto duration_ms = std::chrono::milliseconds(10 * duration);
  auto period_ms = std::chrono::milliseconds(1280 * period);

  // If both the Duration and Period parameters are non-zero and the Duration is
  // greater than or equal to the Period, the Controller shall return the
  // error code Invalid HCI Command Parameters (0x12).
  if (period != 0 && duration != 0 && duration >= period) {
  if (period != 0 && duration != 0 && duration_ms >= period_ms) {
    LOG_INFO("the period is greater than or equal to the duration");
    return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
  }
@@ -809,15 +816,22 @@ ErrorCode LinkLayerController::LeSetExtendedScanEnable(
  }

  scanner_.scan_enable = true;
  scanner_.history.clear();
  scanner_.timeout = {};
  scanner_.periodical_timeout = {};
  scanner_.filter_duplicates = filter_duplicates;
  scanner_.duration = slots(duration);
  scanner_.period = slots(period);
  scanner_.duration = duration_ms;
  scanner_.period = period_ms;

  auto now = std::chrono::steady_clock::now();

  // At the end of a single scan (Duration non-zero but Period zero), an
  // HCI_LE_Scan_Timeout event shall be generated.
  if (duration != 0 && period == 0) {
    scanner_.timeout = std::chrono::steady_clock::now() + scanner_.duration;
  if (duration != 0) {
    scanner_.timeout = now + scanner_.duration;
  }
  if (period != 0) {
    scanner_.periodical_timeout = now + scanner_.period;
  }

  return ErrorCode::SUCCESS;
@@ -2728,8 +2742,19 @@ void LinkLayerController::ScanIncomingLeLegacyAdvertisingPdu(
    }
  }

  bool should_send_advertising_report = true;
  if (scanner_.filter_duplicates !=
      bluetooth::hci::FilterDuplicates::DISABLED) {
    if (scanner_.IsPacketInHistory(pdu)) {
      should_send_advertising_report = false;
    } else {
      scanner_.AddPacketToHistory(pdu);
    }
  }

  // Legacy scanning, directed advertising.
  if (LegacyAdvertising() && should_send_directed_advertising_report &&
  if (LegacyAdvertising() && should_send_advertising_report &&
      should_send_directed_advertising_report &&
      IsLeEventUnmasked(SubeventCode::DIRECTED_ADVERTISING_REPORT)) {
    bluetooth::hci::LeDirectedAdvertisingResponse response;
    response.event_type_ =
@@ -2748,7 +2773,8 @@ void LinkLayerController::ScanIncomingLeLegacyAdvertisingPdu(
  }

  // Legacy scanning, un-directed advertising.
  if (LegacyAdvertising() && !should_send_directed_advertising_report &&
  if (LegacyAdvertising() && should_send_advertising_report &&
      !should_send_directed_advertising_report &&
      IsLeEventUnmasked(SubeventCode::ADVERTISING_REPORT)) {
    bluetooth::hci::LeAdvertisingResponseRaw response;
    response.address_type_ = resolved_advertising_address.GetAddressType();
@@ -2779,7 +2805,7 @@ void LinkLayerController::ScanIncomingLeLegacyAdvertisingPdu(
  }

  // Extended scanning.
  if (ExtendedAdvertising() &&
  if (ExtendedAdvertising() && should_send_advertising_report &&
      IsLeEventUnmasked(SubeventCode::EXTENDED_ADVERTISING_REPORT)) {
    bluetooth::hci::LeExtendedAdvertisingResponseRaw response;
    response.connectable_ = connectable_advertising;
@@ -2835,6 +2861,12 @@ void LinkLayerController::ScanIncomingLeLegacyAdvertisingPdu(
        "an LE Scan request is already pending",
        advertising_address.ToString().c_str(),
        advertising_address.GetAddressType());
  } else if (!should_send_advertising_report) {
    LOG_VERB(
        "Not sending LE Scan request to advertising address %s(%hhx) because "
        "the advertising message was filtered",
        advertising_address.ToString().c_str(),
        advertising_address.GetAddressType());
  } else {
    // TODO: apply privacy mode in resolving list.
    // Scan requests with public or random device addresses must be ignored
@@ -3187,7 +3219,18 @@ void LinkLayerController::ScanIncomingLeExtendedAdvertisingPdu(
    }
  }

  if (IsLeEventUnmasked(SubeventCode::EXTENDED_ADVERTISING_REPORT)) {
  bool should_send_advertising_report = true;
  if (scanner_.filter_duplicates !=
      bluetooth::hci::FilterDuplicates::DISABLED) {
    if (scanner_.IsPacketInHistory(pdu)) {
      should_send_advertising_report = false;
    } else {
      scanner_.AddPacketToHistory(pdu);
    }
  }

  if (should_send_advertising_report &&
      IsLeEventUnmasked(SubeventCode::EXTENDED_ADVERTISING_REPORT)) {
    bluetooth::hci::LeExtendedAdvertisingResponseRaw response;
    response.connectable_ = connectable_advertising;
    response.scannable_ = scannable_advertising;
@@ -3242,6 +3285,12 @@ void LinkLayerController::ScanIncomingLeExtendedAdvertisingPdu(
        "an LE Scan request is already pending",
        advertising_address.ToString().c_str(),
        advertising_address.GetAddressType());
  } else if (!should_send_advertising_report) {
    LOG_VERB(
        "Not sending LE Scan request to advertising address %s(%hhx) because "
        "the advertising message was filtered",
        advertising_address.ToString().c_str(),
        advertising_address.GetAddressType());
  } else {
    // TODO: apply privacy mode in resolving list.
    // Scan requests with public or random device addresses must be ignored
@@ -4383,7 +4432,17 @@ void LinkLayerController::IncomingLeScanResponsePacket(

  scanner_.pending_scan_request = {};

  if (LegacyAdvertising() &&
  bool should_send_advertising_report = true;
  if (scanner_.filter_duplicates !=
      bluetooth::hci::FilterDuplicates::DISABLED) {
    if (scanner_.IsPacketInHistory(incoming)) {
      should_send_advertising_report = false;
    } else {
      scanner_.AddPacketToHistory(incoming);
    }
  }

  if (LegacyAdvertising() && should_send_advertising_report &&
      IsLeEventUnmasked(SubeventCode::ADVERTISING_REPORT)) {
    bluetooth::hci::LeAdvertisingResponseRaw response;
    response.event_type_ = bluetooth::hci::AdvertisingEventType::SCAN_RESPONSE;
@@ -4395,7 +4454,7 @@ void LinkLayerController::IncomingLeScanResponsePacket(
        bluetooth::hci::LeAdvertisingReportRawBuilder::Create({response}));
  }

  if (ExtendedAdvertising() &&
  if (ExtendedAdvertising() && should_send_advertising_report &&
      IsLeEventUnmasked(SubeventCode::EXTENDED_ADVERTISING_REPORT)) {
    bluetooth::hci::LeExtendedAdvertisingResponseRaw response;
    response.address_ = resolved_advertising_address.GetAddress();
@@ -4417,6 +4476,10 @@ void LinkLayerController::IncomingLeScanResponsePacket(
}

void LinkLayerController::LeScanning() {
  if (!scanner_.IsEnabled()) {
    return;
  }

  std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();

  // Extended Scanning Timeout
@@ -4425,17 +4488,35 @@ void LinkLayerController::LeScanning() {
  // events with Advertising Timeout error code when the advertising
  // type is ADV_DIRECT_IND and the connection failed to be established.

  if (scanner_.IsEnabled() && scanner_.timeout &&
  if (scanner_.timeout.has_value() &&
      !scanner_.periodical_timeout.has_value() &&
      now >= scanner_.timeout.value()) {
    // At the end of a single scan (Duration non-zero but Period zero),
    // an HCI_LE_Scan_Timeout event shall be generated.
    LOG_INFO("Extended Scan Timeout");
    scanner_.Disable();

    scanner_.scan_enable = false;
    scanner_.history.clear();
    if (IsLeEventUnmasked(SubeventCode::SCAN_TIMEOUT)) {
      send_event_(bluetooth::hci::LeScanTimeoutBuilder::Create());
    }
  }

  // End of duration with scan enabled
  if (scanner_.timeout.has_value() && scanner_.periodical_timeout.has_value() &&
      now >= scanner_.timeout.value()) {
    scanner_.timeout = {};
  }

  // End of period
  if (!scanner_.timeout.has_value() &&
      scanner_.periodical_timeout.has_value() &&
      now >= scanner_.periodical_timeout.value()) {
    if (scanner_.filter_duplicates == FilterDuplicates::RESET_EACH_PERIOD) {
      scanner_.history.clear();
    }
    scanner_.timeout = now + scanner_.duration;
    scanner_.periodical_timeout = now + scanner_.period;
  }
}

#ifndef ROOTCANAL_LMP
+21 −3
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

#pragma once

#include <algorithm>
#include <chrono>
#include <map>
#include <vector>

#include "hci/address.h"
#include "hci/hci_packets.h"
@@ -889,8 +892,8 @@ class LinkLayerController {

  struct Scanner {
    bool scan_enable;
    slots period;
    slots duration;
    std::chrono::steady_clock::duration period;
    std::chrono::steady_clock::duration duration;
    bluetooth::hci::FilterDuplicates filter_duplicates;
    bluetooth::hci::OwnAddressType own_address_type;
    bluetooth::hci::LeScanningFilterPolicy scan_filter_policy;
@@ -911,9 +914,24 @@ class LinkLayerController {

    // Time keeping
    std::optional<std::chrono::steady_clock::time_point> timeout;
    std::optional<std::chrono::steady_clock::time_point> periodical_timeout;

    // Packet History
    std::vector<model::packets::LinkLayerPacketView> history;

    bool IsEnabled() const { return scan_enable; }
    void Disable() { scan_enable = false; }

    bool IsPacketInHistory(model::packets::LinkLayerPacketView packet) const {
      return std::any_of(
          history.begin(), history.end(),
          [packet](model::packets::LinkLayerPacketView const& a) {
            return a.size() == packet.size() &&
                   std::equal(a.begin(), a.end(), packet.begin());
          });
    }
    void AddPacketToHistory(model::packets::LinkLayerPacketView packet) {
      history.push_back(packet);
    }
  };

  // Legacy and extended scanning properties.
Loading