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