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", 107 ADDRESS_TO_LOGGABLE_CSTR(request.address_with_type), 108 request.advertiser_sid); 109 pending_sync_requests_.emplace_back( 110 request.advertiser_sid, request.address_with_type, skip, sync_timeout, handler_); 111 HandleNextRequest(); 112 } 113 StopSync(uint16_t handle)114 void StopSync(uint16_t handle) { 115 LOG_DEBUG("[PSync]: handle = %u", handle); 116 auto periodic_sync = GetEstablishedSyncFromHandle(handle); 117 if (periodic_sync == periodic_syncs_.end()) { 118 LOG_ERROR("[PSync]: invalid index for handle %u", handle); 119 le_scanning_interface_->EnqueueCommand( 120 hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(handle), 121 handler_->BindOnceOn( 122 this, &PeriodicSyncManager::check_status<LePeriodicAdvertisingTerminateSyncCompleteView>)); 123 return; 124 }; 125 periodic_syncs_.erase(periodic_sync); 126 le_scanning_interface_->EnqueueCommand( 127 hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(handle), 128 handler_->BindOnceOn(this, &PeriodicSyncManager::check_status<LePeriodicAdvertisingTerminateSyncCompleteView>)); 129 } 130 CancelCreateSync(uint8_t adv_sid,Address address)131 void CancelCreateSync(uint8_t adv_sid, Address address) { 132 LOG_DEBUG("[PSync]"); 133 auto periodic_sync = GetSyncFromAddressAndSid(address, adv_sid); 134 if (periodic_sync == periodic_syncs_.end()) { 135 LOG_ERROR("[PSync]:Invalid index for sid=%u", adv_sid); 136 return; 137 } 138 139 if (periodic_sync->sync_state == PERIODIC_SYNC_STATE_PENDING) { 140 LOG_WARN("[PSync]: Sync state is pending"); 141 le_scanning_interface_->EnqueueCommand( 142 hci::LePeriodicAdvertisingCreateSyncCancelBuilder::Create(), 143 handler_->BindOnceOn(this, &PeriodicSyncManager::HandlePeriodicAdvertisingCreateSyncCancelStatus)); 144 } else if (periodic_sync->sync_state == PERIODIC_SYNC_STATE_IDLE) { 145 LOG_DEBUG("[PSync]: Removing Sync request from queue"); 146 CleanUpRequest(adv_sid, address); 147 } 148 periodic_syncs_.erase(periodic_sync); 149 } 150 TransferSync(const Address & address,uint16_t service_data,uint16_t sync_handle,int pa_source,uint16_t connection_handle)151 void TransferSync( 152 const Address& address, uint16_t service_data, uint16_t sync_handle, int pa_source, uint16_t connection_handle) { 153 if (periodic_sync_transfers_.size() >= kMaxSyncTransactions) { 154 int status = static_cast<int>(ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES); 155 callbacks_->OnPeriodicSyncTransferred(pa_source, status, address); 156 return; 157 } 158 159 PeriodicSyncTransferStates request{pa_source, connection_handle, address}; 160 periodic_sync_transfers_.emplace_back(request); 161 le_scanning_interface_->EnqueueCommand( 162 hci::LePeriodicAdvertisingSyncTransferBuilder::Create(connection_handle, service_data, sync_handle), 163 handler_->BindOnceOn( 164 this, 165 &PeriodicSyncManager::HandlePeriodicAdvertisingSyncTransferComplete< 166 LePeriodicAdvertisingSyncTransferCompleteView>, 167 connection_handle)); 168 } 169 SyncSetInfo(const Address & address,uint16_t service_data,uint8_t adv_handle,int pa_source,uint16_t connection_handle)170 void SyncSetInfo( 171 const Address& address, uint16_t service_data, uint8_t adv_handle, int pa_source, uint16_t connection_handle) { 172 if (periodic_sync_transfers_.size() >= kMaxSyncTransactions) { 173 int status = static_cast<int>(ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES); 174 callbacks_->OnPeriodicSyncTransferred(pa_source, status, address); 175 return; 176 } 177 PeriodicSyncTransferStates request{pa_source, connection_handle, address}; 178 periodic_sync_transfers_.emplace_back(request); 179 le_scanning_interface_->EnqueueCommand( 180 hci::LePeriodicAdvertisingSetInfoTransferBuilder::Create(connection_handle, service_data, adv_handle), 181 handler_->BindOnceOn( 182 this, 183 &PeriodicSyncManager::HandlePeriodicAdvertisingSyncTransferComplete< 184 LePeriodicAdvertisingSetInfoTransferCompleteView>, 185 connection_handle)); 186 } 187 SyncTxParameters(const Address & address,uint8_t mode,uint16_t skip,uint16_t timeout,int reg_id)188 void SyncTxParameters(const Address& address, uint8_t mode, uint16_t skip, uint16_t timeout, int reg_id) { 189 LOG_DEBUG("[PAST]: mode=%u, skip=%u, timeout=%u", mode, skip, timeout); 190 auto sync_cte_type = static_cast<CteType>( 191 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOA_CONSTANT_TONE_EXTENSION) | 192 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_ONE_US_SLOTS) | 193 static_cast<uint8_t>(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_->BindOnceOn( 201 this, 202 &PeriodicSyncManager::check_status<LeSetDefaultPeriodicAdvertisingSyncTransferParametersCompleteView>)); 203 } 204 HandlePeriodicAdvertisingCreateSyncStatus(CommandStatusView)205 void HandlePeriodicAdvertisingCreateSyncStatus(CommandStatusView) {} 206 HandlePeriodicAdvertisingCreateSyncCancelStatus(CommandCompleteView)207 void HandlePeriodicAdvertisingCreateSyncCancelStatus(CommandCompleteView) {} 208 209 template <class View> HandlePeriodicAdvertisingSyncTransferComplete(uint16_t connection_handle,CommandCompleteView view)210 void HandlePeriodicAdvertisingSyncTransferComplete(uint16_t connection_handle, CommandCompleteView view) { 211 ASSERT(view.IsValid()); 212 auto status_view = View::Create(view); 213 ASSERT(status_view.IsValid()); 214 if (status_view.GetStatus() != ErrorCode::SUCCESS) { 215 LOG_WARN( 216 "Got a Command complete %s, status %s, connection_handle %d", 217 OpCodeText(view.GetCommandOpCode()).c_str(), 218 ErrorCodeText(status_view.GetStatus()).c_str(), 219 connection_handle); 220 } else { 221 LOG_DEBUG( 222 "Got a Command complete %s, status %s, connection_handle %d", 223 OpCodeText(view.GetCommandOpCode()).c_str(), 224 ErrorCodeText(status_view.GetStatus()).c_str(), 225 connection_handle); 226 } 227 228 auto periodic_sync_transfer = GetSyncTransferRequestFromConnectionHandle(connection_handle); 229 if (periodic_sync_transfer == periodic_sync_transfers_.end()) { 230 LOG_ERROR("[PAST]:Invalid, conn_handle %u not found in DB", connection_handle); 231 return; 232 }; 233 234 callbacks_->OnPeriodicSyncTransferred( 235 periodic_sync_transfer->pa_source, (uint16_t)status_view.GetStatus(), periodic_sync_transfer->addr); 236 periodic_sync_transfers_.erase(periodic_sync_transfer); 237 } 238 239 template <class View> check_status(CommandCompleteView view)240 void check_status(CommandCompleteView view) { 241 ASSERT(view.IsValid()); 242 auto status_view = View::Create(view); 243 ASSERT(status_view.IsValid()); 244 if (status_view.GetStatus() != ErrorCode::SUCCESS) { 245 LOG_WARN( 246 "Got a Command complete %s, status %s", 247 OpCodeText(view.GetCommandOpCode()).c_str(), 248 ErrorCodeText(status_view.GetStatus()).c_str()); 249 } else { 250 LOG_DEBUG( 251 "Got a Command complete %s, status %s", 252 OpCodeText(view.GetCommandOpCode()).c_str(), 253 ErrorCodeText(status_view.GetStatus()).c_str()); 254 } 255 } 256 HandleLePeriodicAdvertisingSyncEstablished(LePeriodicAdvertisingSyncEstablishedView event_view)257 void HandleLePeriodicAdvertisingSyncEstablished(LePeriodicAdvertisingSyncEstablishedView event_view) { 258 ASSERT(event_view.IsValid()); 259 LOG_DEBUG( 260 "[PSync]: status=%d, sync_handle=%d, s_id=%d, " 261 "address_type=%d, adv_phy=%d,adv_interval=%d, clock_acc=%d", 262 (uint16_t)event_view.GetStatus(), 263 event_view.GetSyncHandle(), 264 event_view.GetAdvertisingSid(), 265 (uint16_t)event_view.GetAdvertiserAddressType(), 266 (uint16_t)event_view.GetAdvertiserPhy(), 267 event_view.GetPeriodicAdvertisingInterval(), 268 (uint16_t)event_view.GetAdvertiserClockAccuracy()); 269 270 auto pending_sync_request = 271 GetPendingSyncFromAddressAndSid(event_view.GetAdvertiserAddress(), event_view.GetAdvertisingSid()); 272 if (pending_sync_request != pending_sync_requests_.end()) { 273 pending_sync_request->sync_timeout_alarm.Cancel(); 274 } 275 276 auto address_with_type = AddressWithType(event_view.GetAdvertiserAddress(), event_view.GetAdvertiserAddressType()); 277 auto peer_address_type = address_with_type.GetAddressType(); 278 AddressType temp_address_type; 279 switch (peer_address_type) { 280 case AddressType::PUBLIC_DEVICE_ADDRESS: 281 case AddressType::PUBLIC_IDENTITY_ADDRESS: 282 temp_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; 283 break; 284 case AddressType::RANDOM_DEVICE_ADDRESS: 285 case AddressType::RANDOM_IDENTITY_ADDRESS: 286 temp_address_type = AddressType::RANDOM_DEVICE_ADDRESS; 287 break; 288 } 289 290 auto periodic_sync = GetSyncFromAddressWithTypeAndSid( 291 AddressWithType(event_view.GetAdvertiserAddress(), temp_address_type), event_view.GetAdvertisingSid()); 292 if (periodic_sync == periodic_syncs_.end()) { 293 LOG_WARN("[PSync]: Invalid address and sid for sync established"); 294 if (event_view.GetStatus() == ErrorCode::SUCCESS) { 295 LOG_WARN("Terminate sync"); 296 le_scanning_interface_->EnqueueCommand( 297 hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(event_view.GetSyncHandle()), 298 handler_->BindOnceOn( 299 this, &PeriodicSyncManager::check_status<LePeriodicAdvertisingTerminateSyncCompleteView>)); 300 } 301 AdvanceRequest(); 302 return; 303 } 304 periodic_sync->sync_handle = event_view.GetSyncHandle(); 305 periodic_sync->sync_state = PERIODIC_SYNC_STATE_ESTABLISHED; 306 callbacks_->OnPeriodicSyncStarted( 307 periodic_sync->request_id, 308 (uint8_t)event_view.GetStatus(), 309 event_view.GetSyncHandle(), 310 event_view.GetAdvertisingSid(), 311 address_with_type, 312 (uint16_t)event_view.GetAdvertiserPhy(), 313 event_view.GetPeriodicAdvertisingInterval()); 314 AdvanceRequest(); 315 } 316 HandleLePeriodicAdvertisingReport(LePeriodicAdvertisingReportView event_view)317 void HandleLePeriodicAdvertisingReport(LePeriodicAdvertisingReportView event_view) { 318 ASSERT(event_view.IsValid()); 319 LOG_DEBUG( 320 "[PSync]: sync_handle = %u, tx_power = %d, rssi = %d," 321 "cte_type = %u, data_status = %u, data_len = %u", 322 event_view.GetSyncHandle(), 323 event_view.GetTxPower(), 324 event_view.GetRssi(), 325 (uint16_t)event_view.GetCteType(), 326 (uint16_t)event_view.GetDataStatus(), 327 (uint16_t)event_view.GetData().size()); 328 329 uint16_t sync_handle = event_view.GetSyncHandle(); 330 auto periodic_sync = GetEstablishedSyncFromHandle(sync_handle); 331 if (periodic_sync == periodic_syncs_.end()) { 332 LOG_ERROR("[PSync]: index not found for handle %u", sync_handle); 333 return; 334 } 335 LOG_DEBUG("%s", "[PSync]: invoking callback"); 336 callbacks_->OnPeriodicSyncReport( 337 sync_handle, 338 event_view.GetTxPower(), 339 event_view.GetRssi(), 340 (uint16_t)event_view.GetDataStatus(), 341 event_view.GetData()); 342 } 343 HandleLePeriodicAdvertisingSyncLost(LePeriodicAdvertisingSyncLostView event_view)344 void HandleLePeriodicAdvertisingSyncLost(LePeriodicAdvertisingSyncLostView event_view) { 345 ASSERT(event_view.IsValid()); 346 uint16_t sync_handle = event_view.GetSyncHandle(); 347 LOG_DEBUG("[PSync]: sync_handle = %d", sync_handle); 348 callbacks_->OnPeriodicSyncLost(sync_handle); 349 auto periodic_sync = GetEstablishedSyncFromHandle(sync_handle); 350 periodic_syncs_.erase(periodic_sync); 351 } 352 HandleLePeriodicAdvertisingSyncTransferReceived(LePeriodicAdvertisingSyncTransferReceivedView event_view)353 void HandleLePeriodicAdvertisingSyncTransferReceived(LePeriodicAdvertisingSyncTransferReceivedView event_view) { 354 ASSERT(event_view.IsValid()); 355 uint8_t status = (uint8_t)event_view.GetStatus(); 356 uint8_t advertiser_phy = (uint8_t)event_view.GetAdvertiserPhy(); 357 LOG_DEBUG( 358 "[PAST]: status = %u, connection_handle = %u, service_data = %u," 359 " sync_handle = %u, adv_sid = %u, address_type = %u, address = %s," 360 " advertiser_phy = %u, periodic_advertising_interval = %u, clock_accuracy = %u", 361 status, 362 event_view.GetConnectionHandle(), 363 event_view.GetServiceData(), 364 event_view.GetSyncHandle(), 365 event_view.GetAdvertisingSid(), 366 (uint8_t)event_view.GetAdvertiserAddressType(), 367 ADDRESS_TO_LOGGABLE_CSTR(event_view.GetAdvertiserAddress()), 368 advertiser_phy, 369 event_view.GetPeriodicAdvertisingInterval(), 370 (uint8_t)event_view.GetAdvertiserClockAccuracy()); 371 if (sync_received_callback_registered_) { 372 callbacks_->OnPeriodicSyncStarted( 373 sync_received_callback_id, 374 status, 375 event_view.GetSyncHandle(), 376 event_view.GetAdvertisingSid(), 377 AddressWithType(event_view.GetAdvertiserAddress(), event_view.GetAdvertiserAddressType()), 378 advertiser_phy, 379 event_view.GetPeriodicAdvertisingInterval()); 380 } 381 } 382 OnStartSyncTimeout()383 void OnStartSyncTimeout() { 384 auto& request = pending_sync_requests_.front(); 385 LOG_WARN( 386 "%s: sync timeout SID=%04X, bd_addr=%s", 387 __func__, 388 request.advertiser_sid, 389 ADDRESS_TO_LOGGABLE_CSTR(request.address_with_type)); 390 uint8_t adv_sid = request.advertiser_sid; 391 AddressWithType address_with_type = request.address_with_type; 392 auto sync = GetSyncFromAddressWithTypeAndSid(address_with_type, adv_sid); 393 le_scanning_interface_->EnqueueCommand( 394 hci::LePeriodicAdvertisingCreateSyncCancelBuilder::Create(), 395 handler_->BindOnceOn(this, &PeriodicSyncManager::HandlePeriodicAdvertisingCreateSyncCancelStatus)); 396 int status = static_cast<int>(ErrorCode::ADVERTISING_TIMEOUT); 397 callbacks_->OnPeriodicSyncStarted( 398 sync->request_id, status, 0, sync->advertiser_sid, request.address_with_type, 0, 0); 399 RemoveSyncRequest(sync); 400 } 401 HandleLeBigInfoAdvertisingReport(LeBigInfoAdvertisingReportView event_view)402 void HandleLeBigInfoAdvertisingReport(LeBigInfoAdvertisingReportView event_view) { 403 ASSERT(event_view.IsValid()); 404 LOG_DEBUG( 405 "[PAST]:sync_handle %u, num_bises = %u, nse = %u," 406 "iso_interval = %d, bn = %u, pto = %u, irc = %u, max_pdu = %u " 407 "sdu_interval = %d, max_sdu = %u, phy = %u, framing = %u, encryption = " 408 "%u", 409 event_view.GetSyncHandle(), event_view.GetNumBis(), event_view.GetNse(), 410 event_view.GetIsoInterval(), event_view.GetBn(), event_view.GetPto(), event_view.GetIrc(), 411 event_view.GetMaxPdu(), event_view.GetSduInterval(), event_view.GetMaxSdu(), 412 static_cast<uint32_t>(event_view.GetPhy()), static_cast<uint32_t>(event_view.GetFraming()), 413 static_cast<uint32_t>(event_view.GetEncryption())); 414 415 uint16_t sync_handle = event_view.GetSyncHandle(); 416 auto periodic_sync = GetEstablishedSyncFromHandle(sync_handle); 417 if (periodic_sync == periodic_syncs_.end()) { 418 LOG_ERROR("[PSync]: index not found for handle %u", sync_handle); 419 return; 420 } 421 LOG_DEBUG("%s", "[PSync]: invoking callback"); 422 callbacks_->OnBigInfoReport(sync_handle, event_view.GetEncryption() == Enable::ENABLED ? true : false); 423 } 424 425 private: GetEstablishedSyncFromHandle(uint16_t handle)426 std::list<PeriodicSyncStates>::iterator GetEstablishedSyncFromHandle(uint16_t handle) { 427 for (auto it = periodic_syncs_.begin(); it != periodic_syncs_.end(); it++) { 428 if (it->sync_handle == handle && it->sync_state == PeriodicSyncState::PERIODIC_SYNC_STATE_ESTABLISHED) { 429 return it; 430 } 431 } 432 return periodic_syncs_.end(); 433 } 434 GetSyncFromAddressWithTypeAndSid(const AddressWithType & address_with_type,uint8_t adv_sid)435 std::list<PeriodicSyncStates>::iterator GetSyncFromAddressWithTypeAndSid( 436 const AddressWithType& address_with_type, uint8_t adv_sid) { 437 for (auto it = periodic_syncs_.begin(); it != periodic_syncs_.end(); it++) { 438 if (it->advertiser_sid == adv_sid && it->address_with_type == address_with_type) { 439 return it; 440 } 441 } 442 return periodic_syncs_.end(); 443 } 444 GetSyncFromAddressAndSid(const Address & address,uint8_t adv_sid)445 std::list<PeriodicSyncStates>::iterator GetSyncFromAddressAndSid(const Address& address, uint8_t adv_sid) { 446 for (auto it = periodic_syncs_.begin(); it != periodic_syncs_.end(); it++) { 447 if (it->advertiser_sid == adv_sid && it->address_with_type.GetAddress() == address) { 448 return it; 449 } 450 } 451 return periodic_syncs_.end(); 452 } 453 GetPendingSyncFromAddressAndSid(const Address & address,uint8_t adv_sid)454 std::list<PendingPeriodicSyncRequest>::iterator GetPendingSyncFromAddressAndSid( 455 const Address& address, uint8_t adv_sid) { 456 for (auto it = pending_sync_requests_.begin(); it != pending_sync_requests_.end(); it++) { 457 if (it->advertiser_sid == adv_sid && it->address_with_type.GetAddress() == address) { 458 return it; 459 } 460 } 461 return pending_sync_requests_.end(); 462 } 463 RemoveSyncRequest(std::list<PeriodicSyncStates>::iterator it)464 void RemoveSyncRequest(std::list<PeriodicSyncStates>::iterator it) { 465 periodic_syncs_.erase(it); 466 } 467 GetSyncTransferRequestFromConnectionHandle(uint16_t connection_handle)468 std::list<PeriodicSyncTransferStates>::iterator GetSyncTransferRequestFromConnectionHandle( 469 uint16_t connection_handle) { 470 for (auto it = periodic_sync_transfers_.begin(); it != periodic_sync_transfers_.end(); it++) { 471 if (it->connection_handle == connection_handle) { 472 return it; 473 } 474 } 475 return periodic_sync_transfers_.end(); 476 } 477 HandleStartSyncRequest(uint8_t sid,const AddressWithType & address_with_type,uint16_t skip,uint16_t timeout)478 void HandleStartSyncRequest(uint8_t sid, const AddressWithType& address_with_type, uint16_t skip, uint16_t timeout) { 479 PeriodicAdvertisingOptions options; 480 auto sync_cte_type = 481 static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOA_CONSTANT_TONE_EXTENSION) | 482 static_cast<uint8_t>( 483 PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_ONE_US_SLOTS) | 484 static_cast<uint8_t>( 485 PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_TWO_US_SLOTS); 486 auto sync = GetSyncFromAddressWithTypeAndSid(address_with_type, sid); 487 sync->sync_state = PERIODIC_SYNC_STATE_PENDING; 488 AdvertisingAddressType advertisingAddressType = 489 static_cast<AdvertisingAddressType>(address_with_type.GetAddressType()); 490 le_scanning_interface_->EnqueueCommand( 491 hci::LePeriodicAdvertisingCreateSyncBuilder::Create( 492 options, sid, advertisingAddressType, address_with_type.GetAddress(), skip, timeout, sync_cte_type), 493 handler_->BindOnceOn(this, &PeriodicSyncManager::HandlePeriodicAdvertisingCreateSyncStatus)); 494 } 495 HandleNextRequest()496 void HandleNextRequest() { 497 if (pending_sync_requests_.empty()) { 498 LOG_DEBUG("pending_sync_requests_ empty"); 499 return; 500 } 501 auto& request = pending_sync_requests_.front(); 502 LOG_INFO( 503 "executing sync request SID=%04X, bd_addr=%s", 504 request.advertiser_sid, 505 ADDRESS_TO_LOGGABLE_CSTR(request.address_with_type)); 506 if (request.busy) { 507 LOG_INFO("Request is already busy"); 508 return; 509 } 510 request.busy = true; 511 request.sync_timeout_alarm.Cancel(); 512 HandleStartSyncRequest(request.advertiser_sid, request.address_with_type, request.skip, request.sync_timeout); 513 request.sync_timeout_alarm.Schedule( 514 base::BindOnce(&PeriodicSyncManager::OnStartSyncTimeout, base::Unretained(this)), kPeriodicSyncTimeout); 515 } 516 AdvanceRequest()517 void AdvanceRequest() { 518 LOG_DEBUG("AdvanceRequest"); 519 if (pending_sync_requests_.empty()) { 520 LOG_DEBUG("pending_sync_requests_ empty"); 521 return; 522 } 523 auto it = pending_sync_requests_.begin(); 524 pending_sync_requests_.erase(it); 525 HandleNextRequest(); 526 } 527 CleanUpRequest(uint8_t advertiser_sid,Address address)528 void CleanUpRequest(uint8_t advertiser_sid, Address address) { 529 auto it = pending_sync_requests_.begin(); 530 while (it != pending_sync_requests_.end()) { 531 if (it->advertiser_sid == advertiser_sid && it->address_with_type.GetAddress() == address) { 532 LOG_INFO( 533 "removing connection request SID=%04X, bd_addr=%s, busy=%d", 534 it->advertiser_sid, 535 ADDRESS_TO_LOGGABLE_CSTR(it->address_with_type), 536 it->busy); 537 it = pending_sync_requests_.erase(it); 538 } else { 539 ++it; 540 } 541 } 542 } 543 544 hci::LeScanningInterface* le_scanning_interface_; 545 os::Handler* handler_; 546 ScanningCallback* callbacks_; 547 std::list<PendingPeriodicSyncRequest> pending_sync_requests_; 548 std::list<PeriodicSyncStates> periodic_syncs_; 549 std::list<PeriodicSyncTransferStates> periodic_sync_transfers_; 550 bool sync_received_callback_registered_ = false; 551 int sync_received_callback_id{}; 552 }; 553 554 } // namespace hci 555 } // namespace bluetooth 556