1 /*
2 * Copyright 2019 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 #include <memory>
17 #include <mutex>
18 #include <set>
19
20 #include "hci/controller.h"
21 #include "hci/hci_layer.h"
22 #include "hci/hci_packets.h"
23 #include "hci/le_scanning_interface.h"
24 #include "hci/le_scanning_manager.h"
25 #include "module.h"
26 #include "os/handler.h"
27 #include "os/log.h"
28
29 namespace bluetooth {
30 namespace hci {
31
32 constexpr uint16_t kDefaultLeScanWindow = 4800;
33 constexpr uint16_t kDefaultLeScanInterval = 4800;
34
__anoncc64f2cf0102() 35 const ModuleFactory LeScanningManager::Factory = ModuleFactory([]() { return new LeScanningManager(); });
36
37 enum class ScanApiType {
38 LE_4_0 = 1,
39 ANDROID_HCI = 2,
40 LE_5_0 = 3,
41 };
42
43 struct LeScanningManager::impl {
implbluetooth::hci::LeScanningManager::impl44 impl(Module* module) : module_(module), le_scanning_interface_(nullptr) {}
45
startbluetooth::hci::LeScanningManager::impl46 void start(os::Handler* handler, hci::HciLayer* hci_layer, hci::Controller* controller) {
47 module_handler_ = handler;
48 hci_layer_ = hci_layer;
49 controller_ = controller;
50 le_scanning_interface_ = hci_layer_->GetLeScanningInterface(
51 common::Bind(&LeScanningManager::impl::handle_scan_results, common::Unretained(this)), module_handler_);
52 if (controller_->IsSupported(OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS)) {
53 api_type_ = ScanApiType::LE_5_0;
54 } else if (controller_->IsSupported(OpCode::LE_EXTENDED_SCAN_PARAMS)) {
55 api_type_ = ScanApiType::ANDROID_HCI;
56 } else {
57 api_type_ = ScanApiType::LE_4_0;
58 }
59 configure_scan();
60 }
61
handle_scan_resultsbluetooth::hci::LeScanningManager::impl62 void handle_scan_results(LeMetaEventView event) {
63 switch (event.GetSubeventCode()) {
64 case hci::SubeventCode::ADVERTISING_REPORT:
65 handle_advertising_report<LeAdvertisingReportView, LeAdvertisingReport, LeReport>(
66 LeAdvertisingReportView::Create(event));
67 break;
68 case hci::SubeventCode::DIRECTED_ADVERTISING_REPORT:
69 handle_advertising_report<LeDirectedAdvertisingReportView, LeDirectedAdvertisingReport, DirectedLeReport>(
70 LeDirectedAdvertisingReportView::Create(event));
71 break;
72 case hci::SubeventCode::EXTENDED_ADVERTISING_REPORT:
73 handle_advertising_report<LeExtendedAdvertisingReportView, LeExtendedAdvertisingReport, ExtendedLeReport>(
74 LeExtendedAdvertisingReportView::Create(event));
75 break;
76 case hci::SubeventCode::SCAN_TIMEOUT:
77 if (registered_callback_ != nullptr) {
78 registered_callback_->Handler()->Post(
79 common::BindOnce(&LeScanningManagerCallbacks::on_timeout, common::Unretained(registered_callback_)));
80 registered_callback_ = nullptr;
81 }
82 break;
83 default:
84 LOG_ALWAYS_FATAL("Unknown advertising subevent %s", hci::SubeventCodeText(event.GetSubeventCode()).c_str());
85 }
86 }
87
88 template <class EventType, class ReportStructType, class ReportType>
handle_advertising_reportbluetooth::hci::LeScanningManager::impl89 void handle_advertising_report(EventType event_view) {
90 if (registered_callback_ == nullptr) {
91 LOG_INFO("Dropping advertising event (no registered handler)");
92 return;
93 }
94 if (!event_view.IsValid()) {
95 LOG_INFO("Dropping invalid advertising event");
96 return;
97 }
98 std::vector<ReportStructType> report_vector = event_view.GetAdvertisingReports();
99 if (report_vector.empty()) {
100 LOG_INFO("Zero results in advertising event");
101 return;
102 }
103 std::vector<std::shared_ptr<LeReport>> param;
104 param.reserve(report_vector.size());
105 for (const ReportStructType& report : report_vector) {
106 param.push_back(std::shared_ptr<LeReport>(static_cast<LeReport*>(new ReportType(report))));
107 }
108 registered_callback_->Handler()->Post(common::BindOnce(&LeScanningManagerCallbacks::on_advertisements,
109 common::Unretained(registered_callback_), param));
110 }
111
configure_scanbluetooth::hci::LeScanningManager::impl112 void configure_scan() {
113 std::vector<PhyScanParameters> parameter_vector;
114 PhyScanParameters phy_scan_parameters;
115 phy_scan_parameters.le_scan_window_ = kDefaultLeScanWindow;
116 phy_scan_parameters.le_scan_interval_ = kDefaultLeScanInterval;
117 phy_scan_parameters.le_scan_type_ = LeScanType::ACTIVE;
118 parameter_vector.push_back(phy_scan_parameters);
119 uint8_t phys_in_use = 1;
120
121 switch (api_type_) {
122 case ScanApiType::LE_5_0:
123 le_scanning_interface_->EnqueueCommand(hci::LeSetExtendedScanParametersBuilder::Create(
124 own_address_type_, filter_policy_, phys_in_use, parameter_vector),
125 common::BindOnce(impl::check_status), module_handler_);
126 break;
127 case ScanApiType::ANDROID_HCI:
128 le_scanning_interface_->EnqueueCommand(
129 hci::LeExtendedScanParamsBuilder::Create(LeScanType::ACTIVE, interval_ms_, window_ms_, own_address_type_,
130 filter_policy_),
131 common::BindOnce(impl::check_status), module_handler_);
132
133 break;
134 case ScanApiType::LE_4_0:
135 le_scanning_interface_->EnqueueCommand(
136 hci::LeSetScanParametersBuilder::Create(LeScanType::ACTIVE, interval_ms_, window_ms_, own_address_type_,
137 filter_policy_),
138 common::BindOnce(impl::check_status), module_handler_);
139 break;
140 }
141 }
142
start_scanbluetooth::hci::LeScanningManager::impl143 void start_scan(LeScanningManagerCallbacks* le_scanning_manager_callbacks) {
144 registered_callback_ = le_scanning_manager_callbacks;
145 switch (api_type_) {
146 case ScanApiType::LE_5_0:
147 le_scanning_interface_->EnqueueCommand(
148 hci::LeSetExtendedScanEnableBuilder::Create(Enable::ENABLED,
149 FilterDuplicates::DISABLED /* filter duplicates */, 0, 0),
150 common::BindOnce(impl::check_status), module_handler_);
151 break;
152 case ScanApiType::ANDROID_HCI:
153 case ScanApiType::LE_4_0:
154 le_scanning_interface_->EnqueueCommand(
155 hci::LeSetScanEnableBuilder::Create(Enable::ENABLED, Enable::DISABLED /* filter duplicates */),
156 common::BindOnce(impl::check_status), module_handler_);
157 break;
158 }
159 }
160
stop_scanbluetooth::hci::LeScanningManager::impl161 void stop_scan(common::Callback<void()> on_stopped) {
162 if (registered_callback_ == nullptr) {
163 return;
164 }
165 registered_callback_->Handler()->Post(std::move(on_stopped));
166 switch (api_type_) {
167 case ScanApiType::LE_5_0:
168 le_scanning_interface_->EnqueueCommand(
169 hci::LeSetExtendedScanEnableBuilder::Create(Enable::DISABLED,
170 FilterDuplicates::DISABLED /* filter duplicates */, 0, 0),
171 common::BindOnce(impl::check_status), module_handler_);
172 registered_callback_ = nullptr;
173 break;
174 case ScanApiType::ANDROID_HCI:
175 case ScanApiType::LE_4_0:
176 le_scanning_interface_->EnqueueCommand(
177 hci::LeSetScanEnableBuilder::Create(Enable::DISABLED, Enable::DISABLED /* filter duplicates */),
178 common::BindOnce(impl::check_status), module_handler_);
179 registered_callback_ = nullptr;
180 break;
181 }
182 }
183
184 ScanApiType api_type_;
185
186 LeScanningManagerCallbacks* registered_callback_;
187 Module* module_;
188 os::Handler* module_handler_;
189 hci::HciLayer* hci_layer_;
190 hci::Controller* controller_;
191 hci::LeScanningInterface* le_scanning_interface_;
192
193 uint32_t interval_ms_{1000};
194 uint16_t window_ms_{1000};
195 AddressType own_address_type_{AddressType::PUBLIC_DEVICE_ADDRESS};
196 LeSetScanningFilterPolicy filter_policy_{LeSetScanningFilterPolicy::ACCEPT_ALL};
197
check_statusbluetooth::hci::LeScanningManager::impl198 static void check_status(CommandCompleteView view) {
199 switch (view.GetCommandOpCode()) {
200 case (OpCode::LE_SET_SCAN_ENABLE): {
201 auto status_view = LeSetScanEnableCompleteView::Create(view);
202 ASSERT(status_view.IsValid());
203 ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS);
204 } break;
205 case (OpCode::LE_SET_EXTENDED_SCAN_ENABLE): {
206 auto status_view = LeSetExtendedScanEnableCompleteView::Create(view);
207 ASSERT(status_view.IsValid());
208 ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS);
209 } break;
210 case (OpCode::LE_SET_SCAN_PARAMETERS): {
211 auto status_view = LeSetScanParametersCompleteView::Create(view);
212 ASSERT(status_view.IsValid());
213 ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS);
214 } break;
215 case (OpCode::LE_EXTENDED_SCAN_PARAMS): {
216 auto status_view = LeExtendedScanParamsCompleteView::Create(view);
217 ASSERT(status_view.IsValid());
218 ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS);
219 } break;
220 case (OpCode::LE_SET_EXTENDED_SCAN_PARAMETERS): {
221 auto status_view = LeSetExtendedScanParametersCompleteView::Create(view);
222 ASSERT(status_view.IsValid());
223 ASSERT(status_view.GetStatus() == ErrorCode::SUCCESS);
224 } break;
225 default:
226 LOG_ALWAYS_FATAL("Unhandled event %s", OpCodeText(view.GetCommandOpCode()).c_str());
227 }
228 }
229 };
230
LeScanningManager()231 LeScanningManager::LeScanningManager() {
232 pimpl_ = std::make_unique<impl>(this);
233 }
234
ListDependencies(ModuleList * list)235 void LeScanningManager::ListDependencies(ModuleList* list) {
236 list->add<hci::HciLayer>();
237 list->add<hci::Controller>();
238 }
239
Start()240 void LeScanningManager::Start() {
241 pimpl_->start(GetHandler(), GetDependency<hci::HciLayer>(), GetDependency<hci::Controller>());
242 }
243
Stop()244 void LeScanningManager::Stop() {
245 pimpl_.reset();
246 }
247
ToString() const248 std::string LeScanningManager::ToString() const {
249 return "Le Scanning Manager";
250 }
251
StartScan(LeScanningManagerCallbacks * callbacks)252 void LeScanningManager::StartScan(LeScanningManagerCallbacks* callbacks) {
253 GetHandler()->Post(common::Bind(&impl::start_scan, common::Unretained(pimpl_.get()), callbacks));
254 }
255
StopScan(common::Callback<void ()> on_stopped)256 void LeScanningManager::StopScan(common::Callback<void()> on_stopped) {
257 GetHandler()->Post(common::Bind(&impl::stop_scan, common::Unretained(pimpl_.get()), on_stopped));
258 }
259
260 } // namespace hci
261 } // namespace bluetooth
262