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