/*
 * Copyright 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#define LOG_TAG "bluetooth"

#include <gtest/gtest.h>

#include "client_interface.h"
#include "codec_status.h"

namespace {

using ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
using ::android::hardware::bluetooth::audio::V2_0::AacParameters;
using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
using ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
using ::android::hardware::bluetooth::audio::V2_0::CodecType;
using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
using ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
using ::android::hardware::bluetooth::audio::V2_0::SbcParameters;

using ::bluetooth::audio::AudioCapabilities;
using ::bluetooth::audio::AudioCapabilities_2_1;
using ::bluetooth::audio::AudioConfiguration;
using ::bluetooth::audio::AudioConfiguration_2_1;
using ::bluetooth::audio::BluetoothAudioClientInterface;
using ::bluetooth::audio::BluetoothAudioSinkClientInterface;
using ::bluetooth::audio::BluetoothAudioSourceClientInterface;
using ::bluetooth::audio::BluetoothAudioStatus;
using ::bluetooth::audio::PcmParameters;
using ::bluetooth::audio::PcmParameters_2_1;
using ::bluetooth::audio::SampleRate;
using ::bluetooth::audio::SampleRate_2_1;
using ::bluetooth::audio::SessionType;
using ::bluetooth::audio::SessionType_2_1;
using ::bluetooth::audio::codec::A2dpCodecToHalBitsPerSample;
using ::bluetooth::audio::codec::A2dpCodecToHalChannelMode;
using ::bluetooth::audio::codec::A2dpCodecToHalSampleRate;
using ::bluetooth::audio::codec::BitsPerSample;
using ::bluetooth::audio::codec::ChannelMode;
using ::bluetooth::audio::codec::CodecConfiguration;
using ::bluetooth::audio::codec::IsCodecOffloadingEnabled;
using ::bluetooth::audio::codec::UpdateOffloadingCapabilities;
using ::testing::Test;

struct SampleRatePair {
  SampleRate hal_sample_rate_;
  btav_a2dp_codec_sample_rate_t btav_sample_rate_;
};
constexpr SampleRatePair kSampleRatePairs[9] = {
    {.hal_sample_rate_ = SampleRate::RATE_UNKNOWN,
     .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE},
    {.hal_sample_rate_ = SampleRate::RATE_44100,
     .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_44100},
    {.hal_sample_rate_ = SampleRate::RATE_48000,
     .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_48000},
    {.hal_sample_rate_ = SampleRate::RATE_88200,
     .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_88200},
    {.hal_sample_rate_ = SampleRate::RATE_96000,
     .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_96000},
    {.hal_sample_rate_ = SampleRate::RATE_176400,
     .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_176400},
    {.hal_sample_rate_ = SampleRate::RATE_192000,
     .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_192000},
    {.hal_sample_rate_ = SampleRate::RATE_16000,
     .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_16000},
    {.hal_sample_rate_ = SampleRate::RATE_24000,
     .btav_sample_rate_ = BTAV_A2DP_CODEC_SAMPLE_RATE_24000}};

constexpr SampleRate_2_1 kSampleRates_2_1[] = {
    SampleRate_2_1::RATE_UNKNOWN, SampleRate_2_1::RATE_8000,
    SampleRate_2_1::RATE_16000,   SampleRate_2_1::RATE_24000,
    SampleRate_2_1::RATE_32000,   SampleRate_2_1::RATE_44100,
    SampleRate_2_1::RATE_48000};

constexpr uint32_t kDataIntervalUs[] = {0 /* Invalid */,
                                        10000 /* Valid 10ms */};

struct BitsPerSamplePair {
  BitsPerSample hal_bits_per_sample_;
  btav_a2dp_codec_bits_per_sample_t btav_bits_per_sample_;
};
constexpr BitsPerSamplePair kBitsPerSamplePairs[4] = {
    {.hal_bits_per_sample_ = BitsPerSample::BITS_UNKNOWN,
     .btav_bits_per_sample_ = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE},
    {.hal_bits_per_sample_ = BitsPerSample::BITS_16,
     .btav_bits_per_sample_ = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16},
    {.hal_bits_per_sample_ = BitsPerSample::BITS_24,
     .btav_bits_per_sample_ = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24},
    {.hal_bits_per_sample_ = BitsPerSample::BITS_32,
     .btav_bits_per_sample_ = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32}};

struct ChannelModePair {
  ChannelMode hal_channel_mode_;
  btav_a2dp_codec_channel_mode_t btav_channel_mode_;
};
constexpr ChannelModePair kChannelModePairs[3] = {
    {.hal_channel_mode_ = ChannelMode::UNKNOWN,
     .btav_channel_mode_ = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE},
    {.hal_channel_mode_ = ChannelMode::MONO,
     .btav_channel_mode_ = BTAV_A2DP_CODEC_CHANNEL_MODE_MONO},
    {.hal_channel_mode_ = ChannelMode::STEREO,
     .btav_channel_mode_ = BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO}};

constexpr btav_a2dp_codec_index_t codec_indexes[] = {
    BTAV_A2DP_CODEC_INDEX_SOURCE_SBC,  BTAV_A2DP_CODEC_INDEX_SOURCE_AAC,
    BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD,
    BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC, BTAV_A2DP_CODEC_INDEX_SINK_SBC,
    BTAV_A2DP_CODEC_INDEX_SINK_AAC,    BTAV_A2DP_CODEC_INDEX_SINK_LDAC};
constexpr uint16_t kPeerMtus[5] = {660, 663, 883, 1005, 1500};

class TestSinkTransport
    : public bluetooth::audio::IBluetoothSinkTransportInstance {
 private:
  static constexpr uint64_t kRemoteDelayReportMs = 200;

 public:
  TestSinkTransport(SessionType session_type)
      : bluetooth::audio::IBluetoothSinkTransportInstance(session_type, {}){};
  TestSinkTransport(SessionType_2_1 session_type_2_1)
      : bluetooth::audio::IBluetoothSinkTransportInstance(session_type_2_1,
                                                          {}){};
  bluetooth::audio::BluetoothAudioCtrlAck StartRequest() override {
    return bluetooth::audio::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
  }
  bluetooth::audio::BluetoothAudioCtrlAck SuspendRequest() override {
    return bluetooth::audio::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
  }
  void StopRequest() override {}
  bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
                               uint64_t* total_bytes_readed,
                               timespec* data_position) override {
    if (remote_delay_report_ns) {
      *remote_delay_report_ns = kRemoteDelayReportMs * 1000000;
    }
    if (total_bytes_readed) {
      *total_bytes_readed = 0;
    }
    if (data_position) {
      clock_gettime(CLOCK_MONOTONIC, data_position);
    }
    return true;
  }
  void MetadataChanged(
      const source_metadata_t& source_metadata __unused) override {}
  void ResetPresentationPosition() override{};
  void LogBytesRead(size_t bytes_readed __unused) override{};
};

class TestSourceTransport
    : public bluetooth::audio::IBluetoothSourceTransportInstance {
 private:
  static constexpr uint64_t kRemoteDelayReportMs = 200;

 public:
  TestSourceTransport(SessionType session_type)
      : bluetooth::audio::IBluetoothSourceTransportInstance(session_type, {}){};
  TestSourceTransport(SessionType_2_1 session_type_2_1)
      : bluetooth::audio::IBluetoothSourceTransportInstance(session_type_2_1,
                                                            {}){};
  bluetooth::audio::BluetoothAudioCtrlAck StartRequest() override {
    return bluetooth::audio::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
  }
  bluetooth::audio::BluetoothAudioCtrlAck SuspendRequest() override {
    return bluetooth::audio::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
  }
  void StopRequest() override {}
  bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
                               uint64_t* total_bytes_written,
                               timespec* data_position) override {
    if (remote_delay_report_ns) {
      *remote_delay_report_ns = kRemoteDelayReportMs * 1000000;
    }
    if (total_bytes_written) {
      *total_bytes_written = 0;
    }
    if (data_position) {
      clock_gettime(CLOCK_MONOTONIC, data_position);
    }
    return true;
  }
  void MetadataChanged(
      const source_metadata_t& source_metadata __unused) override {}
  void ResetPresentationPosition() override{};
  void LogBytesWritten(size_t bytes_written __unused) override{};
};

class BluetoothAudioClientInterfaceTest : public Test {
 protected:
  TestSinkTransport* test_sink_transport_ = nullptr;
  TestSourceTransport* test_source_transport_ = nullptr;
  BluetoothAudioSinkClientInterface* clientif_sink_ = nullptr;
  BluetoothAudioSourceClientInterface* clientif_source_ = nullptr;

  static constexpr int kClientIfReturnSuccess = 0;

  void SetUp() override {}

  void TearDown() override {
    if (clientif_sink_ != nullptr) delete clientif_sink_;
    clientif_sink_ = nullptr;
    if (test_sink_transport_ != nullptr) delete test_sink_transport_;
    test_sink_transport_ = nullptr;

    if (clientif_source_ != nullptr) delete clientif_source_;
    clientif_source_ = nullptr;
    if (test_source_transport_ != nullptr) delete test_source_transport_;
    test_source_transport_ = nullptr;
  }

  bool IsSoftwarePcmParametersSupported(const PcmParameters& pcm_config) {
    const std::vector<AudioCapabilities>& capabilities =
        clientif_sink_->GetAudioCapabilities();
    PcmParameters pcm_capabilities = capabilities[0].pcmCapabilities();
    bool is_pcm_config_valid =
        (pcm_config.sampleRate != SampleRate::RATE_UNKNOWN &&
         pcm_config.bitsPerSample != BitsPerSample::BITS_UNKNOWN &&
         pcm_config.channelMode != ChannelMode::UNKNOWN);
    bool is_pcm_config_supported =
        (pcm_config.sampleRate & pcm_capabilities.sampleRate &&
         pcm_config.bitsPerSample & pcm_capabilities.bitsPerSample &&
         pcm_config.channelMode & pcm_capabilities.channelMode);
    return (is_pcm_config_valid && is_pcm_config_supported);
  }

  bool IsSinkSoftwarePcmParameters_2_1_Supported(
      const PcmParameters_2_1& pcm_config) {
    return IsSoftwarePcmParameters_2_1_Supported(pcm_config, clientif_sink_);
  }

  bool IsSourceSoftwarePcmParameters_2_1_Supported(
      const PcmParameters_2_1& pcm_config) {
    return IsSoftwarePcmParameters_2_1_Supported(pcm_config, clientif_source_);
  }

  bool IsCodecOffloadingSupported(const CodecConfiguration& codec_config) {
    CodecCapabilities codec_capability = {};
    for (auto audio_capability : clientif_sink_->GetAudioCapabilities()) {
      if (audio_capability.codecCapabilities().codecType ==
          codec_config.codecType) {
        codec_capability = audio_capability.codecCapabilities();
      }
    }
    if (codec_capability.codecType != codec_config.codecType) {
      // codec is unsupported
      return false;
    }
    bool is_codec_config_supported = false;
    switch (codec_config.codecType) {
      case CodecType::SBC: {
        SbcParameters sbc_config = codec_config.config.sbcConfig();
        SbcParameters sbc_capability =
            codec_capability.capabilities.sbcCapabilities();
        is_codec_config_supported =
            (sbc_config.sampleRate & sbc_capability.sampleRate &&
             sbc_config.channelMode & sbc_capability.channelMode &&
             sbc_config.blockLength & sbc_capability.blockLength &&
             sbc_config.numSubbands & sbc_capability.numSubbands &&
             sbc_config.allocMethod & sbc_capability.allocMethod &&
             sbc_config.bitsPerSample & sbc_capability.bitsPerSample &&
             (sbc_capability.minBitpool <= sbc_config.minBitpool &&
              sbc_config.minBitpool <= sbc_config.maxBitpool &&
              sbc_config.maxBitpool <= sbc_capability.maxBitpool));
        return is_codec_config_supported;
      }
      case CodecType::AAC: {
        AacParameters aac_config = codec_config.config.aacConfig();
        AacParameters aac_capability =
            codec_capability.capabilities.aacCapabilities();
        is_codec_config_supported =
            (aac_config.objectType & aac_capability.objectType &&
             aac_config.sampleRate & aac_capability.sampleRate &&
             aac_config.channelMode & aac_capability.channelMode &&
             (aac_config.variableBitRateEnabled ==
                  AacVariableBitRate::DISABLED ||
              aac_capability.variableBitRateEnabled ==
                  AacVariableBitRate::ENABLED) &&
             aac_config.bitsPerSample & aac_capability.bitsPerSample);
        return is_codec_config_supported;
      }
      case CodecType::LDAC: {
        LdacParameters ldac_config = codec_config.config.ldacConfig();
        LdacParameters ldac_capability =
            codec_capability.capabilities.ldacCapabilities();
        is_codec_config_supported =
            (ldac_config.sampleRate & ldac_capability.sampleRate &&
             ldac_config.channelMode & ldac_capability.channelMode &&
             ldac_config.bitsPerSample & ldac_capability.bitsPerSample);
        return is_codec_config_supported;
      }
      case CodecType::APTX:
        [[fallthrough]];
      case CodecType::APTX_HD: {
        AptxParameters aptx_config = codec_config.config.aptxConfig();
        AptxParameters aptx_capability =
            codec_capability.capabilities.aptxCapabilities();
        is_codec_config_supported =
            (aptx_config.sampleRate & aptx_capability.sampleRate &&
             aptx_config.channelMode & aptx_capability.channelMode &&
             aptx_config.bitsPerSample & aptx_capability.bitsPerSample);
        return is_codec_config_supported;
      }
      case CodecType::UNKNOWN:
        return false;
    }
  }

 private:
  bool IsSoftwarePcmParameters_2_1_Supported(
      const PcmParameters_2_1& pcm_config,
      const BluetoothAudioClientInterface* clientif_) {
    const std::vector<AudioCapabilities_2_1>& capabilities =
        clientif_->GetAudioCapabilities_2_1();
    PcmParameters_2_1 pcm_capabilities = capabilities[0].pcmCapabilities();
    bool is_pcm_config_valid =
        (pcm_config.sampleRate != SampleRate_2_1::RATE_UNKNOWN &&
         pcm_config.bitsPerSample != BitsPerSample::BITS_UNKNOWN &&
         pcm_config.channelMode != ChannelMode::UNKNOWN &&
         pcm_config.dataIntervalUs != 0);
    bool is_pcm_config_supported =
        (pcm_config.sampleRate & pcm_capabilities.sampleRate &&
         pcm_config.bitsPerSample & pcm_capabilities.bitsPerSample &&
         pcm_config.channelMode & pcm_capabilities.channelMode);
    return (is_pcm_config_valid && is_pcm_config_supported);
  }
};

}  // namespace

TEST_F(BluetoothAudioClientInterfaceTest, A2dpCodecToHalPcmConfig) {
  btav_a2dp_codec_config_t a2dp_codec_config = {};
  for (auto sample_rate_pair : kSampleRatePairs) {
    a2dp_codec_config.sample_rate = sample_rate_pair.btav_sample_rate_;
    for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
      a2dp_codec_config.bits_per_sample =
          bits_per_sample_pair.btav_bits_per_sample_;
      for (auto channel_mode_pair : kChannelModePairs) {
        a2dp_codec_config.channel_mode = channel_mode_pair.btav_channel_mode_;
        ASSERT_EQ(A2dpCodecToHalSampleRate(a2dp_codec_config),
                  sample_rate_pair.hal_sample_rate_);
        ASSERT_EQ(A2dpCodecToHalBitsPerSample(a2dp_codec_config),
                  bits_per_sample_pair.hal_bits_per_sample_);
        ASSERT_EQ(A2dpCodecToHalChannelMode(a2dp_codec_config),
                  channel_mode_pair.hal_channel_mode_);
      }  // ChannelMode
    }    // BitsPerSampple
  }      // SampleRate
}

TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpSoftwareSession) {
  test_sink_transport_ =
      new TestSinkTransport(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  AudioConfiguration audio_config = {};
  PcmParameters pcm_config = {};
  for (auto sample_rate_pair : kSampleRatePairs) {
    pcm_config.sampleRate = sample_rate_pair.hal_sample_rate_;
    for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
      pcm_config.bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_;
      for (auto channel_mode_pair : kChannelModePairs) {
        pcm_config.channelMode = channel_mode_pair.hal_channel_mode_;
        audio_config.pcmConfig(pcm_config);
        clientif_sink_->UpdateAudioConfig(audio_config);
        if (IsSoftwarePcmParametersSupported(pcm_config)) {
          ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
        } else {
          ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
        }
        ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
      }  // ChannelMode
    }    // BitsPerSampple
  }      // SampleRate
}

struct CodecOffloadingPreference {
  bool is_target_codec_included_;
  std::vector<btav_a2dp_codec_config_t> preference_;
};

std::vector<CodecOffloadingPreference> CodecOffloadingPreferenceGenerator(
    btav_a2dp_codec_index_t target_codec_index) {
  std::vector<CodecOffloadingPreference> codec_offloading_preferences = {
      {.is_target_codec_included_ = false,
       .preference_ = std::vector<btav_a2dp_codec_config_t>(0)}};
  btav_a2dp_codec_config_t a2dp_codec_config = {};
  for (auto codec_index : codec_indexes) {
    a2dp_codec_config.codec_type = codec_index;
    auto duplicated_preferences = codec_offloading_preferences;
    for (auto iter = duplicated_preferences.begin();
         iter != duplicated_preferences.end(); ++iter) {
      if (codec_index == target_codec_index) {
        iter->is_target_codec_included_ = true;
      }
      iter->preference_.push_back(a2dp_codec_config);
    }
    codec_offloading_preferences.insert(codec_offloading_preferences.end(),
                                        duplicated_preferences.begin(),
                                        duplicated_preferences.end());
  }
  return codec_offloading_preferences;
}

std::vector<CodecConfiguration> SbcCodecConfigurationsGenerator() {
  std::vector<CodecConfiguration> sbc_codec_configs;
  CodecConfiguration codec_config = {};
  SbcBlockLength block_lengths[4] = {
      SbcBlockLength::BLOCKS_4, SbcBlockLength::BLOCKS_8,
      SbcBlockLength::BLOCKS_12, SbcBlockLength::BLOCKS_16};
  SbcNumSubbands num_subbands[2] = {SbcNumSubbands::SUBBAND_4,
                                    SbcNumSubbands::SUBBAND_8};
  SbcAllocMethod alloc_methods[2] = {SbcAllocMethod::ALLOC_MD_S,
                                     SbcAllocMethod::ALLOC_MD_L};
  for (auto sample_rate_pair : kSampleRatePairs) {
    for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
      for (auto channel_mode_pair : kChannelModePairs) {
        for (auto peer_mtu : kPeerMtus) {
          for (auto block_length : block_lengths) {
            for (auto num_subband : num_subbands) {
              for (auto alloc_method : alloc_methods) {
                codec_config.codecType = CodecType::SBC;
                codec_config.peerMtu = peer_mtu;
                codec_config.isScmstEnabled = false;
                // A2DP_SBC_DEFAULT_BITRATE
                codec_config.encodedAudioBitrate = 328000;
                SbcParameters sbc = {
                    .sampleRate = sample_rate_pair.hal_sample_rate_,
                    .channelMode = (channel_mode_pair.hal_channel_mode_ ==
                                            ChannelMode::MONO
                                        ? SbcChannelMode::MONO
                                        : SbcChannelMode::JOINT_STEREO),
                    .blockLength = block_length,
                    .numSubbands = num_subband,
                    .allocMethod = alloc_method,
                    .bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_,
                    .minBitpool = 2,
                    .maxBitpool = 53};
                codec_config.config.sbcConfig(sbc);
                sbc_codec_configs.push_back(codec_config);
              }  // SbcAllocMethod
            }    // SbcNumSubbands
          }      // SbcBlockLength
        }        // peerMtu
      }          // ChannelMode
    }            // BitsPerSampple
  }              // SampleRate
  return sbc_codec_configs;
}

TEST_F(BluetoothAudioClientInterfaceTest, A2dpSbcCodecOffloadingState) {
  test_sink_transport_ =
      new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  auto sbc_codec_configs = SbcCodecConfigurationsGenerator();
  for (auto codec_offloading_preference :
       CodecOffloadingPreferenceGenerator(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC)) {
    UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
    for (CodecConfiguration codec_config : sbc_codec_configs) {
      if (IsCodecOffloadingSupported(codec_config) &&
          codec_offloading_preference.is_target_codec_included_) {
        ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
      } else {
        ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
      }
    }
  }
}

TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadSbcSession) {
  test_sink_transport_ =
      new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  AudioConfiguration audio_config = {};
  for (CodecConfiguration codec_config : SbcCodecConfigurationsGenerator()) {
    audio_config.codecConfig(codec_config);
    clientif_sink_->UpdateAudioConfig(audio_config);
    if (IsCodecOffloadingSupported(codec_config)) {
      ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
    } else {
      ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
    }
    ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
  }
}

std::vector<CodecConfiguration> AacCodecConfigurationsGenerator() {
  std::vector<CodecConfiguration> aac_codec_configs;
  CodecConfiguration codec_config = {};
  AacObjectType object_types[4] = {
      AacObjectType::MPEG2_LC, AacObjectType::MPEG4_LC,
      AacObjectType::MPEG4_LTP, AacObjectType::MPEG4_SCALABLE};
  AacVariableBitRate variable_bitrates[2] = {AacVariableBitRate::DISABLED,
                                             AacVariableBitRate::ENABLED};
  for (auto sample_rate_pair : kSampleRatePairs) {
    for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
      for (auto channel_mode_pair : kChannelModePairs) {
        for (auto peer_mtu : kPeerMtus) {
          for (auto object_type : object_types) {
            for (auto variable_bitrate : variable_bitrates) {
              codec_config.codecType = CodecType::AAC;
              codec_config.peerMtu = peer_mtu;
              codec_config.isScmstEnabled = false;
              // A2DP_AAC_DEFAULT_BITRATE
              codec_config.encodedAudioBitrate = 320000;
              AacParameters aac = {
                  .objectType = object_type,
                  .sampleRate = sample_rate_pair.hal_sample_rate_,
                  .channelMode = channel_mode_pair.hal_channel_mode_,
                  .variableBitRateEnabled = variable_bitrate,
                  .bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_};
              codec_config.config.aacConfig(aac);
              aac_codec_configs.push_back(codec_config);
            }  // AacVariableBitRate
          }    // AacObjectType
        }      // peerMtu
      }        // ChannelMode
    }          // BitsPerSampple
  }            // SampleRate
  return aac_codec_configs;
}

TEST_F(BluetoothAudioClientInterfaceTest, A2dpAacCodecOffloadingState) {
  test_sink_transport_ =
      new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  auto aac_codec_configs = AacCodecConfigurationsGenerator();
  for (auto codec_offloading_preference :
       CodecOffloadingPreferenceGenerator(BTAV_A2DP_CODEC_INDEX_SOURCE_AAC)) {
    UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
    for (CodecConfiguration codec_config : aac_codec_configs) {
      if (IsCodecOffloadingSupported(codec_config) &&
          codec_offloading_preference.is_target_codec_included_) {
        ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
      } else {
        ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
      }
    }
  }
}

TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAacSession) {
  test_sink_transport_ =
      new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  AudioConfiguration audio_config = {};
  for (CodecConfiguration codec_config : AacCodecConfigurationsGenerator()) {
    audio_config.codecConfig(codec_config);
    clientif_sink_->UpdateAudioConfig(audio_config);
    if (IsCodecOffloadingSupported(codec_config)) {
      ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
    } else {
      ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
    }
    ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
  }
}

std::vector<CodecConfiguration> LdacCodecConfigurationsGenerator() {
  std::vector<CodecConfiguration> ldac_codec_configs;
  CodecConfiguration codec_config = {};
  LdacQualityIndex quality_indexes[4] = {
      LdacQualityIndex::QUALITY_HIGH, LdacQualityIndex::QUALITY_MID,
      LdacQualityIndex::QUALITY_LOW, LdacQualityIndex::QUALITY_ABR};
  for (auto sample_rate_pair : kSampleRatePairs) {
    for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
      for (auto channel_mode_pair : kChannelModePairs) {
        for (auto peer_mtu : kPeerMtus) {
          for (auto quality_index : quality_indexes) {
            codec_config.codecType = CodecType::LDAC;
            codec_config.peerMtu = peer_mtu;
            codec_config.isScmstEnabled = false;
            codec_config.encodedAudioBitrate = 990000;
            LdacParameters ldac = {
                .sampleRate = sample_rate_pair.hal_sample_rate_,
                .channelMode =
                    (channel_mode_pair.hal_channel_mode_ == ChannelMode::MONO
                         ? LdacChannelMode::MONO
                         : LdacChannelMode::STEREO),
                .qualityIndex = quality_index,
                .bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_};
            codec_config.config.ldacConfig(ldac);
            ldac_codec_configs.push_back(codec_config);
          }  // LdacQualityIndex
        }    // peerMtu
      }      // ChannelMode
    }        // BitsPerSampple
  }          // SampleRate
  return ldac_codec_configs;
}

TEST_F(BluetoothAudioClientInterfaceTest, A2dpLdacCodecOffloadingState) {
  test_sink_transport_ =
      new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  auto ldac_codec_configs = LdacCodecConfigurationsGenerator();
  for (auto codec_offloading_preference :
       CodecOffloadingPreferenceGenerator(BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC)) {
    UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
    for (CodecConfiguration codec_config : ldac_codec_configs) {
      if (IsCodecOffloadingSupported(codec_config) &&
          codec_offloading_preference.is_target_codec_included_) {
        ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
      } else {
        ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
      }
    }
  }
}

TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadLdacSession) {
  test_sink_transport_ =
      new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  AudioConfiguration audio_config = {};
  for (CodecConfiguration codec_config : LdacCodecConfigurationsGenerator()) {
    audio_config.codecConfig(codec_config);
    clientif_sink_->UpdateAudioConfig(audio_config);
    if (IsCodecOffloadingSupported(codec_config)) {
      ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
    } else {
      ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
    }
    ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
  }
}

std::vector<CodecConfiguration> AptxCodecConfigurationsGenerator(
    CodecType codec_type) {
  std::vector<CodecConfiguration> aptx_codec_configs;
  if (codec_type != CodecType::APTX && codec_type != CodecType::APTX_HD)
    return aptx_codec_configs;
  CodecConfiguration codec_config = {};
  for (auto sample_rate_pair : kSampleRatePairs) {
    for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
      for (auto channel_mode_pair : kChannelModePairs) {
        for (auto peer_mtu : kPeerMtus) {
          codec_config.codecType = codec_type;
          codec_config.peerMtu = peer_mtu;
          codec_config.isScmstEnabled = false;
          codec_config.encodedAudioBitrate =
              (codec_type == CodecType::APTX ? 352000 : 576000);
          AptxParameters aptx = {
              .sampleRate = sample_rate_pair.hal_sample_rate_,
              .channelMode = channel_mode_pair.hal_channel_mode_,
              .bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_};
          codec_config.config.aptxConfig(aptx);
          aptx_codec_configs.push_back(codec_config);
        }  // peerMtu
      }    // ChannelMode
    }      // BitsPerSampple
  }        // SampleRate
  return aptx_codec_configs;
}

TEST_F(BluetoothAudioClientInterfaceTest, A2dpAptxCodecOffloadingState) {
  test_sink_transport_ =
      new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  auto aptx_codec_configs = AptxCodecConfigurationsGenerator(CodecType::APTX);
  for (auto codec_offloading_preference :
       CodecOffloadingPreferenceGenerator(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX)) {
    UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
    for (CodecConfiguration codec_config : aptx_codec_configs) {
      if (IsCodecOffloadingSupported(codec_config) &&
          codec_offloading_preference.is_target_codec_included_) {
        ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
      } else {
        ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
      }
    }
  }
}

TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAptxSession) {
  test_sink_transport_ =
      new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  AudioConfiguration audio_config = {};
  for (CodecConfiguration codec_config :
       AptxCodecConfigurationsGenerator(CodecType::APTX)) {
    audio_config.codecConfig(codec_config);
    clientif_sink_->UpdateAudioConfig(audio_config);
    if (IsCodecOffloadingSupported(codec_config)) {
      ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
    } else {
      ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
    }
    ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
  }
}

TEST_F(BluetoothAudioClientInterfaceTest, A2dpAptxHdCodecOffloadingState) {
  test_sink_transport_ =
      new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  auto aptx_hd_codec_configs =
      AptxCodecConfigurationsGenerator(CodecType::APTX_HD);
  for (auto codec_offloading_preference : CodecOffloadingPreferenceGenerator(
           BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD)) {
    UpdateOffloadingCapabilities(codec_offloading_preference.preference_);
    for (CodecConfiguration codec_config : aptx_hd_codec_configs) {
      if (IsCodecOffloadingSupported(codec_config) &&
          codec_offloading_preference.is_target_codec_included_) {
        ASSERT_TRUE(IsCodecOffloadingEnabled(codec_config));
      } else {
        ASSERT_FALSE(IsCodecOffloadingEnabled(codec_config));
      }
    }
  }
}

TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAptxHdSession) {
  test_sink_transport_ =
      new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  AudioConfiguration audio_config = {};
  for (CodecConfiguration codec_config :
       AptxCodecConfigurationsGenerator(CodecType::APTX_HD)) {
    audio_config.codecConfig(codec_config);
    clientif_sink_->UpdateAudioConfig(audio_config);
    if (IsCodecOffloadingSupported(codec_config)) {
      ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
    } else {
      ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
    }
    ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
  }
}

TEST_F(BluetoothAudioClientInterfaceTest,
       StartAndEndA2dpOffloadUnknownSession) {
  test_sink_transport_ =
      new TestSinkTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  AudioConfiguration audio_config = {};
  CodecConfiguration codec_config = {};
  codec_config.codecType = CodecType::UNKNOWN;
  codec_config.peerMtu = 1005;
  codec_config.isScmstEnabled = false;
  codec_config.encodedAudioBitrate = 328000;
  codec_config.config = {};
  audio_config.codecConfig(codec_config);
  clientif_sink_->UpdateAudioConfig(audio_config);
  if (IsCodecOffloadingSupported(codec_config)) {
    ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
  } else {
    ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
  }
  ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
}

TEST_F(BluetoothAudioClientInterfaceTest,
       StartAndEndHearingAidSoftwareSession) {
  test_sink_transport_ = new TestSinkTransport(
      SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  AudioConfiguration audio_config = {};
  PcmParameters pcm_config = {};
  for (auto sample_rate_pair : kSampleRatePairs) {
    pcm_config.sampleRate = sample_rate_pair.hal_sample_rate_;
    for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
      pcm_config.bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_;
      for (auto channel_mode_pair : kChannelModePairs) {
        pcm_config.channelMode = channel_mode_pair.hal_channel_mode_;
        audio_config.pcmConfig(pcm_config);
        clientif_sink_->UpdateAudioConfig(audio_config);
        if (IsSoftwarePcmParametersSupported(pcm_config)) {
          ASSERT_EQ(clientif_sink_->StartSession(), kClientIfReturnSuccess);
        } else {
          ASSERT_NE(clientif_sink_->StartSession(), kClientIfReturnSuccess);
        }
        ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
      }  // ChannelMode
    }    // BitsPerSampple
  }      // SampleRate
}

TEST_F(BluetoothAudioClientInterfaceTest,
       StartAndEndLeAudioEncodingSoftwareSession) {
  test_sink_transport_ = new TestSinkTransport(
      SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
  clientif_sink_ =
      new BluetoothAudioSinkClientInterface(test_sink_transport_, nullptr);
  AudioConfiguration_2_1 audio_config = {};
  PcmParameters_2_1 pcm_config = {};
  for (auto sample_rate : kSampleRates_2_1) {
    pcm_config.sampleRate = sample_rate;
    for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
      pcm_config.bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_;
      for (auto channel_mode_pair : kChannelModePairs) {
        pcm_config.channelMode = channel_mode_pair.hal_channel_mode_;
        for (auto data_interval_us : kDataIntervalUs) {
          pcm_config.dataIntervalUs = data_interval_us;
          audio_config.pcmConfig(pcm_config);
          clientif_sink_->UpdateAudioConfig_2_1(audio_config);
          if (IsSinkSoftwarePcmParameters_2_1_Supported(pcm_config)) {
            ASSERT_EQ(clientif_sink_->StartSession_2_1(),
                      kClientIfReturnSuccess);
          } else {
            ASSERT_NE(clientif_sink_->StartSession_2_1(),
                      kClientIfReturnSuccess);
          }
          ASSERT_EQ(clientif_sink_->EndSession(), kClientIfReturnSuccess);
        }  // dataIntervalUs
      }    // ChannelMode
    }      // BitsPerSampple
  }        // SampleRate
}

TEST_F(BluetoothAudioClientInterfaceTest,
       StartAndEndLeAudioDecodedSoftwareSession) {
  test_source_transport_ = new TestSourceTransport(
      SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH);
  clientif_source_ =
      new BluetoothAudioSourceClientInterface(test_source_transport_, nullptr);
  AudioConfiguration_2_1 audio_config = {};
  PcmParameters_2_1 pcm_config = {};
  for (auto sample_rate : kSampleRates_2_1) {
    pcm_config.sampleRate = sample_rate;
    for (auto bits_per_sample_pair : kBitsPerSamplePairs) {
      pcm_config.bitsPerSample = bits_per_sample_pair.hal_bits_per_sample_;
      for (auto channel_mode_pair : kChannelModePairs) {
        pcm_config.channelMode = channel_mode_pair.hal_channel_mode_;
        for (auto data_interval_us : kDataIntervalUs) {
          pcm_config.dataIntervalUs = data_interval_us;
          audio_config.pcmConfig(pcm_config);
          clientif_source_->UpdateAudioConfig_2_1(audio_config);
          if (IsSourceSoftwarePcmParameters_2_1_Supported(pcm_config)) {
            ASSERT_EQ(clientif_source_->StartSession_2_1(),
                      kClientIfReturnSuccess);
          } else {
            ASSERT_NE(clientif_source_->StartSession_2_1(),
                      kClientIfReturnSuccess);
          }
          ASSERT_EQ(clientif_source_->EndSession(), kClientIfReturnSuccess);
        }  // dataIntervalUs
      }    // ChannelMode
    }      // BitsPerSampple
  }        // SampleRate
}
