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 <future>
22
23 #include "base/logging.h" // LOG() stdout and android log
24 #include "btif/include/btif_api.h"
25 #include "osi/include/log.h" // android log only
26 #include "stack/include/sdp_api.h"
27 #include "test/headless/bt_property.h"
28 #include "test/headless/get_options.h"
29 #include "test/headless/headless.h"
30 #include "test/headless/interface.h"
31 #include "test/headless/log.h"
32 #include "test/headless/sdp/sdp.h"
33 #include "test/headless/stopwatch.h"
34 #include "test/headless/timeout.h"
35 #include "types/bluetooth/uuid.h"
36 #include "types/raw_address.h"
37
38 using namespace bluetooth::test::headless;
39 using namespace std::chrono_literals;
40
41 template <typename T>
42 struct messenger_t {
43 std::mutex mutex;
44 std::condition_variable cv;
45 std::deque<T> params_queue;
Notifymessenger_t46 void Notify() { cv.notify_all(); }
47 };
48
49 namespace {
50
51 namespace acl {
52 messenger_t<acl_state_changed_params_t> acl_state_changed_;
53
acl_state_changed_cb(callback_data_t * data)54 void acl_state_changed_cb(callback_data_t* data) {
55 auto params = static_cast<acl_state_changed_params_t*>(data);
56
57 acl_state_changed_.params_queue.push_back(*params);
58 acl_state_changed_.Notify();
59 }
60
await_event(const bt_acl_state_t & state,const Timeout & timeout)61 bool await_event(const bt_acl_state_t& state, const Timeout& timeout) {
62 std::unique_lock<std::mutex> lk(acl_state_changed_.mutex);
63 if (!acl_state_changed_.params_queue.empty()) {
64 auto params = acl_state_changed_.params_queue.back();
65 if (params.state == state) return true;
66 }
67 return acl_state_changed_.cv.wait_for(lk, timeout, [=] {
68 return !acl_state_changed_.params_queue.empty() &&
69 acl_state_changed_.params_queue.back().state == state;
70 });
71 }
72
73 } // namespace acl
74
75 namespace sdp {
76 messenger_t<remote_device_properties_params_t> remote_device_properties_;
77
remote_device_properties_cb(callback_data_t * data)78 void remote_device_properties_cb(callback_data_t* data) {
79 auto params = static_cast<remote_device_properties_params_t*>(data);
80 // TODO Save timestamp into queue
81 remote_device_properties_.params_queue.push_back(*params);
82 remote_device_properties_.Notify();
83 }
84
await_event(const Timeout & timeout,const CheckPoint & check_point,const size_t count)85 bool await_event(const Timeout& timeout, const CheckPoint& check_point,
86 const size_t count) {
87 std::unique_lock<std::mutex> lk(remote_device_properties_.mutex);
88 if (!remote_device_properties_.params_queue.empty()) {
89 if (remote_device_properties_.params_queue.size() - check_point > count)
90 return true;
91 }
92 return remote_device_properties_.cv.wait_for(lk, timeout, [=] {
93 return !remote_device_properties_.params_queue.empty() &&
94 remote_device_properties_.params_queue.size() - check_point >= count;
95 });
96 }
97
98 } // namespace sdp
99
100 namespace inquiry {} // namespace inquiry
101
102 } // namespace
103
104 namespace bluetooth::test::headless {
105
106 namespace messenger {
107 namespace acl {
108
await_connected(const Timeout & timeout)109 bool await_connected(const Timeout& timeout) {
110 return ::acl::await_event(BT_ACL_STATE_CONNECTED, timeout);
111 }
112
await_disconnected(const Timeout & timeout)113 bool await_disconnected(const Timeout& timeout) {
114 return ::acl::await_event(BT_ACL_STATE_DISCONNECTED, timeout);
115 }
116
117 } // namespace acl
118
119 namespace sdp {
120
await_service_discovery(const Timeout & timeout,const CheckPoint & check_point,const size_t count)121 bool await_service_discovery(const Timeout& timeout,
122 const CheckPoint& check_point,
123 const size_t count) {
124 return ::sdp::await_event(timeout, check_point, count);
125 }
126
get_check_point()127 CheckPoint get_check_point() {
128 std::unique_lock<std::mutex> lk(::sdp::remote_device_properties_.mutex);
129 return ::sdp::remote_device_properties_.params_queue.size();
130 }
131
collect_from(CheckPoint & check_point)132 std::deque<remote_device_properties_params_t> collect_from(
133 CheckPoint& check_point) {
134 std::unique_lock<std::mutex> lk(::sdp::remote_device_properties_.mutex);
135 ASSERT_LOG(
136 !(check_point > ::sdp::remote_device_properties_.params_queue.size()),
137 "Checkpoint larger than size");
138 std::deque<remote_device_properties_params_t> deque;
139 for (size_t size = check_point;
140 size < ::sdp::remote_device_properties_.params_queue.size(); ++size) {
141 deque.push_back(::sdp::remote_device_properties_.params_queue[size]);
142 }
143 return deque;
144 }
145
146 } // namespace sdp
147
148 namespace inquiry {
149
get_check_point()150 CheckPoint get_check_point() {
151 std::unique_lock<std::mutex> lk(::sdp::remote_device_properties_.mutex);
152 return ::sdp::remote_device_properties_.params_queue.size();
153 }
154
await_inquiry_result(const Timeout & timeout,const CheckPoint & check_point,const size_t count)155 bool await_inquiry_result(const Timeout& timeout, const CheckPoint& check_point,
156 const size_t count) {
157 return ::sdp::await_event(timeout, check_point, count);
158 }
159
collect_from(CheckPoint & check_point)160 std::deque<remote_device_properties_params_t> collect_from(
161 CheckPoint& check_point) {
162 std::unique_lock<std::mutex> lk(::sdp::remote_device_properties_.mutex);
163 ASSERT_LOG(
164 !(check_point > ::sdp::remote_device_properties_.params_queue.size()),
165 "Checkpoint larger than size");
166 std::deque<remote_device_properties_params_t> deque;
167 for (size_t size = check_point;
168 size < ::sdp::remote_device_properties_.params_queue.size(); ++size) {
169 deque.push_back(::sdp::remote_device_properties_.params_queue[size]);
170 }
171 check_point +=
172 (::sdp::remote_device_properties_.params_queue.size() - check_point);
173 return deque;
174 }
175
176 } // namespace inquiry
177 } // namespace messenger
178
start_messenger()179 void start_messenger() {
180 headless_add_callback("acl_state_changed", ::acl::acl_state_changed_cb);
181 headless_add_callback("remote_device_properties",
182 ::sdp::remote_device_properties_cb);
183
184 LOG_CONSOLE("Started messenger service");
185 }
186
stop_messenger()187 void stop_messenger() {
188 headless_remove_callback("acl_state_changed", ::acl::acl_state_changed_cb);
189 headless_remove_callback("remote_device_properties",
190 ::sdp::remote_device_properties_cb);
191
192 LOG_CONSOLE("Stopped messenger service");
193 }
194
195 } // namespace bluetooth::test::headless
196