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_discovery"
18
19 #include "test/headless/discovery/discovery.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/messenger.h"
33 #include "test/headless/sdp/sdp.h"
34 #include "test/headless/stopwatch.h"
35 #include "test/headless/timeout.h"
36 #include "types/bluetooth/uuid.h"
37 #include "types/raw_address.h"
38
39 using namespace bluetooth::test::headless;
40 using namespace std::chrono_literals;
41
42 namespace {
43
start_discovery(unsigned int num_loops,const RawAddress & raw_address)44 int start_discovery([[maybe_unused]] unsigned int num_loops,
45 const RawAddress& raw_address) {
46 RawAddress bd_addr{raw_address};
47
48 Stopwatch acl_stopwatch("ACL_connection");
49 Stopwatch sdp_stopwatch("SDP_discovery");
50
51 LOG_CONSOLE("Started service discovery");
52 auto check_point = messenger::sdp::get_check_point();
53 ASSERT(bluetoothInterface.get_remote_services(&bd_addr, 0) ==
54 BT_STATUS_SUCCESS);
55
56 if (!messenger::acl::await_connected(8s)) {
57 LOG_CONSOLE("TIMEOUT waiting for connection to %s",
58 raw_address.ToString().c_str());
59 return -1;
60 }
61 LOG_CONSOLE("ACL connected to %s :%sms", STR(raw_address),
62 STR(acl_stopwatch));
63
64 if (!messenger::sdp::await_service_discovery(8s, check_point, 1UL)) {
65 LOG_CONSOLE("TIMEOUT waiting for service discovery to %s",
66 raw_address.ToString().c_str());
67 return -1;
68 }
69 auto callback_queue = messenger::sdp::collect_from(check_point);
70 ASSERT_LOG(callback_queue.size() == 1,
71 "Received unexpected number of SDP queries");
72
73 auto params = callback_queue.front();
74 callback_queue.pop_front();
75
76 LOG_CONSOLE("got remote services :%s", params.ToString().c_str());
77
78 for (int i = 0; i < params.num_properties; i++) {
79 process_property(params.bd_addr, params.properties + i);
80 }
81
82 // Run a second fetch SDP
83 {
84 LOG_CONSOLE("Sending second SDP request");
85 auto check_point = messenger::sdp::get_check_point();
86
87 ASSERT(bluetoothInterface.get_remote_services(&bd_addr, 0) ==
88 BT_STATUS_SUCCESS);
89
90 if (!messenger::acl::await_connected(8s)) {
91 LOG_CONSOLE("TIMEOUT waiting for connection to %s",
92 raw_address.ToString().c_str());
93 return -1;
94 }
95 LOG_CONSOLE("ACL connected to %s :%sms", STR(raw_address),
96 STR(acl_stopwatch));
97
98 if (!messenger::sdp::await_service_discovery(8s, check_point, 1UL)) {
99 LOG_CONSOLE("TIMEOUT waiting for service discovery to %s",
100 raw_address.ToString().c_str());
101 return -1;
102 }
103 auto callback_queue = messenger::sdp::collect_from(check_point);
104 ASSERT_LOG(callback_queue.size() == 1,
105 "Received unexpected number of SDP queries");
106
107 auto params = callback_queue.front();
108 callback_queue.pop_front();
109
110 LOG_CONSOLE("got remote services :%s", params.ToString().c_str());
111
112 for (int i = 0; i < params.num_properties; i++) {
113 process_property(params.bd_addr, params.properties + i);
114 }
115 }
116
117 // Run a third fetch SDP
118 {
119 LOG_CONSOLE("Sending third SDP request");
120 auto check_point = messenger::sdp::get_check_point();
121
122 ASSERT(bluetoothInterface.get_remote_services(&bd_addr, 0) ==
123 BT_STATUS_SUCCESS);
124
125 if (!messenger::acl::await_connected(8s)) {
126 LOG_CONSOLE("TIMEOUT waiting for connection to %s",
127 raw_address.ToString().c_str());
128 return -1;
129 }
130 LOG_CONSOLE("ACL connected to %s :%sms", STR(raw_address),
131 STR(acl_stopwatch));
132
133 if (!messenger::sdp::await_service_discovery(8s, check_point, 1UL)) {
134 LOG_CONSOLE("TIMEOUT waiting for service discovery to %s",
135 raw_address.ToString().c_str());
136 return -1;
137 }
138 auto callback_queue = messenger::sdp::collect_from(check_point);
139 ASSERT_LOG(callback_queue.size() == 1,
140 "Received unexpected number of SDP queries");
141
142 auto params = callback_queue.front();
143 callback_queue.pop_front();
144
145 LOG_CONSOLE("got remote services :%s", params.ToString().c_str());
146
147 for (int i = 0; i < params.num_properties; i++) {
148 process_property(params.bd_addr, params.properties + i);
149 }
150 }
151
152 LOG_CONSOLE("Awaiting disconnect");
153 if (!messenger::acl::await_disconnected(6s)) {
154 LOG_CONSOLE("TIMEOUT waiting for disconnection to %s",
155 raw_address.ToString().c_str());
156 return -1;
157 }
158
159 LOG_CONSOLE("Dumpsys system");
160 bluetoothInterface.dump(2, nullptr);
161 LOG_CONSOLE("Done dumpsys system");
162
163 return 0;
164 }
165
166 } // namespace
167
168 // extern uint8_t btu_trace_level;
169
Run()170 int bluetooth::test::headless::Discovery::Run() {
171 if (options_.loop_ < 1) {
172 LOG_CONSOLE("This test requires at least a single loop");
173 options_.Usage();
174 return -1;
175 }
176 if (options_.device_.size() != 1) {
177 LOG_CONSOLE("This test requires a single device specified");
178 options_.Usage();
179 return -1;
180 }
181 return RunOnHeadlessStack<int>([this]() {
182 return start_discovery(options_.loop_, options_.device_.front());
183 });
184 }
185