/*
 * Copyright (C) 2022 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.
 */
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioPort.h>
#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioPort.h>
#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.h>
#include <android/binder_auto_utils.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
#include <cutils/properties.h>
#include <fmq/AidlMessageQueue.h>

#include <cstdint>
#include <future>
#include <unordered_set>
#include <vector>

using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
using aidl::android::hardware::bluetooth::audio::AacCapabilities;
using aidl::android::hardware::bluetooth::audio::AacConfiguration;
using aidl::android::hardware::bluetooth::audio::AptxAdaptiveLeCapabilities;
using aidl::android::hardware::bluetooth::audio::AptxAdaptiveLeConfiguration;
using aidl::android::hardware::bluetooth::audio::AptxCapabilities;
using aidl::android::hardware::bluetooth::audio::AptxConfiguration;
using aidl::android::hardware::bluetooth::audio::AudioCapabilities;
using aidl::android::hardware::bluetooth::audio::AudioConfiguration;
using aidl::android::hardware::bluetooth::audio::BnBluetoothAudioPort;
using aidl::android::hardware::bluetooth::audio::BroadcastCapability;
using aidl::android::hardware::bluetooth::audio::ChannelMode;
using aidl::android::hardware::bluetooth::audio::CodecCapabilities;
using aidl::android::hardware::bluetooth::audio::CodecConfiguration;
using aidl::android::hardware::bluetooth::audio::CodecType;
using aidl::android::hardware::bluetooth::audio::IBluetoothAudioPort;
using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProvider;
using aidl::android::hardware::bluetooth::audio::IBluetoothAudioProviderFactory;
using aidl::android::hardware::bluetooth::audio::LatencyMode;
using aidl::android::hardware::bluetooth::audio::Lc3Capabilities;
using aidl::android::hardware::bluetooth::audio::Lc3Configuration;
using aidl::android::hardware::bluetooth::audio::LdacCapabilities;
using aidl::android::hardware::bluetooth::audio::LdacConfiguration;
using aidl::android::hardware::bluetooth::audio::LeAudioBroadcastConfiguration;
using aidl::android::hardware::bluetooth::audio::
    LeAudioCodecCapabilitiesSetting;
using aidl::android::hardware::bluetooth::audio::LeAudioCodecConfiguration;
using aidl::android::hardware::bluetooth::audio::LeAudioConfiguration;
using aidl::android::hardware::bluetooth::audio::OpusCapabilities;
using aidl::android::hardware::bluetooth::audio::OpusConfiguration;
using aidl::android::hardware::bluetooth::audio::PcmConfiguration;
using aidl::android::hardware::bluetooth::audio::PresentationPosition;
using aidl::android::hardware::bluetooth::audio::SbcAllocMethod;
using aidl::android::hardware::bluetooth::audio::SbcCapabilities;
using aidl::android::hardware::bluetooth::audio::SbcChannelMode;
using aidl::android::hardware::bluetooth::audio::SbcConfiguration;
using aidl::android::hardware::bluetooth::audio::SessionType;
using aidl::android::hardware::bluetooth::audio::UnicastCapability;
using aidl::android::hardware::common::fmq::MQDescriptor;
using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
using android::AidlMessageQueue;
using android::ProcessState;
using android::String16;
using ndk::ScopedAStatus;
using ndk::SpAIBinder;

using MqDataType = int8_t;
using MqDataMode = SynchronizedReadWrite;
using DataMQ = AidlMessageQueue<MqDataType, MqDataMode>;
using DataMQDesc = MQDescriptor<MqDataType, MqDataMode>;

// Constants

static constexpr int32_t a2dp_sample_rates[] = {0, 44100, 48000, 88200, 96000};
static constexpr int8_t a2dp_bits_per_samples[] = {0, 16, 24, 32};
static constexpr ChannelMode a2dp_channel_modes[] = {
    ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
static std::vector<LatencyMode> latency_modes = {LatencyMode::FREE};
// Helpers

template <typename T>
struct identity {
  typedef T type;
};

template <class T>
bool contained_in_vector(const std::vector<T>& vector,
                         const typename identity<T>::type& target) {
  return std::find(vector.begin(), vector.end(), target) != vector.end();
}

void copy_codec_specific(CodecConfiguration::CodecSpecific& dst,
                         const CodecConfiguration::CodecSpecific& src) {
  switch (src.getTag()) {
    case CodecConfiguration::CodecSpecific::sbcConfig:
      dst.set<CodecConfiguration::CodecSpecific::sbcConfig>(
          src.get<CodecConfiguration::CodecSpecific::sbcConfig>());
      break;
    case CodecConfiguration::CodecSpecific::aacConfig:
      dst.set<CodecConfiguration::CodecSpecific::aacConfig>(
          src.get<CodecConfiguration::CodecSpecific::aacConfig>());
      break;
    case CodecConfiguration::CodecSpecific::ldacConfig:
      dst.set<CodecConfiguration::CodecSpecific::ldacConfig>(
          src.get<CodecConfiguration::CodecSpecific::ldacConfig>());
      break;
    case CodecConfiguration::CodecSpecific::aptxConfig:
      dst.set<CodecConfiguration::CodecSpecific::aptxConfig>(
          src.get<CodecConfiguration::CodecSpecific::aptxConfig>());
      break;
    case CodecConfiguration::CodecSpecific::opusConfig:
      dst.set<CodecConfiguration::CodecSpecific::opusConfig>(
          src.get<CodecConfiguration::CodecSpecific::opusConfig>());
      break;
    case CodecConfiguration::CodecSpecific::aptxAdaptiveConfig:
      dst.set<CodecConfiguration::CodecSpecific::aptxAdaptiveConfig>(
          src.get<CodecConfiguration::CodecSpecific::aptxAdaptiveConfig>());
      break;
    default:
      break;
  }
}

class BluetoothAudioPort : public BnBluetoothAudioPort {
 public:
  BluetoothAudioPort() {}

  ndk::ScopedAStatus startStream(bool) { return ScopedAStatus::ok(); }

  ndk::ScopedAStatus suspendStream() { return ScopedAStatus::ok(); }

  ndk::ScopedAStatus stopStream() { return ScopedAStatus::ok(); }

  ndk::ScopedAStatus getPresentationPosition(PresentationPosition*) {
    return ScopedAStatus::ok();
  }

  ndk::ScopedAStatus updateSourceMetadata(const SourceMetadata&) {
    return ScopedAStatus::ok();
  }

  ndk::ScopedAStatus updateSinkMetadata(const SinkMetadata&) {
    return ScopedAStatus::ok();
  }

  ndk::ScopedAStatus setLatencyMode(const LatencyMode) {
    return ScopedAStatus::ok();
  }

  ndk::ScopedAStatus setCodecType(const CodecType) {
    return ScopedAStatus::ok();
  }

 protected:
  virtual ~BluetoothAudioPort() = default;
};

class BluetoothAudioProviderFactoryAidl
    : public testing::TestWithParam<std::string> {
 public:
  virtual void SetUp() override {
    provider_factory_ = IBluetoothAudioProviderFactory::fromBinder(
        SpAIBinder(AServiceManager_getService(GetParam().c_str())));
    audio_provider_ = nullptr;
    ASSERT_NE(provider_factory_, nullptr);
  }

  virtual void TearDown() override { provider_factory_ = nullptr; }

  void GetProviderCapabilitiesHelper(const SessionType& session_type) {
    temp_provider_capabilities_.clear();
    auto aidl_retval = provider_factory_->getProviderCapabilities(
        session_type, &temp_provider_capabilities_);
    // AIDL calls should not be failed and callback has to be executed
    ASSERT_TRUE(aidl_retval.isOk());
    switch (session_type) {
      case SessionType::UNKNOWN: {
        ASSERT_TRUE(temp_provider_capabilities_.empty());
      } break;
      case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
      case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
      case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
      case SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH:
      case SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH: {
        // All software paths are mandatory and must have exact 1
        // "PcmParameters"
        ASSERT_EQ(temp_provider_capabilities_.size(), 1);
        ASSERT_EQ(temp_provider_capabilities_[0].getTag(),
                  AudioCapabilities::pcmCapabilities);
      } break;
      case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
      case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH: {
        std::unordered_set<CodecType> codec_types;
        // empty capability means offload is unsupported
        for (auto& audio_capability : temp_provider_capabilities_) {
          ASSERT_EQ(audio_capability.getTag(),
                    AudioCapabilities::a2dpCapabilities);
          const auto& codec_capabilities =
              audio_capability.get<AudioCapabilities::a2dpCapabilities>();
          // Every codec can present once at most
          ASSERT_EQ(codec_types.count(codec_capabilities.codecType), 0);
          switch (codec_capabilities.codecType) {
            case CodecType::SBC:
              ASSERT_EQ(codec_capabilities.capabilities.getTag(),
                        CodecCapabilities::Capabilities::sbcCapabilities);
              break;
            case CodecType::AAC:
              ASSERT_EQ(codec_capabilities.capabilities.getTag(),
                        CodecCapabilities::Capabilities::aacCapabilities);
              break;
            case CodecType::APTX:
            case CodecType::APTX_HD:
              ASSERT_EQ(codec_capabilities.capabilities.getTag(),
                        CodecCapabilities::Capabilities::aptxCapabilities);
              break;
            case CodecType::LDAC:
              ASSERT_EQ(codec_capabilities.capabilities.getTag(),
                        CodecCapabilities::Capabilities::ldacCapabilities);
              break;
            case CodecType::OPUS:
              ASSERT_EQ(codec_capabilities.capabilities.getTag(),
                        CodecCapabilities::Capabilities::opusCapabilities);
              break;
            case CodecType::APTX_ADAPTIVE:
            case CodecType::APTX_ADAPTIVE_LE:
            case CodecType::APTX_ADAPTIVE_LEX:
            case CodecType::LC3:
            case CodecType::VENDOR:
            case CodecType::UNKNOWN:
              break;
          }
          codec_types.insert(codec_capabilities.codecType);
        }
      } break;
      case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
      case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
      case SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH: {
        // empty capability means offload is unsupported since capabilities are
        // not hardcoded
        for (auto audio_capability : temp_provider_capabilities_) {
          ASSERT_EQ(audio_capability.getTag(),
                    AudioCapabilities::leAudioCapabilities);
        }
      } break;
      case SessionType::A2DP_SOFTWARE_DECODING_DATAPATH: {
        if (!temp_provider_capabilities_.empty()) {
          ASSERT_EQ(temp_provider_capabilities_.size(), 1);
          ASSERT_EQ(temp_provider_capabilities_[0].getTag(),
                    AudioCapabilities::pcmCapabilities);
        }
      } break;
      default: {
        ASSERT_TRUE(temp_provider_capabilities_.empty());
      }
    }
  }

  /***
   * This helps to open the specified provider and check the openProvider()
   * has corruct return values. BUT, to keep it simple, it does not consider
   * the capability, and please do so at the SetUp of each session's test.
   ***/
  void OpenProviderHelper(const SessionType& session_type) {
    auto aidl_retval =
        provider_factory_->openProvider(session_type, &audio_provider_);
    if (aidl_retval.isOk()) {
      ASSERT_NE(session_type, SessionType::UNKNOWN);
      ASSERT_NE(audio_provider_, nullptr);
      audio_port_ = ndk::SharedRefBase::make<BluetoothAudioPort>();
    } else {
      // optional session type
      ASSERT_TRUE(
          session_type == SessionType::UNKNOWN ||
          session_type ==
              SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
          session_type ==
              SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
          session_type ==
              SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
          session_type ==
              SessionType::
                  LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
          session_type ==
              SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
          session_type == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
      ASSERT_EQ(audio_provider_, nullptr);
    }
  }

  void GetA2dpOffloadCapabilityHelper(const CodecType& codec_type) {
    temp_codec_capabilities_ = nullptr;
    for (auto& codec_capability : temp_provider_capabilities_) {
      auto& a2dp_capabilities =
          codec_capability.get<AudioCapabilities::a2dpCapabilities>();
      if (a2dp_capabilities.codecType != codec_type) {
        continue;
      }
      temp_codec_capabilities_ = &a2dp_capabilities;
    }
  }

  std::vector<CodecConfiguration::CodecSpecific>
  GetSbcCodecSpecificSupportedList(bool supported) {
    std::vector<CodecConfiguration::CodecSpecific> sbc_codec_specifics;
    if (!supported) {
      SbcConfiguration sbc_config{.sampleRateHz = 0, .bitsPerSample = 0};
      sbc_codec_specifics.push_back(
          CodecConfiguration::CodecSpecific(sbc_config));
      return sbc_codec_specifics;
    }
    GetA2dpOffloadCapabilityHelper(CodecType::SBC);
    if (temp_codec_capabilities_ == nullptr ||
        temp_codec_capabilities_->codecType != CodecType::SBC) {
      return sbc_codec_specifics;
    }
    // parse the capability
    auto& sbc_capability =
        temp_codec_capabilities_->capabilities
            .get<CodecCapabilities::Capabilities::sbcCapabilities>();
    if (sbc_capability.minBitpool > sbc_capability.maxBitpool) {
      return sbc_codec_specifics;
    }

    // combine those parameters into one list of
    // CodecConfiguration::CodecSpecific
    for (int32_t sample_rate : sbc_capability.sampleRateHz) {
      for (int8_t block_length : sbc_capability.blockLength) {
        for (int8_t num_subbands : sbc_capability.numSubbands) {
          for (int8_t bits_per_sample : sbc_capability.bitsPerSample) {
            for (auto channel_mode : sbc_capability.channelMode) {
              for (auto alloc_method : sbc_capability.allocMethod) {
                SbcConfiguration sbc_data = {
                    .sampleRateHz = sample_rate,
                    .channelMode = channel_mode,
                    .blockLength = block_length,
                    .numSubbands = num_subbands,
                    .allocMethod = alloc_method,
                    .bitsPerSample = bits_per_sample,
                    .minBitpool = sbc_capability.minBitpool,
                    .maxBitpool = sbc_capability.maxBitpool};
                sbc_codec_specifics.push_back(
                    CodecConfiguration::CodecSpecific(sbc_data));
              }
            }
          }
        }
      }
    }
    return sbc_codec_specifics;
  }

  std::vector<CodecConfiguration::CodecSpecific>
  GetAacCodecSpecificSupportedList(bool supported) {
    std::vector<CodecConfiguration::CodecSpecific> aac_codec_specifics;
    if (!supported) {
      AacConfiguration aac_config{.sampleRateHz = 0, .bitsPerSample = 0};
      aac_codec_specifics.push_back(
          CodecConfiguration::CodecSpecific(aac_config));
      return aac_codec_specifics;
    }
    GetA2dpOffloadCapabilityHelper(CodecType::AAC);
    if (temp_codec_capabilities_ == nullptr ||
        temp_codec_capabilities_->codecType != CodecType::AAC) {
      return aac_codec_specifics;
    }
    // parse the capability
    auto& aac_capability =
        temp_codec_capabilities_->capabilities
            .get<CodecCapabilities::Capabilities::aacCapabilities>();

    std::vector<bool> variable_bit_rate_enableds = {false};
    if (aac_capability.variableBitRateSupported) {
      variable_bit_rate_enableds.push_back(true);
    }

    std::vector<bool> adaptive_bit_rate_supporteds = {false};
    if (aac_capability.adaptiveBitRateSupported) {
      adaptive_bit_rate_supporteds.push_back(true);
    }

    // combine those parameters into one list of
    // CodecConfiguration::CodecSpecific
    for (auto object_type : aac_capability.objectType) {
      for (int32_t sample_rate : aac_capability.sampleRateHz) {
        for (auto channel_mode : aac_capability.channelMode) {
          for (int8_t bits_per_sample : aac_capability.bitsPerSample) {
            for (auto variable_bit_rate_enabled : variable_bit_rate_enableds) {
              for (auto adaptive_bit_rate_supported :
                   adaptive_bit_rate_supporteds) {
                AacConfiguration aac_data{
                    .objectType = object_type,
                    .sampleRateHz = sample_rate,
                    .channelMode = channel_mode,
                    .variableBitRateEnabled = variable_bit_rate_enabled,
                    .bitsPerSample = bits_per_sample,
                    .adaptiveBitRateSupported = adaptive_bit_rate_supported};
                aac_codec_specifics.push_back(
                    CodecConfiguration::CodecSpecific(aac_data));
              }
            }
          }
        }
      }
    }
    return aac_codec_specifics;
  }

  std::vector<CodecConfiguration::CodecSpecific>
  GetLdacCodecSpecificSupportedList(bool supported) {
    std::vector<CodecConfiguration::CodecSpecific> ldac_codec_specifics;
    if (!supported) {
      LdacConfiguration ldac_config{.sampleRateHz = 0, .bitsPerSample = 0};
      ldac_codec_specifics.push_back(
          CodecConfiguration::CodecSpecific(ldac_config));
      return ldac_codec_specifics;
    }
    GetA2dpOffloadCapabilityHelper(CodecType::LDAC);
    if (temp_codec_capabilities_ == nullptr ||
        temp_codec_capabilities_->codecType != CodecType::LDAC) {
      return ldac_codec_specifics;
    }
    // parse the capability
    auto& ldac_capability =
        temp_codec_capabilities_->capabilities
            .get<CodecCapabilities::Capabilities::ldacCapabilities>();

    // combine those parameters into one list of
    // CodecConfiguration::CodecSpecific
    for (int32_t sample_rate : ldac_capability.sampleRateHz) {
      for (int8_t bits_per_sample : ldac_capability.bitsPerSample) {
        for (auto channel_mode : ldac_capability.channelMode) {
          for (auto quality_index : ldac_capability.qualityIndex) {
            LdacConfiguration ldac_data{.sampleRateHz = sample_rate,
                                        .channelMode = channel_mode,
                                        .qualityIndex = quality_index,
                                        .bitsPerSample = bits_per_sample};
            ldac_codec_specifics.push_back(
                CodecConfiguration::CodecSpecific(ldac_data));
          }
        }
      }
    }
    return ldac_codec_specifics;
  }

  std::vector<CodecConfiguration::CodecSpecific>
  GetAptxCodecSpecificSupportedList(bool is_hd, bool supported) {
    std::vector<CodecConfiguration::CodecSpecific> aptx_codec_specifics;
    if (!supported) {
      AptxConfiguration aptx_config{.sampleRateHz = 0, .bitsPerSample = 0};
      aptx_codec_specifics.push_back(
          CodecConfiguration::CodecSpecific(aptx_config));
      return aptx_codec_specifics;
    }
    GetA2dpOffloadCapabilityHelper(
        (is_hd ? CodecType::APTX_HD : CodecType::APTX));
    if (temp_codec_capabilities_ == nullptr) {
      return aptx_codec_specifics;
    }
    if ((is_hd && temp_codec_capabilities_->codecType != CodecType::APTX_HD) ||
        (!is_hd && temp_codec_capabilities_->codecType != CodecType::APTX)) {
      return aptx_codec_specifics;
    }

    // parse the capability
    auto& aptx_capability =
        temp_codec_capabilities_->capabilities
            .get<CodecCapabilities::Capabilities::aptxCapabilities>();

    // combine those parameters into one list of
    // CodecConfiguration::CodecSpecific
    for (int8_t bits_per_sample : aptx_capability.bitsPerSample) {
      for (int32_t sample_rate : aptx_capability.sampleRateHz) {
        for (auto channel_mode : aptx_capability.channelMode) {
          AptxConfiguration aptx_data{.sampleRateHz = sample_rate,
                                      .channelMode = channel_mode,
                                      .bitsPerSample = bits_per_sample};
          aptx_codec_specifics.push_back(
              CodecConfiguration::CodecSpecific(aptx_data));
        }
      }
    }
    return aptx_codec_specifics;
  }

  std::vector<CodecConfiguration::CodecSpecific>
  GetOpusCodecSpecificSupportedList(bool supported) {
    std::vector<CodecConfiguration::CodecSpecific> opus_codec_specifics;
    if (!supported) {
      OpusConfiguration opus_config{.samplingFrequencyHz = 0,
                                    .frameDurationUs = 0};
      opus_codec_specifics.push_back(
          CodecConfiguration::CodecSpecific(opus_config));
      return opus_codec_specifics;
    }
    GetA2dpOffloadCapabilityHelper(CodecType::OPUS);
    if (temp_codec_capabilities_ == nullptr ||
        temp_codec_capabilities_->codecType != CodecType::OPUS) {
      return opus_codec_specifics;
    }
    // parse the capability
    auto& opus_capability =
        temp_codec_capabilities_->capabilities
            .get<CodecCapabilities::Capabilities::opusCapabilities>();

    // combine those parameters into one list of
    // CodecConfiguration::CodecSpecific
    for (int32_t samplingFrequencyHz : opus_capability->samplingFrequencyHz) {
      for (int32_t frameDurationUs : opus_capability->frameDurationUs) {
        for (auto channel_mode : opus_capability->channelMode) {
          OpusConfiguration opus_data{
              .samplingFrequencyHz = samplingFrequencyHz,
              .frameDurationUs = frameDurationUs,
              .channelMode = channel_mode,
          };
          opus_codec_specifics.push_back(
              CodecConfiguration::CodecSpecific(opus_data));
        }
      }
    }
    return opus_codec_specifics;
  }

  bool IsPcmConfigSupported(const PcmConfiguration& pcm_config) {
    if (temp_provider_capabilities_.size() != 1 ||
        temp_provider_capabilities_[0].getTag() !=
            AudioCapabilities::pcmCapabilities) {
      return false;
    }
    auto pcm_capability = temp_provider_capabilities_[0]
                              .get<AudioCapabilities::pcmCapabilities>();
    return (contained_in_vector(pcm_capability.channelMode,
                                pcm_config.channelMode) &&
            contained_in_vector(pcm_capability.sampleRateHz,
                                pcm_config.sampleRateHz) &&
            contained_in_vector(pcm_capability.bitsPerSample,
                                pcm_config.bitsPerSample));
  }

  std::shared_ptr<IBluetoothAudioProviderFactory> provider_factory_;
  std::shared_ptr<IBluetoothAudioProvider> audio_provider_;
  std::shared_ptr<IBluetoothAudioPort> audio_port_;
  std::vector<AudioCapabilities> temp_provider_capabilities_;

  // temp storage saves the specified codec capability by
  // GetOffloadCodecCapabilityHelper()
  CodecCapabilities* temp_codec_capabilities_;

  static constexpr SessionType kSessionTypes[] = {
      SessionType::UNKNOWN,
      SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
      SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
      SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
      SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
      SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
      SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
      SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
      SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
      SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
      SessionType::A2DP_SOFTWARE_DECODING_DATAPATH,
      SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH,
  };
};

/**
 * Test whether we can get the FactoryService from HIDL
 */
TEST_P(BluetoothAudioProviderFactoryAidl, GetProviderFactoryService) {}

/**
 * Test whether we can open a provider for each provider returned by
 * getProviderCapabilities() with non-empty capabalities
 */
TEST_P(BluetoothAudioProviderFactoryAidl,
       OpenProviderAndCheckCapabilitiesBySession) {
  for (auto session_type : kSessionTypes) {
    GetProviderCapabilitiesHelper(session_type);
    OpenProviderHelper(session_type);
    // We must be able to open a provider if its getProviderCapabilities()
    // returns non-empty list.
    EXPECT_TRUE(temp_provider_capabilities_.empty() ||
                audio_provider_ != nullptr);
  }
}

/**
 * openProvider A2DP_SOFTWARE_ENCODING_DATAPATH
 */
class BluetoothAudioProviderA2dpEncodingSoftwareAidl
    : public BluetoothAudioProviderFactoryAidl {
 public:
  virtual void SetUp() override {
    BluetoothAudioProviderFactoryAidl::SetUp();
    GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
    OpenProviderHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
    ASSERT_NE(audio_provider_, nullptr);
  }

  virtual void TearDown() override {
    audio_port_ = nullptr;
    audio_provider_ = nullptr;
    BluetoothAudioProviderFactoryAidl::TearDown();
  }
};

/**
 * Test whether we can open a provider of type
 */
TEST_P(BluetoothAudioProviderA2dpEncodingSoftwareAidl,
       OpenA2dpEncodingSoftwareProvider) {}

/**
 * Test whether each provider of type
 * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
 * different PCM config
 */
TEST_P(BluetoothAudioProviderA2dpEncodingSoftwareAidl,
       StartAndEndA2dpEncodingSoftwareSessionWithPossiblePcmConfig) {
  for (auto sample_rate : a2dp_sample_rates) {
    for (auto bits_per_sample : a2dp_bits_per_samples) {
      for (auto channel_mode : a2dp_channel_modes) {
        PcmConfiguration pcm_config{
            .sampleRateHz = sample_rate,
            .channelMode = channel_mode,
            .bitsPerSample = bits_per_sample,
        };
        bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
        DataMQDesc mq_desc;
        auto aidl_retval = audio_provider_->startSession(
            audio_port_, AudioConfiguration(pcm_config), latency_modes,
            &mq_desc);
        DataMQ data_mq(mq_desc);

        EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
        if (is_codec_config_valid) {
          EXPECT_TRUE(data_mq.isValid());
        }
        EXPECT_TRUE(audio_provider_->endSession().isOk());
      }
    }
  }
}

/**
 * openProvider A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH
 */
class BluetoothAudioProviderA2dpEncodingHardwareAidl
    : public BluetoothAudioProviderFactoryAidl {
 public:
  virtual void SetUp() override {
    BluetoothAudioProviderFactoryAidl::SetUp();
    GetProviderCapabilitiesHelper(
        SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
    OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
                audio_provider_ != nullptr);
  }

  virtual void TearDown() override {
    audio_port_ = nullptr;
    audio_provider_ = nullptr;
    BluetoothAudioProviderFactoryAidl::TearDown();
  }

  bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
};

/**
 * Test whether we can open a provider of type
 */
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
       OpenA2dpEncodingHardwareProvider) {}

/**
 * Test whether each provider of type
 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
 * SBC hardware encoding config
 */
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
       StartAndEndA2dpSbcEncodingHardwareSession) {
  if (!IsOffloadSupported()) {
    return;
  }

  CodecConfiguration codec_config = {
      .codecType = CodecType::SBC,
      .encodedAudioBitrate = 328000,
      .peerMtu = 1005,
      .isScmstEnabled = false,
  };
  auto sbc_codec_specifics = GetSbcCodecSpecificSupportedList(true);

  for (auto& codec_specific : sbc_codec_specifics) {
    copy_codec_specific(codec_config.config, codec_specific);
    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);

    ASSERT_TRUE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * Test whether each provider of type
 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
 * AAC hardware encoding config
 */
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
       StartAndEndA2dpAacEncodingHardwareSession) {
  if (!IsOffloadSupported()) {
    return;
  }

  CodecConfiguration codec_config = {
      .codecType = CodecType::AAC,
      .encodedAudioBitrate = 320000,
      .peerMtu = 1005,
      .isScmstEnabled = false,
  };
  auto aac_codec_specifics = GetAacCodecSpecificSupportedList(true);

  for (auto& codec_specific : aac_codec_specifics) {
    copy_codec_specific(codec_config.config, codec_specific);
    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);

    ASSERT_TRUE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * Test whether each provider of type
 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
 * LDAC hardware encoding config
 */
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
       StartAndEndA2dpLdacEncodingHardwareSession) {
  if (!IsOffloadSupported()) {
    return;
  }

  CodecConfiguration codec_config = {
      .codecType = CodecType::LDAC,
      .encodedAudioBitrate = 990000,
      .peerMtu = 1005,
      .isScmstEnabled = false,
  };
  auto ldac_codec_specifics = GetLdacCodecSpecificSupportedList(true);

  for (auto& codec_specific : ldac_codec_specifics) {
    copy_codec_specific(codec_config.config, codec_specific);
    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);

    ASSERT_TRUE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * Test whether each provider of type
 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
 * Opus hardware encoding config
 */
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
       StartAndEndA2dpOpusEncodingHardwareSession) {
  if (!IsOffloadSupported()) {
    return;
  }

  CodecConfiguration codec_config = {
      .codecType = CodecType::OPUS,
      .encodedAudioBitrate = 990000,
      .peerMtu = 1005,
      .isScmstEnabled = false,
  };
  auto opus_codec_specifics = GetOpusCodecSpecificSupportedList(true);

  for (auto& codec_specific : opus_codec_specifics) {
    copy_codec_specific(codec_config.config, codec_specific);
    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);

    ASSERT_TRUE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * Test whether each provider of type
 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
 * AptX hardware encoding config
 */
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
       StartAndEndA2dpAptxEncodingHardwareSession) {
  if (!IsOffloadSupported()) {
    return;
  }

  for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
    CodecConfiguration codec_config = {
        .codecType = codec_type,
        .encodedAudioBitrate =
            (codec_type == CodecType::APTX ? 352000 : 576000),
        .peerMtu = 1005,
        .isScmstEnabled = false,
    };

    auto aptx_codec_specifics = GetAptxCodecSpecificSupportedList(
        (codec_type == CodecType::APTX_HD ? true : false), true);

    for (auto& codec_specific : aptx_codec_specifics) {
      copy_codec_specific(codec_config.config, codec_specific);
      DataMQDesc mq_desc;
      auto aidl_retval = audio_provider_->startSession(
          audio_port_, AudioConfiguration(codec_config), latency_modes,
          &mq_desc);

      ASSERT_TRUE(aidl_retval.isOk());
      EXPECT_TRUE(audio_provider_->endSession().isOk());
    }
  }
}

/**
 * Test whether each provider of type
 * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
 * an invalid codec config
 */
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
       StartAndEndA2dpEncodingHardwareSessionInvalidCodecConfig) {
  if (!IsOffloadSupported()) {
    return;
  }
  ASSERT_NE(audio_provider_, nullptr);

  std::vector<CodecConfiguration::CodecSpecific> codec_specifics;
  for (auto codec_type : ndk::enum_range<CodecType>()) {
    switch (codec_type) {
      case CodecType::SBC:
        codec_specifics = GetSbcCodecSpecificSupportedList(false);
        break;
      case CodecType::AAC:
        codec_specifics = GetAacCodecSpecificSupportedList(false);
        break;
      case CodecType::LDAC:
        codec_specifics = GetLdacCodecSpecificSupportedList(false);
        break;
      case CodecType::APTX:
        codec_specifics = GetAptxCodecSpecificSupportedList(false, false);
        break;
      case CodecType::APTX_HD:
        codec_specifics = GetAptxCodecSpecificSupportedList(true, false);
        break;
      case CodecType::OPUS:
        codec_specifics = GetOpusCodecSpecificSupportedList(false);
        continue;
      case CodecType::APTX_ADAPTIVE:
      case CodecType::APTX_ADAPTIVE_LE:
      case CodecType::APTX_ADAPTIVE_LEX:
      case CodecType::LC3:
      case CodecType::VENDOR:
      case CodecType::UNKNOWN:
        codec_specifics.clear();
        break;
    }
    if (codec_specifics.empty()) {
      continue;
    }

    CodecConfiguration codec_config = {
        .codecType = codec_type,
        .encodedAudioBitrate = 328000,
        .peerMtu = 1005,
        .isScmstEnabled = false,
    };
    for (auto codec_specific : codec_specifics) {
      copy_codec_specific(codec_config.config, codec_specific);
      DataMQDesc mq_desc;
      auto aidl_retval = audio_provider_->startSession(
          audio_port_, AudioConfiguration(codec_config), latency_modes,
          &mq_desc);

      // AIDL call should fail on invalid codec
      ASSERT_FALSE(aidl_retval.isOk());
      EXPECT_TRUE(audio_provider_->endSession().isOk());
    }
  }
}

/**
 * openProvider HEARING_AID_SOFTWARE_ENCODING_DATAPATH
 */
class BluetoothAudioProviderHearingAidSoftwareAidl
    : public BluetoothAudioProviderFactoryAidl {
 public:
  virtual void SetUp() override {
    BluetoothAudioProviderFactoryAidl::SetUp();
    GetProviderCapabilitiesHelper(
        SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
    OpenProviderHelper(SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
    ASSERT_NE(audio_provider_, nullptr);
  }

  virtual void TearDown() override {
    audio_port_ = nullptr;
    audio_provider_ = nullptr;
    BluetoothAudioProviderFactoryAidl::TearDown();
  }

  static constexpr int32_t hearing_aid_sample_rates_[] = {0, 16000, 24000};
  static constexpr int8_t hearing_aid_bits_per_samples_[] = {0, 16, 24};
  static constexpr ChannelMode hearing_aid_channel_modes_[] = {
      ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
};

/**
 * Test whether we can open a provider of type
 */
TEST_P(BluetoothAudioProviderHearingAidSoftwareAidl,
       OpenHearingAidSoftwareProvider) {}

/**
 * Test whether each provider of type
 * SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and
 * stopped with different PCM config
 */
TEST_P(BluetoothAudioProviderHearingAidSoftwareAidl,
       StartAndEndHearingAidSessionWithPossiblePcmConfig) {
  for (int32_t sample_rate : hearing_aid_sample_rates_) {
    for (int8_t bits_per_sample : hearing_aid_bits_per_samples_) {
      for (auto channel_mode : hearing_aid_channel_modes_) {
        PcmConfiguration pcm_config{
            .sampleRateHz = sample_rate,
            .channelMode = channel_mode,
            .bitsPerSample = bits_per_sample,
        };
        bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
        DataMQDesc mq_desc;
        auto aidl_retval = audio_provider_->startSession(
            audio_port_, AudioConfiguration(pcm_config), latency_modes,
            &mq_desc);
        DataMQ data_mq(mq_desc);

        EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
        if (is_codec_config_valid) {
          EXPECT_TRUE(data_mq.isValid());
        }
        EXPECT_TRUE(audio_provider_->endSession().isOk());
      }
    }
  }
}

/**
 * openProvider LE_AUDIO_SOFTWARE_ENCODING_DATAPATH
 */
class BluetoothAudioProviderLeAudioOutputSoftwareAidl
    : public BluetoothAudioProviderFactoryAidl {
 public:
  virtual void SetUp() override {
    BluetoothAudioProviderFactoryAidl::SetUp();
    GetProviderCapabilitiesHelper(
        SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
    OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
    ASSERT_NE(audio_provider_, nullptr);
  }

  virtual void TearDown() override {
    audio_port_ = nullptr;
    audio_provider_ = nullptr;
    BluetoothAudioProviderFactoryAidl::TearDown();
  }

  static constexpr int32_t le_audio_output_sample_rates_[] = {
      0, 8000, 16000, 24000, 32000, 44100, 48000,
  };
  static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
  static constexpr ChannelMode le_audio_output_channel_modes_[] = {
      ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
  static constexpr int32_t le_audio_output_data_interval_us_[] = {
      0 /* Invalid */, 10000 /* Valid 10ms */};
};

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
 * stopped
 */
TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareAidl,
       OpenLeAudioOutputSoftwareProvider) {}

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH can be started and
 * stopped with different PCM config
 */
TEST_P(BluetoothAudioProviderLeAudioOutputSoftwareAidl,
       StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
  for (auto sample_rate : le_audio_output_sample_rates_) {
    for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
      for (auto channel_mode : le_audio_output_channel_modes_) {
        for (auto data_interval_us : le_audio_output_data_interval_us_) {
          PcmConfiguration pcm_config{
              .sampleRateHz = sample_rate,
              .channelMode = channel_mode,
              .bitsPerSample = bits_per_sample,
              .dataIntervalUs = data_interval_us,
          };
          bool is_codec_config_valid =
              IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
          DataMQDesc mq_desc;
          auto aidl_retval = audio_provider_->startSession(
              audio_port_, AudioConfiguration(pcm_config), latency_modes,
              &mq_desc);
          DataMQ data_mq(mq_desc);

          EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
          if (is_codec_config_valid) {
            EXPECT_TRUE(data_mq.isValid());
          }
          EXPECT_TRUE(audio_provider_->endSession().isOk());
        }
      }
    }
  }
}

/**
 * openProvider LE_AUDIO_SOFTWARE_DECODING_DATAPATH
 */
class BluetoothAudioProviderLeAudioInputSoftwareAidl
    : public BluetoothAudioProviderFactoryAidl {
 public:
  virtual void SetUp() override {
    BluetoothAudioProviderFactoryAidl::SetUp();
    GetProviderCapabilitiesHelper(
        SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
    OpenProviderHelper(SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH);
    ASSERT_NE(audio_provider_, nullptr);
  }

  virtual void TearDown() override {
    audio_port_ = nullptr;
    audio_provider_ = nullptr;
    BluetoothAudioProviderFactoryAidl::TearDown();
  }

  static constexpr int32_t le_audio_input_sample_rates_[] = {
      0, 8000, 16000, 24000, 32000, 44100, 48000};
  static constexpr int8_t le_audio_input_bits_per_samples_[] = {0, 16, 24};
  static constexpr ChannelMode le_audio_input_channel_modes_[] = {
      ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
  static constexpr int32_t le_audio_input_data_interval_us_[] = {
      0 /* Invalid */, 10000 /* Valid 10ms */};
};

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH can be started and
 * stopped
 */
TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
       OpenLeAudioInputSoftwareProvider) {}

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH can be started and
 * stopped with different PCM config
 */
TEST_P(BluetoothAudioProviderLeAudioInputSoftwareAidl,
       StartAndEndLeAudioInputSessionWithPossiblePcmConfig) {
  for (auto sample_rate : le_audio_input_sample_rates_) {
    for (auto bits_per_sample : le_audio_input_bits_per_samples_) {
      for (auto channel_mode : le_audio_input_channel_modes_) {
        for (auto data_interval_us : le_audio_input_data_interval_us_) {
          PcmConfiguration pcm_config{
              .sampleRateHz = sample_rate,
              .channelMode = channel_mode,
              .bitsPerSample = bits_per_sample,
              .dataIntervalUs = data_interval_us,
          };
          bool is_codec_config_valid =
              IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
          DataMQDesc mq_desc;
          auto aidl_retval = audio_provider_->startSession(
              audio_port_, AudioConfiguration(pcm_config), latency_modes,
              &mq_desc);
          DataMQ data_mq(mq_desc);

          EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
          if (is_codec_config_valid) {
            EXPECT_TRUE(data_mq.isValid());
          }
          EXPECT_TRUE(audio_provider_->endSession().isOk());
        }
      }
    }
  }
}

/**
 * openProvider LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH
 */
class BluetoothAudioProviderLeAudioOutputHardwareAidl
    : public BluetoothAudioProviderFactoryAidl {
 public:
  virtual void SetUp() override {
    BluetoothAudioProviderFactoryAidl::SetUp();
    GetProviderCapabilitiesHelper(
        SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
    OpenProviderHelper(
        SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
                audio_provider_ != nullptr);
  }

  virtual void TearDown() override {
    audio_port_ = nullptr;
    audio_provider_ = nullptr;
    BluetoothAudioProviderFactoryAidl::TearDown();
  }

  bool IsOffloadOutputSupported() {
    for (auto& capability : temp_provider_capabilities_) {
      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
        continue;
      }
      auto& le_audio_capability =
          capability.get<AudioCapabilities::leAudioCapabilities>();
      if (le_audio_capability.unicastEncodeCapability.codecType !=
          CodecType::UNKNOWN)
        return true;
    }
    return false;
  }

  std::vector<Lc3Configuration> GetUnicastLc3SupportedList(bool decoding,
                                                           bool supported) {
    std::vector<Lc3Configuration> le_audio_codec_configs;
    if (!supported) {
      Lc3Configuration lc3_config{.pcmBitDepth = 0, .samplingFrequencyHz = 0};
      le_audio_codec_configs.push_back(lc3_config);
      return le_audio_codec_configs;
    }

    // There might be more than one LeAudioCodecCapabilitiesSetting
    std::vector<Lc3Capabilities> lc3_capabilities;
    for (auto& capability : temp_provider_capabilities_) {
      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
        continue;
      }
      auto& le_audio_capability =
          capability.get<AudioCapabilities::leAudioCapabilities>();
      auto& unicast_capability =
          decoding ? le_audio_capability.unicastDecodeCapability
                   : le_audio_capability.unicastEncodeCapability;
      if (unicast_capability.codecType != CodecType::LC3) {
        continue;
      }
      auto& lc3_capability = unicast_capability.leAudioCodecCapabilities.get<
          UnicastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
      lc3_capabilities.push_back(lc3_capability);
    }

    // Combine those parameters into one list of LeAudioCodecConfiguration
    // This seems horrible, but usually each Lc3Capability only contains a
    // single Lc3Configuration, which means every array has a length of 1.
    for (auto& lc3_capability : lc3_capabilities) {
      for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
        for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
          for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
            Lc3Configuration lc3_config = {
                .samplingFrequencyHz = samplingFrequencyHz,
                .frameDurationUs = frameDurationUs,
                .octetsPerFrame = octetsPerFrame,
            };
            le_audio_codec_configs.push_back(lc3_config);
          }
        }
      }
    }

    return le_audio_codec_configs;
  }

  static constexpr int32_t apx_adaptive_le_config_codec_modes[] = {0, 1, 2, 3};

  std::vector<AptxAdaptiveLeConfiguration>
  GetUnicastAptxAdaptiveLeSupportedList(bool decoding, bool supported,
                                        bool is_le_extended) {
    std::vector<AptxAdaptiveLeConfiguration> le_audio_codec_configs;
    if (!supported) {
      AptxAdaptiveLeConfiguration aptx_adaptive_le_config{
          .pcmBitDepth = 0, .samplingFrequencyHz = 0};
      le_audio_codec_configs.push_back(aptx_adaptive_le_config);
      return le_audio_codec_configs;
    }

    // There might be more than one LeAudioCodecCapabilitiesSetting
    std::vector<AptxAdaptiveLeCapabilities> aptx_adaptive_le_capabilities;
    for (auto& capability : temp_provider_capabilities_) {
      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
        continue;
      }
      auto& le_audio_capability =
          capability.get<AudioCapabilities::leAudioCapabilities>();
      auto& unicast_capability =
          decoding ? le_audio_capability.unicastDecodeCapability
                   : le_audio_capability.unicastEncodeCapability;
      if ((!is_le_extended &&
           unicast_capability.codecType != CodecType::APTX_ADAPTIVE_LE) ||
          (is_le_extended &&
           unicast_capability.codecType != CodecType::APTX_ADAPTIVE_LEX)) {
        continue;
      }

      auto& aptx_adaptive_le_capability =
          unicast_capability.leAudioCodecCapabilities
              .get<UnicastCapability::LeAudioCodecCapabilities::
                       aptxAdaptiveLeCapabilities>();

      aptx_adaptive_le_capabilities.push_back(aptx_adaptive_le_capability);
    }

    for (auto& aptx_adaptive_le_capability : aptx_adaptive_le_capabilities) {
      for (int32_t samplingFrequencyHz :
           aptx_adaptive_le_capability.samplingFrequencyHz) {
        for (int32_t frameDurationUs :
             aptx_adaptive_le_capability.frameDurationUs) {
          for (int32_t octetsPerFrame :
               aptx_adaptive_le_capability.octetsPerFrame) {
            for (int8_t blocksPerSdu :
                 aptx_adaptive_le_capability.blocksPerSdu) {
              for (int32_t codecMode : apx_adaptive_le_config_codec_modes) {
                AptxAdaptiveLeConfiguration aptx_adaptive_le_config = {
                    .samplingFrequencyHz = samplingFrequencyHz,
                    .frameDurationUs = frameDurationUs,
                    .octetsPerFrame = octetsPerFrame,
                    .blocksPerSdu = blocksPerSdu,
                    .codecMode = codecMode,
                };
                le_audio_codec_configs.push_back(aptx_adaptive_le_config);
              }
            }
          }
        }
      }
    }

    return le_audio_codec_configs;
  }

  LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
};

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
 * stopped
 */
TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
       OpenLeAudioOutputHardwareProvider) {}

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
 * stopped with Unicast hardware encoding config
 */
TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
       StartAndEndLeAudioOutputSessionWithPossibleUnicastConfig) {
  if (!IsOffloadOutputSupported()) {
    return;
  }

  auto lc3_codec_configs =
      GetUnicastLc3SupportedList(false /* decoding */, true /* supported */);
  LeAudioConfiguration le_audio_config = {
      .codecType = CodecType::LC3,
      .peerDelayUs = 0,
  };

  for (auto& lc3_config : lc3_codec_configs) {
    le_audio_config.leAudioCodecConfig
        .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(le_audio_config), latency_modes,
        &mq_desc);

    ASSERT_TRUE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
 * stopped with Unicast hardware encoding config
 *
 * Disabled since offload codec checking is not ready
 */
TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
       DISABLED_StartAndEndLeAudioOutputSessionWithInvalidAudioConfiguration) {
  if (!IsOffloadOutputSupported()) {
    return;
  }

  auto lc3_codec_configs =
      GetUnicastLc3SupportedList(false /* decoding */, false /* supported */);
  LeAudioConfiguration le_audio_config = {
      .codecType = CodecType::LC3,
      .peerDelayUs = 0,
  };

  for (auto& lc3_config : lc3_codec_configs) {
    le_audio_config.leAudioCodecConfig
        .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(le_audio_config), latency_modes,
        &mq_desc);

    // AIDL call should fail on invalid codec
    ASSERT_FALSE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

static std::vector<uint8_t> vendorMetadata = {0x0B,  // Length
                                              0xFF,  // Type: Vendor-specific
                                              0x0A, 0x00,  // Company_ID
                                              0x01, 0x02, 0x03, 0x04,  // Data
                                              0x05, 0x06, 0x07, 0x08};

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
 * stopped with Unicast hardware encoding config
 */
TEST_P(BluetoothAudioProviderLeAudioOutputHardwareAidl,
       StartAndEndLeAudioOutputSessionWithAptxAdaptiveLeUnicastConfig) {
  if (!IsOffloadOutputSupported()) {
    return;
  }
  for (auto codec_type :
       {CodecType::APTX_ADAPTIVE_LE, CodecType::APTX_ADAPTIVE_LEX}) {
    bool is_le_extended = (codec_type == CodecType::APTX_ADAPTIVE_LEX);
    auto aptx_adaptive_le_codec_configs =
        GetUnicastAptxAdaptiveLeSupportedList(false, true, is_le_extended);
    LeAudioConfiguration le_audio_config = {
        .codecType = codec_type,
        .peerDelayUs = 0,
        .vendorSpecificMetadata = vendorMetadata,
    };

    for (auto& aptx_adaptive_le_config : aptx_adaptive_le_codec_configs) {
      le_audio_config.leAudioCodecConfig
          .set<LeAudioCodecConfiguration::aptxAdaptiveLeConfig>(
              aptx_adaptive_le_config);
      DataMQDesc mq_desc;
      auto aidl_retval = audio_provider_->startSession(
          audio_port_, AudioConfiguration(le_audio_config), latency_modes,
          &mq_desc);

      ASSERT_TRUE(aidl_retval.isOk());
      EXPECT_TRUE(audio_provider_->endSession().isOk());
    }
  }
}

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
 * stopped with Unicast hardware encoding config
 */
TEST_P(
    BluetoothAudioProviderLeAudioOutputHardwareAidl,
    BluetoothAudioProviderLeAudioOutputHardwareAidl_StartAndEndLeAudioOutputSessionWithInvalidAptxAdaptiveLeAudioConfiguration) {
  if (!IsOffloadOutputSupported()) {
    return;
  }

  for (auto codec_type :
       {CodecType::APTX_ADAPTIVE_LE, CodecType::APTX_ADAPTIVE_LEX}) {
    bool is_le_extended = (codec_type == CodecType::APTX_ADAPTIVE_LEX);
    auto aptx_adaptive_le_codec_configs =
        GetUnicastAptxAdaptiveLeSupportedList(false, true, is_le_extended);
    LeAudioConfiguration le_audio_config = {
        .codecType = codec_type,
        .peerDelayUs = 0,
        .vendorSpecificMetadata = vendorMetadata,
    };

    for (auto& aptx_adaptive_le_config : aptx_adaptive_le_codec_configs) {
      le_audio_config.leAudioCodecConfig
          .set<LeAudioCodecConfiguration::aptxAdaptiveLeConfig>(
              aptx_adaptive_le_config);
      DataMQDesc mq_desc;
      auto aidl_retval = audio_provider_->startSession(
          audio_port_, AudioConfiguration(le_audio_config), latency_modes,
          &mq_desc);

      // AIDL call should fail on invalid codec
      ASSERT_FALSE(aidl_retval.isOk());
      EXPECT_TRUE(audio_provider_->endSession().isOk());
    }
  }
}

/**
 * openProvider LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH
 */
class BluetoothAudioProviderLeAudioInputHardwareAidl
    : public BluetoothAudioProviderLeAudioOutputHardwareAidl {
 public:
  virtual void SetUp() override {
    BluetoothAudioProviderFactoryAidl::SetUp();
    GetProviderCapabilitiesHelper(
        SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
    OpenProviderHelper(
        SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
                audio_provider_ != nullptr);
  }

  bool IsOffloadInputSupported() {
    for (auto& capability : temp_provider_capabilities_) {
      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
        continue;
      }
      auto& le_audio_capability =
          capability.get<AudioCapabilities::leAudioCapabilities>();
      if (le_audio_capability.unicastDecodeCapability.codecType !=
          CodecType::UNKNOWN)
        return true;
    }
    return false;
  }

  virtual void TearDown() override {
    audio_port_ = nullptr;
    audio_provider_ = nullptr;
    BluetoothAudioProviderFactoryAidl::TearDown();
  }
};

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
 * stopped
 */
TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
       OpenLeAudioInputHardwareProvider) {}

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
 * stopped with Unicast hardware encoding config
 */
TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
       StartAndEndLeAudioInputSessionWithPossibleUnicastConfig) {
  if (!IsOffloadInputSupported()) {
    return;
  }

  auto lc3_codec_configs =
      GetUnicastLc3SupportedList(true /* decoding */, true /* supported */);
  LeAudioConfiguration le_audio_config = {
      .codecType = CodecType::LC3,
      .peerDelayUs = 0,
  };

  for (auto& lc3_config : lc3_codec_configs) {
    le_audio_config.leAudioCodecConfig
        .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);
    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(le_audio_config), latency_modes,
        &mq_desc);

    ASSERT_TRUE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be started and
 * stopped with Unicast hardware encoding config
 *
 * Disabled since offload codec checking is not ready
 */
TEST_P(BluetoothAudioProviderLeAudioInputHardwareAidl,
       DISABLED_StartAndEndLeAudioInputSessionWithInvalidAudioConfiguration) {
  if (!IsOffloadInputSupported()) {
    return;
  }

  auto lc3_codec_configs =
      GetUnicastLc3SupportedList(true /* decoding */, false /* supported */);
  LeAudioConfiguration le_audio_config = {
      .codecType = CodecType::LC3,
      .peerDelayUs = 0,
  };

  for (auto& lc3_config : lc3_codec_configs) {
    le_audio_config.leAudioCodecConfig
        .set<LeAudioCodecConfiguration::lc3Config>(lc3_config);

    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(le_audio_config), latency_modes,
        &mq_desc);

    // AIDL call should fail on invalid codec
    ASSERT_FALSE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * openProvider LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH
 */
class BluetoothAudioProviderLeAudioBroadcastSoftwareAidl
    : public BluetoothAudioProviderFactoryAidl {
 public:
  virtual void SetUp() override {
    BluetoothAudioProviderFactoryAidl::SetUp();
    GetProviderCapabilitiesHelper(
        SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
    OpenProviderHelper(
        SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
    ASSERT_NE(audio_provider_, nullptr);
  }

  virtual void TearDown() override {
    audio_port_ = nullptr;
    audio_provider_ = nullptr;
    BluetoothAudioProviderFactoryAidl::TearDown();
  }

  static constexpr int32_t le_audio_output_sample_rates_[] = {
      0, 8000, 16000, 24000, 32000, 44100, 48000,
  };
  static constexpr int8_t le_audio_output_bits_per_samples_[] = {0, 16, 24};
  static constexpr ChannelMode le_audio_output_channel_modes_[] = {
      ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
  static constexpr int32_t le_audio_output_data_interval_us_[] = {
      0 /* Invalid */, 10000 /* Valid 10ms */};
};

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started and
 * stopped
 */
TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
       OpenLeAudioOutputSoftwareProvider) {}

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH can be started and
 * stopped with different PCM config
 */
TEST_P(BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
       StartAndEndLeAudioOutputSessionWithPossiblePcmConfig) {
  for (auto sample_rate : le_audio_output_sample_rates_) {
    for (auto bits_per_sample : le_audio_output_bits_per_samples_) {
      for (auto channel_mode : le_audio_output_channel_modes_) {
        for (auto data_interval_us : le_audio_output_data_interval_us_) {
          PcmConfiguration pcm_config{
              .sampleRateHz = sample_rate,
              .channelMode = channel_mode,
              .bitsPerSample = bits_per_sample,
              .dataIntervalUs = data_interval_us,
          };
          bool is_codec_config_valid =
              IsPcmConfigSupported(pcm_config) && pcm_config.dataIntervalUs > 0;
          DataMQDesc mq_desc;
          auto aidl_retval = audio_provider_->startSession(
              audio_port_, AudioConfiguration(pcm_config), latency_modes,
              &mq_desc);
          DataMQ data_mq(mq_desc);

          EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
          if (is_codec_config_valid) {
            EXPECT_TRUE(data_mq.isValid());
          }
          EXPECT_TRUE(audio_provider_->endSession().isOk());
        }
      }
    }
  }
}

/**
 * openProvider LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH
 */
class BluetoothAudioProviderLeAudioBroadcastHardwareAidl
    : public BluetoothAudioProviderFactoryAidl {
 public:
  virtual void SetUp() override {
    BluetoothAudioProviderFactoryAidl::SetUp();
    GetProviderCapabilitiesHelper(
        SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
    OpenProviderHelper(
        SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
                audio_provider_ != nullptr);
  }

  virtual void TearDown() override {
    audio_port_ = nullptr;
    audio_provider_ = nullptr;
    BluetoothAudioProviderFactoryAidl::TearDown();
  }

  bool IsBroadcastOffloadSupported() {
    for (auto& capability : temp_provider_capabilities_) {
      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
        continue;
      }
      auto& le_audio_capability =
          capability.get<AudioCapabilities::leAudioCapabilities>();
      if (le_audio_capability.broadcastCapability.codecType !=
          CodecType::UNKNOWN)
        return true;
    }
    return false;
  }

  std::vector<Lc3Configuration> GetBroadcastLc3SupportedList(bool supported) {
    std::vector<Lc3Configuration> le_audio_codec_configs;
    if (!supported) {
      Lc3Configuration lc3_config{.pcmBitDepth = 0, .samplingFrequencyHz = 0};
      le_audio_codec_configs.push_back(lc3_config);
      return le_audio_codec_configs;
    }

    // There might be more than one LeAudioCodecCapabilitiesSetting
    std::vector<Lc3Capabilities> lc3_capabilities;
    for (auto& capability : temp_provider_capabilities_) {
      if (capability.getTag() != AudioCapabilities::leAudioCapabilities) {
        continue;
      }
      auto& le_audio_capability =
          capability.get<AudioCapabilities::leAudioCapabilities>();
      auto& broadcast_capability = le_audio_capability.broadcastCapability;
      if (broadcast_capability.codecType != CodecType::LC3) {
        continue;
      }
      auto& lc3_capability = broadcast_capability.leAudioCodecCapabilities.get<
          BroadcastCapability::LeAudioCodecCapabilities::lc3Capabilities>();
      for (int idx = 0; idx < lc3_capability->size(); idx++)
        lc3_capabilities.push_back(*lc3_capability->at(idx));
    }

    // Combine those parameters into one list of LeAudioCodecConfiguration
    // This seems horrible, but usually each Lc3Capability only contains a
    // single Lc3Configuration, which means every array has a length of 1.
    for (auto& lc3_capability : lc3_capabilities) {
      for (int32_t samplingFrequencyHz : lc3_capability.samplingFrequencyHz) {
        for (int32_t frameDurationUs : lc3_capability.frameDurationUs) {
          for (int32_t octetsPerFrame : lc3_capability.octetsPerFrame) {
            Lc3Configuration lc3_config = {
                .samplingFrequencyHz = samplingFrequencyHz,
                .frameDurationUs = frameDurationUs,
                .octetsPerFrame = octetsPerFrame,
            };
            le_audio_codec_configs.push_back(lc3_config);
          }
        }
      }
    }

    return le_audio_codec_configs;
  }

  LeAudioCodecCapabilitiesSetting temp_le_audio_capabilities_;
};

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
 * started and stopped
 */
TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
       OpenLeAudioOutputHardwareProvider) {}

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
 * started and stopped with broadcast hardware encoding config
 */
TEST_P(BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
       StartAndEndLeAudioBroadcastSessionWithPossibleBroadcastConfig) {
  if (!IsBroadcastOffloadSupported()) {
    return;
  }

  auto lc3_codec_configs = GetBroadcastLc3SupportedList(true /* supported */);
  LeAudioBroadcastConfiguration le_audio_broadcast_config = {
      .codecType = CodecType::LC3,
      .streamMap = {},
  };

  for (auto& lc3_config : lc3_codec_configs) {
    le_audio_broadcast_config.streamMap.resize(1);
    le_audio_broadcast_config.streamMap[0]
        .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
            lc3_config);
    le_audio_broadcast_config.streamMap[0].streamHandle = 0x0;
    le_audio_broadcast_config.streamMap[0].pcmStreamId = 0x0;
    le_audio_broadcast_config.streamMap[0].audioChannelAllocation = 0x1 << 0;

    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(le_audio_broadcast_config),
        latency_modes, &mq_desc);

    ASSERT_TRUE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * Test whether each provider of type
 * SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH can be
 * started and stopped with Broadcast hardware encoding config
 *
 * Disabled since offload codec checking is not ready
 */
TEST_P(
    BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
    DISABLED_StartAndEndLeAudioBroadcastSessionWithInvalidAudioConfiguration) {
  if (!IsBroadcastOffloadSupported()) {
    return;
  }

  auto lc3_codec_configs = GetBroadcastLc3SupportedList(false /* supported */);
  LeAudioBroadcastConfiguration le_audio_broadcast_config = {
      .codecType = CodecType::LC3,
      .streamMap = {},
  };

  for (auto& lc3_config : lc3_codec_configs) {
    le_audio_broadcast_config.streamMap[0]
        .leAudioCodecConfig.set<LeAudioCodecConfiguration::lc3Config>(
            lc3_config);
    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(le_audio_broadcast_config),
        latency_modes, &mq_desc);

    // AIDL call should fail on invalid codec
    ASSERT_FALSE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * openProvider A2DP_SOFTWARE_DECODING_DATAPATH
 */
class BluetoothAudioProviderA2dpDecodingSoftwareAidl
    : public BluetoothAudioProviderFactoryAidl {
 public:
  virtual void SetUp() override {
    BluetoothAudioProviderFactoryAidl::SetUp();
    GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
    OpenProviderHelper(SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
                audio_provider_ != nullptr);
  }

  virtual void TearDown() override {
    audio_port_ = nullptr;
    audio_provider_ = nullptr;
    BluetoothAudioProviderFactoryAidl::TearDown();
  }
};

/**
 * Test whether we can open a provider of type
 */
TEST_P(BluetoothAudioProviderA2dpDecodingSoftwareAidl,
       OpenA2dpDecodingSoftwareProvider) {}

/**
 * Test whether each provider of type
 * SessionType::A2DP_SOFTWARE_DECODING_DATAPATH can be started and stopped with
 * different PCM config
 */
TEST_P(BluetoothAudioProviderA2dpDecodingSoftwareAidl,
       StartAndEndA2dpDecodingSoftwareSessionWithPossiblePcmConfig) {
  for (auto sample_rate : a2dp_sample_rates) {
    for (auto bits_per_sample : a2dp_bits_per_samples) {
      for (auto channel_mode : a2dp_channel_modes) {
        PcmConfiguration pcm_config{
            .sampleRateHz = sample_rate,
            .channelMode = channel_mode,
            .bitsPerSample = bits_per_sample,
        };
        bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
        DataMQDesc mq_desc;
        auto aidl_retval = audio_provider_->startSession(
            audio_port_, AudioConfiguration(pcm_config), latency_modes,
            &mq_desc);
        DataMQ data_mq(mq_desc);

        EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
        if (is_codec_config_valid) {
          EXPECT_TRUE(data_mq.isValid());
        }
        EXPECT_TRUE(audio_provider_->endSession().isOk());
      }
    }
  }
}

/**
 * openProvider A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH
 */
class BluetoothAudioProviderA2dpDecodingHardwareAidl
    : public BluetoothAudioProviderFactoryAidl {
 public:
  virtual void SetUp() override {
    BluetoothAudioProviderFactoryAidl::SetUp();
    GetProviderCapabilitiesHelper(
        SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
    OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
                audio_provider_ != nullptr);
  }

  virtual void TearDown() override {
    audio_port_ = nullptr;
    audio_provider_ = nullptr;
    BluetoothAudioProviderFactoryAidl::TearDown();
  }

  bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
};

/**
 * Test whether we can open a provider of type
 */
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
       OpenA2dpDecodingHardwareProvider) {}

/**
 * Test whether each provider of type
 * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
 * SBC hardware encoding config
 */
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
       StartAndEndA2dpSbcDecodingHardwareSession) {
  if (!IsOffloadSupported()) {
    return;
  }

  CodecConfiguration codec_config = {
      .codecType = CodecType::SBC,
      .encodedAudioBitrate = 328000,
      .peerMtu = 1005,
      .isScmstEnabled = false,
  };
  auto sbc_codec_specifics = GetSbcCodecSpecificSupportedList(true);

  for (auto& codec_specific : sbc_codec_specifics) {
    copy_codec_specific(codec_config.config, codec_specific);
    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);

    ASSERT_TRUE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * Test whether each provider of type
 * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
 * AAC hardware encoding config
 */
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
       StartAndEndA2dpAacDecodingHardwareSession) {
  if (!IsOffloadSupported()) {
    return;
  }

  CodecConfiguration codec_config = {
      .codecType = CodecType::AAC,
      .encodedAudioBitrate = 320000,
      .peerMtu = 1005,
      .isScmstEnabled = false,
  };
  auto aac_codec_specifics = GetAacCodecSpecificSupportedList(true);

  for (auto& codec_specific : aac_codec_specifics) {
    copy_codec_specific(codec_config.config, codec_specific);
    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);

    ASSERT_TRUE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * Test whether each provider of type
 * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
 * LDAC hardware encoding config
 */
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
       StartAndEndA2dpLdacDecodingHardwareSession) {
  if (!IsOffloadSupported()) {
    return;
  }

  CodecConfiguration codec_config = {
      .codecType = CodecType::LDAC,
      .encodedAudioBitrate = 990000,
      .peerMtu = 1005,
      .isScmstEnabled = false,
  };
  auto ldac_codec_specifics = GetLdacCodecSpecificSupportedList(true);

  for (auto& codec_specific : ldac_codec_specifics) {
    copy_codec_specific(codec_config.config, codec_specific);
    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);

    ASSERT_TRUE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * Test whether each provider of type
 * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
 * Opus hardware encoding config
 */
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
       StartAndEndA2dpOpusDecodingHardwareSession) {
  if (!IsOffloadSupported()) {
    return;
  }

  CodecConfiguration codec_config = {
      .codecType = CodecType::OPUS,
      .encodedAudioBitrate = 990000,
      .peerMtu = 1005,
      .isScmstEnabled = false,
  };
  auto opus_codec_specifics = GetOpusCodecSpecificSupportedList(true);

  for (auto& codec_specific : opus_codec_specifics) {
    copy_codec_specific(codec_config.config, codec_specific);
    DataMQDesc mq_desc;
    auto aidl_retval = audio_provider_->startSession(
        audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);

    ASSERT_TRUE(aidl_retval.isOk());
    EXPECT_TRUE(audio_provider_->endSession().isOk());
  }
}

/**
 * Test whether each provider of type
 * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
 * AptX hardware encoding config
 */
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
       StartAndEndA2dpAptxDecodingHardwareSession) {
  if (!IsOffloadSupported()) {
    return;
  }

  for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
    CodecConfiguration codec_config = {
        .codecType = codec_type,
        .encodedAudioBitrate =
            (codec_type == CodecType::APTX ? 352000 : 576000),
        .peerMtu = 1005,
        .isScmstEnabled = false,
    };

    auto aptx_codec_specifics = GetAptxCodecSpecificSupportedList(
        (codec_type == CodecType::APTX_HD ? true : false), true);

    for (auto& codec_specific : aptx_codec_specifics) {
      copy_codec_specific(codec_config.config, codec_specific);
      DataMQDesc mq_desc;
      auto aidl_retval = audio_provider_->startSession(
          audio_port_, AudioConfiguration(codec_config), latency_modes,
          &mq_desc);

      ASSERT_TRUE(aidl_retval.isOk());
      EXPECT_TRUE(audio_provider_->endSession().isOk());
    }
  }
}

/**
 * Test whether each provider of type
 * SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
 * an invalid codec config
 */
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
       StartAndEndA2dpDecodingHardwareSessionInvalidCodecConfig) {
  if (!IsOffloadSupported()) {
    return;
  }
  ASSERT_NE(audio_provider_, nullptr);

  std::vector<CodecConfiguration::CodecSpecific> codec_specifics;
  for (auto codec_type : ndk::enum_range<CodecType>()) {
    switch (codec_type) {
      case CodecType::SBC:
        codec_specifics = GetSbcCodecSpecificSupportedList(false);
        break;
      case CodecType::AAC:
        codec_specifics = GetAacCodecSpecificSupportedList(false);
        break;
      case CodecType::LDAC:
        codec_specifics = GetLdacCodecSpecificSupportedList(false);
        break;
      case CodecType::APTX:
        codec_specifics = GetAptxCodecSpecificSupportedList(false, false);
        break;
      case CodecType::APTX_HD:
        codec_specifics = GetAptxCodecSpecificSupportedList(true, false);
        break;
      case CodecType::OPUS:
        codec_specifics = GetOpusCodecSpecificSupportedList(false);
        continue;
      case CodecType::APTX_ADAPTIVE:
      case CodecType::APTX_ADAPTIVE_LE:
      case CodecType::APTX_ADAPTIVE_LEX:
      case CodecType::LC3:
      case CodecType::VENDOR:
      case CodecType::UNKNOWN:
        codec_specifics.clear();
        break;
    }
    if (codec_specifics.empty()) {
      continue;
    }

    CodecConfiguration codec_config = {
        .codecType = codec_type,
        .encodedAudioBitrate = 328000,
        .peerMtu = 1005,
        .isScmstEnabled = false,
    };
    for (auto codec_specific : codec_specifics) {
      copy_codec_specific(codec_config.config, codec_specific);
      DataMQDesc mq_desc;
      auto aidl_retval = audio_provider_->startSession(
          audio_port_, AudioConfiguration(codec_config), latency_modes,
          &mq_desc);

      // AIDL call should fail on invalid codec
      ASSERT_FALSE(aidl_retval.isOk());
      EXPECT_TRUE(audio_provider_->endSession().isOk());
    }
  }
}

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
    BluetoothAudioProviderFactoryAidl);
INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl,
                         testing::ValuesIn(android::getAidlHalInstanceNames(
                             IBluetoothAudioProviderFactory::descriptor)),
                         android::PrintInstanceNameToString);

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
    BluetoothAudioProviderA2dpEncodingSoftwareAidl);
INSTANTIATE_TEST_SUITE_P(PerInstance,
                         BluetoothAudioProviderA2dpEncodingSoftwareAidl,
                         testing::ValuesIn(android::getAidlHalInstanceNames(
                             IBluetoothAudioProviderFactory::descriptor)),
                         android::PrintInstanceNameToString);

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
    BluetoothAudioProviderA2dpEncodingHardwareAidl);
INSTANTIATE_TEST_SUITE_P(PerInstance,
                         BluetoothAudioProviderA2dpEncodingHardwareAidl,
                         testing::ValuesIn(android::getAidlHalInstanceNames(
                             IBluetoothAudioProviderFactory::descriptor)),
                         android::PrintInstanceNameToString);

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
    BluetoothAudioProviderHearingAidSoftwareAidl);
INSTANTIATE_TEST_SUITE_P(PerInstance,
                         BluetoothAudioProviderHearingAidSoftwareAidl,
                         testing::ValuesIn(android::getAidlHalInstanceNames(
                             IBluetoothAudioProviderFactory::descriptor)),
                         android::PrintInstanceNameToString);

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
    BluetoothAudioProviderLeAudioOutputSoftwareAidl);
INSTANTIATE_TEST_SUITE_P(PerInstance,
                         BluetoothAudioProviderLeAudioOutputSoftwareAidl,
                         testing::ValuesIn(android::getAidlHalInstanceNames(
                             IBluetoothAudioProviderFactory::descriptor)),
                         android::PrintInstanceNameToString);

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
    BluetoothAudioProviderLeAudioInputSoftwareAidl);
INSTANTIATE_TEST_SUITE_P(PerInstance,
                         BluetoothAudioProviderLeAudioInputSoftwareAidl,
                         testing::ValuesIn(android::getAidlHalInstanceNames(
                             IBluetoothAudioProviderFactory::descriptor)),
                         android::PrintInstanceNameToString);

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
    BluetoothAudioProviderLeAudioOutputHardwareAidl);
INSTANTIATE_TEST_SUITE_P(PerInstance,
                         BluetoothAudioProviderLeAudioOutputHardwareAidl,
                         testing::ValuesIn(android::getAidlHalInstanceNames(
                             IBluetoothAudioProviderFactory::descriptor)),
                         android::PrintInstanceNameToString);

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
    BluetoothAudioProviderLeAudioInputHardwareAidl);
INSTANTIATE_TEST_SUITE_P(PerInstance,
                         BluetoothAudioProviderLeAudioInputHardwareAidl,
                         testing::ValuesIn(android::getAidlHalInstanceNames(
                             IBluetoothAudioProviderFactory::descriptor)),
                         android::PrintInstanceNameToString);

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
    BluetoothAudioProviderLeAudioBroadcastSoftwareAidl);
INSTANTIATE_TEST_SUITE_P(PerInstance,
                         BluetoothAudioProviderLeAudioBroadcastSoftwareAidl,
                         testing::ValuesIn(android::getAidlHalInstanceNames(
                             IBluetoothAudioProviderFactory::descriptor)),
                         android::PrintInstanceNameToString);

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
    BluetoothAudioProviderLeAudioBroadcastHardwareAidl);
INSTANTIATE_TEST_SUITE_P(PerInstance,
                         BluetoothAudioProviderLeAudioBroadcastHardwareAidl,
                         testing::ValuesIn(android::getAidlHalInstanceNames(
                             IBluetoothAudioProviderFactory::descriptor)),
                         android::PrintInstanceNameToString);

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
    BluetoothAudioProviderA2dpDecodingSoftwareAidl);
INSTANTIATE_TEST_SUITE_P(PerInstance,
                         BluetoothAudioProviderA2dpDecodingSoftwareAidl,
                         testing::ValuesIn(android::getAidlHalInstanceNames(
                             IBluetoothAudioProviderFactory::descriptor)),
                         android::PrintInstanceNameToString);

GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
    BluetoothAudioProviderA2dpDecodingHardwareAidl);
INSTANTIATE_TEST_SUITE_P(PerInstance,
                         BluetoothAudioProviderA2dpDecodingHardwareAidl,
                         testing::ValuesIn(android::getAidlHalInstanceNames(
                             IBluetoothAudioProviderFactory::descriptor)),
                         android::PrintInstanceNameToString);

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  ABinderProcess_setThreadPoolMaxThreadCount(1);
  ABinderProcess_startThreadPool();
  return RUN_ALL_TESTS();
}
