/* * 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 #include "common/bind.h" #include "hci/address.h" #include "hci/class_of_device.h" #include "hci/controller.h" #include "hci/hci_layer.h" #include "os/thread.h" #include "packet/raw_builder.h" namespace bluetooth { namespace hci { namespace acl_manager { namespace { using common::BidiQueue; using common::BidiQueueEnd; using packet::kLittleEndian; using packet::PacketView; using packet::RawBuilder; constexpr std::chrono::seconds kTimeout = std::chrono::seconds(2); constexpr uint16_t kScanIntervalFast = 0x0060; constexpr uint16_t kScanWindowFast = 0x0030; constexpr uint16_t kScanIntervalSlow = 0x0800; constexpr uint16_t kScanWindowSlow = 0x0030; const AddressWithType empty_address_with_type = hci::AddressWithType(); PacketView GetPacketView(std::unique_ptr packet) { auto bytes = std::make_shared>(); BitInserter i(*bytes); bytes->reserve(packet->size()); packet->Serialize(i); return packet::PacketView(bytes); } std::unique_ptr NextPayload(uint16_t handle) { static uint32_t packet_number = 1; auto payload = std::make_unique(); payload->AddOctets2(6); // L2CAP PDU size payload->AddOctets2(2); // L2CAP CID payload->AddOctets2(handle); payload->AddOctets4(packet_number++); return std::move(payload); } std::unique_ptr NextAclPacket(uint16_t handle) { PacketBoundaryFlag packet_boundary_flag = PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE; BroadcastFlag broadcast_flag = BroadcastFlag::POINT_TO_POINT; return AclBuilder::Create(handle, packet_boundary_flag, broadcast_flag, NextPayload(handle)); } class TestController : public Controller { 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_.Invoke(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) override {} }; class TestHciLayer : public HciLayer { public: void EnqueueCommand( std::unique_ptr command, common::ContextualOnceCallback 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 command, common::ContextualOnceCallback 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(); } } void SetCommandFuture() { ASSERT_LOG(command_promise_ == nullptr, "Promises, Promises, ... Only one at a time."); command_promise_ = std::make_unique>(); command_future_ = std::make_unique>(command_promise_->get_future()); } CommandView GetLastCommand() { if (command_queue_.size() == 0) { return CommandView::Create(PacketView(std::make_shared>())); } auto last = std::move(command_queue_.front()); command_queue_.pop(); return CommandView::Create(GetPacketView(std::move(last))); } ConnectionManagementCommandView GetCommand(OpCode op_code) { if (command_future_ != nullptr) { auto result = command_future_->wait_for(std::chrono::milliseconds(1000)); EXPECT_NE(std::future_status::timeout, result); } if (command_queue_.empty()) { return ConnectionManagementCommandView::Create(AclCommandView::Create( CommandView::Create(PacketView(std::make_shared>())))); } CommandView command_packet_view = GetLastCommand(); ConnectionManagementCommandView command = ConnectionManagementCommandView::Create(AclCommandView::Create(command_packet_view)); EXPECT_TRUE(command.IsValid()); EXPECT_EQ(command.GetOpCode(), op_code); return command; } ConnectionManagementCommandView GetLastCommand(OpCode op_code) { if (!command_queue_.empty() && 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); } if (command_queue_.empty()) { return ConnectionManagementCommandView::Create(AclCommandView::Create( CommandView::Create(PacketView(std::make_shared>())))); } CommandView command_packet_view = GetLastCommand(); ConnectionManagementCommandView command = ConnectionManagementCommandView::Create(AclCommandView::Create(command_packet_view)); EXPECT_TRUE(command.IsValid()); EXPECT_EQ(command.GetOpCode(), op_code); return command; } void RegisterEventHandler(EventCode event_code, common::ContextualCallback event_handler) override { registered_events_[event_code] = event_handler; } void UnregisterEventHandler(EventCode event_code) override { registered_events_.erase(event_code); } void RegisterLeEventHandler(SubeventCode subevent_code, common::ContextualCallback event_handler) override { registered_le_events_[subevent_code] = event_handler; } void UnregisterLeEventHandler(SubeventCode subevent_code) override { registered_le_events_.erase(subevent_code); } void IncomingEvent(std::unique_ptr event_builder) { auto packet = GetPacketView(std::move(event_builder)); EventView event = EventView::Create(packet); ASSERT_TRUE(event.IsValid()); EventCode event_code = event.GetEventCode(); ASSERT_NE(registered_events_.find(event_code), registered_events_.end()) << EventCodeText(event_code); registered_events_[event_code].Invoke(event); } void IncomingLeMetaEvent(std::unique_ptr 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()); SubeventCode subevent_code = meta_event_view.GetSubeventCode(); EXPECT_TRUE(registered_le_events_.find(subevent_code) != registered_le_events_.end()); registered_le_events_[subevent_code].Invoke(meta_event_view); } void IncomingAclData(uint16_t handle) { os::Handler* hci_handler = GetHandler(); auto* queue_end = acl_queue_.GetDownEnd(); std::promise promise; auto future = promise.get_future(); queue_end->RegisterEnqueue(hci_handler, common::Bind( [](decltype(queue_end) queue_end, uint16_t handle, std::promise promise) { auto packet = GetPacketView(NextAclPacket(handle)); AclView acl2 = AclView::Create(packet); queue_end->UnregisterEnqueue(); promise.set_value(); return std::make_unique(acl2); }, queue_end, handle, common::Passed(std::move(promise)))); auto status = future.wait_for(kTimeout); ASSERT_EQ(status, std::future_status::ready); } void AssertNoOutgoingAclData() { auto queue_end = acl_queue_.GetDownEnd(); EXPECT_EQ(queue_end->TryDequeue(), nullptr); } void CommandCompleteCallback(EventView event) { CommandCompleteView complete_view = CommandCompleteView::Create(event); ASSERT_TRUE(complete_view.IsValid()); std::move(command_complete_callbacks.front()).Invoke(complete_view); command_complete_callbacks.pop_front(); } void CommandStatusCallback(EventView event) { CommandStatusView status_view = CommandStatusView::Create(event); ASSERT_TRUE(status_view.IsValid()); std::move(command_status_callbacks.front()).Invoke(status_view); command_status_callbacks.pop_front(); } PacketView OutgoingAclData() { auto queue_end = acl_queue_.GetDownEnd(); std::unique_ptr received; do { received = queue_end->TryDequeue(); } while (received == nullptr); return GetPacketView(std::move(received)); } BidiQueueEnd* GetAclQueueEnd() override { return acl_queue_.GetUpEnd(); } void ListDependencies(ModuleList* list) override {} void Start() override { RegisterEventHandler(EventCode::COMMAND_COMPLETE, GetHandler()->BindOn(this, &TestHciLayer::CommandCompleteCallback)); RegisterEventHandler(EventCode::COMMAND_STATUS, GetHandler()->BindOn(this, &TestHciLayer::CommandStatusCallback)); } void Stop() override {} void Disconnect(uint16_t handle, ErrorCode reason) override { GetHandler()->Post(common::BindOnce(&TestHciLayer::do_disconnect, common::Unretained(this), handle, reason)); } private: std::map> registered_events_; std::map> registered_le_events_; std::list> command_complete_callbacks; std::list> command_status_callbacks; BidiQueue acl_queue_{3 /* TODO: Set queue depth */}; std::queue> command_queue_; std::unique_ptr> command_promise_; std::unique_ptr> command_future_; void do_disconnect(uint16_t handle, ErrorCode reason) { HciLayer::Disconnect(handle, reason); } }; class AclManagerNoCallbacksTest : public ::testing::Test { protected: void SetUp() override { test_hci_layer_ = new TestHciLayer; // 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); test_hci_layer_->SetCommandFuture(); 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(test_hci_layer_->GetCommand(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); // Verify LE Set Random Address was sent during setup test_hci_layer_->GetLastCommand(OpCode::LE_SET_RANDOM_ADDRESS); test_hci_layer_->IncomingEvent(LeSetRandomAddressCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); } void TearDown() override { fake_registry_.SynchronizeModuleHandler(&AclManager::Factory, std::chrono::milliseconds(20)); fake_registry_.StopAll(); } TestModuleRegistry fake_registry_; TestHciLayer* 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_connect_list_ = true; // gd currently only supports connect list std::future GetConnectionFuture() { ASSERT_LOG(mock_connection_callback_.connection_promise_ == nullptr, "Promises promises ... Only one at a time"); mock_connection_callback_.connection_promise_ = std::make_unique>(); return mock_connection_callback_.connection_promise_->get_future(); } std::future GetLeConnectionFuture() { ASSERT_LOG(mock_le_connection_callbacks_.le_connection_promise_ == nullptr, "Promises promises ... Only one at a time"); mock_le_connection_callbacks_.le_connection_promise_ = std::make_unique>(); return mock_le_connection_callbacks_.le_connection_promise_->get_future(); } std::shared_ptr GetLastConnection() { return mock_connection_callback_.connections_.back(); } std::shared_ptr GetLastLeConnection() { return mock_le_connection_callbacks_.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); } class MockConnectionCallback : public ConnectionCallbacks { public: void OnConnectSuccess(std::unique_ptr connection) override { // Convert to std::shared_ptr during push_back() connections_.push_back(std::move(connection)); if (connection_promise_ != nullptr) { connection_promise_->set_value(); connection_promise_.reset(); } } MOCK_METHOD(void, OnConnectFail, (Address, ErrorCode reason), (override)); MOCK_METHOD(void, HACK_OnEscoConnectRequest, (Address, ClassOfDevice), (override)); MOCK_METHOD(void, HACK_OnScoConnectRequest, (Address, ClassOfDevice), (override)); std::list> connections_; std::unique_ptr> connection_promise_; } mock_connection_callback_; class MockLeConnectionCallbacks : public LeConnectionCallbacks { public: void OnLeConnectSuccess(AddressWithType address_with_type, std::unique_ptr connection) override { le_connections_.push_back(std::move(connection)); if (le_connection_promise_ != nullptr) { le_connection_promise_->set_value(); le_connection_promise_.reset(); } } MOCK_METHOD(void, OnLeConnectFail, (AddressWithType, ErrorCode reason), (override)); std::list> le_connections_; std::unique_ptr> le_connection_promise_; } 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 = test_hci_layer_->GetCommand(OpCode::CREATE_CONNECTION); while (!last_command.IsValid()) { last_command = test_hci_layer_->GetCommand(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 { fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&AclManager::Factory, std::chrono::milliseconds(20)); fake_registry_.StopAll(); } void sync_client_handler() { std::promise promise; auto future = promise.get_future(); client_handler_->Post(common::BindOnce(&std::promise::set_value, common::Unretained(&promise))); auto future_status = future.wait_for(std::chrono::seconds(1)); EXPECT_EQ(future_status, std::future_status::ready); } uint16_t handle_; std::shared_ptr connection_; class MockConnectionManagementCallbacks : public ConnectionManagementCallbacks { public: MOCK_METHOD1(OnConnectionPacketTypeChanged, void(uint16_t packet_type)); MOCK_METHOD1(OnAuthenticationComplete, void(hci::ErrorCode hci_status)); MOCK_METHOD1(OnEncryptionChange, void(EncryptionEnabled enabled)); MOCK_METHOD0(OnChangeConnectionLinkKeyComplete, void()); MOCK_METHOD1(OnReadClockOffsetComplete, void(uint16_t clock_offse)); MOCK_METHOD3(OnModeChange, void(ErrorCode status, Mode current_mode, uint16_t interval)); MOCK_METHOD5( OnSniffSubrating, void( ErrorCode status, uint16_t maximum_transmit_latency, uint16_t maximum_receive_latency, uint16_t minimum_remote_timeout, uint16_t minimum_local_timeout)); MOCK_METHOD5(OnQosSetupComplete, void(ServiceType service_type, uint32_t token_rate, uint32_t peak_bandwidth, uint32_t latency, uint32_t delay_variation)); MOCK_METHOD6(OnFlowSpecificationComplete, void(FlowDirection flow_direction, ServiceType service_type, uint32_t token_rate, uint32_t token_bucket_size, uint32_t peak_bandwidth, uint32_t access_latency)); MOCK_METHOD0(OnFlushOccurred, void()); MOCK_METHOD1(OnRoleDiscoveryComplete, void(Role current_role)); MOCK_METHOD1(OnReadLinkPolicySettingsComplete, void(uint16_t link_policy_settings)); MOCK_METHOD1(OnReadAutomaticFlushTimeoutComplete, void(uint16_t flush_timeout)); MOCK_METHOD1(OnReadTransmitPowerLevelComplete, void(uint8_t transmit_power_level)); MOCK_METHOD1(OnReadLinkSupervisionTimeoutComplete, void(uint16_t link_supervision_timeout)); MOCK_METHOD1(OnReadFailedContactCounterComplete, void(uint16_t failed_contact_counter)); MOCK_METHOD1(OnReadLinkQualityComplete, void(uint8_t link_quality)); MOCK_METHOD2(OnReadAfhChannelMapComplete, void(AfhMode afh_mode, std::array afh_channel_map)); MOCK_METHOD1(OnReadRssiComplete, void(uint8_t rssi)); MOCK_METHOD2(OnReadClockComplete, void(uint32_t clock, uint16_t accuracy)); MOCK_METHOD1(OnCentralLinkKeyComplete, void(KeyFlag flag)); MOCK_METHOD2(OnRoleChange, void(ErrorCode hci_status, Role new_role)); MOCK_METHOD1(OnDisconnection, void(ErrorCode reason)); MOCK_METHOD4( OnReadRemoteVersionInformationComplete, void(hci::ErrorCode hci_status, uint8_t lmp_version, uint16_t manufacturer_name, uint16_t sub_version)); MOCK_METHOD1(OnReadRemoteSupportedFeaturesComplete, void(uint64_t features)); MOCK_METHOD3( OnReadRemoteExtendedFeaturesComplete, void(uint8_t page_number, uint8_t max_page_number, uint64_t features)); } mock_connection_management_callbacks_; }; TEST_F(AclManagerTest, startup_teardown) {} TEST_F(AclManagerNoCallbacksTest, acl_connection_before_registered_callbacks) { ClassOfDevice class_of_device; test_hci_layer_->IncomingEvent( ConnectionRequestBuilder::Create(remote, class_of_device, ConnectionRequestLinkType::ACL)); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&AclManager::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); CommandView command = CommandView::Create(test_hci_layer_->GetLastCommand()); EXPECT_TRUE(command.IsValid()); OpCode op_code = command.GetOpCode(); EXPECT_EQ(op_code, OpCode::REJECT_CONNECTION_REQUEST); } TEST_F(AclManagerTest, invoke_registered_callback_connection_complete_success) { uint16_t handle = 1; test_hci_layer_->SetCommandFuture(); acl_manager_->CreateConnection(remote); // Wait for the connection request auto last_command = test_hci_layer_->GetCommand(OpCode::CREATE_CONNECTION); while (!last_command.IsValid()) { last_command = test_hci_layer_->GetCommand(OpCode::CREATE_CONNECTION); } 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); auto connection = GetLastConnection(); ASSERT_EQ(connection->GetAddress(), remote); } TEST_F(AclManagerTest, invoke_registered_callback_connection_complete_fail) { uint16_t handle = 0x123; test_hci_layer_->SetCommandFuture(); acl_manager_->CreateConnection(remote); // Wait for the connection request auto last_command = test_hci_layer_->GetCommand(OpCode::CREATE_CONNECTION); while (!last_command.IsValid()) { last_command = test_hci_layer_->GetCommand(OpCode::CREATE_CONNECTION); } EXPECT_CALL(mock_connection_callback_, OnConnectFail(remote, ErrorCode::PAGE_TIMEOUT)); test_hci_layer_->IncomingEvent( ConnectionCompleteBuilder::Create(ErrorCode::PAGE_TIMEOUT, handle, remote, LinkType::ACL, Enable::DISABLED)); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&AclManager::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); } class AclManagerWithLeConnectionTest : public AclManagerTest { protected: void SetUp() override { AclManagerTest::SetUp(); remote_with_type_ = AddressWithType(remote, AddressType::PUBLIC_DEVICE_ADDRESS); test_hci_layer_->SetCommandFuture(); acl_manager_->CreateLeConnection(remote_with_type_, true); test_hci_layer_->GetCommand(OpCode::LE_ADD_DEVICE_TO_CONNECT_LIST); test_hci_layer_->IncomingEvent(LeAddDeviceToConnectListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); test_hci_layer_->SetCommandFuture(); auto packet = test_hci_layer_->GetCommand(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_connect_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(); test_hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, handle_, Role::PERIPHERAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, 0x0100, 0x0010, 0x0C80, ClockAccuracy::PPM_30)); test_hci_layer_->SetCommandFuture(); test_hci_layer_->GetCommand(OpCode::LE_REMOVE_DEVICE_FROM_CONNECT_LIST); test_hci_layer_->IncomingEvent(LeRemoveDeviceFromConnectListCompleteBuilder::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 { fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&AclManager::Factory, std::chrono::milliseconds(20)); fake_registry_.StopAll(); } void sync_client_handler() { std::promise promise; auto future = promise.get_future(); client_handler_->Post(common::BindOnce(&std::promise::set_value, common::Unretained(&promise))); auto future_status = future.wait_for(std::chrono::seconds(1)); EXPECT_EQ(future_status, std::future_status::ready); } uint16_t handle_ = 0x123; std::shared_ptr connection_; AddressWithType remote_with_type_; class MockLeConnectionManagementCallbacks : public LeConnectionManagementCallbacks { public: MOCK_METHOD1(OnDisconnection, void(ErrorCode reason)); MOCK_METHOD4( OnConnectionUpdate, void( hci::ErrorCode hci_status, uint16_t connection_interval, uint16_t connection_latency, uint16_t supervision_timeout)); MOCK_METHOD4(OnDataLengthChange, void(uint16_t tx_octets, uint16_t tx_time, uint16_t rx_octets, uint16_t rx_time)); MOCK_METHOD4( OnReadRemoteVersionInformationComplete, void(hci::ErrorCode hci_status, uint8_t version, uint16_t manufacturer_name, uint16_t sub_version)); MOCK_METHOD3(OnPhyUpdate, void(hci::ErrorCode hci_status, uint8_t tx_phy, uint8_t rx_phy)); MOCK_METHOD1(OnLocalAddressUpdate, void(AddressWithType address_with_type)); } mock_le_connection_management_callbacks_; }; // 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); test_hci_layer_->SetCommandFuture(); acl_manager_->CreateLeConnection(remote_with_type, true); test_hci_layer_->GetLastCommand(OpCode::LE_ADD_DEVICE_TO_CONNECT_LIST); test_hci_layer_->IncomingEvent(LeAddDeviceToConnectListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); test_hci_layer_->SetCommandFuture(); auto packet = test_hci_layer_->GetLastCommand(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_connect_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::PERIPHERAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, 0x0100, 0x0010, 0x0011, ClockAccuracy::PPM_30)); test_hci_layer_->SetCommandFuture(); packet = test_hci_layer_->GetLastCommand(OpCode::LE_REMOVE_DEVICE_FROM_CONNECT_LIST); le_connection_management_command_view = LeConnectionManagementCommandView::Create(AclCommandView::Create(packet)); auto remove_command_view = LeRemoveDeviceFromConnectListView::Create(le_connection_management_command_view); ASSERT_TRUE(remove_command_view.IsValid()); test_hci_layer_->IncomingEvent(LeRemoveDeviceFromConnectListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); } TEST_F(AclManagerTest, cancel_le_connection) { AddressWithType remote_with_type(remote, AddressType::PUBLIC_DEVICE_ADDRESS); test_hci_layer_->SetCommandFuture(); acl_manager_->CreateLeConnection(remote_with_type, true); test_hci_layer_->GetLastCommand(OpCode::LE_ADD_DEVICE_TO_CONNECT_LIST); test_hci_layer_->IncomingEvent(LeAddDeviceToConnectListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); test_hci_layer_->SetCommandFuture(); test_hci_layer_->GetLastCommand(OpCode::LE_CREATE_CONNECTION); test_hci_layer_->SetCommandFuture(); acl_manager_->CancelLeConnect(remote_with_type); auto packet = test_hci_layer_->GetLastCommand(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::PERIPHERAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, 0x0100, 0x0010, 0x0011, ClockAccuracy::PPM_30)); test_hci_layer_->SetCommandFuture(); packet = test_hci_layer_->GetLastCommand(OpCode::LE_REMOVE_DEVICE_FROM_CONNECT_LIST); le_connection_management_command_view = LeConnectionManagementCommandView::Create(AclCommandView::Create(packet)); auto remove_command_view = LeRemoveDeviceFromConnectListView::Create(le_connection_management_command_view); ASSERT_TRUE(remove_command_view.IsValid()); test_hci_layer_->IncomingEvent(LeRemoveDeviceFromConnectListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); } TEST_F(AclManagerTest, create_connection_with_fast_mode) { AddressWithType remote_with_type(remote, AddressType::PUBLIC_DEVICE_ADDRESS); test_hci_layer_->SetCommandFuture(); acl_manager_->CreateLeConnection(remote_with_type, true); test_hci_layer_->GetLastCommand(OpCode::LE_ADD_DEVICE_TO_CONNECT_LIST); test_hci_layer_->IncomingEvent(LeAddDeviceToConnectListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); test_hci_layer_->SetCommandFuture(); auto packet = test_hci_layer_->GetLastCommand(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(); test_hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x00, Role::PERIPHERAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, 0x0100, 0x0010, 0x0C80, ClockAccuracy::PPM_30)); test_hci_layer_->SetCommandFuture(); test_hci_layer_->GetCommand(OpCode::LE_REMOVE_DEVICE_FROM_CONNECT_LIST); test_hci_layer_->IncomingEvent(LeRemoveDeviceFromConnectListCompleteBuilder::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); test_hci_layer_->SetCommandFuture(); acl_manager_->CreateLeConnection(remote_with_type, false); test_hci_layer_->GetLastCommand(OpCode::LE_ADD_DEVICE_TO_CONNECT_LIST); test_hci_layer_->IncomingEvent(LeAddDeviceToConnectListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); test_hci_layer_->SetCommandFuture(); auto packet = test_hci_layer_->GetLastCommand(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(); test_hci_layer_->IncomingLeMetaEvent(LeConnectionCompleteBuilder::Create( ErrorCode::SUCCESS, 0x00, Role::PERIPHERAL, AddressType::PUBLIC_DEVICE_ADDRESS, remote, 0x0100, 0x0010, 0x0C80, ClockAccuracy::PPM_30)); test_hci_layer_->SetCommandFuture(); test_hci_layer_->GetCommand(OpCode::LE_REMOVE_DEVICE_FROM_CONNECT_LIST); test_hci_layer_->IncomingEvent(LeRemoveDeviceFromConnectListCompleteBuilder::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; test_hci_layer_->SetCommandFuture(); connection_->LeConnectionUpdate(connection_interval_min, connection_interval_max, connection_latency, supervision_timeout, 0x10, 0x20); auto update_packet = test_hci_layer_->GetCommand(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_); 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)); } 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); } TEST_F(AclManagerWithLeConnectionTest, DISABLED_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); } 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(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); } 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(); test_hci_layer_->SetCommandFuture(); auto reason = ErrorCode::AUTHENTICATION_FAILURE; EXPECT_CALL(mock_connection_management_callbacks_, OnDisconnection(reason)); connection_->Disconnect(DisconnectReason::AUTHENTICATION_FAILURE); auto packet = test_hci_layer_->GetCommand(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); } 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(); } TEST_F(AclManagerWithConnectionTest, send_switch_role) { test_hci_layer_->SetCommandFuture(); acl_manager_->SwitchRole(connection_->GetAddress(), Role::PERIPHERAL); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_write_default_link_policy_settings) { test_hci_layer_->SetCommandFuture(); uint16_t link_policy_settings = 0x05; acl_manager_->WriteDefaultLinkPolicySettings(link_policy_settings); auto packet = test_hci_layer_->GetCommand(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)); ASSERT_EQ(link_policy_settings, acl_manager_->ReadDefaultLinkPolicySettings()); } TEST_F(AclManagerWithConnectionTest, send_authentication_requested) { test_hci_layer_->SetCommandFuture(); connection_->AuthenticationRequested(); auto packet = test_hci_layer_->GetCommand(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_)); } TEST_F(AclManagerWithConnectionTest, send_read_clock_offset) { test_hci_layer_->SetCommandFuture(); connection_->ReadClockOffset(); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_hold_mode) { test_hci_layer_->SetCommandFuture(); connection_->HoldMode(0x0500, 0x0020); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_sniff_mode) { test_hci_layer_->SetCommandFuture(); connection_->SniffMode(0x0500, 0x0020, 0x0040, 0x0014); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_exit_sniff_mode) { test_hci_layer_->SetCommandFuture(); connection_->ExitSniffMode(); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_qos_setup) { test_hci_layer_->SetCommandFuture(); connection_->QosSetup(ServiceType::BEST_EFFORT, 0x1234, 0x1233, 0x1232, 0x1231); auto packet = test_hci_layer_->GetCommand(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(), 0x1234); ASSERT_EQ(command_view.GetPeakBandwidth(), 0x1233); ASSERT_EQ(command_view.GetLatency(), 0x1232); ASSERT_EQ(command_view.GetDelayVariation(), 0x1231); 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)); } TEST_F(AclManagerWithConnectionTest, send_flow_specification) { test_hci_layer_->SetCommandFuture(); connection_->FlowSpecification(FlowDirection::OUTGOING_FLOW, ServiceType::BEST_EFFORT, 0x1234, 0x1233, 0x1232, 0x1231); auto packet = test_hci_layer_->GetCommand(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(), 0x1234); ASSERT_EQ(command_view.GetTokenBucketSize(), 0x1233); ASSERT_EQ(command_view.GetPeakBandwidth(), 0x1232); ASSERT_EQ(command_view.GetAccessLatency(), 0x1231); 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)); } TEST_F(AclManagerWithConnectionTest, send_flush) { test_hci_layer_->SetCommandFuture(); connection_->Flush(); auto packet = test_hci_layer_->GetCommand(OpCode::FLUSH); auto command_view = FlushView::Create(packet); ASSERT_TRUE(command_view.IsValid()); EXPECT_CALL(mock_connection_management_callbacks_, OnFlushOccurred()); test_hci_layer_->IncomingEvent(FlushOccurredBuilder::Create(handle_)); } TEST_F(AclManagerWithConnectionTest, send_role_discovery) { test_hci_layer_->SetCommandFuture(); connection_->RoleDiscovery(); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_read_link_policy_settings) { test_hci_layer_->SetCommandFuture(); connection_->ReadLinkPolicySettings(); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_write_link_policy_settings) { test_hci_layer_->SetCommandFuture(); connection_->WriteLinkPolicySettings(0x05); auto packet = test_hci_layer_->GetCommand(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_)); } TEST_F(AclManagerWithConnectionTest, send_sniff_subrating) { test_hci_layer_->SetCommandFuture(); connection_->SniffSubrating(0x1234, 0x1235, 0x1236); auto packet = test_hci_layer_->GetCommand(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_)); } TEST_F(AclManagerWithConnectionTest, send_read_automatic_flush_timeout) { test_hci_layer_->SetCommandFuture(); connection_->ReadAutomaticFlushTimeout(); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_write_automatic_flush_timeout) { test_hci_layer_->SetCommandFuture(); connection_->WriteAutomaticFlushTimeout(0x07FF); auto packet = test_hci_layer_->GetCommand(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_)); } TEST_F(AclManagerWithConnectionTest, send_read_transmit_power_level) { test_hci_layer_->SetCommandFuture(); connection_->ReadTransmitPowerLevel(TransmitPowerLevelType::CURRENT); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_read_link_supervision_timeout) { test_hci_layer_->SetCommandFuture(); connection_->ReadLinkSupervisionTimeout(); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_write_link_supervision_timeout) { test_hci_layer_->SetCommandFuture(); connection_->WriteLinkSupervisionTimeout(0x5678); auto packet = test_hci_layer_->GetCommand(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_)); } TEST_F(AclManagerWithConnectionTest, send_read_failed_contact_counter) { test_hci_layer_->SetCommandFuture(); connection_->ReadFailedContactCounter(); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_reset_failed_contact_counter) { test_hci_layer_->SetCommandFuture(); connection_->ResetFailedContactCounter(); auto packet = test_hci_layer_->GetCommand(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_)); } TEST_F(AclManagerWithConnectionTest, send_read_link_quality) { test_hci_layer_->SetCommandFuture(); connection_->ReadLinkQuality(); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_read_afh_channel_map) { test_hci_layer_->SetCommandFuture(); connection_->ReadAfhChannelMap(); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_read_rssi) { test_hci_layer_->SetCommandFuture(); connection_->ReadRssi(); auto packet = test_hci_layer_->GetCommand(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)); } TEST_F(AclManagerWithConnectionTest, send_read_clock) { test_hci_layer_->SetCommandFuture(); connection_->ReadClock(WhichClock::LOCAL); auto packet = test_hci_layer_->GetCommand(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)); } class AclManagerWithResolvableAddressTest : public AclManagerNoCallbacksTest { protected: void SetUp() override { test_hci_layer_ = new TestHciLayer; // 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); test_hci_layer_->SetCommandFuture(); 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); test_hci_layer_->GetLastCommand(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); test_hci_layer_->SetCommandFuture(); acl_manager_->CreateLeConnection(remote_with_type_, true); // Set random address test_hci_layer_->GetLastCommand(OpCode::LE_SET_RANDOM_ADDRESS); test_hci_layer_->SetCommandFuture(); test_hci_layer_->IncomingEvent(LeSetRandomAddressCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); // Add device to connect list test_hci_layer_->GetLastCommand(OpCode::LE_ADD_DEVICE_TO_CONNECT_LIST); test_hci_layer_->SetCommandFuture(); test_hci_layer_->IncomingEvent(LeAddDeviceToConnectListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); // send create connection command test_hci_layer_->GetLastCommand(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 test_hci_layer_->SetCommandFuture(); acl_manager_->CreateLeConnection(remote_with_type2, true); // cancel previous connection test_hci_layer_->GetLastCommand(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_->SetCommandFuture(); test_hci_layer_->IncomingEvent( LeCreateConnectionCancelCompleteBuilder::Create(0x01, ErrorCode::CONNECTION_ALREADY_EXISTS)); // Add another device to connect list test_hci_layer_->GetLastCommand(OpCode::LE_ADD_DEVICE_TO_CONNECT_LIST); test_hci_layer_->IncomingEvent(LeAddDeviceToConnectListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); } 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 test_hci_layer_->SetCommandFuture(); acl_manager_->CreateConnection(remote); auto connection_command = test_hci_layer_->GetCommand(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)); auto connection_future_status = connection_future.wait_for(kTimeout); ASSERT_NE(connection_future_status, std::future_status::ready); } TEST_F(AclManagerLifeCycleTest, unregister_classic_before_connection_request) { ClassOfDevice class_of_device; // Unregister callbacks before receiving 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 request auto connection_future = GetConnectionFuture(); test_hci_layer_->IncomingEvent( ConnectionRequestBuilder::Create(remote, class_of_device, ConnectionRequestLinkType::ACL)); auto connection_future_status = connection_future.wait_for(kTimeout); ASSERT_NE(connection_future_status, std::future_status::ready); test_hci_layer_->GetLastCommand(OpCode::REJECT_CONNECTION_REQUEST); } TEST_F(AclManagerLifeCycleTest, unregister_le_before_connection_complete) { AddressWithType remote_with_type(remote, AddressType::PUBLIC_DEVICE_ADDRESS); test_hci_layer_->SetCommandFuture(); acl_manager_->CreateLeConnection(remote_with_type, true); test_hci_layer_->GetLastCommand(OpCode::LE_ADD_DEVICE_TO_CONNECT_LIST); test_hci_layer_->IncomingEvent(LeAddDeviceToConnectListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); test_hci_layer_->SetCommandFuture(); auto packet = test_hci_layer_->GetLastCommand(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_connect_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)); auto connection_future_status = connection_future.wait_for(kTimeout); 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); test_hci_layer_->SetCommandFuture(); acl_manager_->CreateLeConnection(remote_with_type, true); test_hci_layer_->GetLastCommand(OpCode::LE_ADD_DEVICE_TO_CONNECT_LIST); test_hci_layer_->IncomingEvent(LeAddDeviceToConnectListCompleteBuilder::Create(0x01, ErrorCode::SUCCESS)); test_hci_layer_->SetCommandFuture(); auto packet = test_hci_layer_->GetLastCommand(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_connect_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)); auto connection_future_status = connection_future.wait_for(kTimeout); ASSERT_NE(connection_future_status, std::future_status::ready); } TEST_F(AclManagerWithConnectionTest, remote_sco_connect_request) { ClassOfDevice class_of_device; EXPECT_CALL(mock_connection_callback_, HACK_OnScoConnectRequest(remote, class_of_device)); test_hci_layer_->IncomingEvent( ConnectionRequestBuilder::Create(remote, class_of_device, ConnectionRequestLinkType::SCO)); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&AclManager::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); } TEST_F(AclManagerWithConnectionTest, remote_esco_connect_request) { ClassOfDevice class_of_device; EXPECT_CALL(mock_connection_callback_, HACK_OnEscoConnectRequest(remote, class_of_device)); test_hci_layer_->IncomingEvent( ConnectionRequestBuilder::Create(remote, class_of_device, ConnectionRequestLinkType::ESCO)); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&AclManager::Factory, std::chrono::milliseconds(20)); fake_registry_.SynchronizeModuleHandler(&HciLayer::Factory, std::chrono::milliseconds(20)); } } // namespace } // namespace acl_manager } // namespace hci } // namespace bluetooth