// 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 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::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
