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 <string.h>
24 #include <queue>
25 #include <vector>
26 
27 #include "bt_target.h"
28 #include "device/include/controller.h"
29 #include "osi/include/alarm.h"
30 
31 #include "ble_advertiser.h"
32 #include "ble_advertiser_hci_interface.h"
33 #include "btm_int_types.h"
34 
35 using base::Bind;
36 using RegisterCb =
37     base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)>;
38 using IdTxPowerStatusCb = base::Callback<void(
39     uint8_t /* inst_id */, int8_t /* tx_power */, uint8_t /* status */)>;
40 extern void btm_gen_resolvable_private_addr(
41     base::Callback<void(uint8_t[8])> cb);
42 extern fixed_queue_t* btu_general_alarm_queue;
43 
44 constexpr int ADV_DATA_LEN_MAX = 251;
45 
46 namespace {
47 
is_connectable(uint16_t advertising_event_properties)48 bool is_connectable(uint16_t advertising_event_properties) {
49   return advertising_event_properties & 0x01;
50 }
51 
52 struct AdvertisingInstance {
53   uint8_t inst_id;
54   bool in_use;
55   uint8_t advertising_event_properties;
56   alarm_t* adv_raddr_timer;
57   int8_t tx_power;
58   uint16_t duration;
59   uint8_t maxExtAdvEvents;
60   alarm_t* timeout_timer;
61   uint8_t own_address_type;
62   BD_ADDR own_address;
63   MultiAdvCb timeout_cb;
64   bool address_update_required;
65 
66   /* When true, advertising set is enabled, or last scheduled call to "LE Set
67    * Extended Advertising Set Enable" is to enable this advertising set. Any
68    * command scheduled when in this state will execute when the set is enabled,
69    * unless enabling fails.
70    *
71    * When false, advertising set is disabled, or last scheduled call to "LE Set
72    * Extended Advertising Set Enable" is to disable this advertising set. Any
73    * command scheduled when in this state will execute when the set is disabled.
74    */
75   bool enable_status;
76 
IsEnabled__anon08ab64bc0111::AdvertisingInstance77   bool IsEnabled() { return enable_status; }
78 
IsConnectable__anon08ab64bc0111::AdvertisingInstance79   bool IsConnectable() { return is_connectable(advertising_event_properties); }
80 
AdvertisingInstance__anon08ab64bc0111::AdvertisingInstance81   AdvertisingInstance(int inst_id)
82       : inst_id(inst_id),
83         in_use(false),
84         advertising_event_properties(0),
85         tx_power(0),
86         duration(0),
87         timeout_timer(nullptr),
88         own_address_type(0),
89         own_address{0},
90         address_update_required(false),
91         enable_status(false) {
92     adv_raddr_timer = alarm_new_periodic("btm_ble.adv_raddr_timer");
93   }
94 
~AdvertisingInstance__anon08ab64bc0111::AdvertisingInstance95   ~AdvertisingInstance() {
96     alarm_free(adv_raddr_timer);
97     if (timeout_timer) alarm_free(timeout_timer);
98   }
99 };
100 
101 void btm_ble_adv_raddr_timer_timeout(void* data);
102 
DoNothing(uint8_t)103 void DoNothing(uint8_t) {}
DoNothing2(uint8_t,uint8_t)104 void DoNothing2(uint8_t, uint8_t) {}
105 
106 struct closure_data {
107   base::Closure user_task;
108   tracked_objects::Location posted_from;
109 };
110 
alarm_closure_cb(void * p)111 static void alarm_closure_cb(void* p) {
112   closure_data* data = (closure_data*)p;
113   VLOG(1) << "executing timer scheduled at %s" << data->posted_from.ToString();
114   data->user_task.Run();
115   delete data;
116 }
117 
118 // Periodic alarms are not supported, because we clean up data in callback
alarm_set_closure_on_queue(const tracked_objects::Location & posted_from,alarm_t * alarm,period_ms_t interval_ms,base::Closure user_task,fixed_queue_t * queue)119 void alarm_set_closure_on_queue(const tracked_objects::Location& posted_from,
120                                 alarm_t* alarm, period_ms_t interval_ms,
121                                 base::Closure user_task, fixed_queue_t* queue) {
122   closure_data* data = new closure_data;
123   data->posted_from = posted_from;
124   data->user_task = std::move(user_task);
125   VLOG(1) << "scheduling timer %s" << data->posted_from.ToString();
126   alarm_set_on_queue(alarm, interval_ms, alarm_closure_cb, data, queue);
127 }
128 
129 class BleAdvertisingManagerImpl;
130 
131 /* a temporary type for holding all the data needed in callbacks below*/
132 struct CreatorParams {
133   uint8_t inst_id;
134   BleAdvertisingManagerImpl* self;
135   IdTxPowerStatusCb cb;
136   tBTM_BLE_ADV_PARAMS params;
137   std::vector<uint8_t> advertise_data;
138   std::vector<uint8_t> scan_response_data;
139   tBLE_PERIODIC_ADV_PARAMS periodic_params;
140   std::vector<uint8_t> periodic_data;
141   uint16_t duration;
142   uint8_t maxExtAdvEvents;
143   RegisterCb timeout_cb;
144 };
145 
146 using c_type = std::unique_ptr<CreatorParams>;
147 
148 class BleAdvertisingManagerImpl
149     : public BleAdvertisingManager,
150       public BleAdvertiserHciInterface::AdvertisingEventObserver {
151  public:
BleAdvertisingManagerImpl(BleAdvertiserHciInterface * interface)152   BleAdvertisingManagerImpl(BleAdvertiserHciInterface* interface) {
153     this->hci_interface = interface;
154     hci_interface->ReadInstanceCount(
155         base::Bind(&BleAdvertisingManagerImpl::ReadInstanceCountCb,
156                    base::Unretained(this)));
157   }
158 
~BleAdvertisingManagerImpl()159   ~BleAdvertisingManagerImpl() { adv_inst.clear(); }
160 
GetOwnAddress(uint8_t inst_id,GetAddressCallback cb)161   void GetOwnAddress(uint8_t inst_id, GetAddressCallback cb) override {
162     bt_bdaddr_t addr;
163     memcpy(addr.address, adv_inst[inst_id].own_address, BD_ADDR_LEN);
164     cb.Run(adv_inst[inst_id].own_address_type, addr);
165   }
166 
ReadInstanceCountCb(uint8_t instance_count)167   void ReadInstanceCountCb(uint8_t instance_count) {
168     this->inst_count = instance_count;
169     adv_inst.reserve(inst_count);
170     /* Initialize adv instance indices and IDs. */
171     for (uint8_t i = 0; i < inst_count; i++) {
172       adv_inst.emplace_back(i);
173     }
174   }
175 
OnRpaGenerationComplete(base::Callback<void (bt_bdaddr_t)> cb,uint8_t rand[8])176   void OnRpaGenerationComplete(base::Callback<void(bt_bdaddr_t)> cb,
177                                uint8_t rand[8]) {
178     VLOG(1) << __func__;
179 
180     bt_bdaddr_t bda;
181 
182     rand[2] &= (~BLE_RESOLVE_ADDR_MASK);
183     rand[2] |= BLE_RESOLVE_ADDR_MSB;
184 
185     bda.address[2] = rand[0];
186     bda.address[1] = rand[1];
187     bda.address[0] = rand[2];
188 
189     BT_OCTET16 irk;
190     BTM_GetDeviceIDRoot(irk);
191     tSMP_ENC output;
192 
193     if (!SMP_Encrypt(irk, BT_OCTET16_LEN, rand, 3, &output))
194       LOG_ASSERT(false) << "SMP_Encrypt failed";
195 
196     /* set hash to be LSB of rpAddress */
197     bda.address[5] = output.param_buf[0];
198     bda.address[4] = output.param_buf[1];
199     bda.address[3] = output.param_buf[2];
200 
201     cb.Run(bda);
202   }
203 
GenerateRpa(base::Callback<void (bt_bdaddr_t)> cb)204   void GenerateRpa(base::Callback<void(bt_bdaddr_t)> cb) {
205     btm_gen_resolvable_private_addr(
206         Bind(&BleAdvertisingManagerImpl::OnRpaGenerationComplete,
207              base::Unretained(this), std::move(cb)));
208   }
209 
ConfigureRpa(AdvertisingInstance * p_inst,MultiAdvCb configuredCb)210   void ConfigureRpa(AdvertisingInstance* p_inst, MultiAdvCb configuredCb) {
211     /* Connectable advertising set must be disabled when updating RPA */
212     bool restart = p_inst->IsEnabled() && p_inst->IsConnectable();
213 
214     // If there is any form of timeout on the set, schedule address update when
215     // the set stops, because there is no good way to compute new timeout value.
216     // Maximum duration value is around 10 minutes, so this is safe.
217     if (restart && (p_inst->duration || p_inst->maxExtAdvEvents)) {
218       p_inst->address_update_required = true;
219       configuredCb.Run(0x01);
220       return;
221     }
222 
223     GenerateRpa(Bind(
224         [](AdvertisingInstance* p_inst, MultiAdvCb configuredCb,
225            bt_bdaddr_t bda) {
226           /* Connectable advertising set must be disabled when updating RPA */
227           bool restart = p_inst->IsEnabled() && p_inst->IsConnectable();
228 
229           auto hci_interface =
230               ((BleAdvertisingManagerImpl*)BleAdvertisingManager::Get())
231                   ->GetHciInterface();
232 
233           if (restart) {
234             p_inst->enable_status = false;
235             hci_interface->Enable(false, p_inst->inst_id, 0x00, 0x00,
236                                   Bind(DoNothing));
237           }
238 
239           /* set it to controller */
240           hci_interface->SetRandomAddress(
241               p_inst->inst_id, p_inst->own_address,
242               Bind(
243                   [](AdvertisingInstance* p_inst, bt_bdaddr_t bda,
244                      MultiAdvCb configuredCb, uint8_t status) {
245                     memcpy(p_inst->own_address, &bda, BD_ADDR_LEN);
246                     configuredCb.Run(0x00);
247                   },
248                   p_inst, bda, configuredCb));
249 
250           if (restart) {
251             p_inst->enable_status = true;
252             hci_interface->Enable(true, p_inst->inst_id, 0x00, 0x00,
253                                   Bind(DoNothing));
254           }
255         },
256         p_inst, std::move(configuredCb)));
257   }
258 
RegisterAdvertiser(base::Callback<void (uint8_t,uint8_t)> cb)259   void RegisterAdvertiser(
260       base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)> cb)
261       override {
262     AdvertisingInstance* p_inst = &adv_inst[0];
263     for (uint8_t i = 0; i < inst_count; i++, p_inst++) {
264       if (p_inst->in_use) continue;
265 
266       p_inst->in_use = true;
267 
268       // set up periodic timer to update address.
269       if (BTM_BleLocalPrivacyEnabled()) {
270         p_inst->own_address_type = BLE_ADDR_RANDOM;
271         GenerateRpa(Bind(
272             [](AdvertisingInstance* p_inst,
273                base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)>
274                    cb,
275                bt_bdaddr_t bda) {
276               memcpy(p_inst->own_address, &bda, BD_ADDR_LEN);
277 
278               alarm_set_on_queue(p_inst->adv_raddr_timer,
279                                  BTM_BLE_PRIVATE_ADDR_INT_MS,
280                                  btm_ble_adv_raddr_timer_timeout, p_inst,
281                                  btu_general_alarm_queue);
282               cb.Run(p_inst->inst_id, BTM_BLE_MULTI_ADV_SUCCESS);
283             },
284             p_inst, cb));
285       } else {
286         p_inst->own_address_type = BLE_ADDR_PUBLIC;
287         memcpy(p_inst->own_address,
288                controller_get_interface()->get_address()->address, BD_ADDR_LEN);
289 
290         cb.Run(p_inst->inst_id, BTM_BLE_MULTI_ADV_SUCCESS);
291       }
292       return;
293     }
294 
295     LOG(INFO) << "no free advertiser instance";
296     cb.Run(0xFF, ADVERTISE_FAILED_TOO_MANY_ADVERTISERS);
297   }
298 
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)299   void StartAdvertising(uint8_t advertiser_id, MultiAdvCb cb,
300                         tBTM_BLE_ADV_PARAMS* params,
301                         std::vector<uint8_t> advertise_data,
302                         std::vector<uint8_t> scan_response_data, int duration,
303                         MultiAdvCb timeout_cb) override {
304     /* a temporary type for holding all the data needed in callbacks below*/
305     struct CreatorParams {
306       uint8_t inst_id;
307       BleAdvertisingManagerImpl* self;
308       MultiAdvCb cb;
309       tBTM_BLE_ADV_PARAMS params;
310       std::vector<uint8_t> advertise_data;
311       std::vector<uint8_t> scan_response_data;
312       int duration;
313       MultiAdvCb timeout_cb;
314     };
315 
316     std::unique_ptr<CreatorParams> c;
317     c.reset(new CreatorParams());
318 
319     c->self = this;
320     c->cb = std::move(cb);
321     c->params = *params;
322     c->advertise_data = std::move(advertise_data);
323     c->scan_response_data = std::move(scan_response_data);
324     c->duration = duration;
325     c->timeout_cb = std::move(timeout_cb);
326     c->inst_id = advertiser_id;
327 
328     using c_type = std::unique_ptr<CreatorParams>;
329 
330     // this code is intentionally left formatted this way to highlight the
331     // asynchronous flow
332     // clang-format off
333     c->self->SetParameters(c->inst_id, &c->params, Bind(
334       [](c_type c, uint8_t status, int8_t tx_power) {
335         if (status != 0) {
336           LOG(ERROR) << "setting parameters failed, status: " << +status;
337           c->cb.Run(status);
338           return;
339         }
340 
341         c->self->adv_inst[c->inst_id].tx_power = tx_power;
342 
343         BD_ADDR *rpa = &c->self->adv_inst[c->inst_id].own_address;
344         c->self->GetHciInterface()->SetRandomAddress(c->inst_id, *rpa, Bind(
345           [](c_type c, uint8_t status) {
346             if (status != 0) {
347               LOG(ERROR) << "setting random address failed, status: " << +status;
348               c->cb.Run(status);
349               return;
350             }
351 
352             c->self->SetData(c->inst_id, false, std::move(c->advertise_data), Bind(
353               [](c_type c, uint8_t status) {
354                 if (status != 0) {
355                   LOG(ERROR) << "setting advertise data failed, status: " << +status;
356                   c->cb.Run(status);
357                   return;
358                 }
359 
360                 c->self->SetData(c->inst_id, true, std::move(c->scan_response_data), Bind(
361                   [](c_type c, uint8_t status) {
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 = this;
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 
399     // this code is intentionally left formatted this way to highlight the
400     // asynchronous flow
401     // clang-format off
402     c->self->RegisterAdvertiser(Bind(
403       [](c_type c, uint8_t advertiser_id, uint8_t status) {
404         if (status != 0) {
405           LOG(ERROR) << "registering advertiser failed, status: " << +status;
406           c->cb.Run(0, 0, status);
407           return;
408         }
409 
410         c->inst_id = advertiser_id;
411 
412         c->self->SetParameters(c->inst_id, &c->params, Bind(
413           [](c_type c, uint8_t status, int8_t tx_power) {
414             if (status != 0) {
415               c->self->Unregister(c->inst_id);
416               LOG(ERROR) << "setting parameters failed, status: " << +status;
417               c->cb.Run(0, 0, status);
418               return;
419             }
420 
421             c->self->adv_inst[c->inst_id].tx_power = tx_power;
422 
423             BD_ADDR *rpa = &c->self->adv_inst[c->inst_id].own_address;
424             c->self->GetHciInterface()->SetRandomAddress(c->inst_id, *rpa, Bind(
425               [](c_type c, uint8_t status) {
426                 if (status != 0) {
427                   c->self->Unregister(c->inst_id);
428                   LOG(ERROR) << "setting random address failed, status: " << +status;
429                   c->cb.Run(0, 0, status);
430                   return;
431                 }
432 
433                 c->self->SetData(c->inst_id, false, std::move(c->advertise_data), Bind(
434                   [](c_type c, uint8_t status) {
435                     if (status != 0) {
436                       c->self->Unregister(c->inst_id);
437                       LOG(ERROR) << "setting advertise data failed, status: " << +status;
438                       c->cb.Run(0, 0, status);
439                       return;
440                     }
441 
442                     c->self->SetData(c->inst_id, true, std::move(c->scan_response_data), Bind(
443                       [](c_type c, uint8_t status) {
444                         if (status != 0) {
445                           c->self->Unregister(c->inst_id);
446                           LOG(ERROR) << "setting scan response data failed, status: " << +status;
447                           c->cb.Run(0, 0, status);
448                           return;
449                         }
450 
451                         if (c->periodic_params.enable) {
452                           c->self->StartAdvertisingSetPeriodicPart(std::move(c));
453                         } else {
454                           c->self->StartAdvertisingSetFinish(std::move(c));
455                         }
456                     }, base::Passed(&c)));
457                 }, base::Passed(&c)));
458             }, base::Passed(&c)));
459         }, base::Passed(&c)));
460     }, base::Passed(&c)));
461     // clang-format on
462   }
463 
StartAdvertisingSetPeriodicPart(c_type c)464   void StartAdvertisingSetPeriodicPart(c_type c) {
465     // this code is intentionally left formatted this way to highlight the
466     // asynchronous flow
467     // clang-format off
468     c->self->SetPeriodicAdvertisingParameters(c->inst_id, &c->periodic_params, Bind(
469       [](c_type c, uint8_t status) {
470         if (status != 0) {
471           c->self->Unregister(c->inst_id);
472           LOG(ERROR) << "setting periodic parameters failed, status: " << +status;
473           c->cb.Run(0, 0, status);
474           return;
475         }
476 
477         c->self->SetPeriodicAdvertisingData(c->inst_id, std::move(c->periodic_data), Bind(
478           [](c_type c, uint8_t status) {
479             if (status != 0) {
480               c->self->Unregister(c->inst_id);
481               LOG(ERROR) << "setting periodic parameters failed, status: " << +status;
482               c->cb.Run(0, 0, status);
483               return;
484             }
485 
486             c->self->SetPeriodicAdvertisingEnable(c->inst_id, true, Bind(
487               [](c_type c, uint8_t status) {
488                 if (status != 0) {
489                   c->self->Unregister(c->inst_id);
490                   LOG(ERROR) << "enabling periodic advertising failed, status: " << +status;
491                   c->cb.Run(0, 0, status);
492                   return;
493                 }
494 
495                 c->self->StartAdvertisingSetFinish(std::move(c));
496 
497               }, base::Passed(&c)));
498         }, base::Passed(&c)));
499     }, base::Passed(&c)));
500     // clang-format on
501   }
502 
StartAdvertisingSetFinish(c_type c)503   void StartAdvertisingSetFinish(c_type c) {
504     uint8_t inst_id = c->inst_id;
505     uint16_t duration = c->duration;
506     uint8_t maxExtAdvEvents = c->maxExtAdvEvents;
507     RegisterCb timeout_cb = std::move(c->timeout_cb);
508     BleAdvertisingManagerImpl* self = c->self;
509     MultiAdvCb enable_cb = Bind(
510         [](c_type c, uint8_t status) {
511           if (status != 0) {
512             c->self->Unregister(c->inst_id);
513             LOG(ERROR) << "enabling advertiser failed, status: " << +status;
514             c->cb.Run(0, 0, status);
515             return;
516           }
517           int8_t tx_power = c->self->adv_inst[c->inst_id].tx_power;
518           c->cb.Run(c->inst_id, tx_power, status);
519         },
520         base::Passed(&c));
521 
522     self->Enable(inst_id, true, std::move(enable_cb), duration, maxExtAdvEvents,
523                  Bind(std::move(timeout_cb), inst_id));
524   }
525 
EnableWithTimerCb(uint8_t inst_id,MultiAdvCb enable_cb,int duration,MultiAdvCb timeout_cb,uint8_t status)526   void EnableWithTimerCb(uint8_t inst_id, MultiAdvCb enable_cb, int duration,
527                          MultiAdvCb timeout_cb, uint8_t status) {
528     VLOG(1) << __func__ << " inst_id: " << +inst_id;
529     AdvertisingInstance* p_inst = &adv_inst[inst_id];
530 
531     // Run the regular enable callback
532     enable_cb.Run(status);
533 
534     p_inst->timeout_timer = alarm_new("btm_ble.adv_timeout");
535 
536     base::Closure cb = Bind(&BleAdvertisingManagerImpl::Enable,
537                             base::Unretained(this), inst_id, 0 /* disable */,
538                             std::move(timeout_cb), 0, 0, base::Bind(DoNothing));
539 
540     // schedule disable when the timeout passes
541     alarm_set_closure_on_queue(FROM_HERE, p_inst->timeout_timer, duration * 10,
542                                std::move(cb), btu_general_alarm_queue);
543   }
544 
Enable(uint8_t inst_id,bool enable,MultiAdvCb cb,uint16_t duration,uint8_t maxExtAdvEvents,MultiAdvCb timeout_cb)545   void Enable(uint8_t inst_id, bool enable, MultiAdvCb cb, uint16_t duration,
546               uint8_t maxExtAdvEvents, MultiAdvCb timeout_cb) override {
547     VLOG(1) << __func__ << " inst_id: " << +inst_id;
548     if (inst_id >= inst_count) {
549       LOG(ERROR) << "bad instance id " << +inst_id;
550       return;
551     }
552 
553     AdvertisingInstance* p_inst = &adv_inst[inst_id];
554     VLOG(1) << __func__ << " enable: " << enable << ", duration: " << +duration;
555     if (!p_inst->in_use) {
556       LOG(ERROR) << "Invalid or no active instance";
557       cb.Run(BTM_BLE_MULTI_ADV_FAILURE);
558       return;
559     }
560 
561     if (enable && (duration || maxExtAdvEvents)) {
562       p_inst->timeout_cb = std::move(timeout_cb);
563     }
564 
565     p_inst->duration = duration;
566     p_inst->maxExtAdvEvents = maxExtAdvEvents;
567 
568     if (enable && p_inst->address_update_required) {
569       p_inst->address_update_required = false;
570       ConfigureRpa(p_inst, base::Bind(&BleAdvertisingManagerImpl::EnableFinish,
571                                       base::Unretained(this), p_inst, enable,
572                                       std::move(cb)));
573       return;
574     }
575 
576     EnableFinish(p_inst, enable, std::move(cb), 0);
577   }
578 
EnableFinish(AdvertisingInstance * p_inst,bool enable,MultiAdvCb cb,uint8_t status)579   void EnableFinish(AdvertisingInstance* p_inst, bool enable, MultiAdvCb cb,
580                     uint8_t status) {
581     if (enable && p_inst->duration) {
582       p_inst->enable_status = enable;
583       // TODO(jpawlowski): HCI implementation that can't do duration should
584       // emulate it, not EnableWithTimerCb.
585       GetHciInterface()->Enable(
586           enable, p_inst->inst_id, p_inst->duration, p_inst->maxExtAdvEvents,
587           Bind(&BleAdvertisingManagerImpl::EnableWithTimerCb,
588                base::Unretained(this), p_inst->inst_id, std::move(cb),
589                p_inst->duration, p_inst->timeout_cb));
590 
591     } else {
592       if (p_inst->timeout_timer) {
593         alarm_cancel(p_inst->timeout_timer);
594         alarm_free(p_inst->timeout_timer);
595         p_inst->timeout_timer = nullptr;
596       }
597 
598       p_inst->enable_status = enable;
599       GetHciInterface()->Enable(enable, p_inst->inst_id, p_inst->duration,
600                                 p_inst->maxExtAdvEvents, std::move(cb));
601     }
602   }
603 
SetParameters(uint8_t inst_id,tBTM_BLE_ADV_PARAMS * p_params,ParametersCb cb)604   void SetParameters(uint8_t inst_id, tBTM_BLE_ADV_PARAMS* p_params,
605                      ParametersCb cb) override {
606     VLOG(1) << __func__ << " inst_id: " << +inst_id;
607     if (inst_id >= inst_count) {
608       LOG(ERROR) << "bad instance id " << +inst_id;
609       return;
610     }
611 
612     AdvertisingInstance* p_inst = &adv_inst[inst_id];
613     if (!p_inst->in_use) {
614       LOG(ERROR) << "adv instance not in use" << +inst_id;
615       cb.Run(BTM_BLE_MULTI_ADV_FAILURE, 0);
616       return;
617     }
618 
619     // TODO: disable only if was enabled, currently no use scenario needs that,
620     // we always set parameters before enabling
621     // GetHciInterface()->Enable(false, inst_id, Bind(DoNothing));
622     p_inst->advertising_event_properties =
623         p_params->advertising_event_properties;
624     p_inst->tx_power = p_params->tx_power;
625     BD_ADDR peer_address = {0, 0, 0, 0, 0, 0};
626 
627     GetHciInterface()->SetParameters(
628         p_inst->inst_id, p_params->advertising_event_properties,
629         p_params->adv_int_min, p_params->adv_int_max, p_params->channel_map,
630         p_inst->own_address_type, p_inst->own_address, 0x00, peer_address,
631         p_params->adv_filter_policy, p_inst->tx_power,
632         p_params->primary_advertising_phy, 0x01,
633         p_params->secondary_advertising_phy, 0x01 /* TODO: proper SID */,
634         p_params->scan_request_notification_enable, cb);
635 
636     // TODO: re-enable only if it was enabled, properly call
637     // SetParamsCallback
638     // currently no use scenario needs that
639     // GetHciInterface()->Enable(true, inst_id, BTM_BleUpdateAdvInstParamCb);
640   }
641 
SetData(uint8_t inst_id,bool is_scan_rsp,std::vector<uint8_t> data,MultiAdvCb cb)642   void SetData(uint8_t inst_id, bool is_scan_rsp, std::vector<uint8_t> data,
643                MultiAdvCb cb) override {
644     VLOG(1) << __func__ << " inst_id: " << +inst_id;
645     if (inst_id >= inst_count) {
646       LOG(ERROR) << "bad instance id " << +inst_id;
647       return;
648     }
649 
650     AdvertisingInstance* p_inst = &adv_inst[inst_id];
651     VLOG(1) << "is_scan_rsp = " << is_scan_rsp;
652 
653     if (!is_scan_rsp && is_connectable(p_inst->advertising_event_properties)) {
654       uint8_t flags_val = BTM_GENERAL_DISCOVERABLE;
655 
656       if (p_inst->duration) flags_val = BTM_LIMITED_DISCOVERABLE;
657 
658       std::vector<uint8_t> flags;
659       flags.push_back(2);  // length
660       flags.push_back(HCI_EIR_FLAGS_TYPE);
661       flags.push_back(flags_val);
662 
663       data.insert(data.begin(), flags.begin(), flags.end());
664     }
665 
666     // Find and fill TX Power with the correct value
667     if (data.size()) {
668       size_t i = 0;
669       while (i < data.size()) {
670         uint8_t type = data[i + 1];
671         if (type == HCI_EIR_TX_POWER_LEVEL_TYPE) {
672           data[i + 2] = adv_inst[inst_id].tx_power;
673         }
674         i += data[i] + 1;
675       }
676     }
677 
678     VLOG(1) << "data is: " << base::HexEncode(data.data(), data.size());
679     DivideAndSendData(
680         inst_id, data, cb,
681         base::Bind(&BleAdvertisingManagerImpl::SetDataAdvDataSender,
682                    base::Unretained(this), is_scan_rsp));
683   }
684 
SetDataAdvDataSender(uint8_t is_scan_rsp,uint8_t inst_id,uint8_t operation,uint8_t length,uint8_t * data,MultiAdvCb cb)685   void SetDataAdvDataSender(uint8_t is_scan_rsp, uint8_t inst_id,
686                             uint8_t operation, uint8_t length, uint8_t* data,
687                             MultiAdvCb cb) {
688     if (is_scan_rsp)
689       GetHciInterface()->SetScanResponseData(inst_id, operation, 0x01, length,
690                                              data, cb);
691     else
692       GetHciInterface()->SetAdvertisingData(inst_id, operation, 0x01, length,
693                                             data, cb);
694   }
695 
696   using DataSender = base::Callback<void(
697       uint8_t /*inst_id*/, uint8_t /* operation */, uint8_t /* length */,
698       uint8_t* /* data */, MultiAdvCb /* done */)>;
699 
DivideAndSendData(int inst_id,std::vector<uint8_t> data,MultiAdvCb done_cb,DataSender sender)700   void DivideAndSendData(int inst_id, std::vector<uint8_t> data,
701                          MultiAdvCb done_cb, DataSender sender) {
702     DivideAndSendDataRecursively(true, inst_id, std::move(data), 0,
703                                  std::move(done_cb), std::move(sender), 0);
704   }
705 
DivideAndSendDataRecursively(bool isFirst,int inst_id,std::vector<uint8_t> data,int offset,MultiAdvCb done_cb,DataSender sender,uint8_t status)706   static void DivideAndSendDataRecursively(bool isFirst, int inst_id,
707                                            std::vector<uint8_t> data,
708                                            int offset, MultiAdvCb done_cb,
709                                            DataSender sender, uint8_t status) {
710     constexpr uint8_t INTERMEDIATE =
711         0x00;                        // Intermediate fragment of fragmented data
712     constexpr uint8_t FIRST = 0x01;  // First fragment of fragmented data
713     constexpr uint8_t LAST = 0x02;   // Last fragment of fragmented data
714     constexpr uint8_t COMPLETE = 0x03;  // Complete extended advertising data
715 
716     int dataSize = (int)data.size();
717     if (status != 0 || (!isFirst && offset == dataSize)) {
718       /* if we got error writing data, or reached the end of data */
719       done_cb.Run(status);
720       return;
721     }
722 
723     bool moreThanOnePacket = dataSize - offset > ADV_DATA_LEN_MAX;
724     uint8_t operation = isFirst ? moreThanOnePacket ? FIRST : COMPLETE
725                                 : moreThanOnePacket ? INTERMEDIATE : LAST;
726     int length = moreThanOnePacket ? ADV_DATA_LEN_MAX : dataSize - offset;
727     int newOffset = offset + length;
728 
729     sender.Run(
730         inst_id, operation, length, data.data() + offset,
731         Bind(&BleAdvertisingManagerImpl::DivideAndSendDataRecursively, false,
732              inst_id, std::move(data), newOffset, std::move(done_cb), sender));
733   }
734 
SetPeriodicAdvertisingParameters(uint8_t inst_id,tBLE_PERIODIC_ADV_PARAMS * params,MultiAdvCb cb)735   void SetPeriodicAdvertisingParameters(uint8_t inst_id,
736                                         tBLE_PERIODIC_ADV_PARAMS* params,
737                                         MultiAdvCb cb) override {
738     VLOG(1) << __func__ << " inst_id: " << +inst_id;
739 
740     GetHciInterface()->SetPeriodicAdvertisingParameters(
741         inst_id, params->min_interval, params->max_interval,
742         params->periodic_advertising_properties, cb);
743   }
744 
SetPeriodicAdvertisingData(uint8_t inst_id,std::vector<uint8_t> data,MultiAdvCb cb)745   void SetPeriodicAdvertisingData(uint8_t inst_id, std::vector<uint8_t> data,
746                                   MultiAdvCb cb) override {
747     VLOG(1) << __func__ << " inst_id: " << +inst_id;
748 
749     VLOG(1) << "data is: " << base::HexEncode(data.data(), data.size());
750 
751     DivideAndSendData(
752         inst_id, data, cb,
753         base::Bind(&BleAdvertiserHciInterface::SetPeriodicAdvertisingData,
754                    base::Unretained(GetHciInterface())));
755   }
756 
SetPeriodicAdvertisingEnable(uint8_t inst_id,uint8_t enable,MultiAdvCb cb)757   void SetPeriodicAdvertisingEnable(uint8_t inst_id, uint8_t enable,
758                                     MultiAdvCb cb) override {
759     VLOG(1) << __func__ << " inst_id: " << +inst_id << ", enable: " << +enable;
760 
761     GetHciInterface()->SetPeriodicAdvertisingEnable(enable, inst_id, cb);
762   }
763 
Unregister(uint8_t inst_id)764   void Unregister(uint8_t inst_id) override {
765     AdvertisingInstance* p_inst = &adv_inst[inst_id];
766 
767     VLOG(1) << __func__ << " inst_id: " << +inst_id;
768     if (inst_id >= inst_count) {
769       LOG(ERROR) << "bad instance id " << +inst_id;
770       return;
771     }
772 
773     if (adv_inst[inst_id].IsEnabled()) {
774       p_inst->enable_status = false;
775       GetHciInterface()->Enable(false, inst_id, 0x00, 0x00, Bind(DoNothing));
776     }
777 
778     alarm_cancel(p_inst->adv_raddr_timer);
779     p_inst->in_use = false;
780     GetHciInterface()->RemoveAdvertisingSet(inst_id, Bind(DoNothing));
781     p_inst->address_update_required = false;
782   }
783 
OnAdvertisingSetTerminated(uint8_t status,uint8_t advertising_handle,uint16_t connection_handle,uint8_t num_completed_extended_adv_events)784   void OnAdvertisingSetTerminated(
785       uint8_t status, uint8_t advertising_handle, uint16_t connection_handle,
786       uint8_t num_completed_extended_adv_events) override {
787     AdvertisingInstance* p_inst = &adv_inst[advertising_handle];
788     VLOG(1) << __func__ << "status: 0x" << std::hex << +status
789             << ", advertising_handle: 0x" << std::hex << +advertising_handle
790             << ", connection_handle: 0x" << std::hex << +connection_handle;
791 
792     if (status == 0x43 || status == 0x3C) {
793       // either duration elapsed, or maxExtAdvEvents reached
794       p_inst->enable_status = false;
795 
796       if (p_inst->timeout_cb.is_null()) {
797         LOG(INFO) << __func__ << "No timeout callback";
798         return;
799       }
800 
801       p_inst->timeout_cb.Run(status);
802       return;
803     }
804 
805     if (BTM_BleLocalPrivacyEnabled() &&
806         advertising_handle <= BTM_BLE_MULTI_ADV_MAX) {
807       btm_acl_update_conn_addr(connection_handle, p_inst->own_address);
808     }
809 
810     VLOG(1) << "reneabling advertising";
811 
812     if (p_inst->in_use == true) {
813       // TODO(jpawlowski): we don't really allow to do directed advertising
814       // right now. This should probably be removed, check with Andre.
815       if ((p_inst->advertising_event_properties & 0x0C) ==
816           0 /* directed advertising bits not set */) {
817         GetHciInterface()->Enable(true, advertising_handle, 0x00, 0x00,
818                                   Bind(DoNothing));
819       } else {
820         /* mark directed adv as disabled if adv has been stopped */
821         p_inst->in_use = false;
822       }
823     }
824   }
825 
826  private:
GetHciInterface()827   BleAdvertiserHciInterface* GetHciInterface() { return hci_interface; }
828 
829   BleAdvertiserHciInterface* hci_interface = nullptr;
830   std::vector<AdvertisingInstance> adv_inst;
831   uint8_t inst_count;
832 };
833 
834 BleAdvertisingManager* instance;
835 
btm_ble_adv_raddr_timer_timeout(void * data)836 void btm_ble_adv_raddr_timer_timeout(void* data) {
837   ((BleAdvertisingManagerImpl*)BleAdvertisingManager::Get())
838       ->ConfigureRpa((AdvertisingInstance*)data, base::Bind(DoNothing));
839 }
840 }  // namespace
841 
Initialize(BleAdvertiserHciInterface * interface)842 void BleAdvertisingManager::Initialize(BleAdvertiserHciInterface* interface) {
843   instance = new BleAdvertisingManagerImpl(interface);
844 }
845 
Get()846 BleAdvertisingManager* BleAdvertisingManager::Get() {
847   CHECK(instance);
848   return instance;
849 };
850 
CleanUp()851 void BleAdvertisingManager::CleanUp() {
852   delete instance;
853   instance = nullptr;
854 };
855 
856 /**
857  * This function initialize the advertising manager.
858  **/
btm_ble_adv_init()859 void btm_ble_adv_init() {
860   BleAdvertiserHciInterface::Initialize();
861   BleAdvertisingManager::Initialize(BleAdvertiserHciInterface::Get());
862   BleAdvertiserHciInterface::Get()->SetAdvertisingEventObserver(
863       (BleAdvertisingManagerImpl*)BleAdvertisingManager::Get());
864 
865   if (BleAdvertiserHciInterface::Get()->QuirkAdvertiserZeroHandle()) {
866     // If handle 0 can't be used, register advertiser for it, but never use it.
867     BleAdvertisingManager::Get()->RegisterAdvertiser(Bind(DoNothing2));
868   }
869 }
870 
871 /*******************************************************************************
872  *
873  * Function         btm_ble_multi_adv_cleanup
874  *
875  * Description      This function cleans up multi adv control block.
876  *
877  * Parameters
878  * Returns          void
879  *
880  ******************************************************************************/
btm_ble_multi_adv_cleanup(void)881 void btm_ble_multi_adv_cleanup(void) {
882   BleAdvertisingManager::CleanUp();
883   BleAdvertiserHciInterface::CleanUp();
884 }
885