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 
__anon53b70a730102() 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