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