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

Commit c599487a authored by Zach Johnson's avatar Zach Johnson
Browse files

Add ContextualCallback and start using for hci events

Bound to a handler similar to ContextualOnceCallback,
but can be invoked multiple times.

Test: cert/run --host
Test: fuzz/run --host bluetooth_gd_hci_layer_fuzz_test
Change-Id: I980a3c2851721ba0d6d0f7538dccad64998ac720
parent 5e4ff826
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ class IPostableContext {
template <typename R, typename... Args>
class ContextualOnceCallback;

// A callback bound to an execution context that can be invoked only once.
template <typename R, typename... Args>
class ContextualOnceCallback<R(Args...)> {
 public:
@@ -53,5 +54,31 @@ class ContextualOnceCallback<R(Args...)> {
  IPostableContext* context_;
};

template <typename R, typename... Args>
class ContextualCallback;

// A callback bound to an execution context that can be invoked multiple times.
template <typename R, typename... Args>
class ContextualCallback<R(Args...)> {
 public:
  ContextualCallback(common::Callback<R(Args...)>&& callback, IPostableContext* context)
      : callback_(std::move(callback)), context_(context) {}

  constexpr ContextualCallback() = default;

  ContextualCallback(const ContextualCallback&) = default;
  ContextualCallback& operator=(const ContextualCallback&) = default;
  ContextualCallback(ContextualCallback&&) noexcept = default;
  ContextualCallback& operator=(ContextualCallback&&) noexcept = default;

  void Invoke(Args... args) {
    context_->Post(common::BindOnce(callback_, std::forward<Args>(args)...));
  }

 private:
  common::Callback<R(Args...)> callback_;
  IPostableContext* context_;
};

}  // namespace common
}  // namespace bluetooth
+2 −4
Original line number Diff line number Diff line
@@ -300,11 +300,9 @@ struct AclManager::impl : public security::ISecurityManagerListener {
    hci_queue_end_->RegisterDequeue(
        handler_, common::Bind(&impl::dequeue_and_route_acl_packet_to_connection, common::Unretained(this)));
    acl_connection_interface_ = hci_layer_->GetAclConnectionInterface(
        common::Bind(&impl::on_classic_event, common::Unretained(this)),
        common::Bind(&impl::on_classic_disconnect, common::Unretained(this)), handler_);
        handler_->BindOn(this, &impl::on_classic_event), handler_->BindOn(this, &impl::on_classic_disconnect));
    le_acl_connection_interface_ = hci_layer_->GetLeAclConnectionInterface(
        common::Bind(&impl::on_le_event, common::Unretained(this)),
        common::Bind(&impl::on_le_disconnect, common::Unretained(this)), handler_);
        handler_->BindOn(this, &impl::on_le_event), handler_->BindOn(this, &impl::on_le_disconnect));
    le_initiator_address_ =
        AddressWithType(Address{{0x00, 0x11, 0xFF, 0xFF, 0x33, 0x22}}, AddressType::RANDOM_DEVICE_ADDRESS);
  }
+10 −12
Original line number Diff line number Diff line
@@ -167,8 +167,8 @@ class TestHciLayer : public HciLayer {
    return command;
  }

  void RegisterEventHandler(EventCode event_code, common::Callback<void(EventPacketView)> event_handler,
                            os::Handler* handler) override {
  void RegisterEventHandler(EventCode event_code,
                            common::ContextualCallback<void(EventPacketView)> event_handler) override {
    registered_events_[event_code] = event_handler;
  }

@@ -176,8 +176,8 @@ class TestHciLayer : public HciLayer {
    registered_events_.erase(event_code);
  }

  void RegisterLeEventHandler(SubeventCode subevent_code, common::Callback<void(LeMetaEventView)> event_handler,
                              os::Handler* handler) override {
  void RegisterLeEventHandler(SubeventCode subevent_code,
                              common::ContextualCallback<void(LeMetaEventView)> event_handler) override {
    registered_le_events_[subevent_code] = event_handler;
  }

@@ -191,7 +191,7 @@ class TestHciLayer : public HciLayer {
    ASSERT_TRUE(event.IsValid());
    EventCode event_code = event.GetEventCode();
    ASSERT_TRUE(registered_events_.find(event_code) != registered_events_.end()) << EventCodeText(event_code);
    registered_events_[event_code].Run(event);
    registered_events_[event_code].Invoke(event);
  }

  void IncomingLeMetaEvent(std::unique_ptr<LeMetaEventBuilder> event_builder) {
@@ -201,7 +201,7 @@ class TestHciLayer : public HciLayer {
    EXPECT_TRUE(meta_event_view.IsValid());
    SubeventCode subevent_code = meta_event_view.GetSubeventCode();
    EXPECT_TRUE(registered_le_events_.find(subevent_code) != registered_le_events_.end());
    registered_le_events_[subevent_code].Run(meta_event_view);
    registered_le_events_[subevent_code].Invoke(meta_event_view);
  }

  void IncomingAclData(uint16_t handle) {
@@ -259,15 +259,14 @@ class TestHciLayer : public HciLayer {
  void ListDependencies(ModuleList* list) override {}
  void Start() override {
    RegisterEventHandler(EventCode::COMMAND_COMPLETE,
                         base::Bind(&TestHciLayer::CommandCompleteCallback, common::Unretained(this)), nullptr);
    RegisterEventHandler(EventCode::COMMAND_STATUS,
                         base::Bind(&TestHciLayer::CommandStatusCallback, common::Unretained(this)), nullptr);
                         GetHandler()->BindOn(this, &TestHciLayer::CommandCompleteCallback));
    RegisterEventHandler(EventCode::COMMAND_STATUS, GetHandler()->BindOn(this, &TestHciLayer::CommandStatusCallback));
  }
  void Stop() override {}

 private:
  std::map<EventCode, common::Callback<void(EventPacketView)>> registered_events_;
  std::map<SubeventCode, common::Callback<void(LeMetaEventView)>> registered_le_events_;
  std::map<EventCode, common::ContextualCallback<void(EventPacketView)>> registered_events_;
  std::map<SubeventCode, common::ContextualCallback<void(LeMetaEventView)>> registered_le_events_;
  std::list<common::ContextualOnceCallback<void(CommandCompleteView)>> command_complete_callbacks;
  std::list<common::ContextualOnceCallback<void(CommandStatusView)>> command_status_callbacks;
  BidiQueue<AclPacketView, AclPacketBuilder> acl_queue_{3 /* TODO: Set queue depth */};
@@ -281,7 +280,6 @@ class AclManagerNoCallbacksTest : public ::testing::Test {
 protected:
  void SetUp() override {
    test_hci_layer_ = new TestHciLayer;  // Ownership is transferred to registry
    test_hci_layer_->Start();
    test_controller_ = new TestController;
    fake_registry_.InjectTestModule(&HciLayer::Factory, test_hci_layer_);
    fake_registry_.InjectTestModule(&Controller::Factory, test_controller_);
+2 −3
Original line number Diff line number Diff line
@@ -40,12 +40,11 @@ struct Controller::impl {

  void Start(hci::HciLayer* hci) {
    hci_ = hci;
    Handler* handler = module_.GetHandler();
    hci_->RegisterEventHandler(EventCode::NUMBER_OF_COMPLETED_PACKETS,
                               Bind(&Controller::impl::NumberOfCompletedPackets, common::Unretained(this)),
                               module_.GetHandler());
                               handler->BindOn(this, &Controller::impl::NumberOfCompletedPackets));

    set_event_mask(kDefaultEventMask);
    Handler* handler = module_.GetHandler();
    hci_->EnqueueCommand(ReadLocalNameBuilder::Create(),
                         handler->BindOnceOn(this, &Controller::impl::read_local_name_complete_handler));
    hci_->EnqueueCommand(ReadLocalVersionInformationBuilder::Create(),
+4 −7
Original line number Diff line number Diff line
@@ -198,17 +198,15 @@ class TestHciLayer : public HciLayer {
    on_complete.Invoke(std::move(command_complete));
  }

  void RegisterEventHandler(EventCode event_code, common::Callback<void(EventPacketView)> event_handler,
                            os::Handler* handler) override {
  void RegisterEventHandler(EventCode event_code,
                            common::ContextualCallback<void(EventPacketView)> event_handler) override {
    EXPECT_EQ(event_code, EventCode::NUMBER_OF_COMPLETED_PACKETS) << "Only NUMBER_OF_COMPLETED_PACKETS is needed";
    number_of_completed_packets_callback_ = event_handler;
    client_handler_ = handler;
  }

  void UnregisterEventHandler(EventCode event_code) override {
    EXPECT_EQ(event_code, EventCode::NUMBER_OF_COMPLETED_PACKETS) << "Only NUMBER_OF_COMPLETED_PACKETS is needed";
    number_of_completed_packets_callback_ = {};
    client_handler_ = nullptr;
  }

  void IncomingCredit() {
@@ -224,7 +222,7 @@ class TestHciLayer : public HciLayer {
    auto packet = GetPacketView(std::move(event_builder));
    EventPacketView event = EventPacketView::Create(packet);
    ASSERT(event.IsValid());
    client_handler_->Post(common::BindOnce(number_of_completed_packets_callback_, event));
    number_of_completed_packets_callback_.Invoke(event);
  }

  CommandPacketView GetCommand(OpCode op_code) {
@@ -255,8 +253,7 @@ class TestHciLayer : public HciLayer {
  uint64_t event_mask = 0;

 private:
  common::Callback<void(EventPacketView)> number_of_completed_packets_callback_;
  os::Handler* client_handler_;
  common::ContextualCallback<void(EventPacketView)> number_of_completed_packets_callback_;
  std::queue<CommandPacketView> command_queue_;
  mutable std::mutex mutex_;
  std::condition_variable not_empty_;
Loading