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 <bluetooth/log.h> 19 #include <com_android_bluetooth_flags.h> 20 21 #include <chrono> 22 #include <memory> 23 #include <utility> 24 25 #include "common/callback.h" 26 #include "common/init_flags.h" 27 #include "hci/address_with_type.h" 28 #include "hci/event_checkers.h" 29 #include "hci/hci_packets.h" 30 #include "hci/le_scanning_callback.h" 31 #include "hci/le_scanning_interface.h" 32 #include "hci/le_scanning_reassembler.h" 33 #include "hci/uuid.h" 34 #include "module.h" 35 #include "os/alarm.h" 36 #include "os/log.h" 37 38 namespace bluetooth { 39 namespace hci { 40 41 constexpr std::chrono::duration kPeriodicSyncTimeout = std::chrono::seconds(5); 42 constexpr int kMaxSyncTransactions = 16; 43 44 enum PeriodicSyncState : int { 45 PERIODIC_SYNC_STATE_IDLE = 0, 46 PERIODIC_SYNC_STATE_PENDING, 47 PERIODIC_SYNC_STATE_ESTABLISHED, 48 }; 49 50 struct PeriodicSyncTransferStates { 51 int pa_source; 52 int connection_handle; 53 Address addr; 54 }; 55 56 struct PeriodicSyncStates { 57 int request_id; 58 uint8_t advertiser_sid; 59 AddressWithType address_with_type; 60 uint16_t sync_handle; 61 PeriodicSyncState sync_state; 62 }; 63 64 struct PendingPeriodicSyncRequest { PendingPeriodicSyncRequestPendingPeriodicSyncRequest65 PendingPeriodicSyncRequest( 66 uint8_t advertiser_sid, 67 AddressWithType address_with_type, 68 uint16_t skip, 69 uint16_t sync_timeout, 70 os::Handler* handler) 71 : advertiser_sid(advertiser_sid), 72 address_with_type(std::move(address_with_type)), 73 skip(skip), 74 sync_timeout(sync_timeout), 75 sync_timeout_alarm(handler) {} 76 bool busy = false; 77 uint8_t advertiser_sid; 78 AddressWithType address_with_type; 79 uint16_t skip; 80 uint16_t sync_timeout; 81 os::Alarm sync_timeout_alarm; 82 }; 83 84 class PeriodicSyncManager { 85 public: PeriodicSyncManager(ScanningCallback * callbacks)86 explicit PeriodicSyncManager(ScanningCallback* callbacks) 87 : le_scanning_interface_(nullptr), handler_(nullptr), callbacks_(callbacks), sync_received_callback_id(0) {} 88 Init(hci::LeScanningInterface * le_scanning_interface,os::Handler * handler)89 void Init(hci::LeScanningInterface* le_scanning_interface, os::Handler* handler) { 90 le_scanning_interface_ = le_scanning_interface; 91 handler_ = handler; 92 } 93 SetScanningCallback(ScanningCallback * callbacks)94 void SetScanningCallback(ScanningCallback* callbacks) { 95 callbacks_ = callbacks; 96 } 97 StartSync(const PeriodicSyncStates & request,uint16_t skip,uint16_t sync_timeout)98 void StartSync(const PeriodicSyncStates& request, uint16_t skip, uint16_t sync_timeout) { 99 if (periodic_syncs_.size() >= kMaxSyncTransactions) { 100 int status = static_cast<int>(ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES); 101 callbacks_->OnPeriodicSyncStarted( 102 request.request_id, status, 0, request.advertiser_sid, request.address_with_type, 0, 0); 103 return; 104 } 105 auto address_type = request.address_with_type.GetAddressType(); 106 log::assert_that( 107 (address_type == AddressType::PUBLIC_DEVICE_ADDRESS || 108 address_type == AddressType::RANDOM_DEVICE_ADDRESS), 109 "Invalid address type {}", 110 AddressTypeText(address_type)); 111 periodic_syncs_.emplace_back(request); 112 log::debug("address = {}, sid = {}", request.address_with_type, request.advertiser_sid); 113 pending_sync_requests_.emplace_back( 114 request.advertiser_sid, request.address_with_type, skip, sync_timeout, handler_); 115 HandleNextRequest(); 116 } 117 StopSync(uint16_t handle)118 void StopSync(uint16_t handle) { 119 log::debug("[PSync]: handle = {}", handle); 120 auto periodic_sync = GetEstablishedSyncFromHandle(handle); 121 if (periodic_sync == periodic_syncs_.end()) { 122 log::error("[PSync]: invalid index for handle {}", handle); 123 le_scanning_interface_->EnqueueCommand( 124 hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(handle), 125 handler_->BindOnce(check_complete<LePeriodicAdvertisingTerminateSyncCompleteView>)); 126 return; 127 }; 128 periodic_syncs_.erase(periodic_sync); 129 le_scanning_interface_->EnqueueCommand( 130 hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(handle), 131 handler_->BindOnce(check_complete<LePeriodicAdvertisingTerminateSyncCompleteView>)); 132 } 133 CancelCreateSync(uint8_t adv_sid,Address address)134 void CancelCreateSync(uint8_t adv_sid, Address address) { 135 log::debug("[PSync]"); 136 auto periodic_sync = GetSyncFromAddressAndSid(address, adv_sid); 137 if (periodic_sync == periodic_syncs_.end()) { 138 log::error("[PSync]:Invalid index for sid={}", adv_sid); 139 return; 140 } 141 142 if (periodic_sync->sync_state == PERIODIC_SYNC_STATE_PENDING) { 143 log::warn("[PSync]: Sync state is pending"); 144 le_scanning_interface_->EnqueueCommand( 145 hci::LePeriodicAdvertisingCreateSyncCancelBuilder::Create(), 146 handler_->BindOnceOn( 147 this, 148 &PeriodicSyncManager::HandlePeriodicAdvertisingCreateSyncCancelStatus< 149 LePeriodicAdvertisingCreateSyncCancelCompleteView>)); 150 } else if (periodic_sync->sync_state == PERIODIC_SYNC_STATE_IDLE) { 151 log::debug("[PSync]: Removing Sync request from queue"); 152 CleanUpRequest(adv_sid, address); 153 } 154 periodic_syncs_.erase(periodic_sync); 155 } 156 TransferSync(const Address & address,uint16_t service_data,uint16_t sync_handle,int pa_source,uint16_t connection_handle)157 void TransferSync( 158 const Address& address, uint16_t service_data, uint16_t sync_handle, int pa_source, uint16_t connection_handle) { 159 if (periodic_sync_transfers_.size() >= kMaxSyncTransactions) { 160 int status = static_cast<int>(ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES); 161 callbacks_->OnPeriodicSyncTransferred(pa_source, status, address); 162 return; 163 } 164 165 PeriodicSyncTransferStates request{pa_source, connection_handle, address}; 166 periodic_sync_transfers_.emplace_back(request); 167 le_scanning_interface_->EnqueueCommand( 168 hci::LePeriodicAdvertisingSyncTransferBuilder::Create(connection_handle, service_data, sync_handle), 169 handler_->BindOnceOn( 170 this, 171 &PeriodicSyncManager::HandlePeriodicAdvertisingSyncTransferComplete< 172 LePeriodicAdvertisingSyncTransferCompleteView>, 173 connection_handle)); 174 } 175 SyncSetInfo(const Address & address,uint16_t service_data,uint8_t adv_handle,int pa_source,uint16_t connection_handle)176 void SyncSetInfo( 177 const Address& address, uint16_t service_data, uint8_t adv_handle, int pa_source, uint16_t connection_handle) { 178 if (periodic_sync_transfers_.size() >= kMaxSyncTransactions) { 179 int status = static_cast<int>(ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES); 180 callbacks_->OnPeriodicSyncTransferred(pa_source, status, address); 181 return; 182 } 183 PeriodicSyncTransferStates request{pa_source, connection_handle, address}; 184 periodic_sync_transfers_.emplace_back(request); 185 le_scanning_interface_->EnqueueCommand( 186 hci::LePeriodicAdvertisingSetInfoTransferBuilder::Create(connection_handle, service_data, adv_handle), 187 handler_->BindOnceOn( 188 this, 189 &PeriodicSyncManager::HandlePeriodicAdvertisingSyncTransferComplete< 190 LePeriodicAdvertisingSetInfoTransferCompleteView>, 191 connection_handle)); 192 } 193 SyncTxParameters(const Address &,uint8_t mode,uint16_t skip,uint16_t timeout,int reg_id)194 void SyncTxParameters( 195 const Address& /* address */, uint8_t mode, uint16_t skip, uint16_t timeout, int reg_id) { 196 log::debug("[PAST]: mode={}, skip={}, timeout={}", mode, skip, timeout); 197 auto sync_cte_type = static_cast<CteType>( 198 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOA_CONSTANT_TONE_EXTENSION) | 199 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_ONE_US_SLOTS) | 200 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_TWO_US_SLOTS)); 201 sync_received_callback_registered_ = true; 202 sync_received_callback_id = reg_id; 203 204 le_scanning_interface_->EnqueueCommand( 205 hci::LeSetDefaultPeriodicAdvertisingSyncTransferParametersBuilder::Create( 206 static_cast<SyncTransferMode>(mode), skip, timeout, sync_cte_type), 207 handler_->BindOnce( 208 check_complete<LeSetDefaultPeriodicAdvertisingSyncTransferParametersCompleteView>)); 209 } 210 211 template <class View> HandlePeriodicAdvertisingCreateSyncStatus(CommandStatusView view)212 void HandlePeriodicAdvertisingCreateSyncStatus(CommandStatusView view) { 213 if (!com::android::bluetooth::flags::leaudio_broadcast_assistant_handle_command_statuses()) { 214 return; 215 } 216 log::assert_that(view.IsValid(), "assert failed: view.IsValid()"); 217 auto status_view = View::Create(view); 218 log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()"); 219 auto status = status_view.GetStatus(); 220 if (status != ErrorCode::SUCCESS) { 221 auto& request = pending_sync_requests_.front(); 222 request.sync_timeout_alarm.Cancel(); 223 log::warn( 224 "Got a Command status {}, status {}, SID={:04X}, bd_addr={}", 225 OpCodeText(view.GetCommandOpCode()), 226 ErrorCodeText(status), 227 request.advertiser_sid, 228 request.address_with_type); 229 230 uint8_t adv_sid = request.advertiser_sid; 231 AddressWithType address_with_type = request.address_with_type; 232 auto sync = GetSyncFromAddressWithTypeAndSid(address_with_type, adv_sid); 233 callbacks_->OnPeriodicSyncStarted( 234 sync->request_id, 235 (uint8_t)status, 236 0, 237 sync->advertiser_sid, 238 request.address_with_type, 239 0, 240 0); 241 periodic_syncs_.erase(sync); 242 AdvanceRequest(); 243 } 244 } 245 246 template <class View> HandlePeriodicAdvertisingCreateSyncCancelStatus(CommandCompleteView view)247 void HandlePeriodicAdvertisingCreateSyncCancelStatus(CommandCompleteView view) { 248 if (!com::android::bluetooth::flags::leaudio_broadcast_assistant_handle_command_statuses()) { 249 return; 250 } 251 log::assert_that(view.IsValid(), "assert failed: view.IsValid()"); 252 auto status_view = View::Create(view); 253 log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()"); 254 auto status = status_view.GetStatus(); 255 if (status != ErrorCode::SUCCESS) { 256 auto& request = pending_sync_requests_.front(); 257 request.sync_timeout_alarm.Cancel(); 258 log::warn( 259 "Got a Command complete {}, status {}, SID={:04X}, bd_addr={}", 260 OpCodeText(view.GetCommandOpCode()), 261 ErrorCodeText(status), 262 request.advertiser_sid, 263 request.address_with_type); 264 AdvanceRequest(); 265 } 266 } 267 268 template <class View> HandlePeriodicAdvertisingSyncTransferComplete(uint16_t connection_handle,CommandCompleteView view)269 void HandlePeriodicAdvertisingSyncTransferComplete(uint16_t connection_handle, CommandCompleteView view) { 270 log::assert_that(view.IsValid(), "assert failed: view.IsValid()"); 271 auto status_view = View::Create(view); 272 log::assert_that(status_view.IsValid(), "assert failed: status_view.IsValid()"); 273 if (status_view.GetStatus() != ErrorCode::SUCCESS) { 274 log::warn( 275 "Got a Command complete {}, status {}, connection_handle {}", 276 OpCodeText(view.GetCommandOpCode()), 277 ErrorCodeText(status_view.GetStatus()), 278 connection_handle); 279 } else { 280 log::debug( 281 "Got a Command complete {}, status {}, connection_handle {}", 282 OpCodeText(view.GetCommandOpCode()), 283 ErrorCodeText(status_view.GetStatus()), 284 connection_handle); 285 } 286 287 auto periodic_sync_transfer = GetSyncTransferRequestFromConnectionHandle(connection_handle); 288 if (periodic_sync_transfer == periodic_sync_transfers_.end()) { 289 log::error("[PAST]:Invalid, conn_handle {} not found in DB", connection_handle); 290 return; 291 }; 292 293 callbacks_->OnPeriodicSyncTransferred( 294 periodic_sync_transfer->pa_source, (uint16_t)status_view.GetStatus(), periodic_sync_transfer->addr); 295 periodic_sync_transfers_.erase(periodic_sync_transfer); 296 } 297 HandleLePeriodicAdvertisingSyncEstablished(LePeriodicAdvertisingSyncEstablishedView event_view)298 void HandleLePeriodicAdvertisingSyncEstablished(LePeriodicAdvertisingSyncEstablishedView event_view) { 299 log::assert_that(event_view.IsValid(), "assert failed: event_view.IsValid()"); 300 log::debug( 301 "[PSync]: status={}, sync_handle={}, address={}, s_id={}, address_type={}, adv_phy={}, " 302 "adv_interval={}, clock_acc={}", 303 (uint16_t)event_view.GetStatus(), 304 event_view.GetSyncHandle(), 305 AddressWithType(event_view.GetAdvertiserAddress(), event_view.GetAdvertiserAddressType()), 306 event_view.GetAdvertisingSid(), 307 (uint16_t)event_view.GetAdvertiserAddressType(), 308 (uint16_t)event_view.GetAdvertiserPhy(), 309 event_view.GetPeriodicAdvertisingInterval(), 310 (uint16_t)event_view.GetAdvertiserClockAccuracy()); 311 312 auto pending_sync_request = 313 GetPendingSyncFromAddressAndSid(event_view.GetAdvertiserAddress(), event_view.GetAdvertisingSid()); 314 if (pending_sync_request != pending_sync_requests_.end()) { 315 pending_sync_request->sync_timeout_alarm.Cancel(); 316 } 317 318 auto address_with_type = AddressWithType(event_view.GetAdvertiserAddress(), event_view.GetAdvertiserAddressType()); 319 auto peer_address_type = address_with_type.GetAddressType(); 320 AddressType temp_address_type; 321 switch (peer_address_type) { 322 case AddressType::PUBLIC_DEVICE_ADDRESS: 323 case AddressType::PUBLIC_IDENTITY_ADDRESS: 324 temp_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; 325 break; 326 case AddressType::RANDOM_DEVICE_ADDRESS: 327 case AddressType::RANDOM_IDENTITY_ADDRESS: 328 temp_address_type = AddressType::RANDOM_DEVICE_ADDRESS; 329 break; 330 } 331 332 auto periodic_sync = GetSyncFromAddressWithTypeAndSid( 333 AddressWithType(event_view.GetAdvertiserAddress(), temp_address_type), event_view.GetAdvertisingSid()); 334 if (periodic_sync == periodic_syncs_.end()) { 335 log::warn("[PSync]: Invalid address and sid for sync established"); 336 if (event_view.GetStatus() == ErrorCode::SUCCESS) { 337 log::warn("Terminate sync"); 338 le_scanning_interface_->EnqueueCommand( 339 hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(event_view.GetSyncHandle()), 340 handler_->BindOnce(check_complete<LePeriodicAdvertisingTerminateSyncCompleteView>)); 341 } 342 AdvanceRequest(); 343 return; 344 } 345 periodic_sync->sync_handle = event_view.GetSyncHandle(); 346 periodic_sync->sync_state = PERIODIC_SYNC_STATE_ESTABLISHED; 347 callbacks_->OnPeriodicSyncStarted( 348 periodic_sync->request_id, 349 (uint8_t)event_view.GetStatus(), 350 event_view.GetSyncHandle(), 351 event_view.GetAdvertisingSid(), 352 address_with_type, 353 (uint16_t)event_view.GetAdvertiserPhy(), 354 event_view.GetPeriodicAdvertisingInterval()); 355 356 if (com::android::bluetooth::flags::leaudio_broadcast_feature_support()) { 357 if (event_view.GetStatus() != ErrorCode::SUCCESS) { 358 periodic_syncs_.erase(periodic_sync); 359 } 360 } 361 362 AdvanceRequest(); 363 } 364 HandleLePeriodicAdvertisingReport(LePeriodicAdvertisingReportView event_view)365 void HandleLePeriodicAdvertisingReport(LePeriodicAdvertisingReportView event_view) { 366 log::assert_that(event_view.IsValid(), "assert failed: event_view.IsValid()"); 367 log::debug( 368 "[PSync]: sync_handle = {}, tx_power = {}, rssi = {},cte_type = {}, data_status = {}, " 369 "data_len = {}", 370 event_view.GetSyncHandle(), 371 event_view.GetTxPower(), 372 event_view.GetRssi(), 373 (uint16_t)event_view.GetCteType(), 374 (uint16_t)event_view.GetDataStatus(), 375 (uint16_t)event_view.GetData().size()); 376 377 uint16_t sync_handle = event_view.GetSyncHandle(); 378 auto periodic_sync = GetEstablishedSyncFromHandle(sync_handle); 379 if (periodic_sync == periodic_syncs_.end()) { 380 log::error("[PSync]: index not found for handle {}", sync_handle); 381 return; 382 } 383 384 auto complete_advertising_data = 385 com::android::bluetooth::flags::le_periodic_scanning_reassembler() 386 ? scanning_reassembler_.ProcessPeriodicAdvertisingReport( 387 sync_handle, DataStatus(event_view.GetDataStatus()), event_view.GetData()) 388 : event_view.GetData(); 389 if (!complete_advertising_data.has_value()) { 390 return; 391 } 392 393 log::debug("{}", "[PSync]: invoking callback"); 394 callbacks_->OnPeriodicSyncReport( 395 sync_handle, 396 event_view.GetTxPower(), 397 event_view.GetRssi(), 398 (uint16_t)event_view.GetDataStatus(), 399 complete_advertising_data.value()); 400 } 401 HandleLePeriodicAdvertisingSyncLost(LePeriodicAdvertisingSyncLostView event_view)402 void HandleLePeriodicAdvertisingSyncLost(LePeriodicAdvertisingSyncLostView event_view) { 403 log::assert_that(event_view.IsValid(), "assert failed: event_view.IsValid()"); 404 uint16_t sync_handle = event_view.GetSyncHandle(); 405 log::debug("[PSync]: sync_handle = {}", sync_handle); 406 callbacks_->OnPeriodicSyncLost(sync_handle); 407 auto periodic_sync = GetEstablishedSyncFromHandle(sync_handle); 408 if (periodic_sync == periodic_syncs_.end()) { 409 log::error("[PSync]: index not found for handle {}", sync_handle); 410 return; 411 } 412 periodic_syncs_.erase(periodic_sync); 413 } 414 HandleLePeriodicAdvertisingSyncTransferReceived(LePeriodicAdvertisingSyncTransferReceivedView event_view)415 void HandleLePeriodicAdvertisingSyncTransferReceived(LePeriodicAdvertisingSyncTransferReceivedView event_view) { 416 log::assert_that(event_view.IsValid(), "assert failed: event_view.IsValid()"); 417 uint8_t status = (uint8_t)event_view.GetStatus(); 418 uint8_t advertiser_phy = (uint8_t)event_view.GetAdvertiserPhy(); 419 log::debug( 420 "[PAST]: status = {}, connection_handle = {}, service_data = {}, sync_handle = {}, adv_sid " 421 "= {}, address_type = {}, address = {}, advertiser_phy = {}, periodic_advertising_interval " 422 "= {}, clock_accuracy = {}", 423 status, 424 event_view.GetConnectionHandle(), 425 event_view.GetServiceData(), 426 event_view.GetSyncHandle(), 427 event_view.GetAdvertisingSid(), 428 (uint8_t)event_view.GetAdvertiserAddressType(), 429 event_view.GetAdvertiserAddress(), 430 advertiser_phy, 431 event_view.GetPeriodicAdvertisingInterval(), 432 (uint8_t)event_view.GetAdvertiserClockAccuracy()); 433 if (sync_received_callback_registered_) { 434 callbacks_->OnPeriodicSyncStarted( 435 sync_received_callback_id, 436 status, 437 event_view.GetSyncHandle(), 438 event_view.GetAdvertisingSid(), 439 AddressWithType(event_view.GetAdvertiserAddress(), event_view.GetAdvertiserAddressType()), 440 advertiser_phy, 441 event_view.GetPeriodicAdvertisingInterval()); 442 } 443 } 444 OnStartSyncTimeout()445 void OnStartSyncTimeout() { 446 auto& request = pending_sync_requests_.front(); 447 log::warn( 448 "sync timeout SID={:04X}, bd_addr={}", request.advertiser_sid, request.address_with_type); 449 uint8_t adv_sid = request.advertiser_sid; 450 AddressWithType address_with_type = request.address_with_type; 451 auto sync = GetSyncFromAddressWithTypeAndSid(address_with_type, adv_sid); 452 le_scanning_interface_->EnqueueCommand( 453 hci::LePeriodicAdvertisingCreateSyncCancelBuilder::Create(), 454 handler_->BindOnceOn( 455 this, 456 &PeriodicSyncManager::HandlePeriodicAdvertisingCreateSyncCancelStatus< 457 LePeriodicAdvertisingCreateSyncCancelCompleteView>)); 458 int status = static_cast<int>(ErrorCode::ADVERTISING_TIMEOUT); 459 callbacks_->OnPeriodicSyncStarted( 460 sync->request_id, status, 0, sync->advertiser_sid, request.address_with_type, 0, 0); 461 periodic_syncs_.erase(sync); 462 } 463 HandleLeBigInfoAdvertisingReport(LeBigInfoAdvertisingReportView event_view)464 void HandleLeBigInfoAdvertisingReport(LeBigInfoAdvertisingReportView event_view) { 465 log::assert_that(event_view.IsValid(), "assert failed: event_view.IsValid()"); 466 log::debug( 467 "[PAST]:sync_handle {}, num_bises = {}, nse = {},iso_interval = {}, bn = {}, pto = {}, irc " 468 "= {}, max_pdu = {} sdu_interval = {}, max_sdu = {}, phy = {}, framing = {}, encryption = " 469 "{}", 470 event_view.GetSyncHandle(), 471 event_view.GetNumBis(), 472 event_view.GetNse(), 473 event_view.GetIsoInterval(), 474 event_view.GetBn(), 475 event_view.GetPto(), 476 event_view.GetIrc(), 477 event_view.GetMaxPdu(), 478 event_view.GetSduInterval(), 479 event_view.GetMaxSdu(), 480 static_cast<uint32_t>(event_view.GetPhy()), 481 static_cast<uint32_t>(event_view.GetFraming()), 482 static_cast<uint32_t>(event_view.GetEncryption())); 483 484 uint16_t sync_handle = event_view.GetSyncHandle(); 485 auto periodic_sync = GetEstablishedSyncFromHandle(sync_handle); 486 if (periodic_sync == periodic_syncs_.end()) { 487 log::error("[PSync]: index not found for handle {}", sync_handle); 488 return; 489 } 490 log::debug("{}", "[PSync]: invoking callback"); 491 callbacks_->OnBigInfoReport(sync_handle, event_view.GetEncryption() == Enable::ENABLED ? true : false); 492 } 493 494 private: GetEstablishedSyncFromHandle(uint16_t handle)495 std::list<PeriodicSyncStates>::iterator GetEstablishedSyncFromHandle(uint16_t handle) { 496 for (auto it = periodic_syncs_.begin(); it != periodic_syncs_.end(); it++) { 497 if (it->sync_handle == handle && it->sync_state == PeriodicSyncState::PERIODIC_SYNC_STATE_ESTABLISHED) { 498 return it; 499 } 500 } 501 return periodic_syncs_.end(); 502 } 503 GetSyncFromAddressWithTypeAndSid(const AddressWithType & address_with_type,uint8_t adv_sid)504 std::list<PeriodicSyncStates>::iterator GetSyncFromAddressWithTypeAndSid( 505 const AddressWithType& address_with_type, uint8_t adv_sid) { 506 for (auto it = periodic_syncs_.begin(); it != periodic_syncs_.end(); it++) { 507 if (it->advertiser_sid == adv_sid && it->address_with_type == address_with_type) { 508 return it; 509 } 510 } 511 return periodic_syncs_.end(); 512 } 513 GetSyncFromAddressAndSid(const Address & address,uint8_t adv_sid)514 std::list<PeriodicSyncStates>::iterator GetSyncFromAddressAndSid(const Address& address, uint8_t adv_sid) { 515 for (auto it = periodic_syncs_.begin(); it != periodic_syncs_.end(); it++) { 516 if (it->advertiser_sid == adv_sid && it->address_with_type.GetAddress() == address) { 517 return it; 518 } 519 } 520 return periodic_syncs_.end(); 521 } 522 GetPendingSyncFromAddressAndSid(const Address & address,uint8_t adv_sid)523 std::list<PendingPeriodicSyncRequest>::iterator GetPendingSyncFromAddressAndSid( 524 const Address& address, uint8_t adv_sid) { 525 for (auto it = pending_sync_requests_.begin(); it != pending_sync_requests_.end(); it++) { 526 if (it->advertiser_sid == adv_sid && it->address_with_type.GetAddress() == address) { 527 return it; 528 } 529 } 530 return pending_sync_requests_.end(); 531 } 532 GetSyncTransferRequestFromConnectionHandle(uint16_t connection_handle)533 std::list<PeriodicSyncTransferStates>::iterator GetSyncTransferRequestFromConnectionHandle( 534 uint16_t connection_handle) { 535 for (auto it = periodic_sync_transfers_.begin(); it != periodic_sync_transfers_.end(); it++) { 536 if (it->connection_handle == connection_handle) { 537 return it; 538 } 539 } 540 return periodic_sync_transfers_.end(); 541 } 542 HandleStartSyncRequest(uint8_t sid,const AddressWithType & address_with_type,uint16_t skip,uint16_t timeout)543 void HandleStartSyncRequest(uint8_t sid, const AddressWithType& address_with_type, uint16_t skip, uint16_t timeout) { 544 PeriodicAdvertisingOptions options; 545 auto sync_cte_type = 546 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOA_CONSTANT_TONE_EXTENSION) | 547 static_cast<uint8_t>( 548 PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_ONE_US_SLOTS) | 549 static_cast<uint8_t>( 550 PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_TWO_US_SLOTS); 551 auto sync = GetSyncFromAddressWithTypeAndSid(address_with_type, sid); 552 sync->sync_state = PERIODIC_SYNC_STATE_PENDING; 553 AdvertisingAddressType advertisingAddressType = 554 static_cast<AdvertisingAddressType>(address_with_type.GetAddressType()); 555 le_scanning_interface_->EnqueueCommand( 556 hci::LePeriodicAdvertisingCreateSyncBuilder::Create( 557 options, 558 sid, 559 advertisingAddressType, 560 address_with_type.GetAddress(), 561 skip, 562 timeout, 563 sync_cte_type), 564 handler_->BindOnceOn( 565 this, 566 &PeriodicSyncManager::HandlePeriodicAdvertisingCreateSyncStatus< 567 LePeriodicAdvertisingCreateSyncStatusView>)); 568 } 569 HandleNextRequest()570 void HandleNextRequest() { 571 if (pending_sync_requests_.empty()) { 572 log::debug("pending_sync_requests_ empty"); 573 return; 574 } 575 auto& request = pending_sync_requests_.front(); 576 log::info( 577 "executing sync request SID={:04X}, bd_addr={}", 578 request.advertiser_sid, 579 request.address_with_type); 580 if (request.busy) { 581 log::info("Request is already busy"); 582 return; 583 } 584 request.busy = true; 585 request.sync_timeout_alarm.Cancel(); 586 HandleStartSyncRequest(request.advertiser_sid, request.address_with_type, request.skip, request.sync_timeout); 587 request.sync_timeout_alarm.Schedule( 588 base::BindOnce(&PeriodicSyncManager::OnStartSyncTimeout, base::Unretained(this)), kPeriodicSyncTimeout); 589 } 590 AdvanceRequest()591 void AdvanceRequest() { 592 log::debug("AdvanceRequest"); 593 if (pending_sync_requests_.empty()) { 594 log::debug("pending_sync_requests_ empty"); 595 return; 596 } 597 auto it = pending_sync_requests_.begin(); 598 pending_sync_requests_.erase(it); 599 HandleNextRequest(); 600 } 601 CleanUpRequest(uint8_t advertiser_sid,Address address)602 void CleanUpRequest(uint8_t advertiser_sid, Address address) { 603 auto it = pending_sync_requests_.begin(); 604 while (it != pending_sync_requests_.end()) { 605 if (it->advertiser_sid == advertiser_sid && it->address_with_type.GetAddress() == address) { 606 log::info( 607 "removing connection request SID={:04X}, bd_addr={}, busy={}", 608 it->advertiser_sid, 609 it->address_with_type, 610 it->busy); 611 it = pending_sync_requests_.erase(it); 612 } else { 613 ++it; 614 } 615 } 616 } 617 618 hci::LeScanningInterface* le_scanning_interface_; 619 os::Handler* handler_; 620 ScanningCallback* callbacks_; 621 std::list<PendingPeriodicSyncRequest> pending_sync_requests_; 622 std::list<PeriodicSyncStates> periodic_syncs_; 623 std::list<PeriodicSyncTransferStates> periodic_sync_transfers_; 624 LeScanningReassembler scanning_reassembler_; 625 bool sync_received_callback_registered_ = false; 626 int sync_received_callback_id{}; 627 }; 628 629 } // namespace hci 630 } // namespace bluetooth 631