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_scan"
18
19 #include "test/headless/scan/scan.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/stopwatch.h"
33 #include "types/bluetooth/uuid.h"
34 #include "types/raw_address.h"
35
36 using namespace bluetooth::test::headless;
37 using namespace std::chrono_literals;
38
39 namespace scan {
40 std::promise<acl_state_changed_params_t> acl_state_changed_promise;
41 std::promise<remote_device_properties_params_t>
42 remote_device_properties_promise;
43
44 std::mutex mutex;
45 std::condition_variable cv;
46
47 std::queue<acl_state_changed_params_t> acl_state_changed_params_queue;
48 std::queue<discovery_state_changed_params_t>
49 discovery_state_changed_params_queue;
50 ;
51
52 // Callback from another thread
callback_interface(callback_data_t * data)53 void callback_interface(callback_data_t* data) {
54 if (data->Name() == "discovery_state_changed") {
55 LOG(INFO) << "Received discovery_state_changed";
56 auto params = static_cast<discovery_state_changed_params_t*>(data);
57 discovery_state_changed_params_queue.push(*params);
58 LOG_CONSOLE("Received discovery state change callback %s",
59 params->ToString().c_str());
60 cv.notify_all();
61 return;
62 }
63 LOG(ERROR) << "Received unexpected interface callback";
64 }
65
66 } // namespace scan
67
68 namespace {
69
start_scan(unsigned int num_loops)70 int start_scan([[maybe_unused]] unsigned int num_loops) {
71 LOG(INFO) << "Started Device Scan";
72
73 Stopwatch stop_watch("Inquiry_timeout");
74 auto check_point = messenger::inquiry::get_check_point();
75
76 ASSERT(bluetoothInterface.start_discovery() == BT_STATUS_SUCCESS);
77 LOG_CONSOLE("Started inquiry - device discovery");
78
79 while (stop_watch.LapMs() < 10000) {
80 if (messenger::inquiry::await_inquiry_result(1s, check_point, 1)) {
81 auto callback_queue = messenger::inquiry::collect_from(check_point);
82 while (!callback_queue.empty()) {
83 remote_device_properties_params_t params = callback_queue.front();
84 callback_queue.pop_front();
85 LOG_CONSOLE("Received remote inquiry :%s", STR(params));
86 bt_property_t* prop = params.properties;
87 for (int i = 0; i < params.num_properties; ++i, prop++) {
88 process_property(params.bd_addr, prop);
89 }
90 }
91 }
92 }
93
94 LOG_CONSOLE("Stopped inquiry - device discovery");
95 return 0;
96 }
97
98 } // namespace
99
100 extern uint8_t btu_trace_level;
101
Run()102 int bluetooth::test::headless::Scan::Run() {
103 if (options_.loop_ < 1) {
104 LOG_CONSOLE("This test requires at least a single loop");
105 options_.Usage();
106 return -1;
107 }
108 return RunOnHeadlessStack<int>([this]() {
109 btif_trace_level = BT_TRACE_LEVEL_DEBUG;
110 appl_trace_level = BT_TRACE_LEVEL_DEBUG;
111 btu_trace_level = BT_TRACE_LEVEL_DEBUG;
112 return start_scan(options_.loop_);
113 });
114 }
115