// 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 "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/adapter.h"

#include <endian.h>

#include <pw_async/dispatcher.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/log.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/metrics.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/random.h"
#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/gap/bredr_discovery_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/event_masks.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/low_energy_address_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/low_energy_advertising_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/low_energy_connection_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/low_energy_discovery_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gap/peer.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-spec/vendor_protocol.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci/android_extended_low_energy_advertiser.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci/extended_low_energy_advertiser.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci/extended_low_energy_scanner.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci/legacy_low_energy_advertiser.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci/legacy_low_energy_scanner.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/hci/low_energy_connector.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/channel_manager.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/transport/emboss_control_packets.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/transport/transport.h"

#include <pw_bluetooth/hci_commands.emb.h>

namespace bt::gap {

namespace android_hci = hci_spec::vendor::android;
namespace android_emb = pw::bluetooth::vendor::android_hci;

static constexpr const char* kInspectLowEnergyDiscoveryManagerNodeName =
    "low_energy_discovery_manager";
static constexpr const char* kInspectLowEnergyConnectionManagerNodeName =
    "low_energy_connection_manager";
static constexpr const char* kInspectBrEdrConnectionManagerNodeName =
    "bredr_connection_manager";
static constexpr const char* kInspectBrEdrDiscoveryManagerNodeName =
    "bredr_discovery_manager";

// All asynchronous callbacks are posted on the Loop on which this Adapter
// instance is created.
class AdapterImpl final : public Adapter {
 public:
  explicit AdapterImpl(pw::async::Dispatcher& pw_dispatcher,
                       hci::Transport::WeakPtr hci,
                       gatt::GATT::WeakPtr gatt,
                       std::unique_ptr<l2cap::ChannelManager> l2cap);
  ~AdapterImpl() override;

  AdapterId identifier() const override { return identifier_; }

  bool Initialize(InitializeCallback callback,
                  fit::closure transport_error_cb) 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), connection_options);
      adapter_->metrics_.le.outgoing_connection_requests.Add();
    }

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

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

    void SetLESecurityMode(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,
        AdvertisingInterval interval,
        bool extended_pdu,
        bool anonymous,
        bool include_tx_power_level,
        std::optional<ConnectableAdvertisingParameters> connectable,
        AdvertisingStatusCallback status_callback) override {
      LowEnergyAdvertisingManager::ConnectionCallback advertisement_connect_cb =
          nullptr;
      if (connectable) {
        BT_ASSERT(connectable->connection_cb);

        // All advertisement connections are first registered with
        // LowEnergyConnectionManager before being reported to higher layers.
        advertisement_connect_cb =
            [this, connectable = std::move(connectable)](
                AdvertisementId advertisement_id,
                std::unique_ptr<hci::LowEnergyConnection> link) mutable {
              auto register_link_cb =
                  [advertisement_id,
                   connection_callback = std::move(connectable->connection_cb)](
                      ConnectionResult result) {
                    connection_callback(advertisement_id, std::move(result));
                  };

              adapter_->le_connection_manager_->RegisterRemoteInitiatedLink(
                  std::move(link),
                  connectable->bondable_mode,
                  std::move(register_link_cb));
            };
      }

      adapter_->le_advertising_manager_->StartAdvertising(
          std::move(data),
          std::move(scan_rsp),
          std::move(advertisement_connect_cb),
          interval,
          extended_pdu,
          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);
    }

    bool PrivacyEnabled() const override {
      return adapter_->le_address_manager_->PrivacyEnabled();
    }

    const DeviceAddress& CurrentAddress() const override {
      return adapter_->le_address_manager_->current_address();
    }

    void register_address_changed_callback(fit::closure callback) override {
      auto cb = [cb = std::move(callback)](auto) { cb(); };
      adapter_->le_address_manager_->register_address_changed_callback(
          std::move(cb));
    }

    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(
        pw::chrono::SystemClock::duration value) override {
      adapter_->le_connection_manager_->set_request_timeout_for_testing(value);
    }

    void set_scan_period_for_testing(
        pw::chrono::SystemClock::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_spec::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::ResultFunction<> callback) override {
      adapter_->bredr_connection_manager_->Pair(
          peer_id, security, std::move(callback));
      adapter_->metrics_.bredr.pair_requests.Add();
    }

    void SetBrEdrSecurityMode(BrEdrSecurityMode mode) override {
      adapter_->bredr_connection_manager_->SetSecurityMode(mode);
    }

    BrEdrSecurityMode security_mode() const override {
      return adapter_->bredr_connection_manager_->security_mode();
    }

    void SetConnectable(bool connectable,
                        hci::ResultFunction<> 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,
        const bt::StaticPacket<
            pw::bluetooth::emboss::SynchronousConnectionParametersWriter>&
            parameters,
        sco::ScoConnectionManager::OpenConnectionCallback callback) override {
      return adapter_->bredr_connection_manager_->OpenScoConnection(
          peer_id, parameters, std::move(callback));
    }
    std::optional<ScoRequestHandle> AcceptScoConnection(
        PeerId peer_id,
        const std::vector<bt::StaticPacket<
            pw::bluetooth::emboss::SynchronousConnectionParametersWriter>>
            parameters,
        sco::ScoConnectionManager::AcceptConnectionCallback callback) override {
      return adapter_->bredr_connection_manager_->AcceptScoConnection(
          peer_id, std::move(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(PairingDelegate::WeakPtr delegate) override;

  bool IsDiscoverable() const override;

  bool IsDiscovering() const override;

  void SetLocalName(std::string name, hci::ResultFunction<> callback) override;

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

  void SetDeviceClass(DeviceClass dev_class,
                      hci::ResultFunction<> callback) override;

  void GetSupportedDelayRange(
      std::unique_ptr<bt::StaticPacket<pw::bluetooth::emboss::CodecIdWriter>>
          codec_id,
      pw::bluetooth::emboss::LogicalTransportType logical_transport_type,
      pw::bluetooth::emboss::DataPathDirection direction,
      std::optional<std::vector<uint8_t>> codec_configuration,
      GetSupportedDelayRangeCallback cb) override;

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

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

  WeakSelf<Adapter>::WeakPtr AsWeakPtr() override {
    return weak_self_adapter_.GetWeakPtr();
  }

 private:
  // Called by Initialize() after Transport is initialized.
  void InitializeStep1();

  // Second step of the initialization sequence. Called by InitializeStep1()
  // when the first batch of HCI commands have been sent.
  void InitializeStep2();

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

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

  // Returns true if initialization was completed, or false if initialization is
  // not in progress.
  bool CompleteInitialization(bool success);

  // Reads LMP feature mask's bits from |page|
  void InitQueueReadLMPFeatureMaskPage(uint8_t page);

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

  // 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 experiences a fatal error.
  void OnTransportError();

  // 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();

  // Called when we receive an LE Get Vendor Capabilities Command Complete from
  // the Controller
  void ParseLEGetVendorCapabilitiesCommandComplete(
      const hci::EmbossEventPacket& event);

  std::unique_ptr<hci::LowEnergyAdvertiser> CreateAdvertiser(bool extended) {
    if (extended) {
      return std::make_unique<hci::ExtendedLowEnergyAdvertiser>(
          hci_, state_.low_energy_state.max_advertising_data_length_);
    }

    constexpr pw::bluetooth::Controller::FeaturesBits feature =
        pw::bluetooth::Controller::FeaturesBits::kAndroidVendorExtensions;
    if (!state().IsControllerFeatureSupported(feature)) {
      return std::make_unique<hci::LegacyLowEnergyAdvertiser>(hci_);
    }

    if (!state().android_vendor_capabilities) {
      bt_log(
          WARN,
          "gap",
          "controller supports android vendor extensions, but failed to parse "
          "LEGetVendorCapabilitiesCommandComplete, using legacy advertiser");
      return std::make_unique<hci::LegacyLowEnergyAdvertiser>(hci_);
    }

    uint8_t max_advt =
        state().android_vendor_capabilities->max_simultaneous_advertisements();
    bt_log(INFO,
           "gap",
           "controller supports android vendor extensions, max simultaneous "
           "advertisements: %d",
           max_advt);
    return std::make_unique<hci::AndroidExtendedLowEnergyAdvertiser>(hci_,
                                                                     max_advt);
  }

  std::unique_ptr<hci::LowEnergyConnector> CreateConnector(bool extended) {
    return std::make_unique<hci::LowEnergyConnector>(
        hci_,
        le_address_manager_.get(),
        dispatcher_,
        fit::bind_member<&hci::LowEnergyAdvertiser::OnIncomingConnection>(
            hci_le_advertiser_.get()),
        extended);
  }

  std::unique_ptr<hci::LowEnergyScanner> CreateScanner(bool extended) {
    if (extended) {
      return std::make_unique<hci::ExtendedLowEnergyScanner>(
          le_address_manager_.get(), hci_, dispatcher_);
    }

    return std::make_unique<hci::LegacyLowEnergyScanner>(
        le_address_manager_.get(), hci_, dispatcher_);
  }

  // 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::UintProperty sco_max_num_packets;
    inspect::UintProperty sco_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_;

  hci::Transport::WeakPtr hci_;

  // Callback invoked to notify clients when the underlying transport is closed.
  fit::closure transport_error_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_;

  // The callback passed to Initialize(). Null after initialization completes.
  InitializeCallback init_cb_;

  // Contains the global adapter state.
  AdapterState state_;

  // The maximum LMP feature page that we will read.
  std::optional<size_t> max_lmp_feature_page_index_;

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

  // L2CAP layer used by GAP. This must be destroyed after the following members
  // because they raw pointers to this member.
  std::unique_ptr<l2cap::ChannelManager> l2cap_;

  // The GATT profile. We use this reference to add and remove data bearers and
  // for service discovery.
  gatt::GATT::WeakPtr 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_;

  pw::async::Dispatcher& dispatcher_;

  // This must remain the last member to make sure that all weak pointers are
  // invalidating before other members are destroyed.
  WeakSelf<AdapterImpl> weak_self_;
  WeakSelf<Adapter> weak_self_adapter_;

  BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(AdapterImpl);
};

AdapterImpl::AdapterImpl(pw::async::Dispatcher& pw_dispatcher,
                         hci::Transport::WeakPtr hci,
                         gatt::GATT::WeakPtr gatt,
                         std::unique_ptr<l2cap::ChannelManager> l2cap)
    : identifier_(Random<AdapterId>()),
      hci_(std::move(hci)),
      init_state_(State::kNotInitialized),
      peer_cache_(pw_dispatcher),
      l2cap_(std::move(l2cap)),
      gatt_(std::move(gatt)),
      dispatcher_(pw_dispatcher),
      weak_self_(this),
      weak_self_adapter_(this) {
  BT_DEBUG_ASSERT(hci_.is_alive());
  BT_DEBUG_ASSERT(gatt_.is_alive());

  auto self = weak_self_.GetWeakPtr();
  hci_->SetTransportErrorCallback([self] {
    if (self.is_alive()) {
      self->OnTransportError();
    }
  });

  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>();
    }

    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>();
    }

    return std::optional(peer->le()->get_service_changed_gatt_data());
  });
}

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

bool AdapterImpl::Initialize(InitializeCallback callback,
                             fit::closure transport_error_cb) {
  BT_DEBUG_ASSERT(callback);
  BT_DEBUG_ASSERT(transport_error_cb);

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

  BT_DEBUG_ASSERT(!IsInitializing());
  BT_DEBUG_ASSERT(!init_seq_runner_);

  init_state_ = State::kInitializing;
  init_cb_ = std::move(callback);
  transport_error_cb_ = std::move(transport_error_cb);

  hci_->Initialize([this](bool success) {
    if (!success) {
      bt_log(ERROR, "gap", "Failed to initialize Transport");
      CompleteInitialization(/*success=*/false);
      return;
    }
    init_seq_runner_ = std::make_unique<hci::SequentialCommandRunner>(
        hci_->command_channel()->AsWeakPtr());

    InitializeStep1();
  });

  return true;
}

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

  if (IsInitializing()) {
    BT_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(PairingDelegate::WeakPtr delegate) {
  le_connection_manager_->SetPairingDelegate(delegate);
  bredr_connection_manager_->SetPairingDelegate(delegate);
}

bool AdapterImpl::IsDiscoverable() const {
  if (bredr_discovery_manager_ && bredr_discovery_manager_->discoverable()) {
    return true;
  }

  // If LE Privacy is enabled, then we are not discoverable.
  // TODO(https://fxbug.dev/42060496): Make this dependent on whether the LE
  // Public advertisement is active or not.
  if (le_address_manager_ && le_address_manager_->PrivacyEnabled()) {
    return false;
  }

  return (le_advertising_manager_ && le_advertising_manager_->advertising());
}

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::ResultFunction<> callback) {
  // TODO(https://fxbug.dev/42116852): set the public LE advertisement name from
  // |name| If BrEdr is not supported, skip the name update.
  if (!bredr_discovery_manager_) {
    callback(ToResult(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::ResultFunction<> callback) {
  auto write_dev_class = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::WriteClassOfDeviceCommandWriter>(
      hci_spec::kWriteClassOfDevice);
  write_dev_class.view_t().class_of_device().BackingStorage().WriteUInt(
      dev_class.to_int());
  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.ToResult());
      });
}

void AdapterImpl::GetSupportedDelayRange(
    std::unique_ptr<bt::StaticPacket<pw::bluetooth::emboss::CodecIdWriter>>
        codec_id,
    pw::bluetooth::emboss::LogicalTransportType logical_transport_type,
    pw::bluetooth::emboss::DataPathDirection direction,
    std::optional<std::vector<uint8_t>> codec_configuration,
    fit::function<void(zx_status_t, uint32_t, uint32_t)> cb) {
  if (!state_.IsCommandSupported(
          /*octet=*/45,
          hci_spec::SupportedCommand::kReadLocalSupportedControllerDelay)) {
    bt_log(WARN,
           "gap",
           "read local supported controller delay command not supported");
    cb(ZX_ERR_NOT_SUPPORTED, /*min=*/0, /*max=*/0);
    return;
  }
  bt_log(INFO, "gap", "retrieving controller codec delay");
  size_t codec_configuration_size = 0;
  if (codec_configuration.has_value()) {
    codec_configuration_size = codec_configuration->size();
  }
  size_t packet_size =
      pw::bluetooth::emboss::ReadLocalSupportedControllerDelayCommand::
          MinSizeInBytes() +
      codec_configuration_size;
  auto cmd_packet = hci::EmbossCommandPacket::New<
      pw::bluetooth::emboss::ReadLocalSupportedControllerDelayCommandWriter>(
      hci_spec::kReadLocalSupportedControllerDelay, packet_size);
  auto cmd_view = cmd_packet.view_t();
  cmd_view.codec_id().CopyFrom(codec_id->view());
  cmd_view.logical_transport_type().Write(logical_transport_type);
  cmd_view.direction().Write(direction);
  cmd_view.codec_configuration_length().Write(codec_configuration_size);
  if (codec_configuration.has_value()) {
    std::memcpy(cmd_view.codec_configuration().BackingStorage().data(),
                codec_configuration->data(),
                codec_configuration_size);
  }

  hci_->command_channel()->SendCommand(
      std::move(cmd_packet),
      [cb = std::move(cb)](auto /*id*/, const hci::EmbossEventPacket& event) {
        auto view = event.view<
            pw::bluetooth::emboss::
                ReadLocalSupportedControllerDelayCommandCompleteEventView>();
        if (hci_is_error(event,
                         WARN,
                         "gap",
                         "read local supported controller delay failed")) {
          cb(ZX_ERR_INTERNAL, /*min=*/0, /*max=*/0);
          return;
        }
        bt_log(INFO, "gap", "controller delay read successfully");
        cb(ZX_OK,
           view.min_controller_delay().Read(),
           view.max_controller_delay().Read());
      });
}

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::ParseLEGetVendorCapabilitiesCommandComplete(
    const hci::EmbossEventPacket& event) {
  // NOTE: There can be various versions of this command complete event
  // sent by the Controller. As fields are added, the version_supported
  // field is incremented to signify which fields are available. In a previous
  // undertaking (pwrev.dev/203950, fxrev.dev/1029396), we attempted to use
  // Emboss' conditional fields feature to define fields based on the version
  // they are included in. However, in practice, we've found vendors sometimes
  // send the wrong number of bytes required for the version they claim to send.
  // To tolerate these types of errors, we simply define all the fields in
  // Emboss. If we receive a response smaller than what we expect, we use what
  // the vendor sends, and fill the rest with zero to disable the feature. If we
  // receive a response larger than what we expect, we read up to what we
  // support and drop the rest of the data.
  StaticPacket<android_emb::LEGetVendorCapabilitiesCommandCompleteEventView>
      packet;
  packet.SetToZeros();
  size_t copy_size = std::min(packet.data().size(), event.size());
  packet.mutable_data().Write(event.data().data(), copy_size);

  auto params = packet.view();
  state_.android_vendor_capabilities = AndroidVendorCapabilities::New(params);

  size_t expected_size = 0;
  uint8_t major = params.version_supported().major_number().Read();
  uint8_t minor = params.version_supported().minor_number().Read();

  if (major == 0 && minor == 0) {
    // The version_supported field was only introduced into the command in
    // Version 0.95. Controllers that use the base version, Version 0.55,
    // don't have the version_supported field.
    expected_size = android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
        version_0_55_size();
  } else if (major == 0 && minor == 95) {
    expected_size = android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
        version_0_95_size();
  } else if (major == 0 && minor == 96) {
    expected_size = android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
        version_0_96_size();
  } else if (major == 0 && minor == 98) {
    expected_size = android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
        version_0_98_size();
  } else if (major == 1 && minor == 03) {
    expected_size = android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
        version_1_03_size();
  } else if (major == 1 && minor == 04) {
    expected_size = android_emb::LEGetVendorCapabilitiesCommandCompleteEvent::
        version_1_04_size();
  }

  if (event.size() != expected_size) {
    bt_log(WARN,
           "gap",
           "LE Get Vendor Capabilities Command Complete, received %zu bytes, "
           "expected %zu bytes, version: %d.%d",
           event.size(),
           expected_size,
           major,
           minor);
  }
}

void AdapterImpl::InitializeStep1() {
  state_.controller_features = hci_->GetFeatures();

  // 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
  auto reset_command =
      hci::EmbossCommandPacket::New<pw::bluetooth::emboss::ResetCommandWriter>(
          hci_spec::kReset);
  init_seq_runner_->QueueCommand(std::move(reset_command));

  // HCI_Read_Local_Version_Information
  init_seq_runner_->QueueCommand(
      hci::EmbossCommandPacket::New<
          pw::bluetooth::emboss::ReadLocalVersionInformationCommandView>(
          hci_spec::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_spec::ReadLocalVersionInfoReturnParams>();
        state_.hci_version = params->hci_version;
      });

  // HCI_Read_Local_Supported_Commands
  init_seq_runner_->QueueCommand(
      hci::EmbossCommandPacket::New<
          pw::bluetooth::emboss::ReadLocalSupportedCommandsCommandView>(
          hci_spec::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_spec::ReadLocalSupportedCommandsReturnParams>();
        std::memcpy(state_.supported_commands,
                    params->supported_commands,
                    sizeof(params->supported_commands));
      });

  // HCI_Read_Local_Supported_Features
  InitQueueReadLMPFeatureMaskPage(0);

  // HCI_Read_BD_ADDR
  init_seq_runner_->QueueCommand(
      hci::EmbossCommandPacket::New<
          pw::bluetooth::emboss::ReadBdAddrCommandView>(hci_spec::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_spec::ReadBDADDRReturnParams>();
        state_.controller_address = params->bd_addr;
      });

  if (state().IsControllerFeatureSupported(
          pw::bluetooth::Controller::FeaturesBits::kAndroidVendorExtensions)) {
    bt_log(INFO,
           "gap",
           "controller supports android hci extensions, querying exact feature "
           "set");
    init_seq_runner_->QueueCommand(
        hci::EmbossCommandPacket::New<
            android_emb::LEGetVendorCapabilitiesCommandView>(
            android_hci::kLEGetVendorCapabilities),
        [this](const hci::EmbossEventPacket& event) {
          if (hci_is_error(
                  event,
                  WARN,
                  "gap",
                  "Failed to query android hci extension capabilities")) {
            return;
          }

          ParseLEGetVendorCapabilitiesCommandComplete(event);
        });
  }

  init_seq_runner_->RunCommands([this](hci::Result<> status) mutable {
    if (bt_is_error(status,
                    ERROR,
                    "gap",
                    "Failed to obtain initial controller information: %s",
                    bt_str(status))) {
      CompleteInitialization(/*success=*/false);
      return;
    }

    InitializeStep2();
  });
}

void AdapterImpl::InitializeStep2() {
  BT_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");
    CompleteInitialization(/*success=*/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 <
      pw::bluetooth::emboss::CoreSpecificationVersion::V4_2) {
    bt_log(WARN,
           "gap",
           "controller is using legacy HCI version %s",
           hci_spec::HCIVersionToString(state_.hci_version).c_str());
  }

  BT_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(/*octet=*/14,
                                hci_spec::SupportedCommand::kReadBufferSize)) {
    // HCI_Read_Buffer_Size
    init_seq_runner_->QueueCommand(
        hci::EmbossCommandPacket::New<
            pw::bluetooth::emboss::ReadBufferSizeCommandView>(
            hci_spec::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_spec::ReadBufferSizeReturnParams>();
          uint16_t acl_mtu = le16toh(params->hc_acl_data_packet_length);
          uint16_t acl_max_count =
              le16toh(params->hc_total_num_acl_data_packets);
          if (acl_mtu && acl_max_count) {
            state_.bredr_data_buffer_info =
                hci::DataBufferInfo(acl_mtu, acl_max_count);
          }
          uint16_t sco_mtu = le16toh(params->hc_synchronous_data_packet_length);
          uint16_t sco_max_count =
              le16toh(params->hc_total_num_synchronous_data_packets);
          if (sco_mtu && sco_max_count) {
            state_.sco_buffer_info =
                hci::DataBufferInfo(sco_mtu, sco_max_count);
          }
        });
  }

  // HCI_LE_Read_Local_Supported_Features
  init_seq_runner_->QueueCommand(
      hci::EmbossCommandPacket::New<
          pw::bluetooth::emboss::LEReadLocalSupportedFeaturesCommandView>(
          hci_spec::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_spec::LEReadLocalSupportedFeaturesReturnParams>();
        state_.low_energy_state.supported_features_ =
            le64toh(params->le_features);
      });

  // HCI_LE_Read_Supported_States
  init_seq_runner_->QueueCommand(
      hci::EmbossCommandPacket::New<
          pw::bluetooth::emboss::LEReadSupportedStatesCommandView>(
          hci_spec::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_spec::LEReadSupportedStatesReturnParams>();
        state_.low_energy_state.supported_states_ = le64toh(params->le_states);
      });

  if (state_.IsCommandSupported(
          /*octet=*/36,
          hci_spec::SupportedCommand::kLEReadMaximumAdvertisingDataLength)) {
    // HCI_LE_Read_Maximum_Advertising_Data_Length
    init_seq_runner_->QueueCommand(
        hci::EmbossCommandPacket::New<
            pw::bluetooth::emboss::LEReadMaxAdvertisingDataLengthCommandView>(
            hci_spec::kLEReadMaximumAdvertisingDataLength),
        [this](const hci::EmbossEventPacket& cmd_complete) {
          if (hci_is_error(cmd_complete,
                           WARN,
                           "gap",
                           "LE read maximum advertising data length failed")) {
            return;
          }

          auto params = cmd_complete.view<
              pw::bluetooth::emboss::
                  LEReadMaximumAdvertisingDataLengthCommandCompleteEventView>();
          state_.low_energy_state.max_advertising_data_length_ =
              params.max_advertising_data_length().Read();
          bt_log(INFO,
                 "gap",
                 "maximum advertising data length: %d",
                 state_.low_energy_state.max_advertising_data_length_);
        });
  } else {
    bt_log(INFO,
           "gap",
           "LE read maximum advertising data command not supported, "
           "defaulting to legacy maximum: %zu",
           hci_spec::kMaxLEAdvertisingDataLength);
    state_.low_energy_state.max_advertising_data_length_ =
        hci_spec::kMaxLEAdvertisingDataLength;
  }

  if (state_.IsCommandSupported(
          /*octet=*/41, hci_spec::SupportedCommand::kLEReadBufferSizeV2)) {
    // HCI_LE_Read_Buffer_Size [v2]
    init_seq_runner_->QueueCommand(
        hci::EmbossCommandPacket::New<
            pw::bluetooth::emboss::LEReadBufferSizeCommandV2View>(
            hci_spec::kLEReadBufferSizeV2),
        [this](const hci::EmbossEventPacket& cmd_complete) {
          if (hci_is_error(cmd_complete,
                           WARN,
                           "gap",
                           "LE read buffer size [v2] failed")) {
            return;
          }
          auto params =
              cmd_complete
                  .view<pw::bluetooth::emboss::
                            LEReadBufferSizeV2CommandCompleteEventView>();
          uint16_t acl_mtu = params.le_acl_data_packet_length().Read();
          uint8_t acl_max_count = params.total_num_le_acl_data_packets().Read();
          if (acl_mtu && acl_max_count) {
            state_.low_energy_state.acl_data_buffer_info_ =
                hci::DataBufferInfo(acl_mtu, acl_max_count);
          }
          uint16_t iso_mtu = params.iso_data_packet_length().Read();
          uint8_t iso_max_count = params.total_num_iso_data_packets().Read();
          if (iso_mtu && iso_max_count) {
            state_.low_energy_state.iso_data_buffer_info_ =
                hci::DataBufferInfo(iso_mtu, iso_max_count);
          }
        });
  } else {
    // HCI_LE_Read_Buffer_Size [v1]
    init_seq_runner_->QueueCommand(
        hci::EmbossCommandPacket::New<
            pw::bluetooth::emboss::LEReadBufferSizeCommandV1View>(
            hci_spec::kLEReadBufferSizeV1),
        [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_spec::LEReadBufferSizeV1ReturnParams>();
          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_.low_energy_state.acl_data_buffer_info_ =
                hci::DataBufferInfo(mtu, max_count);
          }
        });
  }

  if (state_.features.HasBit(
          /*page=*/0u,
          hci_spec::LMPFeature::kSecureSimplePairingControllerSupport)) {
    // HCI_Write_Simple_Pairing_Mode
    auto write_spm = hci::EmbossCommandPacket::New<
        pw::bluetooth::emboss::WriteSimplePairingModeCommandWriter>(
        hci_spec::kWriteSimplePairingMode);
    auto write_ssp_params = write_spm.view_t();
    write_ssp_params.simple_pairing_mode().Write(
        pw::bluetooth::emboss::GenericEnableParam::ENABLE);
    init_seq_runner_->QueueCommand(
        std::move(write_spm), [](const hci::EventPacket& 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(/*page=*/0u,
                             hci_spec::LMPFeature::kExtendedFeatures)) {
    // HCI_Write_LE_Host_Support
    if (!state_.IsCommandSupported(
            /*octet=*/24, hci_spec::SupportedCommand::kWriteLEHostSupport)) {
      bt_log(INFO, "gap", "LE Host is not supported");
    } else {
      bt_log(INFO, "gap", "LE Host is supported. Enabling LE Host mode");
      auto cmd_packet = hci::EmbossCommandPacket::New<
          pw::bluetooth::emboss::WriteLEHostSupportCommandWriter>(
          hci_spec::kWriteLEHostSupport);
      auto params = cmd_packet.view_t();
      params.le_supported_host().Write(
          pw::bluetooth::emboss::GenericEnableParam::ENABLE);
      init_seq_runner_->QueueCommand(
          std::move(cmd_packet), [](const hci::EventPacket& event) {
            hci_is_error(event, WARN, "gap", "Write LE Host support failed");
          });
    }

    // HCI_Write_Secure_Connections_Host_Support
    if (!state_.IsCommandSupported(
            /*octet=*/32,
            hci_spec::SupportedCommand::kWriteSecureConnectionsHostSupport)) {
      bt_log(INFO, "gap", "Secure Connections (Host Support) is not supported");
    } else {
      bt_log(INFO,
             "gap",
             "Secure Connections (Host Support) is supported. "
             "Enabling Secure Connections (Host Support) mode");
      auto cmd_packet = hci::EmbossCommandPacket::New<
          pw::bluetooth::emboss::
              WriteSecureConnectionsHostSupportCommandWriter>(
          hci_spec::kWriteSecureConnectionsHostSupport);
      auto params = cmd_packet.view_t();
      params.secure_connections_host_support().Write(
          pw::bluetooth::emboss::GenericEnableParam::ENABLE);
      init_seq_runner_->QueueCommand(
          std::move(cmd_packet), [](const hci::EventPacket& event) {
            hci_is_error(event,
                         WARN,
                         "gap",
                         "Write Secure Connections (Host Support) failed");
          });
    }

    // Read updated page 1 after host support bits enabled.
    InitQueueReadLMPFeatureMaskPage(1);
  }

  init_seq_runner_->RunCommands([this](hci::Result<> status) mutable {
    if (bt_is_error(
            status,
            ERROR,
            "gap",
            "failed to obtain initial controller information (step 2)")) {
      CompleteInitialization(/*success=*/false);
      return;
    }
    InitializeStep3();
  });
}

void AdapterImpl::InitializeStep3() {
  BT_ASSERT(IsInitializing());
  BT_ASSERT(init_seq_runner_->IsReady());
  BT_ASSERT(!init_seq_runner_->HasQueuedCommands());

  if (!state_.bredr_data_buffer_info.IsAvailable() &&
      !state_.low_energy_state.acl_data_buffer_info().IsAvailable()) {
    bt_log(ERROR, "gap", "Both BR/EDR and LE buffers are unavailable");
    CompleteInitialization(/*success=*/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.acl_data_buffer_info())) {
    bt_log(ERROR, "gap", "Failed to initialize ACLDataChannel (step 3)");
    CompleteInitialization(/*success=*/false);
    return;
  }

  // The controller may not support SCO flow control (as implied by not
  // supporting HCI_Write_Synchronous_Flow_Control_Enable), in which case we
  // don't support HCI SCO on this controller yet.
  // TODO(https://fxbug.dev/42171056): Support controllers that don't support
  // SCO flow control.
  bool sco_flow_control_supported = state_.IsCommandSupported(
      /*octet=*/10,
      hci_spec::SupportedCommand::kWriteSynchronousFlowControlEnable);
  if (state_.sco_buffer_info.IsAvailable() && sco_flow_control_supported) {
    // Enable SCO flow control.
    auto sync_flow_control = hci::EmbossCommandPacket::New<
        pw::bluetooth::emboss::WriteSynchronousFlowControlEnableCommandWriter>(
        hci_spec::kWriteSynchronousFlowControlEnable);
    auto flow_control_params = sync_flow_control.view_t();
    flow_control_params.synchronous_flow_control_enable().Write(
        pw::bluetooth::emboss::GenericEnableParam::ENABLE);
    init_seq_runner_->QueueCommand(
        std::move(sync_flow_control), [this](const hci::EventPacket& event) {
          if (hci_is_error(event,
                           ERROR,
                           "gap",
                           "Write synchronous flow control enable failed, "
                           "proceeding without HCI "
                           "SCO support")) {
            return;
          }

          if (!hci_->InitializeScoDataChannel(state_.sco_buffer_info)) {
            bt_log(WARN,
                   "gap",
                   "Failed to initialize ScoDataChannel, proceeding without "
                   "HCI SCO support");
            return;
          }
          bt_log(DEBUG, "gap", "ScoDataChannel initialized successfully");
        });
  } else {
    bt_log(INFO,
           "gap",
           "HCI SCO not supported (SCO buffer available: %d, SCO flow control "
           "supported: %d)",
           state_.sco_buffer_info.IsAvailable(),
           sco_flow_control_supported);
  }

  hci_->AttachInspect(adapter_node_);

  // Create ChannelManager, if we haven't been provided one for testing. Doing
  // so here lets us guarantee that AclDataChannel's lifetime is a superset of
  // ChannelManager's lifetime.
  if (!l2cap_) {
    // Initialize ChannelManager to make it available for the next
    // initialization step. The AclDataChannel must be initialized before
    // creating ChannelManager.
    l2cap_ = l2cap::ChannelManager::Create(hci_->acl_data_channel(),
                                           hci_->command_channel(),
                                           /*random_channel_ids=*/true,
                                           dispatcher_);
    l2cap_->AttachInspect(adapter_node_,
                          l2cap::ChannelManager::kInspectNodeName);
  }

  // HCI_Set_Event_Mask
  {
    uint64_t event_mask = BuildEventMask();
    auto set_event = hci::EmbossCommandPacket::New<
        pw::bluetooth::emboss::SetEventMaskCommandWriter>(
        hci_spec::kSetEventMask);
    auto set_event_params = set_event.view_t();
    set_event_params.event_mask().Write(event_mask);
    init_seq_runner_->QueueCommand(
        std::move(set_event), [](const hci::EventPacket& 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::EmbossCommandPacket::New<
        pw::bluetooth::emboss::LESetEventMaskCommandWriter>(
        hci_spec::kLESetEventMask);
    cmd_packet.view_t().le_event_mask().BackingStorage().WriteUInt(event_mask);
    init_seq_runner_->QueueCommand(
        std::move(cmd_packet), [](const hci::EventPacket& event) {
          hci_is_error(event, WARN, "gap", "LE set event mask failed");
        });
  }

  // If page 2 of the extended features bitfield is available, read it
  if (max_lmp_feature_page_index_.has_value() &&
      max_lmp_feature_page_index_.value() > 1) {
    InitQueueReadLMPFeatureMaskPage(2);
  }

  init_seq_runner_->RunCommands([this](hci::Result<> status) mutable {
    if (bt_is_error(
            status,
            ERROR,
            "gap",
            "failed to obtain initial controller information (step 3)")) {
      CompleteInitialization(/*success=*/false);
      return;
    }
    InitializeStep4();
  });
}

void AdapterImpl::InitializeStep4() {
  // Initialize the scan manager and low energy adapters based on current
  // feature support
  BT_DEBUG_ASSERT(IsInitializing());

  // 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<&AdapterImpl::IsLeRandomAddressChangeAllowed>(this),
      hci_->command_channel()->AsWeakPtr(),
      dispatcher_);

  // Initialize the HCI adapters. Note: feature support for extended
  // scanning, connections, etc are all grouped under the extended advertising
  // feature flag.
  bool extended = state().low_energy_state.IsFeatureSupported(
      hci_spec::LESupportedFeature::kLEExtendedAdvertising);
  bt_log(INFO,
         "gap",
         "controller support for extended operations: %s",
         extended ? "yes" : "no");
  hci_le_advertiser_ = CreateAdvertiser(extended);
  hci_le_connector_ = CreateConnector(extended);
  hci_le_scanner_ = CreateScanner(extended);

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

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

  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_.get(),
        state_.features.HasBit(/*page=*/0,
                               hci_spec::LMPFeature::kInterlacedPageScan),
        state_.IsLocalSecureConnectionsSupported(),
        dispatcher_);
    bredr_connection_manager_->AttachInspect(
        adapter_node_, kInspectBrEdrConnectionManagerNodeName);

    pw::bluetooth::emboss::InquiryMode mode =
        pw::bluetooth::emboss::InquiryMode::STANDARD;
    if (state_.features.HasBit(
            /*page=*/0, hci_spec::LMPFeature::kExtendedInquiryResponse)) {
      mode = pw::bluetooth::emboss::InquiryMode::EXTENDED;
    } else if (state_.features.HasBit(
                   /*page=*/0, hci_spec::LMPFeature::kRSSIwithInquiryResults)) {
      mode = pw::bluetooth::emboss::InquiryMode::RSSI;
    }

    bredr_discovery_manager_ = std::make_unique<BrEdrDiscoveryManager>(
        dispatcher_, hci_->command_channel()->AsWeakPtr(), mode, &peer_cache_);
    bredr_discovery_manager_->AttachInspect(
        adapter_node_, kInspectBrEdrDiscoveryManagerNodeName);

    sdp_server_ = std::make_unique<sdp::Server>(l2cap_.get());
    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(https://fxbug.dev/42141593): 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_self_.GetWeakPtr();
  SetLocalName(kDefaultLocalName, [self](auto status) mutable {
    // Set the default device class - a computer with audio.
    // TODO(https://fxbug.dev/42074312): set this from a platform configuration
    // file
    DeviceClass dev_class(DeviceClass::MajorClass::kComputer);
    dev_class.SetServiceClasses({DeviceClass::ServiceClass::kAudio});
    self->SetDeviceClass(dev_class, [self](const auto&) {
      self->CompleteInitialization(/*success=*/true);
    });
  });
}

bool AdapterImpl::CompleteInitialization(bool success) {
  if (!init_cb_) {
    return false;
  }

  if (success) {
    init_state_ = State::kInitialized;
  } else {
    CleanUp();
  }

  init_cb_(success);
  return true;
}

void AdapterImpl::InitQueueReadLMPFeatureMaskPage(uint8_t page) {
  BT_DEBUG_ASSERT(init_seq_runner_);
  BT_DEBUG_ASSERT(init_seq_runner_->IsReady());

  if (max_lmp_feature_page_index_.has_value() &&
      page > max_lmp_feature_page_index_.value()) {
    bt_log(WARN,
           "gap",
           "Maximum value of LMP features mask page is %lu. Received page %hu",
           max_lmp_feature_page_index_.value(),
           page);
    return;
  }

  if (page == 0) {
    init_seq_runner_->QueueCommand(
        hci::EmbossCommandPacket::New<
            pw::bluetooth::emboss::ReadLocalSupportedFeaturesCommandView>(
            hci_spec::kReadLocalSupportedFeatures),
        [this, page](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_spec::ReadLocalSupportedFeaturesReturnParams>();
          state_.features.SetPage(page, le64toh(params->lmp_features));
        });
    return;
  }

  if (!state_.features.HasBit(/*page=*/0u,
                              hci_spec::LMPFeature::kExtendedFeatures)) {
    bt_log(WARN, "gap", "LMP features mask does not have extended features");
    max_lmp_feature_page_index_ = 0;
    return;
  }

  if (!max_lmp_feature_page_index_.has_value() ||
      page <= max_lmp_feature_page_index_.value()) {
    // HCI_Read_Local_Extended_Features
    auto cmd_packet = hci::EmbossCommandPacket::New<
        pw::bluetooth::emboss::ReadLocalExtendedFeaturesCommandWriter>(
        hci_spec::kReadLocalExtendedFeatures);
    cmd_packet.view_t().page_number().Write(page);  // Try to read |page|

    init_seq_runner_->QueueCommand(
        std::move(cmd_packet),
        [this, page](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_spec::ReadLocalExtendedFeaturesReturnParams>();
          state_.features.SetPage(page, le64toh(params->extended_lmp_features));
          max_lmp_feature_page_index_ = params->maximum_page_number;
        });
  }
}

void AdapterImpl::UpdateInspectProperties() {
  inspect_properties_.adapter_id =
      adapter_node_.CreateString("adapter_id", identifier_.ToString());
  inspect_properties_.hci_version = adapter_node_.CreateString(
      "hci_version", hci_spec::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.acl_data_buffer_info().max_num_packets());
  inspect_properties_.le_max_data_length = adapter_node_.CreateUint(
      "le_max_data_length",
      state_.low_energy_state.acl_data_buffer_info().max_data_length());

  inspect_properties_.sco_max_num_packets = adapter_node_.CreateUint(
      "sco_max_num_packets", state_.sco_buffer_info.max_num_packets());
  inspect_properties_.sco_max_data_length = adapter_node_.CreateUint(
      "sco_max_data_length", state_.sco_buffer_info.max_data_length());

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

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

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

  init_state_ = State::kNotInitialized;
  state_ = AdapterState();
  transport_error_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_.reset();
}

void AdapterImpl::OnTransportError() {
  bt_log(INFO, "gap", "HCI transport error");
  if (CompleteInitialization(/*success=*/false)) {
    return;
  }
  if (transport_error_cb_) {
    transport_error_cb_();
  }
}

void AdapterImpl::OnLeAutoConnectRequest(Peer* peer) {
  BT_DEBUG_ASSERT(le_connection_manager_);
  BT_DEBUG_ASSERT(peer);
  BT_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_self_.GetWeakPtr();
  le_connection_manager_->Connect(
      peer_id,
      [self, peer_id](auto result) {
        if (!self.is_alive()) {
          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_value()).c_str());
          return;
        }

        auto conn = std::move(result).value();
        BT_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(
    pw::async::Dispatcher& pw_dispatcher,
    hci::Transport::WeakPtr hci,
    gatt::GATT::WeakPtr gatt,
    std::unique_ptr<l2cap::ChannelManager> l2cap) {
  return std::make_unique<AdapterImpl>(
      pw_dispatcher, hci, gatt, std::move(l2cap));
}

}  // namespace bt::gap
