OSDN Git Service

gd hci: Check credit before sending next fragment
authorChienyuan <chienyuanhuang@google.com>
Thu, 8 Apr 2021 07:37:19 +0000 (15:37 +0800)
committerJack He <siyuanh@google.com>
Thu, 8 Apr 2021 17:28:14 +0000 (17:28 +0000)
Tag: #gd-refactor
Bug: 180870443
Test: gd/cert/run
BYPASS_LONG_LINES_REASON: Bluetooth likes 120 lines
Change-Id: Ifd2af34886a0cf40d5ca3f4fdd4869089276d919

gd/hci/acl_manager/round_robin_scheduler.cc
gd/hci/acl_manager/round_robin_scheduler_test.cc

index 6a469b0..4790708 100644 (file)
@@ -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;
   }
@@ -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();
   }
 }
index 03bcf96..9d43c0f 100644 (file)
@@ -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