1 /******************************************************************************
2 *
3 * Copyright (C) 2017 The Android Open Source Project
4 * Copyright (C) 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 <base/bind.h>
21 #include <base/logging.h>
22 #include <base/strings/string_number_conversions.h>
23 #include <string.h>
24 #include <queue>
25 #include <vector>
26
27 #include "bt_target.h"
28 #include "device/include/controller.h"
29 #include "osi/include/alarm.h"
30
31 #include "ble_advertiser.h"
32 #include "ble_advertiser_hci_interface.h"
33 #include "btm_int_types.h"
34
35 using base::Bind;
36 using RegisterCb =
37 base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)>;
38 using IdTxPowerStatusCb = base::Callback<void(
39 uint8_t /* inst_id */, int8_t /* tx_power */, uint8_t /* status */)>;
40 extern void btm_gen_resolvable_private_addr(
41 base::Callback<void(uint8_t[8])> cb);
42 extern fixed_queue_t* btu_general_alarm_queue;
43
44 constexpr int ADV_DATA_LEN_MAX = 251;
45
46 namespace {
47
is_connectable(uint16_t advertising_event_properties)48 bool is_connectable(uint16_t advertising_event_properties) {
49 return advertising_event_properties & 0x01;
50 }
51
52 struct AdvertisingInstance {
53 uint8_t inst_id;
54 bool in_use;
55 uint8_t advertising_event_properties;
56 alarm_t* adv_raddr_timer;
57 int8_t tx_power;
58 uint16_t duration;
59 uint8_t maxExtAdvEvents;
60 alarm_t* timeout_timer;
61 uint8_t own_address_type;
62 BD_ADDR own_address;
63 MultiAdvCb timeout_cb;
64 bool address_update_required;
65
66 /* When true, advertising set is enabled, or last scheduled call to "LE Set
67 * Extended Advertising Set Enable" is to enable this advertising set. Any
68 * command scheduled when in this state will execute when the set is enabled,
69 * unless enabling fails.
70 *
71 * When false, advertising set is disabled, or last scheduled call to "LE Set
72 * Extended Advertising Set Enable" is to disable this advertising set. Any
73 * command scheduled when in this state will execute when the set is disabled.
74 */
75 bool enable_status;
76
IsEnabled__anon08ab64bc0111::AdvertisingInstance77 bool IsEnabled() { return enable_status; }
78
IsConnectable__anon08ab64bc0111::AdvertisingInstance79 bool IsConnectable() { return is_connectable(advertising_event_properties); }
80
AdvertisingInstance__anon08ab64bc0111::AdvertisingInstance81 AdvertisingInstance(int inst_id)
82 : inst_id(inst_id),
83 in_use(false),
84 advertising_event_properties(0),
85 tx_power(0),
86 duration(0),
87 timeout_timer(nullptr),
88 own_address_type(0),
89 own_address{0},
90 address_update_required(false),
91 enable_status(false) {
92 adv_raddr_timer = alarm_new_periodic("btm_ble.adv_raddr_timer");
93 }
94
~AdvertisingInstance__anon08ab64bc0111::AdvertisingInstance95 ~AdvertisingInstance() {
96 alarm_free(adv_raddr_timer);
97 if (timeout_timer) alarm_free(timeout_timer);
98 }
99 };
100
101 void btm_ble_adv_raddr_timer_timeout(void* data);
102
DoNothing(uint8_t)103 void DoNothing(uint8_t) {}
DoNothing2(uint8_t,uint8_t)104 void DoNothing2(uint8_t, uint8_t) {}
105
106 struct closure_data {
107 base::Closure user_task;
108 tracked_objects::Location posted_from;
109 };
110
alarm_closure_cb(void * p)111 static void alarm_closure_cb(void* p) {
112 closure_data* data = (closure_data*)p;
113 VLOG(1) << "executing timer scheduled at %s" << data->posted_from.ToString();
114 data->user_task.Run();
115 delete data;
116 }
117
118 // Periodic alarms are not supported, because we clean up data in callback
alarm_set_closure_on_queue(const tracked_objects::Location & posted_from,alarm_t * alarm,period_ms_t interval_ms,base::Closure user_task,fixed_queue_t * queue)119 void alarm_set_closure_on_queue(const tracked_objects::Location& posted_from,
120 alarm_t* alarm, period_ms_t interval_ms,
121 base::Closure user_task, fixed_queue_t* queue) {
122 closure_data* data = new closure_data;
123 data->posted_from = posted_from;
124 data->user_task = std::move(user_task);
125 VLOG(1) << "scheduling timer %s" << data->posted_from.ToString();
126 alarm_set_on_queue(alarm, interval_ms, alarm_closure_cb, data, queue);
127 }
128
129 class BleAdvertisingManagerImpl;
130
131 /* a temporary type for holding all the data needed in callbacks below*/
132 struct CreatorParams {
133 uint8_t inst_id;
134 BleAdvertisingManagerImpl* self;
135 IdTxPowerStatusCb cb;
136 tBTM_BLE_ADV_PARAMS params;
137 std::vector<uint8_t> advertise_data;
138 std::vector<uint8_t> scan_response_data;
139 tBLE_PERIODIC_ADV_PARAMS periodic_params;
140 std::vector<uint8_t> periodic_data;
141 uint16_t duration;
142 uint8_t maxExtAdvEvents;
143 RegisterCb timeout_cb;
144 };
145
146 using c_type = std::unique_ptr<CreatorParams>;
147
148 class BleAdvertisingManagerImpl
149 : public BleAdvertisingManager,
150 public BleAdvertiserHciInterface::AdvertisingEventObserver {
151 public:
BleAdvertisingManagerImpl(BleAdvertiserHciInterface * interface)152 BleAdvertisingManagerImpl(BleAdvertiserHciInterface* interface) {
153 this->hci_interface = interface;
154 hci_interface->ReadInstanceCount(
155 base::Bind(&BleAdvertisingManagerImpl::ReadInstanceCountCb,
156 base::Unretained(this)));
157 }
158
~BleAdvertisingManagerImpl()159 ~BleAdvertisingManagerImpl() { adv_inst.clear(); }
160
GetOwnAddress(uint8_t inst_id,GetAddressCallback cb)161 void GetOwnAddress(uint8_t inst_id, GetAddressCallback cb) override {
162 bt_bdaddr_t addr;
163 memcpy(addr.address, adv_inst[inst_id].own_address, BD_ADDR_LEN);
164 cb.Run(adv_inst[inst_id].own_address_type, addr);
165 }
166
ReadInstanceCountCb(uint8_t instance_count)167 void ReadInstanceCountCb(uint8_t instance_count) {
168 this->inst_count = instance_count;
169 adv_inst.reserve(inst_count);
170 /* Initialize adv instance indices and IDs. */
171 for (uint8_t i = 0; i < inst_count; i++) {
172 adv_inst.emplace_back(i);
173 }
174 }
175
OnRpaGenerationComplete(base::Callback<void (bt_bdaddr_t)> cb,uint8_t rand[8])176 void OnRpaGenerationComplete(base::Callback<void(bt_bdaddr_t)> cb,
177 uint8_t rand[8]) {
178 VLOG(1) << __func__;
179
180 bt_bdaddr_t bda;
181
182 rand[2] &= (~BLE_RESOLVE_ADDR_MASK);
183 rand[2] |= BLE_RESOLVE_ADDR_MSB;
184
185 bda.address[2] = rand[0];
186 bda.address[1] = rand[1];
187 bda.address[0] = rand[2];
188
189 BT_OCTET16 irk;
190 BTM_GetDeviceIDRoot(irk);
191 tSMP_ENC output;
192
193 if (!SMP_Encrypt(irk, BT_OCTET16_LEN, rand, 3, &output))
194 LOG_ASSERT(false) << "SMP_Encrypt failed";
195
196 /* set hash to be LSB of rpAddress */
197 bda.address[5] = output.param_buf[0];
198 bda.address[4] = output.param_buf[1];
199 bda.address[3] = output.param_buf[2];
200
201 cb.Run(bda);
202 }
203
GenerateRpa(base::Callback<void (bt_bdaddr_t)> cb)204 void GenerateRpa(base::Callback<void(bt_bdaddr_t)> cb) {
205 btm_gen_resolvable_private_addr(
206 Bind(&BleAdvertisingManagerImpl::OnRpaGenerationComplete,
207 base::Unretained(this), std::move(cb)));
208 }
209
ConfigureRpa(AdvertisingInstance * p_inst,MultiAdvCb configuredCb)210 void ConfigureRpa(AdvertisingInstance* p_inst, MultiAdvCb configuredCb) {
211 /* Connectable advertising set must be disabled when updating RPA */
212 bool restart = p_inst->IsEnabled() && p_inst->IsConnectable();
213
214 // If there is any form of timeout on the set, schedule address update when
215 // the set stops, because there is no good way to compute new timeout value.
216 // Maximum duration value is around 10 minutes, so this is safe.
217 if (restart && (p_inst->duration || p_inst->maxExtAdvEvents)) {
218 p_inst->address_update_required = true;
219 configuredCb.Run(0x01);
220 return;
221 }
222
223 GenerateRpa(Bind(
224 [](AdvertisingInstance* p_inst, MultiAdvCb configuredCb,
225 bt_bdaddr_t bda) {
226 /* Connectable advertising set must be disabled when updating RPA */
227 bool restart = p_inst->IsEnabled() && p_inst->IsConnectable();
228
229 auto hci_interface =
230 ((BleAdvertisingManagerImpl*)BleAdvertisingManager::Get())
231 ->GetHciInterface();
232
233 if (restart) {
234 p_inst->enable_status = false;
235 hci_interface->Enable(false, p_inst->inst_id, 0x00, 0x00,
236 Bind(DoNothing));
237 }
238
239 /* set it to controller */
240 hci_interface->SetRandomAddress(
241 p_inst->inst_id, p_inst->own_address,
242 Bind(
243 [](AdvertisingInstance* p_inst, bt_bdaddr_t bda,
244 MultiAdvCb configuredCb, uint8_t status) {
245 memcpy(p_inst->own_address, &bda, BD_ADDR_LEN);
246 configuredCb.Run(0x00);
247 },
248 p_inst, bda, configuredCb));
249
250 if (restart) {
251 p_inst->enable_status = true;
252 hci_interface->Enable(true, p_inst->inst_id, 0x00, 0x00,
253 Bind(DoNothing));
254 }
255 },
256 p_inst, std::move(configuredCb)));
257 }
258
RegisterAdvertiser(base::Callback<void (uint8_t,uint8_t)> cb)259 void RegisterAdvertiser(
260 base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)> cb)
261 override {
262 AdvertisingInstance* p_inst = &adv_inst[0];
263 for (uint8_t i = 0; i < inst_count; i++, p_inst++) {
264 if (p_inst->in_use) continue;
265
266 p_inst->in_use = true;
267
268 // set up periodic timer to update address.
269 if (BTM_BleLocalPrivacyEnabled()) {
270 p_inst->own_address_type = BLE_ADDR_RANDOM;
271 GenerateRpa(Bind(
272 [](AdvertisingInstance* p_inst,
273 base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)>
274 cb,
275 bt_bdaddr_t bda) {
276 memcpy(p_inst->own_address, &bda, BD_ADDR_LEN);
277
278 alarm_set_on_queue(p_inst->adv_raddr_timer,
279 BTM_BLE_PRIVATE_ADDR_INT_MS,
280 btm_ble_adv_raddr_timer_timeout, p_inst,
281 btu_general_alarm_queue);
282 cb.Run(p_inst->inst_id, BTM_BLE_MULTI_ADV_SUCCESS);
283 },
284 p_inst, cb));
285 } else {
286 p_inst->own_address_type = BLE_ADDR_PUBLIC;
287 memcpy(p_inst->own_address,
288 controller_get_interface()->get_address()->address, BD_ADDR_LEN);
289
290 cb.Run(p_inst->inst_id, BTM_BLE_MULTI_ADV_SUCCESS);
291 }
292 return;
293 }
294
295 LOG(INFO) << "no free advertiser instance";
296 cb.Run(0xFF, ADVERTISE_FAILED_TOO_MANY_ADVERTISERS);
297 }
298
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)299 void StartAdvertising(uint8_t advertiser_id, MultiAdvCb cb,
300 tBTM_BLE_ADV_PARAMS* params,
301 std::vector<uint8_t> advertise_data,
302 std::vector<uint8_t> scan_response_data, int duration,
303 MultiAdvCb timeout_cb) override {
304 /* a temporary type for holding all the data needed in callbacks below*/
305 struct CreatorParams {
306 uint8_t inst_id;
307 BleAdvertisingManagerImpl* self;
308 MultiAdvCb cb;
309 tBTM_BLE_ADV_PARAMS params;
310 std::vector<uint8_t> advertise_data;
311 std::vector<uint8_t> scan_response_data;
312 int duration;
313 MultiAdvCb timeout_cb;
314 };
315
316 std::unique_ptr<CreatorParams> c;
317 c.reset(new CreatorParams());
318
319 c->self = this;
320 c->cb = std::move(cb);
321 c->params = *params;
322 c->advertise_data = std::move(advertise_data);
323 c->scan_response_data = std::move(scan_response_data);
324 c->duration = duration;
325 c->timeout_cb = std::move(timeout_cb);
326 c->inst_id = advertiser_id;
327
328 using c_type = std::unique_ptr<CreatorParams>;
329
330 // this code is intentionally left formatted this way to highlight the
331 // asynchronous flow
332 // clang-format off
333 c->self->SetParameters(c->inst_id, &c->params, Bind(
334 [](c_type c, uint8_t status, int8_t tx_power) {
335 if (status != 0) {
336 LOG(ERROR) << "setting parameters failed, status: " << +status;
337 c->cb.Run(status);
338 return;
339 }
340
341 c->self->adv_inst[c->inst_id].tx_power = tx_power;
342
343 BD_ADDR *rpa = &c->self->adv_inst[c->inst_id].own_address;
344 c->self->GetHciInterface()->SetRandomAddress(c->inst_id, *rpa, Bind(
345 [](c_type c, uint8_t status) {
346 if (status != 0) {
347 LOG(ERROR) << "setting random address failed, status: " << +status;
348 c->cb.Run(status);
349 return;
350 }
351
352 c->self->SetData(c->inst_id, false, std::move(c->advertise_data), Bind(
353 [](c_type c, uint8_t status) {
354 if (status != 0) {
355 LOG(ERROR) << "setting advertise data failed, status: " << +status;
356 c->cb.Run(status);
357 return;
358 }
359
360 c->self->SetData(c->inst_id, true, std::move(c->scan_response_data), Bind(
361 [](c_type c, uint8_t status) {
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 = this;
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
399 // this code is intentionally left formatted this way to highlight the
400 // asynchronous flow
401 // clang-format off
402 c->self->RegisterAdvertiser(Bind(
403 [](c_type c, uint8_t advertiser_id, uint8_t status) {
404 if (status != 0) {
405 LOG(ERROR) << "registering advertiser failed, status: " << +status;
406 c->cb.Run(0, 0, status);
407 return;
408 }
409
410 c->inst_id = advertiser_id;
411
412 c->self->SetParameters(c->inst_id, &c->params, Bind(
413 [](c_type c, uint8_t status, int8_t tx_power) {
414 if (status != 0) {
415 c->self->Unregister(c->inst_id);
416 LOG(ERROR) << "setting parameters failed, status: " << +status;
417 c->cb.Run(0, 0, status);
418 return;
419 }
420
421 c->self->adv_inst[c->inst_id].tx_power = tx_power;
422
423 BD_ADDR *rpa = &c->self->adv_inst[c->inst_id].own_address;
424 c->self->GetHciInterface()->SetRandomAddress(c->inst_id, *rpa, Bind(
425 [](c_type c, uint8_t status) {
426 if (status != 0) {
427 c->self->Unregister(c->inst_id);
428 LOG(ERROR) << "setting random address failed, status: " << +status;
429 c->cb.Run(0, 0, status);
430 return;
431 }
432
433 c->self->SetData(c->inst_id, false, std::move(c->advertise_data), Bind(
434 [](c_type c, uint8_t status) {
435 if (status != 0) {
436 c->self->Unregister(c->inst_id);
437 LOG(ERROR) << "setting advertise data failed, status: " << +status;
438 c->cb.Run(0, 0, status);
439 return;
440 }
441
442 c->self->SetData(c->inst_id, true, std::move(c->scan_response_data), Bind(
443 [](c_type c, uint8_t status) {
444 if (status != 0) {
445 c->self->Unregister(c->inst_id);
446 LOG(ERROR) << "setting scan response data failed, status: " << +status;
447 c->cb.Run(0, 0, status);
448 return;
449 }
450
451 if (c->periodic_params.enable) {
452 c->self->StartAdvertisingSetPeriodicPart(std::move(c));
453 } else {
454 c->self->StartAdvertisingSetFinish(std::move(c));
455 }
456 }, base::Passed(&c)));
457 }, base::Passed(&c)));
458 }, base::Passed(&c)));
459 }, base::Passed(&c)));
460 }, base::Passed(&c)));
461 // clang-format on
462 }
463
StartAdvertisingSetPeriodicPart(c_type c)464 void StartAdvertisingSetPeriodicPart(c_type c) {
465 // this code is intentionally left formatted this way to highlight the
466 // asynchronous flow
467 // clang-format off
468 c->self->SetPeriodicAdvertisingParameters(c->inst_id, &c->periodic_params, Bind(
469 [](c_type c, uint8_t status) {
470 if (status != 0) {
471 c->self->Unregister(c->inst_id);
472 LOG(ERROR) << "setting periodic parameters failed, status: " << +status;
473 c->cb.Run(0, 0, status);
474 return;
475 }
476
477 c->self->SetPeriodicAdvertisingData(c->inst_id, std::move(c->periodic_data), Bind(
478 [](c_type c, uint8_t status) {
479 if (status != 0) {
480 c->self->Unregister(c->inst_id);
481 LOG(ERROR) << "setting periodic parameters failed, status: " << +status;
482 c->cb.Run(0, 0, status);
483 return;
484 }
485
486 c->self->SetPeriodicAdvertisingEnable(c->inst_id, true, Bind(
487 [](c_type c, uint8_t status) {
488 if (status != 0) {
489 c->self->Unregister(c->inst_id);
490 LOG(ERROR) << "enabling periodic advertising failed, status: " << +status;
491 c->cb.Run(0, 0, status);
492 return;
493 }
494
495 c->self->StartAdvertisingSetFinish(std::move(c));
496
497 }, base::Passed(&c)));
498 }, base::Passed(&c)));
499 }, base::Passed(&c)));
500 // clang-format on
501 }
502
StartAdvertisingSetFinish(c_type c)503 void StartAdvertisingSetFinish(c_type c) {
504 uint8_t inst_id = c->inst_id;
505 uint16_t duration = c->duration;
506 uint8_t maxExtAdvEvents = c->maxExtAdvEvents;
507 RegisterCb timeout_cb = std::move(c->timeout_cb);
508 BleAdvertisingManagerImpl* self = c->self;
509 MultiAdvCb enable_cb = Bind(
510 [](c_type c, uint8_t status) {
511 if (status != 0) {
512 c->self->Unregister(c->inst_id);
513 LOG(ERROR) << "enabling advertiser failed, status: " << +status;
514 c->cb.Run(0, 0, status);
515 return;
516 }
517 int8_t tx_power = c->self->adv_inst[c->inst_id].tx_power;
518 c->cb.Run(c->inst_id, tx_power, status);
519 },
520 base::Passed(&c));
521
522 self->Enable(inst_id, true, std::move(enable_cb), duration, maxExtAdvEvents,
523 Bind(std::move(timeout_cb), inst_id));
524 }
525
EnableWithTimerCb(uint8_t inst_id,MultiAdvCb enable_cb,int duration,MultiAdvCb timeout_cb,uint8_t status)526 void EnableWithTimerCb(uint8_t inst_id, MultiAdvCb enable_cb, int duration,
527 MultiAdvCb timeout_cb, uint8_t status) {
528 VLOG(1) << __func__ << " inst_id: " << +inst_id;
529 AdvertisingInstance* p_inst = &adv_inst[inst_id];
530
531 // Run the regular enable callback
532 enable_cb.Run(status);
533
534 p_inst->timeout_timer = alarm_new("btm_ble.adv_timeout");
535
536 base::Closure cb = Bind(&BleAdvertisingManagerImpl::Enable,
537 base::Unretained(this), inst_id, 0 /* disable */,
538 std::move(timeout_cb), 0, 0, base::Bind(DoNothing));
539
540 // schedule disable when the timeout passes
541 alarm_set_closure_on_queue(FROM_HERE, p_inst->timeout_timer, duration * 10,
542 std::move(cb), btu_general_alarm_queue);
543 }
544
Enable(uint8_t inst_id,bool enable,MultiAdvCb cb,uint16_t duration,uint8_t maxExtAdvEvents,MultiAdvCb timeout_cb)545 void Enable(uint8_t inst_id, bool enable, MultiAdvCb cb, uint16_t duration,
546 uint8_t maxExtAdvEvents, MultiAdvCb timeout_cb) override {
547 VLOG(1) << __func__ << " inst_id: " << +inst_id;
548 if (inst_id >= inst_count) {
549 LOG(ERROR) << "bad instance id " << +inst_id;
550 return;
551 }
552
553 AdvertisingInstance* p_inst = &adv_inst[inst_id];
554 VLOG(1) << __func__ << " enable: " << enable << ", duration: " << +duration;
555 if (!p_inst->in_use) {
556 LOG(ERROR) << "Invalid or no active instance";
557 cb.Run(BTM_BLE_MULTI_ADV_FAILURE);
558 return;
559 }
560
561 if (enable && (duration || maxExtAdvEvents)) {
562 p_inst->timeout_cb = std::move(timeout_cb);
563 }
564
565 p_inst->duration = duration;
566 p_inst->maxExtAdvEvents = maxExtAdvEvents;
567
568 if (enable && p_inst->address_update_required) {
569 p_inst->address_update_required = false;
570 ConfigureRpa(p_inst, base::Bind(&BleAdvertisingManagerImpl::EnableFinish,
571 base::Unretained(this), p_inst, enable,
572 std::move(cb)));
573 return;
574 }
575
576 EnableFinish(p_inst, enable, std::move(cb), 0);
577 }
578
EnableFinish(AdvertisingInstance * p_inst,bool enable,MultiAdvCb cb,uint8_t status)579 void EnableFinish(AdvertisingInstance* p_inst, bool enable, MultiAdvCb cb,
580 uint8_t status) {
581 if (enable && p_inst->duration) {
582 p_inst->enable_status = enable;
583 // TODO(jpawlowski): HCI implementation that can't do duration should
584 // emulate it, not EnableWithTimerCb.
585 GetHciInterface()->Enable(
586 enable, p_inst->inst_id, p_inst->duration, p_inst->maxExtAdvEvents,
587 Bind(&BleAdvertisingManagerImpl::EnableWithTimerCb,
588 base::Unretained(this), p_inst->inst_id, std::move(cb),
589 p_inst->duration, p_inst->timeout_cb));
590
591 } else {
592 if (p_inst->timeout_timer) {
593 alarm_cancel(p_inst->timeout_timer);
594 alarm_free(p_inst->timeout_timer);
595 p_inst->timeout_timer = nullptr;
596 }
597
598 p_inst->enable_status = enable;
599 GetHciInterface()->Enable(enable, p_inst->inst_id, p_inst->duration,
600 p_inst->maxExtAdvEvents, std::move(cb));
601 }
602 }
603
SetParameters(uint8_t inst_id,tBTM_BLE_ADV_PARAMS * p_params,ParametersCb cb)604 void SetParameters(uint8_t inst_id, tBTM_BLE_ADV_PARAMS* p_params,
605 ParametersCb cb) override {
606 VLOG(1) << __func__ << " inst_id: " << +inst_id;
607 if (inst_id >= inst_count) {
608 LOG(ERROR) << "bad instance id " << +inst_id;
609 return;
610 }
611
612 AdvertisingInstance* p_inst = &adv_inst[inst_id];
613 if (!p_inst->in_use) {
614 LOG(ERROR) << "adv instance not in use" << +inst_id;
615 cb.Run(BTM_BLE_MULTI_ADV_FAILURE, 0);
616 return;
617 }
618
619 // TODO: disable only if was enabled, currently no use scenario needs that,
620 // we always set parameters before enabling
621 // GetHciInterface()->Enable(false, inst_id, Bind(DoNothing));
622 p_inst->advertising_event_properties =
623 p_params->advertising_event_properties;
624 p_inst->tx_power = p_params->tx_power;
625 BD_ADDR peer_address = {0, 0, 0, 0, 0, 0};
626
627 GetHciInterface()->SetParameters(
628 p_inst->inst_id, p_params->advertising_event_properties,
629 p_params->adv_int_min, p_params->adv_int_max, p_params->channel_map,
630 p_inst->own_address_type, p_inst->own_address, 0x00, peer_address,
631 p_params->adv_filter_policy, p_inst->tx_power,
632 p_params->primary_advertising_phy, 0x01,
633 p_params->secondary_advertising_phy, 0x01 /* TODO: proper SID */,
634 p_params->scan_request_notification_enable, cb);
635
636 // TODO: re-enable only if it was enabled, properly call
637 // SetParamsCallback
638 // currently no use scenario needs that
639 // GetHciInterface()->Enable(true, inst_id, BTM_BleUpdateAdvInstParamCb);
640 }
641
SetData(uint8_t inst_id,bool is_scan_rsp,std::vector<uint8_t> data,MultiAdvCb cb)642 void SetData(uint8_t inst_id, bool is_scan_rsp, std::vector<uint8_t> data,
643 MultiAdvCb cb) override {
644 VLOG(1) << __func__ << " inst_id: " << +inst_id;
645 if (inst_id >= inst_count) {
646 LOG(ERROR) << "bad instance id " << +inst_id;
647 return;
648 }
649
650 AdvertisingInstance* p_inst = &adv_inst[inst_id];
651 VLOG(1) << "is_scan_rsp = " << is_scan_rsp;
652
653 if (!is_scan_rsp && is_connectable(p_inst->advertising_event_properties)) {
654 uint8_t flags_val = BTM_GENERAL_DISCOVERABLE;
655
656 if (p_inst->duration) flags_val = BTM_LIMITED_DISCOVERABLE;
657
658 std::vector<uint8_t> flags;
659 flags.push_back(2); // length
660 flags.push_back(HCI_EIR_FLAGS_TYPE);
661 flags.push_back(flags_val);
662
663 data.insert(data.begin(), flags.begin(), flags.end());
664 }
665
666 // Find and fill TX Power with the correct value
667 if (data.size()) {
668 size_t i = 0;
669 while (i < data.size()) {
670 uint8_t type = data[i + 1];
671 if (type == HCI_EIR_TX_POWER_LEVEL_TYPE) {
672 data[i + 2] = adv_inst[inst_id].tx_power;
673 }
674 i += data[i] + 1;
675 }
676 }
677
678 VLOG(1) << "data is: " << base::HexEncode(data.data(), data.size());
679 DivideAndSendData(
680 inst_id, data, cb,
681 base::Bind(&BleAdvertisingManagerImpl::SetDataAdvDataSender,
682 base::Unretained(this), is_scan_rsp));
683 }
684
SetDataAdvDataSender(uint8_t is_scan_rsp,uint8_t inst_id,uint8_t operation,uint8_t length,uint8_t * data,MultiAdvCb cb)685 void SetDataAdvDataSender(uint8_t is_scan_rsp, uint8_t inst_id,
686 uint8_t operation, uint8_t length, uint8_t* data,
687 MultiAdvCb cb) {
688 if (is_scan_rsp)
689 GetHciInterface()->SetScanResponseData(inst_id, operation, 0x01, length,
690 data, cb);
691 else
692 GetHciInterface()->SetAdvertisingData(inst_id, operation, 0x01, length,
693 data, cb);
694 }
695
696 using DataSender = base::Callback<void(
697 uint8_t /*inst_id*/, uint8_t /* operation */, uint8_t /* length */,
698 uint8_t* /* data */, MultiAdvCb /* done */)>;
699
DivideAndSendData(int inst_id,std::vector<uint8_t> data,MultiAdvCb done_cb,DataSender sender)700 void DivideAndSendData(int inst_id, std::vector<uint8_t> data,
701 MultiAdvCb done_cb, DataSender sender) {
702 DivideAndSendDataRecursively(true, inst_id, std::move(data), 0,
703 std::move(done_cb), std::move(sender), 0);
704 }
705
DivideAndSendDataRecursively(bool isFirst,int inst_id,std::vector<uint8_t> data,int offset,MultiAdvCb done_cb,DataSender sender,uint8_t status)706 static void DivideAndSendDataRecursively(bool isFirst, int inst_id,
707 std::vector<uint8_t> data,
708 int offset, MultiAdvCb done_cb,
709 DataSender sender, uint8_t status) {
710 constexpr uint8_t INTERMEDIATE =
711 0x00; // Intermediate fragment of fragmented data
712 constexpr uint8_t FIRST = 0x01; // First fragment of fragmented data
713 constexpr uint8_t LAST = 0x02; // Last fragment of fragmented data
714 constexpr uint8_t COMPLETE = 0x03; // Complete extended advertising data
715
716 int dataSize = (int)data.size();
717 if (status != 0 || (!isFirst && offset == dataSize)) {
718 /* if we got error writing data, or reached the end of data */
719 done_cb.Run(status);
720 return;
721 }
722
723 bool moreThanOnePacket = dataSize - offset > ADV_DATA_LEN_MAX;
724 uint8_t operation = isFirst ? moreThanOnePacket ? FIRST : COMPLETE
725 : moreThanOnePacket ? INTERMEDIATE : LAST;
726 int length = moreThanOnePacket ? ADV_DATA_LEN_MAX : dataSize - offset;
727 int newOffset = offset + length;
728
729 sender.Run(
730 inst_id, operation, length, data.data() + offset,
731 Bind(&BleAdvertisingManagerImpl::DivideAndSendDataRecursively, false,
732 inst_id, std::move(data), newOffset, std::move(done_cb), sender));
733 }
734
SetPeriodicAdvertisingParameters(uint8_t inst_id,tBLE_PERIODIC_ADV_PARAMS * params,MultiAdvCb cb)735 void SetPeriodicAdvertisingParameters(uint8_t inst_id,
736 tBLE_PERIODIC_ADV_PARAMS* params,
737 MultiAdvCb cb) override {
738 VLOG(1) << __func__ << " inst_id: " << +inst_id;
739
740 GetHciInterface()->SetPeriodicAdvertisingParameters(
741 inst_id, params->min_interval, params->max_interval,
742 params->periodic_advertising_properties, cb);
743 }
744
SetPeriodicAdvertisingData(uint8_t inst_id,std::vector<uint8_t> data,MultiAdvCb cb)745 void SetPeriodicAdvertisingData(uint8_t inst_id, std::vector<uint8_t> data,
746 MultiAdvCb cb) override {
747 VLOG(1) << __func__ << " inst_id: " << +inst_id;
748
749 VLOG(1) << "data is: " << base::HexEncode(data.data(), data.size());
750
751 DivideAndSendData(
752 inst_id, data, cb,
753 base::Bind(&BleAdvertiserHciInterface::SetPeriodicAdvertisingData,
754 base::Unretained(GetHciInterface())));
755 }
756
SetPeriodicAdvertisingEnable(uint8_t inst_id,uint8_t enable,MultiAdvCb cb)757 void SetPeriodicAdvertisingEnable(uint8_t inst_id, uint8_t enable,
758 MultiAdvCb cb) override {
759 VLOG(1) << __func__ << " inst_id: " << +inst_id << ", enable: " << +enable;
760
761 GetHciInterface()->SetPeriodicAdvertisingEnable(enable, inst_id, cb);
762 }
763
Unregister(uint8_t inst_id)764 void Unregister(uint8_t inst_id) override {
765 AdvertisingInstance* p_inst = &adv_inst[inst_id];
766
767 VLOG(1) << __func__ << " inst_id: " << +inst_id;
768 if (inst_id >= inst_count) {
769 LOG(ERROR) << "bad instance id " << +inst_id;
770 return;
771 }
772
773 if (adv_inst[inst_id].IsEnabled()) {
774 p_inst->enable_status = false;
775 GetHciInterface()->Enable(false, inst_id, 0x00, 0x00, Bind(DoNothing));
776 }
777
778 alarm_cancel(p_inst->adv_raddr_timer);
779 p_inst->in_use = false;
780 GetHciInterface()->RemoveAdvertisingSet(inst_id, Bind(DoNothing));
781 p_inst->address_update_required = false;
782 }
783
OnAdvertisingSetTerminated(uint8_t status,uint8_t advertising_handle,uint16_t connection_handle,uint8_t num_completed_extended_adv_events)784 void OnAdvertisingSetTerminated(
785 uint8_t status, uint8_t advertising_handle, uint16_t connection_handle,
786 uint8_t num_completed_extended_adv_events) override {
787 AdvertisingInstance* p_inst = &adv_inst[advertising_handle];
788 VLOG(1) << __func__ << "status: 0x" << std::hex << +status
789 << ", advertising_handle: 0x" << std::hex << +advertising_handle
790 << ", connection_handle: 0x" << std::hex << +connection_handle;
791
792 if (status == 0x43 || status == 0x3C) {
793 // either duration elapsed, or maxExtAdvEvents reached
794 p_inst->enable_status = false;
795
796 if (p_inst->timeout_cb.is_null()) {
797 LOG(INFO) << __func__ << "No timeout callback";
798 return;
799 }
800
801 p_inst->timeout_cb.Run(status);
802 return;
803 }
804
805 if (BTM_BleLocalPrivacyEnabled() &&
806 advertising_handle <= BTM_BLE_MULTI_ADV_MAX) {
807 btm_acl_update_conn_addr(connection_handle, p_inst->own_address);
808 }
809
810 VLOG(1) << "reneabling advertising";
811
812 if (p_inst->in_use == true) {
813 // TODO(jpawlowski): we don't really allow to do directed advertising
814 // right now. This should probably be removed, check with Andre.
815 if ((p_inst->advertising_event_properties & 0x0C) ==
816 0 /* directed advertising bits not set */) {
817 GetHciInterface()->Enable(true, advertising_handle, 0x00, 0x00,
818 Bind(DoNothing));
819 } else {
820 /* mark directed adv as disabled if adv has been stopped */
821 p_inst->in_use = false;
822 }
823 }
824 }
825
826 private:
GetHciInterface()827 BleAdvertiserHciInterface* GetHciInterface() { return hci_interface; }
828
829 BleAdvertiserHciInterface* hci_interface = nullptr;
830 std::vector<AdvertisingInstance> adv_inst;
831 uint8_t inst_count;
832 };
833
834 BleAdvertisingManager* instance;
835
btm_ble_adv_raddr_timer_timeout(void * data)836 void btm_ble_adv_raddr_timer_timeout(void* data) {
837 ((BleAdvertisingManagerImpl*)BleAdvertisingManager::Get())
838 ->ConfigureRpa((AdvertisingInstance*)data, base::Bind(DoNothing));
839 }
840 } // namespace
841
Initialize(BleAdvertiserHciInterface * interface)842 void BleAdvertisingManager::Initialize(BleAdvertiserHciInterface* interface) {
843 instance = new BleAdvertisingManagerImpl(interface);
844 }
845
Get()846 BleAdvertisingManager* BleAdvertisingManager::Get() {
847 CHECK(instance);
848 return instance;
849 };
850
CleanUp()851 void BleAdvertisingManager::CleanUp() {
852 delete instance;
853 instance = nullptr;
854 };
855
856 /**
857 * This function initialize the advertising manager.
858 **/
btm_ble_adv_init()859 void btm_ble_adv_init() {
860 BleAdvertiserHciInterface::Initialize();
861 BleAdvertisingManager::Initialize(BleAdvertiserHciInterface::Get());
862 BleAdvertiserHciInterface::Get()->SetAdvertisingEventObserver(
863 (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get());
864
865 if (BleAdvertiserHciInterface::Get()->QuirkAdvertiserZeroHandle()) {
866 // If handle 0 can't be used, register advertiser for it, but never use it.
867 BleAdvertisingManager::Get()->RegisterAdvertiser(Bind(DoNothing2));
868 }
869 }
870
871 /*******************************************************************************
872 *
873 * Function btm_ble_multi_adv_cleanup
874 *
875 * Description This function cleans up multi adv control block.
876 *
877 * Parameters
878 * Returns void
879 *
880 ******************************************************************************/
btm_ble_multi_adv_cleanup(void)881 void btm_ble_multi_adv_cleanup(void) {
882 BleAdvertisingManager::CleanUp();
883 BleAdvertiserHciInterface::CleanUp();
884 }
885