• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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