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