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

Commit 29da2edc authored by Myles Watson's avatar Myles Watson
Browse files

AclManager: Use a shared pointer for the queue

Whether the stack is going down or connections are disconnected
gracefully, clean up the queue.

Bug: 145832107
Test: ./cert/run --host && bluetooth_test_gd
Change-Id: I9b36401df2d675cb2907b8c54cc78e2fc715ac00
parent d783352f
Loading
Loading
Loading
Loading
+7 −7
Original line number Diff line number Diff line
@@ -143,10 +143,10 @@ struct assembler {

struct AclManager::acl_connection {
  acl_connection(AddressWithType address_with_type, os::Handler* handler)
      : queue_(std::make_unique<AclConnection::Queue>(10)),
      : queue_(std::make_shared<AclConnection::Queue>(10)),
        assembler_(address_with_type, queue_->GetDownEnd(), handler), address_with_type_(address_with_type),
        handler_(handler) {}
  std::unique_ptr<AclConnection::Queue> queue_;
  std::shared_ptr<AclConnection::Queue> queue_;
  struct assembler assembler_;
  AddressWithType address_with_type_;
  os::Handler* handler_;
@@ -166,9 +166,9 @@ struct AclManager::acl_connection {

struct AclManager::le_acl_connection {
  le_acl_connection(AddressWithType address_with_type, os::Handler* handler)
      : queue_(std::make_unique<AclConnection::Queue>(10)),
      : queue_(std::make_shared<AclConnection::Queue>(10)),
        assembler_(address_with_type, queue_->GetDownEnd(), handler), handler_(handler) {}
  std::unique_ptr<AclConnection::Queue> queue_;
  std::shared_ptr<AclConnection::Queue> queue_;
  struct assembler assembler_;
  LeConnectionManagementCallbacks* le_connection_management_callbacks_;
  os::Handler* handler_;
@@ -453,7 +453,7 @@ struct AclManager::impl : public security::ISecurityManagerListener {
                                              std::move(connection_proxy)));
    hci_layer_->GetHciHandler()->Post(
        common::BindOnce(&RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_),
                         RoundRobinScheduler::ConnectionType::LE, handle, connection.queue_->GetDownEnd()));
                         RoundRobinScheduler::ConnectionType::LE, handle, connection.queue_));
  }

  void on_le_enhanced_connection_complete(LeMetaEventView packet) {
@@ -482,7 +482,7 @@ struct AclManager::impl : public security::ISecurityManagerListener {
    auto& connection = check_and_get_le_connection(handle);
    hci_layer_->GetHciHandler()->Post(
        common::BindOnce(&RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_),
                         RoundRobinScheduler::ConnectionType::LE, handle, connection.queue_->GetDownEnd()));
                         RoundRobinScheduler::ConnectionType::LE, handle, connection.queue_));
    auto role = connection_complete.GetRole();
    auto do_disconnect = common::BindOnce(&impl::handle_disconnect, common::Unretained(this), handle);
    std::unique_ptr<LeAclConnection> connection_proxy(
@@ -513,7 +513,7 @@ struct AclManager::impl : public security::ISecurityManagerListener {
    auto& connection = check_and_get_connection(handle);
    hci_layer_->GetHciHandler()->Post(common::BindOnce(
        &RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_),
        RoundRobinScheduler::ConnectionType::CLASSIC, handle, check_and_get_connection(handle).queue_->GetDownEnd()));
        RoundRobinScheduler::ConnectionType::CLASSIC, handle, check_and_get_connection(handle).queue_));
    std::unique_ptr<ClassicAclConnection> connection_proxy(
        new ClassicAclConnection(&acl_manager_, connection.queue_->GetUpEnd(), acl_connection_interface_, handle,
                                 address, Role::MASTER /* TODO: Did we connect? */));
+6 −6
Original line number Diff line number Diff line
@@ -40,8 +40,8 @@ RoundRobinScheduler::~RoundRobinScheduler() {
}

void RoundRobinScheduler::Register(ConnectionType connection_type, uint16_t handle,
                                   AclConnection::QueueDownEnd* queue_down_end) {
  acl_queue_handler acl_queue_handler = {connection_type, queue_down_end, false, 0, false};
                                   std::shared_ptr<AclConnection::Queue> queue) {
  acl_queue_handler acl_queue_handler = {connection_type, std::move(queue), false, 0, false};
  acl_queue_handlers_.insert(std::pair<uint16_t, RoundRobinScheduler::acl_queue_handler>(handle, acl_queue_handler));
  if (fragments_to_send_.size() == 0) {
    start_round_robin();
@@ -53,7 +53,7 @@ void RoundRobinScheduler::Unregister(uint16_t handle) {
  auto acl_queue_handler = acl_queue_handlers_.find(handle)->second;
  if (acl_queue_handler.dequeue_is_registered_) {
    acl_queue_handler.dequeue_is_registered_ = false;
    acl_queue_handler.queue_down_end_->UnregisterDequeue();
    acl_queue_handler.queue_->GetDownEnd()->UnregisterDequeue();
  }
  acl_queue_handlers_.erase(handle);
  starting_point_ = acl_queue_handlers_.begin();
@@ -101,7 +101,7 @@ void RoundRobinScheduler::start_round_robin() {
        le_acl_packet_credits_ == 0 && acl_queue_handler->second.connection_type_ == ConnectionType::LE;
    if (!acl_queue_handler->second.dequeue_is_registered_ && !classic_buffer_full && !le_buffer_full) {
      acl_queue_handler->second.dequeue_is_registered_ = true;
      acl_queue_handler->second.queue_down_end_->RegisterDequeue(
      acl_queue_handler->second.queue_->GetDownEnd()->RegisterDequeue(
          handler_, common::Bind(&RoundRobinScheduler::buffer_packet, common::Unretained(this), acl_queue_handler));
    }
    acl_queue_handler = std::next(acl_queue_handler);
@@ -117,7 +117,7 @@ void RoundRobinScheduler::buffer_packet(std::map<uint16_t, acl_queue_handler>::i
  BroadcastFlag broadcast_flag = BroadcastFlag::POINT_TO_POINT;
  // Wrap packet and enqueue it
  uint16_t handle = acl_queue_handler->first;
  auto packet = acl_queue_handler->second.queue_down_end_->TryDequeue();
  auto packet = acl_queue_handler->second.queue_->GetDownEnd()->TryDequeue();
  ASSERT(packet != nullptr);

  ConnectionType connection_type = acl_queue_handler->second.connection_type_;
@@ -148,7 +148,7 @@ void RoundRobinScheduler::unregister_all_connections() {
       acl_queue_handler = std::next(acl_queue_handler)) {
    if (acl_queue_handler->second.dequeue_is_registered_) {
      acl_queue_handler->second.dequeue_is_registered_ = false;
      acl_queue_handler->second.queue_down_end_->UnregisterDequeue();
      acl_queue_handler->second.queue_->GetDownEnd()->UnregisterDequeue();
    }
  }
}
+2 −2
Original line number Diff line number Diff line
@@ -37,13 +37,13 @@ class RoundRobinScheduler {

  struct acl_queue_handler {
    ConnectionType connection_type_;
    AclConnection::QueueDownEnd* queue_down_end_;
    std::shared_ptr<AclConnection::Queue> queue_;
    bool dequeue_is_registered_ = false;
    uint16_t number_of_sent_packets_ = 0;  // Track credits
    bool is_disconnected_ = false;
  };

  void Register(ConnectionType connection_type, uint16_t handle, AclConnection::QueueDownEnd* queue_down_end);
  void Register(ConnectionType connection_type, uint16_t handle, std::shared_ptr<AclConnection::Queue> queue);
  void Unregister(uint16_t handle);
  void SetDisconnect(uint16_t handle);
  uint16_t GetCredits();
+35 −43
Original line number Diff line number Diff line
@@ -15,9 +15,12 @@
 */

#include "hci/round_robin_scheduler.h"

#include <gtest/gtest.h>

#include "common/bidi_queue.h"
#include "common/callback.h"
#include "hci/acl_manager.h"
#include "hci/controller.h"
#include "hci/hci_packets.h"
#include "os/handler.h"
@@ -172,20 +175,18 @@ TEST_F(RoundRobinSchedulerTest, startup_teardown) {}

TEST_F(RoundRobinSchedulerTest, register_unregister_connection) {
  uint16_t handle = 0x01;
  BidiQueue<PacketView<kLittleEndian>, BasePacketBuilder> connection_queue{10};
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue.GetDownEnd());
  auto connection_queue = std::make_shared<AclConnection::Queue>(10);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue);
  round_robin_scheduler_->Unregister(handle);
}

TEST_F(RoundRobinSchedulerTest, buffer_packet) {
  uint16_t handle = 0x01;
  BidiQueue<PacketView<kLittleEndian>, BasePacketBuilder> connection_queue{10};

  AclConnection::QueueDownEnd* queue_down_end = connection_queue.GetDownEnd();
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, queue_down_end);
  auto connection_queue = std::make_shared<AclConnection::Queue>(10);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue);

  SetPacketFuture(2);
  AclConnection::QueueUpEnd* queue_up_end = connection_queue.GetUpEnd();
  AclConnection::QueueUpEnd* queue_up_end = connection_queue->GetUpEnd();
  std::vector<uint8_t> packet1 = {0x01, 0x02, 0x03};
  std::vector<uint8_t> packet2 = {0x04, 0x05, 0x06};
  EnqueueAclUpEnd(queue_up_end, packet1);
@@ -202,17 +203,15 @@ TEST_F(RoundRobinSchedulerTest, buffer_packet) {
TEST_F(RoundRobinSchedulerTest, buffer_packet_from_two_connections) {
  uint16_t handle = 0x01;
  uint16_t le_handle = 0x02;
  BidiQueue<PacketView<kLittleEndian>, BasePacketBuilder> connection_queue{10};
  BidiQueue<PacketView<kLittleEndian>, BasePacketBuilder> le_connection_queue{10};
  auto connection_queue = std::make_shared<AclConnection::Queue>(10);
  auto le_connection_queue = std::make_shared<AclConnection::Queue>(10);

  AclConnection::QueueDownEnd* queue_down_end = connection_queue.GetDownEnd();
  AclConnection::QueueDownEnd* le_queue_down_end = le_connection_queue.GetDownEnd();
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, queue_down_end);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle, le_queue_down_end);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle, le_connection_queue);

  SetPacketFuture(2);
  AclConnection::QueueUpEnd* queue_up_end = connection_queue.GetUpEnd();
  AclConnection::QueueUpEnd* le_queue_up_end = le_connection_queue.GetUpEnd();
  AclConnection::QueueUpEnd* queue_up_end = connection_queue->GetUpEnd();
  AclConnection::QueueUpEnd* le_queue_up_end = le_connection_queue->GetUpEnd();
  std::vector<uint8_t> packet = {0x01, 0x02, 0x03};
  std::vector<uint8_t> le_packet = {0x04, 0x05, 0x06};
  EnqueueAclUpEnd(le_queue_up_end, le_packet);
@@ -230,12 +229,11 @@ TEST_F(RoundRobinSchedulerTest, buffer_packet_from_two_connections) {

TEST_F(RoundRobinSchedulerTest, do_not_register_when_credits_is_zero) {
  uint16_t handle = 0x01;
  BidiQueue<PacketView<kLittleEndian>, BasePacketBuilder> connection_queue{15};
  AclConnection::QueueDownEnd* queue_down_end = connection_queue.GetDownEnd();
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, queue_down_end);
  auto connection_queue = std::make_shared<AclConnection::Queue>(15);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue);

  SetPacketFuture(10);
  AclConnection::QueueUpEnd* queue_up_end = connection_queue.GetUpEnd();
  AclConnection::QueueUpEnd* queue_up_end = connection_queue->GetUpEnd();
  for (uint8_t i = 0; i < 15; i++) {
    std::vector<uint8_t> packet = {0x01, 0x02, 0x03, i};
    EnqueueAclUpEnd(queue_up_end, packet);
@@ -273,25 +271,21 @@ TEST_F(RoundRobinSchedulerTest, buffer_packet_intervally) {
  uint16_t handle2 = 0x02;
  uint16_t le_handle1 = 0x03;
  uint16_t le_handle2 = 0x04;
  BidiQueue<PacketView<kLittleEndian>, BasePacketBuilder> connection_queue1{10};
  BidiQueue<PacketView<kLittleEndian>, BasePacketBuilder> connection_queue2{10};
  BidiQueue<PacketView<kLittleEndian>, BasePacketBuilder> le_connection_queue1{10};
  BidiQueue<PacketView<kLittleEndian>, BasePacketBuilder> le_connection_queue2{10};
  AclConnection::QueueDownEnd* queue_down_end1 = connection_queue1.GetDownEnd();
  AclConnection::QueueDownEnd* queue_down_end2 = connection_queue2.GetDownEnd();
  AclConnection::QueueDownEnd* le_queue_down_end1 = le_connection_queue1.GetDownEnd();
  AclConnection::QueueDownEnd* le_queue_down_end2 = le_connection_queue2.GetDownEnd();
  auto connection_queue1 = std::make_shared<AclConnection::Queue>(10);
  auto connection_queue2 = std::make_shared<AclConnection::Queue>(10);
  auto le_connection_queue1 = std::make_shared<AclConnection::Queue>(10);
  auto le_connection_queue2 = std::make_shared<AclConnection::Queue>(10);

  SetPacketFuture(18);
  AclConnection::QueueUpEnd* queue_up_end1 = connection_queue1.GetUpEnd();
  AclConnection::QueueUpEnd* queue_up_end2 = connection_queue2.GetUpEnd();
  AclConnection::QueueUpEnd* le_queue_up_end1 = le_connection_queue1.GetUpEnd();
  AclConnection::QueueUpEnd* le_queue_up_end2 = le_connection_queue2.GetUpEnd();
  AclConnection::QueueUpEnd* queue_up_end1 = connection_queue1->GetUpEnd();
  AclConnection::QueueUpEnd* queue_up_end2 = connection_queue2->GetUpEnd();
  AclConnection::QueueUpEnd* le_queue_up_end1 = le_connection_queue1->GetUpEnd();
  AclConnection::QueueUpEnd* le_queue_up_end2 = le_connection_queue2->GetUpEnd();

  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle1, queue_down_end1);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle2, queue_down_end2);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle1, le_queue_down_end1);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle2, le_queue_down_end2);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle1, connection_queue1);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle2, connection_queue2);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle1, le_connection_queue1);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle2, le_connection_queue2);

  std::vector<uint8_t> packet = {0x01, 0x02, 0x03};
  EnqueueAclUpEnd(queue_up_end1, packet);
@@ -333,17 +327,15 @@ TEST_F(RoundRobinSchedulerTest, buffer_packet_intervally) {
TEST_F(RoundRobinSchedulerTest, send_fragments_without_interval) {
  uint16_t handle = 0x01;
  uint16_t le_handle = 0x02;
  BidiQueue<PacketView<kLittleEndian>, BasePacketBuilder> connection_queue{10};
  BidiQueue<PacketView<kLittleEndian>, BasePacketBuilder> le_connection_queue{10};
  auto connection_queue = std::make_shared<AclConnection::Queue>(10);
  auto le_connection_queue = std::make_shared<AclConnection::Queue>(10);

  AclConnection::QueueDownEnd* queue_down_end = connection_queue.GetDownEnd();
  AclConnection::QueueDownEnd* le_queue_down_end = le_connection_queue.GetDownEnd();
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, queue_down_end);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle, le_queue_down_end);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue);
  round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle, le_connection_queue);

  SetPacketFuture(5);
  AclConnection::QueueUpEnd* queue_up_end = connection_queue.GetUpEnd();
  AclConnection::QueueUpEnd* le_queue_up_end = le_connection_queue.GetUpEnd();
  AclConnection::QueueUpEnd* queue_up_end = connection_queue->GetUpEnd();
  AclConnection::QueueUpEnd* le_queue_up_end = le_connection_queue->GetUpEnd();
  std::vector<uint8_t> packet(controller_->hci_mtu_, 0xff);
  std::vector<uint8_t> packet_part1(controller_->hci_mtu_, 0xff);
  std::vector<uint8_t> packet_part2 = {0x03, 0x02, 0x01};