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
19 #include "hci/acl_manager.h"
20 #include "hci/controller.h"
21 #include "hci/hci_layer.h"
22 #include "hci/hci_packets.h"
23 #include "hci/le_advertising_interface.h"
24 #include "hci/le_advertising_manager.h"
25 #include "module.h"
26 #include "os/handler.h"
27 #include "os/log.h"
28
29 namespace bluetooth {
30 namespace hci {
31
__anon7318a81a0102() 32 const ModuleFactory LeAdvertisingManager::Factory = ModuleFactory([]() { return new LeAdvertisingManager(); });
33
34 enum class AdvertisingApiType {
35 LEGACY = 1,
36 ANDROID_HCI = 2,
37 EXTENDED = 3,
38 };
39
40 enum class AdvertisingFlag : uint8_t {
41 LE_LIMITED_DISCOVERABLE = 0x01,
42 LE_GENERAL_DISCOVERABLE = 0x02,
43 BR_EDR_NOT_SUPPORTED = 0x04,
44 SIMULTANEOUS_LE_AND_BR_EDR_CONTROLLER = 0x08,
45 SIMULTANEOUS_LE_AND_BR_EDR_HOST = 0x10,
46 };
47
48 struct Advertiser {
49 os::Handler* handler;
50 AddressWithType current_address;
51 common::Callback<void(Address, AddressType)> scan_callback;
52 common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback;
53 int8_t tx_power;
54 uint16_t duration;
55 uint8_t max_extended_advertising_events;
56 bool started = false;
57 bool connectable = false;
58 std::unique_ptr<os::Alarm> address_rotation_alarm;
59 };
60
ExtendedAdvertisingConfig(const AdvertisingConfig & config)61 ExtendedAdvertisingConfig::ExtendedAdvertisingConfig(const AdvertisingConfig& config) : AdvertisingConfig(config) {
62 switch (config.advertising_type) {
63 case AdvertisingType::ADV_IND:
64 connectable = true;
65 scannable = true;
66 break;
67 case AdvertisingType::ADV_DIRECT_IND:
68 connectable = true;
69 directed = true;
70 high_duty_directed_connectable = true;
71 break;
72 case AdvertisingType::ADV_SCAN_IND:
73 scannable = true;
74 break;
75 case AdvertisingType::ADV_NONCONN_IND:
76 break;
77 case AdvertisingType::ADV_DIRECT_IND_LOW:
78 connectable = true;
79 directed = true;
80 break;
81 default:
82 LOG_WARN("Unknown event type");
83 break;
84 }
85 }
86
87 struct LeAdvertisingManager::impl : public bluetooth::hci::LeAddressManagerCallback {
implbluetooth::hci::LeAdvertisingManager::impl88 impl(Module* module) : module_(module), le_advertising_interface_(nullptr), num_instances_(0) {}
89
~implbluetooth::hci::LeAdvertisingManager::impl90 ~impl() {
91 if (address_manager_registered) {
92 le_address_manager_->Unregister(this);
93 }
94 advertising_sets_.clear();
95 }
96
startbluetooth::hci::LeAdvertisingManager::impl97 void start(os::Handler* handler, hci::HciLayer* hci_layer, hci::Controller* controller,
98 hci::AclManager* acl_manager) {
99 module_handler_ = handler;
100 hci_layer_ = hci_layer;
101 controller_ = controller;
102 le_maximum_advertising_data_length_ = controller_->GetLeMaximumAdvertisingDataLength();
103 acl_manager_ = acl_manager;
104 le_address_manager_ = acl_manager->GetLeAddressManager();
105 le_advertising_interface_ =
106 hci_layer_->GetLeAdvertisingInterface(module_handler_->BindOn(this, &LeAdvertisingManager::impl::handle_event));
107 num_instances_ = controller_->GetLeNumberOfSupportedAdverisingSets();
108 enabled_sets_ = std::vector<EnabledSet>(num_instances_);
109 for (size_t i = 0; i < enabled_sets_.size(); i++) {
110 enabled_sets_[i].advertising_handle_ = kInvalidHandle;
111 }
112
113 if (controller_->IsSupported(hci::OpCode::LE_SET_EXTENDED_ADVERTISING_PARAMETERS)) {
114 advertising_api_type_ = AdvertisingApiType::EXTENDED;
115 } else if (controller_->IsSupported(hci::OpCode::LE_MULTI_ADVT)) {
116 advertising_api_type_ = AdvertisingApiType::ANDROID_HCI;
117 } else {
118 advertising_api_type_ = AdvertisingApiType::LEGACY;
119 hci_layer_->EnqueueCommand(
120 LeReadAdvertisingPhysicalChannelTxPowerBuilder::Create(),
121 handler->BindOnceOn(this, &impl::on_read_advertising_physical_channel_tx_power));
122 }
123 }
124
GetNumberOfAdvertisingInstancesbluetooth::hci::LeAdvertisingManager::impl125 size_t GetNumberOfAdvertisingInstances() const {
126 return num_instances_;
127 }
128
get_advertising_api_typebluetooth::hci::LeAdvertisingManager::impl129 AdvertisingApiType get_advertising_api_type() const {
130 return advertising_api_type_;
131 }
132
register_advertising_callbackbluetooth::hci::LeAdvertisingManager::impl133 void register_advertising_callback(AdvertisingCallback* advertising_callback) {
134 advertising_callbacks_ = advertising_callback;
135 }
136
handle_eventbluetooth::hci::LeAdvertisingManager::impl137 void handle_event(LeMetaEventView event) {
138 switch (event.GetSubeventCode()) {
139 case hci::SubeventCode::SCAN_REQUEST_RECEIVED:
140 handle_scan_request(LeScanRequestReceivedView::Create(event));
141 break;
142 case hci::SubeventCode::ADVERTISING_SET_TERMINATED:
143 handle_set_terminated(LeAdvertisingSetTerminatedView::Create(event));
144 break;
145 default:
146 LOG_INFO("Unknown subevent in scanner %s", hci::SubeventCodeText(event.GetSubeventCode()).c_str());
147 }
148 }
149
handle_scan_requestbluetooth::hci::LeAdvertisingManager::impl150 void handle_scan_request(LeScanRequestReceivedView event_view) {
151 if (!event_view.IsValid()) {
152 LOG_INFO("Dropping invalid scan request event");
153 return;
154 }
155 registered_handler_->Post(
156 common::BindOnce(scan_callback_, event_view.GetScannerAddress(), event_view.GetScannerAddressType()));
157 }
158
handle_set_terminatedbluetooth::hci::LeAdvertisingManager::impl159 void handle_set_terminated(LeAdvertisingSetTerminatedView event_view) {
160 if (!event_view.IsValid()) {
161 LOG_INFO("Dropping invalid advertising event");
162 return;
163 }
164
165 uint8_t advertiser_id = event_view.GetAdvertisingHandle();
166
167 if (advertising_sets_[advertiser_id].address_rotation_alarm != nullptr) {
168 advertising_sets_[advertiser_id].address_rotation_alarm->Cancel();
169 advertising_sets_[advertiser_id].address_rotation_alarm.reset();
170 }
171 enabled_sets_[advertiser_id].advertising_handle_ = kInvalidHandle;
172
173 AddressWithType advertiser_address = advertising_sets_[event_view.GetAdvertisingHandle()].current_address;
174
175 acl_manager_->OnAdvertisingSetTerminated(
176 event_view.GetStatus(), event_view.GetConnectionHandle(), advertiser_address);
177 }
178
allocate_advertiserbluetooth::hci::LeAdvertisingManager::impl179 AdvertiserId allocate_advertiser() {
180 AdvertiserId id = 0;
181 {
182 std::unique_lock lock(id_mutex_);
183 while (id < num_instances_ && advertising_sets_.count(id) != 0) {
184 id++;
185 }
186 }
187 if (id == num_instances_) {
188 return kInvalidId;
189 }
190 return id;
191 }
192
remove_advertiserbluetooth::hci::LeAdvertisingManager::impl193 void remove_advertiser(AdvertiserId advertiser_id) {
194 stop_advertising(advertiser_id);
195 std::unique_lock lock(id_mutex_);
196 if (advertising_sets_.count(advertiser_id) == 0) {
197 return;
198 }
199 if (advertising_sets_.empty() && address_manager_registered) {
200 le_address_manager_->Unregister(this);
201 address_manager_registered = false;
202 paused = false;
203 }
204 if (advertising_api_type_ == AdvertisingApiType::EXTENDED) {
205 le_advertising_interface_->EnqueueCommand(
206 hci::LeRemoveAdvertisingSetBuilder::Create(advertiser_id),
207 module_handler_->BindOnce(impl::check_status<LeRemoveAdvertisingSetCompleteView>));
208
209 if (advertising_sets_[advertiser_id].address_rotation_alarm != nullptr) {
210 advertising_sets_[advertiser_id].address_rotation_alarm->Cancel();
211 advertising_sets_[advertiser_id].address_rotation_alarm.reset();
212 }
213 }
214 advertising_sets_.erase(advertiser_id);
215 }
216
create_advertiserbluetooth::hci::LeAdvertisingManager::impl217 void create_advertiser(
218 AdvertiserId id,
219 const AdvertisingConfig config,
220 const common::Callback<void(Address, AddressType)>& scan_callback,
221 const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback,
222 os::Handler* handler) {
223 advertising_sets_[id].scan_callback = scan_callback;
224 advertising_sets_[id].set_terminated_callback = set_terminated_callback;
225 advertising_sets_[id].handler = handler;
226 advertising_sets_[id].current_address = AddressWithType{};
227
228 if (!address_manager_registered) {
229 le_address_manager_->Register(this);
230 address_manager_registered = true;
231 }
232
233 switch (advertising_api_type_) {
234 case (AdvertisingApiType::LEGACY): {
235 set_parameters(id, config);
236 if (config.advertising_type == AdvertisingType::ADV_IND ||
237 config.advertising_type == AdvertisingType::ADV_NONCONN_IND) {
238 set_data(id, true, config.scan_response);
239 }
240 set_data(id, false, config.advertisement);
241 if (!paused) {
242 enable_advertiser(id, true, 0, 0);
243 } else {
244 enabled_sets_[id].advertising_handle_ = id;
245 }
246 } break;
247 case (AdvertisingApiType::ANDROID_HCI): {
248 set_parameters(id, config);
249 if (config.advertising_type == AdvertisingType::ADV_IND ||
250 config.advertising_type == AdvertisingType::ADV_NONCONN_IND) {
251 set_data(id, true, config.scan_response);
252 }
253 set_data(id, false, config.advertisement);
254 advertising_sets_[id].current_address = le_address_manager_->GetAnotherAddress();
255 le_advertising_interface_->EnqueueCommand(
256 hci::LeMultiAdvtSetRandomAddrBuilder::Create(advertising_sets_[id].current_address.GetAddress(), id),
257 module_handler_->BindOnce(impl::check_status<LeMultiAdvtCompleteView>));
258 if (!paused) {
259 enable_advertiser(id, true, 0, 0);
260 } else {
261 enabled_sets_[id].advertising_handle_ = id;
262 }
263 } break;
264 case (AdvertisingApiType::EXTENDED): {
265 LOG_WARN("Unexpected AdvertisingApiType EXTENDED");
266 } break;
267 }
268 }
269
create_extended_advertiserbluetooth::hci::LeAdvertisingManager::impl270 void create_extended_advertiser(
271 int reg_id,
272 AdvertiserId id,
273 const ExtendedAdvertisingConfig config,
274 const common::Callback<void(Address, AddressType)>& scan_callback,
275 const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback,
276 uint16_t duration,
277 uint8_t max_ext_adv_events,
278 os::Handler* handler) {
279 id_map_[id] = reg_id;
280
281 if (advertising_api_type_ != AdvertisingApiType::EXTENDED) {
282 create_advertiser(id, config, scan_callback, set_terminated_callback, handler);
283 return;
284 }
285
286 advertising_sets_[id].scan_callback = scan_callback;
287 advertising_sets_[id].set_terminated_callback = set_terminated_callback;
288 advertising_sets_[id].duration = duration;
289 advertising_sets_[id].max_extended_advertising_events = max_ext_adv_events;
290 advertising_sets_[id].handler = handler;
291
292 set_parameters(id, config);
293
294 auto address_policy = le_address_manager_->GetAddressPolicy();
295 if (config.own_address_type == OwnAddressType::RANDOM_DEVICE_ADDRESS) {
296 if (address_policy == LeAddressManager::AddressPolicy::USE_NON_RESOLVABLE_ADDRESS ||
297 address_policy == LeAddressManager::AddressPolicy::USE_RESOLVABLE_ADDRESS) {
298 AddressWithType address_with_type = le_address_manager_->GetAnotherAddress();
299 le_advertising_interface_->EnqueueCommand(
300 hci::LeSetExtendedAdvertisingRandomAddressBuilder::Create(id, address_with_type.GetAddress()),
301 module_handler_->BindOnceOn(
302 this,
303 &impl::on_set_advertising_set_random_address_complete<
304 LeSetExtendedAdvertisingRandomAddressCompleteView>,
305 id,
306 address_with_type));
307
308 // start timer for random address
309 advertising_sets_[id].address_rotation_alarm = std::make_unique<os::Alarm>(module_handler_);
310 advertising_sets_[id].address_rotation_alarm->Schedule(
311 common::BindOnce(&impl::set_advertising_set_random_address, common::Unretained(this), id),
312 le_address_manager_->GetNextPrivateAddressIntervalMs());
313 } else {
314 advertising_sets_[id].current_address = le_address_manager_->GetCurrentAddress();
315 le_advertising_interface_->EnqueueCommand(
316 hci::LeSetExtendedAdvertisingRandomAddressBuilder::Create(
317 id, advertising_sets_[id].current_address.GetAddress()),
318 module_handler_->BindOnce(impl::check_status<LeSetExtendedAdvertisingRandomAddressCompleteView>));
319 }
320 } else {
321 advertising_sets_[id].current_address =
322 AddressWithType(controller_->GetMacAddress(), AddressType::PUBLIC_DEVICE_ADDRESS);
323 }
324 if (config.advertising_type == AdvertisingType::ADV_IND ||
325 config.advertising_type == AdvertisingType::ADV_NONCONN_IND) {
326 set_data(id, true, config.scan_response);
327 }
328 set_data(id, false, config.advertisement);
329
330 if (!config.periodic_data.empty()) {
331 set_periodic_parameter(id, config.periodic_advertising_parameters);
332 set_periodic_data(id, config.periodic_data);
333 enable_periodic_advertising(id, true);
334 }
335
336 if (!paused) {
337 enable_advertiser(id, true, duration, max_ext_adv_events);
338 } else {
339 EnabledSet curr_set;
340 curr_set.advertising_handle_ = id;
341 curr_set.duration_ = duration;
342 curr_set.max_extended_advertising_events_ = max_ext_adv_events;
343 std::vector<EnabledSet> enabled_sets = {curr_set};
344 enabled_sets_[id] = curr_set;
345 }
346 }
347
stop_advertisingbluetooth::hci::LeAdvertisingManager::impl348 void stop_advertising(AdvertiserId advertiser_id) {
349 if (advertising_sets_.find(advertiser_id) == advertising_sets_.end()) {
350 LOG_INFO("Unknown advertising set %u", advertiser_id);
351 return;
352 }
353 EnabledSet curr_set;
354 curr_set.advertising_handle_ = advertiser_id;
355 std::vector<EnabledSet> enabled_vector{curr_set};
356
357 // If advertising or periodic advertising on the advertising set is enabled,
358 // then the Controller will return the error code Command Disallowed (0x0C).
359 // Thus, we should disable it before removing it.
360 switch (advertising_api_type_) {
361 case (AdvertisingApiType::LEGACY):
362 le_advertising_interface_->EnqueueCommand(
363 hci::LeSetAdvertisingEnableBuilder::Create(Enable::DISABLED),
364 module_handler_->BindOnce(impl::check_status<LeSetAdvertisingEnableCompleteView>));
365 break;
366 case (AdvertisingApiType::ANDROID_HCI):
367 le_advertising_interface_->EnqueueCommand(
368 hci::LeMultiAdvtSetEnableBuilder::Create(Enable::DISABLED, advertiser_id),
369 module_handler_->BindOnce(impl::check_status<LeMultiAdvtCompleteView>));
370 break;
371 case (AdvertisingApiType::EXTENDED): {
372 le_advertising_interface_->EnqueueCommand(
373 hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::DISABLED, enabled_vector),
374 module_handler_->BindOnce(impl::check_status<LeSetExtendedAdvertisingEnableCompleteView>));
375
376 le_advertising_interface_->EnqueueCommand(
377 hci::LeSetPeriodicAdvertisingEnableBuilder::Create(Enable::DISABLED, advertiser_id),
378 module_handler_->BindOnce(impl::check_status<LeSetPeriodicAdvertisingEnableCompleteView>));
379 } break;
380 }
381
382 std::unique_lock lock(id_mutex_);
383 enabled_sets_[advertiser_id].advertising_handle_ = kInvalidHandle;
384 }
385
set_advertising_set_random_addressbluetooth::hci::LeAdvertisingManager::impl386 void set_advertising_set_random_address(AdvertiserId advertiser_id) {
387 // This function should only be trigger by enabled advertising set
388 if (enabled_sets_[advertiser_id].advertising_handle_ == kInvalidHandle) {
389 if (advertising_sets_[advertiser_id].address_rotation_alarm != nullptr) {
390 advertising_sets_[advertiser_id].address_rotation_alarm->Cancel();
391 advertising_sets_[advertiser_id].address_rotation_alarm.reset();
392 }
393 return;
394 }
395
396 // TODO handle duration and max_extended_advertising_events_
397 EnabledSet curr_set;
398 curr_set.advertising_handle_ = advertiser_id;
399 curr_set.duration_ = advertising_sets_[advertiser_id].duration;
400 curr_set.max_extended_advertising_events_ = advertising_sets_[advertiser_id].max_extended_advertising_events;
401 std::vector<EnabledSet> enabled_sets = {curr_set};
402
403 // For connectable advertising, we should disable it first
404 if (advertising_sets_[advertiser_id].connectable) {
405 le_advertising_interface_->EnqueueCommand(
406 hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::DISABLED, enabled_sets),
407 module_handler_->BindOnce(impl::check_status<LeSetExtendedAdvertisingEnableCompleteView>));
408 }
409
410 AddressWithType address_with_type = le_address_manager_->GetAnotherAddress();
411 le_advertising_interface_->EnqueueCommand(
412 hci::LeSetExtendedAdvertisingRandomAddressBuilder::Create(advertiser_id, address_with_type.GetAddress()),
413 module_handler_->BindOnceOn(
414 this,
415 &impl::on_set_advertising_set_random_address_complete<LeSetExtendedAdvertisingRandomAddressCompleteView>,
416 advertiser_id,
417 address_with_type));
418
419 if (advertising_sets_[advertiser_id].connectable) {
420 le_advertising_interface_->EnqueueCommand(
421 hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::ENABLED, enabled_sets),
422 module_handler_->BindOnce(impl::check_status<LeSetExtendedAdvertisingEnableCompleteView>));
423 }
424
425 advertising_sets_[advertiser_id].address_rotation_alarm->Schedule(
426 common::BindOnce(&impl::set_advertising_set_random_address, common::Unretained(this), advertiser_id),
427 le_address_manager_->GetNextPrivateAddressIntervalMs());
428 }
429
set_parametersbluetooth::hci::LeAdvertisingManager::impl430 void set_parameters(AdvertiserId advertiser_id, ExtendedAdvertisingConfig config) {
431 advertising_sets_[advertiser_id].connectable = config.connectable;
432 advertising_sets_[advertiser_id].tx_power = config.tx_power;
433
434 switch (advertising_api_type_) {
435 case (AdvertisingApiType::LEGACY): {
436 le_advertising_interface_->EnqueueCommand(
437 hci::LeSetAdvertisingParametersBuilder::Create(
438 config.interval_min,
439 config.interval_max,
440 config.advertising_type,
441 config.own_address_type,
442 config.peer_address_type,
443 config.peer_address,
444 config.channel_map,
445 config.filter_policy),
446 module_handler_->BindOnceOn(
447 this, &impl::check_status_with_id<LeSetAdvertisingParametersCompleteView>, advertiser_id));
448 } break;
449 case (AdvertisingApiType::ANDROID_HCI): {
450 le_advertising_interface_->EnqueueCommand(
451 hci::LeMultiAdvtParamBuilder::Create(
452 config.interval_min,
453 config.interval_max,
454 config.advertising_type,
455 config.own_address_type,
456 config.peer_address_type,
457 config.peer_address,
458 config.channel_map,
459 config.filter_policy,
460 advertiser_id,
461 config.tx_power),
462 module_handler_->BindOnceOn(this, &impl::check_status_with_id<LeMultiAdvtCompleteView>, advertiser_id));
463 } break;
464 case (AdvertisingApiType::EXTENDED): {
465 // sid must be in range 0x00 to 0x0F. Since no controller supports more than
466 // 16 advertisers, it's safe to make sid equal to id.
467 config.sid = advertiser_id % kAdvertisingSetIdMask;
468
469 if (config.legacy_pdus) {
470 LegacyAdvertisingProperties legacy_properties = LegacyAdvertisingProperties::ADV_IND;
471 if (config.connectable && config.directed) {
472 if (config.high_duty_directed_connectable) {
473 legacy_properties = LegacyAdvertisingProperties::ADV_DIRECT_IND_HIGH;
474 } else {
475 legacy_properties = LegacyAdvertisingProperties::ADV_DIRECT_IND_LOW;
476 }
477 }
478 if (config.scannable && !config.connectable) {
479 legacy_properties = LegacyAdvertisingProperties::ADV_SCAN_IND;
480 }
481 if (!config.scannable && !config.connectable) {
482 legacy_properties = LegacyAdvertisingProperties::ADV_NONCONN_IND;
483 }
484
485 le_advertising_interface_->EnqueueCommand(
486 LeSetExtendedAdvertisingLegacyParametersBuilder::Create(
487 advertiser_id,
488 legacy_properties,
489 config.interval_min,
490 config.interval_max,
491 config.channel_map,
492 config.own_address_type,
493 config.peer_address_type,
494 config.peer_address,
495 config.filter_policy,
496 config.tx_power,
497 config.sid,
498 config.enable_scan_request_notifications),
499 module_handler_->BindOnceOn(
500 this,
501 &impl::on_set_extended_advertising_parameters_complete<
502 LeSetExtendedAdvertisingParametersCompleteView>,
503 advertiser_id));
504 } else {
505 uint8_t legacy_properties = (config.connectable ? 0x1 : 0x00) | (config.scannable ? 0x2 : 0x00) |
506 (config.directed ? 0x4 : 0x00) |
507 (config.high_duty_directed_connectable ? 0x8 : 0x00);
508 uint8_t extended_properties = (config.anonymous ? 0x20 : 0x00) | (config.include_tx_power ? 0x40 : 0x00);
509 extended_properties = extended_properties >> 5;
510
511 le_advertising_interface_->EnqueueCommand(
512 hci::LeSetExtendedAdvertisingParametersBuilder::Create(
513 advertiser_id,
514 legacy_properties,
515 extended_properties,
516 config.interval_min,
517 config.interval_max,
518 config.channel_map,
519 config.own_address_type,
520 config.peer_address_type,
521 config.peer_address,
522 config.filter_policy,
523 config.tx_power,
524 (config.use_le_coded_phy ? PrimaryPhyType::LE_CODED : PrimaryPhyType::LE_1M),
525 config.secondary_max_skip,
526 config.secondary_advertising_phy,
527 config.sid,
528 config.enable_scan_request_notifications),
529 module_handler_->BindOnceOn(
530 this,
531 &impl::on_set_extended_advertising_parameters_complete<
532 LeSetExtendedAdvertisingParametersCompleteView>,
533 advertiser_id));
534 }
535 } break;
536 }
537 }
538
set_databluetooth::hci::LeAdvertisingManager::impl539 void set_data(AdvertiserId advertiser_id, bool set_scan_rsp, std::vector<GapData> data) {
540 if (!set_scan_rsp && advertising_sets_[advertiser_id].connectable) {
541 GapData gap_data;
542 gap_data.data_type_ = GapDataType::FLAGS;
543 if (advertising_sets_[advertiser_id].duration == 0) {
544 gap_data.data_.push_back(static_cast<uint8_t>(AdvertisingFlag::LE_GENERAL_DISCOVERABLE));
545 } else {
546 gap_data.data_.push_back(static_cast<uint8_t>(AdvertisingFlag::LE_LIMITED_DISCOVERABLE));
547 }
548 data.insert(data.begin(), gap_data);
549 }
550
551 // Find and fill TX Power with the correct value.
552 for (auto& gap_data : data) {
553 if (gap_data.data_type_ == GapDataType::TX_POWER_LEVEL) {
554 gap_data.data_[0] = advertising_sets_[advertiser_id].tx_power;
555 break;
556 }
557 }
558
559 switch (advertising_api_type_) {
560 case (AdvertisingApiType::LEGACY): {
561 if (set_scan_rsp) {
562 le_advertising_interface_->EnqueueCommand(
563 hci::LeSetScanResponseDataBuilder::Create(data),
564 module_handler_->BindOnceOn(
565 this, &impl::check_status_with_id<LeSetScanResponseDataCompleteView>, advertiser_id));
566 } else {
567 le_advertising_interface_->EnqueueCommand(
568 hci::LeSetAdvertisingDataBuilder::Create(data),
569 module_handler_->BindOnceOn(
570 this, &impl::check_status_with_id<LeSetAdvertisingDataCompleteView>, advertiser_id));
571 }
572 } break;
573 case (AdvertisingApiType::ANDROID_HCI): {
574 if (set_scan_rsp) {
575 le_advertising_interface_->EnqueueCommand(
576 hci::LeMultiAdvtSetScanRespBuilder::Create(data, advertiser_id),
577 module_handler_->BindOnceOn(this, &impl::check_status_with_id<LeMultiAdvtCompleteView>, advertiser_id));
578 } else {
579 le_advertising_interface_->EnqueueCommand(
580 hci::LeMultiAdvtSetDataBuilder::Create(data, advertiser_id),
581 module_handler_->BindOnceOn(this, &impl::check_status_with_id<LeMultiAdvtCompleteView>, advertiser_id));
582 }
583 } break;
584 case (AdvertisingApiType::EXTENDED): {
585 uint16_t data_len = 0;
586 // check data size
587 for (int i = 0; i < data.size(); i++) {
588 if (data[i].size() > kLeMaximumFragmentLength) {
589 LOG_WARN("AD data len shall not greater than %d", kLeMaximumFragmentLength);
590 if (advertising_callbacks_ != nullptr) {
591 if (set_scan_rsp) {
592 advertising_callbacks_->OnScanResponseDataSet(
593 advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
594 } else {
595 advertising_callbacks_->OnAdvertisingDataSet(
596 advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
597 }
598 }
599 return;
600 }
601 data_len += data[i].size();
602 }
603
604 if (data_len > le_maximum_advertising_data_length_) {
605 LOG_WARN(
606 "advertising data len exceeds le_maximum_advertising_data_length_ %d",
607 le_maximum_advertising_data_length_);
608 if (advertising_callbacks_ != nullptr) {
609 if (set_scan_rsp) {
610 advertising_callbacks_->OnScanResponseDataSet(
611 advertiser_id, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE);
612 } else {
613 advertising_callbacks_->OnAdvertisingDataSet(
614 advertiser_id, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE);
615 }
616 }
617 return;
618 }
619
620 if (data_len <= kLeMaximumFragmentLength) {
621 send_data_fragment(advertiser_id, set_scan_rsp, data, Operation::COMPLETE_ADVERTISEMENT);
622 } else {
623 std::vector<GapData> sub_data;
624 uint16_t sub_data_len = 0;
625 Operation operation = Operation::FIRST_FRAGMENT;
626
627 for (int i = 0; i < data.size(); i++) {
628 if (sub_data_len + data[i].size() > kLeMaximumFragmentLength) {
629 send_data_fragment(advertiser_id, set_scan_rsp, sub_data, operation);
630 operation = Operation::INTERMEDIATE_FRAGMENT;
631 sub_data_len = 0;
632 sub_data.clear();
633 }
634 sub_data.push_back(data[i]);
635 sub_data_len += data[i].size();
636 }
637 send_data_fragment(advertiser_id, set_scan_rsp, sub_data, Operation::LAST_FRAGMENT);
638 }
639 } break;
640 }
641 }
642
send_data_fragmentbluetooth::hci::LeAdvertisingManager::impl643 void send_data_fragment(
644 AdvertiserId advertiser_id, bool set_scan_rsp, std::vector<GapData> data, Operation operation) {
645 if (operation == Operation::COMPLETE_ADVERTISEMENT || operation == Operation::LAST_FRAGMENT) {
646 if (set_scan_rsp) {
647 le_advertising_interface_->EnqueueCommand(
648 hci::LeSetExtendedAdvertisingScanResponseBuilder::Create(
649 advertiser_id, operation, kFragment_preference, data),
650 module_handler_->BindOnceOn(
651 this, &impl::check_status_with_id<LeSetExtendedAdvertisingScanResponseCompleteView>, advertiser_id));
652 } else {
653 le_advertising_interface_->EnqueueCommand(
654 hci::LeSetExtendedAdvertisingDataBuilder::Create(advertiser_id, operation, kFragment_preference, data),
655 module_handler_->BindOnceOn(
656 this, &impl::check_status_with_id<LeSetExtendedAdvertisingDataCompleteView>, advertiser_id));
657 }
658 } else {
659 // For first and intermediate fragment, do not trigger advertising_callbacks_.
660 if (set_scan_rsp) {
661 le_advertising_interface_->EnqueueCommand(
662 hci::LeSetExtendedAdvertisingScanResponseBuilder::Create(
663 advertiser_id, operation, kFragment_preference, data),
664 module_handler_->BindOnce(impl::check_status<LeSetExtendedAdvertisingScanResponseCompleteView>));
665 } else {
666 le_advertising_interface_->EnqueueCommand(
667 hci::LeSetExtendedAdvertisingDataBuilder::Create(advertiser_id, operation, kFragment_preference, data),
668 module_handler_->BindOnce(impl::check_status<LeSetExtendedAdvertisingDataCompleteView>));
669 }
670 }
671 }
672
enable_advertiserbluetooth::hci::LeAdvertisingManager::impl673 void enable_advertiser(
674 AdvertiserId advertiser_id, bool enable, uint16_t duration, uint8_t max_extended_advertising_events) {
675 EnabledSet curr_set;
676 curr_set.advertising_handle_ = advertiser_id;
677 curr_set.duration_ = duration;
678 curr_set.max_extended_advertising_events_ = max_extended_advertising_events;
679 std::vector<EnabledSet> enabled_sets = {curr_set};
680 Enable enable_value = enable ? Enable::ENABLED : Enable::DISABLED;
681
682 switch (advertising_api_type_) {
683 case (AdvertisingApiType::LEGACY): {
684 le_advertising_interface_->EnqueueCommand(
685 hci::LeSetAdvertisingEnableBuilder::Create(enable_value),
686 module_handler_->BindOnceOn(
687 this,
688 &impl::on_set_advertising_enable_complete<LeSetAdvertisingEnableCompleteView>,
689 enable,
690 enabled_sets));
691 } break;
692 case (AdvertisingApiType::ANDROID_HCI): {
693 le_advertising_interface_->EnqueueCommand(
694 hci::LeMultiAdvtSetEnableBuilder::Create(enable_value, advertiser_id),
695 module_handler_->BindOnceOn(
696 this, &impl::on_set_advertising_enable_complete<LeMultiAdvtCompleteView>, enable, enabled_sets));
697 } break;
698 case (AdvertisingApiType::EXTENDED): {
699 le_advertising_interface_->EnqueueCommand(
700 hci::LeSetExtendedAdvertisingEnableBuilder::Create(enable_value, enabled_sets),
701 module_handler_->BindOnceOn(
702 this,
703 &impl::on_set_extended_advertising_enable_complete<LeSetExtendedAdvertisingEnableCompleteView>,
704 enable,
705 enabled_sets));
706 } break;
707 }
708
709 if (enable) {
710 enabled_sets_[advertiser_id].advertising_handle_ = advertiser_id;
711 advertising_sets_[advertiser_id].duration = duration;
712 advertising_sets_[advertiser_id].max_extended_advertising_events = max_extended_advertising_events;
713 } else {
714 enabled_sets_[advertiser_id].advertising_handle_ = kInvalidHandle;
715 if (advertising_sets_[advertiser_id].address_rotation_alarm != nullptr) {
716 advertising_sets_[advertiser_id].address_rotation_alarm->Cancel();
717 advertising_sets_[advertiser_id].address_rotation_alarm.reset();
718 }
719 }
720 }
721
set_periodic_parameterbluetooth::hci::LeAdvertisingManager::impl722 void set_periodic_parameter(
723 AdvertiserId advertiser_id, PeriodicAdvertisingParameters periodic_advertising_parameters) {
724 uint8_t include_tx_power = periodic_advertising_parameters.properties >>
725 PeriodicAdvertisingParameters::AdvertisingProperty::INCLUDE_TX_POWER;
726
727 le_advertising_interface_->EnqueueCommand(
728 hci::LeSetPeriodicAdvertisingParamBuilder::Create(
729 advertiser_id,
730 periodic_advertising_parameters.min_interval,
731 periodic_advertising_parameters.max_interval,
732 include_tx_power),
733 module_handler_->BindOnceOn(
734 this, &impl::check_status_with_id<LeSetPeriodicAdvertisingParamCompleteView>, advertiser_id));
735 }
736
set_periodic_databluetooth::hci::LeAdvertisingManager::impl737 void set_periodic_data(AdvertiserId advertiser_id, std::vector<GapData> data) {
738 uint16_t data_len = 0;
739 // check data size
740 for (int i = 0; i < data.size(); i++) {
741 if (data[i].size() > kLeMaximumFragmentLength) {
742 LOG_WARN("AD data len shall not greater than %d", kLeMaximumFragmentLength);
743 if (advertising_callbacks_ != nullptr) {
744 advertising_callbacks_->OnPeriodicAdvertisingDataSet(
745 advertiser_id, AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR);
746 }
747 return;
748 }
749 data_len += data[i].size();
750 }
751
752 if (data_len > le_maximum_advertising_data_length_) {
753 LOG_WARN(
754 "advertising data len exceeds le_maximum_advertising_data_length_ %d", le_maximum_advertising_data_length_);
755 if (advertising_callbacks_ != nullptr) {
756 advertising_callbacks_->OnPeriodicAdvertisingDataSet(
757 advertiser_id, AdvertisingCallback::AdvertisingStatus::DATA_TOO_LARGE);
758 }
759 return;
760 }
761
762 if (data_len <= kLeMaximumFragmentLength) {
763 send_periodic_data_fragment(advertiser_id, data, Operation::COMPLETE_ADVERTISEMENT);
764 } else {
765 std::vector<GapData> sub_data;
766 uint16_t sub_data_len = 0;
767 Operation operation = Operation::FIRST_FRAGMENT;
768
769 for (int i = 0; i < data.size(); i++) {
770 if (sub_data_len + data[i].size() > kLeMaximumFragmentLength) {
771 send_periodic_data_fragment(advertiser_id, sub_data, operation);
772 operation = Operation::INTERMEDIATE_FRAGMENT;
773 sub_data_len = 0;
774 sub_data.clear();
775 }
776 sub_data.push_back(data[i]);
777 sub_data_len += data[i].size();
778 }
779 send_periodic_data_fragment(advertiser_id, sub_data, Operation::LAST_FRAGMENT);
780 }
781 }
782
send_periodic_data_fragmentbluetooth::hci::LeAdvertisingManager::impl783 void send_periodic_data_fragment(AdvertiserId advertiser_id, std::vector<GapData> data, Operation operation) {
784 if (operation == Operation::COMPLETE_ADVERTISEMENT || operation == Operation::LAST_FRAGMENT) {
785 le_advertising_interface_->EnqueueCommand(
786 hci::LeSetPeriodicAdvertisingDataBuilder::Create(advertiser_id, operation, data),
787 module_handler_->BindOnceOn(
788 this, &impl::check_status_with_id<LeSetPeriodicAdvertisingDataCompleteView>, advertiser_id));
789 } else {
790 // For first and intermediate fragment, do not trigger advertising_callbacks_.
791 le_advertising_interface_->EnqueueCommand(
792 hci::LeSetPeriodicAdvertisingDataBuilder::Create(advertiser_id, operation, data),
793 module_handler_->BindOnce(impl::check_status<LeSetPeriodicAdvertisingDataCompleteView>));
794 }
795 }
796
enable_periodic_advertisingbluetooth::hci::LeAdvertisingManager::impl797 void enable_periodic_advertising(AdvertiserId advertiser_id, bool enable) {
798 Enable enable_value = enable ? Enable::ENABLED : Enable::DISABLED;
799
800 le_advertising_interface_->EnqueueCommand(
801 hci::LeSetPeriodicAdvertisingEnableBuilder::Create(enable_value, advertiser_id),
802 module_handler_->BindOnceOn(
803 this,
804 &impl::on_set_periodic_advertising_enable_complete<LeSetPeriodicAdvertisingEnableCompleteView>,
805 enable,
806 advertiser_id));
807 }
808
OnPausebluetooth::hci::LeAdvertisingManager::impl809 void OnPause() override {
810 paused = true;
811 if (!advertising_sets_.empty()) {
812 std::vector<EnabledSet> enabled_sets = {};
813 for (size_t i = 0; i < enabled_sets_.size(); i++) {
814 EnabledSet curr_set = enabled_sets_[i];
815 if (enabled_sets_[i].advertising_handle_ != kInvalidHandle) {
816 enabled_sets.push_back(enabled_sets_[i]);
817 }
818 }
819
820 switch (advertising_api_type_) {
821 case (AdvertisingApiType::LEGACY): {
822 le_advertising_interface_->EnqueueCommand(
823 hci::LeSetAdvertisingEnableBuilder::Create(Enable::DISABLED),
824 module_handler_->BindOnceOn(
825 this,
826 &impl::on_set_advertising_enable_complete<LeSetAdvertisingEnableCompleteView>,
827 false,
828 enabled_sets));
829 } break;
830 case (AdvertisingApiType::ANDROID_HCI): {
831 for (size_t i = 0; i < enabled_sets_.size(); i++) {
832 uint8_t id = enabled_sets_[i].advertising_handle_;
833 if (id != kInvalidHandle) {
834 le_advertising_interface_->EnqueueCommand(
835 hci::LeMultiAdvtSetEnableBuilder::Create(Enable::DISABLED, id),
836 module_handler_->BindOnce(impl::check_status<LeMultiAdvtCompleteView>));
837 }
838 }
839 } break;
840 case (AdvertisingApiType::EXTENDED): {
841 if (enabled_sets.size() != 0) {
842 le_advertising_interface_->EnqueueCommand(
843 hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::DISABLED, enabled_sets),
844 module_handler_->BindOnceOn(
845 this,
846 &impl::on_set_extended_advertising_enable_complete<LeSetExtendedAdvertisingEnableCompleteView>,
847 false,
848 enabled_sets));
849 }
850 } break;
851 }
852 }
853 le_address_manager_->AckPause(this);
854 }
855
OnResumebluetooth::hci::LeAdvertisingManager::impl856 void OnResume() override {
857 paused = false;
858 if (!advertising_sets_.empty()) {
859 std::vector<EnabledSet> enabled_sets = {};
860 for (size_t i = 0; i < enabled_sets_.size(); i++) {
861 EnabledSet curr_set = enabled_sets_[i];
862 if (enabled_sets_[i].advertising_handle_ != kInvalidHandle) {
863 enabled_sets.push_back(enabled_sets_[i]);
864 }
865 }
866
867 switch (advertising_api_type_) {
868 case (AdvertisingApiType::LEGACY): {
869 le_advertising_interface_->EnqueueCommand(
870 hci::LeSetAdvertisingEnableBuilder::Create(Enable::ENABLED),
871 module_handler_->BindOnceOn(
872 this,
873 &impl::on_set_advertising_enable_complete<LeSetAdvertisingEnableCompleteView>,
874 true,
875 enabled_sets));
876 } break;
877 case (AdvertisingApiType::ANDROID_HCI): {
878 for (size_t i = 0; i < enabled_sets_.size(); i++) {
879 uint8_t id = enabled_sets_[i].advertising_handle_;
880 if (id != kInvalidHandle) {
881 le_advertising_interface_->EnqueueCommand(
882 hci::LeMultiAdvtSetEnableBuilder::Create(Enable::ENABLED, id),
883 module_handler_->BindOnce(impl::check_status<LeMultiAdvtCompleteView>));
884 }
885 }
886 } break;
887 case (AdvertisingApiType::EXTENDED): {
888 if (enabled_sets.size() != 0) {
889 le_advertising_interface_->EnqueueCommand(
890 hci::LeSetExtendedAdvertisingEnableBuilder::Create(Enable::ENABLED, enabled_sets),
891 module_handler_->BindOnceOn(
892 this,
893 &impl::on_set_extended_advertising_enable_complete<LeSetExtendedAdvertisingEnableCompleteView>,
894 true,
895 enabled_sets));
896 }
897 } break;
898 }
899 }
900 le_address_manager_->AckResume(this);
901 }
902
903 common::Callback<void(Address, AddressType)> scan_callback_;
904 common::ContextualCallback<void(ErrorCode, uint16_t, hci::AddressWithType)> set_terminated_callback_{};
905 AdvertisingCallback* advertising_callbacks_ = nullptr;
906 os::Handler* registered_handler_{nullptr};
907 Module* module_;
908 os::Handler* module_handler_;
909 hci::HciLayer* hci_layer_;
910 hci::Controller* controller_;
911 uint16_t le_maximum_advertising_data_length_;
912 int8_t le_physical_channel_tx_power_ = 0;
913 hci::LeAdvertisingInterface* le_advertising_interface_;
914 std::map<AdvertiserId, Advertiser> advertising_sets_;
915 hci::LeAddressManager* le_address_manager_;
916 hci::AclManager* acl_manager_;
917 bool address_manager_registered = false;
918 bool paused = false;
919
920 std::mutex id_mutex_;
921 size_t num_instances_;
922 std::vector<hci::EnabledSet> enabled_sets_;
923 std::map<uint8_t, int> id_map_;
924
925 AdvertisingApiType advertising_api_type_{0};
926
on_read_advertising_physical_channel_tx_powerbluetooth::hci::LeAdvertisingManager::impl927 void on_read_advertising_physical_channel_tx_power(CommandCompleteView view) {
928 auto complete_view = LeReadAdvertisingPhysicalChannelTxPowerCompleteView::Create(view);
929 ASSERT(complete_view.IsValid());
930 if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
931 LOG_INFO("Got a command complete with status %s", ErrorCodeText(complete_view.GetStatus()).c_str());
932 return;
933 }
934 le_physical_channel_tx_power_ = complete_view.GetTransmitPowerLevel();
935 }
936
937 template <class View>
on_set_advertising_enable_completebluetooth::hci::LeAdvertisingManager::impl938 void on_set_advertising_enable_complete(bool enable, std::vector<EnabledSet> enabled_sets, CommandCompleteView view) {
939 ASSERT(view.IsValid());
940 auto complete_view = View::Create(view);
941 ASSERT(complete_view.IsValid());
942 AdvertisingCallback::AdvertisingStatus advertising_status = AdvertisingCallback::AdvertisingStatus::SUCCESS;
943 if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
944 LOG_INFO("Got a command complete with status %s", ErrorCodeText(complete_view.GetStatus()).c_str());
945 }
946
947 if (advertising_callbacks_ == nullptr) {
948 return;
949 }
950 for (EnabledSet enabled_set : enabled_sets) {
951 bool started = advertising_sets_[enabled_set.advertising_handle_].started;
952 uint8_t id = enabled_set.advertising_handle_;
953 if (id == kInvalidHandle) {
954 continue;
955 }
956
957 if (started) {
958 advertising_callbacks_->OnAdvertisingEnabled(id, enable, advertising_status);
959 } else {
960 int reg_id = id_map_[id];
961 advertising_sets_[enabled_set.advertising_handle_].started = true;
962 advertising_callbacks_->OnAdvertisingSetStarted(reg_id, id, le_physical_channel_tx_power_, advertising_status);
963 }
964 }
965 }
966
967 template <class View>
on_set_extended_advertising_enable_completebluetooth::hci::LeAdvertisingManager::impl968 void on_set_extended_advertising_enable_complete(
969 bool enable, std::vector<EnabledSet> enabled_sets, CommandCompleteView view) {
970 ASSERT(view.IsValid());
971 auto complete_view = LeSetExtendedAdvertisingEnableCompleteView::Create(view);
972 ASSERT(complete_view.IsValid());
973 AdvertisingCallback::AdvertisingStatus advertising_status = AdvertisingCallback::AdvertisingStatus::SUCCESS;
974 if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
975 LOG_INFO("Got a command complete with status %s", ErrorCodeText(complete_view.GetStatus()).c_str());
976 advertising_status = AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR;
977 }
978
979 if (advertising_callbacks_ == nullptr) {
980 return;
981 }
982
983 for (EnabledSet enabled_set : enabled_sets) {
984 int8_t tx_power = advertising_sets_[enabled_set.advertising_handle_].tx_power;
985 bool started = advertising_sets_[enabled_set.advertising_handle_].started;
986 uint8_t id = enabled_set.advertising_handle_;
987 if (id == kInvalidHandle) {
988 continue;
989 }
990
991 if (started) {
992 advertising_callbacks_->OnAdvertisingEnabled(id, enable, advertising_status);
993 } else {
994 int reg_id = id_map_[id];
995 advertising_sets_[enabled_set.advertising_handle_].started = true;
996 advertising_callbacks_->OnAdvertisingSetStarted(reg_id, id, tx_power, advertising_status);
997 }
998 }
999 }
1000
1001 template <class View>
on_set_extended_advertising_parameters_completebluetooth::hci::LeAdvertisingManager::impl1002 void on_set_extended_advertising_parameters_complete(AdvertiserId id, CommandCompleteView view) {
1003 ASSERT(view.IsValid());
1004 auto complete_view = LeSetExtendedAdvertisingParametersCompleteView::Create(view);
1005 ASSERT(complete_view.IsValid());
1006 AdvertisingCallback::AdvertisingStatus advertising_status = AdvertisingCallback::AdvertisingStatus::SUCCESS;
1007 if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
1008 LOG_INFO("Got a command complete with status %s", ErrorCodeText(complete_view.GetStatus()).c_str());
1009 advertising_status = AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR;
1010 }
1011 advertising_sets_[id].tx_power = complete_view.GetSelectedTxPower();
1012
1013 if (advertising_sets_[id].started) {
1014 advertising_callbacks_->OnAdvertisingParametersUpdated(id, advertising_sets_[id].tx_power, advertising_status);
1015 }
1016 }
1017
1018 template <class View>
on_set_periodic_advertising_enable_completebluetooth::hci::LeAdvertisingManager::impl1019 void on_set_periodic_advertising_enable_complete(bool enable, AdvertiserId id, CommandCompleteView view) {
1020 ASSERT(view.IsValid());
1021 auto complete_view = LeSetPeriodicAdvertisingEnableCompleteView::Create(view);
1022 ASSERT(complete_view.IsValid());
1023 AdvertisingCallback::AdvertisingStatus advertising_status = AdvertisingCallback::AdvertisingStatus::SUCCESS;
1024 if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
1025 LOG_INFO("Got a command complete with status %s", ErrorCodeText(complete_view.GetStatus()).c_str());
1026 advertising_status = AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR;
1027 }
1028
1029 if (advertising_callbacks_ == nullptr || !advertising_sets_[id].started) {
1030 return;
1031 }
1032
1033 advertising_callbacks_->OnPeriodicAdvertisingEnabled(id, enable, advertising_status);
1034 }
1035
1036 template <class View>
on_set_advertising_set_random_address_completebluetooth::hci::LeAdvertisingManager::impl1037 void on_set_advertising_set_random_address_complete(
1038 AdvertiserId advertiser_id, AddressWithType address_with_type, CommandCompleteView view) {
1039 ASSERT(view.IsValid());
1040 auto complete_view = LeSetExtendedAdvertisingRandomAddressCompleteView::Create(view);
1041 ASSERT(complete_view.IsValid());
1042 if (complete_view.GetStatus() != ErrorCode::SUCCESS) {
1043 LOG_INFO("Got a command complete with status %s", ErrorCodeText(complete_view.GetStatus()).c_str());
1044 } else {
1045 LOG_INFO(
1046 "update random address for advertising set %d : %s",
1047 advertiser_id,
1048 address_with_type.GetAddress().ToString().c_str());
1049 advertising_sets_[advertiser_id].current_address = address_with_type;
1050 }
1051 }
1052
1053 template <class View>
check_status_with_idbluetooth::hci::LeAdvertisingManager::impl1054 void check_status_with_id(AdvertiserId id, CommandCompleteView view) {
1055 ASSERT(view.IsValid());
1056 auto status_view = View::Create(view);
1057 ASSERT(status_view.IsValid());
1058 if (status_view.GetStatus() != ErrorCode::SUCCESS) {
1059 LOG_INFO(
1060 "Got a Command complete %s, status %s",
1061 OpCodeText(view.GetCommandOpCode()).c_str(),
1062 ErrorCodeText(status_view.GetStatus()).c_str());
1063 }
1064 AdvertisingCallback::AdvertisingStatus advertising_status = AdvertisingCallback::AdvertisingStatus::SUCCESS;
1065 if (status_view.GetStatus() != ErrorCode::SUCCESS) {
1066 LOG_INFO("Got a command complete with status %s", ErrorCodeText(status_view.GetStatus()).c_str());
1067 advertising_status = AdvertisingCallback::AdvertisingStatus::INTERNAL_ERROR;
1068 }
1069
1070 // Do not trigger callback if the advertiser not stated yet
1071 if (advertising_callbacks_ == nullptr || !advertising_sets_[id].started) {
1072 return;
1073 }
1074
1075 OpCode opcode = view.GetCommandOpCode();
1076
1077 switch (opcode) {
1078 case OpCode::LE_SET_ADVERTISING_PARAMETERS:
1079 advertising_callbacks_->OnAdvertisingParametersUpdated(id, le_physical_channel_tx_power_, advertising_status);
1080 break;
1081 case OpCode::LE_SET_ADVERTISING_DATA:
1082 case OpCode::LE_SET_EXTENDED_ADVERTISING_DATA:
1083 advertising_callbacks_->OnAdvertisingDataSet(id, advertising_status);
1084 break;
1085 case OpCode::LE_SET_SCAN_RESPONSE_DATA:
1086 case OpCode::LE_SET_EXTENDED_ADVERTISING_SCAN_RESPONSE:
1087 advertising_callbacks_->OnScanResponseDataSet(id, advertising_status);
1088 break;
1089 case OpCode::LE_SET_PERIODIC_ADVERTISING_PARAM:
1090 advertising_callbacks_->OnPeriodicAdvertisingParametersUpdated(id, advertising_status);
1091 break;
1092 case OpCode::LE_SET_PERIODIC_ADVERTISING_DATA:
1093 advertising_callbacks_->OnPeriodicAdvertisingDataSet(id, advertising_status);
1094 break;
1095 case OpCode::LE_MULTI_ADVT: {
1096 auto command_view = LeMultiAdvtCompleteView::Create(view);
1097 ASSERT(command_view.IsValid());
1098 auto sub_opcode = command_view.GetSubCmd();
1099 switch (sub_opcode) {
1100 case SubOcf::SET_PARAM:
1101 advertising_callbacks_->OnAdvertisingParametersUpdated(
1102 id, le_physical_channel_tx_power_, advertising_status);
1103 break;
1104 case SubOcf::SET_DATA:
1105 advertising_callbacks_->OnAdvertisingDataSet(id, advertising_status);
1106 break;
1107 case SubOcf::SET_SCAN_RESP:
1108 advertising_callbacks_->OnScanResponseDataSet(id, advertising_status);
1109 break;
1110 default:
1111 LOG_WARN("Unexpected sub event type %s", SubOcfText(command_view.GetSubCmd()).c_str());
1112 }
1113 } break;
1114 default:
1115 LOG_WARN("Unexpected event type %s", OpCodeText(view.GetCommandOpCode()).c_str());
1116 }
1117 }
1118
1119 template <class View>
check_statusbluetooth::hci::LeAdvertisingManager::impl1120 static void check_status(CommandCompleteView view) {
1121 ASSERT(view.IsValid());
1122 auto status_view = View::Create(view);
1123 ASSERT(status_view.IsValid());
1124 if (status_view.GetStatus() != ErrorCode::SUCCESS) {
1125 LOG_INFO(
1126 "Got a Command complete %s, status %s",
1127 OpCodeText(view.GetCommandOpCode()).c_str(),
1128 ErrorCodeText(status_view.GetStatus()).c_str());
1129 }
1130 }
1131 };
1132
LeAdvertisingManager()1133 LeAdvertisingManager::LeAdvertisingManager() {
1134 pimpl_ = std::make_unique<impl>(this);
1135 }
1136
ListDependencies(ModuleList * list)1137 void LeAdvertisingManager::ListDependencies(ModuleList* list) {
1138 list->add<hci::HciLayer>();
1139 list->add<hci::Controller>();
1140 list->add<hci::AclManager>();
1141 }
1142
Start()1143 void LeAdvertisingManager::Start() {
1144 pimpl_->start(GetHandler(), GetDependency<hci::HciLayer>(), GetDependency<hci::Controller>(),
1145 GetDependency<AclManager>());
1146 }
1147
Stop()1148 void LeAdvertisingManager::Stop() {
1149 pimpl_.reset();
1150 }
1151
ToString() const1152 std::string LeAdvertisingManager::ToString() const {
1153 return "Le Advertising Manager";
1154 }
1155
GetNumberOfAdvertisingInstances() const1156 size_t LeAdvertisingManager::GetNumberOfAdvertisingInstances() const {
1157 return pimpl_->GetNumberOfAdvertisingInstances();
1158 }
1159
create_advertiser(const AdvertisingConfig config,const common::Callback<void (Address,AddressType)> & scan_callback,const common::Callback<void (ErrorCode,uint8_t,uint8_t)> & set_terminated_callback,os::Handler * handler)1160 AdvertiserId LeAdvertisingManager::create_advertiser(
1161 const AdvertisingConfig config,
1162 const common::Callback<void(Address, AddressType)>& scan_callback,
1163 const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback,
1164 os::Handler* handler) {
1165 if (config.peer_address == Address::kEmpty) {
1166 if (config.own_address_type == hci::OwnAddressType::RESOLVABLE_OR_PUBLIC_ADDRESS ||
1167 config.own_address_type == hci::OwnAddressType::RESOLVABLE_OR_RANDOM_ADDRESS) {
1168 LOG_WARN("Peer address can not be empty");
1169 return kInvalidId;
1170 }
1171 if (config.advertising_type == hci::AdvertisingType::ADV_DIRECT_IND ||
1172 config.advertising_type == hci::AdvertisingType::ADV_DIRECT_IND_LOW) {
1173 LOG_WARN("Peer address can not be empty for directed advertising");
1174 return kInvalidId;
1175 }
1176 }
1177 AdvertiserId id = pimpl_->allocate_advertiser();
1178 if (id == kInvalidId) {
1179 return id;
1180 }
1181 GetHandler()->Post(common::BindOnce(&impl::create_advertiser, common::Unretained(pimpl_.get()), id, config,
1182 scan_callback, set_terminated_callback, handler));
1183 return id;
1184 }
1185
ExtendedCreateAdvertiser(int reg_id,const ExtendedAdvertisingConfig config,const common::Callback<void (Address,AddressType)> & scan_callback,const common::Callback<void (ErrorCode,uint8_t,uint8_t)> & set_terminated_callback,uint16_t duration,uint8_t max_extended_advertising_events,os::Handler * handler)1186 AdvertiserId LeAdvertisingManager::ExtendedCreateAdvertiser(
1187 int reg_id,
1188 const ExtendedAdvertisingConfig config,
1189 const common::Callback<void(Address, AddressType)>& scan_callback,
1190 const common::Callback<void(ErrorCode, uint8_t, uint8_t)>& set_terminated_callback,
1191 uint16_t duration,
1192 uint8_t max_extended_advertising_events,
1193 os::Handler* handler) {
1194 AdvertisingApiType advertising_api_type = pimpl_->get_advertising_api_type();
1195 if (advertising_api_type != AdvertisingApiType::EXTENDED) {
1196 return create_advertiser(config, scan_callback, set_terminated_callback, handler);
1197 };
1198
1199 if (config.directed) {
1200 if (config.peer_address == Address::kEmpty) {
1201 LOG_INFO("Peer address can not be empty for directed advertising");
1202 return kInvalidId;
1203 }
1204 }
1205 if (config.channel_map == 0) {
1206 LOG_INFO("At least one channel must be set in the map");
1207 return kInvalidId;
1208 }
1209 if (!config.legacy_pdus) {
1210 if (config.connectable && config.scannable) {
1211 LOG_INFO("Extended advertising PDUs can not be connectable and scannable");
1212 return kInvalidId;
1213 }
1214 if (config.high_duty_directed_connectable) {
1215 LOG_INFO("Extended advertising PDUs can not be high duty cycle");
1216 return kInvalidId;
1217 }
1218 }
1219 if (config.interval_min > config.interval_max) {
1220 LOG_INFO("Advertising interval: min (%hu) > max (%hu)", config.interval_min, config.interval_max);
1221 return kInvalidId;
1222 }
1223 AdvertiserId id = pimpl_->allocate_advertiser();
1224 if (id == kInvalidId) {
1225 return id;
1226 }
1227 CallOn(
1228 pimpl_.get(),
1229 &impl::create_extended_advertiser,
1230 reg_id,
1231 id,
1232 config,
1233 scan_callback,
1234 set_terminated_callback,
1235 duration,
1236 max_extended_advertising_events,
1237 handler);
1238 return id;
1239 }
1240
SetParameters(AdvertiserId advertiser_id,ExtendedAdvertisingConfig config)1241 void LeAdvertisingManager::SetParameters(AdvertiserId advertiser_id, ExtendedAdvertisingConfig config) {
1242 CallOn(pimpl_.get(), &impl::set_parameters, advertiser_id, config);
1243 }
1244
SetData(AdvertiserId advertiser_id,bool set_scan_rsp,std::vector<GapData> data)1245 void LeAdvertisingManager::SetData(AdvertiserId advertiser_id, bool set_scan_rsp, std::vector<GapData> data) {
1246 CallOn(pimpl_.get(), &impl::set_data, advertiser_id, set_scan_rsp, data);
1247 }
1248
EnableAdvertiser(AdvertiserId advertiser_id,bool enable,uint16_t duration,uint8_t max_extended_advertising_events)1249 void LeAdvertisingManager::EnableAdvertiser(
1250 AdvertiserId advertiser_id, bool enable, uint16_t duration, uint8_t max_extended_advertising_events) {
1251 CallOn(pimpl_.get(), &impl::enable_advertiser, advertiser_id, enable, duration, max_extended_advertising_events);
1252 }
1253
SetPeriodicParameters(AdvertiserId advertiser_id,PeriodicAdvertisingParameters periodic_advertising_parameters)1254 void LeAdvertisingManager::SetPeriodicParameters(
1255 AdvertiserId advertiser_id, PeriodicAdvertisingParameters periodic_advertising_parameters) {
1256 CallOn(pimpl_.get(), &impl::set_periodic_parameter, advertiser_id, periodic_advertising_parameters);
1257 }
1258
SetPeriodicData(AdvertiserId advertiser_id,std::vector<GapData> data)1259 void LeAdvertisingManager::SetPeriodicData(AdvertiserId advertiser_id, std::vector<GapData> data) {
1260 CallOn(pimpl_.get(), &impl::set_periodic_data, advertiser_id, data);
1261 }
1262
EnablePeriodicAdvertising(AdvertiserId advertiser_id,bool enable)1263 void LeAdvertisingManager::EnablePeriodicAdvertising(AdvertiserId advertiser_id, bool enable) {
1264 CallOn(pimpl_.get(), &impl::enable_periodic_advertising, advertiser_id, enable);
1265 }
1266
RemoveAdvertiser(AdvertiserId advertiser_id)1267 void LeAdvertisingManager::RemoveAdvertiser(AdvertiserId advertiser_id) {
1268 CallOn(pimpl_.get(), &impl::remove_advertiser, advertiser_id);
1269 }
1270
RegisterAdvertisingCallback(AdvertisingCallback * advertising_callback)1271 void LeAdvertisingManager::RegisterAdvertisingCallback(AdvertisingCallback* advertising_callback) {
1272 CallOn(pimpl_.get(), &impl::register_advertising_callback, advertising_callback);
1273 }
1274
1275 } // namespace hci
1276 } // namespace bluetooth
1277