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