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

Commit 02b234dc authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

Make le LinkManager aware of AddressType

Bug: 142341141
Change-Id: I53b0d0eb8140a6109c0d3f237059b790c76a2111
parent 07330ac0
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);