1 /******************************************************************************
2 *
3 * Copyright 2017 The Android Open Source Project
4 * Copyright 2014 Broadcom Corporation
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at:
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 ******************************************************************************/
19
20 #include "bt_target.h"
21 #include "device/include/controller.h"
22 #include "osi/include/alarm.h"
23
24 #include "ble_advertiser.h"
25 #include "ble_advertiser_hci_interface.h"
26 #include "btm_int_types.h"
27 #include "stack/btm/btm_ble_int.h"
28
29 #include <string.h>
30 #include <queue>
31 #include <vector>
32
33 #include <base/bind.h>
34 #include <base/bind_helpers.h>
35 #include <base/location.h>
36 #include <base/logging.h>
37 #include <base/memory/weak_ptr.h>
38 #include <base/strings/string_number_conversions.h>
39 #include <base/time/time.h>
40
41 using base::Bind;
42 using base::TimeDelta;
43 using base::TimeTicks;
44 using RegisterCb =
45 base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)>;
46 using IdTxPowerStatusCb = base::Callback<void(
47 uint8_t /* inst_id */, int8_t /* tx_power */, uint8_t /* status */)>;
48 using SetEnableData = BleAdvertiserHciInterface::SetEnableData;
49 extern void btm_gen_resolvable_private_addr(
50 base::Callback<void(const RawAddress& rpa)> cb);
51
52 constexpr int ADV_DATA_LEN_MAX = 251;
53
54 namespace {
55
is_connectable(uint16_t advertising_event_properties)56 bool is_connectable(uint16_t advertising_event_properties) {
57 return advertising_event_properties & 0x01;
58 }
59
60 struct AdvertisingInstance {
61 uint8_t inst_id;
62 bool in_use;
63 uint8_t advertising_event_properties;
64 alarm_t* adv_raddr_timer;
65 int8_t tx_power;
66 uint16_t duration; // 1 unit is 10ms
67 uint8_t maxExtAdvEvents;
68 alarm_t* timeout_timer;
69 uint8_t own_address_type;
70 RawAddress own_address;
71 MultiAdvCb timeout_cb;
72 bool address_update_required;
73 bool periodic_enabled;
74 uint32_t advertising_interval; // 1 unit is 0.625 ms
75
76 /* When true, advertising set is enabled, or last scheduled call to "LE Set
77 * Extended Advertising Set Enable" is to enable this advertising set. Any
78 * command scheduled when in this state will execute when the set is enabled,
79 * unless enabling fails.
80 *
81 * When false, advertising set is disabled, or last scheduled call to "LE Set
82 * Extended Advertising Set Enable" is to disable this advertising set. Any
83 * command scheduled when in this state will execute when the set is disabled.
84 */
85 bool enable_status;
86 TimeTicks enable_time;
87
IsEnabled__anon08ab64bc0111::AdvertisingInstance88 bool IsEnabled() { return enable_status; }
89
IsConnectable__anon08ab64bc0111::AdvertisingInstance90 bool IsConnectable() { return is_connectable(advertising_event_properties); }
91
AdvertisingInstance__anon08ab64bc0111::AdvertisingInstance92 AdvertisingInstance(int inst_id)
93 : inst_id(inst_id),
94 in_use(false),
95 advertising_event_properties(0),
96 tx_power(0),
97 duration(0),
98 timeout_timer(nullptr),
99 own_address_type(0),
100 own_address(RawAddress::kEmpty),
101 address_update_required(false),
102 periodic_enabled(false),
103 enable_status(false) {
104 adv_raddr_timer = alarm_new_periodic("btm_ble.adv_raddr_timer");
105 }
106
~AdvertisingInstance__anon08ab64bc0111::AdvertisingInstance107 ~AdvertisingInstance() {
108 alarm_free(adv_raddr_timer);
109 adv_raddr_timer = nullptr;
110 if (timeout_timer) {
111 alarm_free(timeout_timer);
112 timeout_timer = nullptr;
113 }
114 }
115 };
116
117 void btm_ble_adv_raddr_timer_timeout(void* data);
118
119 struct closure_data {
120 base::Closure user_task;
121 base::Location posted_from;
122 };
123
alarm_closure_cb(void * p)124 static void alarm_closure_cb(void* p) {
125 closure_data* data = (closure_data*)p;
126 VLOG(1) << "executing timer scheduled at %s" << data->posted_from.ToString();
127 data->user_task.Run();
128 delete data;
129 }
130
131 // Periodic alarms are not supported, because we clean up data in callback
alarm_set_closure(const base::Location & posted_from,alarm_t * alarm,uint64_t interval_ms,base::Closure user_task)132 void alarm_set_closure(const base::Location& posted_from, alarm_t* alarm,
133 uint64_t interval_ms, base::Closure user_task) {
134 closure_data* data = new closure_data;
135 data->posted_from = posted_from;
136 data->user_task = std::move(user_task);
137 VLOG(1) << "scheduling timer %s" << data->posted_from.ToString();
138 alarm_set_on_mloop(alarm, interval_ms, alarm_closure_cb, data);
139 }
140
141 class BleAdvertisingManagerImpl;
142
143 /* a temporary type for holding all the data needed in callbacks below*/
144 struct CreatorParams {
145 uint8_t inst_id;
146 base::WeakPtr<BleAdvertisingManagerImpl> self;
147 IdTxPowerStatusCb cb;
148 tBTM_BLE_ADV_PARAMS params;
149 std::vector<uint8_t> advertise_data;
150 std::vector<uint8_t> scan_response_data;
151 tBLE_PERIODIC_ADV_PARAMS periodic_params;
152 std::vector<uint8_t> periodic_data;
153 uint16_t duration;
154 uint8_t maxExtAdvEvents;
155 RegisterCb timeout_cb;
156 };
157
158 using c_type = std::unique_ptr<CreatorParams>;
159
160 BleAdvertisingManager* instance;
161 base::WeakPtr<BleAdvertisingManagerImpl> instance_weakptr;
162
163 class BleAdvertisingManagerImpl
164 : public BleAdvertisingManager,
165 public BleAdvertiserHciInterface::AdvertisingEventObserver {
166 public:
BleAdvertisingManagerImpl(BleAdvertiserHciInterface * interface)167 BleAdvertisingManagerImpl(BleAdvertiserHciInterface* interface)
168 : hci_interface(interface), weak_factory_(this) {
169 hci_interface->ReadInstanceCount(
170 base::Bind(&BleAdvertisingManagerImpl::ReadInstanceCountCb,
171 weak_factory_.GetWeakPtr()));
172 }
173
~BleAdvertisingManagerImpl()174 ~BleAdvertisingManagerImpl() override { adv_inst.clear(); }
175
GetOwnAddress(uint8_t inst_id,GetAddressCallback cb)176 void GetOwnAddress(uint8_t inst_id, GetAddressCallback cb) override {
177 cb.Run(adv_inst[inst_id].own_address_type, adv_inst[inst_id].own_address);
178 }
179
ReadInstanceCountCb(uint8_t instance_count)180 void ReadInstanceCountCb(uint8_t instance_count) {
181 this->inst_count = instance_count;
182 adv_inst.reserve(inst_count);
183 /* Initialize adv instance indices and IDs. */
184 for (uint8_t i = 0; i < inst_count; i++) {
185 adv_inst.emplace_back(i);
186 }
187 }
188
GenerateRpa(base::Callback<void (const RawAddress &)> cb)189 void GenerateRpa(base::Callback<void(const RawAddress&)> cb) {
190 btm_gen_resolvable_private_addr(std::move(cb));
191 }
192
ConfigureRpa(AdvertisingInstance * p_inst,MultiAdvCb configuredCb)193 void ConfigureRpa(AdvertisingInstance* p_inst, MultiAdvCb configuredCb) {
194 /* Connectable advertising set must be disabled when updating RPA */
195 bool restart = p_inst->IsEnabled() && p_inst->IsConnectable();
196
197 // If there is any form of timeout on the set, schedule address update when
198 // the set stops, because there is no good way to compute new timeout value.
199 // Maximum duration value is around 10 minutes, so this is safe.
200 if (restart && (p_inst->duration || p_inst->maxExtAdvEvents)) {
201 p_inst->address_update_required = true;
202 configuredCb.Run(0x01);
203 return;
204 }
205
206 GenerateRpa(Bind(
207 [](AdvertisingInstance* p_inst, MultiAdvCb configuredCb,
208 const RawAddress& bda) {
209 /* Connectable advertising set must be disabled when updating RPA */
210 bool restart = p_inst->IsEnabled() && p_inst->IsConnectable();
211
212 if (!instance_weakptr.get()) return;
213 auto hci_interface = instance_weakptr.get()->GetHciInterface();
214
215 if (restart) {
216 p_inst->enable_status = false;
217 hci_interface->Enable(false, p_inst->inst_id, 0x00, 0x00,
218 base::DoNothing());
219 }
220
221 /* set it to controller */
222 hci_interface->SetRandomAddress(
223 p_inst->inst_id, bda,
224 Bind(
225 [](AdvertisingInstance* p_inst, RawAddress bda,
226 MultiAdvCb configuredCb, uint8_t status) {
227 p_inst->own_address = bda;
228 configuredCb.Run(0x00);
229 },
230 p_inst, bda, configuredCb));
231
232 if (restart) {
233 p_inst->enable_status = true;
234 hci_interface->Enable(true, p_inst->inst_id, 0x00, 0x00,
235 base::DoNothing());
236 }
237 },
238 p_inst, std::move(configuredCb)));
239 }
240
RegisterAdvertiser(base::Callback<void (uint8_t,uint8_t)> cb)241 void RegisterAdvertiser(
242 base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)> cb)
243 override {
244 AdvertisingInstance* p_inst = &adv_inst[0];
245 for (uint8_t i = 0; i < inst_count; i++, p_inst++) {
246 if (p_inst->in_use) continue;
247
248 p_inst->in_use = true;
249
250 // set up periodic timer to update address.
251 if (BTM_BleLocalPrivacyEnabled()) {
252 p_inst->own_address_type = BLE_ADDR_RANDOM;
253 GenerateRpa(Bind(
254 [](AdvertisingInstance* p_inst,
255 base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)>
256 cb,
257 const RawAddress& bda) {
258 p_inst->own_address = bda;
259
260 alarm_set_on_mloop(p_inst->adv_raddr_timer,
261 btm_get_next_private_addrress_interval_ms(),
262 btm_ble_adv_raddr_timer_timeout, p_inst);
263 cb.Run(p_inst->inst_id, BTM_BLE_MULTI_ADV_SUCCESS);
264 },
265 p_inst, cb));
266 } else {
267 p_inst->own_address_type = BLE_ADDR_PUBLIC;
268 p_inst->own_address = *controller_get_interface()->get_address();
269
270 cb.Run(p_inst->inst_id, BTM_BLE_MULTI_ADV_SUCCESS);
271 }
272 return;
273 }
274
275 LOG(INFO) << "no free advertiser instance";
276 cb.Run(0xFF, ADVERTISE_FAILED_TOO_MANY_ADVERTISERS);
277 }
278
StartAdvertising(uint8_t advertiser_id,MultiAdvCb cb,tBTM_BLE_ADV_PARAMS * params,std::vector<uint8_t> advertise_data,std::vector<uint8_t> scan_response_data,int duration,MultiAdvCb timeout_cb)279 void StartAdvertising(uint8_t advertiser_id, MultiAdvCb cb,
280 tBTM_BLE_ADV_PARAMS* params,
281 std::vector<uint8_t> advertise_data,
282 std::vector<uint8_t> scan_response_data, int duration,
283 MultiAdvCb timeout_cb) override {
284 /* a temporary type for holding all the data needed in callbacks below*/
285 struct CreatorParams {
286 uint8_t inst_id;
287 base::WeakPtr<BleAdvertisingManagerImpl> self;
288 MultiAdvCb cb;
289 tBTM_BLE_ADV_PARAMS params;
290 std::vector<uint8_t> advertise_data;
291 std::vector<uint8_t> scan_response_data;
292 int duration;
293 MultiAdvCb timeout_cb;
294 };
295
296 std::unique_ptr<CreatorParams> c;
297 c.reset(new CreatorParams());
298
299 c->self = weak_factory_.GetWeakPtr();
300 c->cb = std::move(cb);
301 c->params = *params;
302 c->advertise_data = std::move(advertise_data);
303 c->scan_response_data = std::move(scan_response_data);
304 c->duration = duration;
305 c->timeout_cb = std::move(timeout_cb);
306 c->inst_id = advertiser_id;
307
308 using c_type = std::unique_ptr<CreatorParams>;
309
310 // this code is intentionally left formatted this way to highlight the
311 // asynchronous flow
312 // clang-format off
313 c->self->SetParameters(c->inst_id, &c->params, Bind(
314 [](c_type c, uint8_t status, int8_t tx_power) {
315 if (!c->self) {
316 LOG(INFO) << "Stack was shut down";
317 return;
318 }
319
320 if (status) {
321 LOG(ERROR) << "setting parameters failed, status: " << +status;
322 c->cb.Run(status);
323 return;
324 }
325
326 c->self->adv_inst[c->inst_id].tx_power = tx_power;
327
328 const RawAddress& rpa = c->self->adv_inst[c->inst_id].own_address;
329 c->self->GetHciInterface()->SetRandomAddress(c->inst_id, rpa, Bind(
330 [](c_type c, uint8_t status) {
331 if (!c->self) {
332 LOG(INFO) << "Stack was shut down";
333 return;
334 }
335
336 if (status != 0) {
337 LOG(ERROR) << "setting random address failed, status: " << +status;
338 c->cb.Run(status);
339 return;
340 }
341
342 c->self->SetData(c->inst_id, false, std::move(c->advertise_data), Bind(
343 [](c_type c, uint8_t status) {
344 if (!c->self) {
345 LOG(INFO) << "Stack was shut down";
346 return;
347 }
348
349 if (status != 0) {
350 LOG(ERROR) << "setting advertise data failed, status: " << +status;
351 c->cb.Run(status);
352 return;
353 }
354
355 c->self->SetData(c->inst_id, true, std::move(c->scan_response_data), Bind(
356 [](c_type c, uint8_t status) {
357 if (!c->self) {
358 LOG(INFO) << "Stack was shut down";
359 return;
360 }
361
362 if (status != 0) {
363 LOG(ERROR) << "setting scan response data failed, status: " << +status;
364 c->cb.Run(status);
365 return;
366 }
367
368 c->self->Enable(c->inst_id, true, c->cb, c->duration, 0, std::move(c->timeout_cb));
369
370 }, base::Passed(&c)));
371 }, base::Passed(&c)));
372 }, base::Passed(&c)));
373 }, base::Passed(&c)));
374 // clang-format on
375 }
376
StartAdvertisingSet(IdTxPowerStatusCb cb,tBTM_BLE_ADV_PARAMS * params,std::vector<uint8_t> advertise_data,std::vector<uint8_t> scan_response_data,tBLE_PERIODIC_ADV_PARAMS * periodic_params,std::vector<uint8_t> periodic_data,uint16_t duration,uint8_t maxExtAdvEvents,RegisterCb timeout_cb)377 void StartAdvertisingSet(IdTxPowerStatusCb cb, tBTM_BLE_ADV_PARAMS* params,
378 std::vector<uint8_t> advertise_data,
379 std::vector<uint8_t> scan_response_data,
380 tBLE_PERIODIC_ADV_PARAMS* periodic_params,
381 std::vector<uint8_t> periodic_data,
382 uint16_t duration, uint8_t maxExtAdvEvents,
383 RegisterCb timeout_cb) override {
384 std::unique_ptr<CreatorParams> c;
385 c.reset(new CreatorParams());
386
387 c->self = weak_factory_.GetWeakPtr();
388 c->cb = std::move(cb);
389 c->params = *params;
390 c->advertise_data = std::move(advertise_data);
391 c->scan_response_data = std::move(scan_response_data);
392 c->periodic_params = *periodic_params;
393 c->periodic_data = std::move(periodic_data);
394 c->duration = duration;
395 c->maxExtAdvEvents = maxExtAdvEvents;
396 c->timeout_cb = std::move(timeout_cb);
397
398 // this code is intentionally left formatted this way to highlight the
399 // asynchronous flow
400 // clang-format off
401 c->self->RegisterAdvertiser(Bind(
402 [](c_type c, uint8_t advertiser_id, uint8_t status) {
403 if (!c->self) {
404 LOG(INFO) << "Stack was shut down";
405 return;
406 }
407
408 if (status != 0) {
409 LOG(ERROR) << " failed, status: " << +status;
410 c->cb.Run(0, 0, status);
411 return;
412 }
413
414 c->inst_id = advertiser_id;
415
416 c->self->SetParameters(c->inst_id, &c->params, Bind(
417 [](c_type c, uint8_t status, int8_t tx_power) {
418 if (!c->self) {
419 LOG(INFO) << "Stack was shut down";
420 return;
421 }
422
423 if (status != 0) {
424 c->self->Unregister(c->inst_id);
425 LOG(ERROR) << "setting parameters failed, status: " << +status;
426 c->cb.Run(0, 0, status);
427 return;
428 }
429
430 c->self->adv_inst[c->inst_id].tx_power = tx_power;
431
432 if (c->self->adv_inst[c->inst_id].own_address_type == BLE_ADDR_PUBLIC) {
433 auto self = c->self;
434 self->StartAdvertisingSetAfterAddressPart(std::move(c));
435 return;
436 }
437
438 //own_address_type == BLE_ADDR_RANDOM
439 const RawAddress& rpa = c->self->adv_inst[c->inst_id].own_address;
440 c->self->GetHciInterface()->SetRandomAddress(c->inst_id, rpa, Bind(
441 [](c_type c, uint8_t status) {
442 if (!c->self) {
443 LOG(INFO) << "Stack was shut down";
444 return;
445 }
446
447 if (status != 0) {
448 c->self->Unregister(c->inst_id);
449 LOG(ERROR) << "setting random address failed, status: " << +status;
450 c->cb.Run(0, 0, status);
451 return;
452 }
453
454 auto self = c->self;
455 self->StartAdvertisingSetAfterAddressPart(std::move(c));
456 }, base::Passed(&c)));
457 }, base::Passed(&c)));
458 }, base::Passed(&c)));
459 // clang-format on
460 }
461
StartAdvertisingSetAfterAddressPart(c_type c)462 void StartAdvertisingSetAfterAddressPart(c_type c) {
463 c->self->SetData(
464 c->inst_id, false, std::move(c->advertise_data),
465 Bind(
466 [](c_type c, uint8_t status) {
467 if (!c->self) {
468 LOG(INFO) << "Stack was shut down";
469 return;
470 }
471
472 if (status != 0) {
473 c->self->Unregister(c->inst_id);
474 LOG(ERROR) << "setting advertise data failed, status: "
475 << +status;
476 c->cb.Run(0, 0, status);
477 return;
478 }
479
480 c->self->SetData(
481 c->inst_id, true, std::move(c->scan_response_data),
482 Bind(
483 [](c_type c, uint8_t status) {
484 if (!c->self) {
485 LOG(INFO) << "Stack was shut down";
486 return;
487 }
488
489 if (status != 0) {
490 c->self->Unregister(c->inst_id);
491 LOG(ERROR)
492 << "setting scan response data failed, status: "
493 << +status;
494 c->cb.Run(0, 0, status);
495 return;
496 }
497
498 auto self = c->self;
499 if (c->periodic_params.enable) {
500 self->StartAdvertisingSetPeriodicPart(std::move(c));
501 } else {
502 self->StartAdvertisingSetFinish(std::move(c));
503 }
504 },
505 base::Passed(&c)));
506 },
507 base::Passed(&c)));
508 }
509
StartAdvertisingSetPeriodicPart(c_type c)510 void StartAdvertisingSetPeriodicPart(c_type c) {
511 // this code is intentionally left formatted this way to highlight the
512 // asynchronous flow
513 // clang-format off
514 c->self->SetPeriodicAdvertisingParameters(c->inst_id, &c->periodic_params, Bind(
515 [](c_type c, uint8_t status) {
516 if (!c->self) {
517 LOG(INFO) << "Stack was shut down";
518 return;
519 }
520
521 if (status != 0) {
522 c->self->Unregister(c->inst_id);
523 LOG(ERROR) << "setting periodic parameters failed, status: " << +status;
524 c->cb.Run(0, 0, status);
525 return;
526 }
527
528 c->self->SetPeriodicAdvertisingData(c->inst_id, std::move(c->periodic_data), Bind(
529 [](c_type c, uint8_t status) {
530 if (!c->self) {
531 LOG(INFO) << "Stack was shut down";
532 return;
533 }
534
535 if (status != 0) {
536 c->self->Unregister(c->inst_id);
537 LOG(ERROR) << "setting periodic parameters failed, status: " << +status;
538 c->cb.Run(0, 0, status);
539 return;
540 }
541
542 c->self->SetPeriodicAdvertisingEnable(c->inst_id, true, Bind(
543 [](c_type c, uint8_t status) {
544 if (!c->self) {
545 LOG(INFO) << "Stack was shut down";
546 return;
547 }
548
549 if (status != 0) {
550 c->self->Unregister(c->inst_id);
551 LOG(ERROR) << "enabling periodic advertising failed, status: " << +status;
552 c->cb.Run(0, 0, status);
553 return;
554 }
555
556 auto self = c->self;
557 self->StartAdvertisingSetFinish(std::move(c));
558
559 }, base::Passed(&c)));
560 }, base::Passed(&c)));
561 }, base::Passed(&c)));
562 // clang-format on
563 }
564
StartAdvertisingSetFinish(c_type c)565 void StartAdvertisingSetFinish(c_type c) {
566 uint8_t inst_id = c->inst_id;
567 uint16_t duration = c->duration;
568 uint8_t maxExtAdvEvents = c->maxExtAdvEvents;
569 RegisterCb timeout_cb = std::move(c->timeout_cb);
570 base::WeakPtr<BleAdvertisingManagerImpl> self = c->self;
571 MultiAdvCb enable_cb = Bind(
572 [](c_type c, uint8_t status) {
573 if (!c->self) {
574 LOG(INFO) << "Stack was shut down";
575 return;
576 }
577
578 if (status != 0) {
579 c->self->Unregister(c->inst_id);
580 LOG(ERROR) << "enabling advertiser failed, status: " << +status;
581 c->cb.Run(0, 0, status);
582 return;
583 }
584 int8_t tx_power = c->self->adv_inst[c->inst_id].tx_power;
585 c->cb.Run(c->inst_id, tx_power, status);
586 },
587 base::Passed(&c));
588
589 self->Enable(inst_id, true, std::move(enable_cb), duration, maxExtAdvEvents,
590 Bind(std::move(timeout_cb), inst_id));
591 }
592
EnableWithTimerCb(uint8_t inst_id,MultiAdvCb enable_cb,int duration,MultiAdvCb timeout_cb,uint8_t status)593 void EnableWithTimerCb(uint8_t inst_id, MultiAdvCb enable_cb, int duration,
594 MultiAdvCb timeout_cb, uint8_t status) {
595 VLOG(1) << __func__ << " inst_id: " << +inst_id;
596 AdvertisingInstance* p_inst = &adv_inst[inst_id];
597
598 // Run the regular enable callback
599 enable_cb.Run(status);
600
601 p_inst->timeout_timer = alarm_new("btm_ble.adv_timeout");
602
603 base::Closure cb = Bind(
604 &BleAdvertisingManagerImpl::Enable, weak_factory_.GetWeakPtr(), inst_id,
605 0 /* disable */, std::move(timeout_cb), 0, 0, base::DoNothing());
606
607 // schedule disable when the timeout passes
608 alarm_set_closure(FROM_HERE, p_inst->timeout_timer, duration * 10,
609 std::move(cb));
610 }
611
Enable(uint8_t inst_id,bool enable,MultiAdvCb cb,uint16_t duration,uint8_t maxExtAdvEvents,MultiAdvCb timeout_cb)612 void Enable(uint8_t inst_id, bool enable, MultiAdvCb cb, uint16_t duration,
613 uint8_t maxExtAdvEvents, MultiAdvCb timeout_cb) override {
614 VLOG(1) << __func__ << " inst_id: " << +inst_id;
615 if (inst_id >= inst_count) {
616 LOG(ERROR) << "bad instance id " << +inst_id;
617 return;
618 }
619
620 AdvertisingInstance* p_inst = &adv_inst[inst_id];
621 VLOG(1) << __func__ << " enable: " << enable << ", duration: " << +duration;
622 if (!p_inst->in_use) {
623 LOG(ERROR) << "Invalid or no active instance";
624 cb.Run(BTM_BLE_MULTI_ADV_FAILURE);
625 return;
626 }
627
628 if (enable && (duration || maxExtAdvEvents)) {
629 p_inst->timeout_cb = std::move(timeout_cb);
630 }
631
632 p_inst->duration = duration;
633 p_inst->maxExtAdvEvents = maxExtAdvEvents;
634
635 if (enable && p_inst->address_update_required) {
636 p_inst->address_update_required = false;
637 ConfigureRpa(p_inst, base::Bind(&BleAdvertisingManagerImpl::EnableFinish,
638 weak_factory_.GetWeakPtr(), p_inst,
639 enable, std::move(cb)));
640 return;
641 }
642
643 EnableFinish(p_inst, enable, std::move(cb), 0);
644 }
645
EnableFinish(AdvertisingInstance * p_inst,bool enable,MultiAdvCb cb,uint8_t status)646 void EnableFinish(AdvertisingInstance* p_inst, bool enable, MultiAdvCb cb,
647 uint8_t status) {
648 MultiAdvCb myCb;
649 if (enable && p_inst->duration) {
650 // TODO(jpawlowski): HCI implementation that can't do duration should
651 // emulate it, not EnableWithTimerCb.
652 myCb = Bind(&BleAdvertisingManagerImpl::EnableWithTimerCb,
653 weak_factory_.GetWeakPtr(), p_inst->inst_id, std::move(cb),
654 p_inst->duration, p_inst->timeout_cb);
655 } else {
656 myCb = std::move(cb);
657
658 if (p_inst->timeout_timer) {
659 alarm_cancel(p_inst->timeout_timer);
660 alarm_free(p_inst->timeout_timer);
661 p_inst->timeout_timer = nullptr;
662 }
663 }
664
665 if (enable) p_inst->enable_time = TimeTicks::Now();
666 p_inst->enable_status = enable;
667 GetHciInterface()->Enable(enable, p_inst->inst_id, p_inst->duration,
668 p_inst->maxExtAdvEvents, std::move(myCb));
669 }
670
SetParameters(uint8_t inst_id,tBTM_BLE_ADV_PARAMS * p_params,ParametersCb cb)671 void SetParameters(uint8_t inst_id, tBTM_BLE_ADV_PARAMS* p_params,
672 ParametersCb cb) override {
673 VLOG(1) << __func__ << " inst_id: " << +inst_id;
674 if (inst_id >= inst_count) {
675 LOG(ERROR) << "bad instance id " << +inst_id;
676 return;
677 }
678
679 AdvertisingInstance* p_inst = &adv_inst[inst_id];
680 if (!p_inst->in_use) {
681 LOG(ERROR) << "adv instance not in use" << +inst_id;
682 cb.Run(BTM_BLE_MULTI_ADV_FAILURE, 0);
683 return;
684 }
685
686 // TODO: disable only if was enabled, currently no use scenario needs
687 // that,
688 // we always set parameters before enabling
689 // GetHciInterface()->Enable(false, inst_id, base::DoNothing());
690 p_inst->advertising_event_properties =
691 p_params->advertising_event_properties;
692 p_inst->tx_power = p_params->tx_power;
693 p_inst->advertising_interval = p_params->adv_int_min;
694 const RawAddress& peer_address = RawAddress::kEmpty;
695
696 // sid must be in range 0x00 to 0x0F. Since no controller supports more than
697 // 16 advertisers, it's safe to make sid equal to inst_id.
698 uint8_t sid = p_inst->inst_id % 0x0F;
699
700 GetHciInterface()->SetParameters(
701 p_inst->inst_id, p_params->advertising_event_properties,
702 p_params->adv_int_min, p_params->adv_int_max, p_params->channel_map,
703 p_inst->own_address_type, p_inst->own_address, 0x00, peer_address,
704 p_params->adv_filter_policy, p_inst->tx_power,
705 p_params->primary_advertising_phy, 0x00,
706 p_params->secondary_advertising_phy, sid,
707 p_params->scan_request_notification_enable, cb);
708
709 // TODO: re-enable only if it was enabled, properly call
710 // SetParamsCallback
711 // currently no use scenario needs that
712 // GetHciInterface()->Enable(true, inst_id, BTM_BleUpdateAdvInstParamCb);
713 }
714
SetData(uint8_t inst_id,bool is_scan_rsp,std::vector<uint8_t> data,MultiAdvCb cb)715 void SetData(uint8_t inst_id, bool is_scan_rsp, std::vector<uint8_t> data,
716 MultiAdvCb cb) override {
717 VLOG(1) << __func__ << " inst_id: " << +inst_id;
718 if (inst_id >= inst_count) {
719 LOG(ERROR) << "bad instance id " << +inst_id;
720 return;
721 }
722
723 AdvertisingInstance* p_inst = &adv_inst[inst_id];
724 VLOG(1) << "is_scan_rsp = " << is_scan_rsp;
725
726 if (!is_scan_rsp && is_connectable(p_inst->advertising_event_properties)) {
727 uint8_t flags_val = BTM_GENERAL_DISCOVERABLE;
728
729 if (p_inst->duration) flags_val = BTM_LIMITED_DISCOVERABLE;
730
731 std::vector<uint8_t> flags;
732 flags.push_back(2); // length
733 flags.push_back(HCI_EIR_FLAGS_TYPE);
734 flags.push_back(flags_val);
735
736 data.insert(data.begin(), flags.begin(), flags.end());
737 }
738
739 // Find and fill TX Power with the correct value.
740 // The TX Power section is a 3 byte section.
741 for (size_t i = 0; (i + 2) < data.size();) {
742 if (data[i + 1] == HCI_EIR_TX_POWER_LEVEL_TYPE) {
743 data[i + 2] = adv_inst[inst_id].tx_power;
744 }
745 i += data[i] + 1;
746 }
747
748 VLOG(1) << "data is: " << base::HexEncode(data.data(), data.size());
749 DivideAndSendData(
750 inst_id, data, cb,
751 base::Bind(&BleAdvertisingManagerImpl::SetDataAdvDataSender,
752 weak_factory_.GetWeakPtr(), is_scan_rsp));
753 }
754
SetDataAdvDataSender(uint8_t is_scan_rsp,uint8_t inst_id,uint8_t operation,uint8_t length,uint8_t * data,MultiAdvCb cb)755 void SetDataAdvDataSender(uint8_t is_scan_rsp, uint8_t inst_id,
756 uint8_t operation, uint8_t length, uint8_t* data,
757 MultiAdvCb cb) {
758 if (is_scan_rsp)
759 GetHciInterface()->SetScanResponseData(inst_id, operation, 0x01, length,
760 data, cb);
761 else
762 GetHciInterface()->SetAdvertisingData(inst_id, operation, 0x01, length,
763 data, cb);
764 }
765
766 using DataSender = base::Callback<void(
767 uint8_t /*inst_id*/, uint8_t /* operation */, uint8_t /* length */,
768 uint8_t* /* data */, MultiAdvCb /* done */)>;
769
DivideAndSendData(int inst_id,std::vector<uint8_t> data,MultiAdvCb done_cb,DataSender sender)770 void DivideAndSendData(int inst_id, std::vector<uint8_t> data,
771 MultiAdvCb done_cb, DataSender sender) {
772 DivideAndSendDataRecursively(true, inst_id, std::move(data), 0,
773 std::move(done_cb), std::move(sender), 0);
774 }
775
DivideAndSendDataRecursively(bool isFirst,int inst_id,std::vector<uint8_t> data,int offset,MultiAdvCb done_cb,DataSender sender,uint8_t status)776 static void DivideAndSendDataRecursively(bool isFirst, int inst_id,
777 std::vector<uint8_t> data,
778 int offset, MultiAdvCb done_cb,
779 DataSender sender, uint8_t status) {
780 constexpr uint8_t INTERMEDIATE =
781 0x00; // Intermediate fragment of fragmented data
782 constexpr uint8_t FIRST = 0x01; // First fragment of fragmented data
783 constexpr uint8_t LAST = 0x02; // Last fragment of fragmented data
784 constexpr uint8_t COMPLETE = 0x03; // Complete extended advertising data
785
786 int dataSize = (int)data.size();
787 if (status != 0 || (!isFirst && offset == dataSize)) {
788 /* if we got error writing data, or reached the end of data */
789 done_cb.Run(status);
790 return;
791 }
792
793 bool moreThanOnePacket = dataSize - offset > ADV_DATA_LEN_MAX;
794 uint8_t operation = isFirst ? moreThanOnePacket ? FIRST : COMPLETE
795 : moreThanOnePacket ? INTERMEDIATE : LAST;
796 int length = moreThanOnePacket ? ADV_DATA_LEN_MAX : dataSize - offset;
797 int newOffset = offset + length;
798
799 auto dataData = data.data();
800 sender.Run(
801 inst_id, operation, length, dataData + offset,
802 Bind(&BleAdvertisingManagerImpl::DivideAndSendDataRecursively, false,
803 inst_id, std::move(data), newOffset, std::move(done_cb), sender));
804 }
805
SetPeriodicAdvertisingParameters(uint8_t inst_id,tBLE_PERIODIC_ADV_PARAMS * params,MultiAdvCb cb)806 void SetPeriodicAdvertisingParameters(uint8_t inst_id,
807 tBLE_PERIODIC_ADV_PARAMS* params,
808 MultiAdvCb cb) override {
809 VLOG(1) << __func__ << " inst_id: " << +inst_id;
810
811 GetHciInterface()->SetPeriodicAdvertisingParameters(
812 inst_id, params->min_interval, params->max_interval,
813 params->periodic_advertising_properties, cb);
814 }
815
SetPeriodicAdvertisingData(uint8_t inst_id,std::vector<uint8_t> data,MultiAdvCb cb)816 void SetPeriodicAdvertisingData(uint8_t inst_id, std::vector<uint8_t> data,
817 MultiAdvCb cb) override {
818 VLOG(1) << __func__ << " inst_id: " << +inst_id;
819
820 VLOG(1) << "data is: " << base::HexEncode(data.data(), data.size());
821
822 DivideAndSendData(
823 inst_id, data, cb,
824 base::Bind(&BleAdvertiserHciInterface::SetPeriodicAdvertisingData,
825 base::Unretained(GetHciInterface())));
826 }
827
SetPeriodicAdvertisingEnable(uint8_t inst_id,uint8_t enable,MultiAdvCb cb)828 void SetPeriodicAdvertisingEnable(uint8_t inst_id, uint8_t enable,
829 MultiAdvCb cb) override {
830 VLOG(1) << __func__ << " inst_id: " << +inst_id << ", enable: " << +enable;
831
832 AdvertisingInstance* p_inst = &adv_inst[inst_id];
833 if (!p_inst->in_use) {
834 LOG(ERROR) << "Invalid or not active instance";
835 cb.Run(BTM_BLE_MULTI_ADV_FAILURE);
836 return;
837 }
838
839 MultiAdvCb enable_cb = Bind(
840 [](AdvertisingInstance* p_inst, uint8_t enable, MultiAdvCb cb,
841 uint8_t status) {
842 VLOG(1) << "periodc adv enable cb: inst_id: " << +p_inst->inst_id
843 << ", enable: " << +enable << ", status: " << std::hex
844 << +status;
845 if (!status) p_inst->periodic_enabled = enable;
846
847 cb.Run(status);
848 },
849 p_inst, enable, std::move(cb));
850
851 GetHciInterface()->SetPeriodicAdvertisingEnable(enable, inst_id,
852 std::move(enable_cb));
853 }
854
Unregister(uint8_t inst_id)855 void Unregister(uint8_t inst_id) override {
856 AdvertisingInstance* p_inst = &adv_inst[inst_id];
857
858 VLOG(1) << __func__ << " inst_id: " << +inst_id;
859 if (inst_id >= inst_count) {
860 LOG(ERROR) << "bad instance id " << +inst_id;
861 return;
862 }
863
864 if (adv_inst[inst_id].IsEnabled()) {
865 p_inst->enable_status = false;
866 GetHciInterface()->Enable(false, inst_id, 0x00, 0x00, base::DoNothing());
867 }
868
869 if (p_inst->periodic_enabled) {
870 p_inst->periodic_enabled = false;
871 GetHciInterface()->SetPeriodicAdvertisingEnable(false, inst_id,
872 base::DoNothing());
873 }
874
875 alarm_cancel(p_inst->adv_raddr_timer);
876 p_inst->in_use = false;
877 GetHciInterface()->RemoveAdvertisingSet(inst_id, base::DoNothing());
878 p_inst->address_update_required = false;
879 }
880
RecomputeTimeout(AdvertisingInstance * inst,TimeTicks now)881 void RecomputeTimeout(AdvertisingInstance* inst, TimeTicks now) {
882 TimeDelta duration = now - inst->enable_time;
883 bool cb_fired = false;
884 if (inst->duration) {
885 int durationDone = (duration.InMilliseconds() / 10);
886 if (durationDone + 1 >= inst->duration) {
887 inst->enable_status = false;
888 inst->timeout_cb.Run(0 /* TODO: STATUS HERE?*/);
889 cb_fired = true;
890 } else {
891 inst->duration = inst->duration - durationDone;
892 }
893 }
894
895 if (inst->maxExtAdvEvents && !cb_fired) {
896 int eventsDone =
897 (duration.InMilliseconds() / (inst->advertising_interval * 5 / 8));
898
899 if (eventsDone + 1 >= inst->maxExtAdvEvents) {
900 inst->enable_status = false;
901 inst->timeout_cb.Run(0 /* TODO: STATUS HERE?*/);
902 } else {
903 inst->maxExtAdvEvents = inst->maxExtAdvEvents - eventsDone;
904 }
905 }
906 }
907
Suspend()908 void Suspend() override {
909 std::vector<SetEnableData> sets;
910
911 for (AdvertisingInstance& inst : adv_inst) {
912 if (!inst.in_use || !inst.enable_status) continue;
913
914 if (inst.duration || inst.maxExtAdvEvents)
915 RecomputeTimeout(&inst, TimeTicks::Now());
916
917 sets.emplace_back(SetEnableData{.handle = inst.inst_id});
918 }
919
920 if (!sets.empty())
921 GetHciInterface()->Enable(false, sets, base::DoNothing());
922 }
923
Resume()924 void Resume() override {
925 std::vector<SetEnableData> sets;
926
927 for (const AdvertisingInstance& inst : adv_inst) {
928 if (inst.in_use && inst.enable_status) {
929 sets.emplace_back(SetEnableData{
930 .handle = inst.inst_id,
931 .duration = inst.duration,
932 .max_extended_advertising_events = inst.maxExtAdvEvents});
933 }
934 }
935
936 if (!sets.empty()) GetHciInterface()->Enable(true, sets, base::DoNothing());
937 }
938
OnAdvertisingSetTerminated(uint8_t status,uint8_t advertising_handle,uint16_t connection_handle,uint8_t num_completed_extended_adv_events)939 void OnAdvertisingSetTerminated(
940 uint8_t status, uint8_t advertising_handle, uint16_t connection_handle,
941 uint8_t num_completed_extended_adv_events) override {
942 AdvertisingInstance* p_inst = &adv_inst[advertising_handle];
943 VLOG(1) << __func__ << "status: " << loghex(status)
944 << ", advertising_handle: " << loghex(advertising_handle)
945 << ", connection_handle: " << loghex(connection_handle);
946
947 if (status == HCI_ERR_LIMIT_REACHED ||
948 status == HCI_ERR_ADVERTISING_TIMEOUT) {
949 // either duration elapsed, or maxExtAdvEvents reached
950 p_inst->enable_status = false;
951
952 if (p_inst->timeout_cb.is_null()) {
953 LOG(INFO) << __func__ << "No timeout callback";
954 return;
955 }
956
957 p_inst->timeout_cb.Run(status);
958 return;
959 }
960
961 if (BTM_BleLocalPrivacyEnabled() &&
962 advertising_handle <= BTM_BLE_MULTI_ADV_MAX) {
963 btm_acl_update_conn_addr(connection_handle, p_inst->own_address);
964 }
965
966 VLOG(1) << "reneabling advertising";
967
968 if (p_inst->in_use) {
969 // TODO(jpawlowski): we don't really allow to do directed advertising
970 // right now. This should probably be removed, check with Andre.
971 if ((p_inst->advertising_event_properties & 0x0C) == 0) {
972 /* directed advertising bits not set */
973
974 RecomputeTimeout(p_inst, TimeTicks::Now());
975 if (p_inst->enable_status) {
976 GetHciInterface()->Enable(true, advertising_handle, p_inst->duration,
977 p_inst->maxExtAdvEvents, base::DoNothing());
978 }
979
980 } else {
981 /* mark directed adv as disabled if adv has been stopped */
982 p_inst->in_use = false;
983 }
984 }
985 }
986
GetWeakPtr()987 base::WeakPtr<BleAdvertisingManagerImpl> GetWeakPtr() {
988 return weak_factory_.GetWeakPtr();
989 }
990
CancelAdvAlarms()991 void CancelAdvAlarms() {
992 AdvertisingInstance* p_inst = &adv_inst[0];
993 for (uint8_t i = 0; i < inst_count; i++, p_inst++) {
994 if (p_inst->timeout_timer) {
995 alarm_cancel(p_inst->timeout_timer);
996 }
997 if (p_inst->adv_raddr_timer) {
998 alarm_cancel(p_inst->adv_raddr_timer);
999 }
1000 }
1001 }
1002
1003 private:
GetHciInterface()1004 BleAdvertiserHciInterface* GetHciInterface() { return hci_interface; }
1005
1006 BleAdvertiserHciInterface* hci_interface = nullptr;
1007 std::vector<AdvertisingInstance> adv_inst;
1008 uint8_t inst_count;
1009
1010 // Member variables should appear before the WeakPtrFactory, to ensure
1011 // that any WeakPtrs are invalidated before its members
1012 // variable's destructors are executed, rendering them invalid.
1013 base::WeakPtrFactory<BleAdvertisingManagerImpl> weak_factory_;
1014 };
1015
btm_ble_adv_raddr_timer_timeout(void * data)1016 void btm_ble_adv_raddr_timer_timeout(void* data) {
1017 BleAdvertisingManagerImpl* ptr = instance_weakptr.get();
1018 if (ptr) ptr->ConfigureRpa((AdvertisingInstance*)data, base::DoNothing());
1019 }
1020 } // namespace
1021
Initialize(BleAdvertiserHciInterface * interface)1022 void BleAdvertisingManager::Initialize(BleAdvertiserHciInterface* interface) {
1023 instance = new BleAdvertisingManagerImpl(interface);
1024 instance_weakptr = ((BleAdvertisingManagerImpl*)instance)->GetWeakPtr();
1025 }
1026
IsInitialized()1027 bool BleAdvertisingManager::IsInitialized() { return instance; }
1028
Get()1029 base::WeakPtr<BleAdvertisingManager> BleAdvertisingManager::Get() {
1030 return instance_weakptr;
1031 };
1032
CleanUp()1033 void BleAdvertisingManager::CleanUp() {
1034 if (instance_weakptr.get()) instance_weakptr.get()->CancelAdvAlarms();
1035
1036 delete instance;
1037 instance = nullptr;
1038 };
1039
1040 /**
1041 * This function initialize the advertising manager.
1042 **/
btm_ble_adv_init()1043 void btm_ble_adv_init() {
1044 BleAdvertiserHciInterface::Initialize();
1045 BleAdvertisingManager::Initialize(BleAdvertiserHciInterface::Get());
1046 BleAdvertiserHciInterface::Get()->SetAdvertisingEventObserver(
1047 (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get().get());
1048
1049 if (BleAdvertiserHciInterface::Get()->QuirkAdvertiserZeroHandle()) {
1050 // If handle 0 can't be used, register advertiser for it, but never use it.
1051 BleAdvertisingManager::Get().get()->RegisterAdvertiser(base::DoNothing());
1052 }
1053 }
1054
1055 /*******************************************************************************
1056 *
1057 * Function btm_ble_multi_adv_cleanup
1058 *
1059 * Description This function cleans up multi adv control block.
1060 *
1061 * Parameters
1062 * Returns void
1063 *
1064 ******************************************************************************/
btm_ble_multi_adv_cleanup(void)1065 void btm_ble_multi_adv_cleanup(void) {
1066 BleAdvertisingManager::CleanUp();
1067 BleAdvertiserHciInterface::CleanUp();
1068 }
1069
1070 // TODO(jpawlowski): Find a nicer way to test RecomputeTimeout without exposing
1071 // AdvertisingInstance
1072 bool timeout_triggered = false;
test_timeout_cb(uint8_t status)1073 void test_timeout_cb(uint8_t status) { timeout_triggered = true; }
1074
1075 // verify that if duration passed, or is about to pass, recomputation will shut
1076 // down the advertiser completly
testRecomputeTimeout1()1077 void testRecomputeTimeout1() {
1078 auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get().get();
1079
1080 TimeTicks start = TimeTicks::Now();
1081 TimeTicks end = start + TimeDelta::FromMilliseconds(111);
1082 AdvertisingInstance test1(0);
1083 test1.enable_status = true;
1084 test1.enable_time = start;
1085 test1.duration = 12 /*120ms*/;
1086 test1.timeout_cb = Bind(&test_timeout_cb);
1087
1088 manager->RecomputeTimeout(&test1, end);
1089
1090 CHECK(timeout_triggered);
1091 timeout_triggered = false;
1092 CHECK(!test1.enable_status);
1093 }
1094
1095 // verify that duration and maxExtAdvEvents are properly adjusted when
1096 // recomputing.
testRecomputeTimeout2()1097 void testRecomputeTimeout2() {
1098 auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get().get();
1099
1100 TimeTicks start = TimeTicks::Now();
1101 TimeTicks end = start + TimeDelta::FromMilliseconds(250);
1102 AdvertisingInstance test1(0);
1103 test1.enable_status = true;
1104 test1.enable_time = start;
1105 test1.duration = 50 /*500ms*/;
1106 test1.maxExtAdvEvents = 50;
1107 test1.advertising_interval = 16 /* 10 ms */;
1108 test1.timeout_cb = Bind(&test_timeout_cb);
1109
1110 manager->RecomputeTimeout(&test1, end);
1111
1112 CHECK(!timeout_triggered);
1113 CHECK(test1.enable_status);
1114 CHECK(test1.duration == 25);
1115 CHECK(test1.maxExtAdvEvents == 25);
1116 }
1117
1118 // verify that if maxExtAdvEvents were sent, or are close to end, recomputation
1119 // wil shut down the advertiser completly
testRecomputeTimeout3()1120 void testRecomputeTimeout3() {
1121 auto manager = (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get().get();
1122
1123 TimeTicks start = TimeTicks::Now();
1124 TimeTicks end = start + TimeDelta::FromMilliseconds(495);
1125 AdvertisingInstance test1(0);
1126 test1.enable_status = true;
1127 test1.enable_time = start;
1128 test1.maxExtAdvEvents = 50;
1129 test1.advertising_interval = 16 /* 10 ms */;
1130 test1.timeout_cb = Bind(&test_timeout_cb);
1131
1132 manager->RecomputeTimeout(&test1, end);
1133
1134 CHECK(timeout_triggered);
1135 timeout_triggered = false;
1136 CHECK(!test1.enable_status);
1137 }
1138