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

Commit 10ed2a3e authored by Jack He's avatar Jack He
Browse files

L2CAP: Use AddressWithType in L2CAP LE APIs

* Bluetooth Low Energy connections always require explicit AddressType
  information
* Replacing existing Address and AddressType arguments in l2cap::le
  stack with hci::AddressWithType objects for easier hashing and
  managment

Bug: 140938432
Test: bluetooth_test_gd
Change-Id: I87ce02f0a0c867053a2b3560886924a566881801
parent 16de5463
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -23,14 +23,14 @@ namespace bluetooth {
namespace l2cap {
namespace le {

bool FixedChannelManager::ConnectServices(hci::Address device, hci::AddressType address_type,
bool FixedChannelManager::ConnectServices(hci::AddressWithType address_with_type,
                                          OnConnectionFailureCallback on_fail_callback, os::Handler* handler) {
  internal::LinkManager::PendingFixedChannelConnection pending_fixed_channel_connection{
      .handler_ = handler,
      .on_fail_callback_ = std::move(on_fail_callback),
  };
  l2cap_layer_handler_->Post(common::BindOnce(&internal::LinkManager::ConnectFixedChannelServices,
                                              common::Unretained(link_manager_), device, address_type,
                                              common::Unretained(link_manager_), address_with_type,
                                              std::move(pending_fixed_channel_connection)));
  return true;
}
+3 −3
Original line number Diff line number Diff line
@@ -18,7 +18,7 @@
#include <string>

#include "hci/acl_manager.h"
#include "hci/address.h"
#include "hci/address_with_type.h"
#include "l2cap/cid.h"
#include "l2cap/le/fixed_channel.h"
#include "l2cap/le/fixed_channel_service.h"
@@ -96,14 +96,14 @@ class FixedChannelManager {
   * A module calling ConnectServices() must have called RegisterService() before.
   * The callback will come back from on_open_callback in the service that is registered
   *
   * @param device: Remote device to make this connection.
   * @param address_with_type: Remote device with type to make this connection.
   * @param address_type: Address type of remote device
   * @param on_fail_callback: A callback to indicate connection failure along with a status code.
   * @param handler: The handler context in which to execute the @callback parameters.
   *
   * Returns: true if connection was able to be initiated, false otherwise.
   */
  bool ConnectServices(hci::Address device, hci::AddressType address_type, OnConnectionFailureCallback on_fail_callback,
  bool ConnectServices(hci::AddressWithType address_with_type, OnConnectionFailureCallback on_fail_callback,
                       os::Handler* handler);

  /**
+21 −21
Original line number Diff line number Diff line
@@ -30,7 +30,7 @@ namespace l2cap {
namespace le {
namespace internal {

void LinkManager::ConnectFixedChannelServices(hci::Address device, hci::AddressType address_type,
void LinkManager::ConnectFixedChannelServices(hci::AddressWithType address_with_type,
                                              PendingFixedChannelConnection pending_fixed_channel_connection) {
  // Check if there is any service registered
  auto fixed_channel_services = service_manager_->GetRegisteredServices();
@@ -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, address_type);
  auto* link = GetLink(address_with_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,34 +71,33 @@ 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, address_type});
  auto pending_link = pending_links_.find(address_with_type);
  if (pending_link == pending_links_.end()) {
    // Create pending link if not exist
    pending_links_.try_emplace({device, address_type});
    pending_link = pending_links_.find({device, address_type});
    pending_links_.try_emplace(address_with_type);
    pending_link = pending_links_.find(address_with_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);
  acl_manager_->CreateLeConnection(address_with_type.GetAddress(), address_with_type.GetAddressType());
}

Link* LinkManager::GetLink(const hci::Address device, const hci::AddressType address_type) {
  if (links_.find({device, address_type}) == links_.end()) {
Link* LinkManager::GetLink(hci::AddressWithType address_with_type) {
  if (links_.find(address_with_type) == links_.end()) {
    return nullptr;
  }
  return &links_.find({device, address_type})->second;
  return &links_.find(address_with_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();
  hci::AddressType address_type = acl_connection->GetAddressType();
  ASSERT_LOG(GetLink(device, address_type) == nullptr, "%s is connected twice without disconnection",
  hci::AddressWithType address_with_type(acl_connection->GetAddress(), acl_connection->GetAddressType());
  ASSERT_LOG(GetLink(address_with_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, address_type}, l2cap_handler_, std::move(acl_connection),
  links_.try_emplace(address_with_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, address_type);
  auto* link = GetLink(address_with_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) {
@@ -107,7 +106,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, address_type});
  auto pending_link = pending_links_.find(address_with_type);
  if (pending_link == pending_links_.end()) {
    // This an incoming connection, exit
    return;
@@ -118,10 +117,11 @@ 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, address_type});
  hci::AddressWithType address_with_type(device, address_type);
  auto pending_link = pending_links_.find(address_with_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());
    LOG_DEBUG("Connection to %s failed without a pending link", address_with_type.ToString().c_str());
    return;
  }
  for (auto& pending_fixed_channel_connection : pending_link->second.pending_fixed_channel_connections_) {
@@ -134,12 +134,12 @@ void LinkManager::OnLeConnectFail(hci::Address device, hci::AddressType address_
  pending_links_.erase(pending_link);
}

void LinkManager::OnDisconnect(hci::Address device, hci::AddressType address_type, hci::ErrorCode status) {
  auto* link = GetLink(device, address_type);
void LinkManager::OnDisconnect(hci::AddressWithType address_with_type, hci::ErrorCode status) {
  auto* link = GetLink(address_with_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));
             address_with_type.ToString().c_str(), static_cast<uint8_t>(status));
  link->OnAclDisconnected(status);
  links_.erase({device, address_type});
  links_.erase(address_with_type);
}

}  // namespace internal
+8 −26
Original line number Diff line number Diff line
@@ -22,15 +22,15 @@

#include "os/handler.h"

#include "hci/acl_manager.h"
#include "hci/address.h"
#include "hci/address_with_type.h"
#include "l2cap/internal/parameter_provider.h"
#include "l2cap/internal/scheduler.h"
#include "l2cap/le/fixed_channel_manager.h"
#include "l2cap/le/internal/fixed_channel_service_manager_impl.h"
#include "l2cap/le/internal/link.h"

#include "hci/acl_manager.h"
#include "hci/address.h"

namespace bluetooth {
namespace l2cap {
namespace le {
@@ -54,34 +54,16 @@ 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, hci::AddressType address_type);
  Link* GetLink(hci::AddressWithType address_with_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::AddressType address_type, hci::ErrorCode status);
  void OnDisconnect(hci::AddressWithType address_with_type, hci::ErrorCode status);

  // FixedChannelManager methods

  void ConnectFixedChannelServices(hci::Address device, hci::AddressType address_type,
  void ConnectFixedChannelServices(hci::AddressWithType address_with_type,
                                   PendingFixedChannelConnection pending_fixed_channel_connection);

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

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

+47 −41

File changed.

Preview size limit exceeded, changes collapsed.