• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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