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

Commit 6ba96447 authored by Myles Watson's avatar Myles Watson
Browse files

HCI: Add AdvertisingManager tests

Bug: 139080884
Test: bluetooth_test_gd
Change-Id: Ic982c2b5716cf4951b98d21ee3745bf4f6316df4
parent e17a6839
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ filegroup {
        "dual_device_test.cc",
        "hci_layer_test.cc",
        "hci_packets_test.cc",
        "le_advertising_manager_test.cc",
        "le_scanning_manager_test.cc",
    ],
}
+107 −43
Original line number Diff line number Diff line
@@ -30,6 +30,12 @@ namespace hci {

const ModuleFactory LeAdvertisingManager::Factory = ModuleFactory([]() { return new LeAdvertisingManager(); });

enum class AdvertisingApiType {
  LE_4_0 = 1,
  ANDROID_HCI = 2,
  LE_5_0 = 3,
};

struct Advertiser {
  os::Handler* handler;
  common::Callback<void(Address, AddressType)> scan_callback;
@@ -37,14 +43,22 @@ struct Advertiser {
};

struct LeAdvertisingManager::impl {
  impl(Module* module, os::Handler* handler, hci::HciLayer* hci_layer, hci::Controller* controller)
      : registered_handler_(nullptr), module_(module), module_handler_(handler), hci_layer_(hci_layer),
        controller_(controller), le_advertising_interface_(nullptr), num_instances_(0) {}
  impl(Module* module) : module_(module), le_advertising_interface_(nullptr), num_instances_(0) {}

  void start() {
  void start(os::Handler* handler, hci::HciLayer* hci_layer, hci::Controller* controller) {
    module_handler_ = handler;
    hci_layer_ = hci_layer;
    controller_ = controller;
    le_advertising_interface_ = hci_layer_->GetLeAdvertisingInterface(
        common::Bind(&LeAdvertisingManager::impl::handle_event, common::Unretained(this)), module_handler_);
    num_instances_ = controller_->GetControllerLeNumberOfSupportedAdverisingSets();
    if (controller_->IsSupported(hci::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS)) {
      advertising_api_type_ = AdvertisingApiType::LE_5_0;
    } else if (controller_->IsSupported(hci::OpCode::LE_MULTI_ADVT)) {
      advertising_api_type_ = AdvertisingApiType::ANDROID_HCI;
    } else {
      advertising_api_type_ = AdvertisingApiType::LE_4_0;
    }
  }

  size_t GetNumberOfAdvertisingInstances() const {
@@ -87,7 +101,7 @@ struct LeAdvertisingManager::impl {
    AdvertiserId id = 0;
    {
      std::unique_lock lock(id_mutex_);
      while (id < num_instances_ && advertising_sets_.count(id) == 0) {
      while (id < num_instances_ && advertising_sets_.count(id) != 0) {
        id++;
      }
    }
@@ -112,48 +126,72 @@ struct LeAdvertisingManager::impl {
    advertising_sets_[id].scan_callback = scan_callback;
    advertising_sets_[id].set_terminated_callback = set_terminated_callback;
    advertising_sets_[id].handler = handler;
    if (!controller_->IsSupported(hci::OpCode::LE_MULTI_ADVT)) {
    switch (advertising_api_type_) {
      case (AdvertisingApiType::LE_4_0):
        le_advertising_interface_->EnqueueCommand(
          hci::LeSetAdvertisingParametersBuilder::Create(config.interval_min, config.interval_max, config.event_type,
                                                         config.address_type, config.peer_address_type,
                                                         config.peer_address, config.channel_map, config.filter_policy),
          common::BindOnce(impl::check_enable_status), module_handler_);
      le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingDataBuilder::Create(config.advertisement),
                                                common::BindOnce(impl::check_enable_status), module_handler_);
            hci::LeSetAdvertisingParametersBuilder::Create(
                config.interval_min, config.interval_max, config.event_type, config.address_type,
                config.peer_address_type, config.peer_address, config.channel_map, config.filter_policy),
            common::BindOnce(impl::check_status<LeSetAdvertisingParametersCompleteView>), module_handler_);
        le_advertising_interface_->EnqueueCommand(hci::LeSetRandomAddressBuilder::Create(config.random_address),
                                                common::BindOnce(impl::check_enable_status), module_handler_);
                                                  common::BindOnce(impl::check_status<LeSetRandomAddressCompleteView>),
                                                  module_handler_);
        if (!config.scan_response.empty()) {
        le_advertising_interface_->EnqueueCommand(hci::LeSetScanResponseDataBuilder::Create(config.scan_response),
                                                  common::BindOnce(impl::check_enable_status), module_handler_);
      }
      le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingDataBuilder::Create(config.advertisement),
                                                common::BindOnce(impl::check_enable_status), module_handler_);
      return;
          le_advertising_interface_->EnqueueCommand(
              hci::LeSetScanResponseDataBuilder::Create(config.scan_response),
              common::BindOnce(impl::check_status<LeSetScanResponseDataCompleteView>), module_handler_);
        }
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetAdvertisingDataBuilder::Create(config.advertisement),
            common::BindOnce(impl::check_status<LeSetAdvertisingDataCompleteView>), module_handler_);
        le_advertising_interface_->EnqueueCommand(
            hci::LeSetAdvertisingEnableBuilder::Create(Enable::ENABLED),
            common::BindOnce(impl::check_status<LeSetAdvertisingEnableCompleteView>), module_handler_);
        break;
      case (AdvertisingApiType::ANDROID_HCI):
        le_advertising_interface_->EnqueueCommand(
            hci::LeMultiAdvtParamBuilder::Create(config.interval_min, config.interval_max, config.event_type,
                                                 config.address_type, config.peer_address_type, config.peer_address,
                                                 config.channel_map, config.filter_policy, id, config.tx_power),
        common::BindOnce(impl::check_enable_status), module_handler_);
    le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingEnableBuilder::Create(Enable::ENABLED),
                                              common::BindOnce(impl::check_enable_status), module_handler_);
            common::BindOnce(impl::check_status<LeMultiAdvtCompleteView>), module_handler_);
        le_advertising_interface_->EnqueueCommand(hci::LeMultiAdvtSetDataBuilder::Create(config.advertisement, id),
                                                  common::BindOnce(impl::check_status<LeMultiAdvtCompleteView>),
                                                  module_handler_);
        if (!config.scan_response.empty()) {
          le_advertising_interface_->EnqueueCommand(
              hci::LeMultiAdvtSetScanRespBuilder::Create(config.scan_response, id),
              common::BindOnce(impl::check_status<LeMultiAdvtCompleteView>), module_handler_);
        }
        le_advertising_interface_->EnqueueCommand(
            hci::LeMultiAdvtSetRandomAddrBuilder::Create(config.random_address, id),
            common::BindOnce(impl::check_status<LeMultiAdvtCompleteView>), module_handler_);
        le_advertising_interface_->EnqueueCommand(hci::LeMultiAdvtSetEnableBuilder::Create(Enable::ENABLED, id),
                                                  common::BindOnce(impl::check_status<LeMultiAdvtCompleteView>),
                                                  module_handler_);
        break;
      case (AdvertisingApiType::LE_5_0): {
        ExtendedAdvertisingConfig new_config;
        AdvertisingConfig* base_config_ptr = &new_config;
        *(base_config_ptr) = config;
        create_extended_advertiser(id, new_config, scan_callback, set_terminated_callback, handler);
      } break;
    }
  }

  void create_extended_advertiser(AdvertiserId id, const ExtendedAdvertisingConfig& config,
                                  const common::Callback<void(Address, AddressType)>& scan_callback,
                                  const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback,
                                  os::Handler* handler) {
    if (!controller_->IsSupported(hci::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS)) {
    if (advertising_api_type_ != AdvertisingApiType::LE_5_0) {
      create_advertiser(id, config, scan_callback, set_terminated_callback, handler);
      return;
    } else {
      LOG_ALWAYS_FATAL("LE_SET_EXTENDED_ADVERTISING_PARAMETERS isn't implemented.");
    }
    LOG_ALWAYS_FATAL("LE_SET_EXTENDED_ADVERTISING_PARAMETERS isn't implemented.");

    /*
    le_advertising_interface_->EnqueueCommand(hci::LeSetExtendedAdvertisingParametersBuilder::Create(config.interval_min,
    config.interval_max, config.event_type, config.address_type, config.peer_address_type, config.peer_address,
    config.channel_map, config.filter_policy, id, config.tx_power), common::BindOnce(impl::check_enable_status),
    config.channel_map, config.filter_policy, id, config.tx_power), common::BindOnce(impl::check_status),
    module_handler_);
     */
    advertising_sets_[id].scan_callback = scan_callback;
@@ -167,14 +205,15 @@ struct LeAdvertisingManager::impl {
      return;
    }
    le_advertising_interface_->EnqueueCommand(hci::LeSetAdvertisingEnableBuilder::Create(Enable::DISABLED),
                                              common::BindOnce(impl::check_enable_status), module_handler_);
                                              common::BindOnce(impl::check_status<LeSetAdvertisingEnableCompleteView>),
                                              module_handler_);
    std::unique_lock lock(id_mutex_);
    advertising_sets_.erase(advertising_set);
  }

  common::Callback<void(Address, AddressType)> scan_callback_;
  common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback_;
  os::Handler* registered_handler_;
  os::Handler* registered_handler_{nullptr};
  Module* module_;
  os::Handler* module_handler_;
  hci::HciLayer* hci_layer_;
@@ -185,21 +224,21 @@ struct LeAdvertisingManager::impl {
  std::mutex id_mutex_;
  size_t num_instances_;

  static void check_enable_status(CommandCompleteView view) {
  AdvertisingApiType advertising_api_type_{0};

  template <class View>
  static void check_status(CommandCompleteView view) {
    ASSERT(view.IsValid());
    auto status_view = LeSetAdvertisingEnableCompleteView::Create(view);
    auto status_view = View::Create(view);
    ASSERT(status_view.IsValid());
    if (status_view.GetStatus() != ErrorCode::SUCCESS) {
      LOG_INFO("SetEnable returned status %s", ErrorCodeText(status_view.GetStatus()).c_str());
      return;
    }
  }
};

const AdvertiserId LeAdvertisingManager::kInvalidId = -1;

LeAdvertisingManager::LeAdvertisingManager() {
  pimpl_ = std::make_unique<impl>(this, GetHandler(), GetDependency<hci::HciLayer>(), GetDependency<hci::Controller>());
  pimpl_ = std::make_unique<impl>(this);
}

void LeAdvertisingManager::ListDependencies(ModuleList* list) {
@@ -208,7 +247,7 @@ void LeAdvertisingManager::ListDependencies(ModuleList* list) {
}

void LeAdvertisingManager::Start() {
  pimpl_->start();
  pimpl_->start(GetHandler(), GetDependency<hci::HciLayer>(), GetDependency<hci::Controller>());
}

void LeAdvertisingManager::Stop() {
@@ -225,10 +264,12 @@ AdvertiserId LeAdvertisingManager::CreateAdvertiser(
  if (config.peer_address == Address::kEmpty) {
    if (config.address_type == hci::AddressType::PUBLIC_IDENTITY_ADDRESS ||
        config.address_type == hci::AddressType::RANDOM_IDENTITY_ADDRESS) {
      LOG_WARN("Peer address can not be empty");
      return kInvalidId;
    }
    if (config.event_type == hci::AdvertisingEventType::ADV_DIRECT_IND ||
        config.event_type == hci::AdvertisingEventType::ADV_DIRECT_IND_LOW) {
      LOG_WARN("Peer address can not be empty for directed advertising");
      return kInvalidId;
    }
  }
@@ -244,11 +285,34 @@ AdvertiserId LeAdvertisingManager::CreateAdvertiser(
AdvertiserId LeAdvertisingManager::CreateAdvertiser(
    const ExtendedAdvertisingConfig& config, const common::Callback<void(Address, AddressType)>& scan_callback,
    const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback, os::Handler* handler) {
  if (config.directed) {
    if (config.peer_address == Address::kEmpty) {
      LOG_INFO("Peer address can not be empty for directed advertising");
      return kInvalidId;
    }
  }
  if (config.channel_map == 0) {
    LOG_INFO("At least one channel must be set in the map");
    return kInvalidId;
  }
  if (!config.legacy_pdus) {
    if (config.connectable && config.scannable) {
      LOG_INFO("Extended advertising PDUs can not be connectable and scannable");
      return kInvalidId;
    }
    if (config.high_duty_directed_connectable) {
      LOG_INFO("Extended advertising PDUs can not be high duty cycle");
      return kInvalidId;
    }
  }
  if (config.interval_min > config.interval_max) {
    LOG_INFO("Advertising interval: min (%hu) > max (%hu)", config.interval_min, config.interval_max);
    return kInvalidId;
  }
  AdvertiserId id = pimpl_->allocate_advertiser();
  if (id == kInvalidId) {
    return id;
  }
  // Add error checking here
  GetHandler()->Post(common::BindOnce(&impl::create_extended_advertiser, common::Unretained(pimpl_.get()), id, config,
                                      scan_callback, set_terminated_callback, handler));
  return id;
+1 −1
Original line number Diff line number Diff line
@@ -59,7 +59,7 @@ using AdvertiserId = int32_t;

class LeAdvertisingManager : public bluetooth::Module {
 public:
  static const AdvertiserId kInvalidId;
  static constexpr AdvertiserId kInvalidId = -1;
  LeAdvertisingManager();

  size_t GetNumberOfAdvertisingInstances() const;
+356 −0

File added.

Preview size limit exceeded, changes collapsed.