/* * 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_back(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_back(std::move(data)); } void sendIsoData(hal::HciPacket data) override { outgoing_iso_.push_back(std::move(data)); if (sent_iso_promise_ != nullptr) { auto promise = std::move(sent_iso_promise_); sent_iso_promise_.reset(); promise->set_value(); } } 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(); } CommandView GetSentCommand() { auto packetview = GetPacketView(std::move(outgoing_commands_.front())); outgoing_commands_.pop_front(); return CommandView::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; } std::future GetSentIsoFuture() { ASSERT_LOG(sent_iso_promise_ == nullptr, "Promises promises ... Only one at a time"); sent_iso_promise_ = std::make_unique>(); return sent_iso_promise_->get_future(); } PacketView GetSentIso() { auto packetview = GetPacketView(std::move(outgoing_iso_.front())); outgoing_iso_.pop_front(); return packetview; } void Start() {} void Stop() {} void ListDependencies(ModuleList*) {} std::string ToString() const override { return std::string("TestHciHal"); } static const ModuleFactory Factory; private: std::list outgoing_commands_; std::list outgoing_acl_; std::list outgoing_sco_; std::list outgoing_iso_; std::unique_ptr> sent_command_promise_; std::unique_ptr> sent_acl_promise_; std::unique_ptr> sent_iso_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))); } void SendIsoData(std::unique_ptr iso) { outgoing_iso_.push(std::move(iso)); auto queue_end = hci_->GetIsoQueueEnd(); queue_end->RegisterEnqueue(GetHandler(), common::Bind(&DependsOnHci::handle_enqueue_iso, 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(); } EventView GetReceivedEvent() { std::lock_guard lock(list_protector_); EventView 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(); } AclView GetReceivedAcl() { std::lock_guard lock(list_protector_); AclView packetview = incoming_acl_packets_.front(); incoming_acl_packets_.pop_front(); return packetview; } std::future GetReceivedIsoFuture() { ASSERT_LOG(iso_promise_ == nullptr, "Promises promises ... Only one at a time"); iso_promise_ = std::make_unique>(); return iso_promise_->get_future(); } size_t GetNumReceivedIsoPackets() { return incoming_iso_packets_.size(); } IsoView GetReceivedIso() { std::lock_guard lock(list_protector_); IsoView packetview = incoming_iso_packets_.front(); incoming_iso_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))); hci_->GetIsoQueueEnd()->RegisterDequeue( GetHandler(), common::Bind(&DependsOnHci::handle_iso, common::Unretained(this))); } void Stop() { hci_->GetAclQueueEnd()->UnregisterDequeue(); hci_->GetIsoQueueEnd()->UnregisterDequeue(); } void ListDependencies(ModuleList* list) { list->add(); } std::string ToString() const override { return std::string("DependsOnHci"); } 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::list incoming_iso_packets_; std::unique_ptr> event_promise_; std::unique_ptr> acl_promise_; std::unique_ptr> iso_promise_; /* This mutex is protecting lists above from being pushed/popped from different threads at same time */ std::mutex list_protector_; void handle_acl() { std::lock_guard lock(list_protector_); 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) { std::lock_guard lock(list_protector_); incoming_events_.push_back(event); if (event_promise_ != nullptr) { auto promise = std::move(event_promise_); event_promise_.reset(); promise->set_value(); } } void handle_iso() { std::lock_guard lock(list_protector_); auto iso_ptr = hci_->GetIsoQueueEnd()->TryDequeue(); incoming_iso_packets_.push_back(*iso_ptr); if (iso_promise_ != nullptr) { auto promise = std::move(iso_promise_); iso_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; } std::queue> outgoing_iso_; std::unique_ptr handle_enqueue_iso() { hci_->GetIsoQueueEnd()->UnregisterEnqueue(); auto iso = std::move(outgoing_iso_.front()); outgoing_iso_.pop(); return iso; } }; 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(CommandView::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::CENTRAL; 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 central_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, central_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(EventView::Create(event))).IsValid()); } TEST_F(HciTest, hciTimeOut) { auto event_future = upper->GetReceivedEventFuture(); auto reset_command_future = hal->GetSentCommandFuture(); upper->SendHciCommandExpectingComplete(ResetBuilder::Create()); auto reset_command_sent_status = reset_command_future.wait_for(kTimeout); ASSERT_EQ(reset_command_sent_status, std::future_status::ready); auto reset = hal->GetSentCommand(); ASSERT_TRUE(reset.IsValid()); ASSERT_EQ(reset.GetOpCode(), OpCode::RESET); auto debug_command_future = hal->GetSentCommandFuture(); auto event_status = event_future.wait_for(HciLayer::kHciTimeoutMs); ASSERT_NE(event_status, std::future_status::ready); auto debug_command_sent_status = debug_command_future.wait_for(kTimeout); ASSERT_EQ(debug_command_sent_status, std::future_status::ready); auto debug = hal->GetSentCommand(); ASSERT_TRUE(debug.IsValid()); ASSERT_EQ(debug.GetOpCode(), OpCode::CONTROLLER_DEBUG_INFO); } 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(EventView::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(CommandView::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(EventView::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(CommandView::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(EventView::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(CommandView::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(EventView::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(CommandView::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(CommandView::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(AclCommandView::Create(CommandView::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(AclBuilder::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(AclBuilder::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()); AclView sent_acl_view = AclView::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; const 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(AclBuilder::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) { size_t num_rcv_packets = upper->GetNumReceivedAclPackets(); if (num_rcv_packets == 0) { auto incoming_acl_status = incoming_acl_future.wait_for(kAclTimeout); // Get the next future. ASSERT_EQ(incoming_acl_status, std::future_status::ready); incoming_acl_future = upper->GetReceivedAclFuture(); num_rcv_packets = upper->GetNumReceivedAclPackets(); } for (size_t i = 0; i < num_rcv_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(AclBuilder::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()); } TEST_F(HciTest, receiveMultipleIsoPackets) { uint16_t handle = 0x0001; const uint16_t num_packets = 100; IsoPacketBoundaryFlag packet_boundary_flag = IsoPacketBoundaryFlag::COMPLETE_SDU; TimeStampFlag timestamp_flag = TimeStampFlag::NOT_PRESENT; for (uint16_t i = 0; i < num_packets; i++) { auto iso_payload = std::make_unique(); iso_payload->AddOctets2(handle); iso_payload->AddOctets2(i); hal->callbacks->isoDataReceived( GetPacketBytes(IsoBuilder::Create(handle, packet_boundary_flag, timestamp_flag, std::move(iso_payload)))); } auto incoming_iso_future = upper->GetReceivedIsoFuture(); uint16_t received_packets = 0; while (received_packets < num_packets - 1) { size_t num_rcv_packets = upper->GetNumReceivedIsoPackets(); if (num_rcv_packets == 0) { auto incoming_iso_status = incoming_iso_future.wait_for(kAclTimeout); // Get the next future. ASSERT_EQ(incoming_iso_status, std::future_status::ready); incoming_iso_future = upper->GetReceivedIsoFuture(); num_rcv_packets = upper->GetNumReceivedIsoPackets(); } for (size_t i = 0; i < num_rcv_packets; i++) { auto iso_view = upper->GetReceivedIso(); ASSERT_TRUE(iso_view.IsValid()); ASSERT_EQ(sizeof(handle) + sizeof(received_packets), iso_view.GetPayload().size()); auto itr = iso_view.GetPayload().begin(); ASSERT_EQ(handle, itr.extract()); ASSERT_EQ(received_packets, itr.extract()); received_packets += 1; } } // Check to see if this future was already fulfilled. auto iso_race_status = incoming_iso_future.wait_for(std::chrono::milliseconds(1)); if (iso_race_status == std::future_status::ready) { // Get the next future. incoming_iso_future = upper->GetReceivedIsoFuture(); } // One last packet to make sure they were all sent. Already got the future. auto iso_payload = std::make_unique(); iso_payload->AddOctets2(handle); iso_payload->AddOctets2(num_packets); hal->callbacks->isoDataReceived( GetPacketBytes(IsoBuilder::Create(handle, packet_boundary_flag, timestamp_flag, std::move(iso_payload)))); auto incoming_iso_status = incoming_iso_future.wait_for(kAclTimeout); ASSERT_EQ(incoming_iso_status, std::future_status::ready); auto iso_view = upper->GetReceivedIso(); ASSERT_TRUE(iso_view.IsValid()); ASSERT_EQ(sizeof(handle) + sizeof(received_packets), iso_view.GetPayload().size()); auto itr = iso_view.GetPayload().begin(); ASSERT_EQ(handle, itr.extract()); ASSERT_EQ(received_packets, itr.extract()); } } // namespace hci } // namespace bluetooth