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