1 /* 2 * Copyright 2022 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #pragma once 17 18 #include <chrono> 19 #include <memory> 20 #include <utility> 21 22 #include "common/callback.h" 23 #include "common/init_flags.h" 24 #include "hci/address_with_type.h" 25 #include "hci/hci_packets.h" 26 #include "hci/le_scanning_callback.h" 27 #include "hci/le_scanning_interface.h" 28 #include "hci/uuid.h" 29 #include "module.h" 30 #include "os/alarm.h" 31 #include "os/log.h" 32 33 namespace bluetooth { 34 namespace hci { 35 36 constexpr std::chrono::duration kPeriodicSyncTimeout = std::chrono::seconds(30); 37 constexpr int kMaxSyncTransactions = 16; 38 39 enum PeriodicSyncState : int { 40 PERIODIC_SYNC_STATE_IDLE = 0, 41 PERIODIC_SYNC_STATE_PENDING, 42 PERIODIC_SYNC_STATE_ESTABLISHED, 43 }; 44 45 struct PeriodicSyncTransferStates { 46 int pa_source; 47 int connection_handle; 48 Address addr; 49 }; 50 51 struct PeriodicSyncStates { 52 int request_id; 53 uint8_t advertiser_sid; 54 AddressWithType address_with_type; 55 uint16_t sync_handle; 56 PeriodicSyncState sync_state; 57 }; 58 59 struct PendingPeriodicSyncRequest { PendingPeriodicSyncRequestPendingPeriodicSyncRequest60 PendingPeriodicSyncRequest( 61 uint8_t advertiser_sid, 62 AddressWithType address_with_type, 63 uint16_t skip, 64 uint16_t sync_timeout, 65 os::Handler* handler) 66 : advertiser_sid(advertiser_sid), 67 address_with_type(std::move(address_with_type)), 68 skip(skip), 69 sync_timeout(sync_timeout), 70 sync_timeout_alarm(handler) {} 71 bool busy = false; 72 uint8_t advertiser_sid; 73 AddressWithType address_with_type; 74 uint16_t skip; 75 uint16_t sync_timeout; 76 os::Alarm sync_timeout_alarm; 77 }; 78 79 class PeriodicSyncManager { 80 public: PeriodicSyncManager(ScanningCallback * callbacks)81 explicit PeriodicSyncManager(ScanningCallback* callbacks) 82 : le_scanning_interface_(nullptr), handler_(nullptr), callbacks_(callbacks), sync_received_callback_id(0) {} 83 Init(hci::LeScanningInterface * le_scanning_interface,os::Handler * handler)84 void Init(hci::LeScanningInterface* le_scanning_interface, os::Handler* handler) { 85 le_scanning_interface_ = le_scanning_interface; 86 handler_ = handler; 87 } 88 SetScanningCallback(ScanningCallback * callbacks)89 void SetScanningCallback(ScanningCallback* callbacks) { 90 callbacks_ = callbacks; 91 } 92 StartSync(const PeriodicSyncStates & request,uint16_t skip,uint16_t sync_timeout)93 void StartSync(const PeriodicSyncStates& request, uint16_t skip, uint16_t sync_timeout) { 94 if (periodic_syncs_.size() >= kMaxSyncTransactions) { 95 int status = static_cast<int>(ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES); 96 callbacks_->OnPeriodicSyncStarted( 97 request.request_id, status, 0, request.advertiser_sid, request.address_with_type, 0, 0); 98 return; 99 } 100 auto address_type = request.address_with_type.GetAddressType(); 101 ASSERT_LOG( 102 (address_type == AddressType::PUBLIC_DEVICE_ADDRESS || address_type == AddressType::RANDOM_DEVICE_ADDRESS), 103 "Invalid address type %s", 104 AddressTypeText(address_type).c_str()); 105 periodic_syncs_.emplace_back(request); 106 LOG_DEBUG("address = %s, sid = %d", request.address_with_type.ToString().c_str(), request.advertiser_sid); 107 pending_sync_requests_.emplace_back( 108 request.advertiser_sid, request.address_with_type, skip, sync_timeout, handler_); 109 HandleNextRequest(); 110 } 111 StopSync(uint16_t handle)112 void StopSync(uint16_t handle) { 113 LOG_DEBUG("[PSync]: handle = %u", handle); 114 auto periodic_sync = GetEstablishedSyncFromHandle(handle); 115 if (periodic_sync == periodic_syncs_.end()) { 116 LOG_ERROR("[PSync]: invalid index for handle %u", handle); 117 le_scanning_interface_->EnqueueCommand( 118 hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(handle), 119 handler_->BindOnceOn( 120 this, &PeriodicSyncManager::check_status<LePeriodicAdvertisingTerminateSyncCompleteView>)); 121 return; 122 }; 123 periodic_syncs_.erase(periodic_sync); 124 le_scanning_interface_->EnqueueCommand( 125 hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(handle), 126 handler_->BindOnceOn(this, &PeriodicSyncManager::check_status<LePeriodicAdvertisingTerminateSyncCompleteView>)); 127 } 128 CancelCreateSync(uint8_t adv_sid,Address address)129 void CancelCreateSync(uint8_t adv_sid, Address address) { 130 LOG_DEBUG("[PSync]"); 131 auto periodic_sync = GetSyncFromAddressAndSid(address, adv_sid); 132 if (periodic_sync == periodic_syncs_.end()) { 133 LOG_ERROR("[PSync]:Invalid index for sid=%u", adv_sid); 134 return; 135 } 136 137 if (periodic_sync->sync_state == PERIODIC_SYNC_STATE_PENDING) { 138 LOG_WARN("[PSync]: Sync state is pending"); 139 le_scanning_interface_->EnqueueCommand( 140 hci::LePeriodicAdvertisingCreateSyncCancelBuilder::Create(), 141 handler_->BindOnceOn(this, &PeriodicSyncManager::HandlePeriodicAdvertisingCreateSyncCancelStatus)); 142 } else if (periodic_sync->sync_state == PERIODIC_SYNC_STATE_IDLE) { 143 LOG_DEBUG("[PSync]: Removing Sync request from queue"); 144 CleanUpRequest(adv_sid, address); 145 } 146 periodic_syncs_.erase(periodic_sync); 147 } 148 TransferSync(const Address & address,uint16_t service_data,uint16_t sync_handle,int pa_source,uint16_t connection_handle)149 void TransferSync( 150 const Address& address, uint16_t service_data, uint16_t sync_handle, int pa_source, uint16_t connection_handle) { 151 if (periodic_sync_transfers_.size() >= kMaxSyncTransactions) { 152 int status = static_cast<int>(ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES); 153 callbacks_->OnPeriodicSyncTransferred(pa_source, status, address); 154 return; 155 } 156 157 PeriodicSyncTransferStates request{pa_source, connection_handle, address}; 158 periodic_sync_transfers_.emplace_back(request); 159 le_scanning_interface_->EnqueueCommand( 160 hci::LePeriodicAdvertisingSyncTransferBuilder::Create(connection_handle, service_data, sync_handle), 161 handler_->BindOnceOn( 162 this, 163 &PeriodicSyncManager::HandlePeriodicAdvertisingSyncTransferComplete< 164 LePeriodicAdvertisingSyncTransferCompleteView>, 165 connection_handle)); 166 } 167 SyncSetInfo(const Address & address,uint16_t service_data,uint8_t adv_handle,int pa_source,uint16_t connection_handle)168 void SyncSetInfo( 169 const Address& address, uint16_t service_data, uint8_t adv_handle, int pa_source, uint16_t connection_handle) { 170 if (periodic_sync_transfers_.size() >= kMaxSyncTransactions) { 171 int status = static_cast<int>(ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES); 172 callbacks_->OnPeriodicSyncTransferred(pa_source, status, address); 173 return; 174 } 175 PeriodicSyncTransferStates request{pa_source, connection_handle, address}; 176 periodic_sync_transfers_.emplace_back(request); 177 le_scanning_interface_->EnqueueCommand( 178 hci::LePeriodicAdvertisingSetInfoTransferBuilder::Create(connection_handle, service_data, adv_handle), 179 handler_->BindOnceOn( 180 this, 181 &PeriodicSyncManager::HandlePeriodicAdvertisingSyncTransferComplete< 182 LePeriodicAdvertisingSetInfoTransferCompleteView>, 183 connection_handle)); 184 } 185 SyncTxParameters(const Address & address,uint8_t mode,uint16_t skip,uint16_t timeout,int reg_id)186 void SyncTxParameters(const Address& address, uint8_t mode, uint16_t skip, uint16_t timeout, int reg_id) { 187 LOG_DEBUG("[PAST]: mode=%u, skip=%u, timeout=%u", mode, skip, timeout); 188 auto sync_cte_type = static_cast<CteType>( 189 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOA_CONSTANT_TONE_EXTENSION) | 190 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_ONE_US_SLOTS) | 191 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_TWO_US_SLOTS)); 192 sync_received_callback_registered_ = true; 193 sync_received_callback_id = reg_id; 194 195 le_scanning_interface_->EnqueueCommand( 196 hci::LeSetDefaultPeriodicAdvertisingSyncTransferParametersBuilder::Create( 197 static_cast<SyncTransferMode>(mode), skip, timeout, sync_cte_type), 198 handler_->BindOnceOn( 199 this, 200 &PeriodicSyncManager::check_status<LeSetDefaultPeriodicAdvertisingSyncTransferParametersCompleteView>)); 201 } 202 HandlePeriodicAdvertisingCreateSyncStatus(CommandStatusView)203 void HandlePeriodicAdvertisingCreateSyncStatus(CommandStatusView) {} 204 HandlePeriodicAdvertisingCreateSyncCancelStatus(CommandCompleteView)205 void HandlePeriodicAdvertisingCreateSyncCancelStatus(CommandCompleteView) {} 206 207 template <class View> HandlePeriodicAdvertisingSyncTransferComplete(uint16_t connection_handle,CommandCompleteView view)208 void HandlePeriodicAdvertisingSyncTransferComplete(uint16_t connection_handle, CommandCompleteView view) { 209 ASSERT(view.IsValid()); 210 auto status_view = View::Create(view); 211 ASSERT(status_view.IsValid()); 212 if (status_view.GetStatus() != ErrorCode::SUCCESS) { 213 LOG_WARN( 214 "Got a Command complete %s, status %s, connection_handle %d", 215 OpCodeText(view.GetCommandOpCode()).c_str(), 216 ErrorCodeText(status_view.GetStatus()).c_str(), 217 connection_handle); 218 } else { 219 LOG_DEBUG( 220 "Got a Command complete %s, status %s, connection_handle %d", 221 OpCodeText(view.GetCommandOpCode()).c_str(), 222 ErrorCodeText(status_view.GetStatus()).c_str(), 223 connection_handle); 224 } 225 226 auto periodic_sync_transfer = GetSyncTransferRequestFromConnectionHandle(connection_handle); 227 if (periodic_sync_transfer == periodic_sync_transfers_.end()) { 228 LOG_ERROR("[PAST]:Invalid, conn_handle %u not found in DB", connection_handle); 229 return; 230 }; 231 232 callbacks_->OnPeriodicSyncTransferred( 233 periodic_sync_transfer->pa_source, (uint16_t)status_view.GetStatus(), periodic_sync_transfer->addr); 234 periodic_sync_transfers_.erase(periodic_sync_transfer); 235 } 236 237 template <class View> check_status(CommandCompleteView view)238 void check_status(CommandCompleteView view) { 239 ASSERT(view.IsValid()); 240 auto status_view = View::Create(view); 241 ASSERT(status_view.IsValid()); 242 if (status_view.GetStatus() != ErrorCode::SUCCESS) { 243 LOG_WARN( 244 "Got a Command complete %s, status %s", 245 OpCodeText(view.GetCommandOpCode()).c_str(), 246 ErrorCodeText(status_view.GetStatus()).c_str()); 247 } else { 248 LOG_DEBUG( 249 "Got a Command complete %s, status %s", 250 OpCodeText(view.GetCommandOpCode()).c_str(), 251 ErrorCodeText(status_view.GetStatus()).c_str()); 252 } 253 } 254 HandleLePeriodicAdvertisingSyncEstablished(LePeriodicAdvertisingSyncEstablishedView event_view)255 void HandleLePeriodicAdvertisingSyncEstablished(LePeriodicAdvertisingSyncEstablishedView event_view) { 256 ASSERT(event_view.IsValid()); 257 LOG_DEBUG( 258 "[PSync]: status=%d, sync_handle=%d, s_id=%d, " 259 "address_type=%d, adv_phy=%d,adv_interval=%d, clock_acc=%d", 260 (uint16_t)event_view.GetStatus(), 261 event_view.GetSyncHandle(), 262 event_view.GetAdvertisingSid(), 263 (uint16_t)event_view.GetAdvertiserAddressType(), 264 (uint16_t)event_view.GetAdvertiserPhy(), 265 event_view.GetPeriodicAdvertisingInterval(), 266 (uint16_t)event_view.GetAdvertiserClockAccuracy()); 267 268 auto pending_sync_request = 269 GetPendingSyncFromAddressAndSid(event_view.GetAdvertiserAddress(), event_view.GetAdvertisingSid()); 270 if (pending_sync_request != pending_sync_requests_.end()) { 271 pending_sync_request->sync_timeout_alarm.Cancel(); 272 } 273 274 auto address_with_type = AddressWithType(event_view.GetAdvertiserAddress(), event_view.GetAdvertiserAddressType()); 275 auto peer_address_type = address_with_type.GetAddressType(); 276 AddressType temp_address_type; 277 switch (peer_address_type) { 278 case AddressType::PUBLIC_DEVICE_ADDRESS: 279 case AddressType::PUBLIC_IDENTITY_ADDRESS: 280 temp_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; 281 break; 282 case AddressType::RANDOM_DEVICE_ADDRESS: 283 case AddressType::RANDOM_IDENTITY_ADDRESS: 284 temp_address_type = AddressType::RANDOM_DEVICE_ADDRESS; 285 break; 286 } 287 288 auto periodic_sync = GetSyncFromAddressWithTypeAndSid( 289 AddressWithType(event_view.GetAdvertiserAddress(), temp_address_type), event_view.GetAdvertisingSid()); 290 if (periodic_sync == periodic_syncs_.end()) { 291 LOG_WARN("[PSync]: Invalid address and sid for sync established"); 292 if (event_view.GetStatus() == ErrorCode::SUCCESS) { 293 LOG_WARN("Terminate sync"); 294 le_scanning_interface_->EnqueueCommand( 295 hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(event_view.GetSyncHandle()), 296 handler_->BindOnceOn( 297 this, &PeriodicSyncManager::check_status<LePeriodicAdvertisingTerminateSyncCompleteView>)); 298 } 299 AdvanceRequest(); 300 return; 301 } 302 periodic_sync->sync_handle = event_view.GetSyncHandle(); 303 periodic_sync->sync_state = PERIODIC_SYNC_STATE_ESTABLISHED; 304 callbacks_->OnPeriodicSyncStarted( 305 periodic_sync->request_id, 306 (uint8_t)event_view.GetStatus(), 307 event_view.GetSyncHandle(), 308 event_view.GetAdvertisingSid(), 309 address_with_type, 310 (uint16_t)event_view.GetAdvertiserPhy(), 311 event_view.GetPeriodicAdvertisingInterval()); 312 AdvanceRequest(); 313 } 314 HandleLePeriodicAdvertisingReport(LePeriodicAdvertisingReportView event_view)315 void HandleLePeriodicAdvertisingReport(LePeriodicAdvertisingReportView event_view) { 316 ASSERT(event_view.IsValid()); 317 LOG_DEBUG( 318 "[PSync]: sync_handle = %u, tx_power = %d, rssi = %d," 319 "cte_type = %u, data_status = %u, data_len = %u", 320 event_view.GetSyncHandle(), 321 event_view.GetTxPower(), 322 event_view.GetRssi(), 323 (uint16_t)event_view.GetCteType(), 324 (uint16_t)event_view.GetDataStatus(), 325 (uint16_t)event_view.GetData().size()); 326 327 uint16_t sync_handle = event_view.GetSyncHandle(); 328 auto periodic_sync = GetEstablishedSyncFromHandle(sync_handle); 329 if (periodic_sync == periodic_syncs_.end()) { 330 LOG_ERROR("[PSync]: index not found for handle %u", sync_handle); 331 return; 332 } 333 LOG_DEBUG("%s", "[PSync]: invoking callback"); 334 callbacks_->OnPeriodicSyncReport( 335 sync_handle, 336 event_view.GetTxPower(), 337 event_view.GetRssi(), 338 (uint16_t)event_view.GetDataStatus(), 339 event_view.GetData()); 340 } 341 HandleLePeriodicAdvertisingSyncLost(LePeriodicAdvertisingSyncLostView event_view)342 void HandleLePeriodicAdvertisingSyncLost(LePeriodicAdvertisingSyncLostView event_view) { 343 ASSERT(event_view.IsValid()); 344 uint16_t sync_handle = event_view.GetSyncHandle(); 345 LOG_DEBUG("[PSync]: sync_handle = %d", sync_handle); 346 callbacks_->OnPeriodicSyncLost(sync_handle); 347 auto periodic_sync = GetEstablishedSyncFromHandle(sync_handle); 348 periodic_syncs_.erase(periodic_sync); 349 } 350 HandleLePeriodicAdvertisingSyncTransferReceived(LePeriodicAdvertisingSyncTransferReceivedView event_view)351 void HandleLePeriodicAdvertisingSyncTransferReceived(LePeriodicAdvertisingSyncTransferReceivedView event_view) { 352 ASSERT(event_view.IsValid()); 353 uint8_t status = (uint8_t)event_view.GetStatus(); 354 uint8_t advertiser_phy = (uint8_t)event_view.GetAdvertiserPhy(); 355 LOG_DEBUG( 356 "[PAST]: status = %u, connection_handle = %u, service_data = %u," 357 " sync_handle = %u, adv_sid = %u, address_type = %u, address = %s," 358 " advertiser_phy = %u, periodic_advertising_interval = %u, clock_accuracy = %u", 359 status, 360 event_view.GetConnectionHandle(), 361 event_view.GetServiceData(), 362 event_view.GetSyncHandle(), 363 event_view.GetAdvertisingSid(), 364 (uint8_t)event_view.GetAdvertiserAddressType(), 365 event_view.GetAdvertiserAddress().ToString().c_str(), 366 advertiser_phy, 367 event_view.GetPeriodicAdvertisingInterval(), 368 (uint8_t)event_view.GetAdvertiserClockAccuracy()); 369 if (sync_received_callback_registered_) { 370 callbacks_->OnPeriodicSyncStarted( 371 sync_received_callback_id, 372 status, 373 event_view.GetSyncHandle(), 374 event_view.GetAdvertisingSid(), 375 AddressWithType(event_view.GetAdvertiserAddress(), event_view.GetAdvertiserAddressType()), 376 advertiser_phy, 377 event_view.GetPeriodicAdvertisingInterval()); 378 } 379 } 380 OnStartSyncTimeout()381 void OnStartSyncTimeout() { 382 auto& request = pending_sync_requests_.front(); 383 LOG_WARN( 384 "%s: sync timeout SID=%04X, bd_addr=%s", 385 __func__, 386 request.advertiser_sid, 387 request.address_with_type.ToString().c_str()); 388 uint8_t adv_sid = request.advertiser_sid; 389 AddressWithType address_with_type = request.address_with_type; 390 auto sync = GetSyncFromAddressWithTypeAndSid(address_with_type, adv_sid); 391 le_scanning_interface_->EnqueueCommand( 392 hci::LePeriodicAdvertisingCreateSyncCancelBuilder::Create(), 393 handler_->BindOnceOn(this, &PeriodicSyncManager::HandlePeriodicAdvertisingCreateSyncCancelStatus)); 394 int status = static_cast<int>(ErrorCode::ADVERTISING_TIMEOUT); 395 callbacks_->OnPeriodicSyncStarted( 396 sync->request_id, status, 0, sync->advertiser_sid, request.address_with_type, 0, 0); 397 RemoveSyncRequest(sync); 398 } 399 400 private: GetEstablishedSyncFromHandle(uint16_t handle)401 std::list<PeriodicSyncStates>::iterator GetEstablishedSyncFromHandle(uint16_t handle) { 402 for (auto it = periodic_syncs_.begin(); it != periodic_syncs_.end(); it++) { 403 if (it->sync_handle == handle && it->sync_state == PeriodicSyncState::PERIODIC_SYNC_STATE_ESTABLISHED) { 404 return it; 405 } 406 } 407 return periodic_syncs_.end(); 408 } 409 GetSyncFromAddressWithTypeAndSid(const AddressWithType & address_with_type,uint8_t adv_sid)410 std::list<PeriodicSyncStates>::iterator GetSyncFromAddressWithTypeAndSid( 411 const AddressWithType& address_with_type, uint8_t adv_sid) { 412 for (auto it = periodic_syncs_.begin(); it != periodic_syncs_.end(); it++) { 413 if (it->advertiser_sid == adv_sid && it->address_with_type == address_with_type) { 414 return it; 415 } 416 } 417 return periodic_syncs_.end(); 418 } 419 GetSyncFromAddressAndSid(const Address & address,uint8_t adv_sid)420 std::list<PeriodicSyncStates>::iterator GetSyncFromAddressAndSid(const Address& address, uint8_t adv_sid) { 421 for (auto it = periodic_syncs_.begin(); it != periodic_syncs_.end(); it++) { 422 if (it->advertiser_sid == adv_sid && it->address_with_type.GetAddress() == address) { 423 return it; 424 } 425 } 426 return periodic_syncs_.end(); 427 } 428 GetPendingSyncFromAddressAndSid(const Address & address,uint8_t adv_sid)429 std::list<PendingPeriodicSyncRequest>::iterator GetPendingSyncFromAddressAndSid( 430 const Address& address, uint8_t adv_sid) { 431 for (auto it = pending_sync_requests_.begin(); it != pending_sync_requests_.end(); it++) { 432 if (it->advertiser_sid == adv_sid && it->address_with_type.GetAddress() == address) { 433 return it; 434 } 435 } 436 return pending_sync_requests_.end(); 437 } 438 RemoveSyncRequest(std::list<PeriodicSyncStates>::iterator it)439 void RemoveSyncRequest(std::list<PeriodicSyncStates>::iterator it) { 440 periodic_syncs_.erase(it); 441 } 442 GetSyncTransferRequestFromConnectionHandle(uint16_t connection_handle)443 std::list<PeriodicSyncTransferStates>::iterator GetSyncTransferRequestFromConnectionHandle( 444 uint16_t connection_handle) { 445 for (auto it = periodic_sync_transfers_.begin(); it != periodic_sync_transfers_.end(); it++) { 446 if (it->connection_handle == connection_handle) { 447 return it; 448 } 449 } 450 return periodic_sync_transfers_.end(); 451 } 452 HandleStartSyncRequest(uint8_t sid,const AddressWithType & address_with_type,uint16_t skip,uint16_t timeout)453 void HandleStartSyncRequest(uint8_t sid, const AddressWithType& address_with_type, uint16_t skip, uint16_t timeout) { 454 auto options = static_cast<PeriodicAdvertisingOptions>(0); 455 auto sync_cte_type = static_cast<PeriodicSyncCteType>( 456 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOA_CONSTANT_TONE_EXTENSION) | 457 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_ONE_US_SLOTS) | 458 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_TWO_US_SLOTS)); 459 auto sync = GetSyncFromAddressWithTypeAndSid(address_with_type, sid); 460 sync->sync_state = PERIODIC_SYNC_STATE_PENDING; 461 AdvertisingAddressType advertisingAddressType = 462 static_cast<AdvertisingAddressType>(address_with_type.GetAddressType()); 463 le_scanning_interface_->EnqueueCommand( 464 hci::LePeriodicAdvertisingCreateSyncBuilder::Create( 465 options, sid, advertisingAddressType, address_with_type.GetAddress(), skip, timeout, sync_cte_type), 466 handler_->BindOnceOn(this, &PeriodicSyncManager::HandlePeriodicAdvertisingCreateSyncStatus)); 467 } 468 HandleNextRequest()469 void HandleNextRequest() { 470 if (pending_sync_requests_.empty()) { 471 LOG_DEBUG("pending_sync_requests_ empty"); 472 return; 473 } 474 auto& request = pending_sync_requests_.front(); 475 LOG_INFO( 476 "executing sync request SID=%04X, bd_addr=%s", 477 request.advertiser_sid, 478 request.address_with_type.ToString().c_str()); 479 if (request.busy) { 480 LOG_INFO("Request is already busy"); 481 return; 482 } 483 request.busy = true; 484 request.sync_timeout_alarm.Cancel(); 485 HandleStartSyncRequest(request.advertiser_sid, request.address_with_type, request.skip, request.sync_timeout); 486 request.sync_timeout_alarm.Schedule( 487 base::BindOnce(&PeriodicSyncManager::OnStartSyncTimeout, base::Unretained(this)), kPeriodicSyncTimeout); 488 } 489 AdvanceRequest()490 void AdvanceRequest() { 491 LOG_DEBUG("AdvanceRequest"); 492 if (pending_sync_requests_.empty()) { 493 LOG_DEBUG("pending_sync_requests_ empty"); 494 return; 495 } 496 auto it = pending_sync_requests_.begin(); 497 pending_sync_requests_.erase(it); 498 HandleNextRequest(); 499 } 500 CleanUpRequest(uint8_t advertiser_sid,Address address)501 void CleanUpRequest(uint8_t advertiser_sid, Address address) { 502 auto it = pending_sync_requests_.begin(); 503 while (it != pending_sync_requests_.end()) { 504 if (it->advertiser_sid == advertiser_sid && it->address_with_type.GetAddress() == address) { 505 LOG_INFO( 506 "removing connection request SID=%04X, bd_addr=%s, busy=%d", 507 it->advertiser_sid, 508 it->address_with_type.GetAddress().ToString().c_str(), 509 it->busy); 510 it = pending_sync_requests_.erase(it); 511 } else { 512 ++it; 513 } 514 } 515 } 516 517 hci::LeScanningInterface* le_scanning_interface_; 518 os::Handler* handler_; 519 ScanningCallback* callbacks_; 520 std::list<PendingPeriodicSyncRequest> pending_sync_requests_; 521 std::list<PeriodicSyncStates> periodic_syncs_; 522 std::list<PeriodicSyncTransferStates> periodic_sync_transfers_; 523 bool sync_received_callback_registered_ = false; 524 int sync_received_callback_id{}; 525 }; 526 527 } // namespace hci 528 } // namespace bluetooth