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