• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 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::warn("[PSync]: index not found for handle {}", sync_handle);
365       le_scanning_interface_->EnqueueCommand(
366               hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(sync_handle),
367               handler_->BindOnce(check_complete<LePeriodicAdvertisingTerminateSyncCompleteView>));
368       return;
369     }
370 
371     auto complete_advertising_data = scanning_reassembler_.ProcessPeriodicAdvertisingReport(
372             sync_handle, DataStatus(event_view.GetDataStatus()), event_view.GetData());
373     if (!complete_advertising_data.has_value()) {
374       return;
375     }
376 
377     log::debug("{}", "[PSync]: invoking callback");
378     callbacks_->OnPeriodicSyncReport(sync_handle, event_view.GetTxPower(), event_view.GetRssi(),
379                                      (uint16_t)event_view.GetDataStatus(),
380                                      complete_advertising_data.value());
381   }
382 
HandleLePeriodicAdvertisingSyncLost(LePeriodicAdvertisingSyncLostView event_view)383   void HandleLePeriodicAdvertisingSyncLost(LePeriodicAdvertisingSyncLostView event_view) {
384     log::assert_that(event_view.IsValid(), "assert failed: event_view.IsValid()");
385     uint16_t sync_handle = event_view.GetSyncHandle();
386     log::debug("[PSync]: sync_handle = {}", sync_handle);
387     callbacks_->OnPeriodicSyncLost(sync_handle);
388     auto periodic_sync = GetEstablishedSyncFromHandle(sync_handle);
389     if (periodic_sync == periodic_syncs_.end()) {
390       log::warn("[PSync]: index not found for handle {}", sync_handle);
391       le_scanning_interface_->EnqueueCommand(
392               hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(sync_handle),
393               handler_->BindOnce(check_complete<LePeriodicAdvertisingTerminateSyncCompleteView>));
394       return;
395     }
396     periodic_syncs_.erase(periodic_sync);
397   }
398 
HandleLePeriodicAdvertisingSyncTransferReceived(LePeriodicAdvertisingSyncTransferReceivedView event_view)399   void HandleLePeriodicAdvertisingSyncTransferReceived(
400           LePeriodicAdvertisingSyncTransferReceivedView event_view) {
401     log::assert_that(event_view.IsValid(), "assert failed: event_view.IsValid()");
402     uint8_t status = (uint8_t)event_view.GetStatus();
403     uint8_t advertiser_phy = (uint8_t)event_view.GetAdvertiserPhy();
404     log::debug(
405             "[PAST]: status = {}, connection_handle = {}, service_data = {}, sync_handle = {}, "
406             "adv_sid "
407             "= {}, address_type = {}, address = {}, advertiser_phy = {}, "
408             "periodic_advertising_interval "
409             "= {}, clock_accuracy = {}",
410             status, event_view.GetConnectionHandle(), event_view.GetServiceData(),
411             event_view.GetSyncHandle(), event_view.GetAdvertisingSid(),
412             (uint8_t)event_view.GetAdvertiserAddressType(), event_view.GetAdvertiserAddress(),
413             advertiser_phy, event_view.GetPeriodicAdvertisingInterval(),
414             (uint8_t)event_view.GetAdvertiserClockAccuracy());
415     if (sync_received_callback_registered_) {
416       callbacks_->OnPeriodicSyncStarted(sync_received_callback_id, status,
417                                         event_view.GetSyncHandle(), event_view.GetAdvertisingSid(),
418                                         AddressWithType(event_view.GetAdvertiserAddress(),
419                                                         event_view.GetAdvertiserAddressType()),
420                                         advertiser_phy,
421                                         event_view.GetPeriodicAdvertisingInterval());
422     }
423   }
424 
OnStartSyncTimeout()425   void OnStartSyncTimeout() {
426     if (pending_sync_requests_.empty()) {
427       log::error("pending_sync_requests_ empty");
428       return;
429     }
430     auto& request = pending_sync_requests_.front();
431     log::warn("sync timeout SID={:04X}, bd_addr={}", request.advertiser_sid,
432               request.address_with_type);
433     le_scanning_interface_->EnqueueCommand(
434             hci::LePeriodicAdvertisingCreateSyncCancelBuilder::Create(),
435             handler_->BindOnceOn(
436                     this, &PeriodicSyncManager::HandlePeriodicAdvertisingCreateSyncCancelStatus<
437                                   LePeriodicAdvertisingCreateSyncCancelCompleteView>));
438     auto sync = GetSyncFromAddressWithTypeAndSid(request.address_with_type, request.advertiser_sid);
439     if (sync == periodic_syncs_.end()) {
440       log::error("[PSync]: index not found for address={} and SID={:04X}",
441                  request.address_with_type, request.advertiser_sid);
442       return;
443     }
444     int status = static_cast<int>(ErrorCode::ADVERTISING_TIMEOUT);
445     callbacks_->OnPeriodicSyncStarted(sync->request_id, status, 0, sync->advertiser_sid,
446                                       request.address_with_type, 0, 0);
447     periodic_syncs_.erase(sync);
448   }
449 
HandleLeBigInfoAdvertisingReport(LeBigInfoAdvertisingReportView event_view)450   void HandleLeBigInfoAdvertisingReport(LeBigInfoAdvertisingReportView event_view) {
451     log::assert_that(event_view.IsValid(), "assert failed: event_view.IsValid()");
452     log::debug(
453             "[PAST]:sync_handle {}, num_bises = {}, nse = {},iso_interval = {}, bn = {}, pto = {}, "
454             "irc "
455             "= {}, max_pdu = {} sdu_interval = {}, max_sdu = {}, phy = {}, framing = {}, "
456             "encryption  = "
457             "{}",
458             event_view.GetSyncHandle(), event_view.GetNumBis(), event_view.GetNse(),
459             event_view.GetIsoInterval(), event_view.GetBn(), event_view.GetPto(),
460             event_view.GetIrc(), event_view.GetMaxPdu(), event_view.GetSduInterval(),
461             event_view.GetMaxSdu(), static_cast<uint32_t>(event_view.GetPhy()),
462             static_cast<uint32_t>(event_view.GetFraming()),
463             static_cast<uint32_t>(event_view.GetEncryption()));
464 
465     uint16_t sync_handle = event_view.GetSyncHandle();
466     auto periodic_sync = GetEstablishedSyncFromHandle(sync_handle);
467     if (periodic_sync == periodic_syncs_.end()) {
468       log::warn("[PSync]: index not found for handle {}", sync_handle);
469       le_scanning_interface_->EnqueueCommand(
470               hci::LePeriodicAdvertisingTerminateSyncBuilder::Create(sync_handle),
471               handler_->BindOnce(check_complete<LePeriodicAdvertisingTerminateSyncCompleteView>));
472       return;
473     }
474     log::debug("{}", "[PSync]: invoking callback");
475     callbacks_->OnBigInfoReport(sync_handle,
476                                 event_view.GetEncryption() == Enable::ENABLED ? true : false);
477   }
478 
479 private:
GetEstablishedSyncFromHandle(uint16_t handle)480   std::list<PeriodicSyncStates>::iterator GetEstablishedSyncFromHandle(uint16_t handle) {
481     for (auto it = periodic_syncs_.begin(); it != periodic_syncs_.end(); it++) {
482       if (it->sync_handle == handle &&
483           it->sync_state == PeriodicSyncState::PERIODIC_SYNC_STATE_ESTABLISHED) {
484         return it;
485       }
486     }
487     return periodic_syncs_.end();
488   }
489 
GetSyncFromAddressWithTypeAndSid(const AddressWithType & address_with_type,uint8_t adv_sid)490   std::list<PeriodicSyncStates>::iterator GetSyncFromAddressWithTypeAndSid(
491           const AddressWithType& address_with_type, uint8_t adv_sid) {
492     for (auto it = periodic_syncs_.begin(); it != periodic_syncs_.end(); it++) {
493       if (it->advertiser_sid == adv_sid && it->address_with_type == address_with_type) {
494         return it;
495       }
496     }
497     return periodic_syncs_.end();
498   }
499 
GetSyncFromAddressAndSid(const Address & address,uint8_t adv_sid)500   std::list<PeriodicSyncStates>::iterator GetSyncFromAddressAndSid(const Address& address,
501                                                                    uint8_t adv_sid) {
502     for (auto it = periodic_syncs_.begin(); it != periodic_syncs_.end(); it++) {
503       if (it->advertiser_sid == adv_sid && it->address_with_type.GetAddress() == address) {
504         return it;
505       }
506     }
507     return periodic_syncs_.end();
508   }
509 
GetPendingSyncFromAddressAndSid(const Address & address,uint8_t adv_sid)510   std::list<PendingPeriodicSyncRequest>::iterator GetPendingSyncFromAddressAndSid(
511           const Address& address, uint8_t adv_sid) {
512     for (auto it = pending_sync_requests_.begin(); it != pending_sync_requests_.end(); it++) {
513       if (it->advertiser_sid == adv_sid && it->address_with_type.GetAddress() == address) {
514         return it;
515       }
516     }
517     return pending_sync_requests_.end();
518   }
519 
GetSyncTransferRequestFromConnectionHandle(uint16_t connection_handle)520   std::list<PeriodicSyncTransferStates>::iterator GetSyncTransferRequestFromConnectionHandle(
521           uint16_t connection_handle) {
522     for (auto it = periodic_sync_transfers_.begin(); it != periodic_sync_transfers_.end(); it++) {
523       if (it->connection_handle == connection_handle) {
524         return it;
525       }
526     }
527     return periodic_sync_transfers_.end();
528   }
529 
HandleStartSyncRequest(uint8_t sid,const AddressWithType & address_with_type,uint16_t skip,uint16_t timeout)530   void HandleStartSyncRequest(uint8_t sid, const AddressWithType& address_with_type, uint16_t skip,
531                               uint16_t timeout) {
532     PeriodicAdvertisingOptions options;
533     auto sync_cte_type =
534             static_cast<uint8_t>(PeriodicSyncCteType::AVOID_AOA_CONSTANT_TONE_EXTENSION) |
535             static_cast<uint8_t>(
536                     PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_ONE_US_SLOTS) |
537             static_cast<uint8_t>(
538                     PeriodicSyncCteType::AVOID_AOD_CONSTANT_TONE_EXTENSION_WITH_TWO_US_SLOTS);
539     AdvertisingAddressType advertisingAddressType =
540             static_cast<AdvertisingAddressType>(address_with_type.GetAddressType());
541     le_scanning_interface_->EnqueueCommand(
542             hci::LePeriodicAdvertisingCreateSyncBuilder::Create(
543                     options, sid, advertisingAddressType, address_with_type.GetAddress(), skip,
544                     timeout, sync_cte_type),
545             handler_->BindOnceOn(this,
546                                  &PeriodicSyncManager::HandlePeriodicAdvertisingCreateSyncStatus<
547                                          LePeriodicAdvertisingCreateSyncStatusView>));
548   }
549 
HandleNextRequest()550   void HandleNextRequest() {
551     if (pending_sync_requests_.empty()) {
552       log::debug("pending_sync_requests_ empty");
553       return;
554     }
555     auto& request = pending_sync_requests_.front();
556     log::info("executing sync request SID={:04X}, bd_addr={}", request.advertiser_sid,
557               request.address_with_type);
558     if (request.busy) {
559       log::info("Request is already busy");
560       return;
561     }
562     request.busy = true;
563     request.sync_timeout_alarm.Cancel();
564 
565     auto sync = GetSyncFromAddressWithTypeAndSid(request.address_with_type, request.advertiser_sid);
566     if (sync == periodic_syncs_.end()) {
567       log::warn("[PSync]: index not found for address={} and SID={:04X}", request.address_with_type,
568                 request.advertiser_sid);
569       AdvanceRequest();
570       return;
571     }
572     sync->sync_state = PERIODIC_SYNC_STATE_PENDING;
573     HandleStartSyncRequest(request.advertiser_sid, request.address_with_type, request.skip,
574                            request.sync_timeout);
575     request.sync_timeout_alarm.Schedule(
576             base::BindOnce(&PeriodicSyncManager::OnStartSyncTimeout, base::Unretained(this)),
577             kPeriodicSyncTimeout);
578   }
579 
AdvanceRequest()580   void AdvanceRequest() {
581     log::debug("AdvanceRequest");
582     if (pending_sync_requests_.empty()) {
583       log::debug("pending_sync_requests_ empty");
584       return;
585     }
586     auto it = pending_sync_requests_.begin();
587     pending_sync_requests_.erase(it);
588     HandleNextRequest();
589   }
590 
CleanUpRequest(uint8_t advertiser_sid,Address address)591   void CleanUpRequest(uint8_t advertiser_sid, Address address) {
592     auto it = pending_sync_requests_.begin();
593     while (it != pending_sync_requests_.end()) {
594       if (it->advertiser_sid == advertiser_sid && it->address_with_type.GetAddress() == address) {
595         log::info("removing connection request SID={:04X}, bd_addr={}, busy={}", it->advertiser_sid,
596                   it->address_with_type, it->busy);
597         it = pending_sync_requests_.erase(it);
598       } else {
599         ++it;
600       }
601     }
602   }
603 
604   hci::LeScanningInterface* le_scanning_interface_;
605   os::Handler* handler_;
606   ScanningCallback* callbacks_;
607   std::list<PendingPeriodicSyncRequest> pending_sync_requests_;
608   std::list<PeriodicSyncStates> periodic_syncs_;
609   std::list<PeriodicSyncTransferStates> periodic_sync_transfers_;
610   LeScanningReassembler scanning_reassembler_;
611   bool sync_received_callback_registered_ = false;
612   int sync_received_callback_id{};
613 };
614 
615 }  // namespace hci
616 }  // namespace bluetooth
617