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