diff --git a/bluetooth/audio/2.0/vts/OWNERS b/bluetooth/audio/2.0/vts/OWNERS
new file mode 100644
index 0000000..b6c0813
--- /dev/null
+++ b/bluetooth/audio/2.0/vts/OWNERS
@@ -0,0 +1,3 @@
+include platform/system/bt:/OWNERS
+
+cheneyni@google.com
diff --git a/bluetooth/audio/2.0/vts/functional/Android.bp b/bluetooth/audio/2.0/vts/functional/Android.bp
new file mode 100644
index 0000000..b672fe4
--- /dev/null
+++ b/bluetooth/audio/2.0/vts/functional/Android.bp
@@ -0,0 +1,12 @@
+cc_test {
+    name: "VtsHalBluetoothAudioV2_0TargetTest",
+    defaults: ["VtsHalTargetTestDefaults"],
+    srcs: ["VtsHalBluetoothAudioV2_0TargetTest.cpp"],
+    static_libs: [
+        "android.hardware.audio.common@5.0",
+        "android.hardware.bluetooth.audio@2.0",
+    ],
+    shared_libs: [
+        "libfmq",
+    ],
+}
diff --git a/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp b/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp
new file mode 100644
index 0000000..9572d3f
--- /dev/null
+++ b/bluetooth/audio/2.0/vts/functional/VtsHalBluetoothAudioV2_0TargetTest.cpp
@@ -0,0 +1,915 @@
+/*
+ * Copyright 2018 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_audio_hidl_hal_test"
+
+#include <android-base/logging.h>
+#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h>
+#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvider.h>
+#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvidersFactory.h>
+#include <fmq/MessageQueue.h>
+#include <hidl/MQDescriptor.h>
+#include <utils/Log.h>
+
+#include <VtsHalHidlTargetCallbackBase.h>
+#include <VtsHalHidlTargetTestBase.h>
+#include <VtsHalHidlTargetTestEnvBase.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::kSynchronizedReadWrite;
+using ::android::hardware::MessageQueue;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::audio::common::V5_0::SourceMetadata;
+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::AudioCapabilities;
+using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
+using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
+using ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
+using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioProvider;
+using ::android::hardware::bluetooth::audio::V2_0::
+    IBluetoothAudioProvidersFactory;
+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::PcmParameters;
+using ::android::hardware::bluetooth::audio::V2_0::SampleRate;
+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 ::android::hardware::bluetooth::audio::V2_0::SessionType;
+
+using DataMQ = MessageQueue<uint8_t, kSynchronizedReadWrite>;
+using BluetoothAudioStatus =
+    ::android::hardware::bluetooth::audio::V2_0::Status;
+using CodecSpecificConfig = ::android::hardware::bluetooth::audio::V2_0::
+    CodecConfiguration::CodecSpecific;
+
+namespace {
+constexpr SampleRate a2dp_sample_rates[5] = {
+    SampleRate::RATE_UNKNOWN, SampleRate::RATE_44100, SampleRate::RATE_48000,
+    SampleRate::RATE_88200, SampleRate::RATE_96000};
+constexpr BitsPerSample a2dp_bits_per_samples[4] = {
+    BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16, BitsPerSample::BITS_24,
+    BitsPerSample::BITS_32};
+constexpr ChannelMode a2dp_channel_modes[3] = {
+    ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+constexpr CodecType a2dp_codec_types[6] = {CodecType::UNKNOWN, CodecType::SBC,
+                                           CodecType::AAC,     CodecType::APTX,
+                                           CodecType::APTX_HD, CodecType::LDAC};
+
+template <typename T>
+std::vector<T> ExtractValuesFromBitmask(T bitmasks, uint32_t bitfield,
+                                        bool supported) {
+  std::vector<T> retval;
+  if (!supported) {
+    retval.push_back(static_cast<T>(bitfield));
+  }
+  uint32_t test_bit = 0x00000001;
+  while (test_bit <= static_cast<uint32_t>(bitmasks) && test_bit <= bitfield) {
+    if ((bitfield & test_bit)) {
+      if ((!(bitmasks & test_bit) && !supported) ||
+          ((bitmasks & test_bit) && supported)) {
+        retval.push_back(static_cast<T>(test_bit));
+      }
+    }
+    if (test_bit == 0x80000000) {
+      break;
+    }
+    test_bit <<= 1;
+  }
+  return retval;
+}
+}  // namespace
+
+// Test environment for Bluetooth Audio HAL.
+class BluetoothAudioHidlEnvironment
+    : public ::testing::VtsHalHidlTargetTestEnvBase {
+ public:
+  // get the test environment singleton
+  static BluetoothAudioHidlEnvironment* Instance() {
+    static BluetoothAudioHidlEnvironment* instance =
+        new BluetoothAudioHidlEnvironment;
+    return instance;
+  }
+
+  virtual void registerTestServices() override {
+    registerTestService<IBluetoothAudioProvidersFactory>();
+  }
+
+ private:
+  BluetoothAudioHidlEnvironment() {}
+};
+
+// The base test class for Bluetooth Audio HAL.
+class BluetoothAudioProvidersFactoryHidlTest
+    : public ::testing::VtsHalHidlTargetTestBase {
+ public:
+  virtual void SetUp() override {
+    providers_factory_ = ::testing::VtsHalHidlTargetTestBase::getService<
+        IBluetoothAudioProvidersFactory>(
+        BluetoothAudioHidlEnvironment::Instance()
+            ->getServiceName<IBluetoothAudioProvidersFactory>());
+    ASSERT_NE(providers_factory_, nullptr);
+  }
+
+  virtual void TearDown() override { providers_factory_ = nullptr; }
+
+  // A simple test implementation of IBluetoothAudioPort.
+  class BluetoothAudioPort : public ::testing::VtsHalHidlTargetCallbackBase<
+                                 BluetoothAudioProvidersFactoryHidlTest>,
+                             public IBluetoothAudioPort {
+    BluetoothAudioProvidersFactoryHidlTest& parent_;
+
+   public:
+    BluetoothAudioPort(BluetoothAudioProvidersFactoryHidlTest& parent)
+        : parent_(parent) {}
+    virtual ~BluetoothAudioPort() = default;
+
+    Return<void> startStream() override {
+      parent_.audio_provider_->streamStarted(BluetoothAudioStatus::SUCCESS);
+      return Void();
+    }
+
+    Return<void> suspendStream() override {
+      parent_.audio_provider_->streamSuspended(BluetoothAudioStatus::SUCCESS);
+      return Void();
+    }
+
+    Return<void> stopStream() override { return Void(); }
+
+    Return<void> getPresentationPosition(getPresentationPosition_cb _hidl_cb) {
+      _hidl_cb(BluetoothAudioStatus::SUCCESS, 0, 0, {.tvSec = 0, .tvNSec = 0});
+      return Void();
+    }
+
+    Return<void> updateMetadata(const SourceMetadata& sourceMetadata __unused) {
+      return Void();
+    }
+  };
+
+  void GetProviderCapabilitiesHelper(const SessionType& session_type) {
+    temp_provider_capabilities_.clear();
+    auto hidl_cb = [& temp_capabilities = this->temp_provider_capabilities_](
+                       const hidl_vec<AudioCapabilities>& audioCapabilities) {
+      for (auto audioCapability : audioCapabilities)
+        temp_capabilities.push_back(audioCapability);
+    };
+    auto hidl_retval =
+        providers_factory_->getProviderCapabilities(session_type, hidl_cb);
+    // HIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(hidl_retval.isOk());
+    if (session_type == SessionType::UNKNOWN) {
+      ASSERT_TRUE(temp_provider_capabilities_.empty());
+    } else if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_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].getDiscriminator(),
+                AudioCapabilities::hidl_discriminator::pcmCapabilities);
+    } else {
+      uint32_t codec_type_bitmask = 0x00000000;
+      // empty capability means offload is unsupported
+      for (auto audio_capability : temp_provider_capabilities_) {
+        ASSERT_EQ(audio_capability.getDiscriminator(),
+                  AudioCapabilities::hidl_discriminator::codecCapabilities);
+        const CodecCapabilities& codec_capabilities =
+            audio_capability.codecCapabilities();
+        // Every codec can present once at most
+        ASSERT_EQ(codec_type_bitmask &
+                      static_cast<uint32_t>(codec_capabilities.codecType),
+                  0);
+        switch (codec_capabilities.codecType) {
+          case CodecType::SBC:
+            ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(),
+                      CodecCapabilities::Capabilities::hidl_discriminator::
+                          sbcCapabilities);
+            break;
+          case CodecType::AAC:
+            ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(),
+                      CodecCapabilities::Capabilities::hidl_discriminator::
+                          aacCapabilities);
+            break;
+          case CodecType::APTX:
+            FALLTHROUGH_INTENDED;
+          case CodecType::APTX_HD:
+            ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(),
+                      CodecCapabilities::Capabilities::hidl_discriminator::
+                          aptxCapabilities);
+            break;
+          case CodecType::LDAC:
+            ASSERT_EQ(codec_capabilities.capabilities.getDiscriminator(),
+                      CodecCapabilities::Capabilities::hidl_discriminator::
+                          ldacCapabilities);
+            break;
+          case CodecType::UNKNOWN:
+            break;
+        }
+        codec_type_bitmask |= codec_capabilities.codecType;
+      }
+    }
+  }
+
+  // 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) {
+    BluetoothAudioStatus cb_status;
+    auto hidl_cb = [&cb_status, &local_provider = this->audio_provider_](
+                       BluetoothAudioStatus status,
+                       const sp<IBluetoothAudioProvider>& provider) {
+      cb_status = status;
+      local_provider = provider;
+    };
+    auto hidl_retval = providers_factory_->openProvider(session_type, hidl_cb);
+    // HIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(hidl_retval.isOk());
+    if (cb_status == BluetoothAudioStatus::SUCCESS) {
+      ASSERT_NE(session_type, SessionType::UNKNOWN);
+      ASSERT_NE(audio_provider_, nullptr);
+      audio_port_ = new BluetoothAudioPort(*this);
+    } else {
+      // A2DP_HARDWARE_OFFLOAD_DATAPATH is optional
+      ASSERT_TRUE(session_type == SessionType::UNKNOWN ||
+                  session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+      ASSERT_EQ(cb_status, BluetoothAudioStatus::FAILURE);
+      ASSERT_EQ(audio_provider_, nullptr);
+    }
+  }
+
+  bool IsPcmParametersSupported(const PcmParameters& pcm_parameters) {
+    if (temp_provider_capabilities_.size() != 1 ||
+        temp_provider_capabilities_[0].getDiscriminator() !=
+            AudioCapabilities::hidl_discriminator::pcmCapabilities) {
+      return false;
+    }
+    auto pcm_capability = temp_provider_capabilities_[0].pcmCapabilities();
+    bool is_parameter_valid =
+        (pcm_parameters.sampleRate != SampleRate::RATE_UNKNOWN &&
+         pcm_parameters.channelMode != ChannelMode::UNKNOWN &&
+         pcm_parameters.bitsPerSample != BitsPerSample::BITS_UNKNOWN);
+    bool is_parameter_in_capability =
+        (pcm_capability.sampleRate & pcm_parameters.sampleRate &&
+         pcm_capability.channelMode & pcm_parameters.channelMode &&
+         pcm_capability.bitsPerSample & pcm_parameters.bitsPerSample);
+    return is_parameter_valid && is_parameter_in_capability;
+  }
+
+  sp<IBluetoothAudioProvidersFactory> providers_factory_;
+
+  // temp storage saves the specified provider capability by
+  // GetProviderCapabilitiesHelper()
+  std::vector<AudioCapabilities> temp_provider_capabilities_;
+
+  // audio_provider_ is for the Bluetooth stack to report session started/ended
+  // and handled audio stream started / suspended
+  sp<IBluetoothAudioProvider> audio_provider_;
+
+  // audio_port_ is for the Audio HAL to send stream start/suspend/stop commands
+  // to Bluetooth stack
+  sp<IBluetoothAudioPort> audio_port_;
+
+  static constexpr SessionType session_types_[4] = {
+      SessionType::UNKNOWN, SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
+      SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH,
+      SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH};
+};
+
+/**
+ * Test whether we can get the FactoryService from HIDL
+ */
+TEST_F(BluetoothAudioProvidersFactoryHidlTest, GetProvidersFactoryService) {}
+
+/**
+ * Test whether we can open a provider for each provider returned by
+ * getProviderCapabilities() with non-empty capabalities
+ */
+TEST_F(BluetoothAudioProvidersFactoryHidlTest,
+       OpenProviderAndCheckCapabilitiesBySession) {
+  for (auto session_type : session_types_) {
+    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 BluetoothAudioProviderA2dpSoftwareHidlTest
+    : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProvidersFactoryHidlTest::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;
+    BluetoothAudioProvidersFactoryHidlTest::TearDown();
+  }
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_F(BluetoothAudioProviderA2dpSoftwareHidlTest, OpenA2dpSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
+ * different PCM config
+ */
+TEST_F(BluetoothAudioProviderA2dpSoftwareHidlTest,
+       StartAndEndA2dpSoftwareSessionWithPossiblePcmConfig) {
+  bool is_codec_config_valid;
+  std::unique_ptr<DataMQ> tempDataMQ;
+  auto hidl_cb = [&is_codec_config_valid, &tempDataMQ](
+                     BluetoothAudioStatus status,
+                     const DataMQ::Descriptor& dataMQ) {
+    if (is_codec_config_valid) {
+      ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS);
+      ASSERT_TRUE(dataMQ.isHandleValid());
+      tempDataMQ.reset(new DataMQ(dataMQ));
+    } else {
+      EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+      EXPECT_FALSE(dataMQ.isHandleValid());
+    }
+  };
+  AudioConfiguration audio_config = {};
+  PcmParameters pcm_parameters = {};
+  for (auto sample_rate : a2dp_sample_rates) {
+    pcm_parameters.sampleRate = sample_rate;
+    for (auto bits_per_sample : a2dp_bits_per_samples) {
+      pcm_parameters.bitsPerSample = bits_per_sample;
+      for (auto channel_mode : a2dp_channel_modes) {
+        pcm_parameters.channelMode = channel_mode;
+        is_codec_config_valid = IsPcmParametersSupported(pcm_parameters);
+        audio_config.pcmConfig(pcm_parameters);
+        auto hidl_retval =
+            audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+        // HIDL calls should not be failed and callback has to be executed
+        ASSERT_TRUE(hidl_retval.isOk());
+        if (is_codec_config_valid) {
+          EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid());
+        }
+        EXPECT_TRUE(audio_provider_->endSession().isOk());
+      }  // ChannelMode
+    }    // BitsPerSampple
+  }      // SampleRate
+}
+
+/**
+ * openProvider A2DP_HARDWARE_OFFLOAD_DATAPATH
+ */
+class BluetoothAudioProviderA2dpHardwareHidlTest
+    : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProvidersFactoryHidlTest::SetUp();
+    GetProviderCapabilitiesHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+    OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+    ASSERT_TRUE(temp_provider_capabilities_.empty() ||
+                audio_provider_ != nullptr);
+  }
+
+  virtual void TearDown() override {
+    audio_port_ = nullptr;
+    audio_provider_ = nullptr;
+    BluetoothAudioProvidersFactoryHidlTest::TearDown();
+  }
+
+  bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
+
+  void GetOffloadCodecCapabilityHelper(const CodecType& codec_type) {
+    temp_codec_capabilities_ = {};
+    for (auto codec_capability : temp_provider_capabilities_) {
+      if (codec_capability.codecCapabilities().codecType != codec_type) {
+        continue;
+      }
+      temp_codec_capabilities_ = codec_capability.codecCapabilities();
+    }
+  }
+
+  std::vector<CodecSpecificConfig> GetSbcCodecSpecificSupportedList(
+      bool supported) {
+    std::vector<CodecSpecificConfig> sbc_codec_specifics;
+    GetOffloadCodecCapabilityHelper(CodecType::SBC);
+    if (temp_codec_capabilities_.codecType != CodecType::SBC) {
+      return sbc_codec_specifics;
+    }
+    // parse the capability
+    SbcParameters sbc_capability =
+        temp_codec_capabilities_.capabilities.sbcCapabilities();
+    if (sbc_capability.minBitpool > sbc_capability.maxBitpool) {
+      return sbc_codec_specifics;
+    }
+    std::vector<SampleRate> sample_rates = ExtractValuesFromBitmask<SampleRate>(
+        sbc_capability.sampleRate, 0xff, supported);
+    std::vector<SbcChannelMode> channel_modes =
+        ExtractValuesFromBitmask<SbcChannelMode>(sbc_capability.channelMode,
+                                                 0x0f, supported);
+    std::vector<SbcBlockLength> block_lengths =
+        ExtractValuesFromBitmask<SbcBlockLength>(sbc_capability.blockLength,
+                                                 0xf0, supported);
+    std::vector<SbcNumSubbands> num_subbandss =
+        ExtractValuesFromBitmask<SbcNumSubbands>(sbc_capability.numSubbands,
+                                                 0x0c, supported);
+    std::vector<SbcAllocMethod> alloc_methods =
+        ExtractValuesFromBitmask<SbcAllocMethod>(sbc_capability.allocMethod,
+                                                 0x03, supported);
+    std::vector<BitsPerSample> bits_per_samples =
+        ExtractValuesFromBitmask<BitsPerSample>(sbc_capability.bitsPerSample,
+                                                0x07, supported);
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    CodecSpecificConfig codec_specific = {};
+    SbcParameters sbc_data;
+    for (auto sample_rate : sample_rates) {
+      for (auto channel_mode : channel_modes) {
+        for (auto block_length : block_lengths) {
+          for (auto num_subbands : num_subbandss) {
+            for (auto alloc_method : alloc_methods) {
+              for (auto bits_per_sample : bits_per_samples) {
+                sbc_data = {.sampleRate = 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};
+                codec_specific.sbcConfig(sbc_data);
+                sbc_codec_specifics.push_back(codec_specific);
+              }
+            }
+          }
+        }
+      }
+    }
+    return sbc_codec_specifics;
+  }
+
+  std::vector<CodecSpecificConfig> GetAacCodecSpecificSupportedList(
+      bool supported) {
+    std::vector<CodecSpecificConfig> aac_codec_specifics;
+    GetOffloadCodecCapabilityHelper(CodecType::AAC);
+    if (temp_codec_capabilities_.codecType != CodecType::AAC) {
+      return aac_codec_specifics;
+    }
+    // parse the capability
+    AacParameters aac_capability =
+        temp_codec_capabilities_.capabilities.aacCapabilities();
+    std::vector<AacObjectType> object_types =
+        ExtractValuesFromBitmask<AacObjectType>(aac_capability.objectType, 0xf0,
+                                                supported);
+    std::vector<SampleRate> sample_rates = ExtractValuesFromBitmask<SampleRate>(
+        aac_capability.sampleRate, 0xff, supported);
+    std::vector<ChannelMode> channel_modes =
+        ExtractValuesFromBitmask<ChannelMode>(aac_capability.channelMode, 0x03,
+                                              supported);
+    std::vector<AacVariableBitRate> variable_bit_rate_enableds = {
+        AacVariableBitRate::DISABLED};
+    if (aac_capability.variableBitRateEnabled == AacVariableBitRate::ENABLED) {
+      variable_bit_rate_enableds.push_back(AacVariableBitRate::ENABLED);
+    }
+    std::vector<BitsPerSample> bits_per_samples =
+        ExtractValuesFromBitmask<BitsPerSample>(aac_capability.bitsPerSample,
+                                                0x07, supported);
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    CodecSpecificConfig codec_specific = {};
+    AacParameters aac_data;
+    for (auto object_type : object_types) {
+      for (auto sample_rate : sample_rates) {
+        for (auto channel_mode : channel_modes) {
+          for (auto variable_bit_rate_enabled : variable_bit_rate_enableds) {
+            for (auto bits_per_sample : bits_per_samples) {
+              aac_data = {.objectType = object_type,
+                          .sampleRate = sample_rate,
+                          .channelMode = channel_mode,
+                          .variableBitRateEnabled = variable_bit_rate_enabled,
+                          .bitsPerSample = bits_per_sample};
+              codec_specific.aacConfig(aac_data);
+              aac_codec_specifics.push_back(codec_specific);
+            }
+          }
+        }
+      }
+    }
+    return aac_codec_specifics;
+  }
+
+  std::vector<CodecSpecificConfig> GetLdacCodecSpecificSupportedList(
+      bool supported) {
+    std::vector<CodecSpecificConfig> ldac_codec_specifics;
+    GetOffloadCodecCapabilityHelper(CodecType::LDAC);
+    if (temp_codec_capabilities_.codecType != CodecType::LDAC) {
+      return ldac_codec_specifics;
+    }
+    // parse the capability
+    LdacParameters ldac_capability =
+        temp_codec_capabilities_.capabilities.ldacCapabilities();
+    std::vector<SampleRate> sample_rates = ExtractValuesFromBitmask<SampleRate>(
+        ldac_capability.sampleRate, 0xff, supported);
+    std::vector<LdacChannelMode> channel_modes =
+        ExtractValuesFromBitmask<LdacChannelMode>(ldac_capability.channelMode,
+                                                  0x07, supported);
+    std::vector<LdacQualityIndex> quality_indexes = {
+        LdacQualityIndex::QUALITY_HIGH, LdacQualityIndex::QUALITY_MID,
+        LdacQualityIndex::QUALITY_LOW, LdacQualityIndex::QUALITY_ABR};
+    std::vector<BitsPerSample> bits_per_samples =
+        ExtractValuesFromBitmask<BitsPerSample>(ldac_capability.bitsPerSample,
+                                                0x07, supported);
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    CodecSpecificConfig codec_specific = {};
+    LdacParameters ldac_data;
+    for (auto sample_rate : sample_rates) {
+      for (auto channel_mode : channel_modes) {
+        for (auto quality_index : quality_indexes) {
+          for (auto bits_per_sample : bits_per_samples) {
+            ldac_data = {.sampleRate = sample_rate,
+                         .channelMode = channel_mode,
+                         .qualityIndex = quality_index,
+                         .bitsPerSample = bits_per_sample};
+            codec_specific.ldacConfig(ldac_data);
+            ldac_codec_specifics.push_back(codec_specific);
+          }
+        }
+      }
+    }
+    return ldac_codec_specifics;
+  }
+
+  std::vector<CodecSpecificConfig> GetAptxCodecSpecificSupportedList(
+      bool is_hd, bool supported) {
+    std::vector<CodecSpecificConfig> aptx_codec_specifics;
+    GetOffloadCodecCapabilityHelper(
+        (is_hd ? CodecType::APTX_HD : CodecType::APTX));
+    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
+    AptxParameters aptx_capability =
+        temp_codec_capabilities_.capabilities.aptxCapabilities();
+    std::vector<SampleRate> sample_rates = ExtractValuesFromBitmask<SampleRate>(
+        aptx_capability.sampleRate, 0xff, supported);
+    std::vector<ChannelMode> channel_modes =
+        ExtractValuesFromBitmask<ChannelMode>(aptx_capability.channelMode, 0x03,
+                                              supported);
+    std::vector<BitsPerSample> bits_per_samples =
+        ExtractValuesFromBitmask<BitsPerSample>(aptx_capability.bitsPerSample,
+                                                0x07, supported);
+    // combine those parameters into one list of
+    // CodecConfiguration::CodecSpecific
+    CodecSpecificConfig codec_specific = {};
+    AptxParameters aptx_data;
+    for (auto sample_rate : sample_rates) {
+      for (auto channel_mode : channel_modes) {
+        for (auto bits_per_sample : bits_per_samples) {
+          aptx_data = {.sampleRate = sample_rate,
+                       .channelMode = channel_mode,
+                       .bitsPerSample = bits_per_sample};
+          codec_specific.aptxConfig(aptx_data);
+          aptx_codec_specifics.push_back(codec_specific);
+        }
+      }
+    }
+    return aptx_codec_specifics;
+  }
+
+  // temp storage saves the specified codec capability by
+  // GetOffloadCodecCapabilityHelper()
+  CodecCapabilities temp_codec_capabilities_;
+};
+
+/**
+ * Test whether we can open a provider of type
+ */
+TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest, OpenA2dpHardwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
+ * SBC hardware encoding config
+ */
+TEST_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+       StartAndEndA2dpSbcHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {};
+  codec_config.codecType = CodecType::SBC;
+  codec_config.encodedAudioBitrate = 328000;
+  codec_config.peerMtu = 1005;
+  codec_config.isScmstEnabled = false;
+  AudioConfiguration audio_config = {};
+  std::vector<CodecSpecificConfig> sbc_codec_specifics =
+      GetSbcCodecSpecificSupportedList(true);
+  auto hidl_cb = [](BluetoothAudioStatus status,
+                    const DataMQ::Descriptor& dataMQ) {
+    EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS);
+    EXPECT_FALSE(dataMQ.isHandleValid());
+  };
+  for (auto codec_specific : sbc_codec_specifics) {
+    codec_config.config = codec_specific;
+    audio_config.codecConfig(codec_config);
+    auto hidl_retval =
+        audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+    // HIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(hidl_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_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+       StartAndEndA2dpAacHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {};
+  codec_config.codecType = CodecType::AAC;
+  codec_config.encodedAudioBitrate = 320000;
+  codec_config.peerMtu = 1005;
+  codec_config.isScmstEnabled = false;
+  AudioConfiguration audio_config = {};
+  std::vector<CodecSpecificConfig> aac_codec_specifics =
+      GetAacCodecSpecificSupportedList(true);
+  auto hidl_cb = [](BluetoothAudioStatus status,
+                    const DataMQ::Descriptor& dataMQ) {
+    EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS);
+    EXPECT_FALSE(dataMQ.isHandleValid());
+  };
+  for (auto codec_specific : aac_codec_specifics) {
+    codec_config.config = codec_specific;
+    audio_config.codecConfig(codec_config);
+    auto hidl_retval =
+        audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+    // HIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(hidl_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_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+       StartAndEndA2dpLdacHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  CodecConfiguration codec_config = {};
+  codec_config.codecType = CodecType::LDAC;
+  codec_config.encodedAudioBitrate = 990000;
+  codec_config.peerMtu = 1005;
+  codec_config.isScmstEnabled = false;
+  AudioConfiguration audio_config = {};
+  std::vector<CodecSpecificConfig> ldac_codec_specifics =
+      GetLdacCodecSpecificSupportedList(true);
+  auto hidl_cb = [](BluetoothAudioStatus status,
+                    const DataMQ::Descriptor& dataMQ) {
+    EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS);
+    EXPECT_FALSE(dataMQ.isHandleValid());
+  };
+  for (auto codec_specific : ldac_codec_specifics) {
+    codec_config.config = codec_specific;
+    audio_config.codecConfig(codec_config);
+    auto hidl_retval =
+        audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+    // HIDL calls should not be failed and callback has to be executed
+    ASSERT_TRUE(hidl_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_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+       StartAndEndA2dpAptxHardwareSession) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+
+  for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
+    CodecConfiguration codec_config = {};
+    codec_config.codecType = codec_type;
+    codec_config.encodedAudioBitrate =
+        (codec_type == CodecType::APTX ? 352000 : 576000);
+    codec_config.peerMtu = 1005;
+    codec_config.isScmstEnabled = false;
+    AudioConfiguration audio_config = {};
+    std::vector<CodecSpecificConfig> aptx_codec_specifics =
+        GetAptxCodecSpecificSupportedList(
+            (codec_type == CodecType::APTX_HD ? true : false), true);
+    auto hidl_cb = [](BluetoothAudioStatus status,
+                      const DataMQ::Descriptor& dataMQ) {
+      EXPECT_EQ(status, BluetoothAudioStatus::SUCCESS);
+      EXPECT_FALSE(dataMQ.isHandleValid());
+    };
+    for (auto codec_specific : aptx_codec_specifics) {
+      codec_config.config = codec_specific;
+      audio_config.codecConfig(codec_config);
+      auto hidl_retval =
+          audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+      // HIDL calls should not be failed and callback has to be executed
+      ASSERT_TRUE(hidl_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_F(BluetoothAudioProviderA2dpHardwareHidlTest,
+       StartAndEndA2dpHardwareSessionInvalidCodecConfig) {
+  if (!IsOffloadSupported()) {
+    return;
+  }
+  ASSERT_NE(audio_provider_, nullptr);
+
+  std::vector<CodecSpecificConfig> codec_specifics;
+  for (auto codec_type : a2dp_codec_types) {
+    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::UNKNOWN:
+        codec_specifics.clear();
+        break;
+    }
+    if (codec_specifics.empty()) {
+      continue;
+    }
+
+    CodecConfiguration codec_config = {};
+    codec_config.codecType = codec_type;
+    codec_config.encodedAudioBitrate = 328000;
+    codec_config.peerMtu = 1005;
+    codec_config.isScmstEnabled = false;
+    AudioConfiguration audio_config = {};
+    auto hidl_cb = [](BluetoothAudioStatus status,
+                      const DataMQ::Descriptor& dataMQ) {
+      EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+      EXPECT_FALSE(dataMQ.isHandleValid());
+    };
+    for (auto codec_specific : codec_specifics) {
+      codec_config.config = codec_specific;
+      audio_config.codecConfig(codec_config);
+      auto hidl_retval =
+          audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+      // HIDL calls should not be failed and callback has to be executed
+      ASSERT_TRUE(hidl_retval.isOk());
+      EXPECT_TRUE(audio_provider_->endSession().isOk());
+    }
+  }
+}
+
+/**
+ * openProvider HEARING_AID_SOFTWARE_ENCODING_DATAPATH
+ */
+class BluetoothAudioProviderHearingAidSoftwareHidlTest
+    : public BluetoothAudioProvidersFactoryHidlTest {
+ public:
+  virtual void SetUp() override {
+    BluetoothAudioProvidersFactoryHidlTest::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;
+    BluetoothAudioProvidersFactoryHidlTest::TearDown();
+  }
+
+  static constexpr SampleRate hearing_aid_sample_rates_[3] = {
+      SampleRate::RATE_UNKNOWN, SampleRate::RATE_16000, SampleRate::RATE_24000};
+  static constexpr BitsPerSample hearing_aid_bits_per_samples_[3] = {
+      BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16,
+      BitsPerSample::BITS_24};
+  static constexpr ChannelMode hearing_aid_channel_modes_[3] = {
+      ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+};
+
+/**
+ * Test whether each provider of type
+ * SessionType::HEARING_AID_HARDWARE_ENCODING_DATAPATH can be started and
+ * stopped with SBC hardware encoding config
+ */
+TEST_F(BluetoothAudioProviderHearingAidSoftwareHidlTest,
+       OpenHearingAidSoftwareProvider) {}
+
+/**
+ * Test whether each provider of type
+ * SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH can be started and
+ * stopped with different PCM config
+ */
+TEST_F(BluetoothAudioProviderHearingAidSoftwareHidlTest,
+       StartAndEndHearingAidSessionWithPossiblePcmConfig) {
+  bool is_codec_config_valid;
+  std::unique_ptr<DataMQ> tempDataMQ;
+  auto hidl_cb = [&is_codec_config_valid, &tempDataMQ](
+                     BluetoothAudioStatus status,
+                     const DataMQ::Descriptor& dataMQ) {
+    if (is_codec_config_valid) {
+      ASSERT_EQ(status, BluetoothAudioStatus::SUCCESS);
+      ASSERT_TRUE(dataMQ.isHandleValid());
+      tempDataMQ.reset(new DataMQ(dataMQ));
+    } else {
+      EXPECT_EQ(status, BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION);
+      EXPECT_FALSE(dataMQ.isHandleValid());
+    }
+  };
+  AudioConfiguration audio_config = {};
+  PcmParameters pcm_parameters = {};
+  for (auto sample_rate : hearing_aid_sample_rates_) {
+    pcm_parameters.sampleRate = sample_rate;
+    for (auto bits_per_sample : hearing_aid_bits_per_samples_) {
+      pcm_parameters.bitsPerSample = bits_per_sample;
+      for (auto channel_mode : hearing_aid_channel_modes_) {
+        pcm_parameters.channelMode = channel_mode;
+        is_codec_config_valid = IsPcmParametersSupported(pcm_parameters);
+        audio_config.pcmConfig(pcm_parameters);
+        auto hidl_retval =
+            audio_provider_->startSession(audio_port_, audio_config, hidl_cb);
+        // HIDL calls should not be failed and callback has to be executed
+        ASSERT_TRUE(hidl_retval.isOk());
+        if (is_codec_config_valid) {
+          EXPECT_TRUE(tempDataMQ != nullptr && tempDataMQ->isValid());
+        }
+        EXPECT_TRUE(audio_provider_->endSession().isOk());
+      }  // ChannelMode
+    }    // BitsPerSampple
+  }      // SampleRate
+}
+
+int main(int argc, char** argv) {
+  ::testing::AddGlobalTestEnvironment(
+      BluetoothAudioHidlEnvironment::Instance());
+  ::testing::InitGoogleTest(&argc, argv);
+  BluetoothAudioHidlEnvironment::Instance()->init(&argc, argv);
+  int status = RUN_ALL_TESTS();
+  LOG(INFO) << "Test result = " << status;
+  return status;
+}
