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