/* * Copyright 2018 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 "l2cap/le/internal/link_manager.h" #include #include #include "common/bind.h" #include "common/testing/bind_test_util.h" #include "hci/acl_manager_mock.h" #include "hci/address.h" #include "l2cap/cid.h" #include "l2cap/internal/parameter_provider_mock.h" #include "l2cap/le/fixed_channel_manager.h" #include "l2cap/le/internal/fixed_channel_service_impl_mock.h" #include "l2cap/le/internal/fixed_channel_service_manager_impl_mock.h" #include "os/handler.h" #include "os/thread.h" #include #include namespace bluetooth { namespace l2cap { namespace le { namespace internal { namespace { using hci::testing::MockAclManager; using hci::testing::MockLeAclConnection; using l2cap::internal::testing::MockParameterProvider; using ::testing::_; // Matcher to any value using ::testing::ByMove; using ::testing::DoAll; using testing::MockFixedChannelServiceImpl; using testing::MockFixedChannelServiceManagerImpl; using ::testing::Return; using ::testing::SaveArg; constexpr static auto kTestIdleDisconnectTimeoutLong = std::chrono::milliseconds(1000); constexpr static auto kTestIdleDisconnectTimeoutShort = std::chrono::milliseconds(1000); class L2capLeLinkManagerTest : public ::testing::Test { public: static void SyncHandler(os::Handler* handler) { std::promise promise; auto future = promise.get_future(); handler->Post(common::BindOnce(&std::promise::set_value, common::Unretained(&promise))); future.wait_for(std::chrono::milliseconds(3)); } protected: void SetUp() override { thread_ = new os::Thread("test_thread", os::Thread::Priority::NORMAL); l2cap_handler_ = new os::Handler(thread_); user_handler_ = new os::Handler(thread_); mock_parameter_provider_ = new MockParameterProvider; EXPECT_CALL(*mock_parameter_provider_, GetLeLinkIdleDisconnectTimeout) .WillRepeatedly(Return(kTestIdleDisconnectTimeoutLong)); } void TearDown() override { delete mock_parameter_provider_; l2cap_handler_->Clear(); delete l2cap_handler_; user_handler_->Clear(); delete user_handler_; delete thread_; } os::Thread* thread_ = nullptr; os::Handler* l2cap_handler_ = nullptr; os::Handler* user_handler_ = nullptr; MockParameterProvider* mock_parameter_provider_ = nullptr; }; TEST_F(L2capLeLinkManagerTest, connect_fixed_channel_service_without_acl) { MockFixedChannelServiceManagerImpl mock_le_fixed_channel_service_manager; MockAclManager mock_acl_manager; hci::AddressWithType address_with_type({{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, hci::AddressType::RANDOM_DEVICE_ADDRESS); // Step 1: Verify callback registration with HCI hci::acl_manager::LeConnectionCallbacks* hci_le_connection_callbacks = nullptr; os::Handler* hci_callback_handler = nullptr; EXPECT_CALL(mock_acl_manager, RegisterLeCallbacks(_, _)) .WillOnce(DoAll(SaveArg<0>(&hci_le_connection_callbacks), SaveArg<1>(&hci_callback_handler))); LinkManager le_link_manager( l2cap_handler_, &mock_acl_manager, &mock_le_fixed_channel_service_manager, nullptr, mock_parameter_provider_); EXPECT_EQ(hci_le_connection_callbacks, &le_link_manager); EXPECT_EQ(hci_callback_handler, l2cap_handler_); // Register fake services MockFixedChannelServiceImpl mock_service_1, mock_service_2; std::vector> results; results.emplace_back(kSmpBrCid, &mock_service_1); results.emplace_back(kConnectionlessCid, &mock_service_2); EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()).WillRepeatedly(Return(results)); // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process EXPECT_CALL(mock_acl_manager, CreateLeConnection(address_with_type, true)).Times(1); LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ .handler_ = user_handler_, .on_fail_callback_ = common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; le_link_manager.ConnectFixedChannelServices(address_with_type, std::move(pending_fixed_channel_connection)); // Step 3: ACL connection success event should trigger channel creation for all registered services std::unique_ptr acl_connection = std::make_unique(); EXPECT_CALL(*acl_connection, GetRemoteAddress()).WillRepeatedly(Return(address_with_type)); hci::acl_manager::LeConnectionManagementCallbacks* connection_management_callbacks = nullptr; os::Handler* connection_management_handler = nullptr; EXPECT_CALL(*acl_connection, RegisterCallbacks(_, _)) .WillOnce(DoAll(SaveArg<0>(&connection_management_callbacks), SaveArg<1>(&connection_management_handler))); std::unique_ptr channel_1, channel_2; std::promise promise_1, promise_2; auto future_1 = promise_1.get_future(); auto future_2 = promise_2.get_future(); EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)) .WillOnce([&channel_1, &promise_1](std::unique_ptr channel) { channel_1 = std::move(channel); promise_1.set_value(); }); EXPECT_CALL(mock_service_2, NotifyChannelCreation(_)) .WillOnce([&channel_2, &promise_2](std::unique_ptr channel) { channel_2 = std::move(channel); promise_2.set_value(); }); hci_callback_handler->Post(common::BindOnce(&hci::acl_manager::LeConnectionCallbacks::OnLeConnectSuccess, common::Unretained(hci_le_connection_callbacks), address_with_type, std::move(acl_connection))); SyncHandler(hci_callback_handler); connection_management_handler->Post(common::BindOnce( &hci::acl_manager::LeConnectionManagementCallbacks::OnReadRemoteVersionInformationComplete, common::Unretained(connection_management_callbacks), hci::ErrorCode::SUCCESS, 0, 0, 0)); auto future_1_status = future_1.wait_for(kTestIdleDisconnectTimeoutShort); EXPECT_EQ(future_1_status, std::future_status::ready); auto future_2_status = future_2.wait_for(kTestIdleDisconnectTimeoutShort); EXPECT_EQ(future_2_status, std::future_status::ready); ASSERT_NE(channel_1, nullptr); ASSERT_NE(channel_2, nullptr); // Step 4: Calling ConnectServices() to the same device will not trigger another connection attempt FixedChannelManager::ConnectionResult my_result; LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection_2{ .handler_ = user_handler_, .on_fail_callback_ = common::testing::BindLambdaForTesting( [&my_result](FixedChannelManager::ConnectionResult result) { my_result = result; })}; le_link_manager.ConnectFixedChannelServices(address_with_type, std::move(pending_fixed_channel_connection_2)); SyncHandler(user_handler_); EXPECT_EQ(my_result.connection_result_code, FixedChannelManager::ConnectionResultCode::FAIL_ALL_SERVICES_HAVE_CHANNEL); // Step 5: Register new service will cause new channels to be created during ConnectServices() MockFixedChannelServiceImpl mock_service_3; results.emplace_back(kSmpBrCid + 1, &mock_service_3); EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()).WillRepeatedly(Return(results)); LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection_3{ .handler_ = user_handler_, .on_fail_callback_ = common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; std::unique_ptr channel_3; std::promise promise_3; auto future_3 = promise_3.get_future(); EXPECT_CALL(mock_service_3, NotifyChannelCreation(_)) .WillOnce([&channel_3, &promise_3](std::unique_ptr channel) { channel_3 = std::move(channel); promise_3.set_value(); }); le_link_manager.ConnectFixedChannelServices(address_with_type, std::move(pending_fixed_channel_connection_3)); auto future_3_status = future_3.wait_for(kTestIdleDisconnectTimeoutShort); EXPECT_EQ(future_3_status, std::future_status::ready); EXPECT_NE(channel_3, nullptr); connection_management_handler->Post(common::BindOnce( &hci::acl_manager::LeConnectionManagementCallbacks::OnDisconnection, common::Unretained(connection_management_callbacks), hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION)); SyncHandler(connection_management_handler); } TEST_F(L2capLeLinkManagerTest, connect_fixed_channel_service_without_acl_with_no_service) { MockFixedChannelServiceManagerImpl mock_le_fixed_channel_service_manager; MockAclManager mock_acl_manager; hci::AddressWithType address_with_type({{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, hci::AddressType::PUBLIC_DEVICE_ADDRESS); // Step 1: Verify callback registration with HCI hci::acl_manager::LeConnectionCallbacks* hci_le_connection_callbacks = nullptr; os::Handler* hci_callback_handler = nullptr; EXPECT_CALL(mock_acl_manager, RegisterLeCallbacks(_, _)) .WillOnce(DoAll(SaveArg<0>(&hci_le_connection_callbacks), SaveArg<1>(&hci_callback_handler))); LinkManager le_link_manager( l2cap_handler_, &mock_acl_manager, &mock_le_fixed_channel_service_manager, nullptr, mock_parameter_provider_); EXPECT_EQ(hci_le_connection_callbacks, &le_link_manager); EXPECT_EQ(hci_callback_handler, l2cap_handler_); // Make sure no service is registered std::vector> results; EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()).WillRepeatedly(Return(results)); // Step 2: Connect to fixed channel without any service registered will result in failure EXPECT_CALL(mock_acl_manager, CreateLeConnection(address_with_type, true)).Times(0); FixedChannelManager::ConnectionResult my_result; LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ .handler_ = user_handler_, .on_fail_callback_ = common::testing::BindLambdaForTesting( [&my_result](FixedChannelManager::ConnectionResult result) { my_result = result; })}; le_link_manager.ConnectFixedChannelServices(address_with_type, std::move(pending_fixed_channel_connection)); SyncHandler(user_handler_); EXPECT_EQ(my_result.connection_result_code, FixedChannelManager::ConnectionResultCode::FAIL_NO_SERVICE_REGISTERED); } TEST_F(L2capLeLinkManagerTest, connect_fixed_channel_service_without_acl_with_hci_failure) { MockFixedChannelServiceManagerImpl mock_le_fixed_channel_service_manager; MockAclManager mock_acl_manager; hci::AddressWithType address_with_type({{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, hci::AddressType::RANDOM_DEVICE_ADDRESS); // Step 1: Verify callback registration with HCI hci::acl_manager::LeConnectionCallbacks* hci_le_connection_callbacks = nullptr; os::Handler* hci_callback_handler = nullptr; EXPECT_CALL(mock_acl_manager, RegisterLeCallbacks(_, _)) .WillOnce(DoAll(SaveArg<0>(&hci_le_connection_callbacks), SaveArg<1>(&hci_callback_handler))); LinkManager le_link_manager( l2cap_handler_, &mock_acl_manager, &mock_le_fixed_channel_service_manager, nullptr, mock_parameter_provider_); EXPECT_EQ(hci_le_connection_callbacks, &le_link_manager); EXPECT_EQ(hci_callback_handler, l2cap_handler_); // Register fake services MockFixedChannelServiceImpl mock_service_1; std::vector> results; results.emplace_back(kSmpBrCid, &mock_service_1); EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()).WillRepeatedly(Return(results)); // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process EXPECT_CALL(mock_acl_manager, CreateLeConnection(address_with_type, true)).Times(1); FixedChannelManager::ConnectionResult my_result; LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ .handler_ = user_handler_, .on_fail_callback_ = common::testing::BindLambdaForTesting( [&my_result](FixedChannelManager::ConnectionResult result) { my_result = result; })}; le_link_manager.ConnectFixedChannelServices(address_with_type, std::move(pending_fixed_channel_connection)); // Step 3: ACL connection failure event should trigger connection failure callback EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)).Times(0); hci_callback_handler->Post(common::BindOnce(&hci::acl_manager::LeConnectionCallbacks::OnLeConnectFail, common::Unretained(hci_le_connection_callbacks), address_with_type, hci::ErrorCode::PAGE_TIMEOUT)); SyncHandler(hci_callback_handler); SyncHandler(user_handler_); EXPECT_EQ(my_result.connection_result_code, FixedChannelManager::ConnectionResultCode::FAIL_HCI_ERROR); EXPECT_EQ(my_result.hci_error, hci::ErrorCode::PAGE_TIMEOUT); } TEST_F(L2capLeLinkManagerTest, not_acquiring_channels_should_disconnect_acl_after_timeout) { EXPECT_CALL(*mock_parameter_provider_, GetLeLinkIdleDisconnectTimeout) .WillRepeatedly(Return(kTestIdleDisconnectTimeoutShort)); MockFixedChannelServiceManagerImpl mock_le_fixed_channel_service_manager; MockAclManager mock_acl_manager; hci::AddressWithType address_with_type({{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, hci::AddressType::RANDOM_DEVICE_ADDRESS); // Step 1: Verify callback registration with HCI hci::acl_manager::LeConnectionCallbacks* hci_le_connection_callbacks = nullptr; os::Handler* hci_callback_handler = nullptr; EXPECT_CALL(mock_acl_manager, RegisterLeCallbacks(_, _)) .WillOnce(DoAll(SaveArg<0>(&hci_le_connection_callbacks), SaveArg<1>(&hci_callback_handler))); LinkManager le_link_manager( l2cap_handler_, &mock_acl_manager, &mock_le_fixed_channel_service_manager, nullptr, mock_parameter_provider_); EXPECT_EQ(hci_le_connection_callbacks, &le_link_manager); EXPECT_EQ(hci_callback_handler, l2cap_handler_); // Register fake services MockFixedChannelServiceImpl mock_service_1, mock_service_2; std::vector> results; results.emplace_back(kSmpBrCid, &mock_service_1); results.emplace_back(kConnectionlessCid, &mock_service_2); EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()).WillRepeatedly(Return(results)); // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process EXPECT_CALL(mock_acl_manager, CreateLeConnection(address_with_type, true)).Times(1); LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ .handler_ = user_handler_, .on_fail_callback_ = common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; le_link_manager.ConnectFixedChannelServices(address_with_type, std::move(pending_fixed_channel_connection)); // Step 3: ACL connection success event should trigger channel creation for all registered services auto* raw_acl_connection = new MockLeAclConnection(); std::unique_ptr acl_connection(raw_acl_connection); EXPECT_CALL(*acl_connection, GetRemoteAddress()).WillRepeatedly(Return(address_with_type)); hci::acl_manager::LeConnectionManagementCallbacks* connection_management_callbacks = nullptr; os::Handler* connection_management_handler = nullptr; EXPECT_CALL(*acl_connection, RegisterCallbacks(_, _)) .WillOnce(DoAll(SaveArg<0>(&connection_management_callbacks), SaveArg<1>(&connection_management_handler))); std::unique_ptr channel_1, channel_2; std::promise promise_1, promise_2; auto future_1 = promise_1.get_future(); auto future_2 = promise_2.get_future(); EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)) .WillOnce([&channel_1, &promise_1](std::unique_ptr channel) { channel_1 = std::move(channel); promise_1.set_value(); }); EXPECT_CALL(mock_service_2, NotifyChannelCreation(_)) .WillOnce([&channel_2, &promise_2](std::unique_ptr channel) { channel_2 = std::move(channel); promise_2.set_value(); }); hci_callback_handler->Post(common::BindOnce(&hci::acl_manager::LeConnectionCallbacks::OnLeConnectSuccess, common::Unretained(hci_le_connection_callbacks), address_with_type, std::move(acl_connection))); SyncHandler(hci_callback_handler); connection_management_handler->Post(common::BindOnce( &hci::acl_manager::LeConnectionManagementCallbacks::OnReadRemoteVersionInformationComplete, common::Unretained(connection_management_callbacks), hci::ErrorCode::SUCCESS, 0, 0, 0)); auto future_1_status = future_1.wait_for(kTestIdleDisconnectTimeoutShort); EXPECT_EQ(future_1_status, std::future_status::ready); EXPECT_NE(channel_1, nullptr); auto future_2_status = future_2.wait_for(kTestIdleDisconnectTimeoutShort); EXPECT_EQ(future_2_status, std::future_status::ready); EXPECT_NE(channel_2, nullptr); hci::ErrorCode status_1 = hci::ErrorCode::SUCCESS; channel_1->RegisterOnCloseCallback( user_handler_, common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_1 = status; })); hci::ErrorCode status_2 = hci::ErrorCode::SUCCESS; channel_2->RegisterOnCloseCallback( user_handler_, common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_2 = status; })); // Step 4: Leave channel IDLE long enough, they will disconnect EXPECT_CALL(*raw_acl_connection, Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION)).Times(1); std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 1.2); connection_management_handler->Post(common::BindOnce( &hci::acl_manager::LeConnectionManagementCallbacks::OnDisconnection, common::Unretained(connection_management_callbacks), hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST)); SyncHandler(connection_management_handler); // Step 5: Link disconnect will trigger all callbacks SyncHandler(user_handler_); EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_1); EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_2); } TEST_F(L2capLeLinkManagerTest, acquiring_channels_should_not_disconnect_acl_after_timeout) { EXPECT_CALL(*mock_parameter_provider_, GetLeLinkIdleDisconnectTimeout) .WillRepeatedly(Return(kTestIdleDisconnectTimeoutShort)); MockFixedChannelServiceManagerImpl mock_le_fixed_channel_service_manager; MockAclManager mock_acl_manager; hci::AddressWithType address_with_type({{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, hci::AddressType::RANDOM_DEVICE_ADDRESS); // Step 1: Verify callback registration with HCI hci::acl_manager::LeConnectionCallbacks* hci_le_connection_callbacks = nullptr; os::Handler* hci_callback_handler = nullptr; EXPECT_CALL(mock_acl_manager, RegisterLeCallbacks(_, _)) .WillOnce(DoAll(SaveArg<0>(&hci_le_connection_callbacks), SaveArg<1>(&hci_callback_handler))); LinkManager le_link_manager( l2cap_handler_, &mock_acl_manager, &mock_le_fixed_channel_service_manager, nullptr, mock_parameter_provider_); EXPECT_EQ(hci_le_connection_callbacks, &le_link_manager); EXPECT_EQ(hci_callback_handler, l2cap_handler_); // Register fake services MockFixedChannelServiceImpl mock_service_1, mock_service_2; std::vector> results; results.emplace_back(kSmpBrCid, &mock_service_1); results.emplace_back(kConnectionlessCid, &mock_service_2); EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()).WillRepeatedly(Return(results)); // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process EXPECT_CALL(mock_acl_manager, CreateLeConnection(address_with_type, true)).Times(1); LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ .handler_ = user_handler_, .on_fail_callback_ = common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; le_link_manager.ConnectFixedChannelServices(address_with_type, std::move(pending_fixed_channel_connection)); // Step 3: ACL connection success event should trigger channel creation for all registered services auto* raw_acl_connection = new MockLeAclConnection(); std::unique_ptr acl_connection(raw_acl_connection); EXPECT_CALL(*acl_connection, GetRemoteAddress()).WillRepeatedly(Return(address_with_type)); hci::acl_manager::LeConnectionManagementCallbacks* connection_management_callbacks = nullptr; os::Handler* connection_management_handler = nullptr; EXPECT_CALL(*acl_connection, RegisterCallbacks(_, _)) .WillOnce(DoAll(SaveArg<0>(&connection_management_callbacks), SaveArg<1>(&connection_management_handler))); std::unique_ptr channel_1, channel_2; std::promise promise_1, promise_2; auto future_1 = promise_1.get_future(); auto future_2 = promise_2.get_future(); EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)) .WillOnce([&channel_1, &promise_1](std::unique_ptr channel) { channel_1 = std::move(channel); promise_1.set_value(); }); EXPECT_CALL(mock_service_2, NotifyChannelCreation(_)) .WillOnce([&channel_2, &promise_2](std::unique_ptr channel) { channel_2 = std::move(channel); promise_2.set_value(); }); hci_callback_handler->Post(common::BindOnce(&hci::acl_manager::LeConnectionCallbacks::OnLeConnectSuccess, common::Unretained(hci_le_connection_callbacks), address_with_type, std::move(acl_connection))); SyncHandler(hci_callback_handler); connection_management_handler->Post(common::BindOnce( &hci::acl_manager::LeConnectionManagementCallbacks::OnReadRemoteVersionInformationComplete, common::Unretained(connection_management_callbacks), hci::ErrorCode::SUCCESS, 0, 0, 0)); auto future_1_status = future_1.wait_for(kTestIdleDisconnectTimeoutShort); EXPECT_EQ(future_1_status, std::future_status::ready); EXPECT_NE(channel_1, nullptr); auto future_2_status = future_2.wait_for(kTestIdleDisconnectTimeoutShort); EXPECT_EQ(future_2_status, std::future_status::ready); EXPECT_NE(channel_2, nullptr); hci::ErrorCode status_1 = hci::ErrorCode::SUCCESS; channel_1->RegisterOnCloseCallback( user_handler_, common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_1 = status; })); hci::ErrorCode status_2 = hci::ErrorCode::SUCCESS; channel_2->RegisterOnCloseCallback( user_handler_, common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_2 = status; })); channel_1->Acquire(); // Step 4: ave channel IDLE, it won't disconnect to due acquired channel 1 EXPECT_CALL(*raw_acl_connection, Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION)).Times(0); std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 2); // Step 5: Link disconnect will trigger all callbacks connection_management_handler->Post(common::BindOnce( &hci::acl_manager::LeConnectionManagementCallbacks::OnDisconnection, common::Unretained(connection_management_callbacks), hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST)); SyncHandler(connection_management_handler); SyncHandler(user_handler_); EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_1); EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_2); } TEST_F(L2capLeLinkManagerTest, acquiring_and_releasing_channels_should_eventually_disconnect_acl) { EXPECT_CALL(*mock_parameter_provider_, GetLeLinkIdleDisconnectTimeout) .WillRepeatedly(Return(kTestIdleDisconnectTimeoutShort)); MockFixedChannelServiceManagerImpl mock_le_fixed_channel_service_manager; MockAclManager mock_acl_manager; hci::AddressWithType address_with_type({{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}}, hci::AddressType::PUBLIC_IDENTITY_ADDRESS); // Step 1: Verify callback registration with HCI hci::acl_manager::LeConnectionCallbacks* hci_le_connection_callbacks = nullptr; os::Handler* hci_callback_handler = nullptr; EXPECT_CALL(mock_acl_manager, RegisterLeCallbacks(_, _)) .WillOnce(DoAll(SaveArg<0>(&hci_le_connection_callbacks), SaveArg<1>(&hci_callback_handler))); LinkManager le_link_manager( l2cap_handler_, &mock_acl_manager, &mock_le_fixed_channel_service_manager, nullptr, mock_parameter_provider_); EXPECT_EQ(hci_le_connection_callbacks, &le_link_manager); EXPECT_EQ(hci_callback_handler, l2cap_handler_); // Register fake services MockFixedChannelServiceImpl mock_service_1, mock_service_2; std::vector> results; results.emplace_back(kSmpBrCid, &mock_service_1); results.emplace_back(kConnectionlessCid, &mock_service_2); EXPECT_CALL(mock_le_fixed_channel_service_manager, GetRegisteredServices()).WillRepeatedly(Return(results)); // Step 2: Connect to fixed channel without ACL connection should trigger ACL connection process EXPECT_CALL(mock_acl_manager, CreateLeConnection(address_with_type, true)).Times(1); LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{ .handler_ = user_handler_, .on_fail_callback_ = common::BindOnce([](FixedChannelManager::ConnectionResult result) { FAIL(); })}; le_link_manager.ConnectFixedChannelServices(address_with_type, std::move(pending_fixed_channel_connection)); // Step 3: ACL connection success event should trigger channel creation for all registered services auto* raw_acl_connection = new MockLeAclConnection(); std::unique_ptr acl_connection(raw_acl_connection); EXPECT_CALL(*acl_connection, GetRemoteAddress()).WillRepeatedly(Return(address_with_type)); hci::acl_manager::LeConnectionManagementCallbacks* connection_management_callbacks = nullptr; os::Handler* connection_management_handler = nullptr; EXPECT_CALL(*acl_connection, RegisterCallbacks(_, _)) .WillOnce(DoAll(SaveArg<0>(&connection_management_callbacks), SaveArg<1>(&connection_management_handler))); std::unique_ptr channel_1, channel_2; std::promise promise_1, promise_2; auto future_1 = promise_1.get_future(); auto future_2 = promise_2.get_future(); EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)) .WillOnce([&channel_1, &promise_1](std::unique_ptr channel) { channel_1 = std::move(channel); promise_1.set_value(); }); EXPECT_CALL(mock_service_2, NotifyChannelCreation(_)) .WillOnce([&channel_2, &promise_2](std::unique_ptr channel) { channel_2 = std::move(channel); promise_2.set_value(); }); hci_callback_handler->Post(common::BindOnce(&hci::acl_manager::LeConnectionCallbacks::OnLeConnectSuccess, common::Unretained(hci_le_connection_callbacks), address_with_type, std::move(acl_connection))); SyncHandler(hci_callback_handler); connection_management_handler->Post(common::BindOnce( &hci::acl_manager::LeConnectionManagementCallbacks::OnReadRemoteVersionInformationComplete, common::Unretained(connection_management_callbacks), hci::ErrorCode::SUCCESS, 0, 0, 0)); auto future_1_status = future_1.wait_for(kTestIdleDisconnectTimeoutShort); EXPECT_EQ(future_1_status, std::future_status::ready); EXPECT_NE(channel_1, nullptr); auto future_2_status = future_2.wait_for(kTestIdleDisconnectTimeoutShort); EXPECT_EQ(future_2_status, std::future_status::ready); EXPECT_NE(channel_2, nullptr); hci::ErrorCode status_1 = hci::ErrorCode::SUCCESS; channel_1->RegisterOnCloseCallback( user_handler_, common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_1 = status; })); hci::ErrorCode status_2 = hci::ErrorCode::SUCCESS; channel_2->RegisterOnCloseCallback( user_handler_, common::testing::BindLambdaForTesting([&](hci::ErrorCode status) { status_2 = status; })); channel_1->Acquire(); // Step 4: ave channel IDLE, it won't disconnect to due acquired channel 1 EXPECT_CALL(*raw_acl_connection, Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION)).Times(0); std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 2); // Step 5: ave channel IDLE long enough, they will disconnect channel_1->Release(); EXPECT_CALL(*raw_acl_connection, Disconnect(hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION)).Times(1); std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 1.2); // Step 6: Link disconnect will trigger all callbacks connection_management_handler->Post(common::BindOnce( &hci::acl_manager::LeConnectionManagementCallbacks::OnDisconnection, common::Unretained(connection_management_callbacks), hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST)); SyncHandler(connection_management_handler); SyncHandler(user_handler_); EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_1); EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_2); } } // namespace } // namespace internal } // namespace le } // namespace l2cap } // namespace bluetooth