1 /*
2 * Copyright 2019 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 "hal/hci_hal_host_rootcanal.h"
18
19 #include <fcntl.h>
20 #include <gtest/gtest.h>
21 #include <netdb.h>
22 #include <netinet/in.h>
23 #include <netinet/ip.h>
24 #include <sys/socket.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 #include <cstring>
29 #include <queue>
30 #include <thread>
31 #include <utility>
32 #include <vector>
33
34 #include "hal/hci_hal.h"
35 #include "hal/serialize_packet.h"
36 #include "os/log.h"
37 #include "os/thread.h"
38 #include "os/utils.h"
39 #include "packet/raw_builder.h"
40
41 using ::bluetooth::os::Thread;
42
43 namespace bluetooth {
44 namespace hal {
45 namespace {
46
47 uint16_t kTestPort = 6537;
48
49 constexpr uint8_t kH4Command = 0x01;
50 constexpr uint8_t kH4Acl = 0x02;
51 constexpr uint8_t kH4Sco = 0x03;
52 constexpr uint8_t kH4Event = 0x04;
53
54 using H4Packet = std::vector<uint8_t>;
55
56 std::queue<std::pair<uint8_t, HciPacket>> incoming_packets_queue_;
57
58 class TestHciHalCallbacks : public HciHalCallbacks {
59 public:
hciEventReceived(HciPacket packet)60 void hciEventReceived(HciPacket packet) override {
61 incoming_packets_queue_.emplace(kH4Event, packet);
62 }
63
aclDataReceived(HciPacket packet)64 void aclDataReceived(HciPacket packet) override {
65 incoming_packets_queue_.emplace(kH4Acl, packet);
66 }
67
scoDataReceived(HciPacket packet)68 void scoDataReceived(HciPacket packet) override {
69 incoming_packets_queue_.emplace(kH4Sco, packet);
70 }
71 };
72
73 // An implementation of rootcanal desktop HCI server which listens on localhost:kListeningPort
74 class FakeRootcanalDesktopHciServer {
75 public:
FakeRootcanalDesktopHciServer()76 FakeRootcanalDesktopHciServer() {
77 struct sockaddr_in listen_address;
78 socklen_t sockaddr_in_size = sizeof(struct sockaddr_in);
79 memset(&listen_address, 0, sockaddr_in_size);
80
81 RUN_NO_INTR(listen_fd_ = socket(AF_INET, SOCK_STREAM, 0));
82 if (listen_fd_ < 0) {
83 LOG_WARN("Error creating socket for test channel.");
84 return;
85 }
86
87 listen_address.sin_family = AF_INET;
88 listen_address.sin_port = htons(HciHalHostRootcanalConfig::Get()->GetPort());
89 listen_address.sin_addr.s_addr = htonl(INADDR_ANY);
90
91 if (bind(listen_fd_, reinterpret_cast<sockaddr*>(&listen_address), sockaddr_in_size) < 0) {
92 LOG_WARN("Error binding test channel listener socket to address.");
93 close(listen_fd_);
94 return;
95 }
96
97 if (listen(listen_fd_, 1) < 0) {
98 LOG_WARN("Error listening for test channel.");
99 close(listen_fd_);
100 return;
101 }
102 }
103
~FakeRootcanalDesktopHciServer()104 ~FakeRootcanalDesktopHciServer() {
105 close(listen_fd_);
106 }
107
Accept()108 int Accept() {
109 int accept_fd;
110
111 RUN_NO_INTR(accept_fd = accept(listen_fd_, nullptr, nullptr));
112
113 int flags = fcntl(accept_fd, F_GETFL, NULL);
114 int ret = fcntl(accept_fd, F_SETFL, flags | O_NONBLOCK);
115 if (ret == -1) {
116 LOG_ERROR("Can't fcntl");
117 return -1;
118 }
119
120 if (accept_fd < 0) {
121 LOG_WARN("Error accepting test channel connection errno=%d (%s).", errno, strerror(errno));
122
123 if (errno != EAGAIN && errno != EWOULDBLOCK) {
124 LOG_ERROR("Closing listen_fd_ (won't try again).");
125 close(listen_fd_);
126 return -1;
127 }
128 }
129
130 return accept_fd;
131 }
132
133 private:
134 int listen_fd_ = -1;
135 };
136
137 class HciHalRootcanalTest : public ::testing::Test {
138 protected:
SetUp()139 void SetUp() override {
140 thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
141
142 HciHalHostRootcanalConfig::Get()->SetPort(kTestPort);
143 fake_server_ = new FakeRootcanalDesktopHciServer;
144 hal_ = fake_registry_.Start<HciHal>(thread_);
145 hal_->registerIncomingPacketCallback(&callbacks_);
146 fake_server_socket_ = fake_server_->Accept(); // accept() after client is connected to avoid blocking
147 std::queue<std::pair<uint8_t, HciPacket>> empty;
148 std::swap(incoming_packets_queue_, empty);
149 }
150
TearDown()151 void TearDown() override {
152 hal_->unregisterIncomingPacketCallback();
153 fake_registry_.StopAll();
154 close(fake_server_socket_);
155 delete fake_server_;
156 delete thread_;
157 }
158
SetFakeServerSocketToBlocking()159 void SetFakeServerSocketToBlocking() {
160 int flags = fcntl(fake_server_socket_, F_GETFL, NULL);
161 int ret = fcntl(fake_server_socket_, F_SETFL, flags & ~O_NONBLOCK);
162 EXPECT_NE(ret, -1) << "Can't set accept fd to blocking";
163 }
164
165 FakeRootcanalDesktopHciServer* fake_server_ = nullptr;
166 HciHal* hal_ = nullptr;
167 ModuleRegistry fake_registry_;
168 TestHciHalCallbacks callbacks_;
169 int fake_server_socket_ = -1;
170 Thread* thread_;
171 };
172
check_packet_equal(std::pair<uint8_t,HciPacket> hci_packet1_type_data_pair,H4Packet h4_packet2)173 void check_packet_equal(std::pair<uint8_t, HciPacket> hci_packet1_type_data_pair, H4Packet h4_packet2) {
174 auto packet1_hci_size = hci_packet1_type_data_pair.second.size();
175 ASSERT_EQ(packet1_hci_size + 1, h4_packet2.size());
176 ASSERT_EQ(hci_packet1_type_data_pair.first, h4_packet2[0]);
177 ASSERT_EQ(memcmp(hci_packet1_type_data_pair.second.data(), h4_packet2.data() + 1, packet1_hci_size), 0);
178 }
179
make_sample_hci_cmd_pkt(uint8_t parameter_total_length)180 HciPacket make_sample_hci_cmd_pkt(uint8_t parameter_total_length) {
181 HciPacket pkt;
182 pkt.assign(2 + 1 + parameter_total_length, 0x01);
183 pkt[2] = parameter_total_length;
184 return pkt;
185 }
186
make_sample_hci_acl_pkt(uint8_t payload_size)187 HciPacket make_sample_hci_acl_pkt(uint8_t payload_size) {
188 HciPacket pkt;
189 pkt.assign(2 + 2 + payload_size, 0x01);
190 pkt[2] = payload_size;
191 return pkt;
192 }
193
make_sample_hci_sco_pkt(uint8_t payload_size)194 HciPacket make_sample_hci_sco_pkt(uint8_t payload_size) {
195 HciPacket pkt;
196 pkt.assign(3 + payload_size, 0x01);
197 pkt[2] = payload_size;
198 return pkt;
199 }
200
make_sample_h4_evt_pkt(uint8_t parameter_total_length)201 H4Packet make_sample_h4_evt_pkt(uint8_t parameter_total_length) {
202 H4Packet pkt;
203 pkt.assign(1 + 1 + 1 + parameter_total_length, 0x01);
204 pkt[0] = kH4Event;
205 pkt[2] = parameter_total_length;
206 return pkt;
207 }
208
make_sample_h4_acl_pkt(uint8_t payload_size)209 HciPacket make_sample_h4_acl_pkt(uint8_t payload_size) {
210 HciPacket pkt;
211 pkt.assign(1 + 2 + 2 + payload_size, 0x01);
212 pkt[0] = kH4Acl;
213 pkt[3] = payload_size;
214 pkt[4] = 0;
215 return pkt;
216 }
217
make_sample_h4_sco_pkt(uint8_t payload_size)218 HciPacket make_sample_h4_sco_pkt(uint8_t payload_size) {
219 HciPacket pkt;
220 pkt.assign(1 + 3 + payload_size, 0x01);
221 pkt[0] = kH4Sco;
222 pkt[3] = payload_size;
223 return pkt;
224 }
225
read_with_retry(int socket,uint8_t * data,size_t length)226 size_t read_with_retry(int socket, uint8_t* data, size_t length) {
227 size_t bytes_read = 0;
228 ssize_t bytes_read_current = 0;
229 do {
230 bytes_read_current = read(socket, data + bytes_read, length - bytes_read);
231 bytes_read += bytes_read_current;
232 } while (length > bytes_read && bytes_read_current > 0);
233 return bytes_read;
234 }
235
TEST_F(HciHalRootcanalTest,init_and_close)236 TEST_F(HciHalRootcanalTest, init_and_close) {}
237
TEST_F(HciHalRootcanalTest,receive_hci_evt)238 TEST_F(HciHalRootcanalTest, receive_hci_evt) {
239 H4Packet incoming_packet = make_sample_h4_evt_pkt(3);
240 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size());
241 while (incoming_packets_queue_.size() != 1) {
242 }
243 auto packet = incoming_packets_queue_.front();
244 incoming_packets_queue_.pop();
245 check_packet_equal(packet, incoming_packet);
246 }
247
TEST_F(HciHalRootcanalTest,receive_hci_acl)248 TEST_F(HciHalRootcanalTest, receive_hci_acl) {
249 H4Packet incoming_packet = make_sample_h4_acl_pkt(3);
250 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size());
251 while (incoming_packets_queue_.size() != 1) {
252 }
253 auto packet = incoming_packets_queue_.front();
254 incoming_packets_queue_.pop();
255 check_packet_equal(packet, incoming_packet);
256 }
257
TEST_F(HciHalRootcanalTest,receive_hci_sco)258 TEST_F(HciHalRootcanalTest, receive_hci_sco) {
259 H4Packet incoming_packet = make_sample_h4_sco_pkt(3);
260 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size());
261 while (incoming_packets_queue_.size() != 1) {
262 }
263 auto packet = incoming_packets_queue_.front();
264 incoming_packets_queue_.pop();
265 check_packet_equal(packet, incoming_packet);
266 }
267
TEST_F(HciHalRootcanalTest,receive_two_hci_evts)268 TEST_F(HciHalRootcanalTest, receive_two_hci_evts) {
269 H4Packet incoming_packet = make_sample_h4_evt_pkt(3);
270 H4Packet incoming_packet2 = make_sample_h4_evt_pkt(5);
271 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size());
272 write(fake_server_socket_, incoming_packet2.data(), incoming_packet2.size());
273 while (incoming_packets_queue_.size() != 2) {
274 }
275 auto packet = incoming_packets_queue_.front();
276 incoming_packets_queue_.pop();
277 check_packet_equal(packet, incoming_packet);
278 packet = incoming_packets_queue_.front();
279 incoming_packets_queue_.pop();
280 check_packet_equal(packet, incoming_packet2);
281 }
282
TEST_F(HciHalRootcanalTest,receive_evt_and_acl)283 TEST_F(HciHalRootcanalTest, receive_evt_and_acl) {
284 H4Packet incoming_packet = make_sample_h4_evt_pkt(3);
285 H4Packet incoming_packet2 = make_sample_h4_acl_pkt(5);
286 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size());
287 write(fake_server_socket_, incoming_packet2.data(), incoming_packet2.size());
288 while (incoming_packets_queue_.size() != 2) {
289 }
290 auto packet = incoming_packets_queue_.front();
291 incoming_packets_queue_.pop();
292 check_packet_equal(packet, incoming_packet);
293 packet = incoming_packets_queue_.front();
294 incoming_packets_queue_.pop();
295 check_packet_equal(packet, incoming_packet2);
296 }
297
TEST_F(HciHalRootcanalTest,receive_multiple_acl_batch)298 TEST_F(HciHalRootcanalTest, receive_multiple_acl_batch) {
299 H4Packet incoming_packet = make_sample_h4_acl_pkt(5);
300 int num_packets = 1000;
301 for (int i = 0; i < num_packets; i++) {
302 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size());
303 }
304 while (incoming_packets_queue_.size() != num_packets) {
305 }
306 for (int i = 0; i < num_packets; i++) {
307 auto packet = incoming_packets_queue_.front();
308 incoming_packets_queue_.pop();
309 check_packet_equal(packet, incoming_packet);
310 }
311 }
312
TEST_F(HciHalRootcanalTest,receive_multiple_acl_sequential)313 TEST_F(HciHalRootcanalTest, receive_multiple_acl_sequential) {
314 H4Packet incoming_packet = make_sample_h4_acl_pkt(5);
315 int num_packets = 1000;
316 for (int i = 0; i < num_packets; i++) {
317 write(fake_server_socket_, incoming_packet.data(), incoming_packet.size());
318 while (incoming_packets_queue_.empty()) {
319 }
320 auto packet = incoming_packets_queue_.front();
321 incoming_packets_queue_.pop();
322 check_packet_equal(packet, incoming_packet);
323 }
324 }
325
TEST_F(HciHalRootcanalTest,send_hci_cmd)326 TEST_F(HciHalRootcanalTest, send_hci_cmd) {
327 uint8_t hci_cmd_param_size = 2;
328 HciPacket hci_data = make_sample_hci_cmd_pkt(hci_cmd_param_size);
329 hal_->sendHciCommand(hci_data);
330 H4Packet read_buf(1 + 2 + 1 + hci_cmd_param_size);
331 SetFakeServerSocketToBlocking();
332 auto size_read = read_with_retry(fake_server_socket_, read_buf.data(), read_buf.size());
333
334 ASSERT_EQ(size_read, 1 + hci_data.size());
335 check_packet_equal({kH4Command, hci_data}, read_buf);
336 }
337
TEST_F(HciHalRootcanalTest,send_acl)338 TEST_F(HciHalRootcanalTest, send_acl) {
339 uint8_t acl_payload_size = 200;
340 HciPacket acl_packet = make_sample_hci_acl_pkt(acl_payload_size);
341 hal_->sendAclData(acl_packet);
342 H4Packet read_buf(1 + 2 + 2 + acl_payload_size);
343 SetFakeServerSocketToBlocking();
344 auto size_read = read_with_retry(fake_server_socket_, read_buf.data(), read_buf.size());
345
346 ASSERT_EQ(size_read, 1 + acl_packet.size());
347 check_packet_equal({kH4Acl, acl_packet}, read_buf);
348 }
349
TEST_F(HciHalRootcanalTest,send_sco)350 TEST_F(HciHalRootcanalTest, send_sco) {
351 uint8_t sco_payload_size = 200;
352 HciPacket sco_packet = make_sample_hci_sco_pkt(sco_payload_size);
353 hal_->sendScoData(sco_packet);
354 H4Packet read_buf(1 + 3 + sco_payload_size);
355 SetFakeServerSocketToBlocking();
356 auto size_read = read_with_retry(fake_server_socket_, read_buf.data(), read_buf.size());
357
358 ASSERT_EQ(size_read, 1 + sco_packet.size());
359 check_packet_equal({kH4Sco, sco_packet}, read_buf);
360 }
361
TEST_F(HciHalRootcanalTest,send_multiple_acl_batch)362 TEST_F(HciHalRootcanalTest, send_multiple_acl_batch) {
363 uint8_t acl_payload_size = 200;
364 int num_packets = 1000;
365 HciPacket acl_packet = make_sample_hci_acl_pkt(acl_payload_size);
366 for (int i = 0; i < num_packets; i++) {
367 hal_->sendAclData(acl_packet);
368 }
369 H4Packet read_buf(1 + 2 + 2 + acl_payload_size);
370 SetFakeServerSocketToBlocking();
371 for (int i = 0; i < num_packets; i++) {
372 auto size_read = read_with_retry(fake_server_socket_, read_buf.data(), read_buf.size());
373 ASSERT_EQ(size_read, 1 + acl_packet.size());
374 check_packet_equal({kH4Acl, acl_packet}, read_buf);
375 }
376 }
377
TEST_F(HciHalRootcanalTest,send_multiple_acl_sequential)378 TEST_F(HciHalRootcanalTest, send_multiple_acl_sequential) {
379 uint8_t acl_payload_size = 200;
380 int num_packets = 1000;
381 HciPacket acl_packet = make_sample_hci_acl_pkt(acl_payload_size);
382 SetFakeServerSocketToBlocking();
383 for (int i = 0; i < num_packets; i++) {
384 hal_->sendAclData(acl_packet);
385 H4Packet read_buf(1 + 2 + 2 + acl_payload_size);
386 auto size_read = read_with_retry(fake_server_socket_, read_buf.data(), read_buf.size());
387 ASSERT_EQ(size_read, 1 + acl_packet.size());
388 check_packet_equal({kH4Acl, acl_packet}, read_buf);
389 }
390 }
391
TEST(HciHalHidlTest,serialize)392 TEST(HciHalHidlTest, serialize) {
393 std::vector<uint8_t> bytes = {1, 2, 3, 4, 5, 6, 7, 8, 9};
394 auto packet_bytes = hal::SerializePacket(std::unique_ptr<packet::BasePacketBuilder>(new packet::RawBuilder(bytes)));
395 ASSERT_EQ(bytes, packet_bytes);
396 }
397 } // namespace
398 } // namespace hal
399 } // namespace bluetooth
400