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