• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "hci/acl_manager/round_robin_scheduler.h"
18 
19 #include <gtest/gtest.h>
20 
21 #include "common/bidi_queue.h"
22 #include "common/callback.h"
23 #include "hci/acl_manager.h"
24 #include "hci/controller.h"
25 #include "hci/hci_packets.h"
26 #include "os/handler.h"
27 #include "os/log.h"
28 #include "packet/raw_builder.h"
29 
30 using ::bluetooth::common::BidiQueue;
31 using ::bluetooth::common::Callback;
32 using ::bluetooth::os::Handler;
33 using ::bluetooth::os::Thread;
34 
35 namespace bluetooth {
36 namespace hci {
37 namespace acl_manager {
38 
39 class TestController : public Controller {
40  public:
GetNumAclPacketBuffers() const41   uint16_t GetNumAclPacketBuffers() const {
42     return max_acl_packet_credits_;
43   }
44 
GetAclPacketLength() const45   uint16_t GetAclPacketLength() const {
46     return hci_mtu_;
47   }
48 
GetLeBufferSize() const49   LeBufferSize GetLeBufferSize() const {
50     LeBufferSize le_buffer_size;
51     le_buffer_size.le_data_packet_length_ = le_hci_mtu_;
52     le_buffer_size.total_num_le_packets_ = le_max_acl_packet_credits_;
53     return le_buffer_size;
54   }
55 
RegisterCompletedAclPacketsCallback(CompletedAclPacketsCallback cb)56   void RegisterCompletedAclPacketsCallback(CompletedAclPacketsCallback cb) {
57     acl_credits_callback_ = cb;
58   }
59 
SendCompletedAclPacketsCallback(uint16_t handle,uint16_t credits)60   void SendCompletedAclPacketsCallback(uint16_t handle, uint16_t credits) {
61     acl_credits_callback_.Invoke(handle, credits);
62   }
63 
UnregisterCompletedAclPacketsCallback()64   void UnregisterCompletedAclPacketsCallback() {
65     acl_credits_callback_ = {};
66   }
67 
68   const uint16_t max_acl_packet_credits_ = 10;
69   const uint16_t hci_mtu_ = 1024;
70   const uint16_t le_max_acl_packet_credits_ = 15;
71   const uint16_t le_hci_mtu_ = 27;
72 
73  private:
74   CompletedAclPacketsCallback acl_credits_callback_;
75 };
76 
77 class RoundRobinSchedulerTest : public ::testing::Test {
78  public:
SetUp()79   void SetUp() override {
80     thread_ = new Thread("thread", Thread::Priority::NORMAL);
81     handler_ = new Handler(thread_);
82     controller_ = new TestController();
83     round_robin_scheduler_ = new RoundRobinScheduler(handler_, controller_, hci_queue_.GetUpEnd());
84     hci_queue_.GetDownEnd()->RegisterDequeue(
85         handler_, common::Bind(&RoundRobinSchedulerTest::HciDownEndDequeue, common::Unretained(this)));
86   }
87 
TearDown()88   void TearDown() override {
89     hci_queue_.GetDownEnd()->UnregisterDequeue();
90     delete round_robin_scheduler_;
91     delete controller_;
92     handler_->Clear();
93     delete handler_;
94     delete thread_;
95   }
96 
sync_handler()97   void sync_handler() {
98     std::promise<void> promise;
99     auto future = promise.get_future();
100     handler_->BindOnceOn(&promise, &std::promise<void>::set_value).Invoke();
101     auto status = future.wait_for(std::chrono::milliseconds(3));
102     EXPECT_EQ(status, std::future_status::ready);
103   }
104 
EnqueueAclUpEnd(AclConnection::QueueUpEnd * queue_up_end,std::vector<uint8_t> packet)105   void EnqueueAclUpEnd(AclConnection::QueueUpEnd* queue_up_end, std::vector<uint8_t> packet) {
106     if (enqueue_promise_ != nullptr) {
107       enqueue_future_->wait();
108     }
109     enqueue_promise_ = std::make_unique<std::promise<void>>();
110     enqueue_future_ = std::make_unique<std::future<void>>(enqueue_promise_->get_future());
111     queue_up_end->RegisterEnqueue(handler_, common::Bind(&RoundRobinSchedulerTest::enqueue_callback,
112                                                          common::Unretained(this), queue_up_end, packet));
113   }
114 
enqueue_callback(AclConnection::QueueUpEnd * queue_up_end,std::vector<uint8_t> packet)115   std::unique_ptr<packet::BasePacketBuilder> enqueue_callback(AclConnection::QueueUpEnd* queue_up_end,
116                                                               std::vector<uint8_t> packet) {
117     auto packet_one = std::make_unique<packet::RawBuilder>(2000);
118     packet_one->AddOctets(packet);
119     queue_up_end->UnregisterEnqueue();
120     enqueue_promise_->set_value();
121     return packet_one;
122   };
123 
HciDownEndDequeue()124   void HciDownEndDequeue() {
125     auto packet = hci_queue_.GetDownEnd()->TryDequeue();
126     // Convert from a Builder to a View
127     auto bytes = std::make_shared<std::vector<uint8_t>>();
128     bluetooth::packet::BitInserter i(*bytes);
129     bytes->reserve(packet->size());
130     packet->Serialize(i);
131     auto packet_view = bluetooth::packet::PacketView<bluetooth::packet::kLittleEndian>(bytes);
132     AclView acl_packet_view = AclView::Create(packet_view);
133     ASSERT_TRUE(acl_packet_view.IsValid());
134     PacketView<true> count_view = acl_packet_view.GetPayload();
135     sent_acl_packets_.push(acl_packet_view);
136 
137     packet_count_--;
138     if (packet_count_ == 0) {
139       packet_promise_->set_value();
140       packet_promise_ = nullptr;
141     }
142   }
143 
VerifyPacket(uint16_t handle,std::vector<uint8_t> packet)144   void VerifyPacket(uint16_t handle, std::vector<uint8_t> packet) {
145     auto acl_packet_view = sent_acl_packets_.front();
146     ASSERT_EQ(handle, acl_packet_view.GetHandle());
147     auto payload = acl_packet_view.GetPayload();
148     for (size_t i = 0; i < payload.size(); i++) {
149       ASSERT_EQ(payload[i], packet[i]);
150     }
151     sent_acl_packets_.pop();
152   }
153 
SetPacketFuture(uint16_t count)154   void SetPacketFuture(uint16_t count) {
155     ASSERT_LOG(packet_promise_ == nullptr, "Promises, Promises, ... Only one at a time.");
156     packet_count_ = count;
157     packet_promise_ = std::make_unique<std::promise<void>>();
158     packet_future_ = std::make_unique<std::future<void>>(packet_promise_->get_future());
159   }
160 
161   BidiQueue<AclView, AclBuilder> hci_queue_{3};
162   Thread* thread_;
163   Handler* handler_;
164   TestController* controller_;
165   RoundRobinScheduler* round_robin_scheduler_;
166   std::queue<AclView> sent_acl_packets_;
167   uint16_t packet_count_;
168   std::unique_ptr<std::promise<void>> packet_promise_;
169   std::unique_ptr<std::future<void>> packet_future_;
170   std::unique_ptr<std::promise<void>> enqueue_promise_;
171   std::unique_ptr<std::future<void>> enqueue_future_;
172 };
173 
TEST_F(RoundRobinSchedulerTest,startup_teardown)174 TEST_F(RoundRobinSchedulerTest, startup_teardown) {}
175 
TEST_F(RoundRobinSchedulerTest,register_unregister_connection)176 TEST_F(RoundRobinSchedulerTest, register_unregister_connection) {
177   uint16_t handle = 0x01;
178   auto connection_queue = std::make_shared<AclConnection::Queue>(10);
179   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue);
180   round_robin_scheduler_->Unregister(handle);
181 }
182 
TEST_F(RoundRobinSchedulerTest,buffer_packet)183 TEST_F(RoundRobinSchedulerTest, buffer_packet) {
184   uint16_t handle = 0x01;
185   auto connection_queue = std::make_shared<AclConnection::Queue>(10);
186   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue);
187 
188   SetPacketFuture(2);
189   AclConnection::QueueUpEnd* queue_up_end = connection_queue->GetUpEnd();
190   std::vector<uint8_t> packet1 = {0x01, 0x02, 0x03};
191   std::vector<uint8_t> packet2 = {0x04, 0x05, 0x06};
192   EnqueueAclUpEnd(queue_up_end, packet1);
193   EnqueueAclUpEnd(queue_up_end, packet2);
194 
195   packet_future_->wait();
196   VerifyPacket(handle, packet1);
197   VerifyPacket(handle, packet2);
198   ASSERT_EQ(round_robin_scheduler_->GetCredits(), controller_->max_acl_packet_credits_ - 2);
199 
200   round_robin_scheduler_->Unregister(handle);
201 }
202 
TEST_F(RoundRobinSchedulerTest,buffer_packet_from_two_connections)203 TEST_F(RoundRobinSchedulerTest, buffer_packet_from_two_connections) {
204   uint16_t handle = 0x01;
205   uint16_t le_handle = 0x02;
206   auto connection_queue = std::make_shared<AclConnection::Queue>(10);
207   auto le_connection_queue = std::make_shared<AclConnection::Queue>(10);
208 
209   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue);
210   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle, le_connection_queue);
211 
212   SetPacketFuture(2);
213   AclConnection::QueueUpEnd* queue_up_end = connection_queue->GetUpEnd();
214   AclConnection::QueueUpEnd* le_queue_up_end = le_connection_queue->GetUpEnd();
215   std::vector<uint8_t> packet = {0x01, 0x02, 0x03};
216   std::vector<uint8_t> le_packet = {0x04, 0x05, 0x06};
217   EnqueueAclUpEnd(le_queue_up_end, le_packet);
218   EnqueueAclUpEnd(queue_up_end, packet);
219 
220   packet_future_->wait();
221   VerifyPacket(le_handle, le_packet);
222   VerifyPacket(handle, packet);
223   ASSERT_EQ(round_robin_scheduler_->GetCredits(), controller_->max_acl_packet_credits_ - 1);
224   ASSERT_EQ(round_robin_scheduler_->GetLeCredits(), controller_->le_max_acl_packet_credits_ - 1);
225 
226   round_robin_scheduler_->Unregister(handle);
227   round_robin_scheduler_->Unregister(le_handle);
228 }
229 
TEST_F(RoundRobinSchedulerTest,do_not_register_when_credits_is_zero)230 TEST_F(RoundRobinSchedulerTest, do_not_register_when_credits_is_zero) {
231   uint16_t handle = 0x01;
232   auto connection_queue = std::make_shared<AclConnection::Queue>(15);
233   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue);
234 
235   SetPacketFuture(10);
236   AclConnection::QueueUpEnd* queue_up_end = connection_queue->GetUpEnd();
237   for (uint8_t i = 0; i < 15; i++) {
238     std::vector<uint8_t> packet = {0x01, 0x02, 0x03, i};
239     EnqueueAclUpEnd(queue_up_end, packet);
240   }
241 
242   packet_future_->wait();
243   for (uint8_t i = 0; i < 10; i++) {
244     std::vector<uint8_t> packet = {0x01, 0x02, 0x03, i};
245     VerifyPacket(handle, packet);
246   }
247   ASSERT_EQ(round_robin_scheduler_->GetCredits(), 0);
248 
249   SetPacketFuture(5);
250   controller_->SendCompletedAclPacketsCallback(0x01, 10);
251   sync_handler();
252   packet_future_->wait();
253   for (uint8_t i = 10; i < 15; i++) {
254     std::vector<uint8_t> packet = {0x01, 0x02, 0x03, i};
255     VerifyPacket(handle, packet);
256   }
257   ASSERT_EQ(round_robin_scheduler_->GetCredits(), 5);
258 
259   round_robin_scheduler_->Unregister(handle);
260 }
261 
TEST_F(RoundRobinSchedulerTest,reveived_completed_callback_with_unknown_handle)262 TEST_F(RoundRobinSchedulerTest, reveived_completed_callback_with_unknown_handle) {
263   controller_->SendCompletedAclPacketsCallback(0x00, 1);
264   sync_handler();
265   EXPECT_EQ(round_robin_scheduler_->GetCredits(), controller_->max_acl_packet_credits_);
266   EXPECT_EQ(round_robin_scheduler_->GetLeCredits(), controller_->le_max_acl_packet_credits_);
267 }
268 
TEST_F(RoundRobinSchedulerTest,buffer_packet_intervally)269 TEST_F(RoundRobinSchedulerTest, buffer_packet_intervally) {
270   uint16_t handle1 = 0x01;
271   uint16_t handle2 = 0x02;
272   uint16_t le_handle1 = 0x03;
273   uint16_t le_handle2 = 0x04;
274   auto connection_queue1 = std::make_shared<AclConnection::Queue>(10);
275   auto connection_queue2 = std::make_shared<AclConnection::Queue>(10);
276   auto le_connection_queue1 = std::make_shared<AclConnection::Queue>(10);
277   auto le_connection_queue2 = std::make_shared<AclConnection::Queue>(10);
278 
279   SetPacketFuture(18);
280   AclConnection::QueueUpEnd* queue_up_end1 = connection_queue1->GetUpEnd();
281   AclConnection::QueueUpEnd* queue_up_end2 = connection_queue2->GetUpEnd();
282   AclConnection::QueueUpEnd* le_queue_up_end1 = le_connection_queue1->GetUpEnd();
283   AclConnection::QueueUpEnd* le_queue_up_end2 = le_connection_queue2->GetUpEnd();
284 
285   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle1, connection_queue1);
286   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle2, connection_queue2);
287   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle1, le_connection_queue1);
288   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle2, le_connection_queue2);
289 
290   std::vector<uint8_t> packet = {0x01, 0x02, 0x03};
291   EnqueueAclUpEnd(queue_up_end1, packet);
292   EnqueueAclUpEnd(le_queue_up_end2, packet);
293   for (uint8_t i = 0; i < 4; i++) {
294     std::vector<uint8_t> packet1 = {0x01, 0x02, 0x03, i};
295     std::vector<uint8_t> packet2 = {0x02, 0x02, 0x03, i};
296     std::vector<uint8_t> le_packet1 = {0x04, 0x05, 0x06, i};
297     std::vector<uint8_t> le_packet2 = {0x05, 0x05, 0x06, i};
298     EnqueueAclUpEnd(queue_up_end1, packet1);
299     EnqueueAclUpEnd(queue_up_end2, packet2);
300     EnqueueAclUpEnd(le_queue_up_end1, le_packet1);
301     EnqueueAclUpEnd(le_queue_up_end2, le_packet2);
302   }
303 
304   packet_future_->wait();
305   VerifyPacket(handle1, packet);
306   VerifyPacket(le_handle2, packet);
307   for (uint8_t i = 0; i < 4; i++) {
308     std::vector<uint8_t> packet1 = {0x01, 0x02, 0x03, i};
309     std::vector<uint8_t> packet2 = {0x02, 0x02, 0x03, i};
310     std::vector<uint8_t> le_packet1 = {0x04, 0x05, 0x06, i};
311     std::vector<uint8_t> le_packet2 = {0x05, 0x05, 0x06, i};
312     VerifyPacket(handle1, packet1);
313     VerifyPacket(handle2, packet2);
314     VerifyPacket(le_handle1, le_packet1);
315     VerifyPacket(le_handle2, le_packet2);
316   }
317 
318   ASSERT_EQ(round_robin_scheduler_->GetCredits(), controller_->max_acl_packet_credits_ - 9);
319   ASSERT_EQ(round_robin_scheduler_->GetLeCredits(), controller_->le_max_acl_packet_credits_ - 9);
320 
321   round_robin_scheduler_->Unregister(handle1);
322   round_robin_scheduler_->Unregister(handle2);
323   round_robin_scheduler_->Unregister(le_handle1);
324   round_robin_scheduler_->Unregister(le_handle2);
325 }
326 
TEST_F(RoundRobinSchedulerTest,send_fragments_without_interval)327 TEST_F(RoundRobinSchedulerTest, send_fragments_without_interval) {
328   uint16_t handle = 0x01;
329   uint16_t le_handle = 0x02;
330   auto connection_queue = std::make_shared<AclConnection::Queue>(10);
331   auto le_connection_queue = std::make_shared<AclConnection::Queue>(10);
332 
333   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue);
334   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle, le_connection_queue);
335 
336   SetPacketFuture(5);
337   AclConnection::QueueUpEnd* queue_up_end = connection_queue->GetUpEnd();
338   AclConnection::QueueUpEnd* le_queue_up_end = le_connection_queue->GetUpEnd();
339   std::vector<uint8_t> packet(controller_->hci_mtu_, 0xff);
340   std::vector<uint8_t> packet_part1(controller_->hci_mtu_, 0xff);
341   std::vector<uint8_t> packet_part2 = {0x03, 0x02, 0x01};
342   packet.insert(packet.end(), packet_part2.begin(), packet_part2.end());
343 
344   std::vector<uint8_t> le_packet;
345   std::vector<uint8_t> le_packet_part1;
346   std::vector<uint8_t> le_packet_part2;
347   std::vector<uint8_t> le_packet_part3;
348   for (uint8_t i = 0; i < controller_->le_hci_mtu_; i++) {
349     le_packet.push_back(i);
350     le_packet_part1.push_back(i);
351     le_packet_part2.push_back(i * 2);
352     le_packet_part3.push_back(i * 3);
353   }
354   le_packet.insert(le_packet.end(), le_packet_part2.begin(), le_packet_part2.end());
355   le_packet.insert(le_packet.end(), le_packet_part3.begin(), le_packet_part3.end());
356 
357   EnqueueAclUpEnd(le_queue_up_end, le_packet);
358   EnqueueAclUpEnd(queue_up_end, packet);
359 
360   packet_future_->wait();
361   VerifyPacket(le_handle, le_packet_part1);
362   VerifyPacket(le_handle, le_packet_part2);
363   VerifyPacket(le_handle, le_packet_part3);
364   VerifyPacket(handle, packet_part1);
365   VerifyPacket(handle, packet_part2);
366   ASSERT_EQ(round_robin_scheduler_->GetCredits(), controller_->max_acl_packet_credits_ - 2);
367   ASSERT_EQ(round_robin_scheduler_->GetLeCredits(), controller_->le_max_acl_packet_credits_ - 3);
368 
369   round_robin_scheduler_->Unregister(handle);
370   round_robin_scheduler_->Unregister(le_handle);
371 }
372 
TEST_F(RoundRobinSchedulerTest,receive_le_credit_when_next_fragment_is_classic)373 TEST_F(RoundRobinSchedulerTest, receive_le_credit_when_next_fragment_is_classic) {
374   uint16_t handle = 0x01;
375   uint16_t le_handle = 0x02;
376   auto connection_queue = std::make_shared<AclConnection::Queue>(20);
377   auto le_connection_queue = std::make_shared<AclConnection::Queue>(20);
378 
379   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::CLASSIC, handle, connection_queue);
380   round_robin_scheduler_->Register(RoundRobinScheduler::ConnectionType::LE, le_handle, le_connection_queue);
381 
382   SetPacketFuture(controller_->le_max_acl_packet_credits_ + controller_->max_acl_packet_credits_);
383   AclConnection::QueueUpEnd* queue_up_end = connection_queue->GetUpEnd();
384   AclConnection::QueueUpEnd* le_queue_up_end = le_connection_queue->GetUpEnd();
385   std::vector<uint8_t> huge_packet(2000);
386   std::vector<uint8_t> packet = {0x01, 0x02, 0x03};
387   std::vector<uint8_t> le_packet = {0x04, 0x05, 0x06};
388 
389   // Make le_acl_packet_credits_ = 0;
390   for (uint16_t i = 0; i < controller_->le_max_acl_packet_credits_; i++) {
391     EnqueueAclUpEnd(le_queue_up_end, le_packet);
392   }
393 
394   // Make acl_packet_credits_ = 0 and remain 1 acl fragment in fragments_to_send_
395   for (uint16_t i = 0; i < controller_->max_acl_packet_credits_ - 1; i++) {
396     EnqueueAclUpEnd(queue_up_end, packet);
397   }
398   EnqueueAclUpEnd(queue_up_end, huge_packet);
399 
400   packet_future_->wait();
401 
402   // Trigger start_round_robin
403   controller_->SendCompletedAclPacketsCallback(0x02, 1);
404   std::this_thread::sleep_for(std::chrono::milliseconds(20));
405 
406   ASSERT_EQ(round_robin_scheduler_->GetCredits(), 0);
407   ASSERT_EQ(round_robin_scheduler_->GetLeCredits(), 1);
408 
409   round_robin_scheduler_->Unregister(handle);
410   round_robin_scheduler_->Unregister(le_handle);
411 }
412 
413 }  // namespace acl_manager
414 }  // namespace hci
415 }  // namespace bluetooth
416