Home | History | Annotate | Download | only in btm
      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 
     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 
     83   bool IsEnabled() { return enable_status; }
     84 
     85   bool IsConnectable() { return is_connectable(advertising_event_properties); }
     86 
     87   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 
    102   ~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 
    110 void DoNothing(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 
    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
    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:
    159   BleAdvertisingManagerImpl(BleAdvertiserHciInterface* interface) {
    160     this->hci_interface = interface;
    161     hci_interface->ReadInstanceCount(
    162         base::Bind(&BleAdvertisingManagerImpl::ReadInstanceCountCb,
    163                    base::Unretained(this)));
    164   }
    165 
    166   ~BleAdvertisingManagerImpl() { adv_inst.clear(); }
    167 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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:
    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 
    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 
    934 void BleAdvertisingManager::Initialize(BleAdvertiserHciInterface* interface) {
    935   instance = new BleAdvertisingManagerImpl(interface);
    936 }
    937 
    938 bool BleAdvertisingManager::IsInitialized() { return instance; }
    939 
    940 BleAdvertisingManager* BleAdvertisingManager::Get() {
    941   CHECK(instance);
    942   return instance;
    943 };
    944 
    945 void BleAdvertisingManager::CleanUp() {
    946   delete instance;
    947   instance = nullptr;
    948 };
    949 
    950 /**
    951  * This function initialize the advertising manager.
    952  **/
    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  ******************************************************************************/
    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;
    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
    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.
   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
   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