Loading system/gd/hci/acl_manager.cc +9 −9 Original line number Diff line number Diff line Loading @@ -314,9 +314,9 @@ struct AclManager::impl : public security::ISecurityManagerListener { acl_connections_.emplace(std::piecewise_construct, std::forward_as_tuple(handle), std::forward_as_tuple(address_with_type, handler_)); auto& connection = check_and_get_connection(handle); hci_layer_->GetHciHandler()->Post(common::BindOnce(&RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_), handle, connection.queue_->GetDownEnd())); hci_layer_->GetHciHandler()->Post( common::BindOnce(&RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_), RoundRobinScheduler::ConnectionType::LE, handle, connection.queue_->GetDownEnd())); auto role = connection_complete.GetRole(); std::unique_ptr<LeAclConnection> connection_proxy(new LeAclConnection( &acl_manager_, connection.queue_->GetUpEnd(), le_acl_connection_interface_, handle, address_with_type, role)); Loading Loading @@ -349,9 +349,9 @@ struct AclManager::impl : public security::ISecurityManagerListener { acl_connections_.emplace(std::piecewise_construct, std::forward_as_tuple(handle), std::forward_as_tuple(reporting_address_with_type, handler_)); auto& connection = check_and_get_connection(handle); hci_layer_->GetHciHandler()->Post(common::BindOnce(&RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_), handle, connection.queue_->GetDownEnd())); hci_layer_->GetHciHandler()->Post( common::BindOnce(&RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_), RoundRobinScheduler::ConnectionType::LE, handle, connection.queue_->GetDownEnd())); auto role = connection_complete.GetRole(); std::unique_ptr<LeAclConnection> connection_proxy(new LeAclConnection(&acl_manager_, connection.queue_->GetUpEnd(), le_acl_connection_interface_, handle, Loading @@ -378,9 +378,9 @@ struct AclManager::impl : public security::ISecurityManagerListener { std::piecewise_construct, std::forward_as_tuple(handle), std::forward_as_tuple(AddressWithType{address, AddressType::PUBLIC_DEVICE_ADDRESS}, handler_)); auto& connection = check_and_get_connection(handle); hci_layer_->GetHciHandler()->Post(common::BindOnce(&RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_), handle, check_and_get_connection(handle).queue_->GetDownEnd())); hci_layer_->GetHciHandler()->Post(common::BindOnce( &RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_), RoundRobinScheduler::ConnectionType::CLASSIC, handle, check_and_get_connection(handle).queue_->GetDownEnd())); std::unique_ptr<ClassicAclConnection> connection_proxy( new ClassicAclConnection(&acl_manager_, connection.queue_->GetUpEnd(), acl_connection_interface_, handle, address, Role::MASTER /* TODO: Did we connect? */)); Loading system/gd/hci/controller.cc +8 −0 Original line number Diff line number Diff line Loading @@ -247,6 +247,14 @@ struct Controller::impl { ErrorCode status = complete_view.GetStatus(); ASSERT_LOG(status == ErrorCode::SUCCESS, "Status 0x%02hhx, %s", status, ErrorCodeText(status).c_str()); le_buffer_size_ = complete_view.GetLeBufferSize(); // If LE buffer size is zero, then buffers returned by Read_Buffer_Size are shared between BR/EDR and LE. if (le_buffer_size_.total_num_le_packets_ == 0) { ASSERT(acl_buffers_ != 0); le_buffer_size_.total_num_le_packets_ = acl_buffers_ / 2; acl_buffers_ -= le_buffer_size_.total_num_le_packets_; le_buffer_size_.le_data_packet_length_ = acl_buffer_length_; } } void le_read_local_supported_features_handler(CommandCompleteView view) { Loading system/gd/hci/round_robin_scheduler.cc +49 −20 Original line number Diff line number Diff line Loading @@ -26,6 +26,10 @@ RoundRobinScheduler::RoundRobinScheduler(os::Handler* handler, Controller* contr max_acl_packet_credits_ = controller_->GetControllerNumAclPacketBuffers(); acl_packet_credits_ = max_acl_packet_credits_; hci_mtu_ = controller_->GetControllerAclPacketLength(); LeBufferSize le_buffer_size = controller_->GetControllerLeBufferSize(); le_max_acl_packet_credits_ = le_buffer_size.total_num_le_packets_; le_acl_packet_credits_ = le_max_acl_packet_credits_; le_hci_mtu_ = le_buffer_size.le_data_packet_length_; controller_->RegisterCompletedAclPacketsCallback( common::Bind(&RoundRobinScheduler::IncomingAclCredits, common::Unretained(this)), handler_); } Loading @@ -35,8 +39,9 @@ RoundRobinScheduler::~RoundRobinScheduler() { controller_->UnregisterCompletedAclPacketsCallback(); } void RoundRobinScheduler::Register(uint16_t handle, AclConnection::QueueDownEnd* queue_down_end) { acl_queue_handler acl_queue_handler = {queue_down_end, false, 0, false}; 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}; acl_queue_handlers_.insert(std::pair<uint16_t, RoundRobinScheduler::acl_queue_handler>(handle, acl_queue_handler)); if (fragments_to_send_.size() == 0) { StartRoundRobin(); Loading @@ -58,12 +63,16 @@ void RoundRobinScheduler::SetDisconnect(uint16_t handle) { auto acl_queue_handler = acl_queue_handlers_.find(handle)->second; acl_queue_handler.is_disconnected_ = true; // Reclaim outstanding packets if (acl_queue_handler.connection_type_ == ConnectionType::CLASSIC) { acl_packet_credits_ += acl_queue_handler.number_of_sent_packets_; } else { le_acl_packet_credits_ += acl_queue_handler.number_of_sent_packets_; } acl_queue_handler.number_of_sent_packets_ = 0; } void RoundRobinScheduler::StartRoundRobin() { if (acl_packet_credits_ == 0) { if (acl_packet_credits_ == 0 && le_acl_packet_credits_ == 0) { return; } if (!fragments_to_send_.empty()) { Loading Loading @@ -98,15 +107,19 @@ void RoundRobinScheduler::BufferPacket(std::map<uint16_t, acl_queue_handler>::it auto packet = acl_queue_handler->second.queue_down_end_->TryDequeue(); ASSERT(packet != nullptr); if (packet->size() <= hci_mtu_) { fragments_to_send_.push(AclPacketBuilder::Create(handle, PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE, broadcast_flag, std::move(packet))); ConnectionType connection_type = acl_queue_handler->second.connection_type_; size_t mtu = connection_type == ConnectionType::CLASSIC ? hci_mtu_ : le_hci_mtu_; if (packet->size() <= mtu) { fragments_to_send_.push(std::make_pair( connection_type, AclPacketBuilder::Create(handle, PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE, broadcast_flag, std::move(packet)))); } else { auto fragments = AclFragmenter(hci_mtu_, std::move(packet)).GetFragments(); auto fragments = AclFragmenter(mtu, std::move(packet)).GetFragments(); PacketBoundaryFlag packet_boundary_flag = PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE; for (size_t i = 0; i < fragments.size(); i++) { fragments_to_send_.push( AclPacketBuilder::Create(handle, packet_boundary_flag, broadcast_flag, std::move(fragments[i]))); fragments_to_send_.push(std::make_pair( connection_type, AclPacketBuilder::Create(handle, packet_boundary_flag, broadcast_flag, std::move(fragments[i])))); packet_boundary_flag = PacketBoundaryFlag::CONTINUING_FRAGMENT; } } Loading Loading @@ -136,18 +149,29 @@ void RoundRobinScheduler::SendNextFragment() { // Invoked from some external Queue Reactable context 1 std::unique_ptr<AclPacketBuilder> RoundRobinScheduler::HandleEnqueueNextFragment() { ConnectionType connection_type = fragments_to_send_.front().first; if (connection_type == ConnectionType::CLASSIC) { ASSERT(acl_packet_credits_ > 0); if (acl_packet_credits_ == 1 || fragments_to_send_.size() == 1) { if (enqueue_registered_.exchange(false)) { hci_queue_end_->UnregisterEnqueue(); } } ASSERT(fragments_to_send_.size() > 0); auto raw_pointer = fragments_to_send_.front().release(); acl_packet_credits_ -= 1; } else { ASSERT(le_acl_packet_credits_ > 0); le_acl_packet_credits_ -= 1; } auto raw_pointer = fragments_to_send_.front().second.release(); fragments_to_send_.pop(); if (fragments_to_send_.empty()) { if (enqueue_registered_.exchange(false)) { hci_queue_end_->UnregisterEnqueue(); } handler_->Post(common::BindOnce(&RoundRobinScheduler::StartRoundRobin, common::Unretained(this))); } else { ConnectionType next_connection_type = fragments_to_send_.front().first; bool classic_buffer_full = next_connection_type == ConnectionType::CLASSIC && acl_packet_credits_ == 0; bool le_buffer_full = next_connection_type == ConnectionType::LE && le_acl_packet_credits_ == 0; if ((classic_buffer_full || le_buffer_full) && enqueue_registered_.exchange(false)) { hci_queue_end_->UnregisterEnqueue(); } } return std::unique_ptr<AclPacketBuilder>(raw_pointer); } Loading @@ -163,9 +187,14 @@ void RoundRobinScheduler::IncomingAclCredits(uint16_t handle, uint16_t credits) return; } acl_queue_handler->second.number_of_sent_packets_ -= credits; if (acl_queue_handler->second.connection_type_ == ConnectionType::CLASSIC) { acl_packet_credits_ += credits; } else { le_acl_packet_credits_ += credits; } ASSERT(acl_packet_credits_ <= max_acl_packet_credits_); if (acl_packet_credits_ == credits) { ASSERT(le_acl_packet_credits_ <= le_max_acl_packet_credits_); if (acl_packet_credits_ == credits || le_acl_packet_credits_ == credits) { StartRoundRobin(); } } Loading system/gd/hci/round_robin_scheduler.h +8 −2 Original line number Diff line number Diff line Loading @@ -33,14 +33,17 @@ class RoundRobinScheduler { common::BidiQueueEnd<AclPacketBuilder, AclPacketView>* hci_queue_end); ~RoundRobinScheduler(); enum ConnectionType { CLASSIC, LE }; struct acl_queue_handler { ConnectionType connection_type_; AclConnection::QueueDownEnd* queue_down_end_; bool dequeue_is_registered_ = false; uint16_t number_of_sent_packets_ = 0; // Track credits bool is_disconnected_ = false; }; void Register(uint16_t handle, AclConnection::QueueDownEnd* queue_down_end); void Register(ConnectionType connection_type, uint16_t handle, AclConnection::QueueDownEnd* queue_down_end); void Unregister(uint16_t handle); void SetDisconnect(uint16_t handle); Loading @@ -55,10 +58,13 @@ class RoundRobinScheduler { os::Handler* handler_ = nullptr; Controller* controller_ = nullptr; std::map<uint16_t, acl_queue_handler> acl_queue_handlers_; std::queue<std::unique_ptr<AclPacketBuilder>> fragments_to_send_; std::queue<std::pair<ConnectionType, std::unique_ptr<AclPacketBuilder>>> fragments_to_send_; uint16_t max_acl_packet_credits_ = 0; uint16_t acl_packet_credits_ = 0; uint16_t le_max_acl_packet_credits_ = 0; uint16_t le_acl_packet_credits_ = 0; size_t hci_mtu_{0}; size_t le_hci_mtu_{0}; std::atomic_bool enqueue_registered_ = false; common::BidiQueueEnd<AclPacketBuilder, AclPacketView>* hci_queue_end_ = nullptr; // first register queue end for the Round-robin schedule Loading Loading
system/gd/hci/acl_manager.cc +9 −9 Original line number Diff line number Diff line Loading @@ -314,9 +314,9 @@ struct AclManager::impl : public security::ISecurityManagerListener { acl_connections_.emplace(std::piecewise_construct, std::forward_as_tuple(handle), std::forward_as_tuple(address_with_type, handler_)); auto& connection = check_and_get_connection(handle); hci_layer_->GetHciHandler()->Post(common::BindOnce(&RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_), handle, connection.queue_->GetDownEnd())); hci_layer_->GetHciHandler()->Post( common::BindOnce(&RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_), RoundRobinScheduler::ConnectionType::LE, handle, connection.queue_->GetDownEnd())); auto role = connection_complete.GetRole(); std::unique_ptr<LeAclConnection> connection_proxy(new LeAclConnection( &acl_manager_, connection.queue_->GetUpEnd(), le_acl_connection_interface_, handle, address_with_type, role)); Loading Loading @@ -349,9 +349,9 @@ struct AclManager::impl : public security::ISecurityManagerListener { acl_connections_.emplace(std::piecewise_construct, std::forward_as_tuple(handle), std::forward_as_tuple(reporting_address_with_type, handler_)); auto& connection = check_and_get_connection(handle); hci_layer_->GetHciHandler()->Post(common::BindOnce(&RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_), handle, connection.queue_->GetDownEnd())); hci_layer_->GetHciHandler()->Post( common::BindOnce(&RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_), RoundRobinScheduler::ConnectionType::LE, handle, connection.queue_->GetDownEnd())); auto role = connection_complete.GetRole(); std::unique_ptr<LeAclConnection> connection_proxy(new LeAclConnection(&acl_manager_, connection.queue_->GetUpEnd(), le_acl_connection_interface_, handle, Loading @@ -378,9 +378,9 @@ struct AclManager::impl : public security::ISecurityManagerListener { std::piecewise_construct, std::forward_as_tuple(handle), std::forward_as_tuple(AddressWithType{address, AddressType::PUBLIC_DEVICE_ADDRESS}, handler_)); auto& connection = check_and_get_connection(handle); hci_layer_->GetHciHandler()->Post(common::BindOnce(&RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_), handle, check_and_get_connection(handle).queue_->GetDownEnd())); hci_layer_->GetHciHandler()->Post(common::BindOnce( &RoundRobinScheduler::Register, common::Unretained(round_robin_scheduler_), RoundRobinScheduler::ConnectionType::CLASSIC, handle, check_and_get_connection(handle).queue_->GetDownEnd())); std::unique_ptr<ClassicAclConnection> connection_proxy( new ClassicAclConnection(&acl_manager_, connection.queue_->GetUpEnd(), acl_connection_interface_, handle, address, Role::MASTER /* TODO: Did we connect? */)); Loading
system/gd/hci/controller.cc +8 −0 Original line number Diff line number Diff line Loading @@ -247,6 +247,14 @@ struct Controller::impl { ErrorCode status = complete_view.GetStatus(); ASSERT_LOG(status == ErrorCode::SUCCESS, "Status 0x%02hhx, %s", status, ErrorCodeText(status).c_str()); le_buffer_size_ = complete_view.GetLeBufferSize(); // If LE buffer size is zero, then buffers returned by Read_Buffer_Size are shared between BR/EDR and LE. if (le_buffer_size_.total_num_le_packets_ == 0) { ASSERT(acl_buffers_ != 0); le_buffer_size_.total_num_le_packets_ = acl_buffers_ / 2; acl_buffers_ -= le_buffer_size_.total_num_le_packets_; le_buffer_size_.le_data_packet_length_ = acl_buffer_length_; } } void le_read_local_supported_features_handler(CommandCompleteView view) { Loading
system/gd/hci/round_robin_scheduler.cc +49 −20 Original line number Diff line number Diff line Loading @@ -26,6 +26,10 @@ RoundRobinScheduler::RoundRobinScheduler(os::Handler* handler, Controller* contr max_acl_packet_credits_ = controller_->GetControllerNumAclPacketBuffers(); acl_packet_credits_ = max_acl_packet_credits_; hci_mtu_ = controller_->GetControllerAclPacketLength(); LeBufferSize le_buffer_size = controller_->GetControllerLeBufferSize(); le_max_acl_packet_credits_ = le_buffer_size.total_num_le_packets_; le_acl_packet_credits_ = le_max_acl_packet_credits_; le_hci_mtu_ = le_buffer_size.le_data_packet_length_; controller_->RegisterCompletedAclPacketsCallback( common::Bind(&RoundRobinScheduler::IncomingAclCredits, common::Unretained(this)), handler_); } Loading @@ -35,8 +39,9 @@ RoundRobinScheduler::~RoundRobinScheduler() { controller_->UnregisterCompletedAclPacketsCallback(); } void RoundRobinScheduler::Register(uint16_t handle, AclConnection::QueueDownEnd* queue_down_end) { acl_queue_handler acl_queue_handler = {queue_down_end, false, 0, false}; 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}; acl_queue_handlers_.insert(std::pair<uint16_t, RoundRobinScheduler::acl_queue_handler>(handle, acl_queue_handler)); if (fragments_to_send_.size() == 0) { StartRoundRobin(); Loading @@ -58,12 +63,16 @@ void RoundRobinScheduler::SetDisconnect(uint16_t handle) { auto acl_queue_handler = acl_queue_handlers_.find(handle)->second; acl_queue_handler.is_disconnected_ = true; // Reclaim outstanding packets if (acl_queue_handler.connection_type_ == ConnectionType::CLASSIC) { acl_packet_credits_ += acl_queue_handler.number_of_sent_packets_; } else { le_acl_packet_credits_ += acl_queue_handler.number_of_sent_packets_; } acl_queue_handler.number_of_sent_packets_ = 0; } void RoundRobinScheduler::StartRoundRobin() { if (acl_packet_credits_ == 0) { if (acl_packet_credits_ == 0 && le_acl_packet_credits_ == 0) { return; } if (!fragments_to_send_.empty()) { Loading Loading @@ -98,15 +107,19 @@ void RoundRobinScheduler::BufferPacket(std::map<uint16_t, acl_queue_handler>::it auto packet = acl_queue_handler->second.queue_down_end_->TryDequeue(); ASSERT(packet != nullptr); if (packet->size() <= hci_mtu_) { fragments_to_send_.push(AclPacketBuilder::Create(handle, PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE, broadcast_flag, std::move(packet))); ConnectionType connection_type = acl_queue_handler->second.connection_type_; size_t mtu = connection_type == ConnectionType::CLASSIC ? hci_mtu_ : le_hci_mtu_; if (packet->size() <= mtu) { fragments_to_send_.push(std::make_pair( connection_type, AclPacketBuilder::Create(handle, PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE, broadcast_flag, std::move(packet)))); } else { auto fragments = AclFragmenter(hci_mtu_, std::move(packet)).GetFragments(); auto fragments = AclFragmenter(mtu, std::move(packet)).GetFragments(); PacketBoundaryFlag packet_boundary_flag = PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE; for (size_t i = 0; i < fragments.size(); i++) { fragments_to_send_.push( AclPacketBuilder::Create(handle, packet_boundary_flag, broadcast_flag, std::move(fragments[i]))); fragments_to_send_.push(std::make_pair( connection_type, AclPacketBuilder::Create(handle, packet_boundary_flag, broadcast_flag, std::move(fragments[i])))); packet_boundary_flag = PacketBoundaryFlag::CONTINUING_FRAGMENT; } } Loading Loading @@ -136,18 +149,29 @@ void RoundRobinScheduler::SendNextFragment() { // Invoked from some external Queue Reactable context 1 std::unique_ptr<AclPacketBuilder> RoundRobinScheduler::HandleEnqueueNextFragment() { ConnectionType connection_type = fragments_to_send_.front().first; if (connection_type == ConnectionType::CLASSIC) { ASSERT(acl_packet_credits_ > 0); if (acl_packet_credits_ == 1 || fragments_to_send_.size() == 1) { if (enqueue_registered_.exchange(false)) { hci_queue_end_->UnregisterEnqueue(); } } ASSERT(fragments_to_send_.size() > 0); auto raw_pointer = fragments_to_send_.front().release(); acl_packet_credits_ -= 1; } else { ASSERT(le_acl_packet_credits_ > 0); le_acl_packet_credits_ -= 1; } auto raw_pointer = fragments_to_send_.front().second.release(); fragments_to_send_.pop(); if (fragments_to_send_.empty()) { if (enqueue_registered_.exchange(false)) { hci_queue_end_->UnregisterEnqueue(); } handler_->Post(common::BindOnce(&RoundRobinScheduler::StartRoundRobin, common::Unretained(this))); } else { ConnectionType next_connection_type = fragments_to_send_.front().first; bool classic_buffer_full = next_connection_type == ConnectionType::CLASSIC && acl_packet_credits_ == 0; bool le_buffer_full = next_connection_type == ConnectionType::LE && le_acl_packet_credits_ == 0; if ((classic_buffer_full || le_buffer_full) && enqueue_registered_.exchange(false)) { hci_queue_end_->UnregisterEnqueue(); } } return std::unique_ptr<AclPacketBuilder>(raw_pointer); } Loading @@ -163,9 +187,14 @@ void RoundRobinScheduler::IncomingAclCredits(uint16_t handle, uint16_t credits) return; } acl_queue_handler->second.number_of_sent_packets_ -= credits; if (acl_queue_handler->second.connection_type_ == ConnectionType::CLASSIC) { acl_packet_credits_ += credits; } else { le_acl_packet_credits_ += credits; } ASSERT(acl_packet_credits_ <= max_acl_packet_credits_); if (acl_packet_credits_ == credits) { ASSERT(le_acl_packet_credits_ <= le_max_acl_packet_credits_); if (acl_packet_credits_ == credits || le_acl_packet_credits_ == credits) { StartRoundRobin(); } } Loading
system/gd/hci/round_robin_scheduler.h +8 −2 Original line number Diff line number Diff line Loading @@ -33,14 +33,17 @@ class RoundRobinScheduler { common::BidiQueueEnd<AclPacketBuilder, AclPacketView>* hci_queue_end); ~RoundRobinScheduler(); enum ConnectionType { CLASSIC, LE }; struct acl_queue_handler { ConnectionType connection_type_; AclConnection::QueueDownEnd* queue_down_end_; bool dequeue_is_registered_ = false; uint16_t number_of_sent_packets_ = 0; // Track credits bool is_disconnected_ = false; }; void Register(uint16_t handle, AclConnection::QueueDownEnd* queue_down_end); void Register(ConnectionType connection_type, uint16_t handle, AclConnection::QueueDownEnd* queue_down_end); void Unregister(uint16_t handle); void SetDisconnect(uint16_t handle); Loading @@ -55,10 +58,13 @@ class RoundRobinScheduler { os::Handler* handler_ = nullptr; Controller* controller_ = nullptr; std::map<uint16_t, acl_queue_handler> acl_queue_handlers_; std::queue<std::unique_ptr<AclPacketBuilder>> fragments_to_send_; std::queue<std::pair<ConnectionType, std::unique_ptr<AclPacketBuilder>>> fragments_to_send_; uint16_t max_acl_packet_credits_ = 0; uint16_t acl_packet_credits_ = 0; uint16_t le_max_acl_packet_credits_ = 0; uint16_t le_acl_packet_credits_ = 0; size_t hci_mtu_{0}; size_t le_hci_mtu_{0}; std::atomic_bool enqueue_registered_ = false; common::BidiQueueEnd<AclPacketBuilder, AclPacketView>* hci_queue_end_ = nullptr; // first register queue end for the Round-robin schedule Loading