/* * 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/acl_manager.h" #include #include #include #include #include #include "common/bind.h" #include "hci/acl_manager/connection_callbacks_mock.h" #include "hci/acl_manager/connection_management_callbacks_mock.h" #include "hci/acl_manager/le_connection_callbacks_mock.h" #include "hci/acl_manager/le_connection_management_callbacks_mock.h" #include "hci/address.h" #include "hci/class_of_device.h" #include "hci/controller.h" #include "hci/controller_mock.h" #include "hci/hci_layer.h" #include "hci/hci_layer_fake.h" #include "os/fake_timer/fake_timerfd.h" #include "os/thread.h" #include "packet/raw_builder.h" using bluetooth::common::BidiQueue; using bluetooth::common::BidiQueueEnd; using bluetooth::os::fake_timer::fake_timerfd_advance; using bluetooth::packet::kLittleEndian; using bluetooth::packet::PacketView; using bluetooth::packet::RawBuilder; using testing::_; using testing::ElementsAreArray; namespace { constexpr auto kTimeout = std::chrono::seconds(2); constexpr auto kShortTimeout = std::chrono::milliseconds(100); constexpr uint16_t kHciHandle = 123; constexpr uint16_t kScanIntervalFast = 0x0060; constexpr uint16_t kScanWindowFast = 0x0030; constexpr uint16_t kScanIntervalSlow = 0x0800; constexpr uint16_t kScanWindowSlow = 0x0030; const bluetooth::hci::AddressWithType empty_address_with_type = bluetooth::hci::AddressWithType(); } // namespace namespace bluetooth { namespace hci { namespace acl_manager { class TestController : public testing::MockController { public: void RegisterCompletedAclPacketsCallback( common::ContextualCallback cb) override { acl_cb_ = cb; } void UnregisterCompletedAclPacketsCallback() override { acl_cb_ = {}; } uint16_t GetAclPacketLength() const override { return acl_buffer_length_; } uint16_t GetNumAclPacketBuffers() const override { return total_acl_buffers_; } bool IsSupported(bluetooth::hci::OpCode /* op_code */) const override { return false; } LeBufferSize GetLeBufferSize() const override { LeBufferSize le_buffer_size; le_buffer_size.total_num_le_packets_ = 2; le_buffer_size.le_data_packet_length_ = 32; return le_buffer_size; } void CompletePackets(uint16_t handle, uint16_t packets) { acl_cb_(handle, packets); } uint16_t acl_buffer_length_ = 1024; uint16_t total_acl_buffers_ = 2; common::ContextualCallback acl_cb_; protected: void Start() override {} void Stop() override {} void ListDependencies(ModuleList* /* list */) const {} }; class AclManagerNoCallbacksTest : public ::testing::Test { protected: void SetUp() override { test_hci_layer_ = new HciLayerFake; // Ownership is transferred to registry test_controller_ = new TestController; // Ownership is transferred to registry EXPECT_CALL(*test_controller_, GetMacAddress()); EXPECT_CALL(*test_controller_, GetLeFilterAcceptListSize()); EXPECT_CALL(*test_controller_, GetLeResolvingListSize()); EXPECT_CALL(*test_controller_, SupportsBlePrivacy()); fake_registry_.InjectTestModule(&HciLayer::Factory, test_hci_layer_); fake_registry_.InjectTestModule(&Controller::Factory, test_controller_); client_handler_ = fake_registry_.GetTestModuleHandler(&HciLayer::Factory); ASSERT_NE(client_handler_, nullptr); fake_registry_.Start(&thread_); acl_manager_ = static_cast(fake_registry_.GetModuleUnderTest(&AclManager::Factory)); Address::FromString("A1:A2:A3:A4:A5:A6", remote); hci::Address address; Address::FromString("D0:05:04:03:02:01", address); hci::AddressWithType address_with_type(address, hci::AddressType::RANDOM_DEVICE_ADDRESS); auto minimum_rotation_time = std::chrono::milliseconds(7 * 60 * 1000); auto maximum_rotation_time = std::chrono::milliseconds(15 * 60 * 1000); acl_manager_->SetPrivacyPolicyForInitiatorAddress( LeAddressManager::AddressPolicy::USE_STATIC_ADDRESS, address_with_type, minimum_rotation_time, maximum_rotation_time); auto set_random_address_packet = LeSetRandomAddressView::Create(LeAdvertisingCommandView::Create( GetConnectionManagementCommand(OpCode::LE_SET_RANDOM_ADDRESS))); ASSERT_TRUE(set_random_address_packet.IsValid()); my_initiating_address = AddressWithType(set_random_address_packet.GetRandomAddress(), AddressType::RANDOM_DEVICE_ADDRESS); test_hci_layer_->IncomingEvent( LeSetRandomAddressCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); ON_CALL(mock_connection_callback_, OnConnectSuccess) .WillByDefault([this](std::unique_ptr connection) { connections_.push_back(std::move(connection)); if (connection_promise_ != nullptr) { connection_promise_->set_value(); connection_promise_.reset(); } }); } void TearDown() override { // Invalid mutex exception is raised if the connections // are cleared after the AclConnectionInterface is deleted // through fake_registry_. connections_.clear(); le_connections_.clear(); fake_registry_.SynchronizeModuleHandler(&AclManager::Factory, std::chrono::milliseconds(20)); fake_registry_.StopAll(); } void sync_client_handler() { log::assert_that(thread_.GetReactor()->WaitForIdle(std::chrono::seconds(2)), "assert failed: thread_.GetReactor()->WaitForIdle(std::chrono::seconds(2))"); } TestModuleRegistry fake_registry_; HciLayerFake* test_hci_layer_ = nullptr; TestController* test_controller_ = nullptr; os::Thread& thread_ = fake_registry_.GetTestThread(); AclManager* acl_manager_ = nullptr; os::Handler* client_handler_ = nullptr; Address remote; AddressWithType my_initiating_address; const bool use_accept_list_ = true; // gd currently only supports connect list std::future GetConnectionFuture() { log::assert_that(connection_promise_ == nullptr, "Promises promises ... Only one at a time"); connection_promise_ = std::make_unique>(); return connection_promise_->get_future(); } std::future GetLeConnectionFuture() { log::assert_that(le_connection_promise_ == nullptr, "Promises promises ... Only one at a time"); le_connection_promise_ = std::make_unique>(); return le_connection_promise_->get_future(); } std::shared_ptr GetLastConnection() { return connections_.back(); } std::shared_ptr GetLastLeConnection() { return le_connections_.back(); } void SendAclData(uint16_t handle, AclConnection::QueueUpEnd* queue_end) { std::promise promise; auto future = promise.get_future(); queue_end->RegisterEnqueue( client_handler_, common::Bind( [](decltype(queue_end) queue_end, uint16_t handle, std::promise promise) { queue_end->UnregisterEnqueue(); promise.set_value(); return NextPayload(handle); }, queue_end, handle, common::Passed(std::move(promise)))); auto status = future.wait_for(kTimeout); ASSERT_EQ(status, std::future_status::ready); } ConnectionManagementCommandView GetConnectionManagementCommand(OpCode op_code) { auto base_command = test_hci_layer_->GetCommand(); ConnectionManagementCommandView command = ConnectionManagementCommandView::Create(AclCommandView::Create(base_command)); EXPECT_TRUE(command.IsValid()); EXPECT_EQ(command.GetOpCode(), op_code); return command; } std::list> connections_; std::unique_ptr> connection_promise_; MockConnectionCallback mock_connection_callback_; std::list> le_connections_; std::unique_ptr> le_connection_promise_; MockLeConnectionCallbacks mock_le_connection_callbacks_; }; class AclManagerTest : public AclManagerNoCallbacksTest { protected: void SetUp() override { AclManagerNoCallbacksTest::SetUp(); acl_manager_->RegisterCallbacks(&mock_connection_callback_, client_handler_); acl_manager_->RegisterLeCallbacks(&mock_le_connection_callbacks_, client_handler_); } }; class AclManagerWithConnectionTest : public AclManagerTest { protected: void SetUp() override { AclManagerTest::SetUp(); handle_ = 0x123; acl_manager_->CreateConnection(remote); // Wait for the connection request auto last_command = GetConnectionManagementCommand(OpCode::CREATE_CONNECTION); while (!last_command.IsValid()) { last_command = GetConnectionManagementCommand(OpCode::CREATE_CONNECTION); } EXPECT_CALL(mock_connection_management_callbacks_, OnRoleChange(hci::ErrorCode::SUCCESS, Role::CENTRAL)); auto first_connection = GetConnectionFuture(); test_hci_layer_->IncomingEvent(ConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, handle_, remote, LinkType::ACL, Enable::DISABLED)); auto first_connection_status = first_connection.wait_for(kTimeout); ASSERT_EQ(first_connection_status, std::future_status::ready); connection_ = GetLastConnection(); connection_->RegisterCallbacks(&mock_connection_management_callbacks_, client_handler_); } void TearDown() override { // Invalid mutex exception is raised if the connection // is cleared after the AclConnectionInterface is deleted // through fake_registry_. connections_.clear(); le_connections_.clear(); connection_.reset(); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&AclManager::Factory, std::chrono::milliseconds(20)); fake_registry_.StopAll(); } uint16_t handle_; std::shared_ptr connection_; MockConnectionManagementCallbacks mock_connection_management_callbacks_; }; TEST_F(AclManagerTest, startup_teardown) {} TEST_F(AclManagerTest, invoke_registered_callback_connection_complete_success) { acl_manager_->CreateConnection(remote); // Wait for the connection request auto last_command = GetConnectionManagementCommand(OpCode::CREATE_CONNECTION); while (!last_command.IsValid()) { last_command = GetConnectionManagementCommand(OpCode::CREATE_CONNECTION); } auto first_connection = GetConnectionFuture(); test_hci_layer_->IncomingEvent(ConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, kHciHandle, remote, LinkType::ACL, Enable::DISABLED)); auto first_connection_status = first_connection.wait_for(kTimeout); ASSERT_EQ(first_connection_status, std::future_status::ready); auto connection = GetLastConnection(); ASSERT_EQ(connection->GetAddress(), remote); } TEST_F(AclManagerTest, invoke_registered_callback_connection_complete_fail) { acl_manager_->CreateConnection(remote); // Wait for the connection request auto last_command = GetConnectionManagementCommand(OpCode::CREATE_CONNECTION); while (!last_command.IsValid()) { last_command = GetConnectionManagementCommand(OpCode::CREATE_CONNECTION); } struct callback_t { hci::Address bd_addr; hci::ErrorCode reason; bool is_locally_initiated; }; auto promise = std::promise(); auto future = promise.get_future(); ON_CALL(mock_connection_callback_, OnConnectFail) .WillByDefault([&promise](hci::Address bd_addr, hci::ErrorCode reason, bool is_locally_initiated) { promise.set_value({ .bd_addr = bd_addr, .reason = reason, .is_locally_initiated = is_locally_initiated, }); }); EXPECT_CALL(mock_connection_callback_, OnConnectFail(remote, ErrorCode::PAGE_TIMEOUT, true)); // Remote response event to the connection request test_hci_layer_->IncomingEvent(ConnectionCompleteBuilder::Create( ErrorCode::PAGE_TIMEOUT, kHciHandle, remote, LinkType::ACL, Enable::DISABLED)); ASSERT_EQ(std::future_status::ready, future.wait_for(kTimeout)); auto callback = future.get(); ASSERT_EQ(remote, callback.bd_addr); ASSERT_EQ(ErrorCode::PAGE_TIMEOUT, callback.reason); ASSERT_EQ(true, callback.is_locally_initiated); } class AclManagerWithLeConnectionTest : public AclManagerTest { protected: void SetUp() override { AclManagerTest::SetUp(); remote_with_type_ = AddressWithType(remote, AddressType::PUBLIC_DEVICE_ADDRESS); acl_manager_->CreateLeConnection(remote_with_type_, true); GetConnectionManagementCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); test_hci_layer_->IncomingEvent( LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); auto packet = GetConnectionManagementCommand(OpCode::LE_CREATE_CONNECTION); auto le_connection_management_command_view = LeConnectionManagementCommandView::Create(AclCommandView::Create(packet)); auto command_view = LeCreateConnectionView::Create(le_connection_management_command_view); ASSERT_TRUE(command_view.IsValid()); if (use_accept_list_) { ASSERT_EQ(command_view.GetPeerAddress(), empty_address_with_type.GetAddress()); ASSERT_EQ(command_view.GetPeerAddressType(), empty_address_with_type.GetAddressType()); } else { ASSERT_EQ(command_view.GetPeerAddress(), remote); ASSERT_EQ(command_view.GetPeerAddressType(), AddressType::PUBLIC_DEVICE_ADDRESS); } test_hci_layer_->IncomingEvent( LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); auto first_connection = GetLeConnectionFuture(); EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectSuccess(remote_with_type_, _)) .WillRepeatedly([this](hci::AddressWithType /* address_with_type */, std::unique_ptr connection) { le_connections_.push_back(std::move(connection)); if (le_connection_promise_ != nullptr) { le_connection_promise_->set_value(); le_connection_promise_.reset(); } }); if (send_early_acl_) { log::info("Sending a packet with handle 0x{:02x} ({})", handle_, handle_); test_hci_layer_->IncomingAclData(handle_); } test_hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, handle_, Role::CENTRAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, 0x0100, 0x0010, 0x0C80, ClockAccuracy::PPM_30)); GetConnectionManagementCommand(OpCode::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST); test_hci_layer_->IncomingEvent( LeRemoveDeviceFromFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); auto first_connection_status = first_connection.wait_for(kTimeout); ASSERT_EQ(first_connection_status, std::future_status::ready); connection_ = GetLastLeConnection(); } void TearDown() override { // Invalid mutex exception is raised if the connection // is cleared after the AclConnectionInterface is deleted // through fake_registry_. connections_.clear(); le_connections_.clear(); connection_.reset(); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&AclManager::Factory, std::chrono::milliseconds(20)); fake_registry_.StopAll(); } uint16_t handle_ = 0x123; bool send_early_acl_ = false; std::shared_ptr connection_; AddressWithType remote_with_type_; MockLeConnectionManagementCallbacks mock_le_connection_management_callbacks_; }; class AclManagerWithLateLeConnectionTest : public AclManagerWithLeConnectionTest { protected: void SetUp() override { send_early_acl_ = true; AclManagerWithLeConnectionTest::SetUp(); } }; // TODO: implement version of this test where controller supports Extended Advertising Feature in // GetLeLocalSupportedFeatures, and LE Extended Create Connection is used TEST_F(AclManagerWithLeConnectionTest, invoke_registered_callback_le_connection_complete_success) { ASSERT_EQ(connection_->GetLocalAddress(), my_initiating_address); ASSERT_EQ(connection_->GetRemoteAddress(), remote_with_type_); } TEST_F(AclManagerTest, invoke_registered_callback_le_connection_complete_fail) { AddressWithType remote_with_type(remote, AddressType::PUBLIC_DEVICE_ADDRESS); acl_manager_->CreateLeConnection(remote_with_type, true); GetConnectionManagementCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); test_hci_layer_->IncomingEvent( LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); auto packet = GetConnectionManagementCommand(OpCode::LE_CREATE_CONNECTION); auto le_connection_management_command_view = LeConnectionManagementCommandView::Create(AclCommandView::Create(packet)); auto command_view = LeCreateConnectionView::Create(le_connection_management_command_view); ASSERT_TRUE(command_view.IsValid()); if (use_accept_list_) { ASSERT_EQ(command_view.GetPeerAddress(), hci::Address::kEmpty); } else { ASSERT_EQ(command_view.GetPeerAddress(), remote); } EXPECT_EQ(command_view.GetPeerAddressType(), AddressType::PUBLIC_DEVICE_ADDRESS); test_hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectFail(remote_with_type, ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES)); test_hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES, 0x123, Role::CENTRAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, 0x0100, 0x0010, 0x0011, ClockAccuracy::PPM_30)); packet = GetConnectionManagementCommand(OpCode::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST); le_connection_management_command_view = LeConnectionManagementCommandView::Create(AclCommandView::Create(packet)); auto remove_command_view = LeRemoveDeviceFromFilterAcceptListView::Create(le_connection_management_command_view); ASSERT_TRUE(remove_command_view.IsValid()); test_hci_layer_->IncomingEvent( LeRemoveDeviceFromFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); } TEST_F(AclManagerTest, cancel_le_connection) { AddressWithType remote_with_type(remote, AddressType::PUBLIC_DEVICE_ADDRESS); acl_manager_->CreateLeConnection(remote_with_type, true); GetConnectionManagementCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); test_hci_layer_->IncomingEvent( LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); GetConnectionManagementCommand(OpCode::LE_CREATE_CONNECTION); test_hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); acl_manager_->CancelLeConnect(remote_with_type); auto packet = GetConnectionManagementCommand(OpCode::LE_CREATE_CONNECTION_CANCEL); auto le_connection_management_command_view = LeConnectionManagementCommandView::Create(AclCommandView::Create(packet)); auto command_view = LeCreateConnectionCancelView::Create(le_connection_management_command_view); ASSERT_TRUE(command_view.IsValid()); test_hci_layer_->IncomingEvent( LeCreateConnectionCancelCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); test_hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::UNKNOWN_CONNECTION, 0x123, Role::CENTRAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, 0x0100, 0x0010, 0x0011, ClockAccuracy::PPM_30)); packet = GetConnectionManagementCommand(OpCode::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST); le_connection_management_command_view = LeConnectionManagementCommandView::Create(AclCommandView::Create(packet)); auto remove_command_view = LeRemoveDeviceFromFilterAcceptListView::Create(le_connection_management_command_view); ASSERT_TRUE(remove_command_view.IsValid()); test_hci_layer_->IncomingEvent( LeRemoveDeviceFromFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); } TEST_F(AclManagerTest, create_connection_with_fast_mode) { AddressWithType remote_with_type(remote, AddressType::PUBLIC_DEVICE_ADDRESS); acl_manager_->CreateLeConnection(remote_with_type, true); GetConnectionManagementCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); test_hci_layer_->IncomingEvent( LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); auto packet = GetConnectionManagementCommand(OpCode::LE_CREATE_CONNECTION); auto command_view = LeCreateConnectionView::Create( LeConnectionManagementCommandView::Create(AclCommandView::Create(packet))); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetLeScanInterval(), kScanIntervalFast); ASSERT_EQ(command_view.GetLeScanWindow(), kScanWindowFast); test_hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); auto first_connection = GetLeConnectionFuture(); EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectSuccess(remote_with_type, _)) .WillRepeatedly([this](hci::AddressWithType /* address_with_type */, std::unique_ptr connection) { le_connections_.push_back(std::move(connection)); if (le_connection_promise_ != nullptr) { le_connection_promise_->set_value(); le_connection_promise_.reset(); } }); test_hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x00, Role::CENTRAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, 0x0100, 0x0010, 0x0C80, ClockAccuracy::PPM_30)); GetConnectionManagementCommand(OpCode::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST); test_hci_layer_->IncomingEvent( LeRemoveDeviceFromFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); auto first_connection_status = first_connection.wait_for(kTimeout); ASSERT_EQ(first_connection_status, std::future_status::ready); } TEST_F(AclManagerTest, create_connection_with_slow_mode) { AddressWithType remote_with_type(remote, AddressType::PUBLIC_DEVICE_ADDRESS); acl_manager_->CreateLeConnection(remote_with_type, false); GetConnectionManagementCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); test_hci_layer_->IncomingEvent( LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); auto packet = GetConnectionManagementCommand(OpCode::LE_CREATE_CONNECTION); auto command_view = LeCreateConnectionView::Create( LeConnectionManagementCommandView::Create(AclCommandView::Create(packet))); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetLeScanInterval(), kScanIntervalSlow); ASSERT_EQ(command_view.GetLeScanWindow(), kScanWindowSlow); test_hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); auto first_connection = GetLeConnectionFuture(); EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectSuccess(remote_with_type, _)) .WillRepeatedly([this](hci::AddressWithType /* address_with_type */, std::unique_ptr connection) { le_connections_.push_back(std::move(connection)); if (le_connection_promise_ != nullptr) { le_connection_promise_->set_value(); le_connection_promise_.reset(); } }); test_hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x00, Role::CENTRAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, 0x0100, 0x0010, 0x0C80, ClockAccuracy::PPM_30)); GetConnectionManagementCommand(OpCode::LE_REMOVE_DEVICE_FROM_FILTER_ACCEPT_LIST); test_hci_layer_->IncomingEvent( LeRemoveDeviceFromFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); auto first_connection_status = first_connection.wait_for(kTimeout); ASSERT_EQ(first_connection_status, std::future_status::ready); } TEST_F(AclManagerWithLeConnectionTest, acl_send_data_one_le_connection) { ASSERT_EQ(connection_->GetRemoteAddress(), remote_with_type_); ASSERT_EQ(connection_->GetHandle(), handle_); // Send a packet from HCI test_hci_layer_->IncomingAclData(handle_); auto queue_end = connection_->GetAclQueueEnd(); std::unique_ptr> received; do { received = queue_end->TryDequeue(); } while (received == nullptr); PacketView received_packet = *received; // Send a packet from the connection SendAclData(handle_, connection_->GetAclQueueEnd()); auto sent_packet = test_hci_layer_->OutgoingAclData(); // Send another packet from the connection SendAclData(handle_, connection_->GetAclQueueEnd()); sent_packet = test_hci_layer_->OutgoingAclData(); } TEST_F(AclManagerWithLeConnectionTest, invoke_registered_callback_le_connection_update_success) { ASSERT_EQ(connection_->GetLocalAddress(), my_initiating_address); ASSERT_EQ(connection_->GetRemoteAddress(), remote_with_type_); ASSERT_EQ(connection_->GetHandle(), handle_); connection_->RegisterCallbacks(&mock_le_connection_management_callbacks_, client_handler_); std::promise promise; ErrorCode hci_status = hci::ErrorCode::SUCCESS; uint16_t connection_interval_min = 0x0012; uint16_t connection_interval_max = 0x0080; uint16_t connection_interval = (connection_interval_max + connection_interval_min) / 2; uint16_t connection_latency = 0x0001; uint16_t supervision_timeout = 0x0A00; connection_->LeConnectionUpdate(connection_interval_min, connection_interval_max, connection_latency, supervision_timeout, 0x10, 0x20); auto update_packet = GetConnectionManagementCommand(OpCode::LE_CONNECTION_UPDATE); auto update_view = LeConnectionUpdateView::Create( LeConnectionManagementCommandView::Create(AclCommandView::Create(update_packet))); ASSERT_TRUE(update_view.IsValid()); EXPECT_EQ(update_view.GetConnectionHandle(), handle_); test_hci_layer_->IncomingEvent(LeConnectionUpdateStatusBuilder::Create(ErrorCode::SUCCESS, 0x1)); EXPECT_CALL(mock_le_connection_management_callbacks_, OnConnectionUpdate(hci_status, connection_interval, connection_latency, supervision_timeout)); test_hci_layer_->IncomingLeMetaEvent(LeConnectionUpdateCompleteBuilder::Create( ErrorCode::SUCCESS, handle_, connection_interval, connection_latency, supervision_timeout)); sync_client_handler(); } TEST_F(AclManagerWithLeConnectionTest, invoke_registered_callback_le_disconnect) { ASSERT_EQ(connection_->GetRemoteAddress(), remote_with_type_); ASSERT_EQ(connection_->GetHandle(), handle_); connection_->RegisterCallbacks(&mock_le_connection_management_callbacks_, client_handler_); auto reason = ErrorCode::REMOTE_USER_TERMINATED_CONNECTION; EXPECT_CALL(mock_le_connection_management_callbacks_, OnDisconnection(reason)); test_hci_layer_->Disconnect(handle_, reason); sync_client_handler(); } TEST_F(AclManagerWithLeConnectionTest, invoke_registered_callback_le_disconnect_data_race) { ASSERT_EQ(connection_->GetRemoteAddress(), remote_with_type_); ASSERT_EQ(connection_->GetHandle(), handle_); connection_->RegisterCallbacks(&mock_le_connection_management_callbacks_, client_handler_); test_hci_layer_->IncomingAclData(handle_); auto reason = ErrorCode::REMOTE_USER_TERMINATED_CONNECTION; EXPECT_CALL(mock_le_connection_management_callbacks_, OnDisconnection(reason)); test_hci_layer_->Disconnect(handle_, reason); sync_client_handler(); } TEST_F(AclManagerWithLeConnectionTest, invoke_registered_callback_le_queue_disconnect) { auto reason = ErrorCode::REMOTE_USER_TERMINATED_CONNECTION; test_hci_layer_->Disconnect(handle_, reason); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&AclManager::Factory, std::chrono::milliseconds(20)); EXPECT_CALL(mock_le_connection_management_callbacks_, OnDisconnection(reason)); connection_->RegisterCallbacks(&mock_le_connection_management_callbacks_, client_handler_); sync_client_handler(); } TEST_F(AclManagerWithLateLeConnectionTest, and_receive_nothing) {} TEST_F(AclManagerWithLateLeConnectionTest, receive_acl) { client_handler_->Post(common::BindOnce(fake_timerfd_advance, 1200)); auto queue_end = connection_->GetAclQueueEnd(); std::unique_ptr> received; do { received = queue_end->TryDequeue(); } while (received == nullptr); { ASSERT_EQ(received->size(), 10u); auto itr = received->begin(); ASSERT_EQ(itr.extract(), 6u); // L2CAP PDU size ASSERT_EQ(itr.extract(), 2u); // L2CAP CID ASSERT_EQ(itr.extract(), handle_); ASSERT_GE(itr.extract(), 0u); // packet number } } TEST_F(AclManagerWithLateLeConnectionTest, receive_acl_in_order) { // Send packet #2 from HCI (the first was sent in the test) test_hci_layer_->IncomingAclData(handle_); auto queue_end = connection_->GetAclQueueEnd(); std::unique_ptr> received; do { received = queue_end->TryDequeue(); } while (received == nullptr); uint32_t first_packet_number = 0; { ASSERT_EQ(received->size(), 10u); auto itr = received->begin(); ASSERT_EQ(itr.extract(), 6u); // L2CAP PDU size ASSERT_EQ(itr.extract(), 2u); // L2CAP CID ASSERT_EQ(itr.extract(), handle_); first_packet_number = itr.extract(); } do { received = queue_end->TryDequeue(); } while (received == nullptr); { ASSERT_EQ(received->size(), 10u); auto itr = received->begin(); ASSERT_EQ(itr.extract(), 6u); // L2CAP PDU size ASSERT_EQ(itr.extract(), 2u); // L2CAP CID ASSERT_EQ(itr.extract(), handle_); ASSERT_GT(itr.extract(), first_packet_number); } } TEST_F(AclManagerWithConnectionTest, invoke_registered_callback_disconnection_complete) { auto reason = ErrorCode::REMOTE_USER_TERMINATED_CONNECTION; EXPECT_CALL(mock_connection_management_callbacks_, OnDisconnection(reason)); test_hci_layer_->Disconnect(handle_, reason); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, acl_send_data_one_connection) { // Send a packet from HCI test_hci_layer_->IncomingAclData(handle_); auto queue_end = connection_->GetAclQueueEnd(); std::unique_ptr> received; do { received = queue_end->TryDequeue(); } while (received == nullptr); PacketView received_packet = *received; // Send a packet from the connection SendAclData(handle_, connection_->GetAclQueueEnd()); auto sent_packet = test_hci_layer_->OutgoingAclData(); // Send another packet from the connection SendAclData(handle_, connection_->GetAclQueueEnd()); sent_packet = test_hci_layer_->OutgoingAclData(); auto reason = ErrorCode::AUTHENTICATION_FAILURE; EXPECT_CALL(mock_connection_management_callbacks_, OnDisconnection(reason)); connection_->Disconnect(DisconnectReason::AUTHENTICATION_FAILURE); auto packet = GetConnectionManagementCommand(OpCode::DISCONNECT); auto command_view = DisconnectView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetConnectionHandle(), handle_); test_hci_layer_->Disconnect(handle_, reason); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, acl_send_data_credits) { // Use all the credits for (uint16_t credits = 0; credits < test_controller_->total_acl_buffers_; credits++) { // Send a packet from the connection SendAclData(handle_, connection_->GetAclQueueEnd()); auto sent_packet = test_hci_layer_->OutgoingAclData(); } // Send another packet from the connection SendAclData(handle_, connection_->GetAclQueueEnd()); test_hci_layer_->AssertNoOutgoingAclData(); test_controller_->CompletePackets(handle_, 1); auto after_credits_sent_packet = test_hci_layer_->OutgoingAclData(); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_switch_role) { acl_manager_->SwitchRole(connection_->GetAddress(), Role::PERIPHERAL); auto packet = GetConnectionManagementCommand(OpCode::SWITCH_ROLE); auto command_view = SwitchRoleView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetBdAddr(), connection_->GetAddress()); ASSERT_EQ(command_view.GetRole(), Role::PERIPHERAL); EXPECT_CALL(mock_connection_management_callbacks_, OnRoleChange(hci::ErrorCode::SUCCESS, Role::PERIPHERAL)); test_hci_layer_->IncomingEvent(RoleChangeBuilder::Create( ErrorCode::SUCCESS, connection_->GetAddress(), Role::PERIPHERAL)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_write_default_link_policy_settings) { uint16_t link_policy_settings = 0x05; acl_manager_->WriteDefaultLinkPolicySettings(link_policy_settings); auto packet = GetConnectionManagementCommand(OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS); auto command_view = WriteDefaultLinkPolicySettingsView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetDefaultLinkPolicySettings(), 0x05); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent( WriteDefaultLinkPolicySettingsCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS)); sync_client_handler(); ASSERT_EQ(link_policy_settings, acl_manager_->ReadDefaultLinkPolicySettings()); } TEST_F(AclManagerWithConnectionTest, send_authentication_requested) { connection_->AuthenticationRequested(); auto packet = GetConnectionManagementCommand(OpCode::AUTHENTICATION_REQUESTED); auto command_view = AuthenticationRequestedView::Create(packet); ASSERT_TRUE(command_view.IsValid()); EXPECT_CALL(mock_connection_management_callbacks_, OnAuthenticationComplete); test_hci_layer_->IncomingEvent( AuthenticationCompleteBuilder::Create(ErrorCode::SUCCESS, handle_)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_read_clock_offset) { connection_->ReadClockOffset(); auto packet = GetConnectionManagementCommand(OpCode::READ_CLOCK_OFFSET); auto command_view = ReadClockOffsetView::Create(packet); ASSERT_TRUE(command_view.IsValid()); EXPECT_CALL(mock_connection_management_callbacks_, OnReadClockOffsetComplete(0x0123)); test_hci_layer_->IncomingEvent( ReadClockOffsetCompleteBuilder::Create(ErrorCode::SUCCESS, handle_, 0x0123)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_hold_mode) { connection_->HoldMode(0x0500, 0x0020); auto packet = GetConnectionManagementCommand(OpCode::HOLD_MODE); auto command_view = HoldModeView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetHoldModeMaxInterval(), 0x0500); ASSERT_EQ(command_view.GetHoldModeMinInterval(), 0x0020); EXPECT_CALL(mock_connection_management_callbacks_, OnModeChange(ErrorCode::SUCCESS, Mode::HOLD, 0x0020)); test_hci_layer_->IncomingEvent( ModeChangeBuilder::Create(ErrorCode::SUCCESS, handle_, Mode::HOLD, 0x0020)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_sniff_mode) { connection_->SniffMode(0x0500, 0x0020, 0x0040, 0x0014); auto packet = GetConnectionManagementCommand(OpCode::SNIFF_MODE); auto command_view = SniffModeView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetSniffMaxInterval(), 0x0500); ASSERT_EQ(command_view.GetSniffMinInterval(), 0x0020); ASSERT_EQ(command_view.GetSniffAttempt(), 0x0040); ASSERT_EQ(command_view.GetSniffTimeout(), 0x0014); EXPECT_CALL(mock_connection_management_callbacks_, OnModeChange(ErrorCode::SUCCESS, Mode::SNIFF, 0x0028)); test_hci_layer_->IncomingEvent( ModeChangeBuilder::Create(ErrorCode::SUCCESS, handle_, Mode::SNIFF, 0x0028)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_exit_sniff_mode) { connection_->ExitSniffMode(); auto packet = GetConnectionManagementCommand(OpCode::EXIT_SNIFF_MODE); auto command_view = ExitSniffModeView::Create(packet); ASSERT_TRUE(command_view.IsValid()); EXPECT_CALL(mock_connection_management_callbacks_, OnModeChange(ErrorCode::SUCCESS, Mode::ACTIVE, 0x00)); test_hci_layer_->IncomingEvent( ModeChangeBuilder::Create(ErrorCode::SUCCESS, handle_, Mode::ACTIVE, 0x00)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_qos_setup) { connection_->QosSetup(ServiceType::BEST_EFFORT, 0x1234, 0x1233, 0x1232, 0x1231); auto packet = GetConnectionManagementCommand(OpCode::QOS_SETUP); auto command_view = QosSetupView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetServiceType(), ServiceType::BEST_EFFORT); ASSERT_EQ(command_view.GetTokenRate(), 0x1234u); ASSERT_EQ(command_view.GetPeakBandwidth(), 0x1233u); ASSERT_EQ(command_view.GetLatency(), 0x1232u); ASSERT_EQ(command_view.GetDelayVariation(), 0x1231u); EXPECT_CALL(mock_connection_management_callbacks_, OnQosSetupComplete(ServiceType::BEST_EFFORT, 0x1234, 0x1233, 0x1232, 0x1231)); test_hci_layer_->IncomingEvent(QosSetupCompleteBuilder::Create( ErrorCode::SUCCESS, handle_, ServiceType::BEST_EFFORT, 0x1234, 0x1233, 0x1232, 0x1231)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_flow_specification) { connection_->FlowSpecification(FlowDirection::OUTGOING_FLOW, ServiceType::BEST_EFFORT, 0x1234, 0x1233, 0x1232, 0x1231); auto packet = GetConnectionManagementCommand(OpCode::FLOW_SPECIFICATION); auto command_view = FlowSpecificationView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetFlowDirection(), FlowDirection::OUTGOING_FLOW); ASSERT_EQ(command_view.GetServiceType(), ServiceType::BEST_EFFORT); ASSERT_EQ(command_view.GetTokenRate(), 0x1234u); ASSERT_EQ(command_view.GetTokenBucketSize(), 0x1233u); ASSERT_EQ(command_view.GetPeakBandwidth(), 0x1232u); ASSERT_EQ(command_view.GetAccessLatency(), 0x1231u); EXPECT_CALL(mock_connection_management_callbacks_, OnFlowSpecificationComplete(FlowDirection::OUTGOING_FLOW, ServiceType::BEST_EFFORT, 0x1234, 0x1233, 0x1232, 0x1231)); test_hci_layer_->IncomingEvent(FlowSpecificationCompleteBuilder::Create( ErrorCode::SUCCESS, handle_, FlowDirection::OUTGOING_FLOW, ServiceType::BEST_EFFORT, 0x1234, 0x1233, 0x1232, 0x1231)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_flush) { connection_->Flush(); auto packet = GetConnectionManagementCommand(OpCode::ENHANCED_FLUSH); auto command_view = EnhancedFlushView::Create(packet); ASSERT_TRUE(command_view.IsValid()); EXPECT_CALL(mock_connection_management_callbacks_, OnFlushOccurred()); test_hci_layer_->IncomingEvent(EnhancedFlushCompleteBuilder::Create(handle_)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_role_discovery) { connection_->RoleDiscovery(); auto packet = GetConnectionManagementCommand(OpCode::ROLE_DISCOVERY); auto command_view = RoleDiscoveryView::Create(packet); ASSERT_TRUE(command_view.IsValid()); EXPECT_CALL(mock_connection_management_callbacks_, OnRoleDiscoveryComplete(Role::CENTRAL)); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent(RoleDiscoveryCompleteBuilder::Create( num_packets, ErrorCode::SUCCESS, handle_, Role::CENTRAL)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_read_link_policy_settings) { connection_->ReadLinkPolicySettings(); auto packet = GetConnectionManagementCommand(OpCode::READ_LINK_POLICY_SETTINGS); auto command_view = ReadLinkPolicySettingsView::Create(packet); ASSERT_TRUE(command_view.IsValid()); EXPECT_CALL(mock_connection_management_callbacks_, OnReadLinkPolicySettingsComplete(0x07)); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent(ReadLinkPolicySettingsCompleteBuilder::Create( num_packets, ErrorCode::SUCCESS, handle_, 0x07)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_write_link_policy_settings) { connection_->WriteLinkPolicySettings(0x05); auto packet = GetConnectionManagementCommand(OpCode::WRITE_LINK_POLICY_SETTINGS); auto command_view = WriteLinkPolicySettingsView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetLinkPolicySettings(), 0x05); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent( WriteLinkPolicySettingsCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS, handle_)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_sniff_subrating) { connection_->SniffSubrating(0x1234, 0x1235, 0x1236); auto packet = GetConnectionManagementCommand(OpCode::SNIFF_SUBRATING); auto command_view = SniffSubratingView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetMaximumLatency(), 0x1234); ASSERT_EQ(command_view.GetMinimumRemoteTimeout(), 0x1235); ASSERT_EQ(command_view.GetMinimumLocalTimeout(), 0x1236); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent( SniffSubratingCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS, handle_)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_read_automatic_flush_timeout) { connection_->ReadAutomaticFlushTimeout(); auto packet = GetConnectionManagementCommand(OpCode::READ_AUTOMATIC_FLUSH_TIMEOUT); auto command_view = ReadAutomaticFlushTimeoutView::Create(packet); ASSERT_TRUE(command_view.IsValid()); EXPECT_CALL(mock_connection_management_callbacks_, OnReadAutomaticFlushTimeoutComplete(0x07ff)); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent(ReadAutomaticFlushTimeoutCompleteBuilder::Create( num_packets, ErrorCode::SUCCESS, handle_, 0x07ff)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_write_automatic_flush_timeout) { connection_->WriteAutomaticFlushTimeout(0x07FF); auto packet = GetConnectionManagementCommand(OpCode::WRITE_AUTOMATIC_FLUSH_TIMEOUT); auto command_view = WriteAutomaticFlushTimeoutView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetFlushTimeout(), 0x07FF); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent(WriteAutomaticFlushTimeoutCompleteBuilder::Create( num_packets, ErrorCode::SUCCESS, handle_)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_read_transmit_power_level) { connection_->ReadTransmitPowerLevel(TransmitPowerLevelType::CURRENT); auto packet = GetConnectionManagementCommand(OpCode::READ_TRANSMIT_POWER_LEVEL); auto command_view = ReadTransmitPowerLevelView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetTransmitPowerLevelType(), TransmitPowerLevelType::CURRENT); EXPECT_CALL(mock_connection_management_callbacks_, OnReadTransmitPowerLevelComplete(0x07)); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent(ReadTransmitPowerLevelCompleteBuilder::Create( num_packets, ErrorCode::SUCCESS, handle_, 0x07)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_read_link_supervision_timeout) { connection_->ReadLinkSupervisionTimeout(); auto packet = GetConnectionManagementCommand(OpCode::READ_LINK_SUPERVISION_TIMEOUT); auto command_view = ReadLinkSupervisionTimeoutView::Create(packet); ASSERT_TRUE(command_view.IsValid()); EXPECT_CALL(mock_connection_management_callbacks_, OnReadLinkSupervisionTimeoutComplete(0x5677)); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent(ReadLinkSupervisionTimeoutCompleteBuilder::Create( num_packets, ErrorCode::SUCCESS, handle_, 0x5677)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_write_link_supervision_timeout) { connection_->WriteLinkSupervisionTimeout(0x5678); auto packet = GetConnectionManagementCommand(OpCode::WRITE_LINK_SUPERVISION_TIMEOUT); auto command_view = WriteLinkSupervisionTimeoutView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetLinkSupervisionTimeout(), 0x5678); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent(WriteLinkSupervisionTimeoutCompleteBuilder::Create( num_packets, ErrorCode::SUCCESS, handle_)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_read_failed_contact_counter) { connection_->ReadFailedContactCounter(); auto packet = GetConnectionManagementCommand(OpCode::READ_FAILED_CONTACT_COUNTER); auto command_view = ReadFailedContactCounterView::Create(packet); ASSERT_TRUE(command_view.IsValid()); EXPECT_CALL(mock_connection_management_callbacks_, OnReadFailedContactCounterComplete(0x00)); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent(ReadFailedContactCounterCompleteBuilder::Create( num_packets, ErrorCode::SUCCESS, handle_, 0x00)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_reset_failed_contact_counter) { connection_->ResetFailedContactCounter(); auto packet = GetConnectionManagementCommand(OpCode::RESET_FAILED_CONTACT_COUNTER); auto command_view = ResetFailedContactCounterView::Create(packet); ASSERT_TRUE(command_view.IsValid()); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent(ResetFailedContactCounterCompleteBuilder::Create( num_packets, ErrorCode::SUCCESS, handle_)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_read_link_quality) { connection_->ReadLinkQuality(); auto packet = GetConnectionManagementCommand(OpCode::READ_LINK_QUALITY); auto command_view = ReadLinkQualityView::Create(packet); ASSERT_TRUE(command_view.IsValid()); EXPECT_CALL(mock_connection_management_callbacks_, OnReadLinkQualityComplete(0xa9)); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent( ReadLinkQualityCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS, handle_, 0xa9)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_read_afh_channel_map) { connection_->ReadAfhChannelMap(); auto packet = GetConnectionManagementCommand(OpCode::READ_AFH_CHANNEL_MAP); auto command_view = ReadAfhChannelMapView::Create(packet); ASSERT_TRUE(command_view.IsValid()); std::array afh_channel_map = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}; EXPECT_CALL(mock_connection_management_callbacks_, OnReadAfhChannelMapComplete(AfhMode::AFH_ENABLED, afh_channel_map)); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent(ReadAfhChannelMapCompleteBuilder::Create( num_packets, ErrorCode::SUCCESS, handle_, AfhMode::AFH_ENABLED, afh_channel_map)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_read_rssi) { connection_->ReadRssi(); auto packet = GetConnectionManagementCommand(OpCode::READ_RSSI); auto command_view = ReadRssiView::Create(packet); ASSERT_TRUE(command_view.IsValid()); sync_client_handler(); EXPECT_CALL(mock_connection_management_callbacks_, OnReadRssiComplete(0x00)); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent( ReadRssiCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS, handle_, 0x00)); sync_client_handler(); } TEST_F(AclManagerWithConnectionTest, send_read_clock) { connection_->ReadClock(WhichClock::LOCAL); auto packet = GetConnectionManagementCommand(OpCode::READ_CLOCK); auto command_view = ReadClockView::Create(packet); ASSERT_TRUE(command_view.IsValid()); ASSERT_EQ(command_view.GetWhichClock(), WhichClock::LOCAL); EXPECT_CALL(mock_connection_management_callbacks_, OnReadClockComplete(0x00002e6a, 0x0000)); uint8_t num_packets = 1; test_hci_layer_->IncomingEvent(ReadClockCompleteBuilder::Create(num_packets, ErrorCode::SUCCESS, handle_, 0x00002e6a, 0x0000)); sync_client_handler(); } class AclManagerWithResolvableAddressTest : public AclManagerNoCallbacksTest { protected: void SetUp() override { test_hci_layer_ = new HciLayerFake; // Ownership is transferred to registry test_controller_ = new TestController; fake_registry_.InjectTestModule(&HciLayer::Factory, test_hci_layer_); fake_registry_.InjectTestModule(&Controller::Factory, test_controller_); client_handler_ = fake_registry_.GetTestModuleHandler(&HciLayer::Factory); ASSERT_NE(client_handler_, nullptr); fake_registry_.Start(&thread_); acl_manager_ = static_cast(fake_registry_.GetModuleUnderTest(&AclManager::Factory)); Address::FromString("A1:A2:A3:A4:A5:A6", remote); hci::Address address; Address::FromString("D0:05:04:03:02:01", address); hci::AddressWithType address_with_type(address, hci::AddressType::RANDOM_DEVICE_ADDRESS); acl_manager_->RegisterCallbacks(&mock_connection_callback_, client_handler_); acl_manager_->RegisterLeCallbacks(&mock_le_connection_callbacks_, client_handler_); auto minimum_rotation_time = std::chrono::milliseconds(7 * 60 * 1000); auto maximum_rotation_time = std::chrono::milliseconds(15 * 60 * 1000); acl_manager_->SetPrivacyPolicyForInitiatorAddress( LeAddressManager::AddressPolicy::USE_RESOLVABLE_ADDRESS, address_with_type, minimum_rotation_time, maximum_rotation_time); GetConnectionManagementCommand(OpCode::LE_SET_RANDOM_ADDRESS); test_hci_layer_->IncomingEvent( LeSetRandomAddressCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); } }; TEST_F(AclManagerWithResolvableAddressTest, create_connection_cancel_fail) { auto remote_with_type_ = AddressWithType(remote, AddressType::PUBLIC_DEVICE_ADDRESS); acl_manager_->CreateLeConnection(remote_with_type_, true); // Add device to connect list GetConnectionManagementCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); test_hci_layer_->IncomingEvent( LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); // send create connection command GetConnectionManagementCommand(OpCode::LE_CREATE_CONNECTION); test_hci_layer_->IncomingEvent(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&AclManager::Factory, std::chrono::milliseconds(20)); Address remote2; Address::FromString("A1:A2:A3:A4:A5:A7", remote2); auto remote_with_type2 = AddressWithType(remote2, AddressType::PUBLIC_DEVICE_ADDRESS); // create another connection acl_manager_->CreateLeConnection(remote_with_type2, true); // cancel previous connection GetConnectionManagementCommand(OpCode::LE_CREATE_CONNECTION_CANCEL); // receive connection complete of first device test_hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x123, Role::PERIPHERAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, 0x0100, 0x0010, 0x0011, ClockAccuracy::PPM_30)); // receive create connection cancel complete with ErrorCode::CONNECTION_ALREADY_EXISTS test_hci_layer_->IncomingEvent(LeCreateConnectionCancelCompleteBuilder::Create( 0x01, ErrorCode::CONNECTION_ALREADY_EXISTS)); // Add another device to connect list GetConnectionManagementCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); test_hci_layer_->IncomingEvent( LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); // Sync events. } class AclManagerLifeCycleTest : public AclManagerNoCallbacksTest { protected: void SetUp() override { AclManagerNoCallbacksTest::SetUp(); acl_manager_->RegisterCallbacks(&mock_connection_callback_, client_handler_); acl_manager_->RegisterLeCallbacks(&mock_le_connection_callbacks_, client_handler_); } AddressWithType remote_with_type_; uint16_t handle_{0x123}; }; TEST_F(AclManagerLifeCycleTest, unregister_classic_after_create_connection) { // Inject create connection acl_manager_->CreateConnection(remote); auto connection_command = GetConnectionManagementCommand(OpCode::CREATE_CONNECTION); // Unregister callbacks after sending connection request auto promise = std::promise(); auto future = promise.get_future(); acl_manager_->UnregisterCallbacks(&mock_connection_callback_, std::move(promise)); future.get(); // Inject peer sending connection complete auto connection_future = GetConnectionFuture(); test_hci_layer_->IncomingEvent(ConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, handle_, remote, LinkType::ACL, Enable::DISABLED)); sync_client_handler(); auto connection_future_status = connection_future.wait_for(kShortTimeout); ASSERT_NE(connection_future_status, std::future_status::ready); } TEST_F(AclManagerLifeCycleTest, unregister_le_before_connection_complete) { AddressWithType remote_with_type(remote, AddressType::PUBLIC_DEVICE_ADDRESS); acl_manager_->CreateLeConnection(remote_with_type, true); GetConnectionManagementCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); test_hci_layer_->IncomingEvent( LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); auto packet = GetConnectionManagementCommand(OpCode::LE_CREATE_CONNECTION); auto le_connection_management_command_view = LeConnectionManagementCommandView::Create(AclCommandView::Create(packet)); auto command_view = LeCreateConnectionView::Create(le_connection_management_command_view); ASSERT_TRUE(command_view.IsValid()); if (use_accept_list_) { ASSERT_EQ(command_view.GetPeerAddress(), hci::Address::kEmpty); } else { ASSERT_EQ(command_view.GetPeerAddress(), remote); } ASSERT_EQ(command_view.GetPeerAddressType(), AddressType::PUBLIC_DEVICE_ADDRESS); // Unregister callbacks after sending connection request auto promise = std::promise(); auto future = promise.get_future(); acl_manager_->UnregisterLeCallbacks(&mock_le_connection_callbacks_, std::move(promise)); future.get(); auto connection_future = GetLeConnectionFuture(); test_hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x123, Role::PERIPHERAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, 0x0100, 0x0010, 0x0500, ClockAccuracy::PPM_30)); sync_client_handler(); auto connection_future_status = connection_future.wait_for(kShortTimeout); ASSERT_NE(connection_future_status, std::future_status::ready); } TEST_F(AclManagerLifeCycleTest, unregister_le_before_enhanced_connection_complete) { AddressWithType remote_with_type(remote, AddressType::PUBLIC_DEVICE_ADDRESS); acl_manager_->CreateLeConnection(remote_with_type, true); GetConnectionManagementCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); test_hci_layer_->IncomingEvent( LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); auto packet = GetConnectionManagementCommand(OpCode::LE_CREATE_CONNECTION); auto le_connection_management_command_view = LeConnectionManagementCommandView::Create(AclCommandView::Create(packet)); auto command_view = LeCreateConnectionView::Create(le_connection_management_command_view); ASSERT_TRUE(command_view.IsValid()); if (use_accept_list_) { ASSERT_EQ(command_view.GetPeerAddress(), hci::Address::kEmpty); } else { ASSERT_EQ(command_view.GetPeerAddress(), remote); } ASSERT_EQ(command_view.GetPeerAddressType(), AddressType::PUBLIC_DEVICE_ADDRESS); // Unregister callbacks after sending connection request auto promise = std::promise(); auto future = promise.get_future(); acl_manager_->UnregisterLeCallbacks(&mock_le_connection_callbacks_, std::move(promise)); future.get(); auto connection_future = GetLeConnectionFuture(); test_hci_layer_->IncomingLeMetaEvent(LeEnhancedConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x123, Role::PERIPHERAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, Address::kEmpty, Address::kEmpty, 0x0100, 0x0010, 0x0500, ClockAccuracy::PPM_30)); sync_client_handler(); auto connection_future_status = connection_future.wait_for(kShortTimeout); ASSERT_NE(connection_future_status, std::future_status::ready); } class AclManagerWithConnectionAssemblerTest : public AclManagerWithConnectionTest { protected: void SetUp() override { AclManagerWithConnectionTest::SetUp(); connection_queue_end_ = connection_->GetAclQueueEnd(); } std::vector MakeAclPayload(size_t length, uint16_t cid, uint8_t offset) { std::vector acl_payload; acl_payload.push_back(length & 0xff); acl_payload.push_back((length >> 8u) & 0xff); acl_payload.push_back(cid & 0xff); acl_payload.push_back((cid >> 8u) & 0xff); for (uint8_t i = 0; i < length; i++) { acl_payload.push_back(i + offset); } return acl_payload; } void SendSinglePacket(const std::vector& acl_payload) { auto payload_builder = std::make_unique(acl_payload); test_hci_layer_->IncomingAclData( handle_, AclBuilder::Create(handle_, PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE, BroadcastFlag::POINT_TO_POINT, std::move(payload_builder))); } void ReceiveAndCheckSinglePacket(const std::vector& acl_payload) { std::unique_ptr> received; do { received = connection_queue_end_->TryDequeue(); } while (received == nullptr); std::vector received_vector; for (uint8_t byte : *received) { received_vector.push_back(byte); } EXPECT_THAT(received_vector, ElementsAreArray(acl_payload)); } void SendAndReceiveSinglePacket(const std::vector& acl_payload) { SendSinglePacket(acl_payload); ReceiveAndCheckSinglePacket(acl_payload); } void TearDown() override { // Make sure that all previous packets were received and the assembler is in a good state. SendAndReceiveSinglePacket(MakeAclPayload(0x60, 0xACC, 3)); AclManagerWithConnectionTest::TearDown(); } AclConnection::QueueUpEnd* connection_queue_end_{}; }; TEST_F(AclManagerWithConnectionAssemblerTest, assembler_test_single_packet) {} TEST_F(AclManagerWithConnectionAssemblerTest, assembler_test_short_packet_discarded) { std::vector invalid_payload{1, 2}; test_hci_layer_->IncomingAclData( handle_, AclBuilder::Create(handle_, PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE, BroadcastFlag::POINT_TO_POINT, std::make_unique(invalid_payload))); } TEST_F(AclManagerWithConnectionAssemblerTest, assembler_test_two_short_packets_discarded) { std::vector invalid_payload{1, 2}; test_hci_layer_->IncomingAclData( handle_, AclBuilder::Create(handle_, PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE, BroadcastFlag::POINT_TO_POINT, std::make_unique(invalid_payload))); test_hci_layer_->IncomingAclData( handle_, AclBuilder::Create(handle_, PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE, BroadcastFlag::POINT_TO_POINT, std::make_unique(invalid_payload))); } TEST_F(AclManagerWithConnectionAssemblerTest, assembler_test_single_valid_packet) { SendAndReceiveSinglePacket(MakeAclPayload(20, 0x41, 2)); } TEST_F(AclManagerWithConnectionAssemblerTest, assembler_test_one_byte_packets) { size_t payload_size = 0x30; std::vector payload = MakeAclPayload(payload_size, 0xABB /* cid */, 4 /* offset */); test_hci_layer_->IncomingAclData( handle_, AclBuilder::Create(handle_, PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE, BroadcastFlag::POINT_TO_POINT, std::make_unique(std::vector{ payload.cbegin(), payload.cbegin() + 1}))); for (size_t i = 1; i < payload.size(); i++) { test_hci_layer_->IncomingAclData( handle_, AclBuilder::Create(handle_, PacketBoundaryFlag::CONTINUING_FRAGMENT, BroadcastFlag::POINT_TO_POINT, std::make_unique(std::vector{ payload.cbegin() + i, payload.cbegin() + i + 1}))); } ReceiveAndCheckSinglePacket(payload); } TEST_F(AclManagerWithConnectionAssemblerTest, assembler_test_two_byte_packets) { size_t payload_size = 0x30; // must be even std::vector payload = MakeAclPayload(payload_size, 0xABB /* cid */, 4 /* offset */); test_hci_layer_->IncomingAclData( handle_, AclBuilder::Create(handle_, PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE, BroadcastFlag::POINT_TO_POINT, std::make_unique(std::vector{ payload.cbegin(), payload.cbegin() + 2}))); for (size_t i = 1; i < payload.size() / 2; i++) { test_hci_layer_->IncomingAclData( handle_, AclBuilder::Create(handle_, PacketBoundaryFlag::CONTINUING_FRAGMENT, BroadcastFlag::POINT_TO_POINT, std::make_unique(std::vector{ payload.cbegin() + 2 * i, payload.cbegin() + 2 * (i + 1)}))); } ReceiveAndCheckSinglePacket(payload); } TEST_F(AclManagerWithConnectionAssemblerTest, assembler_test_continuation_without_begin) { size_t payload_size = 0x30; std::vector payload = MakeAclPayload(payload_size, 0xABB /* cid */, 4 /* offset */); test_hci_layer_->IncomingAclData( handle_, AclBuilder::Create(handle_, PacketBoundaryFlag::CONTINUING_FRAGMENT, BroadcastFlag::POINT_TO_POINT, std::make_unique(std::vector{ payload.cbegin(), payload.cend()}))); } TEST_F(AclManagerWithConnectionAssemblerTest, assembler_test_drop_broadcasts) { test_hci_layer_->IncomingAclData( handle_, AclBuilder::Create(handle_, PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE, BroadcastFlag::ACTIVE_PERIPHERAL_BROADCAST, std::make_unique(MakeAclPayload( 20, 0xBBB /* cid */, 5 /* offset */)))); } TEST_F(AclManagerWithConnectionAssemblerTest, assembler_test_drop_non_flushable) { test_hci_layer_->IncomingAclData( handle_, AclBuilder::Create(handle_, PacketBoundaryFlag::FIRST_NON_AUTOMATICALLY_FLUSHABLE, BroadcastFlag::POINT_TO_POINT, std::make_unique( MakeAclPayload(20, 0xAAA /* cid */, 6 /* offset */)))); } } // namespace acl_manager } // namespace hci } // namespace bluetooth