// Copyright 2022 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/transport/sco_data_channel.h"

#include <lib/gtest/test_loop_fixture.h>

#include <gtest/gtest.h>

#include "src/connectivity/bluetooth/core/bt-host/common/test_helpers.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/controller_test.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/mock_controller.h"
#include "src/connectivity/bluetooth/core/bt-host/testing/test_packets.h"

namespace bt::hci {
namespace {

constexpr hci_spec::ConnectionHandle kConnectionHandle0 = 0x0000;
constexpr hci_spec::ConnectionHandle kConnectionHandle1 = 0x0001;
constexpr size_t kBufferMaxNumPackets = 2;

constexpr hci_spec::SynchronousConnectionParameters kMsbcConnectionParameters{
    .transmit_bandwidth = 0,
    .receive_bandwidth = 0,
    .transmit_coding_format =
        hci_spec::VendorCodingFormat{
            .coding_format = hci_spec::CodingFormat::kMSbc,
            .company_id = 0,
            .vendor_codec_id = 0,
        },
    .receive_coding_format =
        hci_spec::VendorCodingFormat{
            .coding_format = hci_spec::CodingFormat::kMSbc,
            .company_id = 0,
            .vendor_codec_id = 0,
        },
    .transmit_codec_frame_size_bytes = 0,
    .receive_codec_frame_size_bytes = 0,
    .input_bandwidth = 32000,
    .output_bandwidth = 32000,
    .input_coding_format =
        hci_spec::VendorCodingFormat{
            .coding_format = hci_spec::CodingFormat::kMSbc,
            .company_id = 0,
            .vendor_codec_id = 0,
        },
    .output_coding_format =
        hci_spec::VendorCodingFormat{
            .coding_format = hci_spec::CodingFormat::kMSbc,
            .company_id = 0,
            .vendor_codec_id = 0,
        },
    .input_coded_data_size_bits = 16,
    .output_coded_data_size_bits = 16,
    .input_pcm_data_format = hci_spec::PcmDataFormat::kUnsigned,
    .output_pcm_data_format = hci_spec::PcmDataFormat::kUnsigned,
    .input_pcm_sample_payload_msb_position = 0,
    .output_pcm_sample_payload_msb_position = 0,
    .input_data_path = hci_spec::ScoDataPath::kHci,
    .output_data_path = hci_spec::ScoDataPath::kHci,
    .input_transport_unit_size_bits = 0,
    .output_transport_unit_size_bits = 0,
    .max_latency_ms = 0,
    .packet_types = 0,
    .retransmission_effort = hci_spec::ScoRetransmissionEffort::kNone,
};

constexpr hci_spec::SynchronousConnectionParameters kCvsdConnectionParameters{
    .transmit_bandwidth = 0,
    .receive_bandwidth = 0,
    .transmit_coding_format =
        hci_spec::VendorCodingFormat{
            .coding_format = hci_spec::CodingFormat::kCvsd,
            .company_id = 0,
            .vendor_codec_id = 0,
        },
    .receive_coding_format =
        hci_spec::VendorCodingFormat{
            .coding_format = hci_spec::CodingFormat::kCvsd,
            .company_id = 0,
            .vendor_codec_id = 0,
        },
    .transmit_codec_frame_size_bytes = 0,
    .receive_codec_frame_size_bytes = 0,
    .input_bandwidth = 8000,
    .output_bandwidth = 8000,
    .input_coding_format =
        hci_spec::VendorCodingFormat{
            .coding_format = hci_spec::CodingFormat::kCvsd,
            .company_id = 0,
            .vendor_codec_id = 0,
        },
    .output_coding_format =
        hci_spec::VendorCodingFormat{
            .coding_format = hci_spec::CodingFormat::kCvsd,
            .company_id = 0,
            .vendor_codec_id = 0,
        },
    .input_coded_data_size_bits = 8,
    .output_coded_data_size_bits = 8,
    .input_pcm_data_format = hci_spec::PcmDataFormat::kUnsigned,
    .output_pcm_data_format = hci_spec::PcmDataFormat::kUnsigned,
    .input_pcm_sample_payload_msb_position = 0,
    .output_pcm_sample_payload_msb_position = 0,
    .input_data_path = hci_spec::ScoDataPath::kHci,
    .output_data_path = hci_spec::ScoDataPath::kHci,
    .input_transport_unit_size_bits = 0,
    .output_transport_unit_size_bits = 0,
    .max_latency_ms = 0,
    .packet_types = 0,
    .retransmission_effort = hci_spec::ScoRetransmissionEffort::kNone,
};

class FakeScoConnection : public ScoDataChannel::ConnectionInterface {
 public:
  explicit FakeScoConnection(
      ScoDataChannel* data_channel, hci_spec::ConnectionHandle handle = kConnectionHandle0,
      hci_spec::SynchronousConnectionParameters params = kMsbcConnectionParameters)
      : handle_(handle), params_(params), data_channel_(data_channel), weak_ptr_factory_(this) {}

  ~FakeScoConnection() override = default;

  void QueuePacket(std::unique_ptr<ScoDataPacket> packet) {
    queued_packets_.push(std::move(packet));
    data_channel_->OnOutboundPacketReadable();
  }

  const std::vector<std::unique_ptr<ScoDataPacket>>& received_packets() const {
    return received_packets_;
  }
  const std::queue<std::unique_ptr<ScoDataPacket>>& queued_packets() const {
    return queued_packets_;
  }

  uint16_t hci_error_count() const { return hci_error_count_; }

  fxl::WeakPtr<FakeScoConnection> GetWeakPtr() { return weak_ptr_factory_.GetWeakPtr(); }

  // ScoDataChannel::ConnectionInterface overrides:

  hci_spec::ConnectionHandle handle() const override { return handle_; }

  hci_spec::SynchronousConnectionParameters parameters() override { return params_; }

  std::unique_ptr<ScoDataPacket> GetNextOutboundPacket() override {
    if (queued_packets_.empty()) {
      return nullptr;
    }
    std::unique_ptr<ScoDataPacket> packet = std::move(queued_packets_.front());
    queued_packets_.pop();
    return packet;
  }

  void ReceiveInboundPacket(std::unique_ptr<ScoDataPacket> packet) override {
    received_packets_.push_back(std::move(packet));
  }

  void OnHciError() override { hci_error_count_++; }

 private:
  hci_spec::ConnectionHandle handle_;
  hci_spec::SynchronousConnectionParameters params_;
  std::queue<std::unique_ptr<ScoDataPacket>> queued_packets_;
  std::vector<std::unique_ptr<ScoDataPacket>> received_packets_;
  ScoDataChannel* data_channel_;
  uint16_t hci_error_count_ = 0;
  fxl::WeakPtrFactory<FakeScoConnection> weak_ptr_factory_;
};

using TestingBase = bt::testing::ControllerTest<bt::testing::MockController>;
class ScoDataChannelTest : public TestingBase {
 public:
  void SetUp() override {
    TestingBase::SetUp();
    StartTestDevice();

    DataBufferInfo buffer_info(/*max_data_length=*/10, kBufferMaxNumPackets);
    InitializeScoDataChannel(buffer_info);
  }
};

class ScoDataChannelSingleConnectionTest : public ScoDataChannelTest {
 public:
  void SetUp() override {
    ScoDataChannelTest::SetUp();

    set_configure_sco_cb([this](ScoCodingFormat format, ScoEncoding encoding, ScoSampleRate rate,
                                HciWrapper::StatusCallback callback) {
      config_count_++;
      EXPECT_EQ(format, ScoCodingFormat::kMsbc);
      EXPECT_EQ(encoding, ScoEncoding::k16Bits);
      EXPECT_EQ(rate, ScoSampleRate::k16Khz);
      callback(ZX_OK);
    });

    set_reset_sco_cb([this](HciWrapper::StatusCallback callback) {
      reset_count_++;
      callback(ZX_OK);
    });

    connection_.emplace(sco_data_channel());

    sco_data_channel()->RegisterConnection(connection_->GetWeakPtr());
    EXPECT_EQ(config_count_, 1);
    EXPECT_EQ(reset_count_, 0);
  }

  void TearDown() override {
    sco_data_channel()->UnregisterConnection(connection_->handle());
    EXPECT_EQ(config_count_, 1);
    EXPECT_EQ(reset_count_, 1);
    set_configure_sco_cb(nullptr);
    set_reset_sco_cb(nullptr);
    ScoDataChannelTest::TearDown();
  }

  FakeScoConnection* connection() { return &connection_.value(); }

 private:
  std::optional<FakeScoConnection> connection_;
  int config_count_ = 0;
  int reset_count_ = 0;
};

TEST_F(ScoDataChannelSingleConnectionTest, SendManyMsbcPackets) {
  // Queue 1 more than than the max number of packets (1 packet will remain queued).
  for (size_t i = 0; i <= kBufferMaxNumPackets; i++) {
    std::unique_ptr<ScoDataPacket> packet =
        ScoDataPacket::New(kConnectionHandle0, /*payload_size=*/1);
    packet->mutable_view()->mutable_payload_data()[0] = static_cast<uint8_t>(i);

    // The last packet should remain queued.
    if (i < kBufferMaxNumPackets) {
      EXPECT_SCO_PACKET_OUT(test_device(), StaticByteBuffer(LowerBits(kConnectionHandle0),
                                                            UpperBits(kConnectionHandle0),
                                                            0x01,  // payload length
                                                            static_cast<uint8_t>(i)));
    }
    connection()->QueuePacket(std::move(packet));
    RunLoopUntilIdle();
  }

  EXPECT_TRUE(test_device()->AllExpectedScoPacketsSent());

  EXPECT_SCO_PACKET_OUT(
      test_device(), StaticByteBuffer(LowerBits(kConnectionHandle0), UpperBits(kConnectionHandle0),
                                      0x01,  // payload length
                                      static_cast<uint8_t>(kBufferMaxNumPackets)));
  test_device()->SendCommandChannelPacket(
      bt::testing::NumberOfCompletedPacketsPacket(kConnectionHandle0, 1));
  RunLoopUntilIdle();
  EXPECT_TRUE(test_device()->AllExpectedScoPacketsSent());
}

TEST_F(ScoDataChannelSingleConnectionTest, ReceiveManyPackets) {
  for (uint8_t i = 0; i < 20; i++) {
    SCOPED_TRACE(i);
    StaticByteBuffer packet(LowerBits(kConnectionHandle0), UpperBits(kConnectionHandle0),
                            0x01,  // payload length
                            i      // payload
    );
    test_device()->SendScoDataChannelPacket(packet);
    RunLoopUntilIdle();
    ASSERT_EQ(connection()->received_packets().size(), static_cast<size_t>(i) + 1);
    EXPECT_TRUE(ContainersEqual(connection()->received_packets()[i]->view().data(), packet));
  }
}

TEST_F(ScoDataChannelTest, RegisterTwoConnectionsAndUnregisterFirstConnection) {
  int config_count = 0;
  set_configure_sco_cb([&](auto, auto, auto, HciWrapper::StatusCallback callback) {
    config_count++;
    callback(ZX_OK);
  });

  int reset_count = 0;
  set_reset_sco_cb([&](HciWrapper::StatusCallback callback) {
    reset_count++;
    callback(ZX_OK);
  });

  FakeScoConnection connection_0(sco_data_channel());
  sco_data_channel()->RegisterConnection(connection_0.GetWeakPtr());
  EXPECT_EQ(config_count, 1);
  EXPECT_EQ(reset_count, 0);

  FakeScoConnection connection_1(sco_data_channel(), kConnectionHandle1);
  sco_data_channel()->RegisterConnection(connection_1.GetWeakPtr());
  EXPECT_EQ(config_count, 1);
  EXPECT_EQ(reset_count, 0);

  StaticByteBuffer packet_0(LowerBits(kConnectionHandle0), UpperBits(kConnectionHandle0),
                            0x01,  // payload length
                            0x00   // payload
  );
  test_device()->SendScoDataChannelPacket(packet_0);
  RunLoopUntilIdle();
  ASSERT_EQ(connection_0.received_packets().size(), 1u);
  ASSERT_EQ(connection_1.received_packets().size(), 0u);

  StaticByteBuffer packet_1(LowerBits(kConnectionHandle1), UpperBits(kConnectionHandle1),
                            0x01,  // payload length
                            0x01   // payload
  );
  test_device()->SendScoDataChannelPacket(packet_1);
  RunLoopUntilIdle();
  ASSERT_EQ(connection_0.received_packets().size(), 1u);
  // The packet should be received even though connection_1 isn't the active connection.
  ASSERT_EQ(connection_1.received_packets().size(), 1u);

  EXPECT_SCO_PACKET_OUT(test_device(), packet_0);
  std::unique_ptr<ScoDataPacket> out_packet_0 = ScoDataPacket::New(/*payload_size=*/1);
  out_packet_0->mutable_view()->mutable_data().Write(packet_0);
  out_packet_0->InitializeFromBuffer();
  connection_0.QueuePacket(std::move(out_packet_0));
  RunLoopUntilIdle();
  EXPECT_TRUE(test_device()->AllExpectedScoPacketsSent());
  test_device()->SendCommandChannelPacket(
      bt::testing::NumberOfCompletedPacketsPacket(kConnectionHandle0, 1));

  std::unique_ptr<ScoDataPacket> out_packet_1 = ScoDataPacket::New(/*payload_size=*/1);
  out_packet_1->mutable_view()->mutable_data().Write(packet_1);
  out_packet_1->InitializeFromBuffer();
  // The packet should be sent even though connection_1 isn't the active connection.
  EXPECT_SCO_PACKET_OUT(test_device(), packet_1);
  connection_1.QueuePacket(std::move(out_packet_1));
  RunLoopUntilIdle();
  EXPECT_TRUE(test_device()->AllExpectedScoPacketsSent());
  // This is necessary because kBufferMaxNumPackets is 2, so we won't be able to send
  // any more packets until at least 1 is ACKed by the controller.
  test_device()->SendCommandChannelPacket(
      bt::testing::NumberOfCompletedPacketsPacket(kConnectionHandle1, 1));

  // connection_1 should become the active connection (+1 to config_count).
  sco_data_channel()->UnregisterConnection(connection_0.handle());
  EXPECT_EQ(config_count, 2);
  EXPECT_EQ(reset_count, 0);
  RunLoopUntilIdle();

  out_packet_1 = ScoDataPacket::New(/*payload_size=*/1);
  out_packet_1->mutable_view()->mutable_data().Write(packet_1);
  out_packet_1->InitializeFromBuffer();
  // Now that connection_1 is the active connection, packets should still be sent.
  EXPECT_SCO_PACKET_OUT(test_device(), packet_1);
  connection_1.QueuePacket(std::move(out_packet_1));
  RunLoopUntilIdle();
  EXPECT_TRUE(test_device()->AllExpectedScoPacketsSent());

  // There are no active connections now (+1 to reset_count).
  sco_data_channel()->UnregisterConnection(connection_1.handle());
  EXPECT_EQ(config_count, 2);
  EXPECT_EQ(reset_count, 1);
}

TEST_F(ScoDataChannelTest, RegisterTwoConnectionsAndClearControllerPacketCountOfFirstConnection) {
  set_configure_sco_cb(
      [](auto, auto, auto, HciWrapper::StatusCallback callback) { callback(ZX_OK); });

  set_reset_sco_cb([](HciWrapper::StatusCallback callback) { callback(ZX_OK); });

  FakeScoConnection connection_0(sco_data_channel());
  sco_data_channel()->RegisterConnection(connection_0.GetWeakPtr());

  FakeScoConnection connection_1(sco_data_channel(), kConnectionHandle1);
  sco_data_channel()->RegisterConnection(connection_1.GetWeakPtr());

  auto packet_0 = StaticByteBuffer(LowerBits(kConnectionHandle0), UpperBits(kConnectionHandle0),
                                   0x01,  // payload length
                                   0x00   // payload
  );
  auto packet_1 = StaticByteBuffer(LowerBits(kConnectionHandle0), UpperBits(kConnectionHandle0),
                                   0x01,  // payload length
                                   0x01   // payload
  );
  auto packet_2 = StaticByteBuffer(LowerBits(kConnectionHandle1), UpperBits(kConnectionHandle1),
                                   0x01,  // payload length
                                   0x02   // payload
  );

  EXPECT_SCO_PACKET_OUT(test_device(), packet_0);
  std::unique_ptr<ScoDataPacket> out_packet_0 = ScoDataPacket::New(/*payload_size=*/1);
  out_packet_0->mutable_view()->mutable_data().Write(packet_0);
  out_packet_0->InitializeFromBuffer();
  connection_0.QueuePacket(std::move(out_packet_0));
  RunLoopUntilIdle();
  EXPECT_TRUE(test_device()->AllExpectedScoPacketsSent());

  // The second packet should fill up the controller buffer (kBufferMaxNumPackets).
  ASSERT_EQ(kBufferMaxNumPackets, 2u);
  EXPECT_SCO_PACKET_OUT(test_device(), packet_1);
  std::unique_ptr<ScoDataPacket> out_packet_1 = ScoDataPacket::New(/*payload_size=*/1);
  out_packet_1->mutable_view()->mutable_data().Write(packet_1);
  out_packet_1->InitializeFromBuffer();
  connection_0.QueuePacket(std::move(out_packet_1));
  RunLoopUntilIdle();
  EXPECT_TRUE(test_device()->AllExpectedScoPacketsSent());

  std::unique_ptr<ScoDataPacket> out_packet_2 = ScoDataPacket::New(/*payload_size=*/1);
  out_packet_2->mutable_view()->mutable_data().Write(packet_2);
  out_packet_2->InitializeFromBuffer();
  // The packet should NOT be sent because the controller buffer is full.
  connection_1.QueuePacket(std::move(out_packet_2));
  RunLoopUntilIdle();

  // connection_1 should become the active connection, but out_packet_2 can't be sent yet.
  sco_data_channel()->UnregisterConnection(connection_0.handle());
  RunLoopUntilIdle();
  EXPECT_EQ(connection_1.queued_packets().size(), 1u);

  // Clearing the pending packet count for connection_0 should result in packet_2 being sent.
  EXPECT_SCO_PACKET_OUT(test_device(), packet_2);
  sco_data_channel()->ClearControllerPacketCount(connection_0.handle());
  RunLoopUntilIdle();
  EXPECT_TRUE(test_device()->AllExpectedScoPacketsSent());

  // There are no active connections now.
  sco_data_channel()->UnregisterConnection(connection_1.handle());
  sco_data_channel()->ClearControllerPacketCount(connection_1.handle());
  RunLoopUntilIdle();
}

TEST_F(ScoDataChannelSingleConnectionTest, IgnoreInboundPacketForUnknownConnectionHandle) {
  // kConnectionHandle1 is not registered.
  auto packet = StaticByteBuffer(LowerBits(kConnectionHandle1), UpperBits(kConnectionHandle1),
                                 0x01,  // payload length
                                 0x07   // payload
  );
  test_device()->SendScoDataChannelPacket(packet);
  RunLoopUntilIdle();
  EXPECT_EQ(connection()->received_packets().size(), 0u);
}

TEST_F(ScoDataChannelSingleConnectionTest,
       IgnoreNumberOfCompletedPacketsEventForUnknownConnectionHandle) {
  // Queue 1 more than than the max number of packets (1 packet will remain queued).
  for (size_t i = 0; i <= kBufferMaxNumPackets; i++) {
    std::unique_ptr<ScoDataPacket> packet =
        ScoDataPacket::New(kConnectionHandle0, /*payload_size=*/1);
    packet->mutable_view()->mutable_payload_data()[0] = static_cast<uint8_t>(i);

    // The last packet should remain queued.
    if (i < kBufferMaxNumPackets) {
      EXPECT_SCO_PACKET_OUT(test_device(), StaticByteBuffer(LowerBits(kConnectionHandle0),
                                                            UpperBits(kConnectionHandle0),
                                                            0x01,  // payload length
                                                            static_cast<uint8_t>(i)));
    }
    connection()->QueuePacket(std::move(packet));
    RunLoopUntilIdle();
  }
  EXPECT_EQ(connection()->queued_packets().size(), 1u);
  EXPECT_TRUE(test_device()->AllExpectedScoPacketsSent());

  // kConnectionHandle1 is not registered, so this event should be ignored (no packets should be
  // sent).
  test_device()->SendCommandChannelPacket(
      bt::testing::NumberOfCompletedPacketsPacket(kConnectionHandle1, 1));
  RunLoopUntilIdle();
  EXPECT_EQ(connection()->queued_packets().size(), 1u);
}

TEST_F(ScoDataChannelSingleConnectionTest, ReceiveTooSmallPacket) {
  StaticByteBuffer invalid_packet(LowerBits(kConnectionHandle0), UpperBits(kConnectionHandle0));
  test_device()->SendScoDataChannelPacket(invalid_packet);
  RunLoopUntilIdle();
  // Packet should be ignored.
  EXPECT_EQ(connection()->received_packets().size(), 0u);

  // The next valid packet should not be ignored.
  auto valid_packet = StaticByteBuffer(LowerBits(kConnectionHandle0), UpperBits(kConnectionHandle0),
                                       0x01,  // correct payload length
                                       0x01   // payload
  );
  test_device()->SendScoDataChannelPacket(valid_packet);
  RunLoopUntilIdle();
  EXPECT_EQ(connection()->received_packets().size(), 1u);
}

TEST_F(ScoDataChannelSingleConnectionTest, ReceivePacketWithIncorrectHeaderLengthField) {
  auto packet = StaticByteBuffer(LowerBits(kConnectionHandle0), UpperBits(kConnectionHandle0),
                                 0x03,  // incorrect payload length
                                 0x00   // payload
  );
  test_device()->SendScoDataChannelPacket(packet);
  RunLoopUntilIdle();
  // Packet should be ignored.
  EXPECT_EQ(connection()->received_packets().size(), 0u);

  // The next valid packet should not be ignored.
  packet = StaticByteBuffer(LowerBits(kConnectionHandle0), UpperBits(kConnectionHandle0),
                            0x01,  // correct payload length
                            0x01   // payload
  );
  test_device()->SendScoDataChannelPacket(packet);
  RunLoopUntilIdle();
  EXPECT_EQ(connection()->received_packets().size(), 1u);
}

TEST_F(ScoDataChannelTest, CvsdConnectionEncodingBits8SampleRate8Khz) {
  int config_count = 0;

  set_configure_sco_cb([&](ScoCodingFormat format, ScoEncoding encoding, ScoSampleRate rate,
                           HciWrapper::StatusCallback callback) {
    config_count++;
    EXPECT_EQ(format, ScoCodingFormat::kCvsd);
    EXPECT_EQ(encoding, ScoEncoding::k8Bits);
    EXPECT_EQ(rate, ScoSampleRate::k8Khz);
    callback(ZX_OK);
  });

  int reset_count = 0;
  set_reset_sco_cb([&](HciWrapper::StatusCallback callback) {
    reset_count++;
    callback(ZX_OK);
  });

  FakeScoConnection connection_0(sco_data_channel(), kConnectionHandle0, kCvsdConnectionParameters);
  sco_data_channel()->RegisterConnection(connection_0.GetWeakPtr());
  EXPECT_EQ(config_count, 1);
  EXPECT_EQ(reset_count, 0);
}

TEST_F(ScoDataChannelTest, CvsdConnectionEncodingBits16SampleRate8Khz) {
  int config_count = 0;
  set_configure_sco_cb([&](ScoCodingFormat format, ScoEncoding encoding, ScoSampleRate rate,
                           HciWrapper::StatusCallback callback) {
    config_count++;
    EXPECT_EQ(format, ScoCodingFormat::kCvsd);
    EXPECT_EQ(encoding, ScoEncoding::k16Bits);
    EXPECT_EQ(rate, ScoSampleRate::k8Khz);
    callback(ZX_OK);
  });

  int reset_count = 0;
  set_reset_sco_cb([&](HciWrapper::StatusCallback callback) {
    reset_count++;
    callback(ZX_OK);
  });

  hci_spec::SynchronousConnectionParameters params = kCvsdConnectionParameters;
  params.input_coded_data_size_bits = 16;
  params.output_coded_data_size_bits = 16;
  // Bandwidth = sample size (2 bytes/sample) * sample rate (8000 samples/sec) = 16000 bytes/sec
  params.output_bandwidth = 16000;
  params.input_bandwidth = 16000;
  FakeScoConnection connection(sco_data_channel(), kConnectionHandle0, params);
  sco_data_channel()->RegisterConnection(connection.GetWeakPtr());
  EXPECT_EQ(config_count, 1);
  EXPECT_EQ(reset_count, 0);
}

TEST_F(ScoDataChannelTest, CvsdConnectionEncodingBits16SampleRate16Khz) {
  int config_count = 0;
  set_configure_sco_cb([&](ScoCodingFormat format, ScoEncoding encoding, ScoSampleRate rate,
                           HciWrapper::StatusCallback callback) {
    config_count++;
    EXPECT_EQ(format, ScoCodingFormat::kCvsd);
    EXPECT_EQ(encoding, ScoEncoding::k16Bits);
    EXPECT_EQ(rate, ScoSampleRate::k16Khz);
    callback(ZX_OK);
  });

  int reset_count = 0;
  set_reset_sco_cb([&](HciWrapper::StatusCallback callback) {
    reset_count++;
    callback(ZX_OK);
  });

  hci_spec::SynchronousConnectionParameters params = kCvsdConnectionParameters;
  params.input_coded_data_size_bits = 16;
  params.output_coded_data_size_bits = 16;
  // Bandwidth = sample size (2 bytes/sample) * sample rate (16,000 samples/sec) = 32,000 bytes/sec
  params.output_bandwidth = 32000;
  params.input_bandwidth = 32000;
  FakeScoConnection connection(sco_data_channel(), kConnectionHandle0, params);
  sco_data_channel()->RegisterConnection(connection.GetWeakPtr());
  EXPECT_EQ(config_count, 1);
  EXPECT_EQ(reset_count, 0);
}

TEST_F(ScoDataChannelTest, CvsdConnectionInvalidSampleSizeAndRate) {
  int config_count = 0;
  set_configure_sco_cb([&](ScoCodingFormat format, ScoEncoding encoding, ScoSampleRate rate,
                           HciWrapper::StatusCallback callback) {
    config_count++;
    EXPECT_EQ(format, ScoCodingFormat::kCvsd);
    EXPECT_EQ(encoding, ScoEncoding::k16Bits);
    EXPECT_EQ(rate, ScoSampleRate::k16Khz);
    callback(ZX_OK);
  });

  int reset_count = 0;
  set_reset_sco_cb([&](HciWrapper::StatusCallback callback) {
    reset_count++;
    callback(ZX_OK);
  });

  hci_spec::SynchronousConnectionParameters params = kCvsdConnectionParameters;
  // Invalid sample size will be replaced with sample size of 16 bits.
  params.input_coded_data_size_bits = 0u;
  params.output_coded_data_size_bits = 0u;
  // Invalid rate will be replaced with 16kHz
  params.output_bandwidth = 1;
  params.input_bandwidth = 1;
  FakeScoConnection connection(sco_data_channel(), kConnectionHandle0, params);
  sco_data_channel()->RegisterConnection(connection.GetWeakPtr());
  EXPECT_EQ(config_count, 1);
  EXPECT_EQ(reset_count, 0);
}

TEST_F(ScoDataChannelTest, ConfigureCallbackCalledAfterTransportDestroyedDoesNotUseAfterFree) {
  HciWrapper::StatusCallback config_cb = nullptr;
  set_configure_sco_cb(
      [&](ScoCodingFormat format, ScoEncoding encoding, ScoSampleRate rate,
          HciWrapper::StatusCallback callback) { config_cb = std::move(callback); });

  int reset_count = 0;
  set_reset_sco_cb([&](HciWrapper::StatusCallback callback) {
    reset_count++;
    callback(ZX_OK);
  });

  FakeScoConnection connection(sco_data_channel());
  sco_data_channel()->RegisterConnection(connection.GetWeakPtr());
  EXPECT_TRUE(config_cb);
  EXPECT_EQ(reset_count, 0);

  DeleteTransport();
  RunLoopUntilIdle();

  // Callback should not use-after-free.
  config_cb(ZX_OK);
  RunLoopUntilIdle();
}

TEST_F(ScoDataChannelTest,
       RegisterAndUnregisterFirstConnectionAndRegisterSecondConnectionBeforeFirstConfigCompletes) {
  std::vector<HciWrapper::StatusCallback> config_callbacks;
  set_configure_sco_cb([&](auto, auto, auto, HciWrapper::StatusCallback callback) {
    config_callbacks.emplace_back(std::move(callback));
  });

  int reset_count = 0;
  set_reset_sco_cb([&](HciWrapper::StatusCallback callback) {
    reset_count++;
    callback(ZX_OK);
  });

  FakeScoConnection connection_0(sco_data_channel());
  sco_data_channel()->RegisterConnection(connection_0.GetWeakPtr());
  EXPECT_EQ(config_callbacks.size(), 1u);
  sco_data_channel()->UnregisterConnection(connection_0.handle());
  EXPECT_EQ(reset_count, 1);

  FakeScoConnection connection_1(sco_data_channel(), kConnectionHandle1);
  auto packet = StaticByteBuffer(LowerBits(kConnectionHandle1), UpperBits(kConnectionHandle1),
                                 0x01,  // payload length
                                 0x00   // payload
  );
  std::unique_ptr<ScoDataPacket> sco_packet = ScoDataPacket::New(/*payload_size=*/1);
  sco_packet->mutable_view()->mutable_data().Write(packet);
  sco_packet->InitializeFromBuffer();
  connection_1.QueuePacket(std::move(sco_packet));

  sco_data_channel()->RegisterConnection(connection_1.GetWeakPtr());
  EXPECT_EQ(config_callbacks.size(), 2u);
  // sco_packet should not be sent yet.
  RunLoopUntilIdle();
  // The first callback completing should not complete the second connection configuration.
  config_callbacks[0](ZX_OK);
  // sco_packet should not be sent yet.
  RunLoopUntilIdle();
  EXPECT_EQ(connection_1.queued_packets().size(), 1u);
  // Queued packet should be sent after second callback called.
  config_callbacks[1](ZX_OK);
  EXPECT_SCO_PACKET_OUT(test_device(), packet);
  RunLoopUntilIdle();
  EXPECT_TRUE(test_device()->AllExpectedScoPacketsSent());
}

TEST_F(ScoDataChannelSingleConnectionTest,
       ReceiveNumberOfCompletedPacketsEventWithInconsistentNumberOfHandles) {
  // Queue 1 more than than the max number of packets (1 packet will remain queued).
  for (size_t i = 0; i <= kBufferMaxNumPackets; i++) {
    std::unique_ptr<ScoDataPacket> packet =
        ScoDataPacket::New(kConnectionHandle0, /*payload_size=*/1);
    packet->mutable_view()->mutable_payload_data()[0] = static_cast<uint8_t>(i);

    // The last packet should remain queued.
    if (i < kBufferMaxNumPackets) {
      EXPECT_SCO_PACKET_OUT(test_device(), StaticByteBuffer(LowerBits(kConnectionHandle0),
                                                            UpperBits(kConnectionHandle0),
                                                            0x01,  // payload length
                                                            static_cast<uint8_t>(i)));
    }
    connection()->QueuePacket(std::move(packet));
    RunLoopUntilIdle();
  }
  EXPECT_TRUE(test_device()->AllExpectedScoPacketsSent());

  // The handle in the event should still be processed even though the number of handles is wrong.
  EXPECT_SCO_PACKET_OUT(
      test_device(), StaticByteBuffer(LowerBits(kConnectionHandle0), UpperBits(kConnectionHandle0),
                                      0x01,  // payload length
                                      static_cast<uint8_t>(kBufferMaxNumPackets)));

  constexpr uint16_t num_packets = 1;
  StaticByteBuffer event{0x13,
                         0x05,  // Number Of Completed Packet HCI event header, parameters length
                         0x09,  // Incorrect number of handles
                         LowerBits(kConnectionHandle0),
                         UpperBits(kConnectionHandle0),
                         LowerBits(num_packets),
                         UpperBits(num_packets)};
  test_device()->SendCommandChannelPacket(event);
  RunLoopUntilIdle();
  EXPECT_TRUE(test_device()->AllExpectedScoPacketsSent());
}

TEST_F(ScoDataChannelTest, RegisterTwoConnectionsAndFirstConfigurationFails) {
  int config_count = 0;
  set_configure_sco_cb([&](ScoCodingFormat format, ScoEncoding encoding, ScoSampleRate rate,
                           HciWrapper::StatusCallback callback) {
    config_count++;
    if (config_count == 1) {
      callback(ZX_ERR_INVALID_ARGS);
      return;
    }
    callback(ZX_OK);
  });

  int reset_count = 0;
  set_reset_sco_cb([&](HciWrapper::StatusCallback callback) {
    reset_count++;
    callback(ZX_OK);
  });

  FakeScoConnection connection_0(sco_data_channel());
  sco_data_channel()->RegisterConnection(connection_0.GetWeakPtr());
  EXPECT_EQ(config_count, 1);
  EXPECT_EQ(reset_count, 0);
  EXPECT_EQ(connection_0.hci_error_count(), 0);

  FakeScoConnection connection_1(sco_data_channel(), kConnectionHandle1);
  sco_data_channel()->RegisterConnection(connection_1.GetWeakPtr());
  EXPECT_EQ(config_count, 1);
  EXPECT_EQ(reset_count, 0);

  // The first configuration error should be processed & the configuration of connection_1 should
  // succeed.
  RunLoopUntilIdle();
  EXPECT_EQ(connection_0.hci_error_count(), 1);
  EXPECT_EQ(config_count, 2);
  EXPECT_EQ(reset_count, 0);

  auto packet_0 = StaticByteBuffer(LowerBits(kConnectionHandle0), UpperBits(kConnectionHandle0),
                                   0x01,  // payload length
                                   0x00   // payload
  );
  test_device()->SendScoDataChannelPacket(packet_0);
  RunLoopUntilIdle();
  // packet_0 should not be received since connection_0 failed configuration and was unregistered.
  ASSERT_EQ(connection_0.received_packets().size(), 0u);

  auto packet_1 = StaticByteBuffer(LowerBits(kConnectionHandle1), UpperBits(kConnectionHandle1),
                                   0x01,  // payload length
                                   0x01   // payload
  );
  test_device()->SendScoDataChannelPacket(packet_1);
  RunLoopUntilIdle();
  ASSERT_EQ(connection_1.received_packets().size(), 1u);

  // There are no active connections now (+1 to reset_count).
  sco_data_channel()->UnregisterConnection(connection_1.handle());
  EXPECT_EQ(config_count, 2);
  EXPECT_EQ(reset_count, 1);
}

TEST_F(ScoDataChannelTest, UnsupportedCodingFormatTreatedAsCvsd) {
  int config_count = 0;
  set_configure_sco_cb([&](ScoCodingFormat format, ScoEncoding encoding, ScoSampleRate rate,
                           HciWrapper::StatusCallback callback) {
    config_count++;
    EXPECT_EQ(format, ScoCodingFormat::kCvsd);
    callback(ZX_OK);
  });

  int reset_count = 0;
  set_reset_sco_cb([&](HciWrapper::StatusCallback callback) {
    reset_count++;
    callback(ZX_OK);
  });

  hci_spec::SynchronousConnectionParameters params = kCvsdConnectionParameters;
  params.output_coding_format.coding_format = hci_spec::CodingFormat::kMuLaw;
  params.input_coding_format.coding_format = hci_spec::CodingFormat::kMuLaw;

  FakeScoConnection connection_0(sco_data_channel(), kConnectionHandle0, params);
  sco_data_channel()->RegisterConnection(connection_0.GetWeakPtr());
  EXPECT_EQ(config_count, 1);
  EXPECT_EQ(reset_count, 0);
}

}  // namespace
}  // namespace bt::hci
