• 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",
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