Loading system/gd/hci/acl_manager/round_robin_scheduler.cc +15 −1 Original line number Diff line number Diff line Loading @@ -89,6 +89,13 @@ void RoundRobinScheduler::start_round_robin() { return; } if (!fragments_to_send_.empty()) { auto connection_type = fragments_to_send_.front().first; bool classic_buffer_full = acl_packet_credits_ == 0 && connection_type == ConnectionType::CLASSIC; bool le_buffer_full = le_acl_packet_credits_ == 0 && connection_type == ConnectionType::LE; if (classic_buffer_full || le_buffer_full) { LOG_WARN("Buffer of connection_type %d is full", connection_type); return; } send_next_fragment(); return; } Loading Loading @@ -217,20 +224,27 @@ void RoundRobinScheduler::incoming_acl_credits(uint16_t handle, uint16_t credits acl_queue_handler->second.number_of_sent_packets_ = 0; } bool credit_was_zero = false; if (acl_queue_handler->second.connection_type_ == ConnectionType::CLASSIC) { if (acl_packet_credits_ == 0) { credit_was_zero = true; } acl_packet_credits_ += credits; if (acl_packet_credits_ > max_acl_packet_credits_) { acl_packet_credits_ = max_acl_packet_credits_; LOG_WARN("acl packet credits overflow due to receive %hx credits", credits); } } else { if (le_acl_packet_credits_ == 0) { credit_was_zero = true; } le_acl_packet_credits_ += credits; if (le_acl_packet_credits_ > le_max_acl_packet_credits_) { le_acl_packet_credits_ = le_max_acl_packet_credits_; LOG_WARN("le acl packet credits overflow due to receive %hx credits", credits); } } if (acl_packet_credits_ == credits || le_acl_packet_credits_ == credits) { if (credit_was_zero) { start_round_robin(); } } Loading system/gd/hci/acl_manager/round_robin_scheduler_test.cc +40 −0 Original line number Diff line number Diff line Loading @@ -370,6 +370,46 @@ TEST_F(RoundRobinSchedulerTest, send_fragments_without_interval) { round_robin_scheduler_->Unregister(le_handle); } TEST_F(RoundRobinSchedulerTest, receive_le_credit_when_next_fragment_is_classic) { uint16_t handle = 0x01; uint16_t le_handle = 0x02; auto connection_queue = std::make_shared<AclConnection::Queue>(20); auto le_connection_queue = std::make_shared<AclConnection::Queue>(20); round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue); round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle, le_connection_queue); SetPacketFuture(controller_->le_max_acl_packet_credits_ + controller_->max_acl_packet_credits_); AclConnection::QueueUpEnd* queue_up_end = connection_queue->GetUpEnd(); AclConnection::QueueUpEnd* le_queue_up_end = le_connection_queue->GetUpEnd(); std::vector<uint8_t> huge_packet(2000); std::vector<uint8_t> packet = {0x01, 0x02, 0x03}; std::vector<uint8_t> le_packet = {0x04, 0x05, 0x06}; // Make le_acl_packet_credits_ = 0; for (uint16_t i = 0; i < controller_->le_max_acl_packet_credits_; i++) { EnqueueAclUpEnd(le_queue_up_end, le_packet); } // Make acl_packet_credits_ = 0 and remain 1 acl fragment in fragments_to_send_ for (uint16_t i = 0; i < controller_->max_acl_packet_credits_ - 1; i++) { EnqueueAclUpEnd(queue_up_end, packet); } EnqueueAclUpEnd(queue_up_end, huge_packet); packet_future_->wait(); // Trigger start_round_robin controller_->SendCompletedAclPacketsCallback(0x02, 1); std::this_thread::sleep_for(std::chrono::milliseconds(20)); ASSERT_EQ(round_robin_scheduler_->GetCredits(), 0); ASSERT_EQ(round_robin_scheduler_->GetLeCredits(), 1); round_robin_scheduler_->Unregister(handle); round_robin_scheduler_->Unregister(le_handle); } } // namespace acl_manager } // namespace hci } // namespace bluetooth Loading
system/gd/hci/acl_manager/round_robin_scheduler.cc +15 −1 Original line number Diff line number Diff line Loading @@ -89,6 +89,13 @@ void RoundRobinScheduler::start_round_robin() { return; } if (!fragments_to_send_.empty()) { auto connection_type = fragments_to_send_.front().first; bool classic_buffer_full = acl_packet_credits_ == 0 && connection_type == ConnectionType::CLASSIC; bool le_buffer_full = le_acl_packet_credits_ == 0 && connection_type == ConnectionType::LE; if (classic_buffer_full || le_buffer_full) { LOG_WARN("Buffer of connection_type %d is full", connection_type); return; } send_next_fragment(); return; } Loading Loading @@ -217,20 +224,27 @@ void RoundRobinScheduler::incoming_acl_credits(uint16_t handle, uint16_t credits acl_queue_handler->second.number_of_sent_packets_ = 0; } bool credit_was_zero = false; if (acl_queue_handler->second.connection_type_ == ConnectionType::CLASSIC) { if (acl_packet_credits_ == 0) { credit_was_zero = true; } acl_packet_credits_ += credits; if (acl_packet_credits_ > max_acl_packet_credits_) { acl_packet_credits_ = max_acl_packet_credits_; LOG_WARN("acl packet credits overflow due to receive %hx credits", credits); } } else { if (le_acl_packet_credits_ == 0) { credit_was_zero = true; } le_acl_packet_credits_ += credits; if (le_acl_packet_credits_ > le_max_acl_packet_credits_) { le_acl_packet_credits_ = le_max_acl_packet_credits_; LOG_WARN("le acl packet credits overflow due to receive %hx credits", credits); } } if (acl_packet_credits_ == credits || le_acl_packet_credits_ == credits) { if (credit_was_zero) { start_round_robin(); } } Loading
system/gd/hci/acl_manager/round_robin_scheduler_test.cc +40 −0 Original line number Diff line number Diff line Loading @@ -370,6 +370,46 @@ TEST_F(RoundRobinSchedulerTest, send_fragments_without_interval) { round_robin_scheduler_->Unregister(le_handle); } TEST_F(RoundRobinSchedulerTest, receive_le_credit_when_next_fragment_is_classic) { uint16_t handle = 0x01; uint16_t le_handle = 0x02; auto connection_queue = std::make_shared<AclConnection::Queue>(20); auto le_connection_queue = std::make_shared<AclConnection::Queue>(20); round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue); round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle, le_connection_queue); SetPacketFuture(controller_->le_max_acl_packet_credits_ + controller_->max_acl_packet_credits_); AclConnection::QueueUpEnd* queue_up_end = connection_queue->GetUpEnd(); AclConnection::QueueUpEnd* le_queue_up_end = le_connection_queue->GetUpEnd(); std::vector<uint8_t> huge_packet(2000); std::vector<uint8_t> packet = {0x01, 0x02, 0x03}; std::vector<uint8_t> le_packet = {0x04, 0x05, 0x06}; // Make le_acl_packet_credits_ = 0; for (uint16_t i = 0; i < controller_->le_max_acl_packet_credits_; i++) { EnqueueAclUpEnd(le_queue_up_end, le_packet); } // Make acl_packet_credits_ = 0 and remain 1 acl fragment in fragments_to_send_ for (uint16_t i = 0; i < controller_->max_acl_packet_credits_ - 1; i++) { EnqueueAclUpEnd(queue_up_end, packet); } EnqueueAclUpEnd(queue_up_end, huge_packet); packet_future_->wait(); // Trigger start_round_robin controller_->SendCompletedAclPacketsCallback(0x02, 1); std::this_thread::sleep_for(std::chrono::milliseconds(20)); ASSERT_EQ(round_robin_scheduler_->GetCredits(), 0); ASSERT_EQ(round_robin_scheduler_->GetLeCredits(), 1); round_robin_scheduler_->Unregister(handle); round_robin_scheduler_->Unregister(le_handle); } } // namespace acl_manager } // namespace hci } // namespace bluetooth