Merge "Add VTS tests for reusable execution."
diff --git a/bluetooth/audio/aidl/Android.bp b/bluetooth/audio/aidl/Android.bp
index 12eed55..5107240 100644
--- a/bluetooth/audio/aidl/Android.bp
+++ b/bluetooth/audio/aidl/Android.bp
@@ -43,6 +43,10 @@
             vndk: {
                 enabled: true,
             },
+            apex_available: [
+                "//apex_available:platform",
+                "com.android.bluetooth",
+            ],
         },
     },
 }
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
new file mode 100644
index 0000000..fc8a911
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.cpp
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioProviderA2dpHW"
+
+#include "A2dpOffloadAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+A2dpOffloadAudioProvider::A2dpOffloadAudioProvider() {
+  session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+bool A2dpOffloadAudioProvider::isValid(const SessionType& session_type) {
+  return (session_type == session_type_);
+}
+
+ndk::ScopedAStatus A2dpOffloadAudioProvider::startSession(
+    const std::shared_ptr<IBluetoothAudioPort>& host_if,
+    const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+  if (audio_config.getTag() != AudioConfiguration::a2dpConfig) {
+    LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+                 << audio_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  if (!BluetoothAudioCodecs::IsOffloadCodecConfigurationValid(
+          session_type_, audio_config.get<AudioConfiguration::a2dpConfig>())) {
+    LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+                 << audio_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  return BluetoothAudioProvider::startSession(host_if, audio_config,
+                                              _aidl_return);
+}
+
+ndk::ScopedAStatus A2dpOffloadAudioProvider::onSessionReady(
+    DataMQDesc* _aidl_return) {
+  *_aidl_return = DataMQDesc();
+  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
+                                                nullptr, *audio_config_);
+  return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
new file mode 100644
index 0000000..5934f5b
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpOffloadAudioProvider.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class A2dpOffloadAudioProvider : public BluetoothAudioProvider {
+ public:
+  A2dpOffloadAudioProvider();
+
+  bool isValid(const SessionType& session_type) override;
+
+  ndk::ScopedAStatus startSession(
+      const std::shared_ptr<IBluetoothAudioPort>& host_if,
+      const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+
+ private:
+  ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
new file mode 100644
index 0000000..7e49074
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.cpp
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioProviderA2dpSW"
+
+#include "A2dpSoftwareAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+// Here the buffer size is based on SBC
+static constexpr uint32_t kPcmFrameSize = 4;  // 16 bits per sample / stereo
+// SBC is 128, and here we choose the LCM of 16, 24, and 32
+static constexpr uint32_t kPcmFrameCount = 96;
+static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
+// The max counts by 1 tick (20ms) for SBC is about 7. Since using 96 for the
+// PCM counts, here we just choose a greater number
+static constexpr uint32_t kRtpFrameCount = 10;
+static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
+static constexpr uint32_t kBufferCount = 2;  // double buffer
+static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
+
+A2dpSoftwareAudioProvider::A2dpSoftwareAudioProvider()
+    : BluetoothAudioProvider(), data_mq_(nullptr) {
+  LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
+            << " byte(s)";
+  std::unique_ptr<DataMQ> data_mq(
+      new DataMQ(kDataMqSize, /* EventFlag */ true));
+  if (data_mq && data_mq->isValid()) {
+    data_mq_ = std::move(data_mq);
+    session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
+  } else {
+    ALOGE_IF(!data_mq, "failed to allocate data MQ");
+    ALOGE_IF(data_mq && !data_mq->isValid(), "data MQ is invalid");
+  }
+}
+
+bool A2dpSoftwareAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_ && data_mq_ && data_mq_->isValid());
+}
+
+ndk::ScopedAStatus A2dpSoftwareAudioProvider::startSession(
+    const std::shared_ptr<IBluetoothAudioPort>& host_if,
+    const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+  if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+    LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+                 << audio_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  const PcmConfiguration& pcm_config =
+      audio_config.get<AudioConfiguration::pcmConfig>();
+  if (!BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(pcm_config)) {
+    LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+                 << pcm_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  return BluetoothAudioProvider::startSession(host_if, audio_config,
+                                              _aidl_return);
+}
+
+ndk::ScopedAStatus A2dpSoftwareAudioProvider::onSessionReady(
+    DataMQDesc* _aidl_return) {
+  if (data_mq_ == nullptr || !data_mq_->isValid()) {
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  *_aidl_return = data_mq_->dupeDesc();
+  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
+                                                _aidl_return, *audio_config_);
+  return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
new file mode 100644
index 0000000..3bc0a13
--- /dev/null
+++ b/bluetooth/audio/aidl/default/A2dpSoftwareAudioProvider.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class A2dpSoftwareAudioProvider : public BluetoothAudioProvider {
+ public:
+  A2dpSoftwareAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+
+  ndk::ScopedAStatus startSession(
+      const std::shared_ptr<IBluetoothAudioPort>& host_if,
+      const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+
+ private:
+  // audio data queue for software encoding
+  std::unique_ptr<DataMQ> data_mq_;
+
+  ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/Android.bp b/bluetooth/audio/aidl/default/Android.bp
new file mode 100644
index 0000000..846702f
--- /dev/null
+++ b/bluetooth/audio/aidl/default/Android.bp
@@ -0,0 +1,34 @@
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "hardware_interfaces_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_shared {
+    name: "android.hardware.bluetooth.audio-V1-impl",
+    vendor: true,
+    vintf_fragments: ["bluetooth_audio.xml"],
+    srcs: [
+        "BluetoothAudioProvider.cpp",
+        "BluetoothAudioProviderFactory.cpp",
+        "A2dpOffloadAudioProvider.cpp",
+        "A2dpSoftwareAudioProvider.cpp",
+        "HearingAidAudioProvider.cpp",
+        "LeAudioOffloadAudioProvider.cpp",
+        "LeAudioSoftwareAudioProvider.cpp",
+    ],
+    export_include_dirs: ["."],
+    header_libs: ["libhardware_headers"],
+    shared_libs: [
+        "libbase",
+        "libbinder_ndk",
+        "libcutils",
+        "libfmq",
+        "liblog",
+        "android.hardware.bluetooth.audio-V1-ndk",
+        "libbluetooth_audio_session_aidl",
+    ],
+}
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
new file mode 100644
index 0000000..c2ffa2e
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.cpp
@@ -0,0 +1,138 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioProviderStub"
+
+#include "BluetoothAudioProvider.h"
+
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+BluetoothAudioProvider::BluetoothAudioProvider() {
+  death_recipient_ = ::ndk::ScopedAIBinder_DeathRecipient(
+      AIBinder_DeathRecipient_new(binderDiedCallbackAidl));
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::startSession(
+    const std::shared_ptr<IBluetoothAudioPort>& host_if,
+    const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+  if (host_if == nullptr) {
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+  stack_iface_ = host_if;
+
+  AIBinder_linkToDeath(stack_iface_->asBinder().get(), death_recipient_.get(),
+                       this);
+
+  onSessionReady(_aidl_return);
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::endSession() {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+
+  if (stack_iface_ != nullptr) {
+    BluetoothAudioSessionReport::OnSessionEnded(session_type_);
+
+    AIBinder_unlinkToDeath(stack_iface_->asBinder().get(),
+                           death_recipient_.get(), this);
+  } else {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " has NO session";
+  }
+
+  stack_iface_ = nullptr;
+  audio_config_ = nullptr;
+
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::streamStarted(
+    BluetoothAudioStatus status) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+            << ", status=" << toString(status);
+
+  if (stack_iface_ != nullptr) {
+    BluetoothAudioSessionReport::ReportControlStatus(session_type_, true,
+                                                     status);
+  } else {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << ", status=" << toString(status) << " has NO session";
+  }
+
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::streamSuspended(
+    BluetoothAudioStatus status) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+            << ", status=" << toString(status);
+
+  if (stack_iface_ != nullptr) {
+    BluetoothAudioSessionReport::ReportControlStatus(session_type_, false,
+                                                     status);
+  } else {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << ", status=" << toString(status) << " has NO session";
+  }
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProvider::updateAudioConfiguration(
+    const AudioConfiguration& audio_config) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+
+  if (stack_iface_ == nullptr || audio_config_ == nullptr) {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " has NO session";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  if (audio_config.getTag() != audio_config_->getTag()) {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " audio config type is not match";
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+  BluetoothAudioSessionReport::ReportAudioConfigChanged(session_type_,
+                                                        *audio_config_);
+  return ndk::ScopedAStatus::ok();
+}
+
+void BluetoothAudioProvider::binderDiedCallbackAidl(void* ptr) {
+  LOG(ERROR) << __func__ << " - BluetoothAudio Service died";
+  auto provider = static_cast<BluetoothAudioProvider*>(ptr);
+  if (provider == nullptr) {
+    LOG(ERROR) << __func__ << ": Null AudioProvider HAL died";
+    return;
+  }
+  provider->endSession();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProvider.h b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
new file mode 100644
index 0000000..f7acbdf
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProvider.h
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProvider.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+#include <fmq/AidlMessageQueue.h>
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+
+using MqDataType = int8_t;
+using MqDataMode = SynchronizedReadWrite;
+using DataMQ = AidlMessageQueue<MqDataType, MqDataMode>;
+using DataMQDesc = MQDescriptor<MqDataType, MqDataMode>;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioProvider : public BnBluetoothAudioProvider {
+ public:
+  BluetoothAudioProvider();
+
+  ndk::ScopedAStatus startSession(
+      const std::shared_ptr<IBluetoothAudioPort>& host_if,
+      const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+  ndk::ScopedAStatus endSession();
+  ndk::ScopedAStatus streamStarted(BluetoothAudioStatus status);
+  ndk::ScopedAStatus streamSuspended(BluetoothAudioStatus status);
+  ndk::ScopedAStatus updateAudioConfiguration(
+      const AudioConfiguration& audio_config);
+
+  virtual bool isValid(const SessionType& sessionType) = 0;
+
+ protected:
+  virtual ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) = 0;
+  static void binderDiedCallbackAidl(void* cookie_ptr);
+
+  ::ndk::ScopedAIBinder_DeathRecipient death_recipient_;
+
+  std::shared_ptr<IBluetoothAudioPort> stack_iface_;
+  std::unique_ptr<AudioConfiguration> audio_config_ = nullptr;
+  SessionType session_type_;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
new file mode 100644
index 0000000..8e6cee7
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.cpp
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioProvidersFactory"
+
+#include "BluetoothAudioProviderFactory.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <android-base/logging.h>
+
+#include "A2dpOffloadAudioProvider.h"
+#include "A2dpSoftwareAudioProvider.h"
+#include "BluetoothAudioProvider.h"
+#include "HearingAidAudioProvider.h"
+#include "LeAudioOffloadAudioProvider.h"
+#include "LeAudioSoftwareAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+BluetoothAudioProviderFactory::BluetoothAudioProviderFactory() {}
+
+ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider(
+    const SessionType session_type,
+    std::shared_ptr<IBluetoothAudioProvider>* _aidl_return) {
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type);
+  std::shared_ptr<BluetoothAudioProvider> provider = nullptr;
+
+  switch (session_type) {
+    case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<A2dpSoftwareAudioProvider>();
+      break;
+    case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<A2dpOffloadAudioProvider>();
+      break;
+    case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<HearingAidAudioProvider>();
+      break;
+    case SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<LeAudioSoftwareOutputAudioProvider>();
+      break;
+    case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<LeAudioOffloadOutputAudioProvider>();
+      break;
+    case SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<LeAudioSoftwareInputAudioProvider>();
+      break;
+    case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+      provider = ndk::SharedRefBase::make<LeAudioOffloadInputAudioProvider>();
+      break;
+    default:
+      provider = nullptr;
+      break;
+  }
+
+  if (provider == nullptr || !provider->isValid(session_type)) {
+    provider = nullptr;
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type);
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  *_aidl_return = provider;
+
+  return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothAudioProviderFactory::getProviderCapabilities(
+    const SessionType session_type,
+    std::vector<AudioCapabilities>* _aidl_return) {
+  if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+    auto codec_capabilities =
+        BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(session_type);
+    _aidl_return->resize(codec_capabilities.size());
+    for (int i = 0; i < codec_capabilities.size(); i++) {
+      _aidl_return->at(i).set<AudioCapabilities::a2dpCapabilities>(
+          codec_capabilities[i]);
+    }
+  } else if (session_type ==
+                 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+             session_type ==
+                 SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    std::vector<LeAudioCodecCapabilitiesSetting> db_codec_capabilities =
+        BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(session_type);
+    if (db_codec_capabilities.size()) {
+      _aidl_return->resize(db_codec_capabilities.size());
+      for (int i = 0; i < db_codec_capabilities.size(); ++i) {
+        _aidl_return->at(i).set<AudioCapabilities::leAudioCapabilities>(
+            db_codec_capabilities[i]);
+      }
+    }
+  } else if (session_type != SessionType::UNKNOWN) {
+    auto pcm_capabilities = BluetoothAudioCodecs::GetSoftwarePcmCapabilities();
+    _aidl_return->resize(pcm_capabilities.size());
+    for (int i = 0; i < pcm_capabilities.size(); i++) {
+      _aidl_return->at(i).set<AudioCapabilities::pcmCapabilities>(
+          pcm_capabilities[i]);
+    }
+  }
+
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type)
+            << " supports " << _aidl_return->size() << " codecs";
+  return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
new file mode 100644
index 0000000..96d888c
--- /dev/null
+++ b/bluetooth/audio/aidl/default/BluetoothAudioProviderFactory.h
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/audio/BnBluetoothAudioProviderFactory.h>
+
+#include "A2dpOffloadAudioProvider.h"
+#include "A2dpSoftwareAudioProvider.h"
+#include "BluetoothAudioProvider.h"
+#include "HearingAidAudioProvider.h"
+#include "LeAudioOffloadAudioProvider.h"
+#include "LeAudioSoftwareAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioProviderFactory : public BnBluetoothAudioProviderFactory {
+ public:
+  BluetoothAudioProviderFactory();
+
+  ndk::ScopedAStatus openProvider(
+      const SessionType session_type,
+      std::shared_ptr<IBluetoothAudioProvider>* _aidl_return) override;
+
+  ndk::ScopedAStatus getProviderCapabilities(
+      const SessionType session_type,
+      std::vector<AudioCapabilities>* _aidl_return) override;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
new file mode 100644
index 0000000..a993059
--- /dev/null
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.cpp
@@ -0,0 +1,95 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioProviderHearingAid"
+
+#include "HearingAidAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+static constexpr uint32_t kPcmFrameSize = 4;  // 16 bits per sample / stereo
+static constexpr uint32_t kPcmFrameCount = 128;
+static constexpr uint32_t kRtpFrameSize = kPcmFrameSize * kPcmFrameCount;
+static constexpr uint32_t kRtpFrameCount = 7;  // max counts by 1 tick (20ms)
+static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
+static constexpr uint32_t kBufferCount = 1;  // single buffer
+static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
+
+HearingAidAudioProvider::HearingAidAudioProvider()
+    : BluetoothAudioProvider(), data_mq_(nullptr) {
+  LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
+            << " byte(s)";
+  std::unique_ptr<DataMQ> data_mq(
+      new DataMQ(kDataMqSize, /* EventFlag */ true));
+  if (data_mq && data_mq->isValid()) {
+    data_mq_ = std::move(data_mq);
+    session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
+  } else {
+    ALOGE_IF(!data_mq, "failed to allocate data MQ");
+    ALOGE_IF(data_mq && !data_mq->isValid(), "data MQ is invalid");
+  }
+}
+bool HearingAidAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_ && data_mq_ && data_mq_->isValid());
+}
+
+ndk::ScopedAStatus HearingAidAudioProvider::startSession(
+    const std::shared_ptr<IBluetoothAudioPort>& host_if,
+    const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+  if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+    LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+                 << audio_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  const auto& pcm_config = audio_config.get<AudioConfiguration::pcmConfig>();
+  if (!BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(pcm_config)) {
+    LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+                 << pcm_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  return BluetoothAudioProvider::startSession(host_if, audio_config,
+                                              _aidl_return);
+}
+
+ndk::ScopedAStatus HearingAidAudioProvider::onSessionReady(
+    DataMQDesc* _aidl_return) {
+  if (data_mq_ == nullptr || !data_mq_->isValid()) {
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  auto desc = data_mq_->dupeDesc();
+  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
+                                                &desc, *audio_config_);
+  *_aidl_return = data_mq_->dupeDesc();
+  return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/HearingAidAudioProvider.h b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
new file mode 100644
index 0000000..a7e19e9
--- /dev/null
+++ b/bluetooth/audio/aidl/default/HearingAidAudioProvider.h
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class HearingAidAudioProvider : public BluetoothAudioProvider {
+ public:
+  HearingAidAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+
+  ndk::ScopedAStatus startSession(
+      const std::shared_ptr<IBluetoothAudioPort>& host_if,
+      const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+
+ private:
+  // audio data queue for software encoding
+  std::unique_ptr<DataMQ> data_mq_;
+
+  ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
new file mode 100644
index 0000000..4078783
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioProviderLeAudioSW"
+
+#include "LeAudioOffloadAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+LeAudioOffloadOutputAudioProvider::LeAudioOffloadOutputAudioProvider()
+    : LeAudioOffloadAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+}
+
+LeAudioOffloadInputAudioProvider::LeAudioOffloadInputAudioProvider()
+    : LeAudioOffloadAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH;
+}
+
+LeAudioOffloadAudioProvider::LeAudioOffloadAudioProvider()
+    : BluetoothAudioProvider() {}
+
+bool LeAudioOffloadAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_);
+}
+
+ndk::ScopedAStatus LeAudioOffloadAudioProvider::startSession(
+    const std::shared_ptr<IBluetoothAudioPort>& host_if,
+    const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+  if (audio_config.getTag() != AudioConfiguration::leAudioConfig) {
+    LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+                 << audio_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  const auto& le_audio_config =
+      audio_config.get<AudioConfiguration::leAudioConfig>();
+  if (!BluetoothAudioCodecs::IsOffloadLeAudioConfigurationValid(
+          session_type_, le_audio_config)) {
+    LOG(WARNING) << __func__ << " - Unsupported LC3 Offloaded Configuration="
+                 << le_audio_config.toString();
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  return BluetoothAudioProvider::startSession(host_if, audio_config,
+                                              _aidl_return);
+}
+
+ndk::ScopedAStatus LeAudioOffloadAudioProvider::onSessionReady(
+    DataMQDesc* _aidl_return) {
+  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
+                                                nullptr, *audio_config_);
+  *_aidl_return = DataMQDesc();
+  return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
new file mode 100644
index 0000000..a27a2e7
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioOffloadAudioProvider.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class LeAudioOffloadAudioProvider : public BluetoothAudioProvider {
+ public:
+  LeAudioOffloadAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+
+  ndk::ScopedAStatus startSession(
+      const std::shared_ptr<IBluetoothAudioPort>& host_if,
+      const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+
+ private:
+  ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+class LeAudioOffloadOutputAudioProvider : public LeAudioOffloadAudioProvider {
+ public:
+  LeAudioOffloadOutputAudioProvider();
+};
+
+class LeAudioOffloadInputAudioProvider : public LeAudioOffloadAudioProvider {
+ public:
+  LeAudioOffloadInputAudioProvider();
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
new file mode 100644
index 0000000..f9962fd
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.cpp
@@ -0,0 +1,125 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioProviderLeAudioHW"
+
+#include "LeAudioSoftwareAudioProvider.h"
+
+#include <BluetoothAudioCodecs.h>
+#include <BluetoothAudioSessionReport.h>
+#include <android-base/logging.h>
+
+#include <cstdint>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+static constexpr uint32_t kBufferOutCount = 2;  // two frame buffer
+static constexpr uint32_t kBufferInCount = 2;   // two frame buffer
+
+inline uint32_t channel_mode_to_channel_count(ChannelMode channel_mode) {
+  switch (channel_mode) {
+    case ChannelMode::MONO:
+      return 1;
+    case ChannelMode::STEREO:
+      return 2;
+    default:
+      return 0;
+  }
+  return 0;
+}
+
+LeAudioSoftwareOutputAudioProvider::LeAudioSoftwareOutputAudioProvider()
+    : LeAudioSoftwareAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+}
+
+LeAudioSoftwareInputAudioProvider::LeAudioSoftwareInputAudioProvider()
+    : LeAudioSoftwareAudioProvider() {
+  session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH;
+}
+
+LeAudioSoftwareAudioProvider::LeAudioSoftwareAudioProvider()
+    : BluetoothAudioProvider(), data_mq_(nullptr) {}
+
+bool LeAudioSoftwareAudioProvider::isValid(const SessionType& sessionType) {
+  return (sessionType == session_type_);
+}
+
+ndk::ScopedAStatus LeAudioSoftwareAudioProvider::startSession(
+    const std::shared_ptr<IBluetoothAudioPort>& host_if,
+    const AudioConfiguration& audio_config, DataMQDesc* _aidl_return) {
+  if (audio_config.getTag() != AudioConfiguration::pcmConfig) {
+    LOG(WARNING) << __func__ << " - Invalid Audio Configuration="
+                 << audio_config.toString();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  const auto& pcm_config = audio_config.get<AudioConfiguration::pcmConfig>();
+  if (!BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(pcm_config)) {
+    LOG(WARNING) << __func__ << " - Unsupported PCM Configuration="
+                 << pcm_config.toString();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+
+  uint32_t buffer_modifier = 0;
+  if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH)
+    buffer_modifier = kBufferOutCount;
+  else if (session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH)
+    buffer_modifier = kBufferInCount;
+
+  uint32_t data_mq_size =
+      (ceil(pcm_config.sampleRateHz) / 1000) *
+      channel_mode_to_channel_count(pcm_config.channelMode) *
+      (pcm_config.bitsPerSample / 8) * (pcm_config.dataIntervalUs / 1000) *
+      buffer_modifier;
+
+  LOG(INFO) << __func__ << " - size of audio buffer " << data_mq_size
+            << " byte(s)";
+
+  std::unique_ptr<DataMQ> temp_data_mq(
+      new DataMQ(data_mq_size, /* EventFlag */ true));
+  if (temp_data_mq == nullptr || !temp_data_mq->isValid()) {
+    ALOGE_IF(!temp_data_mq, "failed to allocate data MQ");
+    ALOGE_IF(temp_data_mq && !temp_data_mq->isValid(), "data MQ is invalid");
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  data_mq_ = std::move(temp_data_mq);
+
+  return BluetoothAudioProvider::startSession(host_if, audio_config,
+                                              _aidl_return);
+}
+
+ndk::ScopedAStatus LeAudioSoftwareAudioProvider::onSessionReady(
+    DataMQDesc* _aidl_return) {
+  if (data_mq_ == nullptr || !data_mq_->isValid()) {
+    *_aidl_return = DataMQDesc();
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+  }
+  *_aidl_return = data_mq_->dupeDesc();
+  BluetoothAudioSessionReport::OnSessionStarted(session_type_, stack_iface_,
+                                                _aidl_return, *audio_config_);
+  return ndk::ScopedAStatus::ok();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
new file mode 100644
index 0000000..fa58182
--- /dev/null
+++ b/bluetooth/audio/aidl/default/LeAudioSoftwareAudioProvider.h
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioProvider.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class LeAudioSoftwareAudioProvider : public BluetoothAudioProvider {
+ public:
+  LeAudioSoftwareAudioProvider();
+
+  bool isValid(const SessionType& sessionType) override;
+
+  ndk::ScopedAStatus startSession(
+      const std::shared_ptr<IBluetoothAudioPort>& host_if,
+      const AudioConfiguration& audio_config, DataMQDesc* _aidl_return);
+
+ private:
+  // audio data queue for software encoding
+  std::unique_ptr<DataMQ> data_mq_;
+
+  ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
+};
+
+class LeAudioSoftwareOutputAudioProvider : public LeAudioSoftwareAudioProvider {
+ public:
+  LeAudioSoftwareOutputAudioProvider();
+};
+
+class LeAudioSoftwareInputAudioProvider : public LeAudioSoftwareAudioProvider {
+ public:
+  LeAudioSoftwareInputAudioProvider();
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/aidl/default/bluetooth_audio.xml b/bluetooth/audio/aidl/default/bluetooth_audio.xml
new file mode 100644
index 0000000..1859a1a
--- /dev/null
+++ b/bluetooth/audio/aidl/default/bluetooth_audio.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+    <hal format="aidl">
+        <name>android.hardware.bluetooth.audio</name>
+        <fqname>IBluetoothAudioProviderFactory/default</fqname>
+    </hal>
+</manifest>
\ No newline at end of file
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 4f712bf..974357e 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -32,5 +32,30 @@
         "libhidlbase",
         "liblog",
         "libutils",
+        "libbluetooth_audio_session_aidl",
+    ],
+}
+
+cc_library_shared {
+    name: "libbluetooth_audio_session_aidl",
+    vendor: true,
+    srcs: [
+        "aidl_session/BluetoothAudioCodecs.cpp",
+        "aidl_session/BluetoothAudioSession.cpp",
+        "aidl_session/HidlToAidlMiddleware.cpp",
+    ],
+    export_include_dirs: ["aidl_session/"],
+    header_libs: ["libhardware_headers"],
+    shared_libs: [
+        "android.hardware.bluetooth.audio@2.0",
+        "android.hardware.bluetooth.audio@2.1",
+        "android.hardware.bluetooth.audio@2.2",
+        "libbase",
+        "libcutils",
+        "libbinder_ndk",
+        "libfmq",
+        "liblog",
+        "android.hardware.bluetooth.audio-V1-ndk",
+        "libhidlbase",
     ],
 }
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
new file mode 100644
index 0000000..92cd0f5
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -0,0 +1,489 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioCodecsAidl"
+
+#include "BluetoothAudioCodecs.h"
+
+#include <aidl/android/hardware/bluetooth/audio/AacCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/AacObjectType.h>
+#include <aidl/android/hardware/bluetooth/audio/AptxCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/ChannelMode.h>
+#include <aidl/android/hardware/bluetooth/audio/LdacCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/LdacChannelMode.h>
+#include <aidl/android/hardware/bluetooth/audio/LdacQualityIndex.h>
+#include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/SbcCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/SbcChannelMode.h>
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+static const PcmCapabilities kDefaultSoftwarePcmCapabilities = {
+    .sampleRateHz = {16000, 24000, 44100, 48000, 88200, 96000},
+    .channelMode = {ChannelMode::MONO, ChannelMode::STEREO},
+    .bitsPerSample = {16, 24, 32},
+    .dataIntervalUs = {},
+};
+
+static const SbcCapabilities kDefaultOffloadSbcCapability = {
+    .sampleRateHz = {44100},
+    .channelMode = {SbcChannelMode::MONO, SbcChannelMode::JOINT_STEREO},
+    .blockLength = {4, 8, 12, 16},
+    .numSubbands = {8},
+    .allocMethod = {SbcAllocMethod::ALLOC_MD_L},
+    .bitsPerSample = {16},
+    .minBitpool = 2,
+    .maxBitpool = 53};
+
+static const AacCapabilities kDefaultOffloadAacCapability = {
+    .objectType = {AacObjectType::MPEG2_LC},
+    .sampleRateHz = {44100},
+    .channelMode = {ChannelMode::STEREO},
+    .variableBitRateSupported = true,
+    .bitsPerSample = {16}};
+
+static const LdacCapabilities kDefaultOffloadLdacCapability = {
+    .sampleRateHz = {44100, 48000, 88200, 96000},
+    .channelMode = {LdacChannelMode::DUAL, LdacChannelMode::STEREO},
+    .qualityIndex = {LdacQualityIndex::HIGH},
+    .bitsPerSample = {16, 24, 32}};
+
+static const AptxCapabilities kDefaultOffloadAptxCapability = {
+    .sampleRateHz = {44100, 48000},
+    .channelMode = {ChannelMode::STEREO},
+    .bitsPerSample = {16},
+};
+
+static const AptxCapabilities kDefaultOffloadAptxHdCapability = {
+    .sampleRateHz = {44100, 48000},
+    .channelMode = {ChannelMode::STEREO},
+    .bitsPerSample = {24},
+};
+
+static const Lc3Capabilities kDefaultOffloadLc3Capability = {
+    .samplingFrequencyHz = {44100, 48000},
+    .frameDurationUs = {7500, 10000},
+    .channelMode = {ChannelMode::MONO, ChannelMode::STEREO},
+};
+
+const std::vector<CodecCapabilities> kDefaultOffloadA2dpCodecCapabilities = {
+    {.codecType = CodecType::SBC, .capabilities = {}},
+    {.codecType = CodecType::AAC, .capabilities = {}},
+    {.codecType = CodecType::LDAC, .capabilities = {}},
+    {.codecType = CodecType::APTX, .capabilities = {}},
+    {.codecType = CodecType::APTX_HD, .capabilities = {}},
+    {.codecType = CodecType::LC3, .capabilities = {}}};
+
+std::vector<LeAudioCodecCapabilitiesSetting> kDefaultOffloadLeAudioCapabilities;
+
+static const UnicastCapability kInvalidUnicastCapability = {
+    .codecType = CodecType::UNKNOWN};
+
+static const BroadcastCapability kInvalidBroadcastCapability = {
+    .codecType = CodecType::UNKNOWN};
+
+// Default Supported Codecs
+// LC3 16_1: sample rate: 16 kHz, frame duration: 7.5 ms, octets per frame: 30
+static const Lc3Capabilities kLc3Capability_16_1 = {
+    .samplingFrequencyHz = {16000},
+    .frameDurationUs = {7500},
+    .octetsPerFrame = {30}};
+
+// Default Supported Codecs
+// LC3 16_2: sample rate: 16 kHz, frame duration: 10 ms, octets per frame: 40
+static const Lc3Capabilities kLc3Capability_16_2 = {
+    .samplingFrequencyHz = {16000},
+    .frameDurationUs = {10000},
+    .octetsPerFrame = {40}};
+
+// Default Supported Codecs
+// LC3 48_4: sample rate: 48 kHz, frame duration: 10 ms, octets per frame: 120
+static const Lc3Capabilities kLc3Capability_48_4 = {
+    .samplingFrequencyHz = {48000},
+    .frameDurationUs = {10000},
+    .octetsPerFrame = {120}};
+
+static const std::vector<Lc3Capabilities> supportedLc3CapabilityList = {
+    kLc3Capability_48_4, kLc3Capability_16_2, kLc3Capability_16_1};
+
+static AudioLocation stereoAudio = static_cast<AudioLocation>(
+    static_cast<uint8_t>(AudioLocation::FRONT_LEFT) |
+    static_cast<uint8_t>(AudioLocation::FRONT_RIGHT));
+static AudioLocation monoAudio = AudioLocation::UNKNOWN;
+
+// Stores the supported setting of audio location, connected device, and the
+// channel count for each device
+std::vector<std::tuple<AudioLocation, uint8_t, uint8_t>>
+    supportedDeviceSetting = {std::make_tuple(stereoAudio, 2, 1),
+                              std::make_tuple(monoAudio, 1, 2),
+                              std::make_tuple(monoAudio, 1, 1)};
+
+template <class T>
+bool BluetoothAudioCodecs::ContainedInVector(
+    const std::vector<T>& vector, const typename identity<T>::type& target) {
+  return std::find(vector.begin(), vector.end(), target) != vector.end();
+}
+
+bool BluetoothAudioCodecs::IsOffloadSbcConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::sbcConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << codec_specific.toString();
+    return false;
+  }
+  const SbcConfiguration sbc_data =
+      codec_specific.get<CodecConfiguration::CodecSpecific::sbcConfig>();
+
+  if (ContainedInVector(kDefaultOffloadSbcCapability.sampleRateHz,
+                        sbc_data.sampleRateHz) &&
+      ContainedInVector(kDefaultOffloadSbcCapability.blockLength,
+                        sbc_data.blockLength) &&
+      ContainedInVector(kDefaultOffloadSbcCapability.numSubbands,
+                        sbc_data.numSubbands) &&
+      ContainedInVector(kDefaultOffloadSbcCapability.bitsPerSample,
+                        sbc_data.bitsPerSample) &&
+      ContainedInVector(kDefaultOffloadSbcCapability.channelMode,
+                        sbc_data.channelMode) &&
+      ContainedInVector(kDefaultOffloadSbcCapability.allocMethod,
+                        sbc_data.allocMethod) &&
+      sbc_data.minBitpool <= sbc_data.maxBitpool &&
+      kDefaultOffloadSbcCapability.minBitpool <= sbc_data.minBitpool &&
+      kDefaultOffloadSbcCapability.maxBitpool >= sbc_data.maxBitpool) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << codec_specific.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadAacConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::aacConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << codec_specific.toString();
+    return false;
+  }
+  const AacConfiguration aac_data =
+      codec_specific.get<CodecConfiguration::CodecSpecific::aacConfig>();
+
+  if (ContainedInVector(kDefaultOffloadAacCapability.sampleRateHz,
+                        aac_data.sampleRateHz) &&
+      ContainedInVector(kDefaultOffloadAacCapability.bitsPerSample,
+                        aac_data.bitsPerSample) &&
+      ContainedInVector(kDefaultOffloadAacCapability.channelMode,
+                        aac_data.channelMode) &&
+      ContainedInVector(kDefaultOffloadAacCapability.objectType,
+                        aac_data.objectType) &&
+      (!aac_data.variableBitRateEnabled ||
+       kDefaultOffloadAacCapability.variableBitRateSupported)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << codec_specific.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadLdacConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getTag() !=
+      CodecConfiguration::CodecSpecific::ldacConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << codec_specific.toString();
+    return false;
+  }
+  const LdacConfiguration ldac_data =
+      codec_specific.get<CodecConfiguration::CodecSpecific::ldacConfig>();
+
+  if (ContainedInVector(kDefaultOffloadLdacCapability.sampleRateHz,
+                        ldac_data.sampleRateHz) &&
+      ContainedInVector(kDefaultOffloadLdacCapability.bitsPerSample,
+                        ldac_data.bitsPerSample) &&
+      ContainedInVector(kDefaultOffloadLdacCapability.channelMode,
+                        ldac_data.channelMode) &&
+      ContainedInVector(kDefaultOffloadLdacCapability.qualityIndex,
+                        ldac_data.qualityIndex)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << codec_specific.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadAptxConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getTag() !=
+      CodecConfiguration::CodecSpecific::aptxConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << codec_specific.toString();
+    return false;
+  }
+  const AptxConfiguration aptx_data =
+      codec_specific.get<CodecConfiguration::CodecSpecific::aptxConfig>();
+
+  if (ContainedInVector(kDefaultOffloadAptxCapability.sampleRateHz,
+                        aptx_data.sampleRateHz) &&
+      ContainedInVector(kDefaultOffloadAptxCapability.bitsPerSample,
+                        aptx_data.bitsPerSample) &&
+      ContainedInVector(kDefaultOffloadAptxCapability.channelMode,
+                        aptx_data.channelMode)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << codec_specific.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadAptxHdConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getTag() !=
+      CodecConfiguration::CodecSpecific::aptxConfig) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << codec_specific.toString();
+    return false;
+  }
+  const AptxConfiguration aptx_data =
+      codec_specific.get<CodecConfiguration::CodecSpecific::aptxConfig>();
+
+  if (ContainedInVector(kDefaultOffloadAptxHdCapability.sampleRateHz,
+                        aptx_data.sampleRateHz) &&
+      ContainedInVector(kDefaultOffloadAptxHdCapability.bitsPerSample,
+                        aptx_data.bitsPerSample) &&
+      ContainedInVector(kDefaultOffloadAptxHdCapability.channelMode,
+                        aptx_data.channelMode)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << codec_specific.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadLc3ConfigurationValid(
+    const CodecConfiguration::CodecSpecific& codec_specific) {
+  if (codec_specific.getTag() != CodecConfiguration::CodecSpecific::lc3Config) {
+    LOG(WARNING) << __func__
+                 << ": Invalid CodecSpecific=" << codec_specific.toString();
+    return false;
+  }
+  const Lc3Configuration lc3_data =
+      codec_specific.get<CodecConfiguration::CodecSpecific::lc3Config>();
+
+  if (ContainedInVector(kDefaultOffloadLc3Capability.samplingFrequencyHz,
+                        lc3_data.samplingFrequencyHz) &&
+      ContainedInVector(kDefaultOffloadLc3Capability.frameDurationUs,
+                        lc3_data.frameDurationUs) &&
+      ContainedInVector(kDefaultOffloadLc3Capability.channelMode,
+                        lc3_data.channelMode)) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << codec_specific.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadLeAudioConfigurationValid(
+    const SessionType& session_type, const LeAudioConfiguration&) {
+  if (session_type !=
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type !=
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return false;
+  }
+  return true;
+}
+
+std::vector<PcmCapabilities>
+BluetoothAudioCodecs::GetSoftwarePcmCapabilities() {
+  return {kDefaultSoftwarePcmCapabilities};
+}
+
+std::vector<CodecCapabilities>
+BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(
+    const SessionType& session_type) {
+  if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+    return {};
+  }
+  std::vector<CodecCapabilities> offload_a2dp_codec_capabilities =
+      kDefaultOffloadA2dpCodecCapabilities;
+  for (auto& codec_capability : offload_a2dp_codec_capabilities) {
+    switch (codec_capability.codecType) {
+      case CodecType::SBC:
+        codec_capability.capabilities
+            .set<CodecCapabilities::Capabilities::sbcCapabilities>(
+                kDefaultOffloadSbcCapability);
+        break;
+      case CodecType::AAC:
+        codec_capability.capabilities
+            .set<CodecCapabilities::Capabilities::aacCapabilities>(
+                kDefaultOffloadAacCapability);
+        break;
+      case CodecType::LDAC:
+        codec_capability.capabilities
+            .set<CodecCapabilities::Capabilities::ldacCapabilities>(
+                kDefaultOffloadLdacCapability);
+        break;
+      case CodecType::APTX:
+        codec_capability.capabilities
+            .set<CodecCapabilities::Capabilities::aptxCapabilities>(
+                kDefaultOffloadAptxCapability);
+        break;
+      case CodecType::APTX_HD:
+        codec_capability.capabilities
+            .set<CodecCapabilities::Capabilities::aptxCapabilities>(
+                kDefaultOffloadAptxHdCapability);
+        break;
+      case CodecType::LC3:
+        codec_capability.capabilities
+            .set<CodecCapabilities::Capabilities::lc3Capabilities>(
+                kDefaultOffloadLc3Capability);
+        break;
+      case CodecType::UNKNOWN:
+        codec_capability = {};
+        break;
+    }
+  }
+  return offload_a2dp_codec_capabilities;
+}
+
+bool BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(
+    const PcmConfiguration& pcm_config) {
+  if (ContainedInVector(kDefaultSoftwarePcmCapabilities.sampleRateHz,
+                        pcm_config.sampleRateHz) &&
+      ContainedInVector(kDefaultSoftwarePcmCapabilities.bitsPerSample,
+                        pcm_config.bitsPerSample) &&
+      ContainedInVector(kDefaultSoftwarePcmCapabilities.channelMode,
+                        pcm_config.channelMode)
+      // data interval is not checked for now
+      // && pcm_config.dataIntervalUs != 0
+  ) {
+    return true;
+  }
+  LOG(WARNING) << __func__
+               << ": Unsupported CodecSpecific=" << pcm_config.toString();
+  return false;
+}
+
+bool BluetoothAudioCodecs::IsOffloadCodecConfigurationValid(
+    const SessionType& session_type, const CodecConfiguration& codec_config) {
+  if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+    LOG(ERROR) << __func__
+               << ": Invalid SessionType=" << toString(session_type);
+    return false;
+  }
+  const CodecConfiguration::CodecSpecific& codec_specific = codec_config.config;
+  switch (codec_config.codecType) {
+    case CodecType::SBC:
+      if (IsOffloadSbcConfigurationValid(codec_specific)) {
+        return true;
+      }
+      break;
+    case CodecType::AAC:
+      if (IsOffloadAacConfigurationValid(codec_specific)) {
+        return true;
+      }
+      break;
+    case CodecType::LDAC:
+      if (IsOffloadLdacConfigurationValid(codec_specific)) {
+        return true;
+      }
+      break;
+    case CodecType::APTX:
+      if (IsOffloadAptxConfigurationValid(codec_specific)) {
+        return true;
+      }
+      break;
+    case CodecType::APTX_HD:
+      if (IsOffloadAptxHdConfigurationValid(codec_specific)) {
+        return true;
+      }
+      break;
+    case CodecType::LC3:
+      if (IsOffloadLc3ConfigurationValid(codec_specific)) {
+        return true;
+      }
+      break;
+    case CodecType::UNKNOWN:
+      break;
+  }
+  return false;
+}
+
+UnicastCapability composeUnicastLc3Capability(
+    AudioLocation audioLocation, uint8_t deviceCnt, uint8_t channelCount,
+    const Lc3Capabilities& capability) {
+  return {
+      .codecType = CodecType::LC3,
+      .supportedChannel = audioLocation,
+      .deviceCount = deviceCnt,
+      .channelCountPerDevice = channelCount,
+      .leAudioCodecCapabilities =
+          UnicastCapability::LeAudioCodecCapabilities(capability),
+  };
+}
+
+std::vector<LeAudioCodecCapabilitiesSetting>
+BluetoothAudioCodecs::GetLeAudioOffloadCodecCapabilities(
+    const SessionType& session_type) {
+  if (session_type !=
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type !=
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return std::vector<LeAudioCodecCapabilitiesSetting>(0);
+  }
+
+  if (kDefaultOffloadLeAudioCapabilities.empty()) {
+    for (auto [audioLocation, deviceCnt, channelCount] :
+         supportedDeviceSetting) {
+      for (auto capability : supportedLc3CapabilityList) {
+        UnicastCapability lc3Capability = composeUnicastLc3Capability(
+            audioLocation, deviceCnt, channelCount, capability);
+        UnicastCapability lc3MonoDecodeCapability =
+            composeUnicastLc3Capability(monoAudio, 1, 1, capability);
+
+        // Adds the capability for encode only
+        kDefaultOffloadLeAudioCapabilities.push_back(
+            {.unicastEncodeCapability = lc3Capability,
+             .unicastDecodeCapability = kInvalidUnicastCapability,
+             .broadcastCapability = kInvalidBroadcastCapability});
+
+        // Adds the capability for decode only
+        kDefaultOffloadLeAudioCapabilities.push_back(
+            {.unicastEncodeCapability = kInvalidUnicastCapability,
+             .unicastDecodeCapability = lc3Capability,
+             .broadcastCapability = kInvalidBroadcastCapability});
+
+        // Adds the capability for the case that encode and decode exist at the
+        // same time
+        kDefaultOffloadLeAudioCapabilities.push_back(
+            {.unicastEncodeCapability = lc3Capability,
+             .unicastDecodeCapability = lc3MonoDecodeCapability,
+             .broadcastCapability = kInvalidBroadcastCapability});
+      }
+    }
+  }
+
+  return kDefaultOffloadLeAudioCapabilities;
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
new file mode 100644
index 0000000..c542ce5
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.h
@@ -0,0 +1,88 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/audio/CodecCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/CodecConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/Lc3Configuration.h>
+#include <aidl/android/hardware/bluetooth/audio/LeAudioCodecCapabilitiesSetting.h>
+#include <aidl/android/hardware/bluetooth/audio/LeAudioConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/PcmCapabilities.h>
+#include <aidl/android/hardware/bluetooth/audio/PcmConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+
+#include <vector>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioCodecs {
+ public:
+  static std::vector<PcmCapabilities> GetSoftwarePcmCapabilities();
+  static std::vector<CodecCapabilities> GetA2dpOffloadCodecCapabilities(
+      const SessionType& session_type);
+
+  static bool IsSoftwarePcmConfigurationValid(
+      const PcmConfiguration& pcm_config);
+  static bool IsOffloadCodecConfigurationValid(
+      const SessionType& session_type, const CodecConfiguration& codec_config);
+
+  static bool IsOffloadLeAudioConfigurationValid(
+      const SessionType& session_type, const Lc3Configuration& codec_config);
+
+  static bool IsOffloadLeAudioConfigurationValid(
+      const SessionType& session_type,
+      const LeAudioConfiguration& codec_config);
+
+  static std::vector<LeAudioCodecCapabilitiesSetting>
+  GetLeAudioOffloadCodecCapabilities(const SessionType& session_type);
+
+ private:
+  template <typename T>
+  struct identity {
+    typedef T type;
+  };
+  template <class T>
+  static bool ContainedInVector(const std::vector<T>& vector,
+                                const typename identity<T>::type& target);
+  template <class T>
+  static bool ContainedInBitmask(const T& bitmask, const T& target);
+  static bool IsSingleBit(uint32_t bitmasks, uint32_t bitfield);
+  static bool IsOffloadSbcConfigurationValid(
+      const CodecConfiguration::CodecSpecific& codec_specific);
+  static bool IsOffloadAacConfigurationValid(
+      const CodecConfiguration::CodecSpecific& codec_specific);
+  static bool IsOffloadLdacConfigurationValid(
+      const CodecConfiguration::CodecSpecific& codec_specific);
+  static bool IsOffloadAptxConfigurationValid(
+      const CodecConfiguration::CodecSpecific& codec_specific);
+  static bool IsOffloadAptxHdConfigurationValid(
+      const CodecConfiguration::CodecSpecific& codec_specific);
+  static bool IsOffloadLc3ConfigurationValid(
+      const CodecConfiguration::CodecSpecific& codec_specific);
+  static bool IsOffloadLeAudioConfigurationValid(
+      const SessionType& session_type, const LeAudioCodecConfiguration&);
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
new file mode 100644
index 0000000..95e473e
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.cpp
@@ -0,0 +1,581 @@
+/*
+ * 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 <sys/types.h>
+#define LOG_TAG "BTAudioSessionAidl"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <android/binder_manager.h>
+
+#include "BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+static constexpr int kFmqSendTimeoutMs = 1000;  // 1000 ms timeout for sending
+static constexpr int kFmqReceiveTimeoutMs =
+    1000;                               // 1000 ms timeout for receiving
+static constexpr int kWritePollMs = 1;  // polled non-blocking interval
+static constexpr int kReadPollMs = 1;   // polled non-blocking interval
+
+const CodecConfiguration BluetoothAudioSession::kInvalidCodecConfiguration = {};
+const LeAudioConfiguration kInvalidLeAudioConfiguration = {};
+AudioConfiguration BluetoothAudioSession::invalidSoftwareAudioConfiguration =
+    {};
+AudioConfiguration BluetoothAudioSession::invalidOffloadAudioConfiguration = {};
+AudioConfiguration BluetoothAudioSession::invalidLeOffloadAudioConfig = {};
+
+BluetoothAudioSession::BluetoothAudioSession(const SessionType& session_type)
+    : session_type_(session_type), stack_iface_(nullptr), data_mq_(nullptr) {
+  invalidSoftwareAudioConfiguration.set<AudioConfiguration::pcmConfig>(
+      kInvalidPcmConfiguration);
+  invalidOffloadAudioConfiguration.set<AudioConfiguration::a2dpConfig>(
+      kInvalidCodecConfiguration);
+  invalidLeOffloadAudioConfig.set<AudioConfiguration::leAudioConfig>(
+      kInvalidLeAudioConfiguration);
+}
+
+/***
+ *
+ * Callback methods
+ *
+ ***/
+
+void BluetoothAudioSession::OnSessionStarted(
+    const std::shared_ptr<IBluetoothAudioPort> stack_iface,
+    const DataMQDesc* mq_desc, const AudioConfiguration& audio_config) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (stack_iface == nullptr) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << ", IBluetoothAudioPort Invalid";
+  } else if (!UpdateAudioConfig(audio_config)) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << ", AudioConfiguration=" << audio_config.toString()
+               << " Invalid";
+  } else if (!UpdateDataPath(mq_desc)) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << " MqDescriptor Invalid";
+    if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+      audio_config_ = std::make_unique<AudioConfiguration>(
+          invalidOffloadAudioConfiguration);
+    } else {
+      audio_config_ = std::make_unique<AudioConfiguration>(
+          invalidSoftwareAudioConfiguration);
+    }
+  } else {
+    stack_iface_ = stack_iface;
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << ", AudioConfiguration=" << audio_config.toString();
+    ReportSessionStatus();
+  }
+}
+
+void BluetoothAudioSession::OnSessionEnded() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  bool toggled = IsSessionReady();
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_);
+  if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+    audio_config_ =
+        std::make_unique<AudioConfiguration>(invalidOffloadAudioConfiguration);
+  } else {
+    audio_config_ =
+        std::make_unique<AudioConfiguration>(invalidSoftwareAudioConfiguration);
+  }
+  stack_iface_ = nullptr;
+  UpdateDataPath(nullptr);
+  if (toggled) {
+    ReportSessionStatus();
+  }
+}
+
+/***
+ *
+ * Util methods
+ *
+ ***/
+
+const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    if (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+      return invalidOffloadAudioConfiguration;
+    } else {
+      return invalidSoftwareAudioConfiguration;
+    }
+    switch (session_type_) {
+      case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+        return invalidOffloadAudioConfiguration;
+      case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
+      case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
+        return invalidLeOffloadAudioConfig;
+      default:
+        return invalidSoftwareAudioConfiguration;
+    }
+  }
+  return *audio_config_;
+}
+
+void BluetoothAudioSession::ReportAudioConfigChanged(
+    const AudioConfiguration& audio_config) {
+  if (session_type_ !=
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
+      session_type_ !=
+          SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
+    return;
+  }
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+  if (observers_.empty()) {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << " has NO port state observer";
+    return;
+  }
+  for (auto& observer : observers_) {
+    uint16_t cookie = observer.first;
+    std::shared_ptr<struct PortStatusCallbacks> cb = observer.second;
+    LOG(INFO) << __func__ << " for SessionType=" << toString(session_type_)
+              << ", bluetooth_audio=0x"
+              << ::android::base::StringPrintf("%04x", cookie);
+    if (cb->audio_configuration_changed_cb_ != nullptr) {
+      cb->audio_configuration_changed_cb_(cookie);
+    }
+  }
+}
+
+bool BluetoothAudioSession::IsSessionReady() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+
+  bool is_mq_valid =
+      (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+       session_type_ ==
+           SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+       session_type_ ==
+           SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
+       (data_mq_ != nullptr && data_mq_->isValid()));
+  return stack_iface_ != nullptr && is_mq_valid;
+}
+
+/***
+ *
+ * Status callback methods
+ *
+ ***/
+
+uint16_t BluetoothAudioSession::RegisterStatusCback(
+    const PortStatusCallbacks& callbacks) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  uint16_t cookie = ObserversCookieGetInitValue(session_type_);
+  uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
+
+  while (cookie < cookie_upper_bound) {
+    if (observers_.find(cookie) == observers_.end()) {
+      break;
+    }
+    ++cookie;
+  }
+  if (cookie >= cookie_upper_bound) {
+    LOG(ERROR) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has " << observers_.size()
+               << " observers already (No Resource)";
+    return kObserversCookieUndefined;
+  }
+  std::shared_ptr<PortStatusCallbacks> cb =
+      std::make_shared<PortStatusCallbacks>();
+  *cb = callbacks;
+  observers_[cookie] = cb;
+  return cookie;
+}
+
+void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (observers_.erase(cookie) != 1) {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << " no such provider=0x"
+                 << ::android::base::StringPrintf("%04x", cookie);
+  }
+}
+
+/***
+ *
+ * Stream methods
+ *
+ ***/
+
+bool BluetoothAudioSession::StartStream() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return false;
+  }
+  auto hal_retval = stack_iface_->startStream();
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+    return false;
+  }
+  return true;
+}
+
+bool BluetoothAudioSession::SuspendStream() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return false;
+  }
+  auto hal_retval = stack_iface_->suspendStream();
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+    return false;
+  }
+  return true;
+}
+
+void BluetoothAudioSession::StopStream() {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    return;
+  }
+  auto hal_retval = stack_iface_->stopStream();
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+  }
+}
+
+/***
+ *
+ * Private methods
+ *
+ ***/
+
+bool BluetoothAudioSession::UpdateDataPath(const DataMQDesc* mq_desc) {
+  if (mq_desc == nullptr) {
+    // usecase of reset by nullptr
+    data_mq_ = nullptr;
+    return true;
+  }
+  std::unique_ptr<DataMQ> temp_mq;
+  temp_mq.reset(new DataMQ(*mq_desc));
+  if (!temp_mq || !temp_mq->isValid()) {
+    data_mq_ = nullptr;
+    return false;
+  }
+  data_mq_ = std::move(temp_mq);
+  return true;
+}
+
+bool BluetoothAudioSession::UpdateAudioConfig(
+    const AudioConfiguration& audio_config) {
+  bool is_software_session =
+      (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+       session_type_ == SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH ||
+       session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
+       session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH);
+  bool is_offload_a2dp_session =
+      (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
+  bool is_offload_le_audio_session =
+      (session_type_ ==
+           SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
+       session_type_ ==
+           SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH);
+  auto audio_config_tag = audio_config.getTag();
+  bool is_software_audio_config =
+      (is_software_session &&
+       audio_config_tag == AudioConfiguration::pcmConfig);
+  bool is_a2dp_offload_audio_config =
+      (is_offload_a2dp_session &&
+       audio_config_tag == AudioConfiguration::a2dpConfig);
+  bool is_le_audio_offload_audio_config =
+      (is_offload_le_audio_session &&
+       audio_config_tag == AudioConfiguration::leAudioConfig);
+  if (!is_software_audio_config && !is_a2dp_offload_audio_config &&
+      !is_le_audio_offload_audio_config) {
+    return false;
+  }
+  audio_config_ = std::make_unique<AudioConfiguration>(audio_config);
+  return true;
+}
+
+void BluetoothAudioSession::ReportSessionStatus() {
+  // This is locked already by OnSessionStarted / OnSessionEnded
+  if (observers_.empty()) {
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " has NO port state observer";
+    return;
+  }
+  for (auto& observer : observers_) {
+    uint16_t cookie = observer.first;
+    std::shared_ptr<PortStatusCallbacks> callback = observer.second;
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << " notify to bluetooth_audio=0x"
+              << ::android::base::StringPrintf("%04x", cookie);
+    callback->session_changed_cb_(cookie);
+  }
+}
+
+/***
+ *
+ * PCM methods
+ *
+ ***/
+
+size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
+                                              size_t bytes) {
+  if (buffer == nullptr || bytes <= 0) {
+    return 0;
+  }
+  size_t total_written = 0;
+  int timeout_ms = kFmqSendTimeoutMs;
+  do {
+    std::unique_lock<std::recursive_mutex> lock(mutex_);
+    if (!IsSessionReady()) {
+      break;
+    }
+    size_t num_bytes_to_write = data_mq_->availableToWrite();
+    if (num_bytes_to_write) {
+      if (num_bytes_to_write > (bytes - total_written)) {
+        num_bytes_to_write = bytes - total_written;
+      }
+
+      if (!data_mq_->write(
+              static_cast<const MQDataType*>(buffer) + total_written,
+              num_bytes_to_write)) {
+        LOG(ERROR) << "FMQ datapath writing " << total_written << "/" << bytes
+                   << " failed";
+        return total_written;
+      }
+      total_written += num_bytes_to_write;
+    } else if (timeout_ms >= kWritePollMs) {
+      lock.unlock();
+      usleep(kWritePollMs * 1000);
+      timeout_ms -= kWritePollMs;
+    } else {
+      LOG(DEBUG) << "Data " << total_written << "/" << bytes << " overflow "
+                 << (kFmqSendTimeoutMs - timeout_ms) << " ms";
+      return total_written;
+    }
+  } while (total_written < bytes);
+  return total_written;
+}
+
+size_t BluetoothAudioSession::InReadPcmData(void* buffer, size_t bytes) {
+  if (buffer == nullptr || bytes <= 0) {
+    return 0;
+  }
+  size_t total_read = 0;
+  int timeout_ms = kFmqReceiveTimeoutMs;
+  do {
+    std::unique_lock<std::recursive_mutex> lock(mutex_);
+    if (!IsSessionReady()) {
+      break;
+    }
+    size_t num_bytes_to_read = data_mq_->availableToRead();
+    if (num_bytes_to_read) {
+      if (num_bytes_to_read > (bytes - total_read)) {
+        num_bytes_to_read = bytes - total_read;
+      }
+      if (!data_mq_->read(static_cast<MQDataType*>(buffer) + total_read,
+                          num_bytes_to_read)) {
+        LOG(ERROR) << "FMQ datapath reading " << total_read << "/" << bytes
+                   << " failed";
+        return total_read;
+      }
+      total_read += num_bytes_to_read;
+    } else if (timeout_ms >= kReadPollMs) {
+      lock.unlock();
+      usleep(kReadPollMs * 1000);
+      timeout_ms -= kReadPollMs;
+      continue;
+    } else {
+      LOG(DEBUG) << "Data " << total_read << "/" << bytes << " overflow "
+                 << (kFmqReceiveTimeoutMs - timeout_ms) << " ms";
+      return total_read;
+    }
+  } while (total_read < bytes);
+  return total_read;
+}
+
+/***
+ *
+ * Other methods
+ *
+ ***/
+
+void BluetoothAudioSession::ReportControlStatus(bool start_resp,
+                                                BluetoothAudioStatus status) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (observers_.empty()) {
+    LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
+                 << " has NO port state observer";
+    return;
+  }
+  for (auto& observer : observers_) {
+    uint16_t cookie = observer.first;
+    std::shared_ptr<PortStatusCallbacks> callback = observer.second;
+    LOG(INFO) << __func__ << " - status=" << toString(status)
+              << " for SessionType=" << toString(session_type_)
+              << ", bluetooth_audio=0x"
+              << ::android::base::StringPrintf("%04x", cookie)
+              << (start_resp ? " started" : " suspended");
+    callback->control_result_cb_(cookie, start_resp, status);
+  }
+}
+
+bool BluetoothAudioSession::GetPresentationPosition(
+    PresentationPosition& presentation_position) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return false;
+  }
+  bool retval = false;
+
+  if (!stack_iface_->getPresentationPosition(&presentation_position).isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+    return false;
+  }
+  return retval;
+}
+
+void BluetoothAudioSession::UpdateSourceMetadata(
+    const struct source_metadata& source_metadata) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return;
+  }
+
+  ssize_t track_count = source_metadata.track_count;
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
+            << track_count << " track(s)";
+  if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+    return;
+  }
+
+  SourceMetadata hal_source_metadata;
+  hal_source_metadata.tracks.resize(track_count);
+  for (int i = 0; i < track_count; i++) {
+    hal_source_metadata.tracks[i].usage =
+        static_cast<media::audio::common::AudioUsage>(
+            source_metadata.tracks[i].usage);
+    hal_source_metadata.tracks[i].contentType =
+        static_cast<media::audio::common::AudioContentType>(
+            source_metadata.tracks[i].content_type);
+    hal_source_metadata.tracks[i].gain = source_metadata.tracks[i].gain;
+    LOG(VERBOSE) << __func__ << " - SessionType=" << toString(session_type_)
+                 << ", usage=" << toString(hal_source_metadata.tracks[i].usage)
+                 << ", content="
+                 << toString(hal_source_metadata.tracks[i].contentType)
+                 << ", gain=" << hal_source_metadata.tracks[i].gain;
+  }
+
+  auto hal_retval = stack_iface_->updateSourceMetadata(hal_source_metadata);
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+  }
+}
+
+void BluetoothAudioSession::UpdateSinkMetadata(
+    const struct sink_metadata& sink_metadata) {
+  std::lock_guard<std::recursive_mutex> guard(mutex_);
+  if (!IsSessionReady()) {
+    LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
+               << " has NO session";
+    return;
+  }
+
+  ssize_t track_count = sink_metadata.track_count;
+  LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
+            << track_count << " track(s)";
+  if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+      session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+    return;
+  }
+
+  SinkMetadata hal_sink_metadata;
+  hal_sink_metadata.tracks.resize(track_count);
+  for (int i = 0; i < track_count; i++) {
+    hal_sink_metadata.tracks[i].source =
+        static_cast<media::audio::common::AudioSource>(
+            sink_metadata.tracks[i].source);
+    hal_sink_metadata.tracks[i].gain = sink_metadata.tracks[i].gain;
+    LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_)
+              << ", source=" << sink_metadata.tracks[i].source
+              << ", dest_device=" << sink_metadata.tracks[i].dest_device
+              << ", gain=" << sink_metadata.tracks[i].gain
+              << ", dest_device_address="
+              << sink_metadata.tracks[i].dest_device_address;
+  }
+
+  auto hal_retval = stack_iface_->updateSinkMetadata(hal_sink_metadata);
+  if (!hal_retval.isOk()) {
+    LOG(WARNING) << __func__ << " - IBluetoothAudioPort SessionType="
+                 << toString(session_type_) << " failed";
+  }
+}
+
+bool BluetoothAudioSession::IsAidlAvailable() {
+  if (is_aidl_checked) return is_aidl_available;
+  is_aidl_available =
+      (AServiceManager_checkService(
+           kDefaultAudioProviderFactoryInterface.c_str()) != nullptr);
+  is_aidl_checked = true;
+  return is_aidl_available;
+}
+
+/***
+ *
+ * BluetoothAudioSessionInstance
+ *
+ ***/
+std::mutex BluetoothAudioSessionInstance::mutex_;
+std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
+    BluetoothAudioSessionInstance::sessions_map_;
+
+std::shared_ptr<BluetoothAudioSession>
+BluetoothAudioSessionInstance::GetSessionInstance(
+    const SessionType& session_type) {
+  std::lock_guard<std::mutex> guard(mutex_);
+
+  if (!sessions_map_.empty()) {
+    auto entry = sessions_map_.find(session_type);
+    if (entry != sessions_map_.end()) {
+      return entry->second;
+    }
+  }
+  std::shared_ptr<BluetoothAudioSession> session_ptr =
+      std::make_shared<BluetoothAudioSession>(session_type);
+  sessions_map_[session_type] = session_ptr;
+  return session_ptr;
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
new file mode 100644
index 0000000..85fd571
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSession.h
@@ -0,0 +1,227 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/common/SinkMetadata.h>
+#include <aidl/android/hardware/audio/common/SourceMetadata.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProvider.h>
+#include <aidl/android/hardware/bluetooth/audio/IBluetoothAudioProviderFactory.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+#include <fmq/AidlMessageQueue.h>
+#include <hardware/audio.h>
+
+#include <mutex>
+#include <unordered_map>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using ::aidl::android::hardware::common::fmq::MQDescriptor;
+using ::aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using ::android::AidlMessageQueue;
+
+using ::aidl::android::hardware::audio::common::SinkMetadata;
+using ::aidl::android::hardware::audio::common::SourceMetadata;
+
+using MQDataType = int8_t;
+using MQDataMode = SynchronizedReadWrite;
+using DataMQ = AidlMessageQueue<MQDataType, MQDataMode>;
+using DataMQDesc =
+    ::aidl::android::hardware::common::fmq::MQDescriptor<MQDataType,
+                                                         MQDataMode>;
+
+static constexpr uint16_t kObserversCookieSize = 0x0010;  // 0x0000 ~ 0x000f
+static constexpr uint16_t kObserversCookieUndefined =
+    (static_cast<uint16_t>(SessionType::UNKNOWN) << 8 & 0xff00);
+inline SessionType ObserversCookieGetSessionType(uint16_t cookie) {
+  return static_cast<SessionType>(cookie >> 8 & 0x00ff);
+}
+inline uint16_t ObserversCookieGetInitValue(SessionType session_type) {
+  return (static_cast<uint16_t>(session_type) << 8 & 0xff00);
+}
+inline uint16_t ObserversCookieGetUpperBound(SessionType session_type) {
+  return (static_cast<uint16_t>(session_type) << 8 & 0xff00) +
+         kObserversCookieSize;
+}
+
+/***
+ * This presents the callbacks of started / suspended and session changed,
+ * and the bluetooth_audio module uses to receive the status notification
+ ***/
+struct PortStatusCallbacks {
+  /***
+   * control_result_cb_ - when the Bluetooth stack reports results of
+   * streamStarted or streamSuspended, the BluetoothAudioProvider will invoke
+   * this callback to report to the bluetooth_audio module.
+   * @param: cookie - indicates which bluetooth_audio output should handle
+   * @param: start_resp - this report is for startStream or not
+   * @param: status - the result of startStream
+   ***/
+  std::function<void(uint16_t cookie, bool start_resp,
+                     BluetoothAudioStatus status)>
+      control_result_cb_;
+  /***
+   * session_changed_cb_ - when the Bluetooth stack start / end session, the
+   * BluetoothAudioProvider will invoke this callback to notify to the
+   * bluetooth_audio module.
+   * @param: cookie - indicates which bluetooth_audio output should handle
+   ***/
+  std::function<void(uint16_t cookie)> session_changed_cb_;
+  /***
+   * audio_configuration_changed_cb_ - when the Bluetooth stack change the audio
+   * configuration, the BluetoothAudioProvider will invoke this callback to
+   * notify to the bluetooth_audio module.
+   * @param: cookie - indicates which bluetooth_audio output should handle
+   ***/
+  std::function<void(uint16_t cookie)> audio_configuration_changed_cb_;
+};
+
+class BluetoothAudioSession {
+ public:
+  BluetoothAudioSession(const SessionType& session_type);
+
+  /***
+   * The function helps to check if this session is ready or not
+   * @return: true if the Bluetooth stack has started the specified session
+   ***/
+  bool IsSessionReady();
+
+  /***
+   * The report function is used to report that the Bluetooth stack has started
+   * this session without any failure, and will invoke session_changed_cb_ to
+   * notify those registered bluetooth_audio outputs
+   ***/
+  void OnSessionStarted(const std::shared_ptr<IBluetoothAudioPort> stack_iface,
+                        const DataMQDesc* mq_desc,
+                        const AudioConfiguration& audio_config);
+
+  /***
+   * The report function is used to report that the Bluetooth stack has ended
+   * the session, and will invoke session_changed_cb_ to notify registered
+   * bluetooth_audio outputs
+   ***/
+  void OnSessionEnded();
+
+  /***
+   * The report function is used to report that the Bluetooth stack has notified
+   * the result of startStream or suspendStream, and will invoke
+   * control_result_cb_ to notify registered bluetooth_audio outputs
+   ***/
+  void ReportControlStatus(bool start_resp, BluetoothAudioStatus status);
+
+  /***
+   * The control function helps the bluetooth_audio module to register
+   * PortStatusCallbacks
+   * @return: cookie - the assigned number to this bluetooth_audio output
+   ***/
+  uint16_t RegisterStatusCback(const PortStatusCallbacks& cbacks);
+
+  /***
+   * The control function helps the bluetooth_audio module to unregister
+   * PortStatusCallbacks
+   * @param: cookie - indicates which bluetooth_audio output is
+   ***/
+  void UnregisterStatusCback(uint16_t cookie);
+
+  /***
+   * The control function is for the bluetooth_audio module to get the current
+   * AudioConfiguration
+   ***/
+  const AudioConfiguration& GetAudioConfig();
+
+  /***
+   * The report function is used to report that the Bluetooth stack has notified
+   * the audio configuration changed, and will invoke
+   * audio_configuration_changed_cb_ to notify registered bluetooth_audio
+   * outputs
+   ***/
+  void ReportAudioConfigChanged(const AudioConfiguration& audio_config);
+
+  /***
+   * Those control functions are for the bluetooth_audio module to start,
+   * suspend, stop stream, to check position, and to update metadata.
+   ***/
+  bool StartStream();
+  bool SuspendStream();
+  void StopStream();
+  bool GetPresentationPosition(PresentationPosition& presentation_position);
+  void UpdateSourceMetadata(const struct source_metadata& source_metadata);
+  void UpdateSinkMetadata(const struct sink_metadata& sink_metadata);
+
+  // The control function writes stream to FMQ
+  size_t OutWritePcmData(const void* buffer, size_t bytes);
+  // The control function read stream from FMQ
+  size_t InReadPcmData(void* buffer, size_t bytes);
+
+  // Return if IBluetoothAudioProviderFactory implementation existed
+  static bool IsAidlAvailable();
+
+  static constexpr PcmConfiguration kInvalidPcmConfiguration = {};
+  // can't be constexpr because of non-literal type
+  static const CodecConfiguration kInvalidCodecConfiguration;
+
+  static AudioConfiguration invalidSoftwareAudioConfiguration;
+  static AudioConfiguration invalidOffloadAudioConfiguration;
+  static AudioConfiguration invalidLeOffloadAudioConfig;
+
+ private:
+  // using recursive_mutex to allow hwbinder to re-enter again.
+  std::recursive_mutex mutex_;
+  SessionType session_type_;
+
+  // audio control path to use for both software and offloading
+  std::shared_ptr<IBluetoothAudioPort> stack_iface_;
+  // audio data path (FMQ) for software encoding
+  std::unique_ptr<DataMQ> data_mq_;
+  // audio data configuration for both software and offloading
+  std::unique_ptr<AudioConfiguration> audio_config_;
+
+  // saving those registered bluetooth_audio's callbacks
+  std::unordered_map<uint16_t, std::shared_ptr<struct PortStatusCallbacks>>
+      observers_;
+
+  bool UpdateDataPath(const DataMQDesc* mq_desc);
+  bool UpdateAudioConfig(const AudioConfiguration& audio_config);
+  // invoking the registered session_changed_cb_
+  void ReportSessionStatus();
+
+  static inline std::atomic<bool> is_aidl_checked = false;
+  static inline std::atomic<bool> is_aidl_available = false;
+  static inline const std::string kDefaultAudioProviderFactoryInterface =
+      std::string() + IBluetoothAudioProviderFactory::descriptor + "/default";
+};
+
+class BluetoothAudioSessionInstance {
+ public:
+  // The API is to fetch the specified session of A2DP / Hearing Aid
+  static std::shared_ptr<BluetoothAudioSession> GetSessionInstance(
+      const SessionType& session_type);
+
+ private:
+  static std::mutex mutex_;
+  static std::unordered_map<SessionType, std::shared_ptr<BluetoothAudioSession>>
+      sessions_map_;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
new file mode 100644
index 0000000..a3ed428
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionControl.h
@@ -0,0 +1,182 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioSessionControl {
+ public:
+  /***
+   * The control API helps to check if session is ready or not
+   * @return: true if the Bluetooth stack has started th specified session
+   ***/
+  static bool IsSessionReady(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->IsSessionReady();
+    }
+
+    return false;
+  }
+
+  /***
+   * The control API helps the bluetooth_audio module to register
+   * PortStatusCallbacks
+   * @return: cookie - the assigned number to this bluetooth_audio output
+   ***/
+  static uint16_t RegisterControlResultCback(
+      const SessionType& session_type, const PortStatusCallbacks& cbacks) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->RegisterStatusCback(cbacks);
+    }
+    return kObserversCookieUndefined;
+  }
+
+  /***
+   * The control API helps the bluetooth_audio module to unregister
+   * PortStatusCallbacks
+   * @param: cookie - indicates which bluetooth_audio output is
+   ***/
+  static void UnregisterControlResultCback(const SessionType& session_type,
+                                           uint16_t cookie) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->UnregisterStatusCback(cookie);
+    }
+  }
+
+  /***
+   * The control API for the bluetooth_audio module to get current
+   * AudioConfiguration
+   ***/
+  static const AudioConfiguration GetAudioConfig(
+      const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->GetAudioConfig();
+    } else if (session_type ==
+               SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
+      return BluetoothAudioSession::invalidOffloadAudioConfiguration;
+    } else {
+      return BluetoothAudioSession::invalidSoftwareAudioConfiguration;
+    }
+  }
+
+  /***
+   * Those control APIs for the bluetooth_audio module to start / suspend /
+  stop
+   * stream, to check position, and to update metadata.
+  ***/
+  static bool StartStream(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->StartStream();
+    }
+    return false;
+  }
+
+  static bool SuspendStream(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->SuspendStream();
+    }
+    return false;
+  }
+
+  static void StopStream(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->StopStream();
+    }
+  }
+
+  static bool GetPresentationPosition(
+      const SessionType& session_type,
+      PresentationPosition& presentation_position) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->GetPresentationPosition(presentation_position);
+    }
+    return false;
+  }
+
+  static void UpdateSourceMetadata(
+      const SessionType& session_type,
+      const struct source_metadata& source_metadata) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->UpdateSourceMetadata(source_metadata);
+    }
+  }
+
+  static void UpdateSinkMetadata(const SessionType& session_type,
+                                 const struct sink_metadata& sink_metadata) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->UpdateSinkMetadata(sink_metadata);
+    }
+  }
+
+  /***
+   * The control API writes stream to FMQ
+   ***/
+  static size_t OutWritePcmData(const SessionType& session_type,
+                                const void* buffer, size_t bytes) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->OutWritePcmData(buffer, bytes);
+    }
+    return 0;
+  }
+
+  /***
+   * The control API reads stream from FMQ
+   ***/
+  static size_t InReadPcmData(const SessionType& session_type, void* buffer,
+                              size_t bytes) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      return session_ptr->InReadPcmData(buffer, bytes);
+    }
+    return 0;
+  }
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h
new file mode 100644
index 0000000..18569c3
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioSessionReport.h
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+class BluetoothAudioSessionReport {
+ public:
+  /***
+   * The API reports the Bluetooth stack has started the session, and will
+   * inform registered bluetooth_audio outputs
+   ***/
+  static void OnSessionStarted(
+      const SessionType& session_type,
+      const std::shared_ptr<IBluetoothAudioPort> host_iface,
+      const DataMQDesc* data_mq, const AudioConfiguration& audio_config) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->OnSessionStarted(host_iface, data_mq, audio_config);
+    }
+  }
+
+  /***
+   * The API reports the Bluetooth stack has ended the session, and will
+   * inform registered bluetooth_audio outputs
+   ***/
+  static void OnSessionEnded(const SessionType& session_type) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->OnSessionEnded();
+    }
+  }
+
+  /***
+   * The API reports the Bluetooth stack has replied the result of startStream
+   * or suspendStream, and will inform registered bluetooth_audio outputs
+   ***/
+  static void ReportControlStatus(const SessionType& session_type,
+                                  const bool& start_resp,
+                                  BluetoothAudioStatus status) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->ReportControlStatus(start_resp, status);
+    }
+  }
+  /***
+   * The API reports the Bluetooth stack has replied the changed of the audio
+   * configuration, and will inform registered bluetooth_audio outputs
+   ***/
+  static void ReportAudioConfigChanged(const SessionType& session_type,
+                                       const AudioConfiguration& audio_config) {
+    std::shared_ptr<BluetoothAudioSession> session_ptr =
+        BluetoothAudioSessionInstance::GetSessionInstance(session_type);
+    if (session_ptr != nullptr) {
+      session_ptr->ReportAudioConfigChanged(audio_config);
+    }
+  }
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
\ No newline at end of file
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
new file mode 100644
index 0000000..91e0238
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware.cpp
@@ -0,0 +1,775 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "BtAudioNakahara"
+
+#include <aidl/android/hardware/bluetooth/audio/AudioConfiguration.h>
+#include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
+#include <android-base/logging.h>
+
+#include <functional>
+#include <unordered_map>
+
+#include "../aidl_session/BluetoothAudioSession.h"
+#include "../aidl_session/BluetoothAudioSessionControl.h"
+#include "HidlToAidlMiddleware_2_0.h"
+#include "HidlToAidlMiddleware_2_1.h"
+#include "HidlToAidlMiddleware_2_2.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using HidlStatus = ::android::hardware::bluetooth::audio::V2_0::Status;
+using PcmConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
+using SampleRate_2_0 = ::android::hardware::bluetooth::audio::V2_0::SampleRate;
+using ChannelMode_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using BitsPerSample_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using CodecConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
+using CodecType_2_0 = ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using SbcConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::SbcParameters;
+using AacConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::AacParameters;
+using LdacConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
+using AptxConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
+using SbcAllocMethod_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
+using SbcBlockLength_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
+using SbcChannelMode_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
+using SbcNumSubbands_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
+using AacObjectType_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
+using AacVarBitRate_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
+using LdacChannelMode_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
+using LdacQualityIndex_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
+
+using PcmConfig_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::PcmParameters;
+using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+using Lc3CodecConfig_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::Lc3CodecConfiguration;
+using Lc3Config_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::Lc3Parameters;
+using Lc3FrameDuration_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::Lc3FrameDuration;
+
+using LeAudioConfig_2_2 =
+    ::android::hardware::bluetooth::audio::V2_2::LeAudioConfiguration;
+using LeAudioMode_2_2 =
+    ::android::hardware::bluetooth::audio::V2_2::LeAudioMode;
+
+std::mutex legacy_callback_lock;
+std::unordered_map<
+    SessionType,
+    std::unordered_map<uint16_t, std::shared_ptr<PortStatusCallbacks_2_2>>>
+    legacy_callback_table;
+
+const static std::unordered_map<SessionType_2_0, SessionType>
+    session_type_2_0_to_aidl_map{
+        {SessionType_2_0::A2DP_SOFTWARE_ENCODING_DATAPATH,
+         SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH},
+        {SessionType_2_0::A2DP_HARDWARE_OFFLOAD_DATAPATH,
+         SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH},
+        {SessionType_2_0::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
+         SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH},
+    };
+
+const static std::unordered_map<SessionType_2_1, SessionType>
+    session_type_2_1_to_aidl_map{
+        {SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH,
+         SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH},
+        {SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH,
+         SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH},
+        {SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
+         SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH},
+        {SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
+         SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH},
+        {SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH,
+         SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH},
+        {SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
+         SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH},
+        {SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
+         SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH},
+    };
+
+const static std::unordered_map<int32_t, SampleRate_2_0>
+    sample_rate_to_hidl_2_0_map{
+        {44100, SampleRate_2_0::RATE_44100},
+        {48000, SampleRate_2_0::RATE_48000},
+        {88200, SampleRate_2_0::RATE_88200},
+        {96000, SampleRate_2_0::RATE_96000},
+        {176400, SampleRate_2_0::RATE_176400},
+        {192000, SampleRate_2_0::RATE_192000},
+        {16000, SampleRate_2_0::RATE_16000},
+        {24000, SampleRate_2_0::RATE_24000},
+    };
+
+const static std::unordered_map<int32_t, SampleRate_2_1>
+    sample_rate_to_hidl_2_1_map{
+        {44100, SampleRate_2_1::RATE_44100},
+        {48000, SampleRate_2_1::RATE_48000},
+        {88200, SampleRate_2_1::RATE_88200},
+        {96000, SampleRate_2_1::RATE_96000},
+        {176400, SampleRate_2_1::RATE_176400},
+        {192000, SampleRate_2_1::RATE_192000},
+        {16000, SampleRate_2_1::RATE_16000},
+        {24000, SampleRate_2_1::RATE_24000},
+        {8000, SampleRate_2_1::RATE_8000},
+        {32000, SampleRate_2_1::RATE_32000},
+    };
+
+const static std::unordered_map<CodecType, CodecType_2_0>
+    codec_type_to_hidl_2_0_map{
+        {CodecType::UNKNOWN, CodecType_2_0::UNKNOWN},
+        {CodecType::SBC, CodecType_2_0::SBC},
+        {CodecType::AAC, CodecType_2_0::AAC},
+        {CodecType::APTX, CodecType_2_0::APTX},
+        {CodecType::APTX_HD, CodecType_2_0::APTX_HD},
+        {CodecType::LDAC, CodecType_2_0::LDAC},
+        {CodecType::LC3, CodecType_2_0::UNKNOWN},
+    };
+
+const static std::unordered_map<SbcChannelMode, SbcChannelMode_2_0>
+    sbc_channel_mode_to_hidl_2_0_map{
+        {SbcChannelMode::UNKNOWN, SbcChannelMode_2_0::UNKNOWN},
+        {SbcChannelMode::JOINT_STEREO, SbcChannelMode_2_0::JOINT_STEREO},
+        {SbcChannelMode::STEREO, SbcChannelMode_2_0::STEREO},
+        {SbcChannelMode::DUAL, SbcChannelMode_2_0::DUAL},
+        {SbcChannelMode::MONO, SbcChannelMode_2_0::MONO},
+    };
+
+const static std::unordered_map<int8_t, SbcBlockLength_2_0>
+    sbc_block_length_to_hidl_map{
+        {4, SbcBlockLength_2_0::BLOCKS_4},
+        {8, SbcBlockLength_2_0::BLOCKS_8},
+        {12, SbcBlockLength_2_0::BLOCKS_12},
+        {16, SbcBlockLength_2_0::BLOCKS_16},
+    };
+
+const static std::unordered_map<int8_t, SbcNumSubbands_2_0>
+    sbc_subbands_to_hidl_map{
+        {4, SbcNumSubbands_2_0::SUBBAND_4},
+        {8, SbcNumSubbands_2_0::SUBBAND_8},
+    };
+
+const static std::unordered_map<SbcAllocMethod, SbcAllocMethod_2_0>
+    sbc_alloc_method_to_hidl_map{
+        {SbcAllocMethod::ALLOC_MD_S, SbcAllocMethod_2_0::ALLOC_MD_S},
+        {SbcAllocMethod::ALLOC_MD_L, SbcAllocMethod_2_0::ALLOC_MD_L},
+    };
+
+const static std::unordered_map<AacObjectType, AacObjectType_2_0>
+    aac_object_type_to_hidl_map{
+        {AacObjectType::MPEG2_LC, AacObjectType_2_0::MPEG2_LC},
+        {AacObjectType::MPEG4_LC, AacObjectType_2_0::MPEG4_LC},
+        {AacObjectType::MPEG4_LTP, AacObjectType_2_0::MPEG4_LTP},
+        {AacObjectType::MPEG4_SCALABLE, AacObjectType_2_0::MPEG4_SCALABLE},
+    };
+
+const static std::unordered_map<LdacChannelMode, LdacChannelMode_2_0>
+    ldac_channel_mode_to_hidl_map{
+        {LdacChannelMode::UNKNOWN, LdacChannelMode_2_0::UNKNOWN},
+        {LdacChannelMode::STEREO, LdacChannelMode_2_0::STEREO},
+        {LdacChannelMode::DUAL, LdacChannelMode_2_0::DUAL},
+        {LdacChannelMode::MONO, LdacChannelMode_2_0::MONO},
+    };
+
+const static std::unordered_map<LdacQualityIndex, LdacQualityIndex_2_0>
+    ldac_qindex_to_hidl_map{
+        {LdacQualityIndex::HIGH, LdacQualityIndex_2_0::QUALITY_HIGH},
+        {LdacQualityIndex::MID, LdacQualityIndex_2_0::QUALITY_MID},
+        {LdacQualityIndex::LOW, LdacQualityIndex_2_0::QUALITY_LOW},
+        {LdacQualityIndex::ABR, LdacQualityIndex_2_0::QUALITY_ABR},
+    };
+
+const static std::unordered_map<LeAudioMode, LeAudioMode_2_2>
+    leaudio_mode_to_hidl_map{
+        {LeAudioMode::UNKNOWN, LeAudioMode_2_2::UNKNOWN},
+        {LeAudioMode::UNICAST, LeAudioMode_2_2::UNICAST},
+        {LeAudioMode::BROADCAST, LeAudioMode_2_2::BROADCAST},
+    };
+
+inline SessionType from_session_type_2_0(
+    const SessionType_2_0& session_type_hidl) {
+  auto it = session_type_2_0_to_aidl_map.find(session_type_hidl);
+  if (it != session_type_2_0_to_aidl_map.end()) return it->second;
+  return SessionType::UNKNOWN;
+}
+
+inline SessionType from_session_type_2_1(
+    const SessionType_2_1& session_type_hidl) {
+  auto it = session_type_2_1_to_aidl_map.find(session_type_hidl);
+  if (it != session_type_2_1_to_aidl_map.end()) return it->second;
+  return SessionType::UNKNOWN;
+}
+
+inline HidlStatus to_hidl_status(const BluetoothAudioStatus& status) {
+  switch (status) {
+    case BluetoothAudioStatus::SUCCESS:
+      return HidlStatus::SUCCESS;
+    case BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION:
+      return HidlStatus::UNSUPPORTED_CODEC_CONFIGURATION;
+    default:
+      return HidlStatus::FAILURE;
+  }
+}
+
+inline SampleRate_2_0 to_hidl_sample_rate_2_0(const int32_t sample_rate_hz) {
+  auto it = sample_rate_to_hidl_2_0_map.find(sample_rate_hz);
+  if (it != sample_rate_to_hidl_2_0_map.end()) return it->second;
+  return SampleRate_2_0::RATE_UNKNOWN;
+}
+
+inline SampleRate_2_1 to_hidl_sample_rate_2_1(const int32_t sample_rate_hz) {
+  auto it = sample_rate_to_hidl_2_1_map.find(sample_rate_hz);
+  if (it != sample_rate_to_hidl_2_1_map.end()) return it->second;
+  return SampleRate_2_1::RATE_UNKNOWN;
+}
+
+inline BitsPerSample_2_0 to_hidl_bits_per_sample(const int8_t bit_per_sample) {
+  switch (bit_per_sample) {
+    case 16:
+      return BitsPerSample_2_0::BITS_16;
+    case 24:
+      return BitsPerSample_2_0::BITS_24;
+    case 32:
+      return BitsPerSample_2_0::BITS_32;
+    default:
+      return BitsPerSample_2_0::BITS_UNKNOWN;
+  }
+}
+
+inline ChannelMode_2_0 to_hidl_channel_mode(const ChannelMode channel_mode) {
+  switch (channel_mode) {
+    case ChannelMode::MONO:
+      return ChannelMode_2_0::MONO;
+    case ChannelMode::STEREO:
+      return ChannelMode_2_0::STEREO;
+    default:
+      return ChannelMode_2_0::UNKNOWN;
+  }
+}
+
+inline PcmConfig_2_0 to_hidl_pcm_config_2_0(
+    const PcmConfiguration& pcm_config) {
+  PcmConfig_2_0 hidl_pcm_config;
+  hidl_pcm_config.sampleRate = to_hidl_sample_rate_2_0(pcm_config.sampleRateHz);
+  hidl_pcm_config.channelMode = to_hidl_channel_mode(pcm_config.channelMode);
+  hidl_pcm_config.bitsPerSample =
+      to_hidl_bits_per_sample(pcm_config.bitsPerSample);
+  return hidl_pcm_config;
+}
+
+inline CodecType_2_0 to_hidl_codec_type_2_0(const CodecType codec_type) {
+  auto it = codec_type_to_hidl_2_0_map.find(codec_type);
+  if (it != codec_type_to_hidl_2_0_map.end()) return it->second;
+  return CodecType_2_0::UNKNOWN;
+}
+
+inline SbcConfig_2_0 to_hidl_sbc_config(const SbcConfiguration sbc_config) {
+  SbcConfig_2_0 hidl_sbc_config;
+  hidl_sbc_config.minBitpool = sbc_config.minBitpool;
+  hidl_sbc_config.maxBitpool = sbc_config.maxBitpool;
+  hidl_sbc_config.sampleRate = to_hidl_sample_rate_2_0(sbc_config.sampleRateHz);
+  hidl_sbc_config.bitsPerSample =
+      to_hidl_bits_per_sample(sbc_config.bitsPerSample);
+  if (sbc_channel_mode_to_hidl_2_0_map.find(sbc_config.channelMode) !=
+      sbc_channel_mode_to_hidl_2_0_map.end()) {
+    hidl_sbc_config.channelMode =
+        sbc_channel_mode_to_hidl_2_0_map.at(sbc_config.channelMode);
+  }
+  if (sbc_block_length_to_hidl_map.find(sbc_config.blockLength) !=
+      sbc_block_length_to_hidl_map.end()) {
+    hidl_sbc_config.blockLength =
+        sbc_block_length_to_hidl_map.at(sbc_config.blockLength);
+  }
+  if (sbc_subbands_to_hidl_map.find(sbc_config.numSubbands) !=
+      sbc_subbands_to_hidl_map.end()) {
+    hidl_sbc_config.numSubbands =
+        sbc_subbands_to_hidl_map.at(sbc_config.numSubbands);
+  }
+  if (sbc_alloc_method_to_hidl_map.find(sbc_config.allocMethod) !=
+      sbc_alloc_method_to_hidl_map.end()) {
+    hidl_sbc_config.allocMethod =
+        sbc_alloc_method_to_hidl_map.at(sbc_config.allocMethod);
+  }
+  return hidl_sbc_config;
+}
+
+inline AacConfig_2_0 to_hidl_aac_config(const AacConfiguration aac_config) {
+  AacConfig_2_0 hidl_aac_config;
+  hidl_aac_config.sampleRate = to_hidl_sample_rate_2_0(aac_config.sampleRateHz);
+  hidl_aac_config.bitsPerSample =
+      to_hidl_bits_per_sample(aac_config.bitsPerSample);
+  hidl_aac_config.channelMode = to_hidl_channel_mode(aac_config.channelMode);
+  if (aac_object_type_to_hidl_map.find(aac_config.objectType) !=
+      aac_object_type_to_hidl_map.end()) {
+    hidl_aac_config.objectType =
+        aac_object_type_to_hidl_map.at(aac_config.objectType);
+  }
+  hidl_aac_config.variableBitRateEnabled = aac_config.variableBitRateEnabled
+                                               ? AacVarBitRate_2_0::ENABLED
+                                               : AacVarBitRate_2_0::DISABLED;
+  return hidl_aac_config;
+}
+
+inline LdacConfig_2_0 to_hidl_ldac_config(const LdacConfiguration ldac_config) {
+  LdacConfig_2_0 hidl_ldac_config;
+  hidl_ldac_config.sampleRate =
+      to_hidl_sample_rate_2_0(ldac_config.sampleRateHz);
+  hidl_ldac_config.bitsPerSample =
+      to_hidl_bits_per_sample(ldac_config.bitsPerSample);
+  if (ldac_channel_mode_to_hidl_map.find(ldac_config.channelMode) !=
+      ldac_channel_mode_to_hidl_map.end()) {
+    hidl_ldac_config.channelMode =
+        ldac_channel_mode_to_hidl_map.at(ldac_config.channelMode);
+  }
+  if (ldac_qindex_to_hidl_map.find(ldac_config.qualityIndex) !=
+      ldac_qindex_to_hidl_map.end()) {
+    hidl_ldac_config.qualityIndex =
+        ldac_qindex_to_hidl_map.at(ldac_config.qualityIndex);
+  }
+  return hidl_ldac_config;
+}
+
+inline AptxConfig_2_0 to_hidl_aptx_config(const AptxConfiguration aptx_config) {
+  AptxConfig_2_0 hidl_aptx_config;
+  hidl_aptx_config.sampleRate =
+      to_hidl_sample_rate_2_0(aptx_config.sampleRateHz);
+  hidl_aptx_config.bitsPerSample =
+      to_hidl_bits_per_sample(aptx_config.bitsPerSample);
+  hidl_aptx_config.channelMode = to_hidl_channel_mode(aptx_config.channelMode);
+  return hidl_aptx_config;
+}
+
+inline CodecConfig_2_0 to_hidl_codec_config_2_0(
+    const CodecConfiguration& codec_config) {
+  CodecConfig_2_0 hidl_codec_config;
+  hidl_codec_config.codecType = to_hidl_codec_type_2_0(codec_config.codecType);
+  hidl_codec_config.encodedAudioBitrate =
+      static_cast<uint32_t>(codec_config.encodedAudioBitrate);
+  hidl_codec_config.peerMtu = static_cast<uint32_t>(codec_config.peerMtu);
+  hidl_codec_config.isScmstEnabled = codec_config.isScmstEnabled;
+  switch (codec_config.config.getTag()) {
+    case CodecConfiguration::CodecSpecific::sbcConfig:
+      hidl_codec_config.config.sbcConfig(to_hidl_sbc_config(
+          codec_config.config
+              .get<CodecConfiguration::CodecSpecific::sbcConfig>()));
+      break;
+    case CodecConfiguration::CodecSpecific::aacConfig:
+      hidl_codec_config.config.aacConfig(to_hidl_aac_config(
+          codec_config.config
+              .get<CodecConfiguration::CodecSpecific::aacConfig>()));
+      break;
+    case CodecConfiguration::CodecSpecific::ldacConfig:
+      hidl_codec_config.config.ldacConfig(to_hidl_ldac_config(
+          codec_config.config
+              .get<CodecConfiguration::CodecSpecific::ldacConfig>()));
+      break;
+    case CodecConfiguration::CodecSpecific::aptxConfig:
+      hidl_codec_config.config.aptxConfig(to_hidl_aptx_config(
+          codec_config.config
+              .get<CodecConfiguration::CodecSpecific::aptxConfig>()));
+      break;
+    default:
+      break;
+  }
+  return hidl_codec_config;
+}
+
+inline AudioConfig_2_0 to_hidl_audio_config_2_0(
+    const AudioConfiguration& audio_config) {
+  AudioConfig_2_0 hidl_audio_config;
+  if (audio_config.getTag() == AudioConfiguration::pcmConfig) {
+    hidl_audio_config.pcmConfig(to_hidl_pcm_config_2_0(
+        audio_config.get<AudioConfiguration::pcmConfig>()));
+  } else if (audio_config.getTag() == AudioConfiguration::a2dpConfig) {
+    hidl_audio_config.codecConfig(to_hidl_codec_config_2_0(
+        audio_config.get<AudioConfiguration::a2dpConfig>()));
+  }
+  return hidl_audio_config;
+}
+
+inline PcmConfig_2_1 to_hidl_pcm_config_2_1(
+    const PcmConfiguration& pcm_config) {
+  PcmConfig_2_1 hidl_pcm_config;
+  hidl_pcm_config.sampleRate = to_hidl_sample_rate_2_1(pcm_config.sampleRateHz);
+  hidl_pcm_config.channelMode = to_hidl_channel_mode(pcm_config.channelMode);
+  hidl_pcm_config.bitsPerSample =
+      to_hidl_bits_per_sample(pcm_config.bitsPerSample);
+  hidl_pcm_config.dataIntervalUs =
+      static_cast<uint32_t>(pcm_config.dataIntervalUs);
+  return hidl_pcm_config;
+}
+
+inline Lc3Config_2_1 to_hidl_lc3_config_2_1(
+    const Lc3Configuration& lc3_config) {
+  Lc3Config_2_1 hidl_lc3_config;
+  hidl_lc3_config.pcmBitDepth = to_hidl_bits_per_sample(lc3_config.pcmBitDepth);
+  hidl_lc3_config.samplingFrequency =
+      to_hidl_sample_rate_2_1(lc3_config.samplingFrequencyHz);
+  if (lc3_config.samplingFrequencyHz == 10000)
+    hidl_lc3_config.frameDuration = Lc3FrameDuration_2_1::DURATION_10000US;
+  else if (lc3_config.samplingFrequencyHz == 7500)
+    hidl_lc3_config.frameDuration = Lc3FrameDuration_2_1::DURATION_7500US;
+  hidl_lc3_config.octetsPerFrame =
+      static_cast<uint32_t>(lc3_config.octetsPerFrame);
+  hidl_lc3_config.blocksPerSdu = static_cast<uint32_t>(lc3_config.blocksPerSdu);
+  return hidl_lc3_config;
+}
+
+inline Lc3CodecConfig_2_1 to_hidl_leaudio_config_2_1(
+    const LeAudioConfiguration& leaudio_config) {
+  auto& unicast_config =
+      leaudio_config.modeConfig
+          .get<LeAudioConfiguration::LeAudioModeConfig::unicastConfig>();
+
+  auto& le_codec_config = unicast_config.leAudioCodecConfig
+                              .get<LeAudioCodecConfiguration::lc3Config>();
+
+  Lc3CodecConfig_2_1 hidl_lc3_codec_config;
+  hidl_lc3_codec_config.lc3Config = to_hidl_lc3_config_2_1(le_codec_config);
+
+  hidl_lc3_codec_config.audioChannelAllocation =
+      unicast_config.streamMap.size();
+
+  return hidl_lc3_codec_config;
+}
+
+inline LeAudioConfig_2_2 to_hidl_leaudio_config_2_2(
+    const LeAudioConfiguration& leaudio_config) {
+  LeAudioConfig_2_2 hidl_leaudio_config;
+  if (leaudio_mode_to_hidl_map.find(leaudio_config.mode) !=
+      leaudio_mode_to_hidl_map.end()) {
+    hidl_leaudio_config.mode = leaudio_mode_to_hidl_map.at(leaudio_config.mode);
+  }
+
+  if (leaudio_config.modeConfig.getTag() ==
+      LeAudioConfiguration::LeAudioModeConfig::unicastConfig) {
+    auto& unicast_config =
+        leaudio_config.modeConfig
+            .get<LeAudioConfiguration::LeAudioModeConfig::unicastConfig>();
+    ::android::hardware::bluetooth::audio::V2_2::UnicastConfig
+        hidl_unicast_config;
+    hidl_unicast_config.peerDelay =
+        static_cast<uint32_t>(unicast_config.peerDelay);
+
+    auto& lc3_config = unicast_config.leAudioCodecConfig
+                           .get<LeAudioCodecConfiguration::lc3Config>();
+    hidl_unicast_config.lc3Config = to_hidl_lc3_config_2_1(lc3_config);
+
+    hidl_unicast_config.streamMap.resize(unicast_config.streamMap.size());
+    for (int i = 0; i < unicast_config.streamMap.size(); i++) {
+      hidl_unicast_config.streamMap[i].audioChannelAllocation =
+          static_cast<uint32_t>(
+              unicast_config.streamMap[i].audioChannelAllocation);
+      hidl_unicast_config.streamMap[i].streamHandle =
+          static_cast<uint16_t>(unicast_config.streamMap[i].streamHandle);
+    }
+  } else if (leaudio_config.modeConfig.getTag() ==
+             LeAudioConfiguration::LeAudioModeConfig::broadcastConfig) {
+    auto bcast_config =
+        leaudio_config.modeConfig
+            .get<LeAudioConfiguration::LeAudioModeConfig::broadcastConfig>();
+    ::android::hardware::bluetooth::audio::V2_2::BroadcastConfig
+        hidl_bcast_config;
+    hidl_bcast_config.streamMap.resize(bcast_config.streamMap.size());
+    for (int i = 0; i < bcast_config.streamMap.size(); i++) {
+      hidl_bcast_config.streamMap[i].audioChannelAllocation =
+          static_cast<uint32_t>(
+              bcast_config.streamMap[i].audioChannelAllocation);
+      hidl_bcast_config.streamMap[i].streamHandle =
+          static_cast<uint16_t>(bcast_config.streamMap[i].streamHandle);
+      hidl_bcast_config.streamMap[i].lc3Config = to_hidl_lc3_config_2_1(
+          bcast_config.streamMap[i]
+              .leAudioCodecConfig.get<LeAudioCodecConfiguration::lc3Config>());
+    }
+  }
+  return hidl_leaudio_config;
+}
+
+inline AudioConfig_2_1 to_hidl_audio_config_2_1(
+    const AudioConfiguration& audio_config) {
+  AudioConfig_2_1 hidl_audio_config;
+  switch (audio_config.getTag()) {
+    case AudioConfiguration::pcmConfig:
+      hidl_audio_config.pcmConfig(to_hidl_pcm_config_2_1(
+          audio_config.get<AudioConfiguration::pcmConfig>()));
+      break;
+    case AudioConfiguration::a2dpConfig:
+      hidl_audio_config.codecConfig(to_hidl_codec_config_2_0(
+          audio_config.get<AudioConfiguration::a2dpConfig>()));
+      break;
+    case AudioConfiguration::leAudioConfig:
+      hidl_audio_config.leAudioCodecConfig(to_hidl_leaudio_config_2_1(
+          audio_config.get<AudioConfiguration::leAudioConfig>()));
+      break;
+  }
+  return hidl_audio_config;
+}
+
+inline AudioConfig_2_2 to_hidl_audio_config_2_2(
+    const AudioConfiguration& audio_config) {
+  AudioConfig_2_2 hidl_audio_config;
+  switch (audio_config.getTag()) {
+    case AudioConfiguration::pcmConfig:
+      hidl_audio_config.pcmConfig(to_hidl_pcm_config_2_1(
+          audio_config.get<AudioConfiguration::pcmConfig>()));
+      break;
+    case AudioConfiguration::a2dpConfig:
+      hidl_audio_config.codecConfig(to_hidl_codec_config_2_0(
+          audio_config.get<AudioConfiguration::a2dpConfig>()));
+      break;
+    case AudioConfiguration::leAudioConfig:
+      hidl_audio_config.leAudioConfig(to_hidl_leaudio_config_2_2(
+          audio_config.get<AudioConfiguration::leAudioConfig>()));
+      break;
+  }
+  return hidl_audio_config;
+}
+
+/***
+ *
+ * 2.0
+ *
+ ***/
+
+bool HidlToAidlMiddleware_2_0::IsSessionReady(
+    const SessionType_2_0& session_type) {
+  return BluetoothAudioSessionControl::IsSessionReady(
+      from_session_type_2_0(session_type));
+}
+
+uint16_t HidlToAidlMiddleware_2_0::RegisterControlResultCback(
+    const SessionType_2_0& session_type,
+    const PortStatusCallbacks_2_0& cbacks) {
+  PortStatusCallbacks_2_2 callback_2_2{
+      .control_result_cb_ = cbacks.control_result_cb_,
+      .session_changed_cb_ = cbacks.session_changed_cb_,
+  };
+  return HidlToAidlMiddleware_2_2::RegisterControlResultCback(
+      static_cast<SessionType_2_1>(session_type), callback_2_2);
+}
+
+void HidlToAidlMiddleware_2_0::UnregisterControlResultCback(
+    const SessionType_2_0& session_type, uint16_t cookie) {
+  HidlToAidlMiddleware_2_2::UnregisterControlResultCback(
+      static_cast<SessionType_2_1>(session_type), cookie);
+}
+
+const AudioConfig_2_0 HidlToAidlMiddleware_2_0::GetAudioConfig(
+    const SessionType_2_0& session_type) {
+  return to_hidl_audio_config_2_0(BluetoothAudioSessionControl::GetAudioConfig(
+      from_session_type_2_0(session_type)));
+}
+
+bool HidlToAidlMiddleware_2_0::StartStream(
+    const SessionType_2_0& session_type) {
+  return BluetoothAudioSessionControl::StartStream(
+      from_session_type_2_0(session_type));
+}
+
+void HidlToAidlMiddleware_2_0::StopStream(const SessionType_2_0& session_type) {
+  return BluetoothAudioSessionControl::StopStream(
+      from_session_type_2_0(session_type));
+}
+
+bool HidlToAidlMiddleware_2_0::SuspendStream(
+    const SessionType_2_0& session_type) {
+  return BluetoothAudioSessionControl::SuspendStream(
+      from_session_type_2_0(session_type));
+}
+
+bool HidlToAidlMiddleware_2_0::GetPresentationPosition(
+    const SessionType_2_0& session_type, uint64_t* remote_delay_report_ns,
+    uint64_t* total_bytes_readed, timespec* data_position) {
+  PresentationPosition presentation_position;
+  auto ret_val = BluetoothAudioSessionControl::GetPresentationPosition(
+      from_session_type_2_0(session_type), presentation_position);
+  if (remote_delay_report_ns)
+    *remote_delay_report_ns = presentation_position.remoteDeviceAudioDelayNanos;
+  if (total_bytes_readed)
+    *total_bytes_readed = presentation_position.transmittedOctets;
+  if (data_position)
+    *data_position = {
+        .tv_sec = static_cast<__kernel_old_time_t>(
+            presentation_position.transmittedOctetsTimestamp.tvSec),
+        .tv_nsec = static_cast<long>(
+            presentation_position.transmittedOctetsTimestamp.tvNSec)};
+  return ret_val;
+}
+
+void HidlToAidlMiddleware_2_0::UpdateTracksMetadata(
+    const SessionType_2_0& session_type,
+    const struct source_metadata* source_metadata) {
+  return BluetoothAudioSessionControl::UpdateSourceMetadata(
+      from_session_type_2_0(session_type), *source_metadata);
+}
+
+size_t HidlToAidlMiddleware_2_0::OutWritePcmData(
+    const SessionType_2_0& session_type, const void* buffer, size_t bytes) {
+  return BluetoothAudioSessionControl::OutWritePcmData(
+      from_session_type_2_0(session_type), buffer, bytes);
+}
+
+bool HidlToAidlMiddleware_2_0::IsAidlAvailable() {
+  return BluetoothAudioSession::IsAidlAvailable();
+}
+
+/***
+ *
+ * 2.1
+ *
+ ***/
+
+const AudioConfig_2_1 HidlToAidlMiddleware_2_1::GetAudioConfig(
+    const SessionType_2_1& session_type) {
+  return to_hidl_audio_config_2_1(BluetoothAudioSessionControl::GetAudioConfig(
+      from_session_type_2_1(session_type)));
+}
+
+/***
+ *
+ * 2.2
+ *
+ ***/
+
+bool HidlToAidlMiddleware_2_2::IsSessionReady(
+    const SessionType_2_1& session_type) {
+  return BluetoothAudioSessionControl::IsSessionReady(
+      from_session_type_2_1(session_type));
+}
+
+uint16_t HidlToAidlMiddleware_2_2::RegisterControlResultCback(
+    const SessionType_2_1& session_type,
+    const PortStatusCallbacks_2_2& cbacks) {
+  LOG(INFO) << __func__ << ": " << toString(session_type);
+  auto aidl_session_type = from_session_type_2_1(session_type);
+  // Pass the exact reference to the lambda
+  auto& session_legacy_callback_table =
+      legacy_callback_table[aidl_session_type];
+  PortStatusCallbacks aidl_callbacks{};
+  if (cbacks.control_result_cb_) {
+    aidl_callbacks.control_result_cb_ =
+        [&session_legacy_callback_table](uint16_t cookie, bool start_resp,
+                                         const BluetoothAudioStatus& status) {
+          if (session_legacy_callback_table.find(cookie) ==
+              session_legacy_callback_table.end()) {
+            LOG(ERROR) << __func__ << ": Unknown callback invoked!";
+            return;
+          }
+          auto& cback = session_legacy_callback_table[cookie];
+          cback->control_result_cb_(cookie, start_resp, to_hidl_status(status));
+        };
+  }
+  if (cbacks.session_changed_cb_) {
+    aidl_callbacks.session_changed_cb_ =
+        [&session_legacy_callback_table](uint16_t cookie) {
+          if (session_legacy_callback_table.find(cookie) ==
+              session_legacy_callback_table.end()) {
+            LOG(ERROR) << __func__ << ": Unknown callback invoked!";
+            return;
+          }
+          auto& cback = session_legacy_callback_table[cookie];
+          cback->session_changed_cb_(cookie);
+        };
+  };
+  if (cbacks.audio_configuration_changed_cb_) {
+    aidl_callbacks.audio_configuration_changed_cb_ =
+        [&session_legacy_callback_table](uint16_t cookie) {
+          if (session_legacy_callback_table.find(cookie) ==
+              session_legacy_callback_table.end()) {
+            LOG(ERROR) << __func__ << ": Unknown callback invoked!";
+            return;
+          }
+          auto& cback = session_legacy_callback_table[cookie];
+          cback->audio_configuration_changed_cb_(cookie);
+        };
+  };
+  auto cookie = BluetoothAudioSessionControl::RegisterControlResultCback(
+      aidl_session_type, aidl_callbacks);
+  {
+    std::lock_guard<std::mutex> guard(legacy_callback_lock);
+    session_legacy_callback_table[cookie] =
+        std::make_shared<PortStatusCallbacks_2_2>(cbacks);
+  }
+  return cookie;
+}
+
+void HidlToAidlMiddleware_2_2::UnregisterControlResultCback(
+    const SessionType_2_1& session_type, uint16_t cookie) {
+  LOG(INFO) << __func__ << ": " << toString(session_type);
+  auto aidl_session_type = from_session_type_2_1(session_type);
+  BluetoothAudioSessionControl::UnregisterControlResultCback(aidl_session_type,
+                                                             cookie);
+  auto& session_callback_table = legacy_callback_table[aidl_session_type];
+  if (session_callback_table.find(cookie) != session_callback_table.end()) {
+    std::lock_guard<std::mutex> guard(legacy_callback_lock);
+    session_callback_table.erase(cookie);
+  }
+}
+
+const AudioConfig_2_2 HidlToAidlMiddleware_2_2::GetAudioConfig(
+    const SessionType_2_1& session_type) {
+  return to_hidl_audio_config_2_2(BluetoothAudioSessionControl::GetAudioConfig(
+      from_session_type_2_1(session_type)));
+}
+
+bool HidlToAidlMiddleware_2_2::StartStream(
+    const SessionType_2_1& session_type) {
+  return BluetoothAudioSessionControl::StartStream(
+      from_session_type_2_1(session_type));
+}
+
+bool HidlToAidlMiddleware_2_2::SuspendStream(
+    const SessionType_2_1& session_type) {
+  return BluetoothAudioSessionControl::SuspendStream(
+      from_session_type_2_1(session_type));
+}
+
+void HidlToAidlMiddleware_2_2::StopStream(const SessionType_2_1& session_type) {
+  return BluetoothAudioSessionControl::StopStream(
+      from_session_type_2_1(session_type));
+}
+
+void HidlToAidlMiddleware_2_2::UpdateSinkMetadata(
+    const SessionType_2_1& session_type,
+    const struct sink_metadata* sink_metadata) {
+  return BluetoothAudioSessionControl::UpdateSinkMetadata(
+      from_session_type_2_1(session_type), *sink_metadata);
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h
new file mode 100644
index 0000000..d10ee37
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_0.h
@@ -0,0 +1,73 @@
+/*
+ * 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 <android/hardware/bluetooth/audio/2.0/types.h>
+
+#include "../session/BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using SessionType_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::SessionType;
+using PortStatusCallbacks_2_0 =
+    ::android::bluetooth::audio::PortStatusCallbacks;
+using AudioConfig_2_0 =
+    ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+
+class HidlToAidlMiddleware_2_0 {
+ public:
+  static bool IsAidlAvailable();
+
+  static bool IsSessionReady(const SessionType_2_0& session_type);
+
+  static uint16_t RegisterControlResultCback(
+      const SessionType_2_0& session_type,
+      const PortStatusCallbacks_2_0& cbacks);
+
+  static void UnregisterControlResultCback(const SessionType_2_0& session_type,
+                                           uint16_t cookie);
+
+  static const AudioConfig_2_0 GetAudioConfig(
+      const SessionType_2_0& session_type);
+
+  static bool StartStream(const SessionType_2_0& session_type);
+
+  static void StopStream(const SessionType_2_0& session_type);
+
+  static bool SuspendStream(const SessionType_2_0& session_type);
+
+  static bool GetPresentationPosition(const SessionType_2_0& session_type,
+                                      uint64_t* remote_delay_report_ns,
+                                      uint64_t* total_bytes_readed,
+                                      timespec* data_position);
+
+  static void UpdateTracksMetadata(
+      const SessionType_2_0& session_type,
+      const struct source_metadata* source_metadata);
+
+  static size_t OutWritePcmData(const SessionType_2_0& session_type,
+                                const void* buffer, size_t bytes);
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_1.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_1.h
new file mode 100644
index 0000000..82dce96
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_1.h
@@ -0,0 +1,42 @@
+/*
+ * 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 <android/hardware/bluetooth/audio/2.1/types.h>
+
+#include "../session/BluetoothAudioSession.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using SessionType_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::SessionType;
+using AudioConfig_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration;
+
+class HidlToAidlMiddleware_2_1 {
+ public:
+  static const AudioConfig_2_1 GetAudioConfig(
+      const SessionType_2_1& session_type);
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h
new file mode 100644
index 0000000..149e404
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/HidlToAidlMiddleware_2_2.h
@@ -0,0 +1,65 @@
+/*
+ * 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 <android/hardware/bluetooth/audio/2.2/types.h>
+
+#include "../session/BluetoothAudioSession.h"
+#include "../session/BluetoothAudioSession_2_2.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace audio {
+
+using SessionType_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::SessionType;
+using PortStatusCallbacks_2_0 =
+    ::android::bluetooth::audio::PortStatusCallbacks;
+using PortStatusCallbacks_2_2 =
+    ::android::bluetooth::audio::PortStatusCallbacks_2_2;
+using AudioConfig_2_2 =
+    ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration;
+
+class HidlToAidlMiddleware_2_2 {
+ public:
+  static bool IsSessionReady(const SessionType_2_1& session_type);
+
+  static uint16_t RegisterControlResultCback(
+      const SessionType_2_1& session_type,
+      const PortStatusCallbacks_2_2& cbacks);
+
+  static void UnregisterControlResultCback(const SessionType_2_1& session_type,
+                                           uint16_t cookie);
+
+  static const AudioConfig_2_2 GetAudioConfig(
+      const SessionType_2_1& session_type);
+
+  static bool StartStream(const SessionType_2_1& session_type);
+
+  static bool SuspendStream(const SessionType_2_1& session_type);
+
+  static void StopStream(const SessionType_2_1& session_type);
+
+  static void UpdateSinkMetadata(const SessionType_2_1& session_type,
+                                 const struct sink_metadata* sink_metadata);
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+}  // namespace aidl
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession.cpp
index 2f3ddaf..6d5608b 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession.cpp
@@ -21,10 +21,13 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 
+#include "../aidl_session/HidlToAidlMiddleware_2_0.h"
+
 namespace android {
 namespace bluetooth {
 namespace audio {
 
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
 using ::android::hardware::audio::common::V5_0::AudioContentType;
 using ::android::hardware::audio::common::V5_0::AudioUsage;
 using ::android::hardware::audio::common::V5_0::PlaybackTrackMetadata;
@@ -149,6 +152,8 @@
 // The function helps to check if this session is ready or not
 // @return: true if the Bluetooth stack has started the specified session
 bool BluetoothAudioSession::IsSessionReady() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::IsSessionReady(session_type_);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   bool dataMQ_valid =
       (session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH ||
@@ -200,6 +205,9 @@
 // @return: cookie - the assigned number to this bluetooth_audio output
 uint16_t BluetoothAudioSession::RegisterStatusCback(
     const PortStatusCallbacks& cbacks) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::RegisterControlResultCback(session_type_,
+                                                                cbacks);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   uint16_t cookie = ObserversCookieGetInitValue(session_type_);
   uint16_t cookie_upper_bound = ObserversCookieGetUpperBound(session_type_);
@@ -227,6 +235,9 @@
 // PortStatusCallbacks
 // @param: cookie - indicates which bluetooth_audio output is
 void BluetoothAudioSession::UnregisterStatusCback(uint16_t cookie) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::UnregisterControlResultCback(session_type_,
+                                                                  cookie);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (observers_.erase(cookie) != 1) {
     LOG(WARNING) << __func__ << " - SessionType=" << toString(session_type_)
@@ -238,6 +249,9 @@
 // The control function is for the bluetooth_audio module to get the current
 // AudioConfiguration
 const AudioConfiguration& BluetoothAudioSession::GetAudioConfig() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return (audio_config_ =
+                HidlToAidlMiddleware_2_0::GetAudioConfig(session_type_));
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (IsSessionReady()) {
     return audio_config_;
@@ -251,6 +265,8 @@
 // Those control functions are for the bluetooth_audio module to start, suspend,
 // stop stream, to check position, and to update metadata.
 bool BluetoothAudioSession::StartStream() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::StartStream(session_type_);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
@@ -267,6 +283,8 @@
 }
 
 bool BluetoothAudioSession::SuspendStream() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::SuspendStream(session_type_);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
@@ -283,6 +301,8 @@
 }
 
 void BluetoothAudioSession::StopStream() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::StopStream(session_type_);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
     return;
@@ -297,6 +317,10 @@
 bool BluetoothAudioSession::GetPresentationPosition(
     uint64_t* remote_delay_report_ns, uint64_t* total_bytes_readed,
     timespec* data_position) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::GetPresentationPosition(
+        session_type_, remote_delay_report_ns, total_bytes_readed,
+        data_position);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
@@ -330,6 +354,9 @@
 
 void BluetoothAudioSession::UpdateTracksMetadata(
     const struct source_metadata* source_metadata) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::UpdateTracksMetadata(session_type_,
+                                                          source_metadata);
   std::lock_guard<std::recursive_mutex> guard(mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_)
@@ -374,6 +401,9 @@
 // The control function writes stream to FMQ
 size_t BluetoothAudioSession::OutWritePcmData(const void* buffer,
                                               size_t bytes) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_0::OutWritePcmData(session_type_, buffer,
+                                                     bytes);
   if (buffer == nullptr || !bytes) return 0;
   size_t totalWritten = 0;
   int ms_timeout = kFmqSendTimeoutMs;
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
index bf1f9b5..276a291 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.cpp
@@ -21,9 +21,14 @@
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
 
+#include "../aidl_session/HidlToAidlMiddleware_2_0.h"
+#include "../aidl_session/HidlToAidlMiddleware_2_1.h"
+
 namespace android {
 namespace bluetooth {
 namespace audio {
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_1;
 using SessionType_2_1 =
     ::android::hardware::bluetooth::audio::V2_1::SessionType;
 using SessionType_2_0 =
@@ -72,6 +77,7 @@
   } else {
     session_type_2_1_ = (session_type);
   }
+  raw_session_type_ = session_type;
 }
 
 std::shared_ptr<BluetoothAudioSession>
@@ -83,6 +89,8 @@
 // AudioConfiguration
 const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration
 BluetoothAudioSession_2_1::GetAudioConfig() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_1::GetAudioConfig(raw_session_type_);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (audio_session->IsSessionReady()) {
     // If session is unknown it means it should be 2.0 type
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
index 5a35153..e634064 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_1.h
@@ -31,6 +31,7 @@
   std::shared_ptr<BluetoothAudioSession> audio_session;
 
   ::android::hardware::bluetooth::audio::V2_1::SessionType session_type_2_1_;
+  ::android::hardware::bluetooth::audio::V2_1::SessionType raw_session_type_;
 
   // audio data configuration for both software and offloading
   ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
index 60ac4ec..4613ddc 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.cpp
@@ -22,10 +22,15 @@
 #include <android-base/stringprintf.h>
 #include <android/hardware/bluetooth/audio/2.2/IBluetoothAudioPort.h>
 
+#include "../aidl_session/HidlToAidlMiddleware_2_0.h"
+#include "../aidl_session/HidlToAidlMiddleware_2_2.h"
+
 namespace android {
 namespace bluetooth {
 namespace audio {
 
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_0;
+using ::aidl::android::hardware::bluetooth::audio::HidlToAidlMiddleware_2_2;
 using ::android::hardware::audio::common::V5_0::AudioSource;
 using ::android::hardware::audio::common::V5_0::RecordTrackMetadata;
 using ::android::hardware::audio::common::V5_0::SinkMetadata;
@@ -93,6 +98,7 @@
   } else {
     session_type_2_1_ = (session_type);
   }
+  raw_session_type_ = session_type;
   invalidSoftwareAudioConfiguration.pcmConfig(kInvalidPcmParameters);
   invalidOffloadAudioConfiguration.codecConfig(
       audio_session->kInvalidCodecConfiguration);
@@ -100,6 +106,8 @@
 }
 
 bool BluetoothAudioSession_2_2::IsSessionReady() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::IsSessionReady(raw_session_type_);
   if (session_type_2_1_ !=
           SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
       session_type_2_1_ !=
@@ -122,6 +130,9 @@
 
 void BluetoothAudioSession_2_2::UpdateSinkMetadata(
     const struct sink_metadata* sink_metadata) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::UpdateSinkMetadata(raw_session_type_,
+                                                        sink_metadata);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
@@ -172,6 +183,8 @@
 // AudioConfiguration
 const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
 BluetoothAudioSession_2_2::GetAudioConfig() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::GetAudioConfig(raw_session_type_);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (IsSessionReady()) {
     auto audio_config_discriminator = audio_config_2_2_.getDiscriminator();
@@ -226,6 +239,8 @@
 // Those control functions are for the bluetooth_audio module to start, suspend,
 // stop stream, to check position, and to update metadata.
 bool BluetoothAudioSession_2_2::StartStream() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::StartStream(raw_session_type_);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
@@ -242,6 +257,8 @@
 }
 
 bool BluetoothAudioSession_2_2::SuspendStream() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::SuspendStream(raw_session_type_);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (!IsSessionReady()) {
     LOG(DEBUG) << __func__ << " - SessionType=" << toString(session_type_2_1_)
@@ -258,6 +275,8 @@
 }
 
 void BluetoothAudioSession_2_2::StopStream() {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::StopStream(raw_session_type_);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (!IsSessionReady()) {
     return;
@@ -395,6 +414,9 @@
 // @return: cookie - the assigned number to this bluetooth_audio output
 uint16_t BluetoothAudioSession_2_2::RegisterStatusCback(
     const PortStatusCallbacks_2_2& cbacks) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::RegisterControlResultCback(
+        raw_session_type_, cbacks);
   if (session_type_2_1_ !=
           SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
       session_type_2_1_ !=
@@ -432,6 +454,9 @@
 // PortStatusCallbacks_2_2
 // @param: cookie - indicates which bluetooth_audio output is
 void BluetoothAudioSession_2_2::UnregisterStatusCback(uint16_t cookie) {
+  if (HidlToAidlMiddleware_2_0::IsAidlAvailable())
+    return HidlToAidlMiddleware_2_2::UnregisterControlResultCback(
+        raw_session_type_, cookie);
   std::lock_guard<std::recursive_mutex> guard(audio_session->mutex_);
   if (session_type_2_1_ !=
           SessionType_2_1::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
diff --git a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
index 3673fd8..b6f96ab 100644
--- a/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
+++ b/bluetooth/audio/utils/session/BluetoothAudioSession_2_2.h
@@ -68,6 +68,7 @@
   std::shared_ptr<BluetoothAudioSession_2_1> audio_session_2_1;
 
   ::android::hardware::bluetooth::audio::V2_1::SessionType session_type_2_1_;
+  ::android::hardware::bluetooth::audio::V2_1::SessionType raw_session_type_;
 
   // audio data configuration for both software and offloading
   ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index ad4f599..a52fde4 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -77,14 +77,6 @@
             <instance>default</instance>
         </interface>
     </hal>
-    <hal format="hidl" optional="true">
-        <name>android.hardware.automotive.sv</name>
-        <version>1.0</version>
-        <interface>
-            <name>ISurroundViewService</name>
-            <instance>default</instance>
-        </interface>
-    </hal>
     <hal format="aidl" optional="true">
         <name>android.hardware.automotive.vehicle</name>
         <interface>
diff --git a/gnss/aidl/Android.bp b/gnss/aidl/Android.bp
index 12dd0ac..d90cf0b 100644
--- a/gnss/aidl/Android.bp
+++ b/gnss/aidl/Android.bp
@@ -24,27 +24,12 @@
 }
 
 aidl_interface {
-    name: "android.hardware.gnss.visibility_control",
-    vendor_available: true,
-    srcs: ["android/hardware/gnss/visibility_control/*.aidl"],
-    stability: "vintf",
-    backend: {
-        java: {
-            platform_apis: true,
-        },
-        ndk: {
-            vndk: {
-                enabled: true,
-            },
-        },
-    },
-}
-
-aidl_interface {
     name: "android.hardware.gnss",
     vendor_available: true,
-    srcs: ["android/hardware/gnss/*.aidl"],
-    imports: ["android.hardware.gnss.visibility_control"],
+    srcs: [
+        "android/hardware/gnss/*.aidl",
+        "android/hardware/gnss/visibility_control/*.aidl",
+    ],
     stability: "vintf",
     backend: {
         java: {
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
index 1b4c581..281c531 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnss.aidl
@@ -53,6 +53,7 @@
   void injectBestLocation(in android.hardware.gnss.GnssLocation location);
   void deleteAidingData(in android.hardware.gnss.IGnss.GnssAidingData aidingDataFlags);
   void setPositionMode(in android.hardware.gnss.IGnss.GnssPositionMode mode, in android.hardware.gnss.IGnss.GnssPositionRecurrence recurrence, in int minIntervalMs, in int preferredAccuracyMeters, in int preferredTimeMs, in boolean lowPowerMode);
+  android.hardware.gnss.IGnssAntennaInfo getExtensionGnssAntennaInfo();
   const int ERROR_INVALID_ARGUMENT = 1;
   const int ERROR_ALREADY_INIT = 2;
   const int ERROR_GENERIC = 3;
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssAntennaInfo.aidl
similarity index 86%
copy from gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssAntennaInfo.aidl
index 7ef08d2..2734ac1 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssAntennaInfo.aidl
@@ -31,9 +31,9 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.gnss.visibility_control;
+package android.hardware.gnss;
 @VintfStability
-interface IGnssVisibilityControl {
-  void enableNfwLocationAccess(in String[] proxyApps);
-  void setCallback(in android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback callback);
+interface IGnssAntennaInfo {
+  void setCallback(in android.hardware.gnss.IGnssAntennaInfoCallback callback);
+  void close();
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssAntennaInfoCallback.aidl
similarity index 63%
copy from gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
copy to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssAntennaInfoCallback.aidl
index 7ef08d2..ada9707 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssAntennaInfoCallback.aidl
@@ -31,9 +31,30 @@
 // with such a backward incompatible change, it has a high risk of breaking
 // later when a module using the interface is updated, e.g., Mainline modules.
 
-package android.hardware.gnss.visibility_control;
+package android.hardware.gnss;
 @VintfStability
-interface IGnssVisibilityControl {
-  void enableNfwLocationAccess(in String[] proxyApps);
-  void setCallback(in android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback callback);
+interface IGnssAntennaInfoCallback {
+  void gnssAntennaInfoCb(in android.hardware.gnss.IGnssAntennaInfoCallback.GnssAntennaInfo[] gnssAntennaInfos);
+  @VintfStability
+  parcelable Row {
+    double[] row;
+  }
+  @VintfStability
+  parcelable Coord {
+    double x;
+    double xUncertainty;
+    double y;
+    double yUncertainty;
+    double z;
+    double zUncertainty;
+  }
+  @VintfStability
+  parcelable GnssAntennaInfo {
+    long carrierFrequencyHz;
+    android.hardware.gnss.IGnssAntennaInfoCallback.Coord phaseCenterOffsetCoordinateMillimeters;
+    android.hardware.gnss.IGnssAntennaInfoCallback.Row[] phaseCenterVariationCorrectionMillimeters;
+    android.hardware.gnss.IGnssAntennaInfoCallback.Row[] phaseCenterVariationCorrectionUncertaintyMillimeters;
+    android.hardware.gnss.IGnssAntennaInfoCallback.Row[] signalGainCorrectionDbi;
+    android.hardware.gnss.IGnssAntennaInfoCallback.Row[] signalGainCorrectionUncertaintyDbi;
+  }
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
similarity index 96%
rename from gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
rename to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
index 7ef08d2..f674099 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
@@ -34,6 +34,6 @@
 package android.hardware.gnss.visibility_control;
 @VintfStability
 interface IGnssVisibilityControl {
-  void enableNfwLocationAccess(in String[] proxyApps);
+  void enableNfwLocationAccess(in @utf8InCpp String[] proxyApps);
   void setCallback(in android.hardware.gnss.visibility_control.IGnssVisibilityControlCallback callback);
 }
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
similarity index 100%
rename from gnss/aidl/aidl_api/android.hardware.gnss.visibility_control/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
rename to gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/visibility_control/IGnssVisibilityControlCallback.aidl
diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl
index 4ddc6a6..e1d4670 100644
--- a/gnss/aidl/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl
@@ -18,6 +18,7 @@
 
 import android.hardware.gnss.GnssLocation;
 import android.hardware.gnss.IAGnss;
+import android.hardware.gnss.IGnssAntennaInfo;
 import android.hardware.gnss.IGnssBatching;
 import android.hardware.gnss.IGnssCallback;
 import android.hardware.gnss.IGnssConfiguration;
@@ -277,4 +278,11 @@
     void setPositionMode(in GnssPositionMode mode, in GnssPositionRecurrence recurrence,
             in int minIntervalMs, in int preferredAccuracyMeters, in int preferredTimeMs,
             in boolean lowPowerMode);
+
+    /*
+     * This method returns the IGnssAntennaInfo.
+     *
+     * @return Handle to the IGnssAntennaInfo.
+     */
+    IGnssAntennaInfo getExtensionGnssAntennaInfo();
 }
diff --git a/gnss/aidl/android/hardware/gnss/IGnssAntennaInfo.aidl b/gnss/aidl/android/hardware/gnss/IGnssAntennaInfo.aidl
new file mode 100644
index 0000000..de83b67
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssAntennaInfo.aidl
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package android.hardware.gnss;
+
+import android.hardware.gnss.IGnssAntennaInfoCallback;
+
+/**
+ * Extended interface for GNSS antenna information support.
+ */
+@VintfStability
+interface IGnssAntennaInfo {
+    /**
+     * Registers the callback routines with the HAL.
+     *
+     * @param callback Handle to the GnssAntennaInfo callback interface.
+     */
+    void setCallback(in IGnssAntennaInfoCallback callback);
+
+    /**
+     * Stops updates from the HAL, and unregisters the callback routines.
+     * After a call to close(), the previously registered callbacks must be
+     * considered invalid by the HAL.
+     * If close() is invoked without a previous setCallback, this function must perform
+     * no work.
+     */
+    void close();
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssAntennaInfoCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssAntennaInfoCallback.aidl
new file mode 100644
index 0000000..ef0a7fc
--- /dev/null
+++ b/gnss/aidl/android/hardware/gnss/IGnssAntennaInfoCallback.aidl
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+package android.hardware.gnss;
+
+/**
+ * The callback interface to report GNSS antenna information from the HAL.
+ */
+@VintfStability
+interface IGnssAntennaInfoCallback {
+    /**
+     * A row of doubles. This is used to represent a row in a 2D array, which are used to
+     * characterize the phase center variation corrections and signal gain corrections.
+     */
+    @VintfStability
+    parcelable Row {
+        double[] row;
+    }
+
+    /**
+     * A point in 3D space, with associated uncertainty.
+     */
+    @VintfStability
+    parcelable Coord {
+        double x;
+
+        double xUncertainty;
+
+        double y;
+
+        double yUncertainty;
+
+        double z;
+
+        double zUncertainty;
+    }
+
+    @VintfStability
+    parcelable GnssAntennaInfo {
+        /**
+         * The carrier frequency in Hz.
+         */
+        long carrierFrequencyHz;
+
+        /**
+         * Phase center offset (PCO) with associated 1-sigma uncertainty. PCO is defined with
+         * respect to the origin of the Android sensor coordinate system, e.g., center of primary
+         * screen for mobiles - see sensor or form factor documents for details.
+         */
+        Coord phaseCenterOffsetCoordinateMillimeters;
+
+        /**
+         * 2D vectors representing the phase center variation (PCV) corrections, in
+         * millimeters, at regularly spaced azimuthal angle (theta) and zenith angle
+         * (phi). The PCV correction is added to the phase measurement to obtain the
+         * corrected value.
+         *
+         * The azimuthal angle, theta, is defined with respect to the X axis of the
+         * Android sensor coordinate system, increasing toward the Y axis. The zenith
+         * angle, phi, is defined with respect to the Z axis of the Android Sensor
+         * coordinate system, increasing toward the X-Y plane.
+         *
+         * Each row vector (outer vectors) represents a fixed theta. The first row
+         * corresponds to a theta angle of 0 degrees. The last row corresponds to a
+         * theta angle of (360 - deltaTheta) degrees, where deltaTheta is the regular
+         * spacing between azimuthal angles, i.e., deltaTheta = 360 / (number of rows).
+         *
+         * The columns (inner vectors) represent fixed zenith angles, beginning at 0
+         * degrees and ending at 180 degrees. They are separated by deltaPhi, the regular
+         * spacing between zenith angles, i.e., deltaPhi = 180 / (number of columns - 1).
+         *
+         * This field is optional, i.e., an empty vector.
+         */
+        Row[] phaseCenterVariationCorrectionMillimeters;
+
+        /**
+         * 2D vectors of 1-sigma uncertainty in millimeters associated with the PCV
+         * correction values.
+         *
+         * This field is optional, i.e., an empty vector.
+         */
+        Row[] phaseCenterVariationCorrectionUncertaintyMillimeters;
+
+        /**
+         * 2D vectors representing the signal gain corrections at regularly spaced
+         * azimuthal angle (theta) and zenith angle (phi). The values are calculated or
+         * measured at the antenna feed point without considering the radio and receiver
+         * noise figure and path loss contribution, in dBi, i.e., decibel over isotropic
+         * antenna with the same total power. The signal gain correction is added the
+         * signal gain measurement to obtain the corrected value.
+         *
+         * The azimuthal angle, theta, is defined with respect to the X axis of the
+         * Android sensor coordinate system, increasing toward the Y axis. The zenith
+         * angle, phi, is defined with respect to the Z axis of the Android Sensor
+         * coordinate system, increasing toward the X-Y plane.
+         *
+         * Each row vector (outer vectors) represents a fixed theta. The first row
+         * corresponds to a theta angle of 0 degrees. The last row corresponds to a
+         * theta angle of (360 - deltaTheta) degrees, where deltaTheta is the regular
+         * spacing between azimuthal angles, i.e., deltaTheta = 360 / (number of rows).
+         *
+         * The columns (inner vectors) represent fixed zenith angles, beginning at 0
+         * degrees and ending at 180 degrees. They are separated by deltaPhi, the regular
+         * spacing between zenith angles, i.e., deltaPhi = 180 / (number of columns - 1).
+         *
+         * This field is optional, i.e., an empty vector.
+         */
+        Row[] signalGainCorrectionDbi;
+
+        /**
+         * 2D vectors of 1-sigma uncertainty in dBi associated with the signal
+         * gain correction values.
+         *
+         * This field is optional, i.e., an empty vector.
+         */
+        Row[] signalGainCorrectionUncertaintyDbi;
+    }
+
+    /**
+     * Called when on connection, and on known-change to these values, such as upon a known
+     * GNSS RF antenna tuning change, or a foldable device state change.
+     *
+     * This is optional. It can never be called if the GNSS antenna information is not
+     * available.
+     */
+    void gnssAntennaInfoCb(in GnssAntennaInfo[] gnssAntennaInfos);
+}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
index 157c912..a74d097 100644
--- a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
@@ -67,7 +67,7 @@
     /** Capability bit mask indicating that GNSS supports measurement corrections */
     const int CAPABILITY_MEASUREMENT_CORRECTIONS = 1 << 10;
 
-    /** Capability bit mask indicating that GNSS supports measurement corrections */
+    /** Capability bit mask indicating that GNSS supports antenna info */
     const int CAPABILITY_ANTENNA_INFO = 1 << 11;
 
     /** Capability bit mask indicating that GNSS supports correlation vector */
diff --git a/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl b/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
index 93c3f2c..c9c1549 100644
--- a/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
+++ b/gnss/aidl/android/hardware/gnss/visibility_control/IGnssVisibilityControl.aidl
@@ -71,7 +71,7 @@
      * The package name of the proxy Android application follows the standard Java language
      * package naming format. For example, com.example.myapp.
      */
-    void enableNfwLocationAccess(in String[] proxyApps);
+    void enableNfwLocationAccess(in @utf8InCpp String[] proxyApps);
 
     /**
      * Registers the callback for HAL implementation to use.
diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp
index 29c26d1..0031dcf 100644
--- a/gnss/aidl/default/Android.bp
+++ b/gnss/aidl/default/Android.bp
@@ -52,12 +52,12 @@
         "android.hardware.gnss.measurement_corrections@1.1",
         "android.hardware.gnss.measurement_corrections@1.0",
         "android.hardware.gnss.visibility_control@1.0",
-        "android.hardware.gnss.visibility_control-V1-ndk",
         "android.hardware.gnss-V2-ndk",
     ],
     srcs: [
         "AGnss.cpp",
         "Gnss.cpp",
+        "GnssAntennaInfo.cpp",
         "GnssBatching.cpp",
         "GnssDebug.cpp",
         "GnssGeofence.cpp",
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index 6578778..2c6df99 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -21,6 +21,7 @@
 #include <log/log.h>
 #include "AGnss.h"
 #include "DeviceFileReader.h"
+#include "GnssAntennaInfo.h"
 #include "GnssBatching.h"
 #include "GnssConfiguration.h"
 #include "GnssDebug.h"
@@ -56,7 +57,8 @@
 
     int capabilities = (int)(IGnssCallback::CAPABILITY_SATELLITE_BLOCKLIST |
                              IGnssCallback::CAPABILITY_SATELLITE_PVT |
-                             IGnssCallback::CAPABILITY_CORRELATION_VECTOR);
+                             IGnssCallback::CAPABILITY_CORRELATION_VECTOR |
+                             IGnssCallback::CAPABILITY_ANTENNA_INFO);
 
     auto status = sGnssCallback->gnssSetCapabilitiesCb(capabilities);
     if (!status.isOk()) {
@@ -279,4 +281,12 @@
     return ndk::ScopedAStatus::ok();
 }
 
+ndk::ScopedAStatus Gnss::getExtensionGnssAntennaInfo(
+        std::shared_ptr<IGnssAntennaInfo>* iGnssAntennaInfo) {
+    ALOGD("Gnss::getExtensionGnssAntennaInfo");
+
+    *iGnssAntennaInfo = SharedRefBase::make<GnssAntennaInfo>();
+    return ndk::ScopedAStatus::ok();
+}
+
 }  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/Gnss.h b/gnss/aidl/default/Gnss.h
index f21d756..b92f4fb 100644
--- a/gnss/aidl/default/Gnss.h
+++ b/gnss/aidl/default/Gnss.h
@@ -18,6 +18,7 @@
 
 #include <aidl/android/hardware/gnss/BnAGnss.h>
 #include <aidl/android/hardware/gnss/BnGnss.h>
+#include <aidl/android/hardware/gnss/BnGnssAntennaInfo.h>
 #include <aidl/android/hardware/gnss/BnGnssBatching.h>
 #include <aidl/android/hardware/gnss/BnGnssConfiguration.h>
 #include <aidl/android/hardware/gnss/BnGnssDebug.h>
@@ -69,6 +70,8 @@
     ndk::ScopedAStatus getExtensionGnssVisibilityControl(
             std::shared_ptr<android::hardware::gnss::visibility_control::IGnssVisibilityControl>*
                     iGnssVisibilityControl) override;
+    ndk::ScopedAStatus getExtensionGnssAntennaInfo(
+            std::shared_ptr<IGnssAntennaInfo>* iGnssAntennaInfo) override;
 
     std::shared_ptr<GnssConfiguration> mGnssConfiguration;
     std::shared_ptr<GnssPowerIndication> mGnssPowerIndication;
diff --git a/gnss/aidl/default/GnssAntennaInfo.cpp b/gnss/aidl/default/GnssAntennaInfo.cpp
new file mode 100644
index 0000000..72def71
--- /dev/null
+++ b/gnss/aidl/default/GnssAntennaInfo.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2021 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 "GnssAntennaInfoAidl"
+
+#include "GnssAntennaInfo.h"
+#include <aidl/android/hardware/gnss/BnGnss.h>
+#include <log/log.h>
+#include "Utils.h"
+
+namespace aidl::android::hardware::gnss {
+
+using namespace ::android::hardware::gnss;
+using Row = IGnssAntennaInfoCallback::Row;
+using Coord = IGnssAntennaInfoCallback::Coord;
+
+std::shared_ptr<IGnssAntennaInfoCallback> GnssAntennaInfo::sCallback = nullptr;
+
+GnssAntennaInfo::GnssAntennaInfo() : mMinIntervalMs(1000) {}
+
+GnssAntennaInfo::~GnssAntennaInfo() {
+    stop();
+}
+
+// Methods from ::android::hardware::gnss::V2_1::IGnssAntennaInfo follow.
+ndk::ScopedAStatus GnssAntennaInfo::setCallback(
+        const std::shared_ptr<IGnssAntennaInfoCallback>& callback) {
+    ALOGD("setCallback");
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = callback;
+
+    if (mIsActive) {
+        ALOGW("GnssAntennaInfo callback already set. Resetting the callback...");
+        stop();
+    }
+    start();
+
+    return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus GnssAntennaInfo::close() {
+    ALOGD("close");
+    stop();
+    std::unique_lock<std::mutex> lock(mMutex);
+    sCallback = nullptr;
+    return ndk::ScopedAStatus::ok();
+}
+
+void GnssAntennaInfo::start() {
+    ALOGD("start");
+    mIsActive = true;
+    mThread = std::thread([this]() {
+        while (mIsActive == true) {
+            if (sCallback != nullptr) {
+                IGnssAntennaInfoCallback::GnssAntennaInfo mockAntennaInfo_1 = {
+                        .carrierFrequencyHz = 1575420000,
+                        .phaseCenterOffsetCoordinateMillimeters = Coord{.x = 1,
+                                                                        .xUncertainty = 0.1,
+                                                                        .y = 2,
+                                                                        .yUncertainty = 0.1,
+                                                                        .z = 3,
+                                                                        .zUncertainty = 0.1},
+                        .phaseCenterVariationCorrectionMillimeters =
+                                {
+                                        Row{std::vector<double>{1, -1, 5, -2, 3, -1}},
+                                        Row{std::vector<double>{-2, 3, 2, 0, 1, 2}},
+                                        Row{std::vector<double>{1, 3, 2, -1, -3, 5}},
+                                },
+                        .phaseCenterVariationCorrectionUncertaintyMillimeters =
+                                {
+                                        Row{std::vector<double>{0.1, 0.2, 0.4, 0.1, 0.2, 0.3}},
+                                        Row{std::vector<double>{0.3, 0.2, 0.3, 0.6, 0.1, 0.1}},
+                                        Row{std::vector<double>{0.1, 0.1, 0.4, 0.2, 0.5, 0.3}},
+                                },
+                        .signalGainCorrectionDbi =
+                                {
+                                        Row{std::vector<double>{2, -3, 1, -3, 0, -4}},
+                                        Row{std::vector<double>{1, 0, -4, 1, 3, -2}},
+                                        Row{std::vector<double>{3, -2, 0, -2, 3, 0}},
+                                },
+                        .signalGainCorrectionUncertaintyDbi =
+                                {
+                                        Row{std::vector<double>{0.3, 0.1, 0.2, 0.6, 0.1, 0.3}},
+                                        Row{std::vector<double>{0.1, 0.1, 0.5, 0.2, 0.3, 0.1}},
+                                        Row{std::vector<double>{0.2, 0.4, 0.2, 0.1, 0.1, 0.2}},
+                                },
+                };
+
+                IGnssAntennaInfoCallback::GnssAntennaInfo mockAntennaInfo_2 = {
+                        .carrierFrequencyHz = 1176450000,
+                        .phaseCenterOffsetCoordinateMillimeters = Coord{.x = 5,
+                                                                        .xUncertainty = 0.1,
+                                                                        .y = 6,
+                                                                        .yUncertainty = 0.1,
+                                                                        .z = 7,
+                                                                        .zUncertainty = 0.1},
+                };
+
+                std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo> mockAntennaInfos = {
+                        mockAntennaInfo_1,
+                        mockAntennaInfo_2,
+                };
+                this->reportAntennaInfo(mockAntennaInfos);
+            }
+
+            /** For mock implementation this is good. On real device, we should only report
+                antennaInfo at start and when there is a configuration change. **/
+            std::this_thread::sleep_for(std::chrono::milliseconds(mMinIntervalMs));
+        }
+    });
+}
+
+void GnssAntennaInfo::stop() {
+    ALOGD("stop");
+    mIsActive = false;
+    if (mThread.joinable()) {
+        mThread.join();
+    }
+}
+
+void GnssAntennaInfo::reportAntennaInfo(
+        const std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo>& antennaInfo) const {
+    std::unique_lock<std::mutex> lock(mMutex);
+
+    if (sCallback == nullptr) {
+        ALOGE("%s: No non-null callback", __func__);
+        return;
+    }
+
+    auto ret = sCallback->gnssAntennaInfoCb(antennaInfo);
+    if (!ret.isOk()) {
+        ALOGE("%s: Unable to invoke callback", __func__);
+    }
+}
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/GnssAntennaInfo.h b/gnss/aidl/default/GnssAntennaInfo.h
new file mode 100644
index 0000000..2cf7b13
--- /dev/null
+++ b/gnss/aidl/default/GnssAntennaInfo.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/gnss/BnGnssAntennaInfo.h>
+#include <atomic>
+#include <mutex>
+#include <thread>
+
+namespace aidl::android::hardware::gnss {
+
+struct GnssAntennaInfo : public BnGnssAntennaInfo {
+  public:
+    GnssAntennaInfo();
+    ~GnssAntennaInfo();
+    ndk::ScopedAStatus setCallback(
+            const std::shared_ptr<IGnssAntennaInfoCallback>& callback) override;
+    ndk::ScopedAStatus close() override;
+
+  private:
+    void start();
+    void stop();
+    void reportAntennaInfo(
+            const std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo>& antennaInfo) const;
+
+    // Guarded by mMutex
+    static std::shared_ptr<IGnssAntennaInfoCallback> sCallback;
+
+    std::atomic<bool> mIsActive;
+    std::atomic<long> mMinIntervalMs;
+    std::thread mThread;
+
+    // Synchronization lock for sCallback
+    mutable std::mutex mMutex;
+};
+
+}  // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp
index d532fad..b23a646 100644
--- a/gnss/aidl/vts/Android.bp
+++ b/gnss/aidl/vts/Android.bp
@@ -31,6 +31,7 @@
         "gnss_hal_test.cpp",
         "gnss_hal_test_cases.cpp",
         "AGnssCallbackAidl.cpp",
+        "GnssAntennaInfoCallbackAidl.cpp",
         "GnssBatchingCallback.cpp",
         "GnssCallbackAidl.cpp",
         "GnssGeofenceCallback.cpp",
@@ -50,7 +51,6 @@
     static_libs: [
         "android.hardware.gnss-V2-cpp",
         "android.hardware.gnss@common-vts-lib",
-        "android.hardware.gnss.visibility_control-V1-cpp",
     ],
     test_suites: [
         "general-tests",
diff --git a/gnss/aidl/vts/GnssAntennaInfoCallbackAidl.cpp b/gnss/aidl/vts/GnssAntennaInfoCallbackAidl.cpp
new file mode 100644
index 0000000..11001cd
--- /dev/null
+++ b/gnss/aidl/vts/GnssAntennaInfoCallbackAidl.cpp
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2021 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 "GnssAntennaInfoCallbackAidl.h"
+#include <inttypes.h>
+#include <log/log.h>
+
+android::binder::Status GnssAntennaInfoCallbackAidl::gnssAntennaInfoCb(
+        const std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos) {
+    ALOGD("GnssAntennaInfo received. Size = %d", (int)gnssAntennaInfos.size());
+    antenna_info_cbq_.store(gnssAntennaInfos);
+    return android::binder::Status::ok();
+}
diff --git a/gnss/aidl/vts/GnssAntennaInfoCallbackAidl.h b/gnss/aidl/vts/GnssAntennaInfoCallbackAidl.h
new file mode 100644
index 0000000..77e1057
--- /dev/null
+++ b/gnss/aidl/vts/GnssAntennaInfoCallbackAidl.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#pragma once
+
+#include <android/hardware/gnss/BnGnssAntennaInfoCallback.h>
+#include <vector>
+#include "GnssCallbackEventQueue.h"
+
+/** Implementation for IGnssAntennaInfoCallback. */
+class GnssAntennaInfoCallbackAidl : public android::hardware::gnss::BnGnssAntennaInfoCallback {
+  public:
+    GnssAntennaInfoCallbackAidl() : antenna_info_cbq_("info"){};
+    ~GnssAntennaInfoCallbackAidl(){};
+
+    android::binder::Status gnssAntennaInfoCb(
+            const std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos)
+            override;
+
+    android::hardware::gnss::common::GnssCallbackEventQueue<
+            std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo>>
+            antenna_info_cbq_;
+};
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index eec50b0..f5f0aa4 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -18,6 +18,7 @@
 
 #include <android/hardware/gnss/IAGnss.h>
 #include <android/hardware/gnss/IGnss.h>
+#include <android/hardware/gnss/IGnssAntennaInfo.h>
 #include <android/hardware/gnss/IGnssBatching.h>
 #include <android/hardware/gnss/IGnssDebug.h>
 #include <android/hardware/gnss/IGnssMeasurementCallback.h>
@@ -27,6 +28,7 @@
 #include <android/hardware/gnss/visibility_control/IGnssVisibilityControl.h>
 #include <cutils/properties.h>
 #include "AGnssCallbackAidl.h"
+#include "GnssAntennaInfoCallbackAidl.h"
 #include "GnssBatchingCallback.h"
 #include "GnssGeofenceCallback.h"
 #include "GnssMeasurementCallbackAidl.h"
@@ -44,6 +46,8 @@
 using android::hardware::gnss::GnssPowerStats;
 using android::hardware::gnss::IAGnss;
 using android::hardware::gnss::IGnss;
+using android::hardware::gnss::IGnssAntennaInfo;
+using android::hardware::gnss::IGnssAntennaInfoCallback;
 using android::hardware::gnss::IGnssBatching;
 using android::hardware::gnss::IGnssBatchingCallback;
 using android::hardware::gnss::IGnssCallback;
@@ -923,7 +927,8 @@
     status = iGnssVisibilityControl->setCallback(gnssVisibilityControlCallback);
     ASSERT_TRUE(status.isOk());
 
-    std::vector<String16> proxyApps{String16("com.example.ims"), String16("com.example.mdt")};
+    std::vector<std::string> proxyApps{std::string("com.example.ims"),
+                                       std::string("com.example.mdt")};
     status = iGnssVisibilityControl->enableNfwLocationAccess(proxyApps);
     ASSERT_TRUE(status.isOk());
 }
@@ -1009,3 +1014,84 @@
     status = iGnssMeasurement->close();
     ASSERT_TRUE(status.isOk());
 }
+
+/*
+ * TestGnssAntennaInfo:
+ * Sets a GnssAntennaInfoCallback, waits for report, and verifies
+ * 1. phaseCenterOffsetCoordinateMillimeters is valid
+ * 2. phaseCenterOffsetCoordinateUncertaintyMillimeters is valid.
+ * PhaseCenterVariationCorrections and SignalGainCorrections are optional.
+ */
+TEST_P(GnssHalTest, TestGnssAntennaInfo) {
+    const int kAntennaInfoTimeoutSeconds = 2;
+
+    if (aidl_gnss_hal_->getInterfaceVersion() == 1) {
+        return;
+    }
+
+    sp<IGnssAntennaInfo> iGnssAntennaInfo;
+    auto status = aidl_gnss_hal_->getExtensionGnssAntennaInfo(&iGnssAntennaInfo);
+    ASSERT_TRUE(status.isOk());
+
+    if (!(aidl_gnss_cb_->last_capabilities_ & (int)GnssCallbackAidl::CAPABILITY_ANTENNA_INFO) ||
+        iGnssAntennaInfo == nullptr) {
+        ALOGD("GnssAntennaInfo AIDL is not supported.");
+        return;
+    }
+
+    auto callback = sp<GnssAntennaInfoCallbackAidl>::make();
+    status = iGnssAntennaInfo->setCallback(callback);
+    ASSERT_TRUE(status.isOk());
+
+    std::vector<IGnssAntennaInfoCallback::GnssAntennaInfo> antennaInfos;
+    ASSERT_TRUE(callback->antenna_info_cbq_.retrieve(antennaInfos, kAntennaInfoTimeoutSeconds));
+    EXPECT_EQ(callback->antenna_info_cbq_.calledCount(), 1);
+    ASSERT_TRUE(antennaInfos.size() > 0);
+
+    for (auto antennaInfo : antennaInfos) {
+        // Remaining fields are optional
+        if (!antennaInfo.phaseCenterVariationCorrectionMillimeters.empty()) {
+            int numRows = antennaInfo.phaseCenterVariationCorrectionMillimeters.size();
+            int numColumns = antennaInfo.phaseCenterVariationCorrectionMillimeters[0].row.size();
+            // Must have at least 1 row and 2 columns
+            ASSERT_TRUE(numRows >= 1 && numColumns >= 2);
+
+            // Corrections and uncertainties must have same dimensions
+            ASSERT_TRUE(antennaInfo.phaseCenterVariationCorrectionMillimeters.size() ==
+                        antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters.size());
+            ASSERT_TRUE(
+                    antennaInfo.phaseCenterVariationCorrectionMillimeters[0].row.size() ==
+                    antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters[0].row.size());
+
+            // Must be rectangular
+            for (auto row : antennaInfo.phaseCenterVariationCorrectionMillimeters) {
+                ASSERT_TRUE(row.row.size() == numColumns);
+            }
+            for (auto row : antennaInfo.phaseCenterVariationCorrectionUncertaintyMillimeters) {
+                ASSERT_TRUE(row.row.size() == numColumns);
+            }
+        }
+        if (!antennaInfo.signalGainCorrectionDbi.empty()) {
+            int numRows = antennaInfo.signalGainCorrectionDbi.size();
+            int numColumns = antennaInfo.signalGainCorrectionUncertaintyDbi[0].row.size();
+            // Must have at least 1 row and 2 columns
+            ASSERT_TRUE(numRows >= 1 && numColumns >= 2);
+
+            // Corrections and uncertainties must have same dimensions
+            ASSERT_TRUE(antennaInfo.signalGainCorrectionDbi.size() ==
+                        antennaInfo.signalGainCorrectionUncertaintyDbi.size());
+            ASSERT_TRUE(antennaInfo.signalGainCorrectionDbi[0].row.size() ==
+                        antennaInfo.signalGainCorrectionUncertaintyDbi[0].row.size());
+
+            // Must be rectangular
+            for (auto row : antennaInfo.signalGainCorrectionDbi) {
+                ASSERT_TRUE(row.row.size() == numColumns);
+            }
+            for (auto row : antennaInfo.signalGainCorrectionUncertaintyDbi) {
+                ASSERT_TRUE(row.row.size() == numColumns);
+            }
+        }
+    }
+
+    iGnssAntennaInfo->close();
+}
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl
index 5c3d4cb..359c655 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Transform.aidl
@@ -34,6 +34,7 @@
 package android.hardware.graphics.common;
 @Backing(type="int") @VintfStability
 enum Transform {
+  NONE = 0,
   FLIP_H = 1,
   FLIP_V = 2,
   ROT_90 = 4,
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Transform.aidl b/graphics/common/aidl/android/hardware/graphics/common/Transform.aidl
index 325816c..4b3a1b1 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/Transform.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/Transform.aidl
@@ -23,6 +23,11 @@
 @Backing(type="int")
 enum Transform {
     /**
+     * Identity transform (i.e. no rotation or flip).
+     */
+    NONE = 0,
+
+    /**
      * Horizontal flip. FLIP_H/FLIP_V is applied before ROT_90.
      */
     FLIP_H = 1 << 0,
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
index a8239cd..5593c57 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -51,6 +51,7 @@
   int getDisplayVsyncPeriod(long display);
   android.hardware.graphics.composer3.DisplayContentSample getDisplayedContentSample(long display, long maxFrames, long timestamp);
   android.hardware.graphics.composer3.DisplayContentSamplingAttributes getDisplayedContentSamplingAttributes(long display);
+  android.hardware.graphics.common.Transform getDisplayPhysicalOrientation(long display);
   android.hardware.graphics.composer3.HdrCapabilities getHdrCapabilities(long display);
   int getMaxVirtualDisplayCount();
   android.hardware.graphics.composer3.PerFrameMetadataKey[] getPerFrameMetadataKeys(long display);
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
index 9a29e7e..c86b9bd 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -16,6 +16,7 @@
 
 package android.hardware.graphics.composer3;
 
+import android.hardware.graphics.common.Transform;
 import android.hardware.graphics.composer3.ClientTargetProperty;
 import android.hardware.graphics.composer3.ColorMode;
 import android.hardware.graphics.composer3.CommandResultPayload;
@@ -354,6 +355,23 @@
     DisplayContentSamplingAttributes getDisplayedContentSamplingAttributes(long display);
 
     /**
+     * Queries the physical orientation of a display. Orientation 'Transform::NONE'
+     * represents a display that doesn't require any transformation on layers
+     * to be presented at their natural orientation.
+     *
+     * @param display is the display where the physical orientation is queried.
+     *
+     * @return is one of the below values:
+     *         Transform::NONE
+     *         Transform::ROT_90
+     *         Transform::ROT_180
+     *         Transform::ROT_270
+     *
+     * @exception EX_BAD_DISPLAY when an invalid display was passed in.
+     */
+    Transform getDisplayPhysicalOrientation(long display);
+
+    /**
      * Returns the high dynamic range (HDR) capabilities of the given display,
      * which are invariant with regard to the active configuration.
      *
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
index b5ad05f..1cfd3f9 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/vts/functional/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -959,6 +959,33 @@
     EXPECT_TRUE(mComposerClient->getDisplayName(mPrimaryDisplay, &displayName).isOk());
 }
 
+TEST_P(GraphicsComposerAidlTest, GetDisplayPhysicalOrientationBadDisplay) {
+    Transform displayOrientation;
+    const auto error =
+            mComposerClient->getDisplayPhysicalOrientation(mInvalidDisplayId, &displayOrientation);
+
+    EXPECT_FALSE(error.isOk());
+    ASSERT_EQ(IComposerClient::EX_BAD_DISPLAY, error.getServiceSpecificError());
+}
+
+TEST_P(GraphicsComposerAidlTest, GetDisplayPhysicalOrientation) {
+    const auto allowedDisplayOrientations = std::array<Transform, 4>{
+            Transform::NONE,
+            Transform::ROT_90,
+            Transform::ROT_180,
+            Transform::ROT_270,
+    };
+
+    Transform displayOrientation;
+    const auto error =
+            mComposerClient->getDisplayPhysicalOrientation(mPrimaryDisplay, &displayOrientation);
+
+    EXPECT_TRUE(error.isOk());
+    EXPECT_NE(std::find(allowedDisplayOrientations.begin(), allowedDisplayOrientations.end(),
+                        displayOrientation),
+              allowedDisplayOrientations.end());
+}
+
 TEST_P(GraphicsComposerAidlTest, SetClientTargetSlotCount) {
     EXPECT_TRUE(
             mComposerClient->setClientTargetSlotCount(mPrimaryDisplay, kBufferSlotCount).isOk());
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
index 6982d40..980b042 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/ApnTypes.aidl
@@ -47,4 +47,7 @@
   EMERGENCY = 512,
   MCX = 1024,
   XCAP = 2048,
+  VSIM = 4096,
+  BIP = 8192,
+  ENTERPRISE = 16384,
 }
diff --git a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
index e780d8e..ae103fc 100644
--- a/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
+++ b/radio/aidl/android/hardware/radio/data/ApnTypes.aidl
@@ -73,4 +73,16 @@
      * APN type for XCAP
      */
     XCAP = 1 << 11,
+    /**
+     * APN type for VSIM.
+     */
+    VSIM = 1 << 12,
+    /**
+     * APN type for BIP.
+     */
+    BIP = 1 << 13,
+    /**
+     * APN type for ENTERPRISE
+     */
+    ENTERPRISE = 1 << 14
 }
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/BccHandover.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/BccHandover.aidl
index ab50c36..8baca94 100644
--- a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/BccHandover.aidl
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/BccHandover.aidl
@@ -35,7 +35,7 @@
 /* @hide */
 @RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable BccHandover {
-  byte[] cdiAttest;
-  byte[] cdiSeal;
+  byte[32] cdiAttest;
+  byte[32] cdiSeal;
   android.hardware.security.dice.Bcc bcc;
 }
diff --git a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/InputValues.aidl b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/InputValues.aidl
index 79583fb..e43c429 100644
--- a/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/InputValues.aidl
+++ b/security/dice/aidl/aidl_api/android.hardware.security.dice/current/android/hardware/security/dice/InputValues.aidl
@@ -35,10 +35,10 @@
 /* @hide */
 @RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
 parcelable InputValues {
-  byte[] codeHash;
+  byte[64] codeHash;
   android.hardware.security.dice.Config config;
-  byte[] authorityHash;
+  byte[64] authorityHash;
   @nullable byte[] authorityDescriptor;
   android.hardware.security.dice.Mode mode = android.hardware.security.dice.Mode.NOT_INITIALIZED;
-  byte[] hidden;
+  byte[64] hidden;
 }
diff --git a/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl b/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl
index d522cef..6ca862c 100644
--- a/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl
+++ b/security/dice/aidl/android/hardware/security/dice/BccHandover.aidl
@@ -27,13 +27,13 @@
 @RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
 parcelable BccHandover {
     /**
-     * CDI_attest. Must a exactly 32 bytes of data.
+     * CDI_attest. Must be exactly 32 bytes of data.
      */
-    byte[] cdiAttest;
+    byte[32] cdiAttest;
     /**
-     * CDI_seal. Must a exactly 32 bytes of data.
+     * CDI_seal. Must be exactly 32 bytes of data.
      */
-    byte[] cdiSeal;
+    byte[32] cdiSeal;
     /**
      * CBOR encoded BCC.
      *
diff --git a/security/dice/aidl/android/hardware/security/dice/InputValues.aidl b/security/dice/aidl/android/hardware/security/dice/InputValues.aidl
index e44ef22..711d523 100644
--- a/security/dice/aidl/android/hardware/security/dice/InputValues.aidl
+++ b/security/dice/aidl/android/hardware/security/dice/InputValues.aidl
@@ -34,7 +34,7 @@
     /**
      * The target code hash. Must be exactly 64 bytes.
      */
-    byte[] codeHash;
+    byte[64] codeHash;
     /**
      * The configuration data.
      */
@@ -42,7 +42,7 @@
     /**
      * The authority hash. Must be exactly 64 bytes. Must be all zero if unused.
      */
-    byte[] authorityHash;
+    byte[64] authorityHash;
     /**
      * Optional free form authorityDescriptor.
      */
@@ -54,5 +54,5 @@
     /**
      * Optional hidden values. Must be exactly 64 bytes. Must be all zero if unused.
      */
-    byte[] hidden;
+    byte[64] hidden;
 }
diff --git a/sensors/aidl/default/multihal/ConvertUtils.cpp b/sensors/aidl/default/multihal/ConvertUtils.cpp
index 4d6697b..509bbb0 100644
--- a/sensors/aidl/default/multihal/ConvertUtils.cpp
+++ b/sensors/aidl/default/multihal/ConvertUtils.cpp
@@ -131,7 +131,7 @@
             break;
         case AidlSensorType::POSE_6DOF:
             std::copy(std::begin(aidlEvent.payload.get<AidlEvent::EventPayload::pose6DOF>().values),
-                      std::end(aidlEvent.payload.get<AidlEvent::EventPayload::data>().values),
+                      std::end(aidlEvent.payload.get<AidlEvent::EventPayload::pose6DOF>().values),
                       hidlEvent->u.pose6DOF.data());
             break;
         case AidlSensorType::DYNAMIC_SENSOR_META:
@@ -318,4 +318,4 @@
 }  // namespace sensors
 }  // namespace hardware
 }  // namespace android
-}  // namespace aidl
\ No newline at end of file
+}  // namespace aidl