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/include/bta_ag_api.h"
27 #include "bta/include/bta_hh_api.h"
28 #include "btcore/include/module.h"
29 #include "common/init_flags.h"
30 #include "include/hardware/bt_hh.h"
31 #include "test/common/core_interface.h"
32 #include "test/common/mock_functions.h"
33 
34 using namespace std::chrono_literals;
35 
36 namespace bluetooth::testing {
37 void set_hal_cbacks(bt_callbacks_t* callbacks);
38 }  // namespace bluetooth::testing
39 
40 // Used the legacy stack manager
41 module_t bt_utils_module;
42 module_t gd_controller_module;
43 module_t gd_shim_module;
44 module_t osi_module;
45 module_t rust_module;
46 
47 const tBTA_AG_RES_DATA tBTA_AG_RES_DATA::kEmpty = {};
48 
49 const bthh_interface_t* btif_hh_get_interface();
50 bt_status_t btif_hh_connect(const tAclLinkSpec& link_spec);
51 bt_status_t btif_hh_virtual_unplug(const tAclLinkSpec& link_spec);
52 
53 namespace bluetooth {
54 namespace legacy {
55 namespace testing {
56 
57 void bte_hh_evt(tBTA_HH_EVT event, tBTA_HH* p_data);
58 
59 }  // namespace testing
60 }  // namespace legacy
61 }  // namespace bluetooth
62 
63 namespace test {
64 namespace mock {
65 extern bool bluetooth_shim_is_gd_stack_started_up;
66 }
67 }  // namespace test
68 
69 namespace {
70 std::array<uint8_t, 32> data32 = {
71     0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
72     0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
73     0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
74 };
75 
76 const RawAddress kDeviceAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
77 const RawAddress kDeviceAddressConnecting({0x66, 0x55, 0x44, 0x33, 0x22, 0x11});
78 const uint16_t kHhHandle = 123;
79 const tBLE_ADDR_TYPE kDeviceAddrType = BLE_ADDR_PUBLIC;
80 const tBT_TRANSPORT kDeviceTransport = BT_TRANSPORT_AUTO;
81 const tAclLinkSpec kDeviceConnecting = {.addrt.type = kDeviceAddrType,
82                                         .addrt.bda = kDeviceAddressConnecting,
83                                         .transport = kDeviceTransport};
84 // Callback parameters grouped into a structure
85 struct get_report_cb_t {
86   RawAddress raw_address;
87   bthh_status_t status;
88   std::vector<uint8_t> data;
89 } get_report_cb_;
90 
91 struct connection_state_cb_t {
92   RawAddress raw_address;
93   bthh_connection_state_t state;
94 };
95 
96 // Globals allow usage within function pointers
97 std::promise<bt_cb_thread_evt> g_thread_evt_promise;
98 std::promise<bt_status_t> g_status_promise;
99 std::promise<get_report_cb_t> g_bthh_callbacks_get_report_promise;
100 std::promise<connection_state_cb_t> g_bthh_connection_state_promise;
101 
102 }  // namespace
103 
104 bt_callbacks_t bt_callbacks = {
105     .size = sizeof(bt_callbacks_t),
106     .adapter_state_changed_cb = nullptr,  // adapter_state_changed_callback
107     .adapter_properties_cb = nullptr,     // adapter_properties_callback
108     .remote_device_properties_cb =
109         nullptr,                            // remote_device_properties_callback
110     .device_found_cb = nullptr,             // device_found_callback
111     .discovery_state_changed_cb = nullptr,  // discovery_state_changed_callback
112     .pin_request_cb = nullptr,              // pin_request_callback
113     .ssp_request_cb = nullptr,              // ssp_request_callback
114     .bond_state_changed_cb = nullptr,       // bond_state_changed_callback
115     .address_consolidate_cb = nullptr,      // address_consolidate_callback
116     .le_address_associate_cb = nullptr,     // le_address_associate_callback
117     .acl_state_changed_cb = nullptr,        // acl_state_changed_callback
118     .thread_evt_cb = nullptr,               // callback_thread_event
119     .dut_mode_recv_cb = nullptr,            // dut_mode_recv_callback
120     .le_test_mode_cb = nullptr,             // le_test_mode_callback
121     .energy_info_cb = nullptr,              // energy_info_callback
122     .link_quality_report_cb = nullptr,      // link_quality_report_callback
123     .generate_local_oob_data_cb = nullptr,  // generate_local_oob_data_callback
124     .switch_buffer_size_cb = nullptr,       // switch_buffer_size_callback
125     .switch_codec_cb = nullptr,             // switch_codec_callback
126     .le_rand_cb = nullptr,                  // le_rand_callback
127 };
128 
129 bthh_callbacks_t bthh_callbacks = {
130     .size = sizeof(bthh_callbacks_t),
131     .connection_state_cb = nullptr,  // bthh_connection_state_callback
132     .hid_info_cb = nullptr,          // bthh_hid_info_callback
133     .protocol_mode_cb = nullptr,     // bthh_protocol_mode_callback
134     .idle_time_cb = nullptr,         // bthh_idle_time_callback
135     .get_report_cb = nullptr,        // bthh_get_report_callback
136     .virtual_unplug_cb = nullptr,    // bthh_virtual_unplug_callback
137     .handshake_cb = nullptr,         // bthh_handshake_callback
138 };
139 
140 class BtifHhWithMockTest : public ::testing::Test {
141  protected:
SetUp()142   void SetUp() override { reset_mock_function_count_map(); }
143 
TearDown()144   void TearDown() override {}
145 };
146 
147 class BtifHhWithHalCallbacksTest : public BtifHhWithMockTest {
148  protected:
SetUp()149   void SetUp() override {
150     BtifHhWithMockTest::SetUp();
151     bluetooth::common::InitFlags::SetAllForTesting();
152     g_thread_evt_promise = std::promise<bt_cb_thread_evt>();
153     auto future = g_thread_evt_promise.get_future();
154     bt_callbacks.thread_evt_cb = [](bt_cb_thread_evt evt) {
155       g_thread_evt_promise.set_value(evt);
156     };
157     bluetooth::testing::set_hal_cbacks(&bt_callbacks);
158     // Start the jni callback thread
159     InitializeCoreInterface();
160     ASSERT_EQ(std::future_status::ready, future.wait_for(2s));
161     ASSERT_EQ(ASSOCIATE_JVM, future.get());
162 
163     bt_callbacks.thread_evt_cb = [](bt_cb_thread_evt /* evt */) {};
164   }
165 
TearDown()166   void TearDown() override {
167     g_thread_evt_promise = std::promise<bt_cb_thread_evt>();
168     auto future = g_thread_evt_promise.get_future();
169     bt_callbacks.thread_evt_cb = [](bt_cb_thread_evt evt) {
170       g_thread_evt_promise.set_value(evt);
171     };
172     CleanCoreInterface();
173     ASSERT_EQ(std::future_status::ready, future.wait_for(2s));
174     ASSERT_EQ(DISASSOCIATE_JVM, future.get());
175 
176     bt_callbacks.thread_evt_cb = [](bt_cb_thread_evt /* evt */) {};
177     BtifHhWithMockTest::TearDown();
178   }
179 };
180 
181 class BtifHhAdapterReady : public BtifHhWithHalCallbacksTest {
182  protected:
SetUp()183   void SetUp() override {
184     BtifHhWithHalCallbacksTest::SetUp();
185     test::mock::bluetooth_shim_is_gd_stack_started_up = true;
186     ASSERT_EQ(BT_STATUS_SUCCESS,
187               btif_hh_get_interface()->init(&bthh_callbacks));
188   }
189 
TearDown()190   void TearDown() override {
191     test::mock::bluetooth_shim_is_gd_stack_started_up = false;
192     BtifHhWithHalCallbacksTest::TearDown();
193   }
194 };
195 
196 class BtifHhWithDevice : public BtifHhAdapterReady {
197  protected:
SetUp()198   void SetUp() override {
199     BtifHhAdapterReady::SetUp();
200 
201     // Short circuit a connected device
202     btif_hh_cb.devices[0].link_spec.addrt.bda = kDeviceAddress;
203     btif_hh_cb.devices[0].link_spec.addrt.type = kDeviceAddrType;
204     btif_hh_cb.devices[0].link_spec.transport = kDeviceTransport;
205     btif_hh_cb.devices[0].dev_status = BTHH_CONN_STATE_CONNECTED;
206     btif_hh_cb.devices[0].dev_handle = kHhHandle;
207   }
208 
TearDown()209   void TearDown() override { BtifHhAdapterReady::TearDown(); }
210 };
211 
TEST_F(BtifHhAdapterReady,lifecycle)212 TEST_F(BtifHhAdapterReady, lifecycle) {}
213 
214 static uint8_t report_data[sizeof(BT_HDR) + data32.size()];
215 
TEST_F(BtifHhWithDevice,BTA_HH_GET_RPT_EVT)216 TEST_F(BtifHhWithDevice, BTA_HH_GET_RPT_EVT) {
217   tBTA_HH data = {
218       .hs_data =
219           {
220               .status = BTA_HH_OK,
221               .handle = kHhHandle,
222               .rsp_data =
223                   {
224                       .p_rpt_data = reinterpret_cast<BT_HDR*>(report_data),
225                   },
226           },
227   };
228 
229   // Fill out the deep copy data
230   data.hs_data.rsp_data.p_rpt_data->len = static_cast<uint16_t>(data32.size());
231   std::copy(data32.begin(), data32.begin() + data32.size(),
232             reinterpret_cast<uint8_t*>((data.hs_data.rsp_data.p_rpt_data + 1)));
233 
234   g_bthh_callbacks_get_report_promise = std::promise<get_report_cb_t>();
235   auto future = g_bthh_callbacks_get_report_promise.get_future();
236   bthh_callbacks.get_report_cb = [](RawAddress* bd_addr,
237                                     tBLE_ADDR_TYPE /* addr_type */,
238                                     tBT_TRANSPORT /* transport */,
239                                     bthh_status_t hh_status, uint8_t* rpt_data,
240                                     int rpt_size) {
241     get_report_cb_t report = {
242         .raw_address = *bd_addr,
243         .status = hh_status,
244         .data = std::vector<uint8_t>(),
245     };
246     report.data.assign(rpt_data, rpt_data + rpt_size),
247         g_bthh_callbacks_get_report_promise.set_value(report);
248   };
249 
250   bluetooth::legacy::testing::bte_hh_evt(BTA_HH_GET_RPT_EVT, &data);
251 
252   ASSERT_EQ(std::future_status::ready, future.wait_for(2s));
253   auto report = future.get();
254 
255   // Verify data was delivered
256   ASSERT_STREQ(kDeviceAddress.ToString().c_str(),
257                report.raw_address.ToString().c_str());
258   ASSERT_EQ(BTHH_OK, report.status);
259   int i = 0;
260   for (const auto& data : data32) {
261     ASSERT_EQ(data, report.data[i++]);
262   }
263 }
264 
265 class BtifHHVirtualUnplugTest : public BtifHhAdapterReady {
266  protected:
SetUp()267   void SetUp() override {
268     BtifHhAdapterReady::SetUp();
269     bthh_callbacks.connection_state_cb = [](RawAddress* bd_addr,
270                                             tBLE_ADDR_TYPE /* addr_type */,
271                                             tBT_TRANSPORT /* transport */,
272                                             bthh_connection_state_t state) {
273       connection_state_cb_t connection_state = {
274         .raw_address = *bd_addr,
275         .state = state,
276       };
277       g_bthh_connection_state_promise.set_value(connection_state);
278     };
279   }
280 
TearDown()281   void TearDown() override {
282     bthh_callbacks.connection_state_cb =
283         [](RawAddress* /* bd_addr */, tBLE_ADDR_TYPE /* addr_type */,
284            tBT_TRANSPORT /* transport */,
285            bthh_connection_state_t /* state */) {};
286     BtifHhAdapterReady::TearDown();
287   }
288 };
289 
TEST_F(BtifHHVirtualUnplugTest,test_btif_hh_virtual_unplug_device_not_open)290 TEST_F(BtifHHVirtualUnplugTest, test_btif_hh_virtual_unplug_device_not_open) {
291   g_bthh_connection_state_promise = std::promise<connection_state_cb_t>();
292 
293   auto future = g_bthh_connection_state_promise.get_future();
294 
295   /* Make device in connecting state */
296   ASSERT_EQ(btif_hh_connect(kDeviceConnecting), BT_STATUS_SUCCESS);
297 
298   ASSERT_EQ(std::future_status::ready, future.wait_for(2s));
299 
300   auto res = future.get();
301   ASSERT_STREQ(kDeviceAddressConnecting.ToString().c_str(),
302                res.raw_address.ToString().c_str());
303   ASSERT_EQ(BTHH_CONN_STATE_CONNECTING, res.state);
304 
305 
306   g_bthh_connection_state_promise = std::promise<connection_state_cb_t>();
307   future = g_bthh_connection_state_promise.get_future();
308   btif_hh_virtual_unplug(kDeviceConnecting);
309 
310   ASSERT_EQ(std::future_status::ready, future.wait_for(2s));
311 
312   // Verify data was delivered
313   res = future.get();
314   ASSERT_STREQ(kDeviceAddressConnecting.ToString().c_str(),
315                res.raw_address.ToString().c_str());
316   ASSERT_EQ(BTHH_CONN_STATE_DISCONNECTED, res.state);
317 }
318