1 //
2 // Copyright 2017 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 #define LOG_TAG "bt_h4_unittest"
18
19 #include "h4_protocol.h"
20 #include <gmock/gmock.h>
21 #include <gtest/gtest.h>
22 #include <condition_variable>
23 #include <cstdint>
24 #include <cstring>
25 #include <mutex>
26 #include <vector>
27
28 #include <log/log.h>
29 #include <sys/socket.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32
33 namespace android {
34 namespace hardware {
35 namespace bluetooth {
36 namespace V1_0 {
37 namespace implementation {
38
39 using hci::H4Protocol;
40 using ::testing::Eq;
41
42 static char sample_data1[100] = "A point is that which has no part.";
43 static char sample_data2[100] = "A line is breadthless length.";
44 static char sample_data3[100] = "The ends of a line are points.";
45 static char sample_data4[100] =
46 "A plane surface is a surface which lies evenly with the straight ...";
47 static char acl_data[100] =
48 "A straight line is a line which lies evenly with the points on itself.";
49 static char sco_data[100] =
50 "A surface is that which has length and breadth only.";
51 static char event_data[100] = "The edges of a surface are lines.";
52 static char iso_data[100] =
53 "A plane angle is the inclination to one another of two lines in a ...";
54
55 MATCHER_P3(HidlVecMatches, preamble, preamble_length, payload, "") {
56 size_t length = strlen(payload) + preamble_length;
57 if (length != arg.size()) {
58 return false;
59 }
60
61 if (memcmp(preamble, arg.data(), preamble_length) != 0) {
62 return false;
63 }
64
65 return memcmp(payload, arg.data() + preamble_length,
66 length - preamble_length) == 0;
67 };
68
ACTION_P2(Notify,mutex,condition)69 ACTION_P2(Notify, mutex, condition) {
70 ALOGD("%s", __func__);
71 std::unique_lock<std::mutex> lock(*mutex);
72 condition->notify_one();
73 }
74
75 class H4ProtocolTest : public ::testing::Test {
76 protected:
SetUp()77 void SetUp() override {
78 ALOGD("%s", __func__);
79
80 int sockfd[2];
81 socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);
82 H4Protocol* h4_hci = new H4Protocol(
83 sockfd[0], event_cb_.AsStdFunction(), acl_cb_.AsStdFunction(),
84 sco_cb_.AsStdFunction(), iso_cb_.AsStdFunction());
85 fd_watcher_.WatchFdForNonBlockingReads(
86 sockfd[0], [h4_hci](int fd) { h4_hci->OnDataReady(fd); });
87 protocol_ = h4_hci;
88
89 fake_uart_ = sockfd[1];
90 }
91
TearDown()92 void TearDown() override { fd_watcher_.StopWatchingFileDescriptors(); }
93
SendAndReadUartOutbound(uint8_t type,char * data)94 void SendAndReadUartOutbound(uint8_t type, char* data) {
95 ALOGD("%s sending", __func__);
96 int data_length = strlen(data);
97 protocol_->Send(type, (uint8_t*)data, data_length);
98
99 int uart_length = data_length + 1; // + 1 for data type code
100 int i;
101
102 ALOGD("%s reading", __func__);
103 for (i = 0; i < uart_length; i++) {
104 fd_set read_fds;
105 FD_ZERO(&read_fds);
106 FD_SET(fake_uart_, &read_fds);
107 TEMP_FAILURE_RETRY(select(fake_uart_ + 1, &read_fds, NULL, NULL, NULL));
108
109 char byte;
110 TEMP_FAILURE_RETRY(read(fake_uart_, &byte, 1));
111
112 EXPECT_EQ(i == 0 ? type : data[i - 1], byte);
113 }
114
115 EXPECT_EQ(i, uart_length);
116 }
117
WriteAndExpectInboundAclData(char * payload)118 void WriteAndExpectInboundAclData(char* payload) {
119 // h4 type[1] + handle[2] + size[2]
120 char preamble[5] = {HCI_PACKET_TYPE_ACL_DATA, 19, 92, 0, 0};
121 int length = strlen(payload);
122 preamble[3] = length & 0xFF;
123 preamble[4] = (length >> 8) & 0xFF;
124
125 ALOGD("%s writing", __func__);
126 TEMP_FAILURE_RETRY(write(fake_uart_, preamble, sizeof(preamble)));
127 TEMP_FAILURE_RETRY(write(fake_uart_, payload, strlen(payload)));
128
129 ALOGD("%s waiting", __func__);
130 std::mutex mutex;
131 std::condition_variable done;
132 EXPECT_CALL(acl_cb_, Call(HidlVecMatches(preamble + 1, sizeof(preamble) - 1,
133 payload)))
134 .WillOnce(Notify(&mutex, &done));
135
136 // Fail if it takes longer than 100 ms.
137 auto timeout_time =
138 std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
139 {
140 std::unique_lock<std::mutex> lock(mutex);
141 done.wait_until(lock, timeout_time);
142 }
143 }
144
WriteAndExpectInboundScoData(char * payload)145 void WriteAndExpectInboundScoData(char* payload) {
146 // h4 type[1] + handle[2] + size[1]
147 char preamble[4] = {HCI_PACKET_TYPE_SCO_DATA, 20, 17, 0};
148 preamble[3] = strlen(payload) & 0xFF;
149
150 ALOGD("%s writing", __func__);
151 TEMP_FAILURE_RETRY(write(fake_uart_, preamble, sizeof(preamble)));
152 TEMP_FAILURE_RETRY(write(fake_uart_, payload, strlen(payload)));
153
154 ALOGD("%s waiting", __func__);
155 std::mutex mutex;
156 std::condition_variable done;
157 EXPECT_CALL(sco_cb_, Call(HidlVecMatches(preamble + 1, sizeof(preamble) - 1,
158 payload)))
159 .WillOnce(Notify(&mutex, &done));
160
161 // Fail if it takes longer than 100 ms.
162 auto timeout_time =
163 std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
164 {
165 std::unique_lock<std::mutex> lock(mutex);
166 done.wait_until(lock, timeout_time);
167 }
168 }
169
WriteAndExpectInboundEvent(char * payload)170 void WriteAndExpectInboundEvent(char* payload) {
171 // h4 type[1] + event_code[1] + size[1]
172 char preamble[3] = {HCI_PACKET_TYPE_EVENT, 9, 0};
173 preamble[2] = strlen(payload) & 0xFF;
174 ALOGD("%s writing", __func__);
175 TEMP_FAILURE_RETRY(write(fake_uart_, preamble, sizeof(preamble)));
176 TEMP_FAILURE_RETRY(write(fake_uart_, payload, strlen(payload)));
177
178 ALOGD("%s waiting", __func__);
179 std::mutex mutex;
180 std::condition_variable done;
181 EXPECT_CALL(event_cb_, Call(HidlVecMatches(preamble + 1,
182 sizeof(preamble) - 1, payload)))
183 .WillOnce(Notify(&mutex, &done));
184
185 {
186 std::unique_lock<std::mutex> lock(mutex);
187 done.wait(lock);
188 }
189 }
190
WriteAndExpectInboundIsoData(char * payload)191 void WriteAndExpectInboundIsoData(char* payload) {
192 // h4 type[1] + handle[2] + size[1]
193 char preamble[4] = {HCI_PACKET_TYPE_ISO_DATA, 20, 17, 0};
194 preamble[3] = strlen(payload) & 0xFF;
195
196 ALOGD("%s writing", __func__);
197 TEMP_FAILURE_RETRY(write(fake_uart_, preamble, sizeof(preamble)));
198 TEMP_FAILURE_RETRY(write(fake_uart_, payload, strlen(payload)));
199
200 ALOGD("%s waiting", __func__);
201 std::mutex mutex;
202 std::condition_variable done;
203 EXPECT_CALL(iso_cb_, Call(HidlVecMatches(preamble + 1, sizeof(preamble) - 1,
204 payload)))
205 .WillOnce(Notify(&mutex, &done));
206
207 // Fail if it takes longer than 100 ms.
208 auto timeout_time =
209 std::chrono::steady_clock::now() + std::chrono::milliseconds(100);
210 {
211 std::unique_lock<std::mutex> lock(mutex);
212 done.wait_until(lock, timeout_time);
213 }
214 }
215
216 testing::MockFunction<void(const hidl_vec<uint8_t>&)> event_cb_;
217 testing::MockFunction<void(const hidl_vec<uint8_t>&)> acl_cb_;
218 testing::MockFunction<void(const hidl_vec<uint8_t>&)> sco_cb_;
219 testing::MockFunction<void(const hidl_vec<uint8_t>&)> iso_cb_;
220 async::AsyncFdWatcher fd_watcher_;
221 H4Protocol* protocol_;
222 int fake_uart_;
223 };
224
225 // Test sending data sends correct data onto the UART
TEST_F(H4ProtocolTest,TestSends)226 TEST_F(H4ProtocolTest, TestSends) {
227 SendAndReadUartOutbound(HCI_PACKET_TYPE_COMMAND, sample_data1);
228 SendAndReadUartOutbound(HCI_PACKET_TYPE_ACL_DATA, sample_data2);
229 SendAndReadUartOutbound(HCI_PACKET_TYPE_SCO_DATA, sample_data3);
230 SendAndReadUartOutbound(HCI_PACKET_TYPE_ISO_DATA, sample_data4);
231 }
232
233 // Ensure we properly parse data coming from the UART
TEST_F(H4ProtocolTest,TestReads)234 TEST_F(H4ProtocolTest, TestReads) {
235 WriteAndExpectInboundAclData(acl_data);
236 WriteAndExpectInboundScoData(sco_data);
237 WriteAndExpectInboundEvent(event_data);
238 WriteAndExpectInboundIsoData(iso_data);
239 }
240
241 } // namespace implementation
242 } // namespace V1_0
243 } // namespace bluetooth
244 } // namespace hardware
245 } // namespace android
246