1 /*
2  * Copyright 2020 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_headless"
18 
19 #include "test/headless/headless.h"
20 
21 #include <bluetooth/log.h>
22 #include <dlfcn.h>  //  dlopen
23 
24 #include <iostream>
25 #include <map>
26 #include <memory>
27 
28 #include "include/hardware/bluetooth.h"
29 #include "test/headless/bt_stack_info.h"
30 #include "test/headless/interface.h"
31 #include "test/headless/log.h"
32 #include "test/headless/messenger.h"
33 #include "types/raw_address.h"
34 
35 // TODO(b/369381361) Enfore -Wmissing-prototypes
36 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
37 
38 //
39 // Aggregate disparate variables from callback API into unified single structure
40 //
41 extern bt_interface_t bluetoothInterface;
42 
43 using namespace bluetooth::test::headless;
44 using namespace bluetooth;
45 
46 namespace {
47 
48 constexpr char kHeadlessIcon[] = "��";
49 
50 std::map<const std::string, std::list<callback_function_t>> interface_api_callback_map_;
51 
52 }  // namespace
53 
headless_add_callback(const std::string interface_name,callback_function_t function)54 void headless_add_callback(const std::string interface_name, callback_function_t function) {
55   if (interface_api_callback_map_.find(interface_name) == interface_api_callback_map_.end()) {
56     interface_api_callback_map_.emplace(interface_name, std::list<callback_function_t>());
57   }
58   interface_api_callback_map_[interface_name].push_back(function);
59 }
60 
headless_remove_callback(const std::string interface_name)61 void headless_remove_callback(const std::string interface_name) {
62   if (interface_api_callback_map_.find(interface_name) == interface_api_callback_map_.end()) {
63     log::fatal("No callbacks registered for interface:{}", interface_name);
64   }
65   interface_api_callback_map_.erase(interface_name);
66 }
67 
68 std::mutex adapter_state_mutex_;
69 std::condition_variable adapter_state_cv_;
70 bt_state_t bt_state_{BT_STATE_OFF};
71 
adapter_state_changed(bt_state_t state)72 void adapter_state_changed(bt_state_t state) {
73   std::unique_lock<std::mutex> lck(adapter_state_mutex_);
74   bt_state_ = state;
75   adapter_state_cv_.notify_all();
76 }
adapter_properties(bt_status_t status,int num_properties,::bt_property_t * properties)77 void adapter_properties(bt_status_t status, int num_properties, ::bt_property_t* properties) {
78   const size_t num_callbacks = interface_api_callback_map_.size();
79   auto callback_list = interface_api_callback_map_.find(__func__);
80   if (callback_list != interface_api_callback_map_.end()) {
81     for (auto callback : callback_list->second) {
82       adapter_properties_params_t params(status, num_properties, properties);
83       (callback)(&params);
84     }
85   }
86   log::info("num_callbacks:{} status:{} num_properties:{} properties:{}", num_callbacks,
87             bt_status_text(status), num_properties, std::format_ptr(properties));
88 }
89 
remote_device_properties(bt_status_t status,RawAddress * bd_addr,int num_properties,::bt_property_t * properties)90 void remote_device_properties(bt_status_t status, RawAddress* bd_addr, int num_properties,
91                               ::bt_property_t* properties) {
92   log::assert_that(bd_addr != nullptr, "assert failed: bd_addr != nullptr");
93   const size_t num_callbacks = interface_api_callback_map_.size();
94   auto callback_list = interface_api_callback_map_.find(__func__);
95   if (callback_list != interface_api_callback_map_.end()) {
96     RawAddress raw_address = (bd_addr != nullptr) ? *bd_addr : RawAddress::kEmpty;
97     for (auto callback : callback_list->second) {
98       remote_device_properties_params_t params(status, raw_address, num_properties, properties);
99       (callback)(&params);
100     }
101   }
102   log::info("num_callbacks:{} status:{} device:{} num_properties:{} properties:{}", num_callbacks,
103             bt_status_text(status), STR(*bd_addr), num_properties, std::format_ptr(properties));
104 }
105 
106 // Aggregate disparate variables from callback API into unified single structure
device_found(int num_properties,::bt_property_t * properties)107 void device_found(int num_properties, ::bt_property_t* properties) {
108   [[maybe_unused]] const size_t num_callbacks = interface_api_callback_map_.size();
109   auto callback_list = interface_api_callback_map_.find(__func__);
110   if (callback_list != interface_api_callback_map_.end()) {
111     for (auto callback : callback_list->second) {
112       device_found_params_t params(num_properties, properties);
113       (callback)(&params);
114     }
115   }
116   log::info("Device found callback: num_properties:{} properties:{}", num_properties,
117             std::format_ptr(properties));
118 }
119 
discovery_state_changed(bt_discovery_state_t state)120 void discovery_state_changed(bt_discovery_state_t state) {
121   auto callback_list = interface_api_callback_map_.find(__func__);
122   if (callback_list != interface_api_callback_map_.end()) {
123     for (auto callback : callback_list->second) {
124       discovery_state_changed_params_t params(state);
125       (callback)(&params);
126     }
127   }
128 }
129 
130 /** Bluetooth Legacy PinKey Request callback */
pin_request(RawAddress * remote_bd_addr,bt_bdname_t * bd_name,uint32_t cod,bool min_16_digit)131 void pin_request([[maybe_unused]] RawAddress* remote_bd_addr, [[maybe_unused]] bt_bdname_t* bd_name,
132                  [[maybe_unused]] uint32_t cod, [[maybe_unused]] bool min_16_digit) {
133   log::info("");
134 }
135 
ssp_request(RawAddress * remote_bd_addr,bt_ssp_variant_t pairing_variant,uint32_t pass_key)136 void ssp_request([[maybe_unused]] RawAddress* remote_bd_addr,
137                  [[maybe_unused]] bt_ssp_variant_t pairing_variant,
138                  [[maybe_unused]] uint32_t pass_key) {
139   log::info("");
140 }
141 
142 /** Bluetooth Bond state changed callback */
143 /* Invoked in response to create_bond, cancel_bond or remove_bond */
bond_state_changed(bt_status_t status,RawAddress * remote_bd_addr,bt_bond_state_t state,int fail_reason)144 void bond_state_changed([[maybe_unused]] bt_status_t status,
145                         [[maybe_unused]] RawAddress* remote_bd_addr,
146                         [[maybe_unused]] bt_bond_state_t state, [[maybe_unused]] int fail_reason) {
147   log::info("");
148 }
149 
address_consolidate(RawAddress * main_bd_addr,RawAddress * secondary_bd_addr)150 void address_consolidate([[maybe_unused]] RawAddress* main_bd_addr,
151                          [[maybe_unused]] RawAddress* secondary_bd_addr) {
152   log::info("");
153 }
154 
le_address_associate(RawAddress * main_bd_addr,RawAddress * secondary_bd_addr,uint8_t identity_address_type)155 void le_address_associate([[maybe_unused]] RawAddress* main_bd_addr,
156                           [[maybe_unused]] RawAddress* secondary_bd_addr,
157                           [[maybe_unused]] uint8_t identity_address_type) {
158   log::info("");
159 }
160 
161 /** Bluetooth ACL connection state changed callback */
acl_state_changed(bt_status_t status,RawAddress * remote_bd_addr,bt_acl_state_t state,int transport_link_type,bt_hci_error_code_t hci_reason,bt_conn_direction_t direction,uint16_t acl_handle)162 void acl_state_changed(bt_status_t status, RawAddress* remote_bd_addr, bt_acl_state_t state,
163                        int transport_link_type, bt_hci_error_code_t hci_reason,
164                        bt_conn_direction_t direction, uint16_t acl_handle) {
165   log::assert_that(remote_bd_addr != nullptr, "assert failed: remote_bd_addr != nullptr");
166   const size_t num_callbacks = interface_api_callback_map_.size();
167   auto callback_list = interface_api_callback_map_.find(__func__);
168   if (callback_list != interface_api_callback_map_.end()) {
169     RawAddress raw_address(*remote_bd_addr);
170     for (auto callback : callback_list->second) {
171       acl_state_changed_params_t params(status, raw_address, state, transport_link_type, hci_reason,
172                                         direction, acl_handle);
173       (callback)(&params);
174     }
175   }
176   log::info("num_callbacks:{} status:{} device:{} state:{}", num_callbacks, bt_status_text(status),
177             remote_bd_addr->ToString(), (state) ? "disconnected" : "connected");
178 }
179 
180 /** Bluetooth Link Quality Report callback */
link_quality_report(uint64_t timestamp,int report_id,int rssi,int snr,int retransmission_count,int packets_not_receive_count,int negative_acknowledgement_count)181 void link_quality_report([[maybe_unused]] uint64_t timestamp, [[maybe_unused]] int report_id,
182                          [[maybe_unused]] int rssi, [[maybe_unused]] int snr,
183                          [[maybe_unused]] int retransmission_count,
184                          [[maybe_unused]] int packets_not_receive_count,
185                          [[maybe_unused]] int negative_acknowledgement_count) {
186   log::info("");
187 }
188 
189 /** Switch buffer size callback */
switch_buffer_size(bool is_low_latency_buffer_size)190 void switch_buffer_size([[maybe_unused]] bool is_low_latency_buffer_size) { log::info(""); }
191 
192 /** Switch codec callback */
switch_codec(bool is_low_latency_buffer_size)193 void switch_codec([[maybe_unused]] bool is_low_latency_buffer_size) { log::info(""); }
194 
thread_event(bt_cb_thread_evt evt)195 void thread_event([[maybe_unused]] bt_cb_thread_evt evt) { log::info(""); }
196 
dut_mode_recv(uint16_t opcode,uint8_t * buf,uint8_t len)197 void dut_mode_recv([[maybe_unused]] uint16_t opcode, [[maybe_unused]] uint8_t* buf,
198                    [[maybe_unused]] uint8_t len) {
199   log::info("");
200 }
201 
le_test_mode(bt_status_t status,uint16_t num_packets)202 void le_test_mode([[maybe_unused]] bt_status_t status, [[maybe_unused]] uint16_t num_packets) {
203   log::info("");
204 }
205 
energy_info(bt_activity_energy_info * energy_info,bt_uid_traffic_t * uid_data)206 void energy_info([[maybe_unused]] bt_activity_energy_info* energy_info,
207                  [[maybe_unused]] bt_uid_traffic_t* uid_data) {
208   log::info("");
209 }
210 
211 bt_callbacks_t bt_callbacks{
212         /** set to sizeof(bt_callbacks_t) */
213         .size = sizeof(bt_callbacks_t),
214         .adapter_state_changed_cb = adapter_state_changed,
215         .adapter_properties_cb = adapter_properties,
216         .remote_device_properties_cb = remote_device_properties,
217         .device_found_cb = device_found,
218         .discovery_state_changed_cb = discovery_state_changed,
219         .pin_request_cb = pin_request,
220         .ssp_request_cb = ssp_request,
221         .bond_state_changed_cb = bond_state_changed,
222         .address_consolidate_cb = address_consolidate,
223         .le_address_associate_cb = le_address_associate,
224         .acl_state_changed_cb = acl_state_changed,
225         .thread_evt_cb = thread_event,
226         .dut_mode_recv_cb = dut_mode_recv,
227         .le_test_mode_cb = le_test_mode,
228         .energy_info_cb = energy_info,
229         .link_quality_report_cb = link_quality_report,
230         .switch_buffer_size_cb = switch_buffer_size,
231         .switch_codec_cb = switch_codec,
232 };
233 // HAL HARDWARE CALLBACKS
234 
235 // OS CALLOUTS
acquire_wake_lock_co(const char * lock_name)236 int acquire_wake_lock_co([[maybe_unused]] const char* lock_name) {
237   log::info("");
238   return 1;
239 }
240 
release_wake_lock_co(const char * lock_name)241 int release_wake_lock_co([[maybe_unused]] const char* lock_name) {
242   log::info("");
243   return 0;
244 }
245 
246 bt_os_callouts_t bt_os_callouts{
247         .size = sizeof(bt_os_callouts_t),
248         .acquire_wake_lock = acquire_wake_lock_co,
249         .release_wake_lock = release_wake_lock_co,
250 };
251 
SetUp()252 void HeadlessStack::SetUp() {
253   log::info("Entry");
254 
255   const bool start_restricted = false;
256   const bool is_common_criteria_mode = false;
257   const int config_compare_result = 0;
258   const bool is_atv = false;
259 
260   int status = bluetoothInterface.init(&bt_callbacks, start_restricted, is_common_criteria_mode,
261                                        config_compare_result, is_atv);
262 
263   if (status == BT_STATUS_SUCCESS) {
264     log::info("Initialized bluetooth callbacks");
265   } else {
266     log::fatal("Failed to initialize Bluetooth stack");
267   }
268 
269   status = bluetoothInterface.set_os_callouts(&bt_os_callouts);
270   if (status == BT_STATUS_SUCCESS) {
271     log::info("Initialized os callouts");
272   } else {
273     log::error("Failed to set up Bluetooth OS callouts");
274   }
275 
276   bluetoothInterface.enable();
277   log::info("HeadlessStack stack has enabled");
278 
279   std::unique_lock<std::mutex> lck(adapter_state_mutex_);
280   while (bt_state_ != BT_STATE_ON) {
281     adapter_state_cv_.wait(lck);
282   }
283   log::info("HeadlessStack stack is operational");
284 
285   bt_stack_info_ = std::make_unique<BtStackInfo>();
286 
287   bluetooth::test::headless::start_messenger();
288 
289   LOG_CONSOLE("%s Headless stack has started up successfully", kHeadlessIcon);
290 }
291 
TearDown()292 void HeadlessStack::TearDown() {
293   bluetooth::test::headless::stop_messenger();
294 
295   log::info("Stack has disabled");
296   int status = bluetoothInterface.disable();
297 
298   log::info("Interface has been disabled status:{}", status);
299 
300   bluetoothInterface.cleanup();
301   log::info("Cleaned up hal bluetooth library");
302 
303   std::unique_lock<std::mutex> lck(adapter_state_mutex_);
304   while (bt_state_ != BT_STATE_OFF) {
305     adapter_state_cv_.wait(lck);
306   }
307   log::info("HeadlessStack stack has exited");
308   LOG_CONSOLE("%s Headless stack has shutdown successfully", kHeadlessIcon);
309 }
310