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