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 
17 #include "hci/le_periodic_sync_manager.h"
18 
19 #include <com_android_bluetooth_flags.h>
20 #include <flag_macros.h>
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 
24 #include "hci/le_scanning_callback.h"
25 #include "hci/le_scanning_interface.h"
26 #include "hci/le_scanning_manager_mock.h"
27 #include "os/handler.h"
28 
29 #define TEST_BT com::android::bluetooth::flags
30 
31 using namespace std::chrono_literals;
32 
33 using testing::_;
34 
35 namespace bluetooth {
36 namespace hci {
37 namespace {
38 
GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet)39 PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
40   auto bytes = std::make_shared<std::vector<uint8_t>>();
41   BitInserter i(*bytes);
42   bytes->reserve(packet->size());
43   packet->Serialize(i);
44   return packet::PacketView<packet::kLittleEndian>(bytes);
45 }
46 
47 class TestLeScanningInterface : public LeScanningInterface {
48  public:
EnqueueCommand(std::unique_ptr<LeScanningCommandBuilder> command,common::ContextualOnceCallback<void (CommandCompleteView)> on_complete)49   void EnqueueCommand(
50       std::unique_ptr<LeScanningCommandBuilder> command,
51       common::ContextualOnceCallback<void(CommandCompleteView)> on_complete) override {
52     std::lock_guard<std::mutex> lock(mutex_);
53     command_queue_.push(std::move(command));
54     command_complete_callbacks.push_back(std::move(on_complete));
55     if (command_promise_ != nullptr) {
56       std::promise<void>* prom = command_promise_.release();
57       prom->set_value();
58       delete prom;
59     }
60   }
61 
EnqueueCommand(std::unique_ptr<LeScanningCommandBuilder> command,common::ContextualOnceCallback<void (CommandStatusView)> on_status)62   void EnqueueCommand(
63       std::unique_ptr<LeScanningCommandBuilder> command,
64       common::ContextualOnceCallback<void(CommandStatusView)> on_status) override {
65     command_queue_.push(std::move(command));
66     command_status_callbacks.push_back(std::move(on_status));
67     if (command_promise_ != nullptr) {
68       std::promise<void>* prom = command_promise_.release();
69       prom->set_value();
70       delete prom;
71     }
72   }
73 
SetCommandFuture()74   void SetCommandFuture() {
75     ASSERT_EQ(command_promise_, nullptr) << "Promises, Promises, ... Only one at a time.";
76     command_promise_ = std::make_unique<std::promise<void>>();
77     command_future_ = std::make_unique<std::future<void>>(command_promise_->get_future());
78   }
79 
GetLastCommand()80   CommandView GetLastCommand() {
81     if (command_queue_.empty()) {
82       return CommandView::Create(PacketView<kLittleEndian>(std::make_shared<std::vector<uint8_t>>()));
83     }
84     auto last = std::move(command_queue_.front());
85     command_queue_.pop();
86     return CommandView::Create(GetPacketView(std::move(last)));
87   }
88 
GetCommand(OpCode op_code)89   CommandView GetCommand(OpCode op_code) {
90     if (!command_queue_.empty()) {
91       std::lock_guard<std::mutex> lock(mutex_);
92       if (command_future_ != nullptr) {
93         command_future_.reset();
94         command_promise_.reset();
95       }
96     } else if (command_future_ != nullptr) {
97       auto result = command_future_->wait_for(std::chrono::milliseconds(1000));
98       EXPECT_NE(std::future_status::timeout, result);
99     }
100     std::lock_guard<std::mutex> lock(mutex_);
101     log::assert_that(
102         !command_queue_.empty(),
103         "Expecting command {} but command queue was empty",
104         OpCodeText(op_code));
105     CommandView command_packet_view = GetLastCommand();
106     EXPECT_TRUE(command_packet_view.IsValid());
107     EXPECT_EQ(command_packet_view.GetOpCode(), op_code);
108     return command_packet_view;
109   }
110 
CommandCompleteCallback(std::unique_ptr<EventBuilder> event_builder)111   void CommandCompleteCallback(std::unique_ptr<EventBuilder> event_builder) {
112     auto event = EventView::Create(GetPacketView(std::move(event_builder)));
113     CommandCompleteView complete_view = CommandCompleteView::Create(event);
114     ASSERT_TRUE(complete_view.IsValid());
115     ASSERT_NE((uint16_t)command_complete_callbacks.size(), 0);
116     std::move(command_complete_callbacks.front())(complete_view);
117     command_complete_callbacks.pop_front();
118   }
119 
CommandStatusCallback(std::unique_ptr<EventBuilder> event_builder)120   void CommandStatusCallback(std::unique_ptr<EventBuilder> event_builder) {
121     auto event = EventView::Create(GetPacketView(std::move(event_builder)));
122     CommandStatusView status_view = CommandStatusView::Create(event);
123     ASSERT_TRUE(status_view.IsValid());
124     ASSERT_NE((uint16_t)command_status_callbacks.size(), 0);
125     std::move(command_status_callbacks.front())(status_view);
126     command_status_callbacks.pop_front();
127   }
128 
129  private:
130   std::list<common::ContextualOnceCallback<void(CommandCompleteView)>> command_complete_callbacks;
131   std::list<common::ContextualOnceCallback<void(CommandStatusView)>> command_status_callbacks;
132   std::queue<std::unique_ptr<CommandBuilder>> command_queue_;
133   std::unique_ptr<std::promise<void>> command_promise_;
134   std::unique_ptr<std::future<void>> command_future_;
135   mutable std::mutex mutex_;
136 };
137 
138 class PeriodicSyncManagerTest : public ::testing::Test {
139  protected:
SetUp()140   void SetUp() override {
141     thread_ = new os::Thread("thread", os::Thread::Priority::NORMAL);
142     handler_ = new os::Handler(thread_);
143     test_le_scanning_interface_ = new TestLeScanningInterface();
144     periodic_sync_manager_ = new PeriodicSyncManager(&mock_callbacks_);
145     periodic_sync_manager_->Init(test_le_scanning_interface_, handler_);
146   }
147 
TearDown()148   void TearDown() override {
149     delete periodic_sync_manager_;
150     periodic_sync_manager_ = nullptr;
151     delete test_le_scanning_interface_;
152     test_le_scanning_interface_ = nullptr;
153     handler_->Clear();
154     delete handler_;
155     handler_ = nullptr;
156     delete thread_;
157     thread_ = nullptr;
158   }
159 
sync_handler()160   void sync_handler() {
161     log::assert_that(thread_ != nullptr, "assert failed: thread_ != nullptr");
162     log::assert_that(
163         thread_->GetReactor()->WaitForIdle(2s),
164         "assert failed: thread_->GetReactor()->WaitForIdle(2s)");
165   }
166 
167   class MockCallbacks : public bluetooth::hci::ScanningCallback {
168    public:
169     MOCK_METHOD(
170         void,
171         OnScannerRegistered,
172         (const bluetooth::hci::Uuid app_uuid, ScannerId scanner_id, ScanningStatus status),
173         (override));
174     MOCK_METHOD(void, OnSetScannerParameterComplete, (ScannerId scanner_id, ScanningStatus status), (override));
175     MOCK_METHOD(
176         void,
177         OnScanResult,
178         (uint16_t event_type,
179          uint8_t address_type,
180          Address address,
181          uint8_t primary_phy,
182          uint8_t secondary_phy,
183          uint8_t advertising_sid,
184          int8_t tx_power,
185          int8_t rssi,
186          uint16_t periodic_advertising_interval,
187          std::vector<uint8_t> advertising_data),
188         (override));
189     MOCK_METHOD(
190         void,
191         OnTrackAdvFoundLost,
192         (bluetooth::hci::AdvertisingFilterOnFoundOnLostInfo on_found_on_lost_info),
193         (override));
194     MOCK_METHOD(
195         void,
196         OnBatchScanReports,
197         (int client_if, int status, int report_format, int num_records, std::vector<uint8_t> data),
198         (override));
199     MOCK_METHOD(void, OnBatchScanThresholdCrossed, (int client_if), (override));
200     MOCK_METHOD(void, OnTimeout, (), (override));
201     MOCK_METHOD(void, OnFilterEnable, (Enable enable, uint8_t status), (override));
202     MOCK_METHOD(void, OnFilterParamSetup, (uint8_t available_spaces, ApcfAction action, uint8_t status), (override));
203     MOCK_METHOD(
204         void,
205         OnFilterConfigCallback,
206         (ApcfFilterType filter_type, uint8_t available_spaces, ApcfAction action, uint8_t status),
207         (override));
208     MOCK_METHOD(void, OnPeriodicSyncStarted, (int, uint8_t, uint16_t, uint8_t, AddressWithType, uint8_t, uint16_t));
209     MOCK_METHOD(void, OnPeriodicSyncReport, (uint16_t, int8_t, int8_t, uint8_t, std::vector<uint8_t>));
210     MOCK_METHOD(void, OnPeriodicSyncLost, (uint16_t));
211     MOCK_METHOD(void, OnPeriodicSyncTransferred, (int, uint8_t, Address));
212     MOCK_METHOD(void, OnBigInfoReport, (uint16_t, bool));
213   } mock_callbacks_;
214 
215   os::Thread* thread_;
216   os::Handler* handler_;
217   TestLeScanningInterface* test_le_scanning_interface_;
218   PeriodicSyncManager* periodic_sync_manager_ = nullptr;
219 };
220 
TEST_F(PeriodicSyncManagerTest,startup_teardown)221 TEST_F(PeriodicSyncManagerTest, startup_teardown) {}
222 
TEST_F(PeriodicSyncManagerTest,start_sync_test)223 TEST_F(PeriodicSyncManagerTest, start_sync_test) {
224   Address address;
225   Address::FromString("00:11:22:33:44:55", address);
226   int request_id = 0x01;
227   uint8_t advertiser_sid = 0x02;
228   AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);
229   uint16_t sync_handle = 0x03;
230   PeriodicSyncStates request{
231       .request_id = request_id,
232       .advertiser_sid = advertiser_sid,
233       .address_with_type = address_with_type,
234       .sync_handle = sync_handle,
235       .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
236   };
237   uint16_t skip = 0x04;
238   uint16_t sync_timeout = 0x0A;
239   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
240   periodic_sync_manager_->StartSync(request, skip, sync_timeout);
241   auto packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
242   auto packet_view = LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
243   ASSERT_TRUE(packet_view.IsValid());
244   ASSERT_EQ(advertiser_sid, packet_view.GetAdvertisingSid());
245   ASSERT_EQ(
246       AdvertisingAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS,
247       packet_view.GetAdvertiserAddressType());
248   ASSERT_EQ(address, packet_view.GetAdvertiserAddress());
249   ASSERT_EQ(skip, packet_view.GetSkip());
250   ASSERT_EQ(sync_timeout, packet_view.GetSyncTimeout());
251   sync_handler();
252 }
253 
TEST_F(PeriodicSyncManagerTest,handle_advertising_sync_established_test)254 TEST_F(PeriodicSyncManagerTest, handle_advertising_sync_established_test) {
255   uint16_t sync_handle = 0x12;
256   uint8_t advertiser_sid = 0x02;
257   // start scan
258   Address address;
259   Address::FromString("00:11:22:33:44:55", address);
260   AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);
261   PeriodicSyncStates request{
262       .request_id = 0x01,
263       .advertiser_sid = advertiser_sid,
264       .address_with_type = address_with_type,
265       .sync_handle = sync_handle,
266       .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
267   };
268   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
269   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
270   auto packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
271   auto temp_view = LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
272   ASSERT_TRUE(temp_view.IsValid());
273 
274   // Get command status
275   test_le_scanning_interface_->CommandStatusCallback(
276       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::SUCCESS, 0x00));
277 
278   EXPECT_CALL(mock_callbacks_, OnPeriodicSyncStarted);
279 
280   // Get LePeriodicAdvertisingSyncEstablished
281   auto builder = LePeriodicAdvertisingSyncEstablishedBuilder::Create(
282       ErrorCode::SUCCESS,
283       sync_handle,
284       advertiser_sid,
285       address_with_type.GetAddressType(),
286       address_with_type.GetAddress(),
287       SecondaryPhyType::LE_1M,
288       0xFF,
289       ClockAccuracy::PPM_250);
290   auto event_view = LePeriodicAdvertisingSyncEstablishedView::Create(
291       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder)))));
292   periodic_sync_manager_->HandleLePeriodicAdvertisingSyncEstablished(event_view);
293   sync_handler();
294 }
295 
TEST_F(PeriodicSyncManagerTest,handle_advertising_sync_established_with_public_identity_address_test)296 TEST_F(PeriodicSyncManagerTest, handle_advertising_sync_established_with_public_identity_address_test) {
297   uint16_t sync_handle = 0x12;
298   uint8_t advertiser_sid = 0x02;
299   // start scan
300   Address address;
301   Address::FromString("00:11:22:33:44:55", address);
302   AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);
303   PeriodicSyncStates request{
304       .request_id = 0x01,
305       .advertiser_sid = advertiser_sid,
306       .address_with_type = address_with_type,
307       .sync_handle = sync_handle,
308       .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
309   };
310   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
311   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
312   auto packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
313   auto temp_view = LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
314   ASSERT_TRUE(temp_view.IsValid());
315 
316   // Get command status
317   test_le_scanning_interface_->CommandStatusCallback(
318       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::SUCCESS, 0x00));
319 
320   EXPECT_CALL(mock_callbacks_, OnPeriodicSyncStarted);
321 
322   // Get LePeriodicAdvertisingSyncEstablished with AddressType::PUBLIC_IDENTITY_ADDRESS
323   auto builder = LePeriodicAdvertisingSyncEstablishedBuilder::Create(
324       ErrorCode::SUCCESS,
325       sync_handle,
326       advertiser_sid,
327       AddressType::PUBLIC_IDENTITY_ADDRESS,
328       address_with_type.GetAddress(),
329       SecondaryPhyType::LE_1M,
330       0xFF,
331       ClockAccuracy::PPM_250);
332   auto event_view = LePeriodicAdvertisingSyncEstablishedView::Create(
333       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder)))));
334   periodic_sync_manager_->HandleLePeriodicAdvertisingSyncEstablished(event_view);
335   sync_handler();
336 }
337 
TEST_F(PeriodicSyncManagerTest,stop_sync_test)338 TEST_F(PeriodicSyncManagerTest, stop_sync_test) {
339   uint16_t sync_handle = 0x12;
340   uint8_t advertiser_sid = 0x02;
341   // start scan
342   Address address;
343   Address::FromString("00:11:22:33:44:55", address);
344   AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);
345   PeriodicSyncStates request{
346       .request_id = 0x01,
347       .advertiser_sid = advertiser_sid,
348       .address_with_type = address_with_type,
349       .sync_handle = sync_handle,
350       .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
351   };
352   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
353   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
354   auto packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
355   auto temp_view =
356       LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
357   ASSERT_TRUE(temp_view.IsValid());
358 
359   // Get command status
360   test_le_scanning_interface_->CommandStatusCallback(
361       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::SUCCESS, 0x00));
362 
363   EXPECT_CALL(mock_callbacks_, OnPeriodicSyncStarted);
364 
365   // Get LePeriodicAdvertisingSyncEstablished
366   auto builder = LePeriodicAdvertisingSyncEstablishedBuilder::Create(
367       ErrorCode::SUCCESS,
368       sync_handle,
369       advertiser_sid,
370       address_with_type.GetAddressType(),
371       address_with_type.GetAddress(),
372       SecondaryPhyType::LE_1M,
373       0xFF,
374       ClockAccuracy::PPM_250);
375   auto event_view = LePeriodicAdvertisingSyncEstablishedView::Create(
376       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder)))));
377   periodic_sync_manager_->HandleLePeriodicAdvertisingSyncEstablished(event_view);
378 
379   // StopSync
380   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
381   periodic_sync_manager_->StopSync(sync_handle);
382   packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_TERMINATE_SYNC);
383   auto packet_view = LePeriodicAdvertisingTerminateSyncView::Create(LeScanningCommandView::Create(packet));
384   ASSERT_TRUE(packet_view.IsValid());
385   ASSERT_EQ(sync_handle, packet_view.GetSyncHandle());
386   sync_handler();
387 }
388 
TEST_F(PeriodicSyncManagerTest,cancel_create_sync_test)389 TEST_F(PeriodicSyncManagerTest, cancel_create_sync_test) {
390   uint16_t sync_handle = 0x12;
391   uint8_t advertiser_sid = 0x02;
392   // start scan
393   Address address;
394   Address::FromString("00:11:22:33:44:55", address);
395   AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);
396   PeriodicSyncStates request{
397       .request_id = 0x01,
398       .advertiser_sid = advertiser_sid,
399       .address_with_type = address_with_type,
400       .sync_handle = sync_handle,
401       .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
402   };
403   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
404   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
405   auto packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
406   auto temp_view =
407       LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
408   ASSERT_TRUE(temp_view.IsValid());
409 
410   // Get command status
411   test_le_scanning_interface_->CommandStatusCallback(
412       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::SUCCESS, 0x00));
413 
414   // Cancel crate sync
415   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
416   periodic_sync_manager_->CancelCreateSync(advertiser_sid, address_with_type.GetAddress());
417   packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL);
418   auto packet_view = LePeriodicAdvertisingCreateSyncCancelView::Create(LeScanningCommandView::Create(packet));
419   ASSERT_TRUE(packet_view.IsValid());
420   sync_handler();
421 }
422 
TEST_F(PeriodicSyncManagerTest,transfer_sync_test)423 TEST_F(PeriodicSyncManagerTest, transfer_sync_test) {
424   Address address;
425   Address::FromString("00:11:22:33:44:55", address);
426   uint16_t service_data = 0x10;
427   uint16_t sync_handle = 0x11;
428   uint16_t connection_handle = 0x12;
429   int pa_source = 0x01;
430   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
431   periodic_sync_manager_->TransferSync(address, service_data, sync_handle, pa_source, connection_handle);
432   auto packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_SYNC_TRANSFER);
433   auto packet_view = LePeriodicAdvertisingSyncTransferView::Create(LeScanningCommandView::Create(packet));
434   ASSERT_TRUE(packet_view.IsValid());
435   ASSERT_EQ(connection_handle, packet_view.GetConnectionHandle());
436   ASSERT_EQ(service_data, packet_view.GetServiceData());
437   ASSERT_EQ(sync_handle, packet_view.GetSyncHandle());
438 
439   EXPECT_CALL(mock_callbacks_, OnPeriodicSyncTransferred);
440 
441   // Get command complete
442   test_le_scanning_interface_->CommandCompleteCallback(
443       LePeriodicAdvertisingSyncTransferCompleteBuilder::Create(0x00, ErrorCode::SUCCESS, connection_handle));
444 
445   sync_handler();
446 }
447 
TEST_F(PeriodicSyncManagerTest,sync_set_info_test)448 TEST_F(PeriodicSyncManagerTest, sync_set_info_test) {
449   Address address;
450   Address::FromString("00:11:22:33:44:55", address);
451   uint16_t service_data = 0x10;
452   uint16_t advertising_handle = 0x11;
453   uint16_t connection_handle = 0x12;
454   int pa_source = 0x01;
455   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
456   periodic_sync_manager_->SyncSetInfo(address, service_data, advertising_handle, pa_source, connection_handle);
457   auto packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_SET_INFO_TRANSFER);
458   auto packet_view = LePeriodicAdvertisingSetInfoTransferView::Create(LeScanningCommandView::Create(packet));
459   ASSERT_TRUE(packet_view.IsValid());
460   ASSERT_EQ(connection_handle, packet_view.GetConnectionHandle());
461   ASSERT_EQ(service_data, packet_view.GetServiceData());
462   ASSERT_EQ(advertising_handle, packet_view.GetAdvertisingHandle());
463 
464   EXPECT_CALL(mock_callbacks_, OnPeriodicSyncTransferred);
465 
466   // Get command complete
467   test_le_scanning_interface_->CommandCompleteCallback(
468       LePeriodicAdvertisingSetInfoTransferCompleteBuilder::Create(0x00, ErrorCode::SUCCESS, connection_handle));
469 
470   sync_handler();
471 }
472 
TEST_F(PeriodicSyncManagerTest,sync_tx_parameters_test)473 TEST_F(PeriodicSyncManagerTest, sync_tx_parameters_test) {
474   Address address;
475   Address::FromString("00:11:22:33:44:55", address);
476   uint8_t mode = 0x00;
477   uint16_t skip = 0x11;
478   uint16_t timout = 0x12;
479   int reg_id = 0x01;
480   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
481   periodic_sync_manager_->SyncTxParameters(address, mode, skip, timout, reg_id);
482   auto packet =
483       test_le_scanning_interface_->GetCommand(OpCode::LE_SET_DEFAULT_PERIODIC_ADVERTISING_SYNC_TRANSFER_PARAMETERS);
484   auto packet_view =
485       LeSetDefaultPeriodicAdvertisingSyncTransferParametersView::Create(LeScanningCommandView::Create(packet));
486 
487   ASSERT_TRUE(packet_view.IsValid());
488   ASSERT_EQ(mode, (uint8_t)packet_view.GetMode());
489   ASSERT_EQ(skip, packet_view.GetSkip());
490   ASSERT_EQ(timout, packet_view.GetSyncTimeout());
491 
492   sync_handler();
493 }
494 
TEST_F(PeriodicSyncManagerTest,handle_sync_lost_test)495 TEST_F(PeriodicSyncManagerTest, handle_sync_lost_test) {
496   uint16_t sync_handle = 0x12;
497   uint8_t advertiser_sid = 0x02;
498   // start scan
499   Address address;
500   Address::FromString("00:11:22:33:44:55", address);
501   AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);
502   PeriodicSyncStates request{
503       .request_id = 0x01,
504       .advertiser_sid = advertiser_sid,
505       .address_with_type = address_with_type,
506       .sync_handle = sync_handle,
507       .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
508   };
509   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
510   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
511   auto packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
512   auto temp_view =
513       LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
514   ASSERT_TRUE(temp_view.IsValid());
515 
516   // Get command status
517   test_le_scanning_interface_->CommandStatusCallback(
518       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::SUCCESS, 0x00));
519 
520   EXPECT_CALL(mock_callbacks_, OnPeriodicSyncStarted);
521 
522   // Get LePeriodicAdvertisingSyncEstablished
523   auto builder = LePeriodicAdvertisingSyncEstablishedBuilder::Create(
524       ErrorCode::SUCCESS,
525       sync_handle,
526       advertiser_sid,
527       address_with_type.GetAddressType(),
528       address_with_type.GetAddress(),
529       SecondaryPhyType::LE_1M,
530       0xFF,
531       ClockAccuracy::PPM_250);
532   auto event_view = LePeriodicAdvertisingSyncEstablishedView::Create(
533       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder)))));
534   periodic_sync_manager_->HandleLePeriodicAdvertisingSyncEstablished(event_view);
535 
536   EXPECT_CALL(mock_callbacks_, OnPeriodicSyncLost);
537 
538   // Get LePeriodicAdvertisingSyncLost
539   auto builder2 = LePeriodicAdvertisingSyncLostBuilder::Create(sync_handle);
540 
541   auto event_view2 = LePeriodicAdvertisingSyncLostView::Create(
542       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder2)))));
543   periodic_sync_manager_->HandleLePeriodicAdvertisingSyncLost(event_view2);
544 
545   sync_handler();
546 }
547 
TEST_F_WITH_FLAGS(PeriodicSyncManagerTest,handle_advertising_sync_established_after_error_test,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_broadcast_feature_support)))548 TEST_F_WITH_FLAGS(
549     PeriodicSyncManagerTest,
550     handle_advertising_sync_established_after_error_test,
551     REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT, leaudio_broadcast_feature_support))) {
552   uint16_t sync_handle = 0x12;
553   uint8_t advertiser_sid = 0x02;
554   // start scan
555   Address address;
556   Address::FromString("00:11:22:33:44:55", address);
557   AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);
558 
559   // First request which will finish with error
560   int request_id_1 = 0x01;
561   PeriodicSyncStates request{
562       .request_id = request_id_1,
563       .advertiser_sid = advertiser_sid,
564       .address_with_type = address_with_type,
565       .sync_handle = sync_handle,
566       .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
567   };
568   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
569   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
570   auto packet =
571       test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
572   auto temp_view =
573       LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
574   ASSERT_TRUE(temp_view.IsValid());
575 
576   // Get command status
577   test_le_scanning_interface_->CommandStatusCallback(
578       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::SUCCESS, 0x00));
579 
580   EXPECT_CALL(
581       mock_callbacks_,
582       OnPeriodicSyncStarted(
583           request_id_1,
584           static_cast<uint8_t>(ErrorCode::CONNECTION_FAILED_ESTABLISHMENT),
585           _,
586           _,
587           _,
588           _,
589           _))
590       .Times(1);
591 
592   // Get LePeriodicAdvertisingSyncEstablished
593   auto builder = LePeriodicAdvertisingSyncEstablishedBuilder::Create(
594       ErrorCode::CONNECTION_FAILED_ESTABLISHMENT,
595       sync_handle,
596       advertiser_sid,
597       address_with_type.GetAddressType(),
598       address_with_type.GetAddress(),
599       SecondaryPhyType::LE_1M,
600       0xFF,
601       ClockAccuracy::PPM_250);
602   auto event_view = LePeriodicAdvertisingSyncEstablishedView::Create(
603       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder)))));
604   periodic_sync_manager_->HandleLePeriodicAdvertisingSyncEstablished(event_view);
605 
606   // Second request with the same data but different id
607   int request_id_2 = 0x02;
608   request.request_id = request_id_2;
609   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
610   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
611   packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
612   temp_view = LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
613   ASSERT_TRUE(temp_view.IsValid());
614 
615   // Get command status
616   test_le_scanning_interface_->CommandStatusCallback(
617       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::SUCCESS, 0x00));
618 
619   EXPECT_CALL(
620       mock_callbacks_,
621       OnPeriodicSyncStarted(request_id_2, static_cast<uint8_t>(ErrorCode::SUCCESS), _, _, _, _, _))
622       .Times(1);
623 
624   // Get LePeriodicAdvertisingSyncEstablished
625   auto builder2 = LePeriodicAdvertisingSyncEstablishedBuilder::Create(
626       ErrorCode::SUCCESS,
627       sync_handle,
628       advertiser_sid,
629       address_with_type.GetAddressType(),
630       address_with_type.GetAddress(),
631       SecondaryPhyType::LE_1M,
632       0xFF,
633       ClockAccuracy::PPM_250);
634   event_view = LePeriodicAdvertisingSyncEstablishedView::Create(
635       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder2)))));
636   periodic_sync_manager_->HandleLePeriodicAdvertisingSyncEstablished(event_view);
637 
638   sync_handler();
639 }
640 
TEST_F_WITH_FLAGS(PeriodicSyncManagerTest,handle_advertising_sync_established_after_create_command_error_test,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_broadcast_assistant_handle_command_statuses)))641 TEST_F_WITH_FLAGS(
642     PeriodicSyncManagerTest,
643     handle_advertising_sync_established_after_create_command_error_test,
644     REQUIRES_FLAGS_ENABLED(
645         ACONFIG_FLAG(TEST_BT, leaudio_broadcast_assistant_handle_command_statuses))) {
646   uint16_t sync_handle = 0x12;
647   Address address;
648   Address::FromString("00:11:22:33:44:55", address);
649   AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);
650 
651   // First request which will finish with error
652   int request_id_1 = 0x01;
653   uint8_t advertiser_sid_1 = 0x02;
654   PeriodicSyncStates request{
655       .request_id = request_id_1,
656       .advertiser_sid = advertiser_sid_1,
657       .address_with_type = address_with_type,
658       .sync_handle = sync_handle,
659       .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
660   };
661   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
662   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
663   auto packet =
664       test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
665   auto temp_view =
666       LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
667   ASSERT_TRUE(temp_view.IsValid());
668 
669   EXPECT_CALL(
670       mock_callbacks_,
671       OnPeriodicSyncStarted(
672           request_id_1,
673           static_cast<uint8_t>(ErrorCode::MEMORY_CAPACITY_EXCEEDED),
674           _,
675           advertiser_sid_1,
676           _,
677           _,
678           _))
679       .Times(1);
680 
681   // Get command status
682   test_le_scanning_interface_->CommandStatusCallback(
683       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(
684           ErrorCode::MEMORY_CAPACITY_EXCEEDED, 0x00));
685 
686   // Second request
687   int request_id_2 = 0x02;
688   uint8_t advertiser_sid_2 = 0x03;
689   request.request_id = request_id_2;
690   request.advertiser_sid = advertiser_sid_2;
691   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
692   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
693   packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
694   temp_view = LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
695   ASSERT_TRUE(temp_view.IsValid());
696 
697   // Get command status
698   test_le_scanning_interface_->CommandStatusCallback(
699       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::SUCCESS, 0x00));
700 
701   EXPECT_CALL(
702       mock_callbacks_,
703       OnPeriodicSyncStarted(
704           request_id_2, static_cast<uint8_t>(ErrorCode::SUCCESS), _, advertiser_sid_2, _, _, _))
705       .Times(1);
706 
707   // Get LePeriodicAdvertisingSyncEstablished
708   auto builder = LePeriodicAdvertisingSyncEstablishedBuilder::Create(
709       ErrorCode::SUCCESS,
710       sync_handle,
711       advertiser_sid_2,
712       address_with_type.GetAddressType(),
713       address_with_type.GetAddress(),
714       SecondaryPhyType::LE_1M,
715       0xFF,
716       ClockAccuracy::PPM_250);
717   auto event_view = LePeriodicAdvertisingSyncEstablishedView::Create(
718       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder)))));
719   periodic_sync_manager_->HandleLePeriodicAdvertisingSyncEstablished(event_view);
720 
721   sync_handler();
722 }
723 
TEST_F_WITH_FLAGS(PeriodicSyncManagerTest,handle_advertising_sync_established_after_cancel_command_error_test,REQUIRES_FLAGS_ENABLED (ACONFIG_FLAG (TEST_BT,leaudio_broadcast_assistant_handle_command_statuses)))724 TEST_F_WITH_FLAGS(
725     PeriodicSyncManagerTest,
726     handle_advertising_sync_established_after_cancel_command_error_test,
727     REQUIRES_FLAGS_ENABLED(
728         ACONFIG_FLAG(TEST_BT, leaudio_broadcast_assistant_handle_command_statuses))) {
729   uint16_t sync_handle = 0x12;
730   Address address;
731   Address::FromString("00:11:22:33:44:55", address);
732   AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);
733 
734   // First request which will finish with timeout error
735   uint8_t advertiser_sid_1 = 0x02;
736   int request_id_1 = 0x01;
737   PeriodicSyncStates request{
738       .request_id = request_id_1,
739       .advertiser_sid = advertiser_sid_1,
740       .address_with_type = address_with_type,
741       .sync_handle = sync_handle,
742       .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
743   };
744   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
745   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
746   auto packet =
747       test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
748   auto temp_view =
749       LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
750   ASSERT_TRUE(temp_view.IsValid());
751 
752   // Get command status
753   test_le_scanning_interface_->CommandStatusCallback(
754       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::SUCCESS, 0x00));
755 
756   EXPECT_CALL(
757       mock_callbacks_,
758       OnPeriodicSyncStarted(
759           request_id_1,
760           static_cast<uint8_t>(ErrorCode::ADVERTISING_TIMEOUT),
761           _,
762           advertiser_sid_1,
763           _,
764           _,
765           _))
766       .Times(1);
767 
768   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
769   periodic_sync_manager_->OnStartSyncTimeout();
770   packet =
771       test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL);
772   auto temp_view2 =
773       LePeriodicAdvertisingCreateSyncCancelView::Create(LeScanningCommandView::Create(packet));
774   ASSERT_TRUE(temp_view2.IsValid());
775 
776   // Get command status
777   test_le_scanning_interface_->CommandCompleteCallback(
778       LePeriodicAdvertisingCreateSyncCancelCompleteBuilder::Create(
779           0x00, ErrorCode::COMMAND_DISALLOWED));
780 
781   // Second request
782   int request_id_2 = 0x02;
783   uint8_t advertiser_sid_2 = 0x03;
784   request.request_id = request_id_2;
785   request.advertiser_sid = advertiser_sid_2;
786   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
787   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
788   packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
789   temp_view = LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
790   ASSERT_TRUE(temp_view.IsValid());
791 
792   // Get command status
793   test_le_scanning_interface_->CommandStatusCallback(
794       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::SUCCESS, 0x00));
795 
796   EXPECT_CALL(
797       mock_callbacks_,
798       OnPeriodicSyncStarted(
799           request_id_2, static_cast<uint8_t>(ErrorCode::SUCCESS), _, advertiser_sid_2, _, _, _))
800       .Times(1);
801 
802   // Get LePeriodicAdvertisingSyncEstablished
803   auto builder2 = LePeriodicAdvertisingSyncEstablishedBuilder::Create(
804       ErrorCode::SUCCESS,
805       sync_handle,
806       advertiser_sid_2,
807       address_with_type.GetAddressType(),
808       address_with_type.GetAddress(),
809       SecondaryPhyType::LE_1M,
810       0xFF,
811       ClockAccuracy::PPM_250);
812   auto event_view = LePeriodicAdvertisingSyncEstablishedView::Create(
813       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder2)))));
814   periodic_sync_manager_->HandleLePeriodicAdvertisingSyncEstablished(event_view);
815 
816   sync_handler();
817 }
818 
TEST_F(PeriodicSyncManagerTest,handle_periodic_advertising_report_test)819 TEST_F(PeriodicSyncManagerTest, handle_periodic_advertising_report_test) {
820   uint16_t sync_handle = 0x12;
821   uint8_t advertiser_sid = 0x02;
822   // start scan
823   Address address;
824   Address::FromString("00:11:22:33:44:55", address);
825   AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);
826   PeriodicSyncStates request{
827       .request_id = 0x01,
828       .advertiser_sid = advertiser_sid,
829       .address_with_type = address_with_type,
830       .sync_handle = sync_handle,
831       .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
832   };
833   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
834   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
835   auto packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
836   auto temp_view =
837       LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
838   ASSERT_TRUE(temp_view.IsValid());
839 
840   // Get command status
841   test_le_scanning_interface_->CommandStatusCallback(
842       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::SUCCESS, 0x00));
843 
844   EXPECT_CALL(mock_callbacks_, OnPeriodicSyncStarted);
845 
846   // Get LePeriodicAdvertisingSyncEstablished
847   auto builder = LePeriodicAdvertisingSyncEstablishedBuilder::Create(
848       ErrorCode::SUCCESS,
849       sync_handle,
850       advertiser_sid,
851       address_with_type.GetAddressType(),
852       address_with_type.GetAddress(),
853       SecondaryPhyType::LE_1M,
854       0xFF,
855       ClockAccuracy::PPM_250);
856   auto event_view = LePeriodicAdvertisingSyncEstablishedView::Create(
857       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder)))));
858   periodic_sync_manager_->HandleLePeriodicAdvertisingSyncEstablished(event_view);
859 
860   EXPECT_CALL(mock_callbacks_, OnPeriodicSyncReport);
861 
862   // Get LePeriodicAdvertisingReport
863   std::vector<uint8_t> data = {0x01, 0x02, 0x03};
864   auto builder2 = LePeriodicAdvertisingReportBuilder::Create(
865       sync_handle, 0x1a, 0x1a, CteType::AOA_CONSTANT_TONE_EXTENSION, DataStatus::COMPLETE, data);
866 
867   auto event_view2 = LePeriodicAdvertisingReportView::Create(
868       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder2)))));
869   periodic_sync_manager_->HandleLePeriodicAdvertisingReport(event_view2);
870 
871   sync_handler();
872 }
873 
TEST_F(PeriodicSyncManagerTest,handle_biginfo_advertising_report_test)874 TEST_F(PeriodicSyncManagerTest, handle_biginfo_advertising_report_test) {
875   uint16_t sync_handle = 0x12;
876   uint8_t advertiser_sid = 0x02;
877 // start scan
878   Address address;
879   Address::FromString("00:11:22:33:44:55", address);
880   AddressWithType address_with_type = AddressWithType(address, AddressType::PUBLIC_DEVICE_ADDRESS);
881   PeriodicSyncStates request{
882       .request_id = 0x01,
883       .advertiser_sid = advertiser_sid,
884       .address_with_type = address_with_type,
885       .sync_handle = sync_handle,
886       .sync_state = PeriodicSyncState::PERIODIC_SYNC_STATE_IDLE,
887   };
888   ASSERT_NO_FATAL_FAILURE(test_le_scanning_interface_->SetCommandFuture());
889   periodic_sync_manager_->StartSync(request, 0x04, 0x0A);
890   auto packet = test_le_scanning_interface_->GetCommand(OpCode::LE_PERIODIC_ADVERTISING_CREATE_SYNC);
891   auto temp_view =
892       LePeriodicAdvertisingCreateSyncView::Create(LeScanningCommandView::Create(packet));
893   ASSERT_TRUE(temp_view.IsValid());
894 
895   // Get command status
896   test_le_scanning_interface_->CommandStatusCallback(
897       LePeriodicAdvertisingCreateSyncStatusBuilder::Create(ErrorCode::SUCCESS, 0x00));
898 
899   EXPECT_CALL(mock_callbacks_, OnPeriodicSyncStarted);
900 
901   // Get LePeriodicAdvertisingSyncEstablished
902   auto builder = LePeriodicAdvertisingSyncEstablishedBuilder::Create(
903       ErrorCode::SUCCESS,
904       sync_handle,
905       advertiser_sid,
906       address_with_type.GetAddressType(),
907       address_with_type.GetAddress(),
908       SecondaryPhyType::LE_1M,
909       0xFF,
910       ClockAccuracy::PPM_250);
911   auto event_view = LePeriodicAdvertisingSyncEstablishedView::Create(
912       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder)))));
913   periodic_sync_manager_->HandleLePeriodicAdvertisingSyncEstablished(event_view);
914 
915   EXPECT_CALL(mock_callbacks_, OnBigInfoReport);
916 
917   // Get LeBigInfoAdvertisingReport
918   auto builder2 = LeBigInfoAdvertisingReportBuilder::Create(
919       sync_handle, 2, 9, 24, 3, 1, 2, 100, 10000, 100, static_cast<SecondaryPhyType>(2),
920       static_cast<Enable> (0), static_cast<Enable> (1));
921 
922   auto event_view2 = LeBigInfoAdvertisingReportView::Create(
923       LeMetaEventView::Create(EventView::Create(GetPacketView(std::move(builder2)))));
924   periodic_sync_manager_->HandleLeBigInfoAdvertisingReport(event_view2);
925 
926   sync_handler();
927 }
928 
929 }  // namespace
930 }  // namespace hci
931 }  // namespace bluetooth
932