1 /*
2 * Copyright 2022 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 "btif/include/btif_hh.h"
18
19 #include <gtest/gtest.h>
20
21 #include <algorithm>
22 #include <array>
23 #include <future>
24 #include <vector>
25
26 #include "bta/hh/bta_hh_int.h"
27 #include "bta/include/bta_ag_api.h"
28 #include "bta/include/bta_hh_api.h"
29 #include "btcore/include/module.h"
30 #include "btif/include/btif_api.h"
31 #include "btif/include/stack_manager.h"
32 #include "include/hardware/bt_hh.h"
33 #include "test/common/mock_functions.h"
34 #include "test/mock/mock_osi_allocator.h"
35
36 using namespace std::chrono_literals;
37
38 void set_hal_cbacks(bt_callbacks_t* callbacks);
39
40 uint8_t appl_trace_level = BT_TRACE_LEVEL_DEBUG;
41 uint8_t btif_trace_level = BT_TRACE_LEVEL_DEBUG;
42 uint8_t btu_trace_level = BT_TRACE_LEVEL_DEBUG;
43
44 module_t bt_utils_module;
45 module_t gd_controller_module;
46 module_t gd_idle_module;
47 module_t gd_shim_module;
48 module_t osi_module;
49
50 const tBTA_AG_RES_DATA tBTA_AG_RES_DATA::kEmpty = {};
51
52 extern void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data);
53 extern const bthh_interface_t* btif_hh_get_interface();
54
55 namespace test {
56 namespace mock {
57 extern bool bluetooth_shim_is_gd_stack_started_up;
58 }
59 } // namespace test
60
61 #if __GLIBC__
strlcpy(char * dst,const char * src,size_t siz)62 size_t strlcpy(char* dst, const char* src, size_t siz) {
63 char* d = dst;
64 const char* s = src;
65 size_t n = siz;
66
67 /* Copy as many bytes as will fit */
68 if (n != 0) {
69 while (--n != 0) {
70 if ((*d++ = *s++) == '\0') break;
71 }
72 }
73
74 /* Not enough room in dst, add NUL and traverse rest of src */
75 if (n == 0) {
76 if (siz != 0) *d = '\0'; /* NUL-terminate dst */
77 while (*s++)
78 ;
79 }
80
81 return (s - src - 1); /* count does not include NUL */
82 }
83
gettid(void)84 pid_t gettid(void) throw() { return syscall(SYS_gettid); }
85 #endif
86
87 namespace {
88 std::array<uint8_t, 32> data32 = {
89 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
90 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
91 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
92 };
93
94 const RawAddress kDeviceAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
95 const uint16_t kHhHandle = 123;
96
97 // Callback parameters grouped into a structure
98 struct get_report_cb_t {
99 RawAddress raw_address;
100 bthh_status_t status;
101 std::vector<uint8_t> data;
102 } get_report_cb_;
103
104 // Globals allow usage within function pointers
105 std::promise<bt_cb_thread_evt> g_thread_evt_promise;
106 std::promise<bt_status_t> g_status_promise;
107 std::promise<get_report_cb_t> g_bthh_callbacks_get_report_promise;
108
109 } // namespace
110
111 bt_callbacks_t bt_callbacks = {
112 .size = sizeof(bt_callbacks_t),
113 .adapter_state_changed_cb = nullptr, // adapter_state_changed_callback
114 .adapter_properties_cb = nullptr, // adapter_properties_callback
115 .remote_device_properties_cb =
116 nullptr, // remote_device_properties_callback
117 .device_found_cb = nullptr, // device_found_callback
118 .discovery_state_changed_cb = nullptr, // discovery_state_changed_callback
119 .pin_request_cb = nullptr, // pin_request_callback
120 .ssp_request_cb = nullptr, // ssp_request_callback
121 .bond_state_changed_cb = nullptr, // bond_state_changed_callback
122 .address_consolidate_cb = nullptr, // address_consolidate_callback
123 .le_address_associate_cb = nullptr, // le_address_associate_callback
124 .acl_state_changed_cb = nullptr, // acl_state_changed_callback
125 .thread_evt_cb = nullptr, // callback_thread_event
126 .dut_mode_recv_cb = nullptr, // dut_mode_recv_callback
127 .le_test_mode_cb = nullptr, // le_test_mode_callback
128 .energy_info_cb = nullptr, // energy_info_callback
129 .link_quality_report_cb = nullptr, // link_quality_report_callback
130 .generate_local_oob_data_cb = nullptr, // generate_local_oob_data_callback
131 .switch_buffer_size_cb = nullptr, // switch_buffer_size_callback
132 .switch_codec_cb = nullptr, // switch_codec_callback
133 };
134
135 bthh_callbacks_t bthh_callbacks = {
136 .size = sizeof(bthh_callbacks_t),
137 .connection_state_cb = nullptr, // bthh_connection_state_callback
138 .hid_info_cb = nullptr, // bthh_hid_info_callback
139 .protocol_mode_cb = nullptr, // bthh_protocol_mode_callback
140 .idle_time_cb = nullptr, // bthh_idle_time_callback
141 .get_report_cb = nullptr, // bthh_get_report_callback
142 .virtual_unplug_cb = nullptr, // bthh_virtual_unplug_callback
143 .handshake_cb = nullptr, // bthh_handshake_callback
144 };
145
146 class BtifHhWithMockTest : public ::testing::Test {
147 protected:
SetUp()148 void SetUp() override {
149 reset_mock_function_count_map();
150 test::mock::osi_allocator::osi_malloc.body = [](size_t size) {
151 return malloc(size);
152 };
153 test::mock::osi_allocator::osi_calloc.body = [](size_t size) {
154 return calloc(1UL, size);
155 };
156 test::mock::osi_allocator::osi_free.body = [](void* ptr) { free(ptr); };
157 test::mock::osi_allocator::osi_free_and_reset.body = [](void** ptr) {
158 free(*ptr);
159 *ptr = nullptr;
160 };
161 }
162
TearDown()163 void TearDown() override {
164 test::mock::osi_allocator::osi_malloc = {};
165 test::mock::osi_allocator::osi_calloc = {};
166 test::mock::osi_allocator::osi_free = {};
167 test::mock::osi_allocator::osi_free_and_reset = {};
168 }
169 };
170
171 class BtifHhWithHalCallbacksTest : public BtifHhWithMockTest {
172 protected:
SetUp()173 void SetUp() override {
174 bluetooth::common::InitFlags::SetAllForTesting();
175 BtifHhWithMockTest::SetUp();
176 g_thread_evt_promise = std::promise<bt_cb_thread_evt>();
177 auto future = g_thread_evt_promise.get_future();
178 bt_callbacks.thread_evt_cb = [](bt_cb_thread_evt evt) {
179 g_thread_evt_promise.set_value(evt);
180 };
181 set_hal_cbacks(&bt_callbacks);
182 // Start the jni callback thread
183 ASSERT_EQ(BT_STATUS_SUCCESS, btif_init_bluetooth());
184 ASSERT_EQ(std::future_status::ready, future.wait_for(2s));
185 ASSERT_EQ(ASSOCIATE_JVM, future.get());
186
187 bt_callbacks.thread_evt_cb = [](bt_cb_thread_evt evt) {};
188 }
189
TearDown()190 void TearDown() override {
191 g_thread_evt_promise = std::promise<bt_cb_thread_evt>();
192 auto future = g_thread_evt_promise.get_future();
193 bt_callbacks.thread_evt_cb = [](bt_cb_thread_evt evt) {
194 g_thread_evt_promise.set_value(evt);
195 };
196 // Shutdown the jni callback thread
197 ASSERT_EQ(BT_STATUS_SUCCESS, btif_cleanup_bluetooth());
198 ASSERT_EQ(std::future_status::ready, future.wait_for(2s));
199 ASSERT_EQ(DISASSOCIATE_JVM, future.get());
200
201 bt_callbacks.thread_evt_cb = [](bt_cb_thread_evt evt) {};
202 BtifHhWithMockTest::TearDown();
203 }
204 };
205
206 class BtifHhAdapterReady : public BtifHhWithHalCallbacksTest {
207 protected:
SetUp()208 void SetUp() override {
209 BtifHhWithHalCallbacksTest::SetUp();
210 test::mock::bluetooth_shim_is_gd_stack_started_up = true;
211 ASSERT_EQ(BT_STATUS_SUCCESS,
212 btif_hh_get_interface()->init(&bthh_callbacks));
213 }
214
TearDown()215 void TearDown() override {
216 test::mock::bluetooth_shim_is_gd_stack_started_up = false;
217 BtifHhWithHalCallbacksTest::TearDown();
218 }
219 };
220
221 class BtifHhWithDevice : public BtifHhAdapterReady {
222 protected:
SetUp()223 void SetUp() override {
224 BtifHhAdapterReady::SetUp();
225
226 // Short circuit a connected device
227 btif_hh_cb.devices[0].bd_addr = kDeviceAddress;
228 btif_hh_cb.devices[0].dev_status = BTHH_CONN_STATE_CONNECTED;
229 btif_hh_cb.devices[0].dev_handle = kHhHandle;
230 }
231
TearDown()232 void TearDown() override { BtifHhAdapterReady::TearDown(); }
233 };
234
TEST_F(BtifHhAdapterReady,lifecycle)235 TEST_F(BtifHhAdapterReady, lifecycle) {}
236
TEST_F(BtifHhWithDevice,BTA_HH_GET_RPT_EVT)237 TEST_F(BtifHhWithDevice, BTA_HH_GET_RPT_EVT) {
238 tBTA_HH data = {
239 .hs_data =
240 {
241 .status = BTA_HH_OK,
242 .handle = kHhHandle,
243 .rsp_data =
244 {
245 .p_rpt_data = static_cast<BT_HDR*>(
246 osi_calloc(data32.size() + sizeof(BT_HDR))),
247 },
248 },
249 };
250
251 // Fill out the deep copy data
252 data.hs_data.rsp_data.p_rpt_data->len = static_cast<uint16_t>(data32.size());
253 std::copy(data32.begin(), data32.begin() + data32.size(),
254 reinterpret_cast<uint8_t*>((data.hs_data.rsp_data.p_rpt_data + 1)));
255
256 g_bthh_callbacks_get_report_promise = std::promise<get_report_cb_t>();
257 auto future = g_bthh_callbacks_get_report_promise.get_future();
258 bthh_callbacks.get_report_cb = [](RawAddress* bd_addr,
259 bthh_status_t hh_status, uint8_t* rpt_data,
260 int rpt_size) {
261 get_report_cb_t report = {
262 .raw_address = *bd_addr,
263 .status = hh_status,
264 .data = std::vector<uint8_t>(),
265 };
266 report.data.assign(rpt_data, rpt_data + rpt_size),
267 g_bthh_callbacks_get_report_promise.set_value(report);
268 };
269
270 bte_hh_evt(BTA_HH_GET_RPT_EVT, &data);
271 osi_free(data.hs_data.rsp_data.p_rpt_data);
272
273 ASSERT_EQ(std::future_status::ready, future.wait_for(2s));
274 auto report = future.get();
275
276 // Verify data was delivered
277 ASSERT_STREQ(kDeviceAddress.ToString().c_str(),
278 report.raw_address.ToString().c_str());
279 ASSERT_EQ(BTHH_OK, report.status);
280 int i = 0;
281 for (const auto& data : data32) {
282 ASSERT_EQ(data, report.data[i++]);
283 }
284 }
285