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