Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4e7ab519 authored by Jakub Pawlowski's avatar Jakub Pawlowski Committed by Gerrit Code Review
Browse files

Merge "Make le LinkManager aware of AddressType"

parents e15805d7 02b234dc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ namespace testing {
class MockAclConnection : public AclConnection {
 public:
  MOCK_METHOD(Address, GetAddress, (), (const, override));
  MOCK_METHOD(AddressType, GetAddressType, (), (const, override));
  MOCK_METHOD(void, RegisterDisconnectCallback,
              (common::OnceCallback<void(ErrorCode)> on_disconnect, os::Handler* handler), (override));
  MOCK_METHOD(bool, Disconnect, (DisconnectReason reason), (override));
+16 −15
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ void LinkManager::ConnectFixedChannelServices(hci::Address device, hci::AddressT
    return;
  }
  // Otherwise, check if device has an ACL connection
  auto* link = GetLink(device);
  auto* link = GetLink(device, address_type);
  if (link != nullptr) {
    // If device already have an ACL connection
    // Check if all registered services have an allocated channel and allocate one if not already allocated
@@ -71,33 +71,34 @@ void LinkManager::ConnectFixedChannelServices(hci::Address device, hci::AddressT
  }
  // If not, create new ACL connection
  // Add request to pending link list first
  auto pending_link = pending_links_.find(device);
  auto pending_link = pending_links_.find({device, address_type});
  if (pending_link == pending_links_.end()) {
    // Create pending link if not exist
    pending_links_.try_emplace(device);
    pending_link = pending_links_.find(device);
    pending_links_.try_emplace({device, address_type});
    pending_link = pending_links_.find({device, address_type});
  }
  pending_link->second.pending_fixed_channel_connections_.push_back(std::move(pending_fixed_channel_connection));
  // Then create new ACL connection
  acl_manager_->CreateLeConnection(device, address_type);
}

Link* LinkManager::GetLink(const hci::Address device) {
  if (links_.find(device) == links_.end()) {
Link* LinkManager::GetLink(const hci::Address device, const hci::AddressType address_type) {
  if (links_.find({device, address_type}) == links_.end()) {
    return nullptr;
  }
  return &links_.find(device)->second;
  return &links_.find({device, address_type})->second;
}

void LinkManager::OnLeConnectSuccess(std::unique_ptr<hci::AclConnection> acl_connection) {
  // Same link should not be connected twice
  hci::Address device = acl_connection->GetAddress();
  ASSERT_LOG(GetLink(device) == nullptr, "%s is connected twice without disconnection",
  hci::AddressType address_type = acl_connection->GetAddressType();
  ASSERT_LOG(GetLink(device, address_type) == nullptr, "%s is connected twice without disconnection",
             acl_connection->GetAddress().ToString().c_str());
  auto* link_queue_up_end = acl_connection->GetAclQueueEnd();
  links_.try_emplace(device, l2cap_handler_, std::move(acl_connection),
  links_.try_emplace({device, address_type}, l2cap_handler_, std::move(acl_connection),
                     std::make_unique<l2cap::internal::Fifo>(link_queue_up_end, l2cap_handler_), parameter_provider_);
  auto* link = GetLink(device);
  auto* link = GetLink(device, address_type);
  // Allocate and distribute channels for all registered fixed channel services
  auto fixed_channel_services = service_manager_->GetRegisteredServices();
  for (auto& fixed_channel_service : fixed_channel_services) {
@@ -106,7 +107,7 @@ void LinkManager::OnLeConnectSuccess(std::unique_ptr<hci::AclConnection> acl_con
        std::make_unique<FixedChannel>(fixed_channel_impl, l2cap_handler_));
  }
  // Remove device from pending links list, if any
  auto pending_link = pending_links_.find(device);
  auto pending_link = pending_links_.find({device, address_type});
  if (pending_link == pending_links_.end()) {
    // This an incoming connection, exit
    return;
@@ -117,7 +118,7 @@ void LinkManager::OnLeConnectSuccess(std::unique_ptr<hci::AclConnection> acl_con

void LinkManager::OnLeConnectFail(hci::Address device, hci::AddressType address_type, hci::ErrorCode reason) {
  // Notify all pending links for this device
  auto pending_link = pending_links_.find(device);
  auto pending_link = pending_links_.find({device, address_type});
  if (pending_link == pending_links_.end()) {
    // There is no pending link, exit
    LOG_DEBUG("Connection to %s failed without a pending link", device.ToString().c_str());
@@ -133,12 +134,12 @@ void LinkManager::OnLeConnectFail(hci::Address device, hci::AddressType address_
  pending_links_.erase(pending_link);
}

void LinkManager::OnDisconnect(hci::Address device, hci::ErrorCode status) {
  auto* link = GetLink(device);
void LinkManager::OnDisconnect(hci::Address device, hci::AddressType address_type, hci::ErrorCode status) {
  auto* link = GetLink(device, address_type);
  ASSERT_LOG(link != nullptr, "Device %s is disconnected with reason 0x%x, but not in local database",
             device.ToString().c_str(), static_cast<uint8_t>(status));
  link->OnAclDisconnected(status);
  links_.erase(device);
  links_.erase({device, address_type});
}

}  // namespace internal
+23 −4
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@

#include <memory>
#include <unordered_map>
#include <utility>

#include "os/handler.h"

@@ -53,12 +54,30 @@ class LinkManager : public hci::LeConnectionCallbacks {
    std::vector<PendingFixedChannelConnection> pending_fixed_channel_connections_;
  };

  struct LinkIdentifier {
    hci::Address address;
    hci::AddressType address_type;
    LinkIdentifier(hci::Address address, hci::AddressType address_type)
        : address(address), address_type(address_type){};

    bool operator==(const LinkIdentifier& li) const {
      return address == li.address && address_type == li.address_type;
    }

    struct Hasher {
      std::size_t operator()(const LinkIdentifier& li) const {
        std::hash<bluetooth::hci::Address> h;
        return h(li.address);
      }
    };
  };

  // ACL methods

  Link* GetLink(hci::Address device);
  Link* GetLink(hci::Address device, hci::AddressType address_type);
  void OnLeConnectSuccess(std::unique_ptr<hci::AclConnection> acl_connection) override;
  void OnLeConnectFail(hci::Address device, hci::AddressType address_type, hci::ErrorCode reason) override;
  void OnDisconnect(hci::Address device, hci::ErrorCode status);
  void OnDisconnect(hci::Address device, hci::AddressType address_type, hci::ErrorCode status);

  // FixedChannelManager methods

@@ -73,8 +92,8 @@ class LinkManager : public hci::LeConnectionCallbacks {
  l2cap::internal::ParameterProvider* parameter_provider_;

  // Internal states
  std::unordered_map<hci::Address, PendingLink> pending_links_;
  std::unordered_map<hci::Address, Link> links_;
  std::unordered_map<LinkIdentifier, PendingLink, LinkIdentifier::Hasher> pending_links_;
  std::unordered_map<LinkIdentifier, Link, LinkIdentifier::Hasher> links_;
  DISALLOW_COPY_AND_ASSIGN(LinkManager);
};

+8 −4
Original line number Diff line number Diff line
@@ -120,6 +120,7 @@ TEST_F(L2capLeLinkManagerTest, connect_fixed_channel_service_without_acl) {
  hci::AclConnection::Queue link_queue{10};
  EXPECT_CALL(*acl_connection, GetAclQueueEnd()).WillRepeatedly((Return(link_queue.GetUpEnd())));
  EXPECT_CALL(*acl_connection, GetAddress()).WillRepeatedly(Return(device));
  EXPECT_CALL(*acl_connection, GetAddressType()).WillRepeatedly(Return(address_type));
  std::unique_ptr<FixedChannel> channel_1, channel_2;
  EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)).WillOnce([&channel_1](std::unique_ptr<FixedChannel> channel) {
    channel_1 = std::move(channel);
@@ -161,7 +162,7 @@ TEST_F(L2capLeLinkManagerTest, connect_fixed_channel_service_without_acl) {

  user_handler->Clear();

  le_link_manager.OnDisconnect(device, hci::ErrorCode::SUCCESS);
  le_link_manager.OnDisconnect(device, address_type, hci::ErrorCode::SUCCESS);
}

TEST_F(L2capLeLinkManagerTest, connect_fixed_channel_service_without_acl_with_no_service) {
@@ -283,6 +284,7 @@ TEST_F(L2capLeLinkManagerTest, not_acquiring_channels_should_disconnect_acl_afte
  hci::AclConnection::Queue link_queue{10};
  EXPECT_CALL(*acl_connection, GetAclQueueEnd()).WillRepeatedly((Return(link_queue.GetUpEnd())));
  EXPECT_CALL(*acl_connection, GetAddress()).WillRepeatedly(Return(device));
  EXPECT_CALL(*acl_connection, GetAddressType()).WillRepeatedly(Return(address_type));
  std::unique_ptr<FixedChannel> channel_1, channel_2;
  EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)).WillOnce([&channel_1](std::unique_ptr<FixedChannel> channel) {
    channel_1 = std::move(channel);
@@ -308,7 +310,7 @@ TEST_F(L2capLeLinkManagerTest, not_acquiring_channels_should_disconnect_acl_afte
  std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 1.2);

  // Step 5: Link disconnect will trigger all callbacks
  le_link_manager.OnDisconnect(device, hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST);
  le_link_manager.OnDisconnect(device, address_type, hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST);
  SyncHandler(user_handler.get());
  EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_1);
  EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_2);
@@ -355,6 +357,7 @@ TEST_F(L2capLeLinkManagerTest, acquiring_channels_should_not_disconnect_acl_afte
  hci::AclConnection::Queue link_queue{10};
  EXPECT_CALL(*acl_connection, GetAclQueueEnd()).WillRepeatedly((Return(link_queue.GetUpEnd())));
  EXPECT_CALL(*acl_connection, GetAddress()).WillRepeatedly(Return(device));
  EXPECT_CALL(*acl_connection, GetAddressType()).WillRepeatedly(Return(address_type));
  std::unique_ptr<FixedChannel> channel_1, channel_2;
  EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)).WillOnce([&channel_1](std::unique_ptr<FixedChannel> channel) {
    channel_1 = std::move(channel);
@@ -382,7 +385,7 @@ TEST_F(L2capLeLinkManagerTest, acquiring_channels_should_not_disconnect_acl_afte
  std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 2);

  // Step 5: Link disconnect will trigger all callbacks
  le_link_manager.OnDisconnect(device, hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST);
  le_link_manager.OnDisconnect(device, address_type, hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST);
  SyncHandler(user_handler.get());
  EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_1);
  EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_2);
@@ -429,6 +432,7 @@ TEST_F(L2capLeLinkManagerTest, acquiring_and_releasing_channels_should_eventuall
  hci::AclConnection::Queue link_queue{10};
  EXPECT_CALL(*acl_connection, GetAclQueueEnd()).WillRepeatedly((Return(link_queue.GetUpEnd())));
  EXPECT_CALL(*acl_connection, GetAddress()).WillRepeatedly(Return(device));
  EXPECT_CALL(*acl_connection, GetAddressType()).WillRepeatedly(Return(address_type));
  std::unique_ptr<FixedChannel> channel_1, channel_2;
  EXPECT_CALL(mock_service_1, NotifyChannelCreation(_)).WillOnce([&channel_1](std::unique_ptr<FixedChannel> channel) {
    channel_1 = std::move(channel);
@@ -461,7 +465,7 @@ TEST_F(L2capLeLinkManagerTest, acquiring_and_releasing_channels_should_eventuall
  std::this_thread::sleep_for(kTestIdleDisconnectTimeoutShort * 1.2);

  // Step 6: Link disconnect will trigger all callbacks
  le_link_manager.OnDisconnect(device, hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST);
  le_link_manager.OnDisconnect(device, address_type, hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST);
  SyncHandler(user_handler.get());
  EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_1);
  EXPECT_EQ(hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST, status_2);