/* * Copyright 2019 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "hci/hci_layer.h" #include #include #include #include "hal/hci_hal.h" #include "hci/hci_packets.h" #include "module.h" #include "os/log.h" #include "os/thread.h" #include "packet/bit_inserter.h" #include "packet/raw_builder.h" using bluetooth::os::Thread; using bluetooth::packet::BitInserter; using bluetooth::packet::RawBuilder; using std::vector; namespace { vector information_request = { 0xfe, 0x2e, 0x0a, 0x00, 0x06, 0x00, 0x01, 0x00, 0x0a, 0x02, 0x02, 0x00, 0x02, 0x00, }; // 0x00, 0x01, 0x02, 0x03, ... vector counting_bytes; // 0xFF, 0xFE, 0xFD, 0xFC, ... vector counting_down_bytes; const size_t count_size = 0x8; } // namespace namespace bluetooth { namespace hci { constexpr std::chrono::milliseconds kTimeout = HciLayer::kHciTimeoutMs / 2; constexpr std::chrono::milliseconds kAclTimeout = std::chrono::milliseconds(1000); class TestHciHal : public hal::HciHal { public: TestHciHal() : hal::HciHal() {} ~TestHciHal() { ASSERT_LOG(callbacks == nullptr, "unregisterIncomingPacketCallback() must be called"); } void registerIncomingPacketCallback(hal::HciHalCallbacks* callback) override { callbacks = callback; } void unregisterIncomingPacketCallback() override { callbacks = nullptr; } void sendHciCommand(hal::HciPacket command) override { outgoing_commands_.push_back(std::move(command)); if (sent_command_promise_ != nullptr) { auto promise = std::move(sent_command_promise_); sent_command_promise_.reset(); promise->set_value(); } } void sendAclData(hal::HciPacket data) override { outgoing_acl_.push_front(std::move(data)); if (sent_acl_promise_ != nullptr) { auto promise = std::move(sent_acl_promise_); sent_acl_promise_.reset(); promise->set_value(); } } void sendScoData(hal::HciPacket data) override { outgoing_sco_.push_front(std::move(data)); } hal::HciHalCallbacks* callbacks = nullptr; PacketView GetPacketView(hal::HciPacket data) { auto shared = std::make_shared>(data); return PacketView(shared); } size_t GetNumSentCommands() { return outgoing_commands_.size(); } std::future GetSentCommandFuture() { ASSERT_LOG(sent_command_promise_ == nullptr, "Promises promises ... Only one at a time"); sent_command_promise_ = std::make_unique>(); return sent_command_promise_->get_future(); } CommandPacketView GetSentCommand() { auto packetview = GetPacketView(std::move(outgoing_commands_.front())); outgoing_commands_.pop_front(); return CommandPacketView::Create(packetview); } std::future GetSentAclFuture() { ASSERT_LOG(sent_acl_promise_ == nullptr, "Promises promises ... Only one at a time"); sent_acl_promise_ = std::make_unique>(); return sent_acl_promise_->get_future(); } PacketView GetSentAcl() { auto packetview = GetPacketView(std::move(outgoing_acl_.front())); outgoing_acl_.pop_front(); return packetview; } void Start() {} void Stop() {} void ListDependencies(ModuleList*) {} static const ModuleFactory Factory; private: std::list outgoing_commands_; std::list outgoing_acl_; std::list outgoing_sco_; std::unique_ptr> sent_command_promise_; std::unique_ptr> sent_acl_promise_; }; const ModuleFactory TestHciHal::Factory = ModuleFactory([]() { return new TestHciHal(); }); class DependsOnHci : public Module { public: DependsOnHci() : Module() {} void SendHciCommandExpectingStatus(std::unique_ptr command) { hci_->EnqueueCommand(std::move(command), GetHandler()->BindOnceOn(this, &DependsOnHci::handle_event)); } void SendHciCommandExpectingComplete(std::unique_ptr command) { hci_->EnqueueCommand(std::move(command), GetHandler()->BindOnceOn(this, &DependsOnHci::handle_event)); } void SendSecurityCommandExpectingComplete(std::unique_ptr command) { if (security_interface_ == nullptr) { security_interface_ = hci_->GetSecurityInterface(GetHandler()->BindOn(this, &DependsOnHci::handle_event)); } hci_->EnqueueCommand(std::move(command), GetHandler()->BindOnceOn(this, &DependsOnHci::handle_event)); } void SendLeSecurityCommandExpectingComplete(std::unique_ptr command) { if (le_security_interface_ == nullptr) { le_security_interface_ = hci_->GetLeSecurityInterface(GetHandler()->BindOn(this, &DependsOnHci::handle_event)); } hci_->EnqueueCommand(std::move(command), GetHandler()->BindOnceOn(this, &DependsOnHci::handle_event)); } void SendAclData(std::unique_ptr acl) { outgoing_acl_.push(std::move(acl)); auto queue_end = hci_->GetAclQueueEnd(); queue_end->RegisterEnqueue(GetHandler(), common::Bind(&DependsOnHci::handle_enqueue, common::Unretained(this))); } std::future GetReceivedEventFuture() { ASSERT_LOG(event_promise_ == nullptr, "Promises promises ... Only one at a time"); event_promise_ = std::make_unique>(); return event_promise_->get_future(); } EventPacketView GetReceivedEvent() { EventPacketView packetview = incoming_events_.front(); incoming_events_.pop_front(); return packetview; } std::future GetReceivedAclFuture() { ASSERT_LOG(acl_promise_ == nullptr, "Promises promises ... Only one at a time"); acl_promise_ = std::make_unique>(); return acl_promise_->get_future(); } size_t GetNumReceivedAclPackets() { return incoming_acl_packets_.size(); } AclPacketView GetReceivedAcl() { AclPacketView packetview = incoming_acl_packets_.front(); incoming_acl_packets_.pop_front(); return packetview; } void Start() { hci_ = GetDependency(); hci_->RegisterEventHandler(EventCode::CONNECTION_COMPLETE, GetHandler()->BindOn(this, &DependsOnHci::handle_event)); hci_->RegisterLeEventHandler(SubeventCode::CONNECTION_COMPLETE, GetHandler()->BindOn(this, &DependsOnHci::handle_event)); hci_->GetAclQueueEnd()->RegisterDequeue(GetHandler(), common::Bind(&DependsOnHci::handle_acl, common::Unretained(this))); } void Stop() { hci_->GetAclQueueEnd()->UnregisterDequeue(); } void ListDependencies(ModuleList* list) { list->add(); } static const ModuleFactory Factory; private: HciLayer* hci_ = nullptr; const SecurityInterface* security_interface_; const LeSecurityInterface* le_security_interface_; std::list incoming_events_; std::list incoming_acl_packets_; std::unique_ptr> event_promise_; std::unique_ptr> acl_promise_; void handle_acl() { auto acl_ptr = hci_->GetAclQueueEnd()->TryDequeue(); incoming_acl_packets_.push_back(*acl_ptr); if (acl_promise_ != nullptr) { auto promise = std::move(acl_promise_); acl_promise_.reset(); promise->set_value(); } } template void handle_event(T event) { incoming_events_.push_back(event); if (event_promise_ != nullptr) { auto promise = std::move(event_promise_); event_promise_.reset(); promise->set_value(); } } std::queue> outgoing_acl_; std::unique_ptr handle_enqueue() { hci_->GetAclQueueEnd()->UnregisterEnqueue(); auto acl = std::move(outgoing_acl_.front()); outgoing_acl_.pop(); return acl; } }; const ModuleFactory DependsOnHci::Factory = ModuleFactory([]() { return new DependsOnHci(); }); class HciTest : public ::testing::Test { public: void SetUp() override { counting_bytes.reserve(count_size); counting_down_bytes.reserve(count_size); for (size_t i = 0; i < count_size; i++) { counting_bytes.push_back(i); counting_down_bytes.push_back(~i); } hal = new TestHciHal(); auto command_future = hal->GetSentCommandFuture(); fake_registry_.InjectTestModule(&hal::HciHal::Factory, hal); fake_registry_.Start(&fake_registry_.GetTestThread()); hci = static_cast(fake_registry_.GetModuleUnderTest(&HciLayer::Factory)); upper = static_cast(fake_registry_.GetModuleUnderTest(&DependsOnHci::Factory)); ASSERT_TRUE(fake_registry_.IsStarted()); auto reset_sent_status = command_future.wait_for(kTimeout); ASSERT_EQ(reset_sent_status, std::future_status::ready); // Verify that reset was received ASSERT_EQ(1, hal->GetNumSentCommands()); auto sent_command = hal->GetSentCommand(); auto reset_view = ResetView::Create(CommandPacketView::Create(sent_command)); ASSERT_TRUE(reset_view.IsValid()); // Verify that only one was sent ASSERT_EQ(0, hal->GetNumSentCommands()); // Send the response event uint8_t num_packets = 1; ErrorCode error_code = ErrorCode::SUCCESS; hal->callbacks->hciEventReceived(GetPacketBytes(ResetCompleteBuilder::Create(num_packets, error_code))); } void TearDown() override { fake_registry_.StopAll(); } std::vector GetPacketBytes(std::unique_ptr packet) { std::vector bytes; BitInserter i(bytes); bytes.reserve(packet->size()); packet->Serialize(i); return bytes; } DependsOnHci* upper = nullptr; TestHciHal* hal = nullptr; HciLayer* hci = nullptr; TestModuleRegistry fake_registry_; }; TEST_F(HciTest, initAndClose) {} TEST_F(HciTest, leMetaEvent) { auto event_future = upper->GetReceivedEventFuture(); // Send an LE event ErrorCode status = ErrorCode::SUCCESS; uint16_t handle = 0x123; Role role = Role::MASTER; AddressType peer_address_type = AddressType::PUBLIC_DEVICE_ADDRESS; Address peer_address = Address::kAny; uint16_t conn_interval = 0x0ABC; uint16_t conn_latency = 0x0123; uint16_t supervision_timeout = 0x0B05; ClockAccuracy master_clock_accuracy = ClockAccuracy::PPM_50; hal->callbacks->hciEventReceived(GetPacketBytes( LeConnectionCompleteBuilder::Create(status, handle, role, peer_address_type, peer_address, conn_interval, conn_latency, supervision_timeout, master_clock_accuracy))); // Wait for the event auto event_status = event_future.wait_for(kTimeout); ASSERT_EQ(event_status, std::future_status::ready); auto event = upper->GetReceivedEvent(); ASSERT_TRUE(LeConnectionCompleteView::Create(LeMetaEventView::Create(EventPacketView::Create(event))).IsValid()); } TEST_F(HciTest, noOpCredits) { ASSERT_EQ(0, hal->GetNumSentCommands()); // Send 0 credits uint8_t num_packets = 0; hal->callbacks->hciEventReceived(GetPacketBytes(NoCommandCompleteBuilder::Create(num_packets))); auto command_future = hal->GetSentCommandFuture(); upper->SendHciCommandExpectingComplete(ReadLocalVersionInformationBuilder::Create()); // Verify that nothing was sent ASSERT_EQ(0, hal->GetNumSentCommands()); num_packets = 1; hal->callbacks->hciEventReceived(GetPacketBytes(NoCommandCompleteBuilder::Create(num_packets))); auto command_sent_status = command_future.wait_for(kTimeout); ASSERT_EQ(command_sent_status, std::future_status::ready); // Verify that one was sent ASSERT_EQ(1, hal->GetNumSentCommands()); auto event_future = upper->GetReceivedEventFuture(); // Send the response event ErrorCode error_code = ErrorCode::SUCCESS; LocalVersionInformation local_version_information; local_version_information.hci_version_ = HciVersion::V_5_0; local_version_information.hci_revision_ = 0x1234; local_version_information.lmp_version_ = LmpVersion::V_4_2; local_version_information.manufacturer_name_ = 0xBAD; local_version_information.lmp_subversion_ = 0x5678; hal->callbacks->hciEventReceived(GetPacketBytes( ReadLocalVersionInformationCompleteBuilder::Create(num_packets, error_code, local_version_information))); // Wait for the event auto event_status = event_future.wait_for(kTimeout); ASSERT_EQ(event_status, std::future_status::ready); auto event = upper->GetReceivedEvent(); ASSERT_TRUE( ReadLocalVersionInformationCompleteView::Create(CommandCompleteView::Create(EventPacketView::Create(event))) .IsValid()); } TEST_F(HciTest, creditsTest) { ASSERT_EQ(0, hal->GetNumSentCommands()); auto command_future = hal->GetSentCommandFuture(); // Send all three commands upper->SendHciCommandExpectingComplete(ReadLocalVersionInformationBuilder::Create()); upper->SendHciCommandExpectingComplete(ReadLocalSupportedCommandsBuilder::Create()); upper->SendHciCommandExpectingComplete(ReadLocalSupportedFeaturesBuilder::Create()); auto command_sent_status = command_future.wait_for(kTimeout); ASSERT_EQ(command_sent_status, std::future_status::ready); // Verify that the first one is sent ASSERT_EQ(1, hal->GetNumSentCommands()); auto sent_command = hal->GetSentCommand(); auto version_view = ReadLocalVersionInformationView::Create(CommandPacketView::Create(sent_command)); ASSERT_TRUE(version_view.IsValid()); // Verify that only one was sent ASSERT_EQ(0, hal->GetNumSentCommands()); // Get a new future auto event_future = upper->GetReceivedEventFuture(); // Send the response event uint8_t num_packets = 1; ErrorCode error_code = ErrorCode::SUCCESS; LocalVersionInformation local_version_information; local_version_information.hci_version_ = HciVersion::V_5_0; local_version_information.hci_revision_ = 0x1234; local_version_information.lmp_version_ = LmpVersion::V_4_2; local_version_information.manufacturer_name_ = 0xBAD; local_version_information.lmp_subversion_ = 0x5678; hal->callbacks->hciEventReceived(GetPacketBytes( ReadLocalVersionInformationCompleteBuilder::Create(num_packets, error_code, local_version_information))); // Wait for the event auto event_status = event_future.wait_for(kTimeout); ASSERT_EQ(event_status, std::future_status::ready); auto event = upper->GetReceivedEvent(); ASSERT_TRUE( ReadLocalVersionInformationCompleteView::Create(CommandCompleteView::Create(EventPacketView::Create(event))) .IsValid()); // Verify that the second one is sent command_sent_status = command_future.wait_for(kTimeout); ASSERT_EQ(command_sent_status, std::future_status::ready); ASSERT_EQ(1, hal->GetNumSentCommands()); sent_command = hal->GetSentCommand(); auto supported_commands_view = ReadLocalSupportedCommandsView::Create(CommandPacketView::Create(sent_command)); ASSERT_TRUE(supported_commands_view.IsValid()); // Verify that only one was sent ASSERT_EQ(0, hal->GetNumSentCommands()); event_future = upper->GetReceivedEventFuture(); command_future = hal->GetSentCommandFuture(); // Send the response event std::array supported_commands; for (uint8_t i = 0; i < 64; i++) { supported_commands[i] = i; } hal->callbacks->hciEventReceived( GetPacketBytes(ReadLocalSupportedCommandsCompleteBuilder::Create(num_packets, error_code, supported_commands))); // Wait for the event event_status = event_future.wait_for(kTimeout); ASSERT_EQ(event_status, std::future_status::ready); event = upper->GetReceivedEvent(); ASSERT_TRUE( ReadLocalSupportedCommandsCompleteView::Create(CommandCompleteView::Create(EventPacketView::Create(event))) .IsValid()); // Verify that the third one is sent command_sent_status = command_future.wait_for(kTimeout); ASSERT_EQ(command_sent_status, std::future_status::ready); ASSERT_EQ(1, hal->GetNumSentCommands()); sent_command = hal->GetSentCommand(); auto supported_features_view = ReadLocalSupportedFeaturesView::Create(CommandPacketView::Create(sent_command)); ASSERT_TRUE(supported_features_view.IsValid()); // Verify that only one was sent ASSERT_EQ(0, hal->GetNumSentCommands()); event_future = upper->GetReceivedEventFuture(); // Send the response event uint64_t lmp_features = 0x012345678abcdef; hal->callbacks->hciEventReceived( GetPacketBytes(ReadLocalSupportedFeaturesCompleteBuilder::Create(num_packets, error_code, lmp_features))); // Wait for the event event_status = event_future.wait_for(kTimeout); ASSERT_EQ(event_status, std::future_status::ready); event = upper->GetReceivedEvent(); ASSERT_TRUE( ReadLocalSupportedFeaturesCompleteView::Create(CommandCompleteView::Create(EventPacketView::Create(event))) .IsValid()); } TEST_F(HciTest, leSecurityInterfaceTest) { // Send LeRand to the controller auto command_future = hal->GetSentCommandFuture(); upper->SendLeSecurityCommandExpectingComplete(LeRandBuilder::Create()); auto command_sent_status = command_future.wait_for(kTimeout); ASSERT_EQ(command_sent_status, std::future_status::ready); // Check the command auto sent_command = hal->GetSentCommand(); ASSERT_LT(0, sent_command.size()); LeRandView view = LeRandView::Create(LeSecurityCommandView::Create(CommandPacketView::Create(sent_command))); ASSERT_TRUE(view.IsValid()); // Send a Command Complete to the host auto event_future = upper->GetReceivedEventFuture(); uint8_t num_packets = 1; ErrorCode status = ErrorCode::SUCCESS; uint64_t rand = 0x0123456789abcdef; hal->callbacks->hciEventReceived(GetPacketBytes(LeRandCompleteBuilder::Create(num_packets, status, rand))); // Verify the event auto event_status = event_future.wait_for(kTimeout); ASSERT_EQ(event_status, std::future_status::ready); auto event = upper->GetReceivedEvent(); ASSERT_TRUE(event.IsValid()); ASSERT_EQ(EventCode::COMMAND_COMPLETE, event.GetEventCode()); ASSERT_TRUE(LeRandCompleteView::Create(CommandCompleteView::Create(event)).IsValid()); } TEST_F(HciTest, securityInterfacesTest) { // Send WriteSimplePairingMode to the controller auto command_future = hal->GetSentCommandFuture(); Enable enable = Enable::ENABLED; upper->SendSecurityCommandExpectingComplete(WriteSimplePairingModeBuilder::Create(enable)); auto command_sent_status = command_future.wait_for(kTimeout); ASSERT_EQ(command_sent_status, std::future_status::ready); // Check the command auto sent_command = hal->GetSentCommand(); ASSERT_LT(0, sent_command.size()); auto view = WriteSimplePairingModeView::Create(SecurityCommandView::Create(CommandPacketView::Create(sent_command))); ASSERT_TRUE(view.IsValid()); // Send a Command Complete to the host auto event_future = upper->GetReceivedEventFuture(); uint8_t num_packets = 1; ErrorCode status = ErrorCode::SUCCESS; hal->callbacks->hciEventReceived(GetPacketBytes(WriteSimplePairingModeCompleteBuilder::Create(num_packets, status))); // Verify the event auto event_status = event_future.wait_for(kTimeout); ASSERT_EQ(event_status, std::future_status::ready); auto event = upper->GetReceivedEvent(); ASSERT_TRUE(event.IsValid()); ASSERT_EQ(EventCode::COMMAND_COMPLETE, event.GetEventCode()); ASSERT_TRUE(WriteSimplePairingModeCompleteView::Create(CommandCompleteView::Create(event)).IsValid()); } TEST_F(HciTest, createConnectionTest) { // Send CreateConnection to the controller auto command_future = hal->GetSentCommandFuture(); Address bd_addr; ASSERT_TRUE(Address::FromString("A1:A2:A3:A4:A5:A6", bd_addr)); uint16_t packet_type = 0x1234; PageScanRepetitionMode page_scan_repetition_mode = PageScanRepetitionMode::R0; uint16_t clock_offset = 0x3456; ClockOffsetValid clock_offset_valid = ClockOffsetValid::VALID; CreateConnectionRoleSwitch allow_role_switch = CreateConnectionRoleSwitch::ALLOW_ROLE_SWITCH; upper->SendHciCommandExpectingStatus(CreateConnectionBuilder::Create( bd_addr, packet_type, page_scan_repetition_mode, clock_offset, clock_offset_valid, allow_role_switch)); auto command_sent_status = command_future.wait_for(kTimeout); ASSERT_EQ(command_sent_status, std::future_status::ready); // Check the command auto sent_command = hal->GetSentCommand(); ASSERT_LT(0, sent_command.size()); CreateConnectionView view = CreateConnectionView::Create(ConnectionManagementCommandView::Create(CommandPacketView::Create(sent_command))); ASSERT_TRUE(view.IsValid()); ASSERT_EQ(bd_addr, view.GetBdAddr()); ASSERT_EQ(packet_type, view.GetPacketType()); ASSERT_EQ(page_scan_repetition_mode, view.GetPageScanRepetitionMode()); ASSERT_EQ(clock_offset, view.GetClockOffset()); ASSERT_EQ(clock_offset_valid, view.GetClockOffsetValid()); ASSERT_EQ(allow_role_switch, view.GetAllowRoleSwitch()); // Send a Command Status to the host auto event_future = upper->GetReceivedEventFuture(); ErrorCode status = ErrorCode::SUCCESS; uint16_t handle = 0x123; LinkType link_type = LinkType::ACL; Enable encryption_enabled = Enable::DISABLED; hal->callbacks->hciEventReceived(GetPacketBytes(CreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 1))); // Verify the event auto event_status = event_future.wait_for(kTimeout); ASSERT_EQ(event_status, std::future_status::ready); auto event = upper->GetReceivedEvent(); ASSERT_TRUE(event.IsValid()); ASSERT_EQ(EventCode::COMMAND_STATUS, event.GetEventCode()); // Send a ConnectionComplete to the host event_future = upper->GetReceivedEventFuture(); hal->callbacks->hciEventReceived( GetPacketBytes(ConnectionCompleteBuilder::Create(status, handle, bd_addr, link_type, encryption_enabled))); // Verify the event event_status = event_future.wait_for(kTimeout); ASSERT_EQ(event_status, std::future_status::ready); event = upper->GetReceivedEvent(); ASSERT_TRUE(event.IsValid()); ASSERT_EQ(EventCode::CONNECTION_COMPLETE, event.GetEventCode()); ConnectionCompleteView connection_complete_view = ConnectionCompleteView::Create(event); ASSERT_TRUE(connection_complete_view.IsValid()); ASSERT_EQ(status, connection_complete_view.GetStatus()); ASSERT_EQ(handle, connection_complete_view.GetConnectionHandle()); ASSERT_EQ(link_type, connection_complete_view.GetLinkType()); ASSERT_EQ(encryption_enabled, connection_complete_view.GetEncryptionEnabled()); // Send an ACL packet from the remote PacketBoundaryFlag packet_boundary_flag = PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE; BroadcastFlag broadcast_flag = BroadcastFlag::POINT_TO_POINT; auto acl_payload = std::make_unique(); acl_payload->AddAddress(bd_addr); acl_payload->AddOctets2(handle); auto incoming_acl_future = upper->GetReceivedAclFuture(); hal->callbacks->aclDataReceived( GetPacketBytes(AclPacketBuilder::Create(handle, packet_boundary_flag, broadcast_flag, std::move(acl_payload)))); // Verify the ACL packet auto incoming_acl_status = incoming_acl_future.wait_for(kAclTimeout); ASSERT_EQ(incoming_acl_status, std::future_status::ready); auto acl_view = upper->GetReceivedAcl(); ASSERT_TRUE(acl_view.IsValid()); ASSERT_EQ(bd_addr.length() + sizeof(handle), acl_view.GetPayload().size()); auto itr = acl_view.GetPayload().begin(); ASSERT_EQ(bd_addr, itr.extract
()); ASSERT_EQ(handle, itr.extract()); // Send an ACL packet from DependsOnHci PacketBoundaryFlag packet_boundary_flag2 = PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE; BroadcastFlag broadcast_flag2 = BroadcastFlag::POINT_TO_POINT; auto acl_payload2 = std::make_unique(); acl_payload2->AddOctets2(handle); acl_payload2->AddAddress(bd_addr); auto sent_acl_future = hal->GetSentAclFuture(); upper->SendAclData(AclPacketBuilder::Create(handle, packet_boundary_flag2, broadcast_flag2, std::move(acl_payload2))); // Verify the ACL packet auto sent_acl_status = sent_acl_future.wait_for(kAclTimeout); ASSERT_EQ(sent_acl_status, std::future_status::ready); auto sent_acl = hal->GetSentAcl(); ASSERT_LT(0, sent_acl.size()); AclPacketView sent_acl_view = AclPacketView::Create(sent_acl); ASSERT_TRUE(sent_acl_view.IsValid()); ASSERT_EQ(bd_addr.length() + sizeof(handle), sent_acl_view.GetPayload().size()); auto sent_itr = sent_acl_view.GetPayload().begin(); ASSERT_EQ(handle, sent_itr.extract()); ASSERT_EQ(bd_addr, sent_itr.extract
()); } TEST_F(HciTest, receiveMultipleAclPackets) { Address bd_addr; ASSERT_TRUE(Address::FromString("A1:A2:A3:A4:A5:A6", bd_addr)); uint16_t handle = 0x0001; uint16_t num_packets = 100; PacketBoundaryFlag packet_boundary_flag = PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE; BroadcastFlag broadcast_flag = BroadcastFlag::POINT_TO_POINT; for (uint16_t i = 0; i < num_packets; i++) { auto acl_payload = std::make_unique(); acl_payload->AddAddress(bd_addr); acl_payload->AddOctets2(handle); acl_payload->AddOctets2(i); hal->callbacks->aclDataReceived( GetPacketBytes(AclPacketBuilder::Create(handle, packet_boundary_flag, broadcast_flag, std::move(acl_payload)))); } auto incoming_acl_future = upper->GetReceivedAclFuture(); uint16_t received_packets = 0; while (received_packets < num_packets - 1) { auto incoming_acl_status = incoming_acl_future.wait_for(kAclTimeout); // Get the next future. incoming_acl_future = upper->GetReceivedAclFuture(); ASSERT_EQ(incoming_acl_status, std::future_status::ready); size_t num_packets = upper->GetNumReceivedAclPackets(); for (size_t i = 0; i < num_packets; i++) { auto acl_view = upper->GetReceivedAcl(); ASSERT_TRUE(acl_view.IsValid()); ASSERT_EQ(bd_addr.length() + sizeof(handle) + sizeof(received_packets), acl_view.GetPayload().size()); auto itr = acl_view.GetPayload().begin(); ASSERT_EQ(bd_addr, itr.extract
()); ASSERT_EQ(handle, itr.extract()); ASSERT_EQ(received_packets, itr.extract()); received_packets += 1; } } // Check to see if this future was already fulfilled. auto acl_race_status = incoming_acl_future.wait_for(std::chrono::milliseconds(1)); if (acl_race_status == std::future_status::ready) { // Get the next future. incoming_acl_future = upper->GetReceivedAclFuture(); } // One last packet to make sure they were all sent. Already got the future. auto acl_payload = std::make_unique(); acl_payload->AddAddress(bd_addr); acl_payload->AddOctets2(handle); acl_payload->AddOctets2(num_packets); hal->callbacks->aclDataReceived( GetPacketBytes(AclPacketBuilder::Create(handle, packet_boundary_flag, broadcast_flag, std::move(acl_payload)))); auto incoming_acl_status = incoming_acl_future.wait_for(kAclTimeout); ASSERT_EQ(incoming_acl_status, std::future_status::ready); auto acl_view = upper->GetReceivedAcl(); ASSERT_TRUE(acl_view.IsValid()); ASSERT_EQ(bd_addr.length() + sizeof(handle) + sizeof(received_packets), acl_view.GetPayload().size()); auto itr = acl_view.GetPayload().begin(); ASSERT_EQ(bd_addr, itr.extract
()); ASSERT_EQ(handle, itr.extract()); ASSERT_EQ(received_packets, itr.extract()); } } // namespace hci } // namespace bluetooth