Loading system/gd/hci/acl_manager/le_impl.h +114 −61 Original line number Diff line number Diff line Loading @@ -306,13 +306,17 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { auto status = connection_complete.GetStatus(); auto address = connection_complete.GetPeerAddress(); auto peer_address_type = connection_complete.GetPeerAddressType(); auto role = connection_complete.GetRole(); AddressWithType remote_address(address, peer_address_type); AddressWithType local_address = le_address_manager_->GetCurrentAddress(); const bool in_filter_accept_list = is_device_in_connect_list(remote_address); if (role == hci::Role::CENTRAL) { connectability_state_ = ConnectabilityState::DISARMED; if (status == ErrorCode::UNKNOWN_CONNECTION && pause_connection) { on_le_connection_canceled_on_pause(); return; } AddressWithType remote_address(address, peer_address_type); AddressWithType local_address = le_address_manager_->GetCurrentAddress(); on_common_le_connection_complete(remote_address); if (status == ErrorCode::UNKNOWN_CONNECTION) { if (remote_address.GetAddress() != Address::kEmpty) { Loading @@ -325,7 +329,6 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { arm_on_resume_ = false; ready_to_unregister = true; const bool in_filter_accept_list = is_device_in_connect_list(remote_address); remove_device_from_connect_list(remote_address); if (!connect_list.empty()) { Loading @@ -339,11 +342,35 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { } if (status != ErrorCode::SUCCESS) { le_client_handler_->Post(common::BindOnce(&LeConnectionCallbacks::OnLeConnectFail, common::Unretained(le_client_callbacks_), remote_address, status)); le_client_handler_->Post(common::BindOnce( &LeConnectionCallbacks::OnLeConnectFail, common::Unretained(le_client_callbacks_), remote_address, status)); return; } } else { LOG_INFO("Received connection complete with Peripheral role"); if (le_client_handler_ == nullptr) { LOG_ERROR("No callbacks to call"); return; } if (status != ErrorCode::SUCCESS) { std::string error_code = ErrorCodeText(status); LOG_WARN("Received on_le_connection_complete with error code %s", error_code.c_str()); return; } if (in_filter_accept_list) { LOG_INFO( "Received incoming connection of device in filter accept_list, %s", PRIVATE_ADDRESS_WITH_TYPE(remote_address)); remove_device_from_connect_list(remote_address); if (create_connection_timeout_alarms_.find(remote_address) != create_connection_timeout_alarms_.end()) { create_connection_timeout_alarms_.at(remote_address).Cancel(); create_connection_timeout_alarms_.erase(remote_address); } } } uint16_t conn_interval = connection_complete.GetConnInterval(); uint16_t conn_latency = connection_complete.GetConnLatency(); uint16_t supervision_timeout = connection_complete.GetSupervisionTimeout(); Loading @@ -352,7 +379,6 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { return; } auto role = connection_complete.GetRole(); uint16_t handle = connection_complete.GetConnectionHandle(); auto queue = std::make_shared<AclConnection::Queue>(10); auto queue_down_end = queue->GetDownEnd(); Loading Loading @@ -380,14 +406,9 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { auto address = connection_complete.GetPeerAddress(); auto peer_address_type = connection_complete.GetPeerAddressType(); auto peer_resolvable_address = connection_complete.GetPeerResolvablePrivateAddress(); connectability_state_ = ConnectabilityState::DISARMED; if (status == ErrorCode::UNKNOWN_CONNECTION && pause_connection) { on_le_connection_canceled_on_pause(); return; } auto role = connection_complete.GetRole(); AddressType remote_address_type; switch (peer_address_type) { case AddressType::PUBLIC_DEVICE_ADDRESS: case AddressType::PUBLIC_IDENTITY_ADDRESS: Loading @@ -399,6 +420,15 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { break; } AddressWithType remote_address(address, remote_address_type); const bool in_filter_accept_list = is_device_in_connect_list(remote_address); if (role == hci::Role::CENTRAL) { connectability_state_ = ConnectabilityState::DISARMED; if (status == ErrorCode::UNKNOWN_CONNECTION && pause_connection) { on_le_connection_canceled_on_pause(); return; } on_common_le_connection_complete(remote_address); if (status == ErrorCode::UNKNOWN_CONNECTION) { Loading @@ -412,7 +442,6 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { arm_on_resume_ = false; ready_to_unregister = true; const bool in_filter_accept_list = is_device_in_connect_list(remote_address); remove_device_from_connect_list(remote_address); if (!connect_list.empty()) { Loading @@ -426,12 +455,36 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { } if (status != ErrorCode::SUCCESS) { le_client_handler_->Post(common::BindOnce(&LeConnectionCallbacks::OnLeConnectFail, common::Unretained(le_client_callbacks_), remote_address, status)); le_client_handler_->Post(common::BindOnce( &LeConnectionCallbacks::OnLeConnectFail, common::Unretained(le_client_callbacks_), remote_address, status)); return; } auto role = connection_complete.GetRole(); } else { LOG_INFO("Received connection complete with Peripheral role"); if (le_client_handler_ == nullptr) { LOG_ERROR("No callbacks to call"); return; } if (status != ErrorCode::SUCCESS) { std::string error_code = ErrorCodeText(status); LOG_WARN("Received on_le_enhanced_connection_complete with error code %s", error_code.c_str()); return; } if (in_filter_accept_list) { LOG_INFO( "Received incoming connection of device in filter accept_list, %s", PRIVATE_ADDRESS_WITH_TYPE(remote_address)); remove_device_from_connect_list(remote_address); if (create_connection_timeout_alarms_.find(remote_address) != create_connection_timeout_alarms_.end()) { create_connection_timeout_alarms_.at(remote_address).Cancel(); create_connection_timeout_alarms_.erase(remote_address); } } } AddressWithType local_address; if (role == hci::Role::CENTRAL) { local_address = le_address_manager_->GetCurrentAddress(); Loading system/gd/hci/acl_manager/le_impl_test.cc +292 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "hci/acl_manager/le_impl.h" #include <gmock/gmock.h> #include <gtest/gtest.h> #include <chrono> Loading @@ -23,6 +24,7 @@ #include "common/bidi_queue.h" #include "common/callback.h" #include "hci/acl_manager.h" #include "hci/acl_manager/le_connection_management_callbacks.h" #include "hci/address_with_type.h" #include "hci/controller.h" #include "hci/hci_packets.h" Loading @@ -41,8 +43,26 @@ namespace bluetooth { namespace hci { namespace acl_manager { PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) { auto bytes = std::make_shared<std::vector<uint8_t>>(); BitInserter i(*bytes); bytes->reserve(packet->size()); packet->Serialize(i); return packet::PacketView<packet::kLittleEndian>(bytes); } class TestController : public Controller { public: bool IsSupported(OpCode op_code) const override { LOG_INFO("IsSupported"); return supported_opcodes_.count(op_code) == 1; } void AddSupported(OpCode op_code) { LOG_INFO("AddSupported"); supported_opcodes_.insert(op_code); } uint16_t GetNumAclPacketBuffers() const { return max_acl_packet_credits_; } Loading Loading @@ -77,6 +97,7 @@ class TestController : public Controller { private: CompletedAclPacketsCallback acl_credits_callback_; std::set<OpCode> supported_opcodes_{}; }; class TestHciLayer : public HciLayer { Loading @@ -98,7 +119,90 @@ class TestHciLayer : public HciLayer { HciLayer& hci_; }; void EnqueueCommand( std::unique_ptr<CommandBuilder> command, common::ContextualOnceCallback<void(CommandStatusView)> on_status) override { command_queue_.push(std::move(command)); command_status_callbacks.push_back(std::move(on_status)); if (command_promise_ != nullptr) { command_promise_->set_value(); command_promise_.reset(); } } void EnqueueCommand( std::unique_ptr<CommandBuilder> command, common::ContextualOnceCallback<void(CommandCompleteView)> on_complete) override { command_queue_.push(std::move(command)); command_complete_callbacks.push_back(std::move(on_complete)); if (command_promise_ != nullptr) { command_promise_->set_value(); command_promise_.reset(); } } public: void SetCommandFuture() { ASSERT_LOG(command_promise_ == nullptr, "Promises, Promises, ... Only one at a time."); command_promise_ = std::make_unique<std::promise<void>>(); command_future_ = std::make_unique<std::future<void>>(command_promise_->get_future()); } CommandView GetLastCommand() { if (command_queue_.empty()) { return CommandView::Create(PacketView<kLittleEndian>(std::make_shared<std::vector<uint8_t>>())); } auto last = std::move(command_queue_.front()); command_queue_.pop(); return CommandView::Create(GetPacketView(std::move(last))); } CommandView GetCommand(OpCode op_code) { if (!command_queue_.empty()) { std::lock_guard<std::mutex> lock(mutex_); if (command_future_ != nullptr) { command_future_.reset(); command_promise_.reset(); } } else if (command_future_ != nullptr) { auto result = command_future_->wait_for(std::chrono::milliseconds(1000)); EXPECT_NE(std::future_status::timeout, result); } std::lock_guard<std::mutex> lock(mutex_); ASSERT_LOG( !command_queue_.empty(), "Expecting command %s but command queue was empty", OpCodeText(op_code).c_str()); CommandView command_packet_view = GetLastCommand(); EXPECT_TRUE(command_packet_view.IsValid()); EXPECT_EQ(command_packet_view.GetOpCode(), op_code); return command_packet_view; } void CommandCompleteCallback(std::unique_ptr<EventBuilder> event_builder) { auto event = EventView::Create(GetPacketView(std::move(event_builder))); CommandCompleteView complete_view = CommandCompleteView::Create(event); ASSERT_TRUE(complete_view.IsValid()); ASSERT_NE((uint16_t)command_complete_callbacks.size(), 0); std::move(command_complete_callbacks.front()).Invoke(complete_view); command_complete_callbacks.pop_front(); } void CommandStatusCallback(std::unique_ptr<EventBuilder> event_builder) { auto event = EventView::Create(GetPacketView(std::move(event_builder))); CommandStatusView status_view = CommandStatusView::Create(event); ASSERT_TRUE(status_view.IsValid()); ASSERT_NE((uint16_t)command_status_callbacks.size(), 0); std::move(command_status_callbacks.front()).Invoke(status_view); command_status_callbacks.pop_front(); } void IncomingLeMetaEvent(std::unique_ptr<LeMetaEventBuilder> event_builder) { auto packet = GetPacketView(std::move(event_builder)); EventView event = EventView::Create(packet); LeMetaEventView meta_event_view = LeMetaEventView::Create(event); EXPECT_TRUE(meta_event_view.IsValid()); le_event_handler_.Invoke(meta_event_view); } LeAclConnectionInterface* GetLeAclConnectionInterface( common::ContextualCallback<void(LeMetaEventView)> event_handler, common::ContextualCallback<void(uint16_t, ErrorCode)> on_disconnect, Loading @@ -107,12 +211,21 @@ class TestHciLayer : public HciLayer { on_read_remote_version) override { disconnect_handlers_.push_back(on_disconnect); read_remote_version_handlers_.push_back(on_read_remote_version); return &le_acl_connection_manager_interface_2_; le_event_handler_ = event_handler; return &le_acl_connection_manager_interface_; } void PutLeAclConnectionInterface() override {} CommandInterfaceImpl<AclCommandBuilder> le_acl_connection_manager_interface_2_{*this}; private: std::list<common::ContextualOnceCallback<void(CommandCompleteView)>> command_complete_callbacks; std::list<common::ContextualOnceCallback<void(CommandStatusView)>> command_status_callbacks; common::ContextualCallback<void(LeMetaEventView)> le_event_handler_; std::queue<std::unique_ptr<CommandBuilder>> command_queue_; std::unique_ptr<std::promise<void>> command_promise_; std::unique_ptr<std::future<void>> command_future_; mutable std::mutex mutex_; CommandInterfaceImpl<AclCommandBuilder> le_acl_connection_manager_interface_{*this}; }; class LeImplTest : public ::testing::Test { Loading @@ -127,6 +240,24 @@ class LeImplTest : public ::testing::Test { hci_queue_.GetDownEnd()->RegisterDequeue( handler_, common::Bind(&LeImplTest::HciDownEndDequeue, common::Unretained(this))); le_impl_ = new le_impl(hci_layer_, controller_, handler_, round_robin_scheduler_, true); le_impl_->handle_register_le_callbacks(&mock_le_connection_callbacks_, handler_); // Set address policy hci_layer_->SetCommandFuture(); hci::Address address; Address::FromString("D0:05:04:03:02:01", address); hci::AddressWithType address_with_type(address, hci::AddressType::RANDOM_DEVICE_ADDRESS); crypto_toolbox::Octet16 rotation_irk{}; auto minimum_rotation_time = std::chrono::milliseconds(7 * 60 * 1000); auto maximum_rotation_time = std::chrono::milliseconds(15 * 60 * 1000); le_impl_->set_privacy_policy_for_initiator_address( LeAddressManager::AddressPolicy::USE_STATIC_ADDRESS, address_with_type, rotation_irk, minimum_rotation_time, maximum_rotation_time); hci_layer_->GetCommand(OpCode::LE_SET_RANDOM_ADDRESS); hci_layer_->CommandCompleteCallback(LeSetRandomAddressCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); } void TearDown() override { Loading Loading @@ -172,6 +303,16 @@ class LeImplTest : public ::testing::Test { } } class MockLeConnectionCallbacks : public LeConnectionCallbacks { public: MOCK_METHOD( void, OnLeConnectSuccess, (AddressWithType address_with_type, std::unique_ptr<LeAclConnection> connection), (override)); MOCK_METHOD(void, OnLeConnectFail, (AddressWithType, ErrorCode reason), (override)); } mock_le_connection_callbacks_; uint16_t packet_count_; std::unique_ptr<std::promise<void>> packet_promise_; std::unique_ptr<std::future<void>> packet_future_; Loading @@ -181,7 +322,7 @@ class LeImplTest : public ::testing::Test { Thread* thread_; Handler* handler_; HciLayer* hci_layer_{nullptr}; TestHciLayer* hci_layer_{nullptr}; TestController* controller_; RoundRobinScheduler* round_robin_scheduler_{nullptr}; Loading Loading @@ -228,6 +369,154 @@ TEST_F(LeImplTest, remove_device_from_connect_list) { ASSERT_EQ(0UL, le_impl_->connect_list.size()); } TEST_F(LeImplTest, connection_complete_with_periperal_role) { // Create connection hci_layer_->SetCommandFuture(); le_impl_->create_le_connection( {{0x21, 0x22, 0x23, 0x24, 0x25, 0x26}, AddressType::PUBLIC_DEVICE_ADDRESS}, true, false); hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); hci_layer_->SetCommandFuture(); hci_layer_->CommandCompleteCallback(LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION); hci_layer_->CommandStatusCallback(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); sync_handler(); // Check state is ARMED ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_); // Receive connection complete of incoming connection (Role::PERIPHERAL) hci::Address remote_address; Address::FromString("D0:05:04:03:02:01", remote_address); hci::AddressWithType address_with_type(remote_address, hci::AddressType::PUBLIC_DEVICE_ADDRESS); EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectSuccess(address_with_type, testing::_)); hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x0041, Role::PERIPHERAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote_address, 0x0024, 0x0000, 0x0011, ClockAccuracy::PPM_30)); sync_handler(); // Check state is still ARMED ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_); } TEST_F(LeImplTest, enhanced_connection_complete_with_periperal_role) { controller_->AddSupported(OpCode::LE_EXTENDED_CREATE_CONNECTION); // Create connection hci_layer_->SetCommandFuture(); le_impl_->create_le_connection( {{0x21, 0x22, 0x23, 0x24, 0x25, 0x26}, AddressType::PUBLIC_DEVICE_ADDRESS}, true, false); hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); hci_layer_->SetCommandFuture(); hci_layer_->CommandCompleteCallback(LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); hci_layer_->GetCommand(OpCode::LE_EXTENDED_CREATE_CONNECTION); hci_layer_->CommandStatusCallback(LeExtendedCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); sync_handler(); // Check state is ARMED ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_); // Receive connection complete of incoming connection (Role::PERIPHERAL) hci::Address remote_address; Address::FromString("D0:05:04:03:02:01", remote_address); hci::AddressWithType address_with_type(remote_address, hci::AddressType::PUBLIC_DEVICE_ADDRESS); EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectSuccess(address_with_type, testing::_)); hci_layer_->IncomingLeMetaEvent(LeEnhancedConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x0041, Role::PERIPHERAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote_address, Address::kEmpty, Address::kEmpty, 0x0024, 0x0000, 0x0011, ClockAccuracy::PPM_30)); sync_handler(); // Check state is still ARMED ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_); } TEST_F(LeImplTest, connection_complete_with_central_role) { hci::Address remote_address; Address::FromString("D0:05:04:03:02:01", remote_address); hci::AddressWithType address_with_type(remote_address, hci::AddressType::PUBLIC_DEVICE_ADDRESS); // Create connection hci_layer_->SetCommandFuture(); le_impl_->create_le_connection(address_with_type, true, false); hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); hci_layer_->SetCommandFuture(); hci_layer_->CommandCompleteCallback(LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION); hci_layer_->CommandStatusCallback(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); sync_handler(); // Check state is ARMED ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_); // Receive connection complete of outgoing connection (Role::CENTRAL) EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectSuccess(address_with_type, testing::_)); hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x0041, Role::CENTRAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote_address, 0x0024, 0x0000, 0x0011, ClockAccuracy::PPM_30)); sync_handler(); // Check state is DISARMED ASSERT_EQ(ConnectabilityState::DISARMED, le_impl_->connectability_state_); } TEST_F(LeImplTest, enhanced_connection_complete_with_central_role) { controller_->AddSupported(OpCode::LE_EXTENDED_CREATE_CONNECTION); hci::Address remote_address; Address::FromString("D0:05:04:03:02:01", remote_address); hci::AddressWithType address_with_type(remote_address, hci::AddressType::PUBLIC_DEVICE_ADDRESS); // Create connection hci_layer_->SetCommandFuture(); le_impl_->create_le_connection(address_with_type, true, false); hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); hci_layer_->SetCommandFuture(); hci_layer_->CommandCompleteCallback(LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); hci_layer_->GetCommand(OpCode::LE_EXTENDED_CREATE_CONNECTION); hci_layer_->CommandStatusCallback(LeExtendedCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); sync_handler(); // Check state is ARMED ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_); // Receive connection complete of outgoing connection (Role::CENTRAL) EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectSuccess(address_with_type, testing::_)); hci_layer_->IncomingLeMetaEvent(LeEnhancedConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x0041, Role::CENTRAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote_address, Address::kEmpty, Address::kEmpty, 0x0024, 0x0000, 0x0011, ClockAccuracy::PPM_30)); sync_handler(); // Check state is DISARMED ASSERT_EQ(ConnectabilityState::DISARMED, le_impl_->connectability_state_); } } // namespace acl_manager } // namespace hci } // namespace bluetooth Loading
system/gd/hci/acl_manager/le_impl.h +114 −61 Original line number Diff line number Diff line Loading @@ -306,13 +306,17 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { auto status = connection_complete.GetStatus(); auto address = connection_complete.GetPeerAddress(); auto peer_address_type = connection_complete.GetPeerAddressType(); auto role = connection_complete.GetRole(); AddressWithType remote_address(address, peer_address_type); AddressWithType local_address = le_address_manager_->GetCurrentAddress(); const bool in_filter_accept_list = is_device_in_connect_list(remote_address); if (role == hci::Role::CENTRAL) { connectability_state_ = ConnectabilityState::DISARMED; if (status == ErrorCode::UNKNOWN_CONNECTION && pause_connection) { on_le_connection_canceled_on_pause(); return; } AddressWithType remote_address(address, peer_address_type); AddressWithType local_address = le_address_manager_->GetCurrentAddress(); on_common_le_connection_complete(remote_address); if (status == ErrorCode::UNKNOWN_CONNECTION) { if (remote_address.GetAddress() != Address::kEmpty) { Loading @@ -325,7 +329,6 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { arm_on_resume_ = false; ready_to_unregister = true; const bool in_filter_accept_list = is_device_in_connect_list(remote_address); remove_device_from_connect_list(remote_address); if (!connect_list.empty()) { Loading @@ -339,11 +342,35 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { } if (status != ErrorCode::SUCCESS) { le_client_handler_->Post(common::BindOnce(&LeConnectionCallbacks::OnLeConnectFail, common::Unretained(le_client_callbacks_), remote_address, status)); le_client_handler_->Post(common::BindOnce( &LeConnectionCallbacks::OnLeConnectFail, common::Unretained(le_client_callbacks_), remote_address, status)); return; } } else { LOG_INFO("Received connection complete with Peripheral role"); if (le_client_handler_ == nullptr) { LOG_ERROR("No callbacks to call"); return; } if (status != ErrorCode::SUCCESS) { std::string error_code = ErrorCodeText(status); LOG_WARN("Received on_le_connection_complete with error code %s", error_code.c_str()); return; } if (in_filter_accept_list) { LOG_INFO( "Received incoming connection of device in filter accept_list, %s", PRIVATE_ADDRESS_WITH_TYPE(remote_address)); remove_device_from_connect_list(remote_address); if (create_connection_timeout_alarms_.find(remote_address) != create_connection_timeout_alarms_.end()) { create_connection_timeout_alarms_.at(remote_address).Cancel(); create_connection_timeout_alarms_.erase(remote_address); } } } uint16_t conn_interval = connection_complete.GetConnInterval(); uint16_t conn_latency = connection_complete.GetConnLatency(); uint16_t supervision_timeout = connection_complete.GetSupervisionTimeout(); Loading @@ -352,7 +379,6 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { return; } auto role = connection_complete.GetRole(); uint16_t handle = connection_complete.GetConnectionHandle(); auto queue = std::make_shared<AclConnection::Queue>(10); auto queue_down_end = queue->GetDownEnd(); Loading Loading @@ -380,14 +406,9 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { auto address = connection_complete.GetPeerAddress(); auto peer_address_type = connection_complete.GetPeerAddressType(); auto peer_resolvable_address = connection_complete.GetPeerResolvablePrivateAddress(); connectability_state_ = ConnectabilityState::DISARMED; if (status == ErrorCode::UNKNOWN_CONNECTION && pause_connection) { on_le_connection_canceled_on_pause(); return; } auto role = connection_complete.GetRole(); AddressType remote_address_type; switch (peer_address_type) { case AddressType::PUBLIC_DEVICE_ADDRESS: case AddressType::PUBLIC_IDENTITY_ADDRESS: Loading @@ -399,6 +420,15 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { break; } AddressWithType remote_address(address, remote_address_type); const bool in_filter_accept_list = is_device_in_connect_list(remote_address); if (role == hci::Role::CENTRAL) { connectability_state_ = ConnectabilityState::DISARMED; if (status == ErrorCode::UNKNOWN_CONNECTION && pause_connection) { on_le_connection_canceled_on_pause(); return; } on_common_le_connection_complete(remote_address); if (status == ErrorCode::UNKNOWN_CONNECTION) { Loading @@ -412,7 +442,6 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { arm_on_resume_ = false; ready_to_unregister = true; const bool in_filter_accept_list = is_device_in_connect_list(remote_address); remove_device_from_connect_list(remote_address); if (!connect_list.empty()) { Loading @@ -426,12 +455,36 @@ struct le_impl : public bluetooth::hci::LeAddressManagerCallback { } if (status != ErrorCode::SUCCESS) { le_client_handler_->Post(common::BindOnce(&LeConnectionCallbacks::OnLeConnectFail, common::Unretained(le_client_callbacks_), remote_address, status)); le_client_handler_->Post(common::BindOnce( &LeConnectionCallbacks::OnLeConnectFail, common::Unretained(le_client_callbacks_), remote_address, status)); return; } auto role = connection_complete.GetRole(); } else { LOG_INFO("Received connection complete with Peripheral role"); if (le_client_handler_ == nullptr) { LOG_ERROR("No callbacks to call"); return; } if (status != ErrorCode::SUCCESS) { std::string error_code = ErrorCodeText(status); LOG_WARN("Received on_le_enhanced_connection_complete with error code %s", error_code.c_str()); return; } if (in_filter_accept_list) { LOG_INFO( "Received incoming connection of device in filter accept_list, %s", PRIVATE_ADDRESS_WITH_TYPE(remote_address)); remove_device_from_connect_list(remote_address); if (create_connection_timeout_alarms_.find(remote_address) != create_connection_timeout_alarms_.end()) { create_connection_timeout_alarms_.at(remote_address).Cancel(); create_connection_timeout_alarms_.erase(remote_address); } } } AddressWithType local_address; if (role == hci::Role::CENTRAL) { local_address = le_address_manager_->GetCurrentAddress(); Loading
system/gd/hci/acl_manager/le_impl_test.cc +292 −3 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "hci/acl_manager/le_impl.h" #include <gmock/gmock.h> #include <gtest/gtest.h> #include <chrono> Loading @@ -23,6 +24,7 @@ #include "common/bidi_queue.h" #include "common/callback.h" #include "hci/acl_manager.h" #include "hci/acl_manager/le_connection_management_callbacks.h" #include "hci/address_with_type.h" #include "hci/controller.h" #include "hci/hci_packets.h" Loading @@ -41,8 +43,26 @@ namespace bluetooth { namespace hci { namespace acl_manager { PacketView<kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) { auto bytes = std::make_shared<std::vector<uint8_t>>(); BitInserter i(*bytes); bytes->reserve(packet->size()); packet->Serialize(i); return packet::PacketView<packet::kLittleEndian>(bytes); } class TestController : public Controller { public: bool IsSupported(OpCode op_code) const override { LOG_INFO("IsSupported"); return supported_opcodes_.count(op_code) == 1; } void AddSupported(OpCode op_code) { LOG_INFO("AddSupported"); supported_opcodes_.insert(op_code); } uint16_t GetNumAclPacketBuffers() const { return max_acl_packet_credits_; } Loading Loading @@ -77,6 +97,7 @@ class TestController : public Controller { private: CompletedAclPacketsCallback acl_credits_callback_; std::set<OpCode> supported_opcodes_{}; }; class TestHciLayer : public HciLayer { Loading @@ -98,7 +119,90 @@ class TestHciLayer : public HciLayer { HciLayer& hci_; }; void EnqueueCommand( std::unique_ptr<CommandBuilder> command, common::ContextualOnceCallback<void(CommandStatusView)> on_status) override { command_queue_.push(std::move(command)); command_status_callbacks.push_back(std::move(on_status)); if (command_promise_ != nullptr) { command_promise_->set_value(); command_promise_.reset(); } } void EnqueueCommand( std::unique_ptr<CommandBuilder> command, common::ContextualOnceCallback<void(CommandCompleteView)> on_complete) override { command_queue_.push(std::move(command)); command_complete_callbacks.push_back(std::move(on_complete)); if (command_promise_ != nullptr) { command_promise_->set_value(); command_promise_.reset(); } } public: void SetCommandFuture() { ASSERT_LOG(command_promise_ == nullptr, "Promises, Promises, ... Only one at a time."); command_promise_ = std::make_unique<std::promise<void>>(); command_future_ = std::make_unique<std::future<void>>(command_promise_->get_future()); } CommandView GetLastCommand() { if (command_queue_.empty()) { return CommandView::Create(PacketView<kLittleEndian>(std::make_shared<std::vector<uint8_t>>())); } auto last = std::move(command_queue_.front()); command_queue_.pop(); return CommandView::Create(GetPacketView(std::move(last))); } CommandView GetCommand(OpCode op_code) { if (!command_queue_.empty()) { std::lock_guard<std::mutex> lock(mutex_); if (command_future_ != nullptr) { command_future_.reset(); command_promise_.reset(); } } else if (command_future_ != nullptr) { auto result = command_future_->wait_for(std::chrono::milliseconds(1000)); EXPECT_NE(std::future_status::timeout, result); } std::lock_guard<std::mutex> lock(mutex_); ASSERT_LOG( !command_queue_.empty(), "Expecting command %s but command queue was empty", OpCodeText(op_code).c_str()); CommandView command_packet_view = GetLastCommand(); EXPECT_TRUE(command_packet_view.IsValid()); EXPECT_EQ(command_packet_view.GetOpCode(), op_code); return command_packet_view; } void CommandCompleteCallback(std::unique_ptr<EventBuilder> event_builder) { auto event = EventView::Create(GetPacketView(std::move(event_builder))); CommandCompleteView complete_view = CommandCompleteView::Create(event); ASSERT_TRUE(complete_view.IsValid()); ASSERT_NE((uint16_t)command_complete_callbacks.size(), 0); std::move(command_complete_callbacks.front()).Invoke(complete_view); command_complete_callbacks.pop_front(); } void CommandStatusCallback(std::unique_ptr<EventBuilder> event_builder) { auto event = EventView::Create(GetPacketView(std::move(event_builder))); CommandStatusView status_view = CommandStatusView::Create(event); ASSERT_TRUE(status_view.IsValid()); ASSERT_NE((uint16_t)command_status_callbacks.size(), 0); std::move(command_status_callbacks.front()).Invoke(status_view); command_status_callbacks.pop_front(); } void IncomingLeMetaEvent(std::unique_ptr<LeMetaEventBuilder> event_builder) { auto packet = GetPacketView(std::move(event_builder)); EventView event = EventView::Create(packet); LeMetaEventView meta_event_view = LeMetaEventView::Create(event); EXPECT_TRUE(meta_event_view.IsValid()); le_event_handler_.Invoke(meta_event_view); } LeAclConnectionInterface* GetLeAclConnectionInterface( common::ContextualCallback<void(LeMetaEventView)> event_handler, common::ContextualCallback<void(uint16_t, ErrorCode)> on_disconnect, Loading @@ -107,12 +211,21 @@ class TestHciLayer : public HciLayer { on_read_remote_version) override { disconnect_handlers_.push_back(on_disconnect); read_remote_version_handlers_.push_back(on_read_remote_version); return &le_acl_connection_manager_interface_2_; le_event_handler_ = event_handler; return &le_acl_connection_manager_interface_; } void PutLeAclConnectionInterface() override {} CommandInterfaceImpl<AclCommandBuilder> le_acl_connection_manager_interface_2_{*this}; private: std::list<common::ContextualOnceCallback<void(CommandCompleteView)>> command_complete_callbacks; std::list<common::ContextualOnceCallback<void(CommandStatusView)>> command_status_callbacks; common::ContextualCallback<void(LeMetaEventView)> le_event_handler_; std::queue<std::unique_ptr<CommandBuilder>> command_queue_; std::unique_ptr<std::promise<void>> command_promise_; std::unique_ptr<std::future<void>> command_future_; mutable std::mutex mutex_; CommandInterfaceImpl<AclCommandBuilder> le_acl_connection_manager_interface_{*this}; }; class LeImplTest : public ::testing::Test { Loading @@ -127,6 +240,24 @@ class LeImplTest : public ::testing::Test { hci_queue_.GetDownEnd()->RegisterDequeue( handler_, common::Bind(&LeImplTest::HciDownEndDequeue, common::Unretained(this))); le_impl_ = new le_impl(hci_layer_, controller_, handler_, round_robin_scheduler_, true); le_impl_->handle_register_le_callbacks(&mock_le_connection_callbacks_, handler_); // Set address policy hci_layer_->SetCommandFuture(); hci::Address address; Address::FromString("D0:05:04:03:02:01", address); hci::AddressWithType address_with_type(address, hci::AddressType::RANDOM_DEVICE_ADDRESS); crypto_toolbox::Octet16 rotation_irk{}; auto minimum_rotation_time = std::chrono::milliseconds(7 * 60 * 1000); auto maximum_rotation_time = std::chrono::milliseconds(15 * 60 * 1000); le_impl_->set_privacy_policy_for_initiator_address( LeAddressManager::AddressPolicy::USE_STATIC_ADDRESS, address_with_type, rotation_irk, minimum_rotation_time, maximum_rotation_time); hci_layer_->GetCommand(OpCode::LE_SET_RANDOM_ADDRESS); hci_layer_->CommandCompleteCallback(LeSetRandomAddressCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); } void TearDown() override { Loading Loading @@ -172,6 +303,16 @@ class LeImplTest : public ::testing::Test { } } class MockLeConnectionCallbacks : public LeConnectionCallbacks { public: MOCK_METHOD( void, OnLeConnectSuccess, (AddressWithType address_with_type, std::unique_ptr<LeAclConnection> connection), (override)); MOCK_METHOD(void, OnLeConnectFail, (AddressWithType, ErrorCode reason), (override)); } mock_le_connection_callbacks_; uint16_t packet_count_; std::unique_ptr<std::promise<void>> packet_promise_; std::unique_ptr<std::future<void>> packet_future_; Loading @@ -181,7 +322,7 @@ class LeImplTest : public ::testing::Test { Thread* thread_; Handler* handler_; HciLayer* hci_layer_{nullptr}; TestHciLayer* hci_layer_{nullptr}; TestController* controller_; RoundRobinScheduler* round_robin_scheduler_{nullptr}; Loading Loading @@ -228,6 +369,154 @@ TEST_F(LeImplTest, remove_device_from_connect_list) { ASSERT_EQ(0UL, le_impl_->connect_list.size()); } TEST_F(LeImplTest, connection_complete_with_periperal_role) { // Create connection hci_layer_->SetCommandFuture(); le_impl_->create_le_connection( {{0x21, 0x22, 0x23, 0x24, 0x25, 0x26}, AddressType::PUBLIC_DEVICE_ADDRESS}, true, false); hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); hci_layer_->SetCommandFuture(); hci_layer_->CommandCompleteCallback(LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION); hci_layer_->CommandStatusCallback(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); sync_handler(); // Check state is ARMED ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_); // Receive connection complete of incoming connection (Role::PERIPHERAL) hci::Address remote_address; Address::FromString("D0:05:04:03:02:01", remote_address); hci::AddressWithType address_with_type(remote_address, hci::AddressType::PUBLIC_DEVICE_ADDRESS); EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectSuccess(address_with_type, testing::_)); hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x0041, Role::PERIPHERAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote_address, 0x0024, 0x0000, 0x0011, ClockAccuracy::PPM_30)); sync_handler(); // Check state is still ARMED ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_); } TEST_F(LeImplTest, enhanced_connection_complete_with_periperal_role) { controller_->AddSupported(OpCode::LE_EXTENDED_CREATE_CONNECTION); // Create connection hci_layer_->SetCommandFuture(); le_impl_->create_le_connection( {{0x21, 0x22, 0x23, 0x24, 0x25, 0x26}, AddressType::PUBLIC_DEVICE_ADDRESS}, true, false); hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); hci_layer_->SetCommandFuture(); hci_layer_->CommandCompleteCallback(LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); hci_layer_->GetCommand(OpCode::LE_EXTENDED_CREATE_CONNECTION); hci_layer_->CommandStatusCallback(LeExtendedCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); sync_handler(); // Check state is ARMED ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_); // Receive connection complete of incoming connection (Role::PERIPHERAL) hci::Address remote_address; Address::FromString("D0:05:04:03:02:01", remote_address); hci::AddressWithType address_with_type(remote_address, hci::AddressType::PUBLIC_DEVICE_ADDRESS); EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectSuccess(address_with_type, testing::_)); hci_layer_->IncomingLeMetaEvent(LeEnhancedConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x0041, Role::PERIPHERAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote_address, Address::kEmpty, Address::kEmpty, 0x0024, 0x0000, 0x0011, ClockAccuracy::PPM_30)); sync_handler(); // Check state is still ARMED ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_); } TEST_F(LeImplTest, connection_complete_with_central_role) { hci::Address remote_address; Address::FromString("D0:05:04:03:02:01", remote_address); hci::AddressWithType address_with_type(remote_address, hci::AddressType::PUBLIC_DEVICE_ADDRESS); // Create connection hci_layer_->SetCommandFuture(); le_impl_->create_le_connection(address_with_type, true, false); hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); hci_layer_->SetCommandFuture(); hci_layer_->CommandCompleteCallback(LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); hci_layer_->GetCommand(OpCode::LE_CREATE_CONNECTION); hci_layer_->CommandStatusCallback(LeCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); sync_handler(); // Check state is ARMED ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_); // Receive connection complete of outgoing connection (Role::CENTRAL) EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectSuccess(address_with_type, testing::_)); hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x0041, Role::CENTRAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote_address, 0x0024, 0x0000, 0x0011, ClockAccuracy::PPM_30)); sync_handler(); // Check state is DISARMED ASSERT_EQ(ConnectabilityState::DISARMED, le_impl_->connectability_state_); } TEST_F(LeImplTest, enhanced_connection_complete_with_central_role) { controller_->AddSupported(OpCode::LE_EXTENDED_CREATE_CONNECTION); hci::Address remote_address; Address::FromString("D0:05:04:03:02:01", remote_address); hci::AddressWithType address_with_type(remote_address, hci::AddressType::PUBLIC_DEVICE_ADDRESS); // Create connection hci_layer_->SetCommandFuture(); le_impl_->create_le_connection(address_with_type, true, false); hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_FILTER_ACCEPT_LIST); hci_layer_->SetCommandFuture(); hci_layer_->CommandCompleteCallback(LeAddDeviceToFilterAcceptListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); hci_layer_->GetCommand(OpCode::LE_EXTENDED_CREATE_CONNECTION); hci_layer_->CommandStatusCallback(LeExtendedCreateConnectionStatusBuilder::Create(ErrorCode::SUCCESS, 0x01)); sync_handler(); // Check state is ARMED ASSERT_EQ(ConnectabilityState::ARMED, le_impl_->connectability_state_); // Receive connection complete of outgoing connection (Role::CENTRAL) EXPECT_CALL(mock_le_connection_callbacks_, OnLeConnectSuccess(address_with_type, testing::_)); hci_layer_->IncomingLeMetaEvent(LeEnhancedConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x0041, Role::CENTRAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote_address, Address::kEmpty, Address::kEmpty, 0x0024, 0x0000, 0x0011, ClockAccuracy::PPM_30)); sync_handler(); // Check state is DISARMED ASSERT_EQ(ConnectabilityState::DISARMED, le_impl_->connectability_state_); } } // namespace acl_manager } // namespace hci } // namespace bluetooth