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

Commit e94f76ab authored by Henri Chataing's avatar Henri Chataing Committed by Gerrit Code Review
Browse files

Merge "RootCanal: Implement LE advertising timeouts"

parents f13ebc72 9957e0f7
Loading
Loading
Loading
Loading
+0 −40
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <cstdint>

namespace test_vendor_lib {

class LeAdvertisement {
 public:
  enum class AdvertisementType : uint8_t {
    ADV_IND = 0,          // Connectable and scannable
    ADV_DIRECT_IND = 1,   // Connectable directed
    ADV_SCAN_IND = 2,     // Scannable undirected
    ADV_NONCONN_IND = 3,  // Non connectable undirected
    SCAN_RESPONSE = 4,
  };
  enum class AddressType : uint8_t {
    PUBLIC = 0,
    RANDOM = 1,
    PUBLIC_IDENTITY = 2,
    RANDOM_IDENTITY = 3,
  };
};

}  // namespace test_vendor_lib
+79 −21
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include "le_advertiser.h"

using namespace bluetooth::hci;
using namespace std::literals;

namespace test_vendor_lib {
void LeAdvertiser::Initialize(AddressWithType address,
@@ -37,10 +38,15 @@ void LeAdvertiser::Initialize(AddressWithType address,
}

void LeAdvertiser::InitializeExtended(
    AddressType address_type, AddressWithType peer_address,
    unsigned advertising_handle,
    AddressType address_type,
    AddressWithType peer_address,
    LeScanningFilterPolicy filter_policy,
    model::packets::AdvertisementType type,
    std::chrono::steady_clock::duration interval, uint8_t tx_power) {
    std::chrono::steady_clock::duration interval,
    uint8_t tx_power) {

  advertising_handle_ = advertising_handle;
  address_ = AddressWithType(address_.GetAddress(), address_type);
  peer_address_ = peer_address;
  filter_policy_ = filter_policy;
@@ -59,7 +65,7 @@ void LeAdvertiser::Clear() {
  type_ = model::packets::AdvertisementType::ADV_IND;
  advertisement_.clear();
  scan_response_.clear();
  interval_ = std::chrono::milliseconds(0);
  interval_ = 0ms;
  enabled_ = false;
}

@@ -79,30 +85,55 @@ void LeAdvertiser::SetScanResponse(const std::vector<uint8_t>& data) {
}

void LeAdvertiser::Enable() {
  EnableExtended(0ms);
  extended_ = false;
}

void LeAdvertiser::EnableExtended(std::chrono::milliseconds duration_ms) {
  enabled_ = true;
  last_le_advertisement_ = std::chrono::steady_clock::now() - interval_;
  extended_ = true;
  num_events_ = 0;
  LOG_INFO("%s -> %s type = %hhx ad length %zu, scan length %zu",
           address_.ToString().c_str(), peer_address_.ToString().c_str(), type_,
           advertisement_.size(), scan_response_.size());
}

void LeAdvertiser::EnableExtended(
    std::chrono::steady_clock::duration duration) {
  Enable();
  if (duration != std::chrono::milliseconds(0)) {
    ending_time_ = std::chrono::steady_clock::now() + duration;
  using Duration = std::chrono::steady_clock::duration;
  using TimePoint = std::chrono::steady_clock::time_point;

  Duration adv_direct_ind_timeout = 1280ms; // 1.28s
  Duration adv_direct_ind_interval_low = 10000us; // 10ms
  Duration adv_direct_ind_interval_high = 3750us; // 3.75ms
  Duration duration = duration_ms;
  TimePoint now = std::chrono::steady_clock::now();

  switch (type_) {
  // [Vol 6] Part B. 4.4.2.4.3 High duty cycle connectable directed advertising
  case model::packets::AdvertisementType::ADV_DIRECT_IND:
    duration = duration == 0ms ?
      adv_direct_ind_timeout :
      std::min(duration, adv_direct_ind_timeout);
    interval_ = adv_direct_ind_interval_high;
    break;

  // [Vol 6] Part B. 4.4.2.4.2 Low duty cycle connectable directed advertising
  case model::packets::AdvertisementType::SCAN_RESPONSE:
    interval_ = adv_direct_ind_interval_low;
    break;

  // Duration set to parameter,
  // interval set by Initialize().
  default:
    break;
  }
  extended_ = true;

  last_le_advertisement_ = now - interval_;
  ending_time_ = now + duration;
  limited_ = duration != 0ms;

  LOG_INFO("%s -> %s type = %hhx ad length %zu, scan length %zu",
           address_.ToString().c_str(), peer_address_.ToString().c_str(), type_,
           advertisement_.size(), scan_response_.size());
}

void LeAdvertiser::Disable() { enabled_ = false; }

bool LeAdvertiser::IsEnabled() const { return enabled_; }

bool LeAdvertiser::IsExtended() const { return extended_; }

bool LeAdvertiser::IsConnectable() const {
@@ -112,18 +143,45 @@ bool LeAdvertiser::IsConnectable() const {

uint8_t LeAdvertiser::GetNumAdvertisingEvents() const { return num_events_; }

std::unique_ptr<model::packets::LinkLayerPacketBuilder>
LeAdvertiser::GetAdvertisement(std::chrono::steady_clock::time_point now) {
std::unique_ptr<bluetooth::hci::EventBuilder>
LeAdvertiser::GetEvent(std::chrono::steady_clock::time_point now) {
  // Advertiser disabled.
  if (!enabled_) {
    return nullptr;
  }

  if (now - last_le_advertisement_ < interval_) {
    return nullptr;
  // [Vol 4] Part E 7.8.9   LE Set Advertising Enable command
  // [Vol 4] Part E 7.8.56  LE Set Extended Advertising Enable command
  if (type_ == model::packets::AdvertisementType::ADV_DIRECT_IND &&
      now >= ending_time_ && limited_) {
    LOG_INFO("Directed Advertising Timeout");
    enabled_ = false;
    return bluetooth::hci::LeConnectionCompleteBuilder::Create(
        ErrorCode::ADVERTISING_TIMEOUT, 0,
        bluetooth::hci::Role::CENTRAL,
        bluetooth::hci::AddressType::PUBLIC_DEVICE_ADDRESS,
        bluetooth::hci::Address(), 0, 0, 0,
        bluetooth::hci::ClockAccuracy::PPM_500);
  }

  if (last_le_advertisement_ < ending_time_ && ending_time_ < now) {
  // [Vol 4] Part E 7.8.56  LE Set Extended Advertising Enable command
  if (extended_ && now >= ending_time_ && limited_) {
    LOG_INFO("Extended Advertising Timeout");
    enabled_ = false;
    return bluetooth::hci::LeAdvertisingSetTerminatedBuilder::Create(
        ErrorCode::SUCCESS, advertising_handle_, 0, num_events_);
  }

  return nullptr;
}

std::unique_ptr<model::packets::LinkLayerPacketBuilder>
LeAdvertiser::GetAdvertisement(std::chrono::steady_clock::time_point now) {
  if (!enabled_) {
    return nullptr;
  }

  if (now - last_le_advertisement_ < interval_) {
    return nullptr;
  }

+13 −10
Original line number Diff line number Diff line
@@ -40,7 +40,8 @@ class LeAdvertiser {
                  const std::vector<uint8_t>& scan_response,
                  std::chrono::steady_clock::duration interval);

  void InitializeExtended(bluetooth::hci::AddressType address_type,
  void InitializeExtended(unsigned advertising_handle,
                          bluetooth::hci::AddressType address_type,
                          bluetooth::hci::AddressWithType peer_address,
                          bluetooth::hci::LeScanningFilterPolicy filter_policy,
                          model::packets::AdvertisementType type,
@@ -53,6 +54,12 @@ class LeAdvertiser {

  void SetScanResponse(const std::vector<uint8_t>& data);

  // Generate LE Connection Complete or LE Extended Advertising Set Terminated
  // events at the end of the advertising period. The advertiser is
  // automatically disabled.
  std::unique_ptr<bluetooth::hci::EventBuilder> GetEvent(
      std::chrono::steady_clock::time_point);

  std::unique_ptr<model::packets::LinkLayerPacketBuilder> GetAdvertisement(
      std::chrono::steady_clock::time_point);

@@ -61,21 +68,15 @@ class LeAdvertiser {
      bluetooth::hci::Address scanner_address);

  void Clear();

  void Disable();

  void Enable();

  void EnableExtended(std::chrono::steady_clock::duration duration);
  void EnableExtended(std::chrono::milliseconds duration);

  bool IsEnabled() const;

  bool IsExtended() const;

  bool IsConnectable() const;

  uint8_t GetNumAdvertisingEvents() const;

  bluetooth::hci::AddressWithType GetAddress() const;

private:
@@ -88,12 +89,14 @@ class LeAdvertiser {
  std::vector<uint8_t> scan_response_;
  std::chrono::steady_clock::duration interval_{};
  std::chrono::steady_clock::time_point ending_time_{};
  std::chrono::steady_clock::time_point last_le_advertisement_{};
  static constexpr uint8_t kTxPowerUnavailable = 0x7f;
  uint8_t tx_power_{kTxPowerUnavailable};
  uint8_t num_events_{0};
  bool extended_{false};
  bool enabled_{false};
  std::chrono::steady_clock::time_point last_le_advertisement_;
  bool limited_{false}; // Set if the advertising set has a timeout.
  unsigned advertising_handle_{0};
};

}  // namespace test_vendor_lib
+23 −14
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@
#include <hci/hci_packets.h>

#include "crypto_toolbox/crypto_toolbox.h"
#include "include/le_advertisement.h"
#include "os/log.h"
#include "packet/raw_builder.h"

@@ -32,6 +31,7 @@ using bluetooth::hci::EventCode;

using namespace model::packets;
using model::packets::PacketType;
using namespace std::literals;

namespace test_vendor_lib {

@@ -1834,8 +1834,7 @@ void LinkLayerController::IncomingLeScanResponsePacket(
  ASSERT(scan_response.IsValid());
  vector<uint8_t> ad = scan_response.GetData();
  auto adv_type = scan_response.GetAdvertisementType();
  auto address_type =
      static_cast<LeAdvertisement::AddressType>(scan_response.GetAddressType());
  auto address_type = scan_response.GetAddressType();
  if (le_scan_enable_ == bluetooth::hci::OpCode::LE_SET_SCAN_ENABLE) {
    if (adv_type != model::packets::AdvertisementType::SCAN_RESPONSE) {
      return;
@@ -2088,11 +2087,16 @@ void LinkLayerController::Close() {
void LinkLayerController::LeAdvertising() {
  steady_clock::time_point now = steady_clock::now();
  for (auto& advertiser : advertisers_) {
    auto ad = advertiser.GetAdvertisement(now);
    if (ad == nullptr) {
      continue;

    auto event = advertiser.GetEvent(now);
    if (event != nullptr) {
      send_event_(std::move(event));
    }

    auto advertisement = advertiser.GetAdvertisement(now);
    if (advertisement != nullptr) {
      SendLeLinkLayerPacket(std::move(advertisement));
    }
    SendLeLinkLayerPacket(std::move(ad));
  }
}

@@ -3023,9 +3027,11 @@ ErrorCode LinkLayerController::SetLeExtendedAdvertisingParameters(
      peer = Address::kEmpty;
      break;
    case bluetooth::hci::LegacyAdvertisingProperties::ADV_DIRECT_IND_HIGH:
    case bluetooth::hci::LegacyAdvertisingProperties::ADV_DIRECT_IND_LOW:
      ad_type = model::packets::AdvertisementType::ADV_DIRECT_IND;
      break;
    case bluetooth::hci::LegacyAdvertisingProperties::ADV_DIRECT_IND_LOW:
      ad_type = model::packets::AdvertisementType::SCAN_RESPONSE;
      break;
  }
  auto interval_ms =
      static_cast<int>((interval_max + interval_min) * 0.625 / 2);
@@ -3082,10 +3088,13 @@ ErrorCode LinkLayerController::SetLeExtendedAdvertisingParameters(
      break;
  }

  advertisers_[set].InitializeExtended(
      own_address_address_type, peer_address, scanning_filter_policy, ad_type,
      std::chrono::milliseconds(interval_ms), tx_power);

  advertisers_[set].InitializeExtended(set,
                                       own_address_address_type,
                                       peer_address,
                                       scanning_filter_policy,
                                       ad_type,
                                       std::chrono::milliseconds(interval_ms),
                                       tx_power);
  return ErrorCode::SUCCESS;
}

@@ -3546,6 +3555,7 @@ uint8_t LinkLayerController::LeReadNumberOfSupportedAdvertisingSets() {
ErrorCode LinkLayerController::SetLeExtendedAdvertisingEnable(
    bluetooth::hci::Enable enable,
    const std::vector<bluetooth::hci::EnabledSet>& enabled_sets) {

  for (const auto& set : enabled_sets) {
    if (set.advertising_handle_ > advertisers_.size()) {
      return ErrorCode::INVALID_HCI_COMMAND_PARAMETERS;
@@ -3554,8 +3564,7 @@ ErrorCode LinkLayerController::SetLeExtendedAdvertisingEnable(
  for (const auto& set : enabled_sets) {
    auto handle = set.advertising_handle_;
    if (enable == bluetooth::hci::Enable::ENABLED) {
      advertisers_[handle].EnableExtended(
          std::chrono::milliseconds(10 * set.duration_));
      advertisers_[handle].EnableExtended(10ms * set.duration_);
    } else {
      advertisers_[handle].Disable();
    }
+0 −1
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

#include "loopback.h"

#include "le_advertisement.h"
#include "model/setup/device_boutique.h"
#include "os/log.h"

Loading