• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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