• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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