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