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