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