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 #define LOG_TAG "bt_headless_messenger"
18
19 #include "test/headless/messenger.h"
20
21 #include <condition_variable>
22 #include <deque>
23 #include <memory>
24 #include <mutex>
25
26 #include "test/headless/interface.h"
27 #include "test/headless/log.h"
28
29 // TODO(b/369381361) Enfore -Wmissing-prototypes
30 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
31
32 using namespace bluetooth::test::headless;
33 using namespace std::chrono_literals;
34
35 template <typename T>
36 struct callback_queue_t {
callback_queue_tcallback_queue_t37 callback_queue_t(const std::string name) : name_(name) {}
38 // Must be held with lock
sizecallback_queue_t39 size_t size() const { return callback_queue.size(); }
40
41 private:
42 const std::string name_;
43 std::deque<T> callback_queue;
44
45 public:
Pushcallback_queue_t46 void Push(T elem) { callback_queue.push_back(elem); }
47 // Must be held with lock
Popcallback_queue_t48 T Pop() {
49 T p = callback_queue.front();
50 callback_queue.pop_front();
51 return p;
52 }
53 // Must be held with lock
emptycallback_queue_t54 bool empty() const { return callback_queue.empty(); }
55 };
56
57 struct messenger_t {
58 mutable std::mutex mutex;
59 std::condition_variable cv;
60 callback_queue_t<std::shared_ptr<callback_params_t>> callback_queue =
61 callback_queue_t<std::shared_ptr<callback_params_t>>("callbacks");
Pushmessenger_t62 void Push(std::shared_ptr<callback_params_t> elem) {
63 std::unique_lock<std::mutex> lk(mutex);
64 callback_queue.Push(elem);
65 cv.notify_all();
66 }
67 };
68
69 namespace bluetooth {
70 namespace test {
71 namespace headless {
72 namespace messenger {
73
74 // Called by client to await any callback for the given callbacks
75 messenger_t callback_data_;
76
await_callback(Context & context)77 bool await_callback(Context& context) {
78 std::unique_lock<std::mutex> lk(callback_data_.mutex);
79 while (!callback_data_.callback_queue.empty()) {
80 std::shared_ptr<callback_params_t> cb = callback_data_.callback_queue.Pop();
81 if (std::find(context.callbacks.begin(), context.callbacks.end(), cb->CallbackType()) !=
82 context.callbacks.end()) {
83 context.callback_ready_q.push_back(cb);
84 }
85 }
86 if (context.callback_ready_q.size() == 0) {
87 callback_data_.cv.wait_for(lk, context.timeout);
88 }
89 return true;
90 }
91
92 } // namespace messenger
93 } // namespace headless
94 } // namespace test
95 } // namespace bluetooth
96
97 namespace bluetooth::test::headless {
98
messenger_stats()99 void messenger_stats() {
100 // LOG_CONSOLE("%30s cnt:%zu", "device_found",
101 // discovered::device_found_.size()); LOG_CONSOLE("%30s cnt:%zu",
102 // "remote_device_properties",
103 // properties::remote_device_properties_.size());
104 }
105
106 // Callbacks that the messenger will handle from the bluetooth stack
start_messenger()107 void start_messenger() {
108 headless_add_callback("acl_state_changed", [](callback_data_t* data) {
109 log::assert_that(data != nullptr, "Received nullptr callback data");
110 messenger::callback_data_.Push(std::make_shared<acl_state_changed_params_t>(
111 *(static_cast<acl_state_changed_params_t*>(data))));
112 });
113 headless_add_callback("adapter_properties", [](callback_data_t* data) {
114 log::assert_that(data != nullptr, "Received nullptr callback data");
115 messenger::callback_data_.Push(std::make_shared<adapter_properties_params_t>(
116 *(static_cast<adapter_properties_params_t*>(data))));
117 });
118 headless_add_callback("device_found", [](callback_data_t* data) {
119 log::assert_that(data != nullptr, "Received nullptr callback data");
120 messenger::callback_data_.Push(
121 std::make_shared<device_found_params_t>(*(static_cast<device_found_params_t*>(data))));
122 });
123 headless_add_callback("remote_device_properties", [](callback_data_t* data) {
124 log::assert_that(data != nullptr, "Received nullptr callback data");
125 messenger::callback_data_.Push(std::make_shared<remote_device_properties_params_t>(
126 *(static_cast<remote_device_properties_params_t*>(data))));
127 });
128 LOG_CONSOLE("Started messenger service");
129 }
130
stop_messenger()131 void stop_messenger() {
132 headless_remove_callback("remote_device_properties");
133 headless_remove_callback("device_found");
134 headless_remove_callback("adapter_properties");
135 headless_remove_callback("acl_state_changed");
136
137 LOG_CONSOLE("Stopped messenger service");
138
139 messenger_stats();
140 }
141
142 } // namespace bluetooth::test::headless
143