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