// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/bredr_connection_manager.h"

#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/assert.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/expiring_set.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/inspectable.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/bredr_connection.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/bredr_interrogator.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/gap.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/peer_cache.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci-spec/constants.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci-spec/protocol.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci-spec/util.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci/bredr_connection.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci/sequential_command_runner.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/l2cap/l2cap_defs.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/l2cap/types.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/transport/emboss_control_packets.h"

namespace bt::gap {

using ConnectionState = Peer::ConnectionState;

namespace {

const char* const kInspectRequestsNodeName = "connection_requests";
const char* const kInspectRequestNodeNamePrefix = "request_";
const char* const kInspectSecurityModeName = "security_mode";
const char* const kInspectConnectionsNodeName = "connections";
const char* const kInspectConnectionNodeNamePrefix = "connection_";
const char* const kInspectLastDisconnectedListName = "last_disconnected";
const char* const kInspectLastDisconnectedItemDurationPropertyName =
    "duration_s";
const char* const kInspectLastDisconnectedItemPeerPropertyName = "peer_id";
const char* const kInspectTimestampPropertyName = "@time";
const char* const kInspectOutgoingNodeName = "outgoing";
const char* const kInspectIncomingNodeName = "incoming";
const char* const kInspectConnectionAttemptsNodeName = "connection_attempts";
const char* const kInspectSuccessfulConnectionsNodeName =
    "successful_connections";
const char* const kInspectFailedConnectionsNodeName = "failed_connections";
const char* const kInspectInterrogationCompleteCountNodeName =
    "interrogation_complete_count";
const char* const kInspectLocalApiRequestCountNodeName =
    "disconnect_local_api_request_count";
const char* const kInspectInterrogationFailedCountNodeName =
    "disconnect_interrogation_failed_count";
const char* const kInspectPairingFailedCountNodeName =
    "disconnect_pairing_failed_count";
const char* const kInspectAclLinkErrorCountNodeName =
    "disconnect_acl_link_error_count";
const char* const kInspectPeerDisconnectionCountNodeName =
    "disconnect_peer_disconnection_count";

std::string ReasonAsString(DisconnectReason reason) {
  switch (reason) {
    case DisconnectReason::kApiRequest:
      return "ApiRequest";
    case DisconnectReason::kInterrogationFailed:
      return "InterrogationFailed";
    case DisconnectReason::kPairingFailed:
      return "PairingFailed";
    case DisconnectReason::kAclLinkError:
      return "AclLinkError";
    case DisconnectReason::kPeerDisconnection:
      return "PeerDisconnection";
    default:
      return "<Unknown Reason>";
  }
}

// This procedure can continue to operate independently of the existence of an
// BrEdrConnectionManager instance, which will begin to disable Page Scan as it
// shuts down.
void SetPageScanEnabled(bool enabled,
                        hci::Transport::WeakPtr hci,
                        hci::ResultFunction<> cb) {
  BT_DEBUG_ASSERT(cb);
  auto read_enable = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::ReadScanEnableCommandWriter>(
      hci_spec::kReadScanEnable);
  auto finish_enable_cb = [enabled, hci, finish_cb = std::move(cb)](
                              auto, const hci::EventPacket& event) mutable {
    if (hci_is_error(event, WARN, "gap-bredr", "read scan enable failed")) {
      finish_cb(event.ToResult());
      return;
    }

    auto params = event.return_params<hci_spec::ReadScanEnableReturnParams>();
    uint8_t scan_type = params->scan_enable;
    if (enabled) {
      scan_type |= static_cast<uint8_t>(hci_spec::ScanEnableBit::kPage);
    } else {
      scan_type &= ~static_cast<uint8_t>(hci_spec::ScanEnableBit::kPage);
    }

    auto write_enable = hci::EmbossCommandPacket::New<
        pw::bluetooth::emboss::WriteScanEnableCommandWriter>(
        hci_spec::kWriteScanEnable);
    auto write_enable_view = write_enable.view_t();
    write_enable_view.scan_enable().inquiry().Write(
        scan_type & static_cast<uint8_t>(hci_spec::ScanEnableBit::kInquiry));
    write_enable_view.scan_enable().page().Write(
        scan_type & static_cast<uint8_t>(hci_spec::ScanEnableBit::kPage));
    hci->command_channel()->SendCommand(
        std::move(write_enable),
        [cb = std::move(finish_cb)](auto, const hci::EventPacket& event) {
          cb(event.ToResult());
        });
  };
  hci->command_channel()->SendCommand(std::move(read_enable),
                                      std::move(finish_enable_cb));
}

}  // namespace

hci::CommandChannel::EventHandlerId BrEdrConnectionManager::AddEventHandler(
    const hci_spec::EventCode& code,
    hci::CommandChannel::EventCallbackVariant cb) {
  auto self = weak_self_.GetWeakPtr();
  hci::CommandChannel::EventHandlerId event_id = 0;
  event_id = std::visit(
      [hci = hci_, &self, code](
          auto&& cb) -> hci::CommandChannel::EventHandlerId {
        using T = std::decay_t<decltype(cb)>;
        if constexpr (std::is_same_v<T, hci::CommandChannel::EventCallback>) {
          return hci->command_channel()->AddEventHandler(
              code, [self, cb = std::move(cb)](const hci::EventPacket& event) {
                if (!self.is_alive()) {
                  return hci::CommandChannel::EventCallbackResult::kRemove;
                }
                return cb(event);
              });
        } else if constexpr (std::is_same_v<
                                 T,
                                 hci::CommandChannel::EmbossEventCallback>) {
          return hci->command_channel()->AddEventHandler(
              code,
              [self, cb = std::move(cb)](const hci::EmbossEventPacket& event) {
                if (!self.is_alive()) {
                  return hci::CommandChannel::EventCallbackResult::kRemove;
                }
                return cb(event);
              });
        }
      },
      std::move(cb));
  BT_DEBUG_ASSERT(event_id);
  event_handler_ids_.push_back(event_id);
  return event_id;
}

BrEdrConnectionManager::BrEdrConnectionManager(
    hci::Transport::WeakPtr hci,
    PeerCache* peer_cache,
    DeviceAddress local_address,
    l2cap::ChannelManager* l2cap,
    bool use_interlaced_scan,
    bool local_secure_connections_supported,
    pw::async::Dispatcher& dispatcher)
    : hci_(std::move(hci)),
      cache_(peer_cache),
      local_address_(local_address),
      l2cap_(l2cap),
      deny_incoming_(dispatcher),
      page_scan_interval_(0),
      page_scan_window_(0),
      use_interlaced_scan_(use_interlaced_scan),
      local_secure_connections_supported_(local_secure_connections_supported),
      dispatcher_(dispatcher),
      weak_self_(this) {
  BT_DEBUG_ASSERT(hci_.is_alive());
  BT_DEBUG_ASSERT(cache_);
  BT_DEBUG_ASSERT(l2cap_);

  hci_cmd_runner_ = std::make_unique<hci::SequentialCommandRunner>(
      hci_->command_channel()->AsWeakPtr());

  // Register event handlers
  AddEventHandler(
      hci_spec::kAuthenticationCompleteEventCode,
      fit::bind_member<&BrEdrConnectionManager::OnAuthenticationComplete>(
          this));
  AddEventHandler(
      hci_spec::kConnectionCompleteEventCode,
      fit::bind_member<&BrEdrConnectionManager::OnConnectionComplete>(this));
  AddEventHandler(
      hci_spec::kConnectionRequestEventCode,
      fit::bind_member<&BrEdrConnectionManager::OnConnectionRequest>(this));
  AddEventHandler(
      hci_spec::kIOCapabilityRequestEventCode,
      fit::bind_member<&BrEdrConnectionManager::OnIoCapabilityRequest>(this));
  AddEventHandler(
      hci_spec::kIOCapabilityResponseEventCode,
      fit::bind_member<&BrEdrConnectionManager::OnIoCapabilityResponse>(this));
  AddEventHandler(
      hci_spec::kLinkKeyRequestEventCode,
      fit::bind_member<&BrEdrConnectionManager::OnLinkKeyRequest>(this));
  AddEventHandler(
      hci_spec::kLinkKeyNotificationEventCode,
      fit::bind_member<&BrEdrConnectionManager::OnLinkKeyNotification>(this));
  AddEventHandler(
      hci_spec::kSimplePairingCompleteEventCode,
      fit::bind_member<&BrEdrConnectionManager::OnSimplePairingComplete>(this));
  AddEventHandler(
      hci_spec::kUserConfirmationRequestEventCode,
      fit::bind_member<&BrEdrConnectionManager::OnUserConfirmationRequest>(
          this));
  AddEventHandler(
      hci_spec::kUserPasskeyRequestEventCode,
      fit::bind_member<&BrEdrConnectionManager::OnUserPasskeyRequest>(this));
  AddEventHandler(
      hci_spec::kUserPasskeyNotificationEventCode,
      fit::bind_member<&BrEdrConnectionManager::OnUserPasskeyNotification>(
          this));
  AddEventHandler(
      hci_spec::kRoleChangeEventCode,
      fit::bind_member<&BrEdrConnectionManager::OnRoleChange>(this));

  // Set the timeout for outbound connections explicitly to the spec default.
  WritePageTimeout(
      hci_spec::kDefaultPageTimeoutDuration, [](const hci::Result<> status) {
        [[maybe_unused]] bool _ =
            bt_is_error(status, WARN, "gap-bredr", "write page timeout failed");
      });
}

BrEdrConnectionManager::~BrEdrConnectionManager() {
  // Disconnect any connections that we're holding.
  connections_.clear();

  if (!hci_.is_alive() || !hci_->command_channel()) {
    return;
  }

  if (pending_request_ && pending_request_->Cancel())
    SendCreateConnectionCancelCommand(pending_request_->peer_address());

  // Become unconnectable
  SetPageScanEnabled(/*enabled=*/false, hci_, [](const auto) {});

  // Remove all event handlers
  for (auto handler_id : event_handler_ids_) {
    hci_->command_channel()->RemoveEventHandler(handler_id);
  }
}

void BrEdrConnectionManager::SetConnectable(bool connectable,
                                            hci::ResultFunction<> status_cb) {
  auto self = weak_self_.GetWeakPtr();
  if (!connectable) {
    auto not_connectable_cb = [self,
                               cb = std::move(status_cb)](const auto& status) {
      if (self.is_alive()) {
        self->page_scan_interval_ = 0;
        self->page_scan_window_ = 0;
      } else if (status.is_ok()) {
        cb(ToResult(HostError::kFailed));
        return;
      }
      cb(status);
    };
    SetPageScanEnabled(/*enabled=*/false, hci_, std::move(not_connectable_cb));
    return;
  }

  WritePageScanSettings(
      hci_spec::kPageScanR1Interval,
      hci_spec::kPageScanR1Window,
      use_interlaced_scan_,
      [self, cb = std::move(status_cb)](const auto& status) mutable {
        if (bt_is_error(
                status, WARN, "gap-bredr", "Write Page Scan Settings failed")) {
          cb(status);
          return;
        }
        if (!self.is_alive()) {
          cb(ToResult(HostError::kFailed));
          return;
        }
        SetPageScanEnabled(/*enabled=*/true, self->hci_, std::move(cb));
      });
}

void BrEdrConnectionManager::SetPairingDelegate(
    PairingDelegate::WeakPtr delegate) {
  pairing_delegate_ = std::move(delegate);
  for (auto& [handle, connection] : connections_) {
    connection.pairing_state().SetPairingDelegate(pairing_delegate_);
  }
}

PeerId BrEdrConnectionManager::GetPeerId(
    hci_spec::ConnectionHandle handle) const {
  auto it = connections_.find(handle);
  if (it == connections_.end()) {
    return kInvalidPeerId;
  }

  auto* peer = cache_->FindByAddress(it->second.link().peer_address());
  BT_DEBUG_ASSERT_MSG(peer, "Couldn't find peer for handle %#.4x", handle);
  return peer->identifier();
}

void BrEdrConnectionManager::Pair(PeerId peer_id,
                                  BrEdrSecurityRequirements security,
                                  hci::ResultFunction<> callback) {
  auto conn_pair = FindConnectionById(peer_id);
  if (!conn_pair) {
    bt_log(WARN,
           "gap-bredr",
           "can't pair to peer_id %s: connection not found",
           bt_str(peer_id));
    callback(ToResult(HostError::kNotFound));
    return;
  }

  auto& [handle, connection] = *conn_pair;
  auto pairing_callback = [pair_callback = std::move(callback)](
                              auto, hci::Result<> status) {
    pair_callback(status);
  };
  connection->pairing_state().InitiatePairing(security,
                                              std::move(pairing_callback));
}

void BrEdrConnectionManager::OpenL2capChannel(
    PeerId peer_id,
    l2cap::Psm psm,
    BrEdrSecurityRequirements security_reqs,
    l2cap::ChannelParameters params,
    l2cap::ChannelCallback cb) {
  auto pairing_cb = [self = weak_self_.GetWeakPtr(),
                     peer_id,
                     psm,
                     params,
                     cb = std::move(cb)](auto status) mutable {
    bt_log(TRACE,
           "gap-bredr",
           "got pairing status %s, %sreturning socket to %s",
           bt_str(status),
           status.is_ok() ? "" : "not ",
           bt_str(peer_id));
    if (status.is_error() || !self.is_alive()) {
      // Report the failure to the user with a null channel.
      cb(l2cap::Channel::WeakPtr());
      return;
    }

    auto conn_pair = self->FindConnectionById(peer_id);
    if (!conn_pair) {
      bt_log(INFO,
             "gap-bredr",
             "can't open l2cap channel: connection not found (peer: %s)",
             bt_str(peer_id));
      cb(l2cap::Channel::WeakPtr());
      return;
    }
    auto& [handle, connection] = *conn_pair;

    connection->OpenL2capChannel(
        psm, params, [cb = std::move(cb)](auto chan) { cb(std::move(chan)); });
  };

  Pair(peer_id, security_reqs, std::move(pairing_cb));
}

BrEdrConnectionManager::SearchId BrEdrConnectionManager::AddServiceSearch(
    const UUID& uuid,
    std::unordered_set<sdp::AttributeId> attributes,
    BrEdrConnectionManager::SearchCallback callback) {
  auto on_service_discovered =
      [self = weak_self_.GetWeakPtr(), uuid, client_cb = std::move(callback)](
          PeerId peer_id, auto& attributes) {
        if (self.is_alive()) {
          Peer* const peer = self->cache_->FindById(peer_id);
          BT_ASSERT(peer);
          peer->MutBrEdr().AddService(uuid);
        }
        client_cb(peer_id, attributes);
      };
  SearchId new_id = discoverer_.AddSearch(
      uuid, std::move(attributes), std::move(on_service_discovered));
  for (auto& [handle, connection] : connections_) {
    auto self = weak_self_.GetWeakPtr();
    connection.OpenL2capChannel(
        l2cap::kSDP,
        l2cap::ChannelParameters(),
        [self, peer_id = connection.peer_id(), search_id = new_id](
            auto channel) {
          if (!self.is_alive()) {
            return;
          }
          if (!channel.is_alive()) {
            // Likely interrogation is not complete. Search will be done at end
            // of interrogation.
            bt_log(INFO,
                   "gap",
                   "no l2cap channel for new search (peer: %s)",
                   bt_str(peer_id));
            // Try anyway, maybe there's a channel open
            self->discoverer_.SingleSearch(search_id, peer_id, nullptr);
            return;
          }
          auto client =
              sdp::Client::Create(std::move(channel), self->dispatcher_);
          self->discoverer_.SingleSearch(search_id, peer_id, std::move(client));
        });
  }
  return new_id;
}

bool BrEdrConnectionManager::RemoveServiceSearch(SearchId id) {
  return discoverer_.RemoveSearch(id);
}

std::optional<BrEdrConnectionManager::ScoRequestHandle>
BrEdrConnectionManager::OpenScoConnection(
    PeerId peer_id,
    bt::StaticPacket<
        pw::bluetooth::emboss::SynchronousConnectionParametersWriter>
        parameters,
    sco::ScoConnectionManager::OpenConnectionCallback callback) {
  auto conn_pair = FindConnectionById(peer_id);
  if (!conn_pair) {
    bt_log(WARN,
           "gap-bredr",
           "Can't open SCO connection to unconnected peer (peer: %s)",
           bt_str(peer_id));
    callback(fit::error(HostError::kNotFound));
    return std::nullopt;
  };
  return conn_pair->second->OpenScoConnection(std::move(parameters),
                                              std::move(callback));
}

std::optional<BrEdrConnectionManager::ScoRequestHandle>
BrEdrConnectionManager::AcceptScoConnection(
    PeerId peer_id,
    std::vector<bt::StaticPacket<
        pw::bluetooth::emboss::SynchronousConnectionParametersWriter>>
        parameters,
    sco::ScoConnectionManager::AcceptConnectionCallback callback) {
  auto conn_pair = FindConnectionById(peer_id);
  if (!conn_pair) {
    bt_log(WARN,
           "gap-bredr",
           "Can't accept SCO connection from unconnected peer (peer: %s)",
           bt_str(peer_id));
    callback(fit::error(HostError::kNotFound));
    return std::nullopt;
  };
  return conn_pair->second->AcceptScoConnection(std::move(parameters),
                                                std::move(callback));
}

bool BrEdrConnectionManager::Disconnect(PeerId peer_id,
                                        DisconnectReason reason) {
  bt_log(INFO,
         "gap-bredr",
         "Disconnect Requested (reason %hhu - %s) (peer: %s)",
         static_cast<unsigned char>(reason),
         ReasonAsString(reason).c_str(),
         bt_str(peer_id));

  // TODO(https://fxbug.dev/42143836) - If a disconnect request is received when
  // we have a pending connection, we should instead abort the connection, by
  // either:
  //   * removing the request if it has not yet been processed
  //   * sending a cancel command to the controller and waiting for it to be
  //   processed
  //   * sending a cancel command, and if we already complete, then beginning a
  //   disconnect procedure
  if (connection_requests_.find(peer_id) != connection_requests_.end()) {
    bt_log(WARN,
           "gap-bredr",
           "Can't disconnect because it's being connected to (peer: %s)",
           bt_str(peer_id));
    return false;
  }

  auto conn_pair = FindConnectionById(peer_id);
  if (!conn_pair) {
    bt_log(INFO,
           "gap-bredr",
           "No need to disconnect: It is not connected (peer: %s)",
           bt_str(peer_id));
    return true;
  }

  auto [handle, connection] = *conn_pair;

  const DeviceAddress& peer_addr = connection->link().peer_address();
  if (reason == DisconnectReason::kApiRequest) {
    bt_log(DEBUG,
           "gap-bredr",
           "requested disconnect from peer, cooldown for %llds (addr: %s)",
           std::chrono::duration_cast<std::chrono::seconds>(
               kLocalDisconnectCooldownDuration)
               .count(),
           bt_str(peer_addr));
    deny_incoming_.add_until(
        peer_addr, dispatcher_.now() + kLocalDisconnectCooldownDuration);
  }

  CleanUpConnection(
      handle, std::move(connections_.extract(handle).mapped()), reason);
  return true;
}

void BrEdrConnectionManager::SetSecurityMode(BrEdrSecurityMode mode) {
  security_mode_.Set(mode);

  if (mode == BrEdrSecurityMode::SecureConnectionsOnly) {
    // `Disconnect`ing the peer must not be done while iterating through
    // `connections_` as it removes the connection from `connections_`, hence
    // the helper vector.
    std::vector<PeerId> insufficiently_secure_peers;
    for (auto& [_, connection] : connections_) {
      if (connection.security_properties().level() !=
          sm::SecurityLevel::kSecureAuthenticated) {
        insufficiently_secure_peers.push_back(connection.peer_id());
      }
    }
    for (PeerId id : insufficiently_secure_peers) {
      bt_log(WARN,
             "gap-bredr",
             "Peer has insufficient security for Secure Connections Only mode. \
             Closing connection for peer (%s)",
             bt_str(id));
      Disconnect(id, DisconnectReason::kPairingFailed);
    }
  }
  for (auto& [_, connection] : connections_) {
    connection.set_security_mode(mode);
  }
}

void BrEdrConnectionManager::AttachInspect(inspect::Node& parent,
                                           std::string name) {
  inspect_node_ = parent.CreateChild(name);

  security_mode_.AttachInspect(inspect_node_, kInspectSecurityModeName);

  inspect_properties_.connections_node_ =
      inspect_node_.CreateChild(kInspectConnectionsNodeName);
  inspect_properties_.last_disconnected_list.AttachInspect(
      inspect_node_, kInspectLastDisconnectedListName);

  inspect_properties_.requests_node_ =
      inspect_node_.CreateChild(kInspectRequestsNodeName);
  for (auto& [_, req] : connection_requests_) {
    req.AttachInspect(inspect_properties_.requests_node_,
                      inspect_properties_.requests_node_.UniqueName(
                          kInspectRequestNodeNamePrefix));
  }

  inspect_properties_.outgoing_.node_ =
      inspect_node_.CreateChild(kInspectOutgoingNodeName);
  inspect_properties_.outgoing_.connection_attempts_.AttachInspect(
      inspect_properties_.outgoing_.node_, kInspectConnectionAttemptsNodeName);
  inspect_properties_.outgoing_.successful_connections_.AttachInspect(
      inspect_properties_.outgoing_.node_,
      kInspectSuccessfulConnectionsNodeName);
  inspect_properties_.outgoing_.failed_connections_.AttachInspect(
      inspect_properties_.outgoing_.node_, kInspectFailedConnectionsNodeName);

  inspect_properties_.incoming_.node_ =
      inspect_node_.CreateChild(kInspectIncomingNodeName);
  inspect_properties_.incoming_.connection_attempts_.AttachInspect(
      inspect_properties_.incoming_.node_, kInspectConnectionAttemptsNodeName);
  inspect_properties_.incoming_.successful_connections_.AttachInspect(
      inspect_properties_.incoming_.node_,
      kInspectSuccessfulConnectionsNodeName);
  inspect_properties_.incoming_.failed_connections_.AttachInspect(
      inspect_properties_.incoming_.node_, kInspectFailedConnectionsNodeName);

  inspect_properties_.interrogation_complete_count_.AttachInspect(
      inspect_node_, kInspectInterrogationCompleteCountNodeName);

  inspect_properties_.disconnect_local_api_request_count_.AttachInspect(
      inspect_node_, kInspectLocalApiRequestCountNodeName);
  inspect_properties_.disconnect_interrogation_failed_count_.AttachInspect(
      inspect_node_, kInspectInterrogationFailedCountNodeName);
  inspect_properties_.disconnect_pairing_failed_count_.AttachInspect(
      inspect_node_, kInspectPairingFailedCountNodeName);
  inspect_properties_.disconnect_acl_link_error_count_.AttachInspect(
      inspect_node_, kInspectAclLinkErrorCountNodeName);
  inspect_properties_.disconnect_peer_disconnection_count_.AttachInspect(
      inspect_node_, kInspectPeerDisconnectionCountNodeName);
}

void BrEdrConnectionManager::WritePageTimeout(
    pw::chrono::SystemClock::duration page_timeout, hci::ResultFunction<> cb) {
  BT_ASSERT(page_timeout >= hci_spec::kMinPageTimeoutDuration);
  BT_ASSERT(page_timeout <= hci_spec::kMaxPageTimeoutDuration);

  const int64_t raw_page_timeout =
      page_timeout / hci_spec::kDurationPerPageTimeoutUnit;
  BT_ASSERT(raw_page_timeout >=
            static_cast<uint16_t>(pw::bluetooth::emboss::PageTimeout::MIN));
  BT_ASSERT(raw_page_timeout <=
            static_cast<uint16_t>(pw::bluetooth::emboss::PageTimeout::MAX));

  auto write_page_timeout_cmd = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::WritePageTimeoutCommandWriter>(
      hci_spec::kWritePageTimeout);
  auto params = write_page_timeout_cmd.view_t();
  params.page_timeout().Write(raw_page_timeout);

  hci_->command_channel()->SendCommand(
      std::move(write_page_timeout_cmd),
      [cb = std::move(cb)](auto id, const hci::EventPacket& event) {
        cb(event.ToResult());
      });
}

void BrEdrConnectionManager::WritePageScanSettings(uint16_t interval,
                                                   uint16_t window,
                                                   bool interlaced,
                                                   hci::ResultFunction<> cb) {
  auto self = weak_self_.GetWeakPtr();
  if (!hci_cmd_runner_->IsReady()) {
    // TODO(jamuraa): could run the three "settings" commands in parallel and
    // remove the sequence runner.
    cb(ToResult(HostError::kInProgress));
    return;
  }

  auto write_activity = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::WritePageScanActivityCommandWriter>(
      hci_spec::kWritePageScanActivity);
  auto activity_params = write_activity.view_t();
  activity_params.page_scan_interval().Write(interval);
  activity_params.page_scan_window().Write(window);

  hci_cmd_runner_->QueueCommand(
      std::move(write_activity),
      [self, interval, window](const hci::EventPacket& event) {
        if (!self.is_alive() ||
            hci_is_error(
                event, WARN, "gap-bredr", "write page scan activity failed")) {
          return;
        }

        self->page_scan_interval_ = interval;
        self->page_scan_window_ = window;

        bt_log(TRACE, "gap-bredr", "page scan activity updated");
      });

  const pw::bluetooth::emboss::PageScanType scan_type =
      interlaced ? pw::bluetooth::emboss::PageScanType::INTERLACED_SCAN
                 : pw::bluetooth::emboss::PageScanType::STANDARD_SCAN;

  auto write_type = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::WritePageScanTypeCommandWriter>(
      hci_spec::kWritePageScanType);
  auto type_params = write_type.view_t();
  type_params.page_scan_type().Write(scan_type);

  hci_cmd_runner_->QueueCommand(
      std::move(write_type), [self, scan_type](const hci::EventPacket& event) {
        if (!self.is_alive() ||
            hci_is_error(
                event, WARN, "gap-bredr", "write page scan type failed")) {
          return;
        }

        bt_log(TRACE, "gap-bredr", "page scan type updated");
        self->page_scan_type_ = scan_type;
      });

  hci_cmd_runner_->RunCommands(std::move(cb));
}

std::optional<std::pair<hci_spec::ConnectionHandle, BrEdrConnection*>>
BrEdrConnectionManager::FindConnectionById(PeerId peer_id) {
  auto it = std::find_if(
      connections_.begin(), connections_.end(), [peer_id](const auto& c) {
        return c.second.peer_id() == peer_id;
      });

  if (it == connections_.end()) {
    return std::nullopt;
  }

  auto& [handle, conn] = *it;
  return std::pair(handle, &conn);
}

std::optional<std::pair<hci_spec::ConnectionHandle, BrEdrConnection*>>
BrEdrConnectionManager::FindConnectionByAddress(
    const DeviceAddressBytes& bd_addr) {
  auto* const peer = cache_->FindByAddress(
      DeviceAddress(DeviceAddress::Type::kBREDR, bd_addr));
  if (!peer) {
    return std::nullopt;
  }

  return FindConnectionById(peer->identifier());
}

Peer* BrEdrConnectionManager::FindOrInitPeer(DeviceAddress addr) {
  Peer* peer = cache_->FindByAddress(addr);
  if (!peer) {
    peer = cache_->NewPeer(addr, /*connectable*/ true);
  }
  return peer;
}

// Build connection state for a new connection and begin interrogation. L2CAP is
// not enabled for this link but pairing is allowed before interrogation
// completes.
void BrEdrConnectionManager::InitializeConnection(
    DeviceAddress addr,
    hci_spec::ConnectionHandle connection_handle,
    pw::bluetooth::emboss::ConnectionRole role) {
  auto link = std::make_unique<hci::BrEdrConnection>(
      connection_handle, local_address_, addr, role, hci_);
  Peer* const peer = FindOrInitPeer(addr);
  auto peer_id = peer->identifier();
  bt_log(DEBUG,
         "gap-bredr",
         "Beginning interrogation for peer %s",
         bt_str(peer_id));

  // We should never have more than one link to a given peer
  BT_DEBUG_ASSERT(!FindConnectionById(peer_id));

  // The controller has completed the HCI connection procedure, so the
  // connection request can no longer be failed by a lower layer error. Now tie
  // error reporting of the request to the lifetime of the connection state
  // object (BrEdrConnection RAII).
  auto node = connection_requests_.extract(peer_id);
  auto request = node ? std::optional(std::move(node.mapped())) : std::nullopt;

  const hci_spec::ConnectionHandle handle = link->handle();
  auto send_auth_request_cb = [this, handle]() {
    this->SendAuthenticationRequested(handle, [handle](auto status) {
      bt_is_error(status,
                  WARN,
                  "gap-bredr",
                  "authentication requested command failed for %#.4x",
                  handle);
    });
  };
  auto disconnect_cb = [this, handle, peer_id] {
    bt_log(WARN,
           "gap-bredr",
           "Error occurred during pairing (handle %#.4x)",
           handle);
    Disconnect(peer_id, DisconnectReason::kPairingFailed);
  };
  auto on_peer_disconnect_cb = [this, link = link.get()] {
    OnPeerDisconnect(link);
  };
  auto [conn_iter, success] =
      connections_.try_emplace(handle,
                               peer->GetWeakPtr(),
                               std::move(link),
                               std::move(send_auth_request_cb),
                               std::move(disconnect_cb),
                               std::move(on_peer_disconnect_cb),
                               l2cap_,
                               hci_,
                               std::move(request),
                               dispatcher_);
  BT_ASSERT(success);

  BrEdrConnection& connection = conn_iter->second;
  connection.pairing_state().SetPairingDelegate(pairing_delegate_);
  connection.set_security_mode(security_mode());
  connection.AttachInspect(inspect_properties_.connections_node_,
                           inspect_properties_.connections_node_.UniqueName(
                               kInspectConnectionNodeNamePrefix));

  // Interrogate this peer to find out its version/capabilities.
  connection.Interrogate([this, peer = peer->GetWeakPtr(), handle](
                             hci::Result<> result) {
    if (bt_is_error(result,
                    WARN,
                    "gap-bredr",
                    "interrogation failed, dropping connection (peer: %s, "
                    "handle: %#.4x)",
                    bt_str(peer->identifier()),
                    handle)) {
      // If this connection was locally requested, requester(s) are notified by
      // the disconnection.
      Disconnect(peer->identifier(), DisconnectReason::kInterrogationFailed);
      return;
    }
    bt_log(INFO,
           "gap-bredr",
           "interrogation complete (peer: %s, handle: %#.4x)",
           bt_str(peer->identifier()),
           handle);
    CompleteConnectionSetup(peer, handle);
  });

  // If this was our in-flight request, close it
  if (pending_request_.has_value() &&
      addr == pending_request_->peer_address()) {
    pending_request_.reset();
  }

  TryCreateNextConnection();
}

// Finish connection setup after a successful interrogation.
void BrEdrConnectionManager::CompleteConnectionSetup(
    Peer::WeakPtr peer, hci_spec::ConnectionHandle handle) {
  auto self = weak_self_.GetWeakPtr();
  auto peer_id = peer->identifier();

  auto connections_iter = connections_.find(handle);
  if (connections_iter == connections_.end()) {
    bt_log(WARN,
           "gap-bredr",
           "Connection to complete not found (peer: %s, handle: %#.4x)",
           bt_str(peer_id),
           handle);
    return;
  }
  BrEdrConnection& conn_state = connections_iter->second;
  if (conn_state.peer_id() != peer->identifier()) {
    bt_log(WARN,
           "gap-bredr",
           "Connection switched peers! (now to %s), ignoring interrogation "
           "result (peer: %s, "
           "handle: %#.4x)",
           bt_str(conn_state.peer_id()),
           bt_str(peer_id),
           handle);
    return;
  }
  hci::BrEdrConnection* const connection = &conn_state.link();

  auto error_handler =
      [self, peer_id, connection = connection->GetWeakPtr(), handle] {
        if (!self.is_alive() || !connection.is_alive())
          return;
        bt_log(
            WARN,
            "gap-bredr",
            "Link error received, closing connection (peer: %s, handle: %#.4x)",
            bt_str(peer_id),
            handle);
        self->Disconnect(peer_id, DisconnectReason::kAclLinkError);
      };

  // TODO(https://fxbug.dev/42113313): Implement this callback as a call to
  // InitiatePairing().
  auto security_callback = [peer_id](hci_spec::ConnectionHandle handle,
                                     sm::SecurityLevel level,
                                     auto cb) {
    bt_log(INFO,
           "gap-bredr",
           "Ignoring security upgrade request; not implemented (peer: %s, "
           "handle: %#.4x)",
           bt_str(peer_id),
           handle);
    cb(ToResult(HostError::kNotSupported));
  };

  // Register with L2CAP to handle services on the ACL signaling channel.
  l2cap_->AddACLConnection(
      handle, connection->role(), error_handler, std::move(security_callback));

  // Remove from the denylist if we successfully connect.
  deny_incoming_.remove(peer->address());

  inspect_properties_.interrogation_complete_count_.Add(1);

  if (discoverer_.search_count()) {
    l2cap_->OpenL2capChannel(
        handle,
        l2cap::kSDP,
        l2cap::ChannelParameters(),
        [self, peer_id](auto channel) {
          if (!self.is_alive()) {
            return;
          }
          if (!channel.is_alive()) {
            bt_log(ERROR,
                   "gap",
                   "failed to create l2cap channel for SDP (peer: %s)",
                   bt_str(peer_id));
            return;
          }
          auto client =
              sdp::Client::Create(std::move(channel), self->dispatcher_);
          self->discoverer_.StartServiceDiscovery(peer_id, std::move(client));
        });
  }

  conn_state.OnInterrogationComplete();
}

hci::CommandChannel::EventCallbackResult
BrEdrConnectionManager::OnAuthenticationComplete(
    const hci::EmbossEventPacket& event) {
  BT_DEBUG_ASSERT(event.event_code() ==
                  hci_spec::kAuthenticationCompleteEventCode);
  auto params =
      event.view<pw::bluetooth::emboss::AuthenticationCompleteEventView>();
  hci_spec::ConnectionHandle connection_handle =
      params.connection_handle().Read();
  pw::bluetooth::emboss::StatusCode status = params.status().Read();

  auto iter = connections_.find(connection_handle);
  if (iter == connections_.end()) {
    bt_log(INFO,
           "gap-bredr",
           "ignoring authentication complete (status: %s) for unknown "
           "connection handle %#.04x",
           bt_str(ToResult(status)),
           connection_handle);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  iter->second.pairing_state().OnAuthenticationComplete(status);
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

bool BrEdrConnectionManager::ExistsIncomingRequest(PeerId id) {
  auto request = connection_requests_.find(id);
  return (request != connection_requests_.end() &&
          request->second.HasIncoming());
}

hci::CommandChannel::EventCallbackResult
BrEdrConnectionManager::OnConnectionRequest(
    const hci::EmbossEventPacket& event) {
  auto params = event.view<pw::bluetooth::emboss::ConnectionRequestEventView>();
  const DeviceAddress addr(DeviceAddress::Type::kBREDR,
                           DeviceAddressBytes(params.bd_addr()));
  const pw::bluetooth::emboss::LinkType link_type = params.link_type().Read();
  const DeviceClass device_class(
      params.class_of_device().BackingStorage().ReadUInt());

  if (link_type != pw::bluetooth::emboss::LinkType::ACL) {
    HandleNonAclConnectionRequest(addr, link_type);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  if (deny_incoming_.contains(addr)) {
    bt_log(INFO,
           "gap-bredr",
           "rejecting incoming from peer (addr: %s) on cooldown",
           bt_str(addr));
    SendRejectConnectionRequest(
        addr,
        pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_BAD_BD_ADDR);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  // Initialize the peer if it doesn't exist, to ensure we have allocated a
  // PeerId Do this after checking the denylist to avoid adding denied peers to
  // cache.
  auto peer = FindOrInitPeer(addr);
  auto peer_id = peer->identifier();

  // In case of concurrent incoming requests from the same peer, reject all but
  // the first
  if (ExistsIncomingRequest(peer_id)) {
    bt_log(WARN,
           "gap-bredr",
           "rejecting duplicate incoming connection request (peer: %s, addr: "
           "%s, link_type: %s, "
           "class: %s)",
           bt_str(peer_id),
           bt_str(addr),
           hci_spec::LinkTypeToString(params.link_type().Read()),
           bt_str(device_class));
    SendRejectConnectionRequest(
        addr,
        pw::bluetooth::emboss::StatusCode::CONNECTION_REJECTED_BAD_BD_ADDR);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  // If we happen to be already connected (for example, if our outgoing raced,
  // or we received duplicate requests), we reject the request with
  // 'ConnectionAlreadyExists'
  if (FindConnectionById(peer_id)) {
    bt_log(WARN,
           "gap-bredr",
           "rejecting incoming connection request; already connected (peer: "
           "%s, addr: %s)",
           bt_str(peer_id),
           bt_str(addr));
    SendRejectConnectionRequest(
        addr, pw::bluetooth::emboss::StatusCode::CONNECTION_ALREADY_EXISTS);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  // Accept the connection, performing a role switch. We receive a Connection
  // Complete event when the connection is complete, and finish the link then.
  bt_log(INFO,
         "gap-bredr",
         "accepting incoming connection (peer: %s, addr: %s, link_type: %s, "
         "class: %s)",
         bt_str(peer_id),
         bt_str(addr),
         hci_spec::LinkTypeToString(link_type),
         bt_str(device_class));

  // Register that we're in the middle of an incoming request for this peer -
  // create a new request if one doesn't already exist
  auto [request, _] = connection_requests_.try_emplace(
      peer_id,
      dispatcher_,
      addr,
      peer_id,
      peer->MutBrEdr().RegisterInitializingConnection());

  inspect_properties_.incoming_.connection_attempts_.Add(1);

  request->second.BeginIncoming();
  request->second.AttachInspect(inspect_properties_.requests_node_,
                                inspect_properties_.requests_node_.UniqueName(
                                    kInspectRequestNodeNamePrefix));

  SendAcceptConnectionRequest(
      addr.value(),
      [addr, self = weak_self_.GetWeakPtr(), peer_id](auto status) {
        if (self.is_alive() && status.is_error())
          self->CompleteRequest(peer_id, addr, status, /*handle=*/0);
      });
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult
BrEdrConnectionManager::OnConnectionComplete(
    const hci::EmbossEventPacket& event) {
  auto params =
      event.view<pw::bluetooth::emboss::ConnectionCompleteEventView>();
  if (params.link_type().Read() != pw::bluetooth::emboss::LinkType::ACL) {
    // Only ACL links are processed
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  // Initialize the peer if it doesn't exist, to ensure we have allocated a
  // PeerId (we should usually have a peer by this point)
  DeviceAddress addr(DeviceAddress::Type::kBREDR,
                     DeviceAddressBytes(params.bd_addr()));
  auto peer = FindOrInitPeer(addr);

  CompleteRequest(peer->identifier(),
                  addr,
                  event.ToResult(),
                  params.connection_handle().Read());
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

// A request for a connection - from an upstream client _or_ a remote peer -
// completed, successfully or not. This may be due to a ConnectionComplete event
// being received, or due to a CommandStatus response being received in response
// to a CreateConnection command
void BrEdrConnectionManager::CompleteRequest(
    PeerId peer_id,
    DeviceAddress address,
    hci::Result<> status,
    hci_spec::ConnectionHandle handle) {
  auto req_iter = connection_requests_.find(peer_id);
  if (req_iter == connection_requests_.end()) {
    // Prevent logspam for rejected during cooldown.
    if (deny_incoming_.contains(address)) {
      return;
    }
    // This could potentially happen if the peer expired from the peer cache
    // during the connection procedure
    bt_log(INFO,
           "gap-bredr",
           "ConnectionComplete received with no known request (status: %s, "
           "peer: %s, addr: %s, "
           "handle: %#.4x)",
           bt_str(status),
           bt_str(peer_id),
           bt_str(address),
           handle);
    return;
  }
  auto& request = req_iter->second;

  bool completes_outgoing_request = pending_request_.has_value() &&
                                    pending_request_->peer_address() == address;
  bool failed = status.is_error();

  const char* direction = completes_outgoing_request ? "outgoing" : "incoming";
  const char* result = status.is_ok() ? "complete" : "error";
  pw::bluetooth::emboss::ConnectionRole role =
      completes_outgoing_request
          ? pw::bluetooth::emboss::ConnectionRole::CENTRAL
          : pw::bluetooth::emboss::ConnectionRole::PERIPHERAL;
  if (request.role_change()) {
    role = request.role_change().value();
  }

  bt_log(INFO,
         "gap-bredr",
         "%s connection %s (status: %s, role: %s, peer: %s, addr: %s, handle: "
         "%#.4x)",
         direction,
         result,
         bt_str(status),
         role == pw::bluetooth::emboss::ConnectionRole::CENTRAL ? "central"
                                                                : "peripheral",
         bt_str(peer_id),
         bt_str(address),
         handle);

  if (completes_outgoing_request) {
    // Determine the modified status in case of cancellation or timeout
    status = pending_request_->CompleteRequest(status);
    pending_request_.reset();
  } else {
    // This incoming connection arrived while we're trying to make an outgoing
    // connection; not an impossible coincidence but log it in case it's
    // interesting.
    // TODO(https://fxbug.dev/42173957): Added to investigate timing and can be
    // removed if it adds no value
    if (pending_request_.has_value()) {
      bt_log(
          INFO,
          "gap-bredr",
          "doesn't complete pending outgoing connection to peer %s (addr: %s)",
          bt_str(pending_request_->peer_id()),
          bt_str(pending_request_->peer_address()));
    }
    // If this was an incoming attempt, clear it
    request.CompleteIncoming();
  }

  if (failed) {
    if (request.HasIncoming() ||
        (!completes_outgoing_request && request.AwaitingOutgoing())) {
      // This request failed, but we're still waiting on either:
      // * an in-progress incoming request or
      // * to attempt our own outgoing request
      // Therefore we don't notify yet - instead take no action, and wait until
      // we finish those steps before completing the request and notifying
      // callbacks
      TryCreateNextConnection();
      return;
    }
    if (completes_outgoing_request && connection_requests_.size() == 1 &&
        request.ShouldRetry(status.error_value())) {
      bt_log(INFO,
             "gap-bredr",
             "no pending connection requests to other peers, so %sretrying "
             "outbound connection (peer: "
             "%s, addr: %s)",
             request.HasIncoming()
                 ? "waiting for inbound request completion before potentially "
                 : "",
             bt_str(peer_id),
             bt_str(address));
      // By not erasing |request| from |connection_requests_|, even if
      // TryCreateNextConnection does not directly retry because there's an
      // inbound request to the same peer, the retry will happen if the inbound
      // request completes unusuccessfully.
      TryCreateNextConnection();
      return;
    }
    if (completes_outgoing_request) {
      inspect_properties_.outgoing_.failed_connections_.Add(1);
    } else if (request.HasIncoming()) {
      inspect_properties_.incoming_.failed_connections_.Add(1);
    }
    request.NotifyCallbacks(status, [] { return nullptr; });
    connection_requests_.erase(req_iter);
  } else {
    if (completes_outgoing_request) {
      inspect_properties_.outgoing_.successful_connections_.Add(1);
    } else if (request.HasIncoming()) {
      inspect_properties_.incoming_.successful_connections_.Add(1);
    }
    // Callbacks will be notified when interrogation completes
    InitializeConnection(address, handle, role);
  }

  TryCreateNextConnection();
}

void BrEdrConnectionManager::OnPeerDisconnect(
    const hci::Connection* connection) {
  auto handle = connection->handle();

  auto it = connections_.find(handle);
  if (it == connections_.end()) {
    bt_log(WARN,
           "gap-bredr",
           "disconnect from unknown connection handle %#.4x",
           handle);
    return;
  }

  auto conn = std::move(it->second);
  connections_.erase(it);

  bt_log(INFO,
         "gap-bredr",
         "peer disconnected (peer: %s, handle: %#.4x)",
         bt_str(conn.peer_id()),
         handle);
  CleanUpConnection(
      handle, std::move(conn), DisconnectReason::kPeerDisconnection);
}

void BrEdrConnectionManager::CleanUpConnection(
    hci_spec::ConnectionHandle handle,
    BrEdrConnection conn,
    DisconnectReason reason) {
  l2cap_->RemoveConnection(handle);
  RecordDisconnectInspect(conn, reason);
  // |conn| is destroyed when it goes out of scope.
}

hci::CommandChannel::EventCallbackResult
BrEdrConnectionManager::OnIoCapabilityRequest(
    const hci::EmbossEventPacket& event) {
  const auto params =
      event.view<pw::bluetooth::emboss::IoCapabilityRequestEventView>();
  const DeviceAddressBytes addr(params.bd_addr());

  auto conn_pair = FindConnectionByAddress(addr);
  if (!conn_pair) {
    bt_log(ERROR,
           "gap-bredr",
           "got %s for unconnected addr %s",
           __func__,
           bt_str(addr));
    SendIoCapabilityRequestNegativeReply(
        addr, pw::bluetooth::emboss::StatusCode::PAIRING_NOT_ALLOWED);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }
  auto [handle, conn_ptr] = *conn_pair;
  auto reply = conn_ptr->pairing_state().OnIoCapabilityRequest();

  if (!reply) {
    SendIoCapabilityRequestNegativeReply(
        addr, pw::bluetooth::emboss::StatusCode::PAIRING_NOT_ALLOWED);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  const pw::bluetooth::emboss::IoCapability io_capability = *reply;

  // TODO(https://fxbug.dev/42138242): Add OOB status from PeerCache.
  const pw::bluetooth::emboss::OobDataPresent oob_data_present =
      pw::bluetooth::emboss::OobDataPresent::NOT_PRESENT;

  // TODO(https://fxbug.dev/42075714): Determine this based on the service
  // requirements.
  const pw::bluetooth::emboss::AuthenticationRequirements auth_requirements =
      io_capability == pw::bluetooth::emboss::IoCapability::NO_INPUT_NO_OUTPUT
          ? pw::bluetooth::emboss::AuthenticationRequirements::GENERAL_BONDING
          : pw::bluetooth::emboss::AuthenticationRequirements::
                MITM_GENERAL_BONDING;

  SendIoCapabilityRequestReply(
      addr, io_capability, oob_data_present, auth_requirements);
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult
BrEdrConnectionManager::OnIoCapabilityResponse(
    const hci::EmbossEventPacket& event) {
  const auto params =
      event.view<pw::bluetooth::emboss::IoCapabilityResponseEventView>();
  const DeviceAddressBytes addr(params.bd_addr());

  auto conn_pair = FindConnectionByAddress(addr);
  if (!conn_pair) {
    bt_log(INFO,
           "gap-bredr",
           "got %s for unconnected addr %s",
           __func__,
           bt_str(addr));
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }
  conn_pair->second->pairing_state().OnIoCapabilityResponse(
      params.io_capability().Read());
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult
BrEdrConnectionManager::OnLinkKeyRequest(const hci::EmbossEventPacket& event) {
  const auto params =
      event.view<pw::bluetooth::emboss::LinkKeyRequestEventView>();
  const DeviceAddress addr(DeviceAddress::Type::kBREDR,
                           DeviceAddressBytes(params.bd_addr()));
  auto* peer = cache_->FindByAddress(addr);
  if (!peer) {
    bt_log(WARN, "gap-bredr", "no peer with address %s found", bt_str(addr));
    SendLinkKeyRequestNegativeReply(addr.value());
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  auto peer_id = peer->identifier();
  auto conn_pair = FindConnectionById(peer_id);

  if (!conn_pair) {
    bt_log(WARN,
           "gap-bredr",
           "can't find connection for ltk (id: %s)",
           bt_str(peer_id));
    SendLinkKeyRequestNegativeReply(addr.value());
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }
  auto& [handle, conn] = *conn_pair;

  auto link_key = conn->pairing_state().OnLinkKeyRequest();
  if (!link_key.has_value()) {
    SendLinkKeyRequestNegativeReply(addr.value());
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  SendLinkKeyRequestReply(addr.value(), link_key.value());
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult
BrEdrConnectionManager::OnLinkKeyNotification(
    const hci::EmbossEventPacket& event) {
  const auto params =
      event.view<pw::bluetooth::emboss::LinkKeyNotificationEventView>();

  const DeviceAddress addr(DeviceAddress::Type::kBREDR,
                           DeviceAddressBytes(params.bd_addr()));
  pw::bluetooth::emboss::KeyType key_type = params.key_type().Read();

  auto* peer = cache_->FindByAddress(addr);
  if (!peer) {
    bt_log(WARN,
           "gap-bredr",
           "no known peer with address %s found; link key not stored (key "
           "type: %u)",
           bt_str(addr),
           static_cast<uint8_t>(key_type));
    cache_->LogBrEdrBondingEvent(false);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  bt_log(INFO,
         "gap-bredr",
         "got link key notification (key type: %u, peer: %s)",
         static_cast<uint8_t>(key_type),
         bt_str(peer->identifier()));

  sm::SecurityProperties sec_props;
  if (key_type == pw::bluetooth::emboss::KeyType::CHANGED_COMBINATION_KEY) {
    if (!peer->bredr() || !peer->bredr()->bonded()) {
      bt_log(WARN,
             "gap-bredr",
             "can't update link key of unbonded peer %s",
             bt_str(peer->identifier()));
      cache_->LogBrEdrBondingEvent(false);
      return hci::CommandChannel::EventCallbackResult::kContinue;
    }

    // Reuse current properties
    BT_DEBUG_ASSERT(peer->bredr()->link_key());
    sec_props = peer->bredr()->link_key()->security();
    key_type = static_cast<pw::bluetooth::emboss::KeyType>(
        sec_props.GetLinkKeyType().value());
  } else {
    sec_props =
        sm::SecurityProperties(static_cast<hci_spec::LinkKeyType>(key_type));
  }

  auto peer_id = peer->identifier();

  if (sec_props.level() == sm::SecurityLevel::kNoSecurity) {
    bt_log(WARN,
           "gap-bredr",
           "link key for peer %s has insufficient security; not stored",
           bt_str(peer_id));
    cache_->LogBrEdrBondingEvent(false);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  UInt128 key_value;
  ::emboss::support::ReadWriteContiguousBuffer(&key_value)
      .CopyFrom(params.link_key().value().BackingStorage(), key_value.size());

  hci_spec::LinkKey hci_key(key_value, 0, 0);
  sm::LTK key(sec_props, hci_key);

  auto handle = FindConnectionById(peer_id);
  if (!handle) {
    bt_log(WARN,
           "gap-bredr",
           "can't find current connection for ltk (peer: %s)",
           bt_str(peer_id));
  } else {
    handle->second->link().set_link_key(
        hci_key, static_cast<hci_spec::LinkKeyType>(key_type));
    handle->second->pairing_state().OnLinkKeyNotification(
        key_value,
        static_cast<hci_spec::LinkKeyType>(key_type),
        local_secure_connections_supported_);
  }

  if (cache_->StoreBrEdrBond(addr, key)) {
    cache_->LogBrEdrBondingEvent(true);
  } else {
    cache_->LogBrEdrBondingEvent(false);
    bt_log(ERROR,
           "gap-bredr",
           "failed to cache bonding data (peer: %s)",
           bt_str(peer_id));
  }
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult
BrEdrConnectionManager::OnSimplePairingComplete(const hci::EventPacket& event) {
  BT_DEBUG_ASSERT(event.event_code() ==
                  hci_spec::kSimplePairingCompleteEventCode);
  const auto& params =
      event.params<hci_spec::SimplePairingCompleteEventParams>();

  auto conn_pair = FindConnectionByAddress(params.bd_addr);
  if (!conn_pair) {
    bt_log(WARN,
           "gap-bredr",
           "got Simple Pairing Complete (status: %s) for unconnected addr %s",
           bt_str(ToResult(params.status)),
           bt_str(params.bd_addr));
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }
  conn_pair->second->pairing_state().OnSimplePairingComplete(params.status);
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult
BrEdrConnectionManager::OnUserConfirmationRequest(
    const hci::EventPacket& event) {
  BT_DEBUG_ASSERT(event.event_code() ==
                  hci_spec::kUserConfirmationRequestEventCode);
  const auto& params =
      event.params<hci_spec::UserConfirmationRequestEventParams>();

  auto conn_pair = FindConnectionByAddress(params.bd_addr);
  if (!conn_pair) {
    bt_log(WARN,
           "gap-bredr",
           "got %s for unconnected addr %s",
           __func__,
           bt_str(params.bd_addr));
    SendUserConfirmationRequestNegativeReply(params.bd_addr);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  auto confirm_cb = [self = weak_self_.GetWeakPtr(),
                     bd_addr = params.bd_addr](bool confirm) {
    if (!self.is_alive()) {
      return;
    }

    if (confirm) {
      self->SendUserConfirmationRequestReply(bd_addr);
    } else {
      self->SendUserConfirmationRequestNegativeReply(bd_addr);
    }
  };
  conn_pair->second->pairing_state().OnUserConfirmationRequest(
      le32toh(params.numeric_value), std::move(confirm_cb));
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult
BrEdrConnectionManager::OnUserPasskeyRequest(const hci::EventPacket& event) {
  BT_DEBUG_ASSERT(event.event_code() == hci_spec::kUserPasskeyRequestEventCode);
  const auto& params = event.params<hci_spec::UserPasskeyRequestEventParams>();

  auto conn_pair = FindConnectionByAddress(params.bd_addr);
  if (!conn_pair) {
    bt_log(WARN,
           "gap-bredr",
           "got %s for unconnected addr %s",
           __func__,
           bt_str(params.bd_addr));
    SendUserPasskeyRequestNegativeReply(params.bd_addr);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  auto passkey_cb = [self = weak_self_.GetWeakPtr(), bd_addr = params.bd_addr](
                        std::optional<uint32_t> passkey) {
    if (!self.is_alive()) {
      return;
    }

    if (passkey) {
      self->SendUserPasskeyRequestReply(bd_addr, *passkey);
    } else {
      self->SendUserPasskeyRequestNegativeReply(bd_addr);
    }
  };
  conn_pair->second->pairing_state().OnUserPasskeyRequest(
      std::move(passkey_cb));
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult
BrEdrConnectionManager::OnUserPasskeyNotification(
    const hci::EventPacket& event) {
  BT_DEBUG_ASSERT(event.event_code() ==
                  hci_spec::kUserPasskeyNotificationEventCode);
  const auto& params =
      event.params<hci_spec::UserPasskeyNotificationEventParams>();

  auto conn_pair = FindConnectionByAddress(params.bd_addr);
  if (!conn_pair) {
    bt_log(WARN,
           "gap-bredr",
           "got %s for unconnected addr %s",
           __func__,
           bt_str(params.bd_addr));
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }
  conn_pair->second->pairing_state().OnUserPasskeyNotification(
      le32toh(params.numeric_value));
  return hci::CommandChannel::EventCallbackResult::kContinue;
}

hci::CommandChannel::EventCallbackResult BrEdrConnectionManager::OnRoleChange(
    const hci::EmbossEventPacket& event) {
  const auto params = event.view<pw::bluetooth::emboss::RoleChangeEventView>();
  const DeviceAddress address(DeviceAddress::Type::kBREDR,
                              DeviceAddressBytes(params.bd_addr()));
  Peer* peer = cache_->FindByAddress(address);
  if (!peer) {
    bt_log(WARN,
           "gap-bredr",
           "got %s for unknown peer (address: %s)",
           __func__,
           bt_str(address));
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }
  PeerId peer_id = peer->identifier();

  const pw::bluetooth::emboss::ConnectionRole new_role = params.role().Read();

  // When a role change is requested in the HCI_Accept_Connection_Request
  // command, a HCI_Role_Change event may be received prior to the
  // HCI_Connection_Complete event (so no connection object will exist yet)
  // (Core Spec v5.2, Vol 2, Part F, Sec 3.1).
  auto request_iter = connection_requests_.find(peer_id);
  if (request_iter != connection_requests_.end()) {
    request_iter->second.set_role_change(new_role);
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  auto conn_pair = FindConnectionByAddress(address.value());
  if (!conn_pair) {
    bt_log(WARN,
           "gap-bredr",
           "got %s for unconnected peer %s",
           __func__,
           bt_str(peer_id));
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  if (hci_is_error(event,
                   WARN,
                   "gap-bredr",
                   "role change failed and remains %s (peer: %s)",
                   hci_spec::ConnectionRoleToString(new_role).c_str(),
                   bt_str(peer_id))) {
    return hci::CommandChannel::EventCallbackResult::kContinue;
  }

  bt_log(DEBUG,
         "gap-bredr",
         "role changed to %s (peer: %s)",
         hci_spec::ConnectionRoleToString(new_role).c_str(),
         bt_str(peer_id));
  conn_pair->second->link().set_role(new_role);

  return hci::CommandChannel::EventCallbackResult::kContinue;
}

void BrEdrConnectionManager::HandleNonAclConnectionRequest(
    const DeviceAddress& addr, pw::bluetooth::emboss::LinkType link_type) {
  BT_DEBUG_ASSERT(link_type != pw::bluetooth::emboss::LinkType::ACL);

  // Initialize the peer if it doesn't exist, to ensure we have allocated a
  // PeerId
  auto peer = FindOrInitPeer(addr);
  auto peer_id = peer->identifier();

  if (link_type != pw::bluetooth::emboss::LinkType::SCO &&
      link_type != pw::bluetooth::emboss::LinkType::ESCO) {
    bt_log(WARN,
           "gap-bredr",
           "reject unsupported connection type %s (peer: %s, addr: %s)",
           hci_spec::LinkTypeToString(link_type),
           bt_str(peer_id),
           bt_str(addr));
    SendRejectConnectionRequest(
        addr,
        pw::bluetooth::emboss::StatusCode::UNSUPPORTED_FEATURE_OR_PARAMETER);
    return;
  }

  auto conn_pair = FindConnectionByAddress(addr.value());
  if (!conn_pair) {
    bt_log(WARN,
           "gap-bredr",
           "rejecting (e)SCO connection request for peer that is not connected "
           "(peer: %s, addr: %s)",
           bt_str(peer_id),
           bt_str(addr));
    SendRejectSynchronousRequest(
        addr,
        pw::bluetooth::emboss::StatusCode::UNACCEPTABLE_CONNECTION_PARAMETERS);
    return;
  }

  // The ScoConnectionManager owned by the BrEdrConnection will respond.
  bt_log(DEBUG,
         "gap-bredr",
         "SCO request ignored, handled by ScoConnectionManager (peer: %s, "
         "addr: %s)",
         bt_str(peer_id),
         bt_str(addr));
}

bool BrEdrConnectionManager::Connect(
    PeerId peer_id, ConnectResultCallback on_connection_result) {
  Peer* peer = cache_->FindById(peer_id);
  if (!peer) {
    bt_log(WARN,
           "gap-bredr",
           "%s: peer not found (peer: %s)",
           __func__,
           bt_str(peer_id));
    return false;
  }

  if (peer->technology() == TechnologyType::kLowEnergy) {
    bt_log(
        ERROR, "gap-bredr", "peer does not support BrEdr: %s", bt_str(*peer));
    return false;
  }

  // Succeed immediately or after interrogation if there is already an active
  // connection.
  auto conn = FindConnectionById(peer_id);
  if (conn) {
    conn->second->AddRequestCallback(std::move(on_connection_result));
    return true;
  }

  // Actively trying to connect to this peer means we can remove it from the
  // denylist.
  deny_incoming_.remove(peer->address());

  // If we are already waiting to connect to |peer_id| then we store
  // |on_connection_result| to be processed after the connection attempt
  // completes (in either success of failure).
  auto pending_iter = connection_requests_.find(peer_id);
  if (pending_iter != connection_requests_.end()) {
    pending_iter->second.AddCallback(std::move(on_connection_result));
    return true;
  }
  // If we are not already connected or pending, initiate a new connection
  auto [request_iter, _] = connection_requests_.try_emplace(
      peer_id,
      dispatcher_,
      peer->address(),
      peer_id,
      peer->MutBrEdr().RegisterInitializingConnection(),
      std::move(on_connection_result));
  request_iter->second.AttachInspect(
      inspect_properties_.requests_node_,
      inspect_properties_.requests_node_.UniqueName(
          kInspectRequestNodeNamePrefix));

  TryCreateNextConnection();

  return true;
}

std::optional<BrEdrConnectionManager::CreateConnectionParams>
BrEdrConnectionManager::NextCreateConnectionParams() {
  for (auto& [peer_id, request] : connection_requests_) {
    // The peer should still be in PeerCache because it was marked
    // "initializing" when the connection was requested.
    const Peer* peer = cache_->FindById(peer_id);
    BT_ASSERT(peer);
    if (peer->bredr() && !request.HasIncoming()) {
      return std::optional(
          CreateConnectionParams{peer->identifier(),
                                 request.address(),
                                 peer->bredr()->clock_offset(),
                                 peer->bredr()->page_scan_repetition_mode()});
    }
  }

  bt_log(
      TRACE, "gap-bredr", "no pending outbound connection requests remaining");
  return std::nullopt;
}

void BrEdrConnectionManager::TryCreateNextConnection() {
  // There can only be one outstanding BrEdr CreateConnection request at a time
  if (pending_request_) {
    return;
  }

  auto next = NextCreateConnectionParams();
  if (next) {
    InitiatePendingConnection(*next);
  }
}

void BrEdrConnectionManager::InitiatePendingConnection(
    CreateConnectionParams params) {
  auto self = weak_self_.GetWeakPtr();
  auto on_failure = [self, addr = params.addr](hci::Result<> status,
                                               auto peer_id) {
    if (self.is_alive() && status.is_error())
      self->CompleteRequest(peer_id, addr, status, /*handle=*/0);
  };
  auto on_timeout = [self] {
    if (self.is_alive())
      self->OnRequestTimeout();
  };
  BrEdrConnectionRequest& pending_gap_req =
      connection_requests_.find(params.peer_id)->second;
  pending_request_.emplace(
      params.peer_id, params.addr, on_timeout, dispatcher_);
  pending_request_->CreateConnection(hci_->command_channel(),
                                     params.clock_offset,
                                     params.page_scan_repetition_mode,
                                     request_timeout_,
                                     on_failure);
  pending_gap_req.RecordHciCreateConnectionAttempt();

  inspect_properties_.outgoing_.connection_attempts_.Add(1);
}

void BrEdrConnectionManager::OnRequestTimeout() {
  if (pending_request_) {
    pending_request_->Timeout();
    SendCreateConnectionCancelCommand(pending_request_->peer_address());
  }
}

void BrEdrConnectionManager::SendCreateConnectionCancelCommand(
    DeviceAddress addr) {
  auto cancel = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::CreateConnectionCancelCommandWriter>(
      hci_spec::kCreateConnectionCancel);
  auto params = cancel.view_t();
  params.bd_addr().CopyFrom(addr.value().view());
  hci_->command_channel()->SendCommand(
      std::move(cancel), [](auto, const hci::EventPacket& event) {
        hci_is_error(
            event, WARN, "hci-bredr", "failed to cancel connection request");
      });
}

void BrEdrConnectionManager::SendAuthenticationRequested(
    hci_spec::ConnectionHandle handle, hci::ResultFunction<> cb) {
  auto auth_request = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::AuthenticationRequestedCommandWriter>(
      hci_spec::kAuthenticationRequested);
  auth_request.view_t().connection_handle().Write(handle);

  // Complete on command status because Authentication Complete Event is already
  // registered.
  hci::CommandChannel::CommandCallback command_cb;
  if (cb) {
    command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
      cb(event.ToResult());
    };
  }
  hci_->command_channel()->SendCommand(std::move(auth_request),
                                       std::move(command_cb),
                                       hci_spec::kCommandStatusEventCode);
}

void BrEdrConnectionManager::SendIoCapabilityRequestReply(
    DeviceAddressBytes bd_addr,
    pw::bluetooth::emboss::IoCapability io_capability,
    pw::bluetooth::emboss::OobDataPresent oob_data_present,
    pw::bluetooth::emboss::AuthenticationRequirements auth_requirements,
    hci::ResultFunction<> cb) {
  auto packet = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::IoCapabilityRequestReplyCommandWriter>(
      hci_spec::kIOCapabilityRequestReply);
  auto params = packet.view_t();
  params.bd_addr().CopyFrom(bd_addr.view());
  params.io_capability().Write(io_capability);
  params.oob_data_present().Write(oob_data_present);
  params.authentication_requirements().Write(auth_requirements);
  SendCommandWithStatusCallback(std::move(packet), std::move(cb));
}

void BrEdrConnectionManager::SendIoCapabilityRequestNegativeReply(
    DeviceAddressBytes bd_addr,
    pw::bluetooth::emboss::StatusCode reason,
    hci::ResultFunction<> cb) {
  auto packet = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::IoCapabilityRequestNegativeReplyCommandWriter>(
      hci_spec::kIOCapabilityRequestNegativeReply);
  auto params = packet.view_t();
  params.bd_addr().CopyFrom(bd_addr.view());
  params.reason().Write(reason);
  SendCommandWithStatusCallback(std::move(packet), std::move(cb));
}

void BrEdrConnectionManager::SendUserConfirmationRequestReply(
    DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
  auto packet = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::UserConfirmationRequestReplyCommandWriter>(
      hci_spec::kUserConfirmationRequestReply);
  packet.view_t().bd_addr().CopyFrom(bd_addr.view());
  SendCommandWithStatusCallback(std::move(packet), std::move(cb));
}

void BrEdrConnectionManager::SendUserConfirmationRequestNegativeReply(
    DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
  auto packet = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::UserConfirmationRequestNegativeReplyCommandWriter>(
      hci_spec::kUserConfirmationRequestNegativeReply);
  packet.view_t().bd_addr().CopyFrom(bd_addr.view());
  SendCommandWithStatusCallback(std::move(packet), std::move(cb));
}

void BrEdrConnectionManager::SendUserPasskeyRequestReply(
    DeviceAddressBytes bd_addr,
    uint32_t numeric_value,
    hci::ResultFunction<> cb) {
  auto packet = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::UserPasskeyRequestReplyCommandWriter>(
      hci_spec::kUserPasskeyRequestReply);
  auto view = packet.view_t();
  view.bd_addr().CopyFrom(bd_addr.view());
  view.numeric_value().Write(numeric_value);
  SendCommandWithStatusCallback(std::move(packet), std::move(cb));
}

void BrEdrConnectionManager::SendUserPasskeyRequestNegativeReply(
    DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
  auto packet = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::UserPasskeyRequestNegativeReplyCommandWriter>(
      hci_spec::kUserPasskeyRequestNegativeReply);
  packet.view_t().bd_addr().CopyFrom(bd_addr.view());
  SendCommandWithStatusCallback(std::move(packet), std::move(cb));
}

void BrEdrConnectionManager::SendLinkKeyRequestNegativeReply(
    DeviceAddressBytes bd_addr, hci::ResultFunction<> cb) {
  auto negative_reply = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::LinkKeyRequestNegativeReplyCommandWriter>(
      hci_spec::kLinkKeyRequestNegativeReply);
  auto negative_reply_params = negative_reply.view_t();
  negative_reply_params.bd_addr().CopyFrom(bd_addr.view());
  SendCommandWithStatusCallback(std::move(negative_reply), std::move(cb));
}

void BrEdrConnectionManager::SendLinkKeyRequestReply(DeviceAddressBytes bd_addr,
                                                     hci_spec::LinkKey link_key,
                                                     hci::ResultFunction<> cb) {
  auto reply = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::LinkKeyRequestReplyCommandWriter>(
      hci_spec::kLinkKeyRequestReply);
  auto reply_params = reply.view_t();
  reply_params.bd_addr().CopyFrom(bd_addr.view());

  auto link_key_value_view = link_key.view();
  reply_params.link_key().CopyFrom(link_key_value_view);

  SendCommandWithStatusCallback(std::move(reply), std::move(cb));
}

template <typename T>
void BrEdrConnectionManager::SendCommandWithStatusCallback(
    T command_packet, hci::ResultFunction<> cb) {
  hci::CommandChannel::CommandCallback command_cb;
  if (cb) {
    command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
      cb(event.ToResult());
    };
  }
  hci_->command_channel()->SendCommand(std::move(command_packet),
                                       std::move(command_cb));
}

void BrEdrConnectionManager::SendAcceptConnectionRequest(
    DeviceAddressBytes addr, hci::ResultFunction<> cb) {
  auto accept = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::AcceptConnectionRequestCommandWriter>(
      hci_spec::kAcceptConnectionRequest);
  auto accept_params = accept.view_t();
  accept_params.bd_addr().CopyFrom(addr.view());
  // This role switch preference can fail. A HCI_Role_Change event will be
  // generated if the role switch is successful (Core Spec v5.2, Vol 2, Part F,
  // Sec 3.1).
  accept_params.role().Write(pw::bluetooth::emboss::ConnectionRole::CENTRAL);

  hci::CommandChannel::CommandCallback command_cb;
  if (cb) {
    command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
      cb(event.ToResult());
    };
  }

  hci_->command_channel()->SendCommand(std::move(accept),
                                       std::move(command_cb),
                                       hci_spec::kCommandStatusEventCode);
}

void BrEdrConnectionManager::SendRejectConnectionRequest(
    DeviceAddress addr,
    pw::bluetooth::emboss::StatusCode reason,
    hci::ResultFunction<> cb) {
  auto reject = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::RejectConnectionRequestCommandWriter>(
      hci_spec::kRejectConnectionRequest);
  auto reject_params = reject.view_t();
  reject_params.bd_addr().CopyFrom(addr.value().view());
  reject_params.reason().Write(reason);

  hci::CommandChannel::CommandCallback command_cb;
  if (cb) {
    command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
      cb(event.ToResult());
    };
  }

  hci_->command_channel()->SendCommand(std::move(reject),
                                       std::move(command_cb),
                                       hci_spec::kCommandStatusEventCode);
}

void BrEdrConnectionManager::SendRejectSynchronousRequest(
    DeviceAddress addr,
    pw::bluetooth::emboss::StatusCode reason,
    hci::ResultFunction<> cb) {
  auto reject = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::RejectSynchronousConnectionRequestCommandWriter>(
      hci_spec::kRejectSynchronousConnectionRequest);
  auto reject_params = reject.view_t();
  reject_params.bd_addr().CopyFrom(addr.value().view());
  reject_params.reason().Write(reason);

  hci::CommandChannel::CommandCallback command_cb;
  if (cb) {
    command_cb = [cb = std::move(cb)](auto, const hci::EventPacket& event) {
      cb(event.ToResult());
    };
  }

  hci_->command_channel()->SendCommand(std::move(reject),
                                       std::move(command_cb),
                                       hci_spec::kCommandStatusEventCode);
}

void BrEdrConnectionManager::RecordDisconnectInspect(
    const BrEdrConnection& conn, DisconnectReason reason) {
  // Add item to recent disconnections list.
  auto& inspect_item = inspect_properties_.last_disconnected_list.CreateItem();
  inspect_item.node.RecordString(kInspectLastDisconnectedItemPeerPropertyName,
                                 conn.peer_id().ToString());
  uint64_t conn_duration_s =
      std::chrono::duration_cast<std::chrono::seconds>(conn.duration()).count();
  inspect_item.node.RecordUint(kInspectLastDisconnectedItemDurationPropertyName,
                               conn_duration_s);

  int64_t time_ns = dispatcher_.now().time_since_epoch().count();
  inspect_item.node.RecordInt(kInspectTimestampPropertyName, time_ns);

  switch (reason) {
    case DisconnectReason::kApiRequest:
      inspect_properties_.disconnect_local_api_request_count_.Add(1);
      break;
    case DisconnectReason::kInterrogationFailed:
      inspect_properties_.disconnect_interrogation_failed_count_.Add(1);
      break;
    case DisconnectReason::kPairingFailed:
      inspect_properties_.disconnect_pairing_failed_count_.Add(1);
      break;
    case DisconnectReason::kAclLinkError:
      inspect_properties_.disconnect_acl_link_error_count_.Add(1);
      break;
    case DisconnectReason::kPeerDisconnection:
      inspect_properties_.disconnect_peer_disconnection_count_.Add(1);
      break;
    default:
      break;
  }
}

}  // namespace bt::gap
