// Copyright 2017 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 "adapter.h"

#include <endian.h>
#include <lib/fit/thread_checker.h>

#include "bredr_connection_manager.h"
#include "bredr_discovery_manager.h"
#include "low_energy_address_manager.h"
#include "low_energy_advertising_manager.h"
#include "low_energy_connection_manager.h"
#include "low_energy_discovery_manager.h"
#include "peer.h"
#include "src/connectivity/bluetooth/core/bt-host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/common/metrics.h"
#include "src/connectivity/bluetooth/core/bt-host/common/random.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/util.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/connection.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/legacy_low_energy_advertiser.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/legacy_low_energy_scanner.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/low_energy_connector.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/sequential_command_runner.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/transport.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/channel_manager.h"

namespace bt::gap {

const char* const kInspectLowEnergyDiscoveryManagerNodeName = "low_energy_discovery_manager";
const char* const kInspectBrEdrConnectionManagerNodeName = "bredr_connection_manager";

// All asynchronous callbacks are posted on the Loop on which this Adapter
// instance is created.
class AdapterImpl final : public Adapter {
 public:
  // There must be an async_t dispatcher registered as a default when an AdapterImpl
  // instance is created. The Adapter instance will use it for all of its
  // asynchronous tasks.
  explicit AdapterImpl(fxl::WeakPtr<hci::Transport> hci, fxl::WeakPtr<gatt::GATT> gatt,
                       std::optional<fbl::RefPtr<l2cap::L2cap>> l2cap);
  ~AdapterImpl() override;

  AdapterId identifier() const override { return identifier_; }

  bool Initialize(InitializeCallback callback, fit::closure transport_closed_callback) override;

  void ShutDown() override;

  bool IsInitializing() const override { return init_state_ == State::kInitializing; }

  bool IsInitialized() const override { return init_state_ == State::kInitialized; }

  const AdapterState& state() const override { return state_; }

  class LowEnergyImpl final : public LowEnergy {
   public:
    explicit LowEnergyImpl(AdapterImpl* adapter) : adapter_(adapter) {}

    void Connect(PeerId peer_id, ConnectionResultCallback callback,
                 LowEnergyConnectionOptions connection_options) override {
      adapter_->le_connection_manager_->Connect(peer_id, std::move(callback),
                                                std::move(connection_options));
      adapter_->metrics_.le.outgoing_connection_requests.Add();
    }

    bool Disconnect(PeerId peer_id) override {
      return adapter_->le_connection_manager_->Disconnect(peer_id);
    }

    void RegisterRemoteInitiatedLink(hci::ConnectionPtr link, sm::BondableMode bondable_mode,
                                     ConnectionResultCallback callback) override {
      adapter_->le_connection_manager_->RegisterRemoteInitiatedLink(std::move(link), bondable_mode,
                                                                    std::move(callback));
    }

    void Pair(PeerId peer_id, sm::SecurityLevel pairing_level, sm::BondableMode bondable_mode,
              sm::StatusCallback cb) override {
      adapter_->le_connection_manager_->Pair(peer_id, pairing_level, bondable_mode, std::move(cb));
      adapter_->metrics_.le.pair_requests.Add();
    }

    void SetSecurityMode(LeSecurityMode mode) override {
      adapter_->le_connection_manager_->SetSecurityMode(mode);
    }

    LeSecurityMode security_mode() const override {
      return adapter_->le_connection_manager_->security_mode();
    }

    void StartAdvertising(AdvertisingData data, AdvertisingData scan_rsp,
                          ConnectionCallback connect_callback, AdvertisingInterval interval,
                          bool anonymous, bool include_tx_power_level,
                          AdvertisingStatusCallback status_callback) override {
      adapter_->le_advertising_manager_->StartAdvertising(
          std::move(data), std::move(scan_rsp), std::move(connect_callback), interval, anonymous,
          include_tx_power_level, std::move(status_callback));
      adapter_->metrics_.le.start_advertising_events.Add();
    }

    void StopAdvertising(AdvertisementId advertisement_id) override {
      adapter_->le_advertising_manager_->StopAdvertising(advertisement_id);
      adapter_->metrics_.le.stop_advertising_events.Add();
    }

    void StartDiscovery(bool active, SessionCallback callback) override {
      adapter_->le_discovery_manager_->StartDiscovery(active, std::move(callback));
      adapter_->metrics_.le.start_discovery_events.Add();
    }

    void EnablePrivacy(bool enabled) override {
      adapter_->le_address_manager_->EnablePrivacy(enabled);
    }

    void set_irk(const std::optional<UInt128>& irk) override {
      adapter_->le_address_manager_->set_irk(irk);
    }

    std::optional<UInt128> irk() const override { return adapter_->le_address_manager_->irk(); }

    void set_request_timeout_for_testing(zx::duration value) override {
      adapter_->le_connection_manager_->set_request_timeout_for_testing(value);
    }

    void set_scan_period_for_testing(zx::duration period) override {
      adapter_->le_discovery_manager_->set_scan_period(period);
    }

   private:
    AdapterImpl* adapter_;
  };

  LowEnergy* le() const override { return low_energy_.get(); }

  class BrEdrImpl final : public BrEdr {
   public:
    explicit BrEdrImpl(AdapterImpl* adapter) : adapter_(adapter) {}

    bool Connect(PeerId peer_id, ConnectResultCallback callback) override {
      return adapter_->bredr_connection_manager_->Connect(peer_id, std::move(callback));
      adapter_->metrics_.bredr.outgoing_connection_requests.Add();
    }

    bool Disconnect(PeerId peer_id, DisconnectReason reason) override {
      return adapter_->bredr_connection_manager_->Disconnect(peer_id, reason);
    }

    void OpenL2capChannel(PeerId peer_id, l2cap::PSM psm,
                          BrEdrSecurityRequirements security_requirements,
                          l2cap::ChannelParameters params, l2cap::ChannelCallback cb) override {
      adapter_->metrics_.bredr.open_l2cap_channel_requests.Add();
      adapter_->bredr_connection_manager_->OpenL2capChannel(peer_id, psm, security_requirements,
                                                            params, std::move(cb));
    }

    PeerId GetPeerId(hci::ConnectionHandle handle) const override {
      return adapter_->bredr_connection_manager_->GetPeerId(handle);
    }

    SearchId AddServiceSearch(const UUID& uuid, std::unordered_set<sdp::AttributeId> attributes,
                              SearchCallback callback) override {
      return adapter_->bredr_connection_manager_->AddServiceSearch(uuid, std::move(attributes),
                                                                   std::move(callback));
    }

    bool RemoveServiceSearch(SearchId id) override {
      return adapter_->bredr_connection_manager_->RemoveServiceSearch(id);
    }

    void Pair(PeerId peer_id, BrEdrSecurityRequirements security,
              hci::StatusCallback callback) override {
      adapter_->bredr_connection_manager_->Pair(peer_id, security, std::move(callback));
      adapter_->metrics_.bredr.pair_requests.Add();
    }

    void SetConnectable(bool connectable, hci::StatusCallback status_cb) override {
      adapter_->bredr_connection_manager_->SetConnectable(connectable, std::move(status_cb));
      if (connectable) {
        adapter_->metrics_.bredr.set_connectable_true_events.Add();
      } else {
        adapter_->metrics_.bredr.set_connectable_false_events.Add();
      }
    }

    void RequestDiscovery(DiscoveryCallback callback) override {
      adapter_->bredr_discovery_manager_->RequestDiscovery(std::move(callback));
      adapter_->metrics_.bredr.request_discovery_events.Add();
    }

    void RequestDiscoverable(DiscoverableCallback callback) override {
      adapter_->bredr_discovery_manager_->RequestDiscoverable(std::move(callback));
      adapter_->metrics_.bredr.request_discoverable_events.Add();
    }

    RegistrationHandle RegisterService(std::vector<sdp::ServiceRecord> records,
                                       l2cap::ChannelParameters chan_params,
                                       ServiceConnectCallback conn_cb) override {
      return adapter_->sdp_server_->RegisterService(std::move(records), chan_params,
                                                    std::move(conn_cb));
    }

    bool UnregisterService(RegistrationHandle handle) override {
      return adapter_->sdp_server_->UnregisterService(handle);
    }

    std::optional<ScoRequestHandle> OpenScoConnection(
        PeerId peer_id, bool initiator, hci::SynchronousConnectionParameters parameters,
        ScoConnectionCallback callback) override {
      return adapter_->bredr_connection_manager_->OpenScoConnection(peer_id, initiator, parameters,
                                                                    std::move(callback));
    }

   private:
    AdapterImpl* adapter_;
  };

  BrEdr* bredr() const override { return bredr_.get(); }

  PeerCache* peer_cache() override { return &peer_cache_; }

  bool AddBondedPeer(BondingData bonding_data) override;

  void SetPairingDelegate(fxl::WeakPtr<PairingDelegate> delegate) override;

  bool IsDiscoverable() const override;

  bool IsDiscovering() const override;

  void SetLocalName(std::string name, hci::StatusCallback callback) override;

  std::string local_name() const override { return bredr_discovery_manager_->local_name(); }

  void SetDeviceClass(DeviceClass dev_class, hci::StatusCallback callback) override;

  void set_auto_connect_callback(AutoConnectCallback callback) override {
    auto_conn_cb_ = std::move(callback);
  }

  void AttachInspect(inspect::Node& parent, std::string name) override;

  fxl::WeakPtr<Adapter> AsWeakPtr() override { return weak_ptr_factory_.GetWeakPtr(); }

 private:
  // Second step of the initialization sequence. Called by Initialize() when the
  // first batch of HCI commands have been sent.
  void InitializeStep2(InitializeCallback callback);

  // Third step of the initialization sequence. Called by InitializeStep2() when
  // the second batch of HCI commands have been sent.
  void InitializeStep3(InitializeCallback callback);

  // Fourth step of the initialization sequence. Called by InitializeStep3()
  // when the third batch of HCI commands have been sent.
  void InitializeStep4(InitializeCallback callback);

  // Assigns properties to |adapter_node_| using values discovered during other initialization
  // steps.
  void UpdateInspectProperties();

  // Builds and returns the HCI event mask based on our supported host side
  // features and controller capabilities. This is used to mask events that we
  // do not know how to handle.
  uint64_t BuildEventMask();

  // Builds and returns the LE event mask based on our supported host side
  // features and controller capabilities. This is used to mask LE events that
  // we do not know how to handle.
  uint64_t BuildLEEventMask();

  // Called by ShutDown() and during Initialize() in case of failure. This
  // synchronously cleans up the transports and resets initialization state.
  void CleanUp();

  // Called by Transport after it has been unexpectedly closed.
  void OnTransportClosed();

  // Called when a directed connectable advertisement is received from a bonded
  // LE device. This amounts to a connection request from a bonded peripheral
  // which is handled by routing the request to |le_connection_manager_| to
  // initiate a Direct Connection Establishment procedure (Vol 3, Part C,
  // 9.3.8).
  void OnLeAutoConnectRequest(Peer* peer);

  // Called by |le_address_manager_| to query whether it is currently allowed to
  // reconfigure the LE random address.
  bool IsLeRandomAddressChangeAllowed();

  // Must be initialized first so that child nodes can be passed to other constructors.
  inspect::Node adapter_node_;
  struct InspectProperties {
    inspect::StringProperty adapter_id;
    inspect::StringProperty hci_version;
    inspect::UintProperty bredr_max_num_packets;
    inspect::UintProperty bredr_max_data_length;
    inspect::UintProperty le_max_num_packets;
    inspect::UintProperty le_max_data_length;
    inspect::StringProperty lmp_features;
    inspect::StringProperty le_features;
  };
  InspectProperties inspect_properties_;

  // Metrics properties
  inspect::Node metrics_node_;
  inspect::Node metrics_bredr_node_;
  inspect::Node metrics_le_node_;
  struct AdapterMetrics {
    struct LeMetrics {
      UintMetricCounter outgoing_connection_requests;
      UintMetricCounter pair_requests;
      UintMetricCounter start_advertising_events;
      UintMetricCounter stop_advertising_events;
      UintMetricCounter start_discovery_events;
    } le;
    struct BrEdrMetrics {
      UintMetricCounter outgoing_connection_requests;
      UintMetricCounter pair_requests;
      UintMetricCounter set_connectable_true_events;
      UintMetricCounter set_connectable_false_events;
      UintMetricCounter request_discovery_events;
      UintMetricCounter request_discoverable_events;
      UintMetricCounter open_l2cap_channel_requests;
    } bredr;
  };
  AdapterMetrics metrics_;

  // Uniquely identifies this adapter on the current system.
  AdapterId identifier_;

  async_dispatcher_t* dispatcher_;
  fxl::WeakPtr<hci::Transport> hci_;

  // Callback invoked to notify clients when the underlying transport is closed.
  fit::closure transport_closed_cb_;

  // Parameters relevant to the initialization sequence.
  // TODO(armansito): The Initialize()/ShutDown() pattern has become common
  // enough in this project that it might be worth considering moving the
  // init-state-keeping into an abstract base.
  enum State {
    kNotInitialized = 0,
    kInitializing,
    kInitialized,
  };
  std::atomic<State> init_state_;
  std::unique_ptr<hci::SequentialCommandRunner> init_seq_runner_;

  // Contains the global adapter state.
  AdapterState state_;

  // The maximum LMP feature page that we will read.
  size_t max_lmp_feature_page_index_;

  // Provides access to discovered, connected, and/or bonded remote Bluetooth
  // devices.
  PeerCache peer_cache_;

  // The data domain used by GAP to interact with L2CAP and RFCOMM layers.
  fbl::RefPtr<l2cap::L2cap> l2cap_;

  // The GATT profile. We use this reference to add and remove data bearers and
  // for service discovery.
  fxl::WeakPtr<gatt::GATT> gatt_;

  // Objects that abstract the controller for connection and advertising
  // procedures.
  std::unique_ptr<hci::LowEnergyAdvertiser> hci_le_advertiser_;
  std::unique_ptr<hci::LowEnergyConnector> hci_le_connector_;
  std::unique_ptr<hci::LowEnergyScanner> hci_le_scanner_;

  // Objects that perform LE procedures.
  std::unique_ptr<LowEnergyAddressManager> le_address_manager_;
  std::unique_ptr<LowEnergyDiscoveryManager> le_discovery_manager_;
  std::unique_ptr<LowEnergyConnectionManager> le_connection_manager_;
  std::unique_ptr<LowEnergyAdvertisingManager> le_advertising_manager_;
  std::unique_ptr<LowEnergyImpl> low_energy_;

  // Objects that perform BR/EDR procedures.
  std::unique_ptr<BrEdrConnectionManager> bredr_connection_manager_;
  std::unique_ptr<BrEdrDiscoveryManager> bredr_discovery_manager_;
  std::unique_ptr<sdp::Server> sdp_server_;
  std::unique_ptr<BrEdrImpl> bredr_;

  // Callback to propagate ownership of an auto-connected LE link.
  AutoConnectCallback auto_conn_cb_;

  fit::thread_checker thread_checker_;

  // This must remain the last member to make sure that all weak pointers are
  // invalidating before other members are destroyed.
  fxl::WeakPtrFactory<AdapterImpl> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(AdapterImpl);
};

AdapterImpl::AdapterImpl(fxl::WeakPtr<hci::Transport> hci, fxl::WeakPtr<gatt::GATT> gatt,
                         std::optional<fbl::RefPtr<l2cap::L2cap>> l2cap)
    : identifier_(Random<AdapterId>()),
      dispatcher_(async_get_default_dispatcher()),
      hci_(std::move(hci)),
      init_state_(State::kNotInitialized),
      max_lmp_feature_page_index_(0),
      peer_cache_(),
      gatt_(gatt),
      weak_ptr_factory_(this) {
  ZX_DEBUG_ASSERT(hci_);
  ZX_DEBUG_ASSERT(gatt_);
  ZX_DEBUG_ASSERT_MSG(dispatcher_, "must create on a thread with a dispatcher");

  init_seq_runner_ = std::make_unique<hci::SequentialCommandRunner>(dispatcher_, hci_);

  if (l2cap.has_value()) {
    l2cap_ = *l2cap;
  }

  auto self = weak_ptr_factory_.GetWeakPtr();
  hci_->SetTransportClosedCallback([self] {
    if (self) {
      self->OnTransportClosed();
    }
  });

  gatt_->SetPersistServiceChangedCCCCallback(
      [this](PeerId peer_id, gatt::ServiceChangedCCCPersistedData gatt_data) {
        Peer* peer = peer_cache_.FindById(peer_id);
        if (!peer) {
          bt_log(WARN, "gap", "Unable to find peer %s when storing persisted GATT data.",
                 bt_str(peer_id));
        } else if (!peer->le()) {
          bt_log(WARN, "gap", "Tried to store persisted GATT data for non-LE peer %s.",
                 bt_str(peer_id));
        } else {
          peer->MutLe().set_service_changed_gatt_data(gatt_data);
        }
      });

  gatt_->SetRetrieveServiceChangedCCCCallback([this](PeerId peer_id) {
    Peer* peer = peer_cache_.FindById(peer_id);
    if (!peer) {
      bt_log(WARN, "gap", "Unable to find peer %s when retrieving persisted GATT data.",
             peer_id.ToString().c_str());
      return std::optional<gatt::ServiceChangedCCCPersistedData>();
    } else if (!peer->le()) {
      bt_log(WARN, "gap", "Tried to retrieve persisted GATT data for non-LE peer %s.",
             peer_id.ToString().c_str());
      return std::optional<gatt::ServiceChangedCCCPersistedData>();
    } else {
      return std::optional(peer->le()->get_service_changed_gatt_data());
    }
  });
}

AdapterImpl::~AdapterImpl() {
  if (IsInitialized())
    ShutDown();
}

bool AdapterImpl::Initialize(InitializeCallback callback, fit::closure transport_closed_cb) {
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());
  ZX_DEBUG_ASSERT(callback);
  ZX_DEBUG_ASSERT(transport_closed_cb);

  if (IsInitialized()) {
    bt_log(WARN, "gap", "Adapter already initialized");
    return false;
  }

  ZX_DEBUG_ASSERT(!IsInitializing());

  init_state_ = State::kInitializing;

  ZX_DEBUG_ASSERT(init_seq_runner_->IsReady());
  ZX_DEBUG_ASSERT(!init_seq_runner_->HasQueuedCommands());

  transport_closed_cb_ = std::move(transport_closed_cb);

  state_.vendor_features_ = hci_->GetVendorFeatures();

  // Start by resetting the controller to a clean state and then send
  // informational parameter commands that are not specific to LE or BR/EDR. The
  // commands sent here are mandatory for all LE controllers.
  //
  // NOTE: It's safe to pass capture |this| directly in the callbacks as
  // |init_seq_runner_| will internally invalidate the callbacks if it ever gets
  // deleted.

  // HCI_Reset
  init_seq_runner_->QueueCommand(hci::CommandPacket::New(hci::kReset));

  // HCI_Read_Local_Version_Information
  init_seq_runner_->QueueCommand(
      hci::CommandPacket::New(hci::kReadLocalVersionInfo),
      [this](const hci::EventPacket& cmd_complete) {
        if (hci_is_error(cmd_complete, WARN, "gap", "read local version info failed")) {
          return;
        }
        auto params = cmd_complete.return_params<hci::ReadLocalVersionInfoReturnParams>();
        state_.hci_version_ = params->hci_version;
      });

  // HCI_Read_Local_Supported_Commands
  init_seq_runner_->QueueCommand(
      hci::CommandPacket::New(hci::kReadLocalSupportedCommands),
      [this](const hci::EventPacket& cmd_complete) {
        if (hci_is_error(cmd_complete, WARN, "gap", "read local supported commands failed")) {
          return;
        }
        auto params = cmd_complete.return_params<hci::ReadLocalSupportedCommandsReturnParams>();
        std::memcpy(state_.supported_commands_, params->supported_commands,
                    sizeof(params->supported_commands));
      });

  // HCI_Read_Local_Supported_Features
  init_seq_runner_->QueueCommand(
      hci::CommandPacket::New(hci::kReadLocalSupportedFeatures),
      [this](const hci::EventPacket& cmd_complete) {
        if (hci_is_error(cmd_complete, WARN, "gap", "read local supported features failed")) {
          return;
        }
        auto params = cmd_complete.return_params<hci::ReadLocalSupportedFeaturesReturnParams>();
        state_.features_.SetPage(0, le64toh(params->lmp_features));
      });

  // HCI_Read_BD_ADDR
  init_seq_runner_->QueueCommand(
      hci::CommandPacket::New(hci::kReadBDADDR), [this](const hci::EventPacket& cmd_complete) {
        if (hci_is_error(cmd_complete, WARN, "gap", "read BR_ADDR failed")) {
          return;
        }
        auto params = cmd_complete.return_params<hci::ReadBDADDRReturnParams>();
        state_.controller_address_ = params->bd_addr;
      });

  init_seq_runner_->RunCommands([callback = std::move(callback), this](hci::Status status) mutable {
    if (!status) {
      bt_log(ERROR, "gap", "Failed to obtain initial controller information: %s",
             status.ToString().c_str());
      CleanUp();
      callback(false);
      return;
    }

    InitializeStep2(std::move(callback));
  });

  return true;
}

void AdapterImpl::ShutDown() {
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());
  bt_log(DEBUG, "gap", "adapter shutting down");

  if (IsInitializing()) {
    ZX_DEBUG_ASSERT(!init_seq_runner_->IsReady());
    init_seq_runner_->Cancel();
  }

  CleanUp();
}

bool AdapterImpl::AddBondedPeer(BondingData bonding_data) {
  return peer_cache()->AddBondedPeer(bonding_data);
}

void AdapterImpl::SetPairingDelegate(fxl::WeakPtr<PairingDelegate> delegate) {
  le_connection_manager_->SetPairingDelegate(delegate);
  bredr_connection_manager_->SetPairingDelegate(delegate);
}

bool AdapterImpl::IsDiscoverable() const {
  return (le_advertising_manager_ && le_advertising_manager_->advertising()) ||
         (bredr_discovery_manager_ && bredr_discovery_manager_->discoverable());
}

bool AdapterImpl::IsDiscovering() const {
  return (le_discovery_manager_ && le_discovery_manager_->discovering()) ||
         (bredr_discovery_manager_ && bredr_discovery_manager_->discovering());
}

void AdapterImpl::SetLocalName(std::string name, hci::StatusCallback callback) {
  // TODO(fxbug.dev/40836): set the public LE advertisement name from |name|
  // If BrEdr is not supported, skip the name update.
  if (!bredr_discovery_manager_) {
    callback(hci::Status(bt::HostError::kNotSupported));
    return;
  }

  // Make a copy of |name| to move separately into the lambda.
  std::string name_copy(name);
  bredr_discovery_manager_->UpdateLocalName(
      std::move(name),
      [this, cb = std::move(callback), local_name = std::move(name_copy)](auto status) {
        if (!bt_is_error(status, WARN, "gap", "set local name failed")) {
          state_.local_name_ = local_name;
        }
        cb(status);
      });
}

void AdapterImpl::SetDeviceClass(DeviceClass dev_class, hci::StatusCallback callback) {
  auto write_dev_class = hci::CommandPacket::New(hci::kWriteClassOfDevice,
                                                 sizeof(hci::WriteClassOfDeviceCommandParams));
  write_dev_class->mutable_payload<hci::WriteClassOfDeviceCommandParams>()->class_of_device =
      dev_class;
  hci_->command_channel()->SendCommand(
      std::move(write_dev_class), [cb = std::move(callback)](auto, const hci::EventPacket& event) {
        hci_is_error(event, WARN, "gap", "set device class failed");
        cb(event.ToStatus());
      });
}

void AdapterImpl::AttachInspect(inspect::Node& parent, std::string name) {
  adapter_node_ = parent.CreateChild(name);
  UpdateInspectProperties();

  peer_cache_.AttachInspect(adapter_node_);

  metrics_node_ = adapter_node_.CreateChild(kMetricsInspectNodeName);

  metrics_le_node_ = metrics_node_.CreateChild("le");
  metrics_.le.outgoing_connection_requests.AttachInspect(metrics_le_node_,
                                                         "outgoing_connection_requests");
  metrics_.le.pair_requests.AttachInspect(metrics_le_node_, "pair_requests");
  metrics_.le.start_advertising_events.AttachInspect(metrics_le_node_, "start_advertising_events");
  metrics_.le.stop_advertising_events.AttachInspect(metrics_le_node_, "stop_advertising_events");
  metrics_.le.start_discovery_events.AttachInspect(metrics_le_node_, "start_discovery_events");

  metrics_bredr_node_ = metrics_node_.CreateChild("bredr");
  metrics_.bredr.outgoing_connection_requests.AttachInspect(metrics_bredr_node_,
                                                            "outgoing_connection_requests");
  metrics_.bredr.pair_requests.AttachInspect(metrics_bredr_node_, "pair_requests");
  metrics_.bredr.set_connectable_true_events.AttachInspect(metrics_bredr_node_,
                                                           "set_connectable_true_events");
  metrics_.bredr.set_connectable_false_events.AttachInspect(metrics_bredr_node_,
                                                            "set_connectable_false_events");
  metrics_.bredr.request_discovery_events.AttachInspect(metrics_bredr_node_,
                                                        "request_discovery_events");
  metrics_.bredr.request_discoverable_events.AttachInspect(metrics_bredr_node_,
                                                           "request_discoverable_events");
  metrics_.bredr.open_l2cap_channel_requests.AttachInspect(metrics_bredr_node_,
                                                           "open_l2cap_channel_requests");
}

void AdapterImpl::InitializeStep2(InitializeCallback callback) {
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());
  ZX_DEBUG_ASSERT(IsInitializing());

  // Low Energy MUST be supported. We don't support BR/EDR-only controllers.
  if (!state_.IsLowEnergySupported()) {
    bt_log(ERROR, "gap", "Bluetooth LE not supported by controller");
    CleanUp();
    callback(false);
    return;
  }

  // Check the HCI version. We officially only support 4.2+ only but for now we
  // just log a warning message if the version is legacy.
  if (state_.hci_version() < hci::HCIVersion::k4_2) {
    bt_log(WARN, "gap", "controller is using legacy HCI version %s",
           hci::HCIVersionToString(state_.hci_version()).c_str());
  }

  ZX_DEBUG_ASSERT(init_seq_runner_->IsReady());

  // If the controller supports the Read Buffer Size command then send it.
  // Otherwise we'll default to 0 when initializing the ACLDataChannel.
  if (state_.IsCommandSupported(14, hci::SupportedCommand::kReadBufferSize)) {
    // HCI_Read_Buffer_Size
    init_seq_runner_->QueueCommand(
        hci::CommandPacket::New(hci::kReadBufferSize),
        [this](const hci::EventPacket& cmd_complete) {
          if (hci_is_error(cmd_complete, WARN, "gap", "read buffer size failed")) {
            return;
          }
          auto params = cmd_complete.return_params<hci::ReadBufferSizeReturnParams>();
          uint16_t mtu = le16toh(params->hc_acl_data_packet_length);
          uint16_t max_count = le16toh(params->hc_total_num_acl_data_packets);
          if (mtu && max_count) {
            state_.bredr_data_buffer_info_ = hci::DataBufferInfo(mtu, max_count);
          }
        });
  }

  // HCI_LE_Read_Local_Supported_Features
  init_seq_runner_->QueueCommand(
      hci::CommandPacket::New(hci::kLEReadLocalSupportedFeatures),
      [this](const hci::EventPacket& cmd_complete) {
        if (hci_is_error(cmd_complete, WARN, "gap", "LE read local supported features failed")) {
          return;
        }
        auto params = cmd_complete.return_params<hci::LEReadLocalSupportedFeaturesReturnParams>();
        state_.le_state_.supported_features_ = le64toh(params->le_features);
      });

  // HCI_LE_Read_Supported_States
  init_seq_runner_->QueueCommand(
      hci::CommandPacket::New(hci::kLEReadSupportedStates),
      [this](const hci::EventPacket& cmd_complete) {
        if (hci_is_error(cmd_complete, WARN, "gap", "LE read local supported states failed")) {
          return;
        }
        auto params = cmd_complete.return_params<hci::LEReadSupportedStatesReturnParams>();
        state_.le_state_.supported_states_ = le64toh(params->le_states);
      });

  // HCI_LE_Read_Buffer_Size
  init_seq_runner_->QueueCommand(
      hci::CommandPacket::New(hci::kLEReadBufferSize),
      [this](const hci::EventPacket& cmd_complete) {
        if (hci_is_error(cmd_complete, WARN, "gap", "LE read buffer size failed")) {
          return;
        }
        auto params = cmd_complete.return_params<hci::LEReadBufferSizeReturnParams>();
        uint16_t mtu = le16toh(params->hc_le_acl_data_packet_length);
        uint8_t max_count = params->hc_total_num_le_acl_data_packets;
        if (mtu && max_count) {
          state_.le_state_.data_buffer_info_ = hci::DataBufferInfo(mtu, max_count);
        }
      });

  if (state_.features().HasBit(0u, hci::LMPFeature::kSecureSimplePairing)) {
    // HCI_Write_Simple_Pairing_Mode
    auto write_ssp = hci::CommandPacket::New(hci::kWriteSimplePairingMode,
                                             sizeof(hci::WriteSimplePairingModeCommandParams));
    write_ssp->mutable_payload<hci::WriteSimplePairingModeCommandParams>()->simple_pairing_mode =
        hci::GenericEnableParam::kEnable;
    init_seq_runner_->QueueCommand(std::move(write_ssp), [](const auto& event) {
      // Warn if the command failed
      hci_is_error(event, WARN, "gap", "write simple pairing mode failed");
    });
  }

  // If there are extended features then try to read the first page of the
  // extended features.
  if (state_.features().HasBit(0u, hci::LMPFeature::kExtendedFeatures)) {
    // Page index 1 must be available.
    max_lmp_feature_page_index_ = 1;

    // HCI_Read_Local_Extended_Features
    auto cmd_packet = hci::CommandPacket::New(hci::kReadLocalExtendedFeatures,
                                              sizeof(hci::ReadLocalExtendedFeaturesCommandParams));

    // Try to read page 1.
    cmd_packet->mutable_payload<hci::ReadLocalExtendedFeaturesCommandParams>()->page_number = 1;

    init_seq_runner_->QueueCommand(
        std::move(cmd_packet), [this](const hci::EventPacket& cmd_complete) {
          if (hci_is_error(cmd_complete, WARN, "gap", "read local extended features failed")) {
            return;
          }
          auto params = cmd_complete.return_params<hci::ReadLocalExtendedFeaturesReturnParams>();
          state_.features_.SetPage(1, le64toh(params->extended_lmp_features));
          max_lmp_feature_page_index_ = params->maximum_page_number;
        });
  }

  init_seq_runner_->RunCommands([callback = std::move(callback), this](hci::Status status) mutable {
    if (bt_is_error(status, ERROR, "gap",
                    "failed to obtain initial controller information (step 2)")) {
      CleanUp();
      callback(false);
      return;
    }
    InitializeStep3(std::move(callback));
  });
}

void AdapterImpl::InitializeStep3(InitializeCallback callback) {
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());
  ZX_DEBUG_ASSERT(IsInitializing());

  if (!state_.bredr_data_buffer_info().IsAvailable() &&
      !state_.low_energy_state().data_buffer_info().IsAvailable()) {
    bt_log(ERROR, "gap", "Both BR/EDR and LE buffers are unavailable");
    CleanUp();
    callback(false);
    return;
  }

  // Now that we have all the ACL data buffer information it's time to
  // initialize the ACLDataChannel.
  if (!hci_->InitializeACLDataChannel(state_.bredr_data_buffer_info(),
                                      state_.low_energy_state().data_buffer_info())) {
    bt_log(ERROR, "gap", "Failed to initialize ACLDataChannel (step 3)");
    CleanUp();
    callback(false);
    return;
  }

  // Create the data domain, if we haven't been provided one. Doing so here lets us guarantee that
  // AclDataChannel's lifetime is a superset of Data L2cap's lifetime.
  // TODO(fxbug.dev/35228) We currently allow tests to inject their own domain in the adapter
  // constructor, as the adapter_unittests rely on injecting a fake domain to avoid concurrency in
  // the unit tests.  Once we move to a single threaded model, we would like to remove this and have
  // the adapter always be responsible for creating the domain.
  if (!l2cap_) {
    // Initialize the data L2cap to make L2CAP available for the next initialization step. The
    // ACLDataChannel must be initialized before creating the data domain
    auto l2cap = l2cap::L2cap::Create(hci_->acl_data_channel(), /*random_channel_ids=*/true);
    if (!l2cap) {
      bt_log(ERROR, "gap", "Failed to initialize Data L2cap");
      CleanUp();
      callback(false);
      return;
    }
    l2cap->AttachInspect(adapter_node_, l2cap::L2cap::kInspectNodeName);
    l2cap_ = l2cap;
  }

  ZX_DEBUG_ASSERT(init_seq_runner_->IsReady());
  ZX_DEBUG_ASSERT(!init_seq_runner_->HasQueuedCommands());

  // HCI_Set_Event_Mask
  {
    uint64_t event_mask = BuildEventMask();
    auto cmd_packet =
        hci::CommandPacket::New(hci::kSetEventMask, sizeof(hci::SetEventMaskCommandParams));
    cmd_packet->mutable_payload<hci::SetEventMaskCommandParams>()->event_mask = htole64(event_mask);
    init_seq_runner_->QueueCommand(std::move(cmd_packet), [](const auto& event) {
      hci_is_error(event, WARN, "gap", "set event mask failed");
    });
  }

  // HCI_LE_Set_Event_Mask
  {
    uint64_t event_mask = BuildLEEventMask();
    auto cmd_packet =
        hci::CommandPacket::New(hci::kLESetEventMask, sizeof(hci::LESetEventMaskCommandParams));
    cmd_packet->mutable_payload<hci::LESetEventMaskCommandParams>()->le_event_mask =
        htole64(event_mask);
    init_seq_runner_->QueueCommand(std::move(cmd_packet), [](const auto& event) {
      hci_is_error(event, WARN, "gap", "LE set event mask failed");
    });
  }

  // HCI_Write_LE_Host_Support if the appropriate feature bit is not set AND if
  // the controller supports this command.
  if (!state_.features().HasBit(1, hci::LMPFeature::kLESupportedHost) &&
      state_.IsCommandSupported(24, hci::SupportedCommand::kWriteLEHostSupport)) {
    auto cmd_packet = hci::CommandPacket::New(hci::kWriteLEHostSupport,
                                              sizeof(hci::WriteLEHostSupportCommandParams));
    auto params = cmd_packet->mutable_payload<hci::WriteLEHostSupportCommandParams>();
    params->le_supported_host = hci::GenericEnableParam::kEnable;
    params->simultaneous_le_host = 0x00;  // note: ignored
    init_seq_runner_->QueueCommand(std::move(cmd_packet), [](const auto& event) {
      hci_is_error(event, WARN, "gap", "write LE host support failed");
    });
  }

  // If we know that Page 2 of the extended features bitfield is available, then
  // request it.
  if (max_lmp_feature_page_index_ > 1) {
    auto cmd_packet = hci::CommandPacket::New(hci::kReadLocalExtendedFeatures,
                                              sizeof(hci::ReadLocalExtendedFeaturesCommandParams));

    // Try to read page 2.
    cmd_packet->mutable_payload<hci::ReadLocalExtendedFeaturesCommandParams>()->page_number = 2;

    // HCI_Read_Local_Extended_Features
    init_seq_runner_->QueueCommand(
        std::move(cmd_packet), [this](const hci::EventPacket& cmd_complete) {
          if (hci_is_error(cmd_complete, WARN, "gap", "read local extended features failed")) {
            return;
          }
          auto params = cmd_complete.return_params<hci::ReadLocalExtendedFeaturesReturnParams>();
          state_.features_.SetPage(2, le64toh(params->extended_lmp_features));
          max_lmp_feature_page_index_ = params->maximum_page_number;
        });
  }

  init_seq_runner_->RunCommands([callback = std::move(callback), this](hci::Status status) mutable {
    if (bt_is_error(status, ERROR, "gap",
                    "failed to obtain initial controller information (step 3)")) {
      CleanUp();
      callback(false);
      return;
    }
    InitializeStep4(std::move(callback));
  });
}

void AdapterImpl::InitializeStep4(InitializeCallback callback) {
  ZX_DEBUG_ASSERT(IsInitializing());

  // Initialize the scan manager based on current feature support.
  if (state_.low_energy_state().IsFeatureSupported(
          hci::LESupportedFeature::kLEExtendedAdvertising)) {
    bt_log(INFO, "gap", "controller supports extended advertising");

    // TODO(armansito): Initialize |hci_le_*| objects here with extended-mode
    // versions.
    bt_log(WARN, "gap", "5.0 not yet supported; using legacy mode");
  }

  // We use the public controller address as the local LE identity address.
  DeviceAddress adapter_identity(DeviceAddress::Type::kLEPublic, state_.controller_address());

  // Initialize the LE local address manager.
  le_address_manager_ = std::make_unique<LowEnergyAddressManager>(
      adapter_identity, fit::bind_member(this, &AdapterImpl::IsLeRandomAddressChangeAllowed), hci_);

  // Initialize the HCI adapters.
  hci_le_advertiser_ = std::make_unique<hci::LegacyLowEnergyAdvertiser>(hci_);
  hci_le_connector_ = std::make_unique<hci::LowEnergyConnector>(
      hci_, le_address_manager_.get(), dispatcher_,
      fit::bind_member(hci_le_advertiser_.get(), &hci::LowEnergyAdvertiser::OnIncomingConnection));
  hci_le_scanner_ =
      std::make_unique<hci::LegacyLowEnergyScanner>(le_address_manager_.get(), hci_, dispatcher_);

  // Initialize the LE manager objects
  le_discovery_manager_ =
      std::make_unique<LowEnergyDiscoveryManager>(hci_, hci_le_scanner_.get(), &peer_cache_);
  le_discovery_manager_->AttachInspect(adapter_node_, kInspectLowEnergyDiscoveryManagerNodeName);
  le_discovery_manager_->set_peer_connectable_callback(
      fit::bind_member(this, &AdapterImpl::OnLeAutoConnectRequest));

  le_connection_manager_ = std::make_unique<LowEnergyConnectionManager>(
      hci_, le_address_manager_.get(), hci_le_connector_.get(), &peer_cache_, l2cap_, gatt_,
      le_discovery_manager_->GetWeakPtr(), sm::SecurityManager::Create);
  le_connection_manager_->AttachInspect(adapter_node_);

  le_advertising_manager_ = std::make_unique<LowEnergyAdvertisingManager>(
      hci_le_advertiser_.get(), le_address_manager_.get());
  low_energy_ = std::make_unique<LowEnergyImpl>(this);

  // Initialize the BR/EDR manager objects if the controller supports BR/EDR.
  if (state_.IsBREDRSupported()) {
    DeviceAddress local_bredr_address(DeviceAddress::Type::kBREDR, state_.controller_address());

    bredr_connection_manager_ = std::make_unique<BrEdrConnectionManager>(
        hci_, &peer_cache_, local_bredr_address, l2cap_,
        state_.features().HasBit(0, hci::LMPFeature::kInterlacedPageScan));
    bredr_connection_manager_->AttachInspect(adapter_node_, kInspectBrEdrConnectionManagerNodeName);

    hci::InquiryMode mode = hci::InquiryMode::kStandard;
    if (state_.features().HasBit(0, hci::LMPFeature::kExtendedInquiryResponse)) {
      mode = hci::InquiryMode::kExtended;
    } else if (state_.features().HasBit(0, hci::LMPFeature::kRSSIwithInquiryResults)) {
      mode = hci::InquiryMode::kRSSI;
    }

    bredr_discovery_manager_ = std::make_unique<BrEdrDiscoveryManager>(hci_, mode, &peer_cache_);

    sdp_server_ = std::make_unique<sdp::Server>(l2cap_);
    sdp_server_->AttachInspect(adapter_node_);

    bredr_ = std::make_unique<BrEdrImpl>(this);
  }

  // Override the current privacy setting and always use the local stable identity address (i.e. not
  // a RPA) when initiating connections. This improves interoperability with certain Bluetooth
  // peripherals that fail to authenticate following a RPA rotation.
  //
  // The implication here is that the public address is revealed in LL connection request PDUs. LE
  // central privacy is still preserved during an active scan, i.e. in LL scan request PDUs.
  //
  // TODO(fxbug.dev/63123): Remove this temporary fix once we determine the root cause for
  // authentication failures.
  hci_le_connector_->UseLocalIdentityAddress();

  // Update properties before callback called so properties can be verified in unit tests.
  UpdateInspectProperties();

  // Assign a default name and device class before notifying completion.
  auto self = weak_ptr_factory_.GetWeakPtr();
  SetLocalName(kDefaultLocalName, [self, callback = std::move(callback)](auto status) mutable {
    // Set the default device class - a computer with audio.
    // TODO(fxbug.dev/1234): set this from a platform configuration file
    DeviceClass dev_class(DeviceClass::MajorClass::kComputer);
    dev_class.SetServiceClasses({DeviceClass::ServiceClass::kAudio});
    self->SetDeviceClass(dev_class, [self, callback = std::move(callback)](const auto&) {
      // This completes the initialization sequence.
      self->init_state_ = State::kInitialized;
      callback(true);
    });
  });
}

void AdapterImpl::UpdateInspectProperties() {
  inspect_properties_.adapter_id = adapter_node_.CreateString("adapter_id", identifier_.ToString());
  inspect_properties_.hci_version =
      adapter_node_.CreateString("hci_version", hci::HCIVersionToString(state_.hci_version()));

  inspect_properties_.bredr_max_num_packets = adapter_node_.CreateUint(
      "bredr_max_num_packets", state_.bredr_data_buffer_info().max_num_packets());
  inspect_properties_.bredr_max_data_length = adapter_node_.CreateUint(
      "bredr_max_data_length", state_.bredr_data_buffer_info().max_data_length());

  inspect_properties_.le_max_num_packets = adapter_node_.CreateUint(
      "le_max_num_packets", state_.low_energy_state().data_buffer_info().max_num_packets());
  inspect_properties_.le_max_data_length = adapter_node_.CreateUint(
      "le_max_data_length", state_.low_energy_state().data_buffer_info().max_data_length());

  inspect_properties_.lmp_features =
      adapter_node_.CreateString("lmp_features", state_.features().ToString());

  auto le_features = fxl::StringPrintf("0x%016lx", state_.low_energy_state().supported_features());
  inspect_properties_.le_features = adapter_node_.CreateString("le_features", le_features);
}

uint64_t AdapterImpl::BuildEventMask() {
  uint64_t event_mask = 0;

#define ENABLE_EVT(event) event_mask |= static_cast<uint64_t>(hci::EventMask::event)

  // Enable events that are needed for basic functionality. (alphabetic)
  ENABLE_EVT(kAuthenticationCompleteEvent);
  ENABLE_EVT(kConnectionCompleteEvent);
  ENABLE_EVT(kConnectionRequestEvent);
  ENABLE_EVT(kDataBufferOverflowEvent);
  ENABLE_EVT(kDisconnectionCompleteEvent);
  ENABLE_EVT(kEncryptionChangeEvent);
  ENABLE_EVT(kEncryptionKeyRefreshCompleteEvent);
  ENABLE_EVT(kExtendedInquiryResultEvent);
  ENABLE_EVT(kHardwareErrorEvent);
  ENABLE_EVT(kInquiryCompleteEvent);
  ENABLE_EVT(kInquiryResultEvent);
  ENABLE_EVT(kInquiryResultWithRSSIEvent);
  ENABLE_EVT(kIOCapabilityRequestEvent);
  ENABLE_EVT(kIOCapabilityResponseEvent);
  ENABLE_EVT(kLEMetaEvent);
  ENABLE_EVT(kLinkKeyRequestEvent);
  ENABLE_EVT(kLinkKeyNotificationEvent);
  ENABLE_EVT(kRemoteOOBDataRequestEvent);
  ENABLE_EVT(kRemoteNameRequestCompleteEvent);
  ENABLE_EVT(kReadRemoteSupportedFeaturesCompleteEvent);
  ENABLE_EVT(kReadRemoteVersionInformationCompleteEvent);
  ENABLE_EVT(kReadRemoteExtendedFeaturesCompleteEvent);
  ENABLE_EVT(kSimplePairingCompleteEvent);
  ENABLE_EVT(kSynchronousConnectionCompleteEvent);
  ENABLE_EVT(kUserConfirmationRequestEvent);
  ENABLE_EVT(kUserPasskeyRequestEvent);
  ENABLE_EVT(kUserPasskeyNotificationEvent);

#undef ENABLE_EVT

  return event_mask;
}

uint64_t AdapterImpl::BuildLEEventMask() {
  uint64_t event_mask = 0;

#define ENABLE_EVT(event) event_mask |= static_cast<uint64_t>(hci::LEEventMask::event)

  ENABLE_EVT(kLEAdvertisingReport);
  ENABLE_EVT(kLEConnectionComplete);
  ENABLE_EVT(kLEConnectionUpdateComplete);
  ENABLE_EVT(kLELongTermKeyRequest);
  ENABLE_EVT(kLEReadRemoteFeaturesComplete);

#undef ENABLE_EVT

  return event_mask;
}

void AdapterImpl::CleanUp() {
  ZX_DEBUG_ASSERT(thread_checker_.is_thread_valid());

  if (init_state_ == State::kNotInitialized) {
    bt_log(DEBUG, "gap", "clean up: not initialized");
    return;
  }

  init_state_ = State::kNotInitialized;
  state_ = AdapterState();
  transport_closed_cb_ = nullptr;

  // Destroy objects in reverse order of construction.
  low_energy_ = nullptr;
  bredr_ = nullptr;
  sdp_server_ = nullptr;
  bredr_discovery_manager_ = nullptr;
  le_advertising_manager_ = nullptr;
  le_connection_manager_ = nullptr;
  le_discovery_manager_ = nullptr;

  hci_le_connector_ = nullptr;
  hci_le_advertiser_ = nullptr;
  hci_le_scanner_ = nullptr;

  le_address_manager_ = nullptr;

  l2cap_ = nullptr;

  hci_ = nullptr;
}

void AdapterImpl::OnTransportClosed() {
  bt_log(INFO, "gap", "HCI transport was closed");
  if (transport_closed_cb_)
    transport_closed_cb_();
}

void AdapterImpl::OnLeAutoConnectRequest(Peer* peer) {
  ZX_DEBUG_ASSERT(le_connection_manager_);
  ZX_DEBUG_ASSERT(peer);
  ZX_DEBUG_ASSERT(peer->le());

  PeerId peer_id = peer->identifier();

  if (!peer->le()->should_auto_connect()) {
    bt_log(DEBUG, "gap",
           "ignoring auto-connection (peer->should_auto_connect() is false) (peer: %s)",
           bt_str(peer_id));
    return;
  }

  LowEnergyConnectionOptions options{.auto_connect = true};

  auto self = weak_ptr_factory_.GetWeakPtr();
  le_connection_manager_->Connect(
      peer_id,
      [self, peer_id](auto result) {
        if (!self) {
          bt_log(DEBUG, "gap", "ignoring auto-connection (adapter destroyed)");
          return;
        }

        if (result.is_error()) {
          bt_log(INFO, "gap", "failed to auto-connect (peer: %s, error: %s)", bt_str(peer_id),
                 HostErrorToString(result.error()).c_str());
          return;
        }

        auto conn = result.take_value();
        ZX_ASSERT(conn);
        bt_log(INFO, "gap", "peer auto-connected (peer: %s)", bt_str(peer_id));
        if (self->auto_conn_cb_) {
          self->auto_conn_cb_(std::move(conn));
        }
      },
      options);
}

bool AdapterImpl::IsLeRandomAddressChangeAllowed() {
  return hci_le_advertiser_->AllowsRandomAddressChange() &&
         hci_le_scanner_->AllowsRandomAddressChange() &&
         hci_le_connector_->AllowsRandomAddressChange();
}

std::unique_ptr<Adapter> Adapter::Create(fxl::WeakPtr<hci::Transport> hci,
                                         fxl::WeakPtr<gatt::GATT> gatt,
                                         std::optional<fbl::RefPtr<l2cap::L2cap>> l2cap) {
  return std::make_unique<AdapterImpl>(hci, gatt, l2cap);
}

}  // namespace bt::gap
