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