Audio: Migrate to AIDL API

Tag: #refactor
Bug: 203490261
Test: atest BluetoothInstrumentationTests
Change-Id: I606fe51ce2e2c070646ce81966e69e82893f36a4
diff --git a/system/audio_bluetooth_hw/Android.bp b/system/audio_bluetooth_hw/Android.bp
index 08496c2..25e1f8c 100644
--- a/system/audio_bluetooth_hw/Android.bp
+++ b/system/audio_bluetooth_hw/Android.bp
@@ -17,21 +17,25 @@
         "audio_bluetooth_hw.cc",
         "stream_apis.cc",
         "device_port_proxy.cc",
+        "device_port_proxy_hidl.cc",
         "utils.cc",
     ],
     header_libs: ["libhardware_headers"],
     shared_libs: [
-        "android.hardware.bluetooth.audio@2.0",
-        "android.hardware.bluetooth.audio@2.1",
-        "android.hardware.bluetooth.audio@2.2",
+        "android.hardware.bluetooth.audio-V1-ndk",
+        "libbluetooth_audio_session_aidl",
         "libaudioutils",
         "libbase",
-        "libbluetooth_audio_session",
+        "libbinder_ndk",
         "libcutils",
         "libfmq",
-        "libhidlbase",
         "liblog",
         "libutils",
+        // HIDL dependencies
+        "android.hardware.bluetooth.audio@2.0",
+        "android.hardware.bluetooth.audio@2.1",
+        "libbluetooth_audio_session",
+        "libhidlbase",
     ],
     cflags: [
         "-Wall",
diff --git a/system/audio_bluetooth_hw/device_port_proxy.cc b/system/audio_bluetooth_hw/device_port_proxy.cc
index ed9f095..b9be63d 100644
--- a/system/audio_bluetooth_hw/device_port_proxy.cc
+++ b/system/audio_bluetooth_hw/device_port_proxy.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 The Android Open Source Project
+ * Copyright 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.
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "BTAudioHalDeviceProxy"
+#define LOG_TAG "BTAudioHalDeviceProxyAIDL"
+
+#include "device_port_proxy.h"
 
 #include <android-base/logging.h>
 #include <android-base/stringprintf.h>
@@ -23,56 +25,29 @@
 #include <log/log.h>
 #include <stdlib.h>
 
-#include "BluetoothAudioSessionControl_2_2.h"
-#include "device_port_proxy.h"
+#include "BluetoothAudioSessionControl.h"
 #include "stream_apis.h"
 #include "utils.h"
 
 namespace android {
 namespace bluetooth {
 namespace audio {
+namespace aidl {
+
+using ::aidl::android::hardware::bluetooth::audio::AudioConfiguration;
+using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioSessionControl;
+using ::aidl::android::hardware::bluetooth::audio::ChannelMode;
+using ::aidl::android::hardware::bluetooth::audio::PcmConfiguration;
+using ::aidl::android::hardware::bluetooth::audio::PortStatusCallbacks;
+using ::aidl::android::hardware::bluetooth::audio::PresentationPosition;
 
 using ::android::base::StringPrintf;
-using ::android::bluetooth::audio::BluetoothAudioSessionControl_2_2;
-using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
-using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
-using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
-using SampleRate = ::android::hardware::bluetooth::audio::V2_0::SampleRate;
-using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate;
-using BluetoothAudioStatus =
-    ::android::hardware::bluetooth::audio::V2_0::Status;
 using ControlResultCallback = std::function<void(
     uint16_t cookie, bool start_resp, const BluetoothAudioStatus& status)>;
 using SessionChangedCallback = std::function<void(uint16_t cookie)>;
 
 namespace {
 
-unsigned int SampleRateToAudioFormat(SampleRate_2_1 sample_rate) {
-  switch (sample_rate) {
-    case SampleRate_2_1::RATE_8000:
-      return 8000;
-    case SampleRate_2_1::RATE_16000:
-      return 16000;
-    case SampleRate_2_1::RATE_24000:
-      return 24000;
-    case SampleRate_2_1::RATE_32000:
-      return 32000;
-    case SampleRate_2_1::RATE_44100:
-      return 44100;
-    case SampleRate_2_1::RATE_48000:
-      return 48000;
-    case SampleRate_2_1::RATE_88200:
-      return 88200;
-    case SampleRate_2_1::RATE_96000:
-      return 96000;
-    case SampleRate_2_1::RATE_176400:
-      return 176400;
-    case SampleRate_2_1::RATE_192000:
-      return 192000;
-    default:
-      return kBluetoothDefaultSampleRate;
-  }
-}
 audio_channel_mask_t OutputChannelModeToAudioFormat(ChannelMode channel_mode) {
   switch (channel_mode) {
     case ChannelMode::MONO:
@@ -95,13 +70,13 @@
   }
 }
 
-audio_format_t BitsPerSampleToAudioFormat(BitsPerSample bits_per_sample) {
+audio_format_t BitsPerSampleToAudioFormat(uint8_t bits_per_sample) {
   switch (bits_per_sample) {
-    case BitsPerSample::BITS_16:
+    case 16:
       return AUDIO_FORMAT_PCM_16_BIT;
-    case BitsPerSample::BITS_24:
+    case 24:
       return AUDIO_FORMAT_PCM_24_BIT_PACKED;
-    case BitsPerSample::BITS_32:
+    case 32:
       return AUDIO_FORMAT_PCM_32_BIT;
     default:
       return kBluetoothDefaultAudioFormatBitsPerSample;
@@ -113,12 +88,21 @@
 
 }  // namespace
 
-BluetoothAudioPort::BluetoothAudioPort()
-    : cookie_(android::bluetooth::audio::kObserversCookieUndefined),
+BluetoothAudioPortAidl::BluetoothAudioPortAidl()
+    : cookie_(::aidl::android::hardware::bluetooth::audio::
+                  kObserversCookieUndefined),
       state_(BluetoothStreamState::DISABLED),
-      session_type_(SessionType_2_1::UNKNOWN) {}
+      session_type_(SessionType::UNKNOWN) {}
 
-bool BluetoothAudioPort::SetUp(audio_devices_t devices) {
+BluetoothAudioPortAidlOut::~BluetoothAudioPortAidlOut() {
+  if (in_use()) TearDown();
+}
+
+BluetoothAudioPortAidlIn::~BluetoothAudioPortAidlIn() {
+  if (in_use()) TearDown();
+}
+
+bool BluetoothAudioPortAidl::SetUp(audio_devices_t devices) {
   if (!init_session_type(devices)) return false;
 
   state_ = BluetoothStreamState::STANDBY;
@@ -126,106 +110,120 @@
   auto control_result_cb = [port = this](uint16_t cookie, bool start_resp,
                                          const BluetoothAudioStatus& status) {
     if (!port->in_use()) {
-      LOG(ERROR) << "control_result_cb: BluetoothAudioPort is not in use";
+      LOG(ERROR) << "control_result_cb: BluetoothAudioPortAidl is not in use";
       return;
     }
     if (port->cookie_ != cookie) {
-      LOG(ERROR) << "control_result_cb: proxy of device port (cookie=" << StringPrintf("%#hx", cookie)
-                 << ") is corrupted";
+      LOG(ERROR) << "control_result_cb: proxy of device port (cookie="
+                 << StringPrintf("%#hx", cookie) << ") is corrupted";
       return;
     }
     port->ControlResultHandler(status);
   };
   auto session_changed_cb = [port = this](uint16_t cookie) {
     if (!port->in_use()) {
-      LOG(ERROR) << "session_changed_cb: BluetoothAudioPort is not in use";
+      LOG(ERROR) << "session_changed_cb: BluetoothAudioPortAidl is not in use";
       return;
     }
     if (port->cookie_ != cookie) {
-      LOG(ERROR) << "session_changed_cb: proxy of device port (cookie=" << StringPrintf("%#hx", cookie)
-                 << ") is corrupted";
+      LOG(ERROR) << "session_changed_cb: proxy of device port (cookie="
+                 << StringPrintf("%#hx", cookie) << ") is corrupted";
       return;
     }
     port->SessionChangedHandler();
   };
-  ::android::bluetooth::audio::PortStatusCallbacks cbacks = {
+  // TODO: Add audio_config_changed_cb
+  PortStatusCallbacks cbacks = {
       .control_result_cb_ = control_result_cb,
-      .session_changed_cb_ = session_changed_cb};
-  cookie_ = BluetoothAudioSessionControl_2_2::RegisterControlResultCback(
+      .session_changed_cb_ = session_changed_cb,
+  };
+  cookie_ = BluetoothAudioSessionControl::RegisterControlResultCback(
       session_type_, cbacks);
-  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_);
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_);
 
-  return (cookie_ != android::bluetooth::audio::kObserversCookieUndefined);
+  return (
+      cookie_ !=
+      ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
 }
 
-bool BluetoothAudioPort::init_session_type(audio_devices_t device) {
+bool BluetoothAudioPortAidl::init_session_type(audio_devices_t device) {
   switch (device) {
     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
     case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
-      LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
-                   << StringPrintf("%#x", device) << ")";
-      session_type_ = SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH;
+      LOG(VERBOSE)
+          << __func__
+          << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
+          << StringPrintf("%#x", device) << ")";
+      session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
       break;
     case AUDIO_DEVICE_OUT_HEARING_AID:
-      LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) (" << StringPrintf("%#x", device)
-                   << ")";
-      session_type_ = SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
+      LOG(VERBOSE) << __func__
+                   << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) ("
+                   << StringPrintf("%#x", device) << ")";
+      session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
       break;
     case AUDIO_DEVICE_OUT_BLE_HEADSET:
       LOG(VERBOSE) << __func__
                    << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) ("
                    << StringPrintf("%#x", device) << ")";
-      session_type_ = SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+      session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
       break;
     case AUDIO_DEVICE_OUT_BLE_SPEAKER:
       LOG(VERBOSE) << __func__
                    << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) ("
                    << StringPrintf("%#x", device) << ")";
-      session_type_ = SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+      session_type_ = SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
       break;
     case AUDIO_DEVICE_IN_BLE_HEADSET:
       LOG(VERBOSE) << __func__
                    << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) ("
                    << StringPrintf("%#x", device) << ")";
-      session_type_ = SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH;
+      session_type_ = SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH;
       break;
     default:
-      LOG(ERROR) << __func__ << ": unknown device=" << StringPrintf("%#x", device);
+      LOG(ERROR) << __func__
+                 << ": unknown device=" << StringPrintf("%#x", device);
       return false;
   }
 
-  if (!BluetoothAudioSessionControl_2_2::IsSessionReady(session_type_)) {
-    LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device) << ", session_type=" << toString(session_type_)
+  if (!BluetoothAudioSessionControl::IsSessionReady(session_type_)) {
+    LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device)
+               << ", session_type=" << toString(session_type_)
                << " is not ready";
     return false;
   }
   return true;
 }
 
-void BluetoothAudioPort::TearDown() {
+void BluetoothAudioPortAidl::TearDown() {
   if (!in_use()) {
     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
-               << ", cookie=" << StringPrintf("%#hx", cookie_) << " unknown monitor";
+               << ", cookie=" << StringPrintf("%#hx", cookie_)
+               << " unknown monitor";
     return;
   }
 
-  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_);
-  BluetoothAudioSessionControl_2_2::UnregisterControlResultCback(session_type_,
-                                                                 cookie_);
-  cookie_ = android::bluetooth::audio::kObserversCookieUndefined;
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_);
+  BluetoothAudioSessionControl::UnregisterControlResultCback(session_type_,
+                                                             cookie_);
+  cookie_ =
+      ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined;
 }
 
-void BluetoothAudioPort::ControlResultHandler(
+void BluetoothAudioPortAidl::ControlResultHandler(
     const BluetoothAudioStatus& status) {
   if (!in_use()) {
-    LOG(ERROR) << __func__ << ": BluetoothAudioPortis not in use";
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlis not in use";
     return;
   }
   std::unique_lock<std::mutex> port_lock(cv_mutex_);
   BluetoothStreamState previous_state = state_;
   LOG(INFO) << "control_result_cb: session_type=" << toString(session_type_)
-            << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state
+            << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", previous_state=" << previous_state
             << ", status=" << toString(status);
 
   switch (previous_state) {
@@ -236,7 +234,8 @@
         // Set to standby since the stack may be busy switching between outputs
         LOG(WARNING) << "control_result_cb: status=" << toString(status)
                      << " failure for session_type=" << toString(session_type_)
-                     << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state;
+                     << ", cookie=" << StringPrintf("%#hx", cookie_)
+                     << ", previous_state=" << previous_state;
         state_ = BluetoothStreamState::STANDBY;
       }
       break;
@@ -248,13 +247,15 @@
         // to wait for re-init again
         LOG(WARNING) << "control_result_cb: status=" << toString(status)
                      << " failure for session_type=" << toString(session_type_)
-                     << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state;
+                     << ", cookie=" << StringPrintf("%#hx", cookie_)
+                     << ", previous_state=" << previous_state;
         state_ = BluetoothStreamState::DISABLED;
       }
       break;
     default:
       LOG(ERROR) << "control_result_cb: unexpected status=" << toString(status)
-                 << " for session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
+                 << " for session_type=" << toString(session_type_)
+                 << ", cookie=" << StringPrintf("%#hx", cookie_)
                  << ", previous_state=" << previous_state;
       return;
   }
@@ -262,75 +263,73 @@
   internal_cv_.notify_all();
 }
 
-void BluetoothAudioPort::SessionChangedHandler() {
+void BluetoothAudioPortAidl::SessionChangedHandler() {
   if (!in_use()) {
-    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
     return;
   }
   std::unique_lock<std::mutex> port_lock(cv_mutex_);
   BluetoothStreamState previous_state = state_;
   LOG(INFO) << "session_changed_cb: session_type=" << toString(session_type_)
-            << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state;
+            << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", previous_state=" << previous_state;
   state_ = BluetoothStreamState::DISABLED;
   port_lock.unlock();
   internal_cv_.notify_all();
 }
 
-bool BluetoothAudioPort::in_use() const {
-  return (cookie_ != android::bluetooth::audio::kObserversCookieUndefined);
+bool BluetoothAudioPortAidl::in_use() const {
+  return (
+      cookie_ !=
+      ::aidl::android::hardware::bluetooth::audio::kObserversCookieUndefined);
 }
 
-bool BluetoothAudioPort::GetPreferredDataIntervalUs(size_t* interval_us) const {
+bool BluetoothAudioPortAidl::GetPreferredDataIntervalUs(
+    size_t* interval_us) const {
   if (!in_use()) {
     return false;
   }
 
-  const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
-      hal_audio_cfg =
-          BluetoothAudioSessionControl_2_2::GetAudioConfig(session_type_);
-  if (hal_audio_cfg.getDiscriminator() !=
-      ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
-          hidl_discriminator::pcmConfig) {
+  const AudioConfiguration& hal_audio_cfg =
+      BluetoothAudioSessionControl::GetAudioConfig(session_type_);
+  if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
     return false;
   }
 
-  const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg =
-      hal_audio_cfg.pcmConfig();
+  const PcmConfiguration& pcm_cfg =
+      hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
   *interval_us = pcm_cfg.dataIntervalUs;
   return true;
 }
 
-bool BluetoothAudioPortOut::LoadAudioConfig(audio_config_t* audio_cfg) const {
+bool BluetoothAudioPortAidlOut::LoadAudioConfig(
+    audio_config_t* audio_cfg) const {
   if (!in_use()) {
-    LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlOut is not in use";
     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
     audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
     return false;
   }
 
-  const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
-      hal_audio_cfg =
-          BluetoothAudioSessionControl_2_2::GetAudioConfig(session_type_);
-  if (hal_audio_cfg.getDiscriminator() !=
-      ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
-          hidl_discriminator::pcmConfig) {
+  const AudioConfiguration& hal_audio_cfg =
+      BluetoothAudioSessionControl::GetAudioConfig(session_type_);
+  if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
     audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
     return false;
   }
-  const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg =
-      hal_audio_cfg.pcmConfig();
+  const PcmConfiguration& pcm_cfg =
+      hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
   LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
-               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", PcmConfig=["
-               << toString(pcm_cfg) << "]";
-  if (pcm_cfg.sampleRate == SampleRate_2_1::RATE_UNKNOWN ||
-      pcm_cfg.channelMode == ChannelMode::UNKNOWN ||
-      pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
+               << ", cookie=" << StringPrintf("%#hx", cookie_)
+               << ", state=" << state_ << ", PcmConfig=[" << pcm_cfg.toString()
+               << "]";
+  if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) {
     return false;
   }
-  audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate);
+  audio_cfg->sample_rate = pcm_cfg.sampleRateHz;
   audio_cfg->channel_mask =
       (is_stereo_to_mono_
            ? AUDIO_CHANNEL_OUT_STEREO
@@ -339,51 +338,48 @@
   return true;
 }
 
-bool BluetoothAudioPortIn::LoadAudioConfig(audio_config_t* audio_cfg) const {
+bool BluetoothAudioPortAidlIn::LoadAudioConfig(
+    audio_config_t* audio_cfg) const {
   if (!in_use()) {
-    LOG(ERROR) << __func__ << ": BluetoothAudioPortIn is not in use";
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortAidlIn is not in use";
     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
     audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
     return false;
   }
 
-  const ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration&
-      hal_audio_cfg =
-          BluetoothAudioSessionControl_2_2::GetAudioConfig(session_type_);
-  if (hal_audio_cfg.getDiscriminator() !=
-      ::android::hardware::bluetooth::audio::V2_2::AudioConfiguration::
-          hidl_discriminator::pcmConfig) {
+  const AudioConfiguration& hal_audio_cfg =
+      BluetoothAudioSessionControl::GetAudioConfig(session_type_);
+  if (hal_audio_cfg.getTag() != AudioConfiguration::pcmConfig) {
     audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
     audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
     audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
     return false;
   }
-  const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg =
-      hal_audio_cfg.pcmConfig();
+  const PcmConfiguration& pcm_cfg =
+      hal_audio_cfg.get<AudioConfiguration::pcmConfig>();
   LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
                << ", cookie=" << StringPrintf("%#hx", cookie_)
-               << ", state=" << state_ << ", PcmConfig=[" << toString(pcm_cfg)
+               << ", state=" << state_ << ", PcmConfig=[" << pcm_cfg.toString()
                << "]";
-  if (pcm_cfg.sampleRate == SampleRate_2_1::RATE_UNKNOWN ||
-      pcm_cfg.channelMode == ChannelMode::UNKNOWN ||
-      pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
+  if (pcm_cfg.channelMode == ChannelMode::UNKNOWN) {
     return false;
   }
 
-  audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate);
+  audio_cfg->sample_rate = pcm_cfg.sampleRateHz;
   audio_cfg->channel_mask = InputChannelModeToAudioFormat(pcm_cfg.channelMode);
   audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample);
   return true;
 }
 
-bool BluetoothAudioPort::CondwaitState(BluetoothStreamState state) {
+bool BluetoothAudioPortAidl::CondwaitState(BluetoothStreamState state) {
   bool retval;
   std::unique_lock<std::mutex> port_lock(cv_mutex_);
   switch (state) {
     case BluetoothStreamState::STARTING:
       LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
-                   << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for STARTED";
+                   << ", cookie=" << StringPrintf("%#hx", cookie_)
+                   << " waiting for STARTED";
       retval = internal_cv_.wait_for(
           port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
           [this] { return this->state_ != BluetoothStreamState::STARTING; });
@@ -391,7 +387,8 @@
       break;
     case BluetoothStreamState::SUSPENDING:
       LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
-                   << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for SUSPENDED";
+                   << ", cookie=" << StringPrintf("%#hx", cookie_)
+                   << " waiting for SUSPENDED";
       retval = internal_cv_.wait_for(
           port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
           [this] { return this->state_ != BluetoothStreamState::SUSPENDING; });
@@ -399,92 +396,107 @@
       break;
     default:
       LOG(WARNING) << __func__ << ": session_type=" << toString(session_type_)
-                   << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for KNOWN";
+                   << ", cookie=" << StringPrintf("%#hx", cookie_)
+                   << " waiting for KNOWN";
       return false;
   }
 
   return retval;  // false if any failure like timeout
 }
 
-bool BluetoothAudioPort::Start() {
+bool BluetoothAudioPortAidl::Start() {
   if (!in_use()) {
-    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
     return false;
   }
 
-  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
-            << ", state=" << state_ << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " request";
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", state=" << state_
+            << ", mono=" << (is_stereo_to_mono_ ? "true" : "false")
+            << " request";
   bool retval = false;
   if (state_ == BluetoothStreamState::STANDBY) {
     state_ = BluetoothStreamState::STARTING;
-    if (BluetoothAudioSessionControl_2_2::StartStream(session_type_)) {
+    if (BluetoothAudioSessionControl::StartStream(session_type_)) {
       retval = CondwaitState(BluetoothStreamState::STARTING);
     } else {
       LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
-                 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " Hal fails";
+                 << ", cookie=" << StringPrintf("%#hx", cookie_)
+                 << ", state=" << state_ << " Hal fails";
     }
   }
 
   if (retval) {
     LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
-              << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
-              << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " done";
+              << ", cookie=" << StringPrintf("%#hx", cookie_)
+              << ", state=" << state_
+              << ", mono=" << (is_stereo_to_mono_ ? "true" : "false")
+              << " done";
   } else {
     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
-               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " failure";
+               << ", cookie=" << StringPrintf("%#hx", cookie_)
+               << ", state=" << state_ << " failure";
   }
 
   return retval;  // false if any failure like timeout
 }
 
-bool BluetoothAudioPort::Suspend() {
+bool BluetoothAudioPortAidl::Suspend() {
   if (!in_use()) {
-    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
     return false;
   }
 
-  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_)
             << ", state=" << state_ << " request";
   bool retval = false;
   if (state_ == BluetoothStreamState::STARTED) {
     state_ = BluetoothStreamState::SUSPENDING;
-    if (BluetoothAudioSessionControl_2_2::SuspendStream(session_type_)) {
+    if (BluetoothAudioSessionControl::SuspendStream(session_type_)) {
       retval = CondwaitState(BluetoothStreamState::SUSPENDING);
     } else {
       LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
-                 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " Hal fails";
+                 << ", cookie=" << StringPrintf("%#hx", cookie_)
+                 << ", state=" << state_ << " Hal fails";
     }
   }
 
   if (retval) {
     LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
-              << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " done";
+              << ", cookie=" << StringPrintf("%#hx", cookie_)
+              << ", state=" << state_ << " done";
   } else {
     LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
-               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " failure";
+               << ", cookie=" << StringPrintf("%#hx", cookie_)
+               << ", state=" << state_ << " failure";
   }
 
   return retval;  // false if any failure like timeout
 }
 
-void BluetoothAudioPort::Stop() {
+void BluetoothAudioPortAidl::Stop() {
   if (!in_use()) {
-    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
     return;
   }
-  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_)
             << ", state=" << state_ << " request";
   state_ = BluetoothStreamState::DISABLED;
-  BluetoothAudioSessionControl_2_2::StopStream(session_type_);
-  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
+  BluetoothAudioSessionControl::StopStream(session_type_);
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_)
             << ", state=" << state_ << " done";
 }
 
-size_t BluetoothAudioPortOut::WriteData(const void* buffer, size_t bytes) const {
+size_t BluetoothAudioPortAidlOut::WriteData(const void* buffer,
+                                            size_t bytes) const {
   if (!in_use()) return 0;
   if (!is_stereo_to_mono_) {
-    return BluetoothAudioSessionControl_2_2::OutWritePcmData(session_type_,
-                                                             buffer, bytes);
+    return BluetoothAudioSessionControl::OutWritePcmData(session_type_, buffer,
+                                                         bytes);
   }
 
   // WAR to mix the stereo into Mono (16 bits per sample)
@@ -494,51 +506,62 @@
   std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
   downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
   // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
-  return BluetoothAudioSessionControl_2_2::OutWritePcmData(
-             session_type_, dst.get(), write_frames * 2) *
+  return BluetoothAudioSessionControl::OutWritePcmData(session_type_, dst.get(),
+                                                       write_frames * 2) *
          2;
 }
 
-size_t BluetoothAudioPortIn::ReadData(void* buffer, size_t bytes) const {
+size_t BluetoothAudioPortAidlIn::ReadData(void* buffer, size_t bytes) const {
   if (!in_use()) return 0;
-  return BluetoothAudioSessionControl_2_2::InReadPcmData(session_type_, buffer,
-                                                         bytes);
+  return BluetoothAudioSessionControl::InReadPcmData(session_type_, buffer,
+                                                     bytes);
 }
 
-bool BluetoothAudioPort::GetPresentationPosition(uint64_t* delay_ns,
-                                                 uint64_t* bytes,
-                                                 timespec* timestamp) const {
+bool BluetoothAudioPortAidl::GetPresentationPosition(
+    uint64_t* delay_ns, uint64_t* bytes, timespec* timestamp) const {
   if (!in_use()) {
-    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
     return false;
   }
-  bool retval = BluetoothAudioSessionControl_2_2::GetPresentationPosition(
-      session_type_, delay_ns, bytes, timestamp);
-  LOG(VERBOSE) << __func__ << ": session_type=" << StringPrintf("%#hhx", session_type_)
-               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", delay=" << *delay_ns
-               << "ns, data=" << *bytes << " bytes, timestamp=" << timestamp->tv_sec << "."
+  PresentationPosition presentation_position;
+  bool retval = BluetoothAudioSessionControl::GetPresentationPosition(
+      session_type_, presentation_position);
+  *delay_ns = presentation_position.remoteDeviceAudioDelayNanos;
+  *bytes = presentation_position.transmittedOctets;
+  *timestamp = {.tv_sec = static_cast<__kernel_old_time_t>(
+                    presentation_position.transmittedOctetsTimestamp.tvSec),
+                .tv_nsec = static_cast<long>(
+                    presentation_position.transmittedOctetsTimestamp.tvNSec)};
+  LOG(VERBOSE) << __func__
+               << ": session_type=" << StringPrintf("%#hhx", session_type_)
+               << ", cookie=" << StringPrintf("%#hx", cookie_)
+               << ", state=" << state_ << ", delay=" << *delay_ns
+               << "ns, data=" << *bytes
+               << " bytes, timestamp=" << timestamp->tv_sec << "."
                << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
 
   return retval;
 }
 
-void BluetoothAudioPort::UpdateMetadata(
+void BluetoothAudioPortAidl::UpdateSourceMetadata(
     const source_metadata* source_metadata) const {
   if (!in_use()) {
-    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
     return;
   }
-  LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
-             << ", state=" << state_ << ", " << source_metadata->track_count << " track(s)";
+  LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_)
+             << ", cookie=" << StringPrintf("%#hx", cookie_)
+             << ", state=" << state_ << ", " << source_metadata->track_count
+             << " track(s)";
   if (source_metadata->track_count == 0) return;
-  BluetoothAudioSessionControl_2_2::UpdateTracksMetadata(session_type_,
-                                                         source_metadata);
+  BluetoothAudioSessionControl::UpdateSourceMetadata(session_type_,
+                                                     *source_metadata);
 }
 
-void BluetoothAudioPort::UpdateSinkMetadata(
+void BluetoothAudioPortAidl::UpdateSinkMetadata(
     const sink_metadata* sink_metadata) const {
   if (!in_use()) {
-    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortAidl is not in use";
     return;
   }
   LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_)
@@ -546,16 +569,17 @@
              << ", state=" << state_ << ", " << sink_metadata->track_count
              << " track(s)";
   if (sink_metadata->track_count == 0) return;
-  BluetoothAudioSessionControl_2_2::UpdateSinkMetadata(session_type_,
-                                                       sink_metadata);
+  BluetoothAudioSessionControl::UpdateSinkMetadata(session_type_,
+                                                   *sink_metadata);
 }
 
-BluetoothStreamState BluetoothAudioPort::GetState() const { return state_; }
+BluetoothStreamState BluetoothAudioPortAidl::GetState() const { return state_; }
 
-void BluetoothAudioPort::SetState(BluetoothStreamState state) {
+void BluetoothAudioPortAidl::SetState(BluetoothStreamState state) {
   state_ = state;
 }
 
+}  // namespace aidl
 }  // namespace audio
 }  // namespace bluetooth
-}  // namespace android
+}  // namespace android
\ No newline at end of file
diff --git a/system/audio_bluetooth_hw/device_port_proxy.h b/system/audio_bluetooth_hw/device_port_proxy.h
index cc5342d..dab4970 100644
--- a/system/audio_bluetooth_hw/device_port_proxy.h
+++ b/system/audio_bluetooth_hw/device_port_proxy.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2019 The Android Open Source Project
+ * Copyright 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.
@@ -16,8 +16,10 @@
 
 #pragma once
 
-#include <android/hardware/bluetooth/audio/2.2/types.h>
+#include <aidl/android/hardware/bluetooth/audio/BluetoothAudioStatus.h>
+#include <aidl/android/hardware/bluetooth/audio/SessionType.h>
 #include <hardware/audio.h>
+
 #include <condition_variable>
 #include <mutex>
 #include <unordered_map>
@@ -28,112 +30,184 @@
 namespace bluetooth {
 namespace audio {
 
-using SessionType_2_1 =
-    ::android::hardware::bluetooth::audio::V2_1::SessionType;
-
-// Proxy for Bluetooth Audio HW Module to communicate with Bluetooth Audio
-// Session Control. All methods are not thread safe, so users must acquire a
-// lock. Note: currently, in stream_apis.cc, if GetState() is only used for
-// verbose logging, it is not locked, so the state may not be synchronized.
+/***
+ * Proxy for Bluetooth Audio HW Module to communicate with Bluetooth Audio
+ * Session Control. All methods are not thread safe, so users must acquire a
+ * lock. Note: currently, in stream_apis.cc, if GetState() is only used for
+ * verbose logging, it is not locked, so the state may not be synchronized.
+ ***/
 class BluetoothAudioPort {
  public:
-  BluetoothAudioPort();
+  BluetoothAudioPort(){};
   virtual ~BluetoothAudioPort() = default;
 
-  // Fetch output control / data path of BluetoothAudioPort and setup
-  // callbacks into BluetoothAudioProvider. If SetUp() returns false, the audio
-  // HAL must delete this BluetoothAudioPort and return EINVAL to caller
-  bool SetUp(audio_devices_t devices);
+  /***
+   * Fetch output control / data path of BluetoothAudioPort and setup
+   * callbacks into BluetoothAudioProvider. If SetUp() returns false, the audio
+   * HAL must delete this BluetoothAudioPort and return EINVAL to caller
+   ***/
+  virtual bool SetUp(audio_devices_t) { return false; }
 
-  // Unregister this BluetoothAudioPort from BluetoothAudioSessionControl.
-  // Audio HAL must delete this BluetoothAudioPort after calling this.
-  void TearDown();
+  /***
+   * Unregister this BluetoothAudioPort from BluetoothAudioSessionControl.
+   * Audio HAL must delete this BluetoothAudioPort after calling this.
+   ***/
+  virtual void TearDown() {}
 
-  // When the Audio framework / HAL tries to query audio config about format,
-  // channel mask and sample rate, it uses this function to fetch from the
-  // Bluetooth stack
-  virtual bool LoadAudioConfig(audio_config_t* audio_cfg) const = 0;
+  /***
+   * When the Audio framework / HAL tries to query audio config about format,
+   * channel mask and sample rate, it uses this function to fetch from the
+   * Bluetooth stack
+   ***/
+  virtual bool LoadAudioConfig(audio_config_t*) const { return false; };
 
-  // WAR to support Mono mode / 16 bits per sample
-  void ForcePcmStereoToMono(bool force) {
-    is_stereo_to_mono_ = force;
+  /***
+   * WAR to support Mono mode / 16 bits per sample
+   ***/
+  virtual void ForcePcmStereoToMono(bool) {}
+
+  /***
+   * When the Audio framework / HAL wants to change the stream state, it invokes
+   * these 3 functions to control the Bluetooth stack (Audio Control Path).
+   * Note: Both Start() and Suspend() will return true when there are no errors.
+   * Called by Audio framework / HAL to start the stream
+   ***/
+  virtual bool Start() { return false; }
+
+  /***
+   * Called by Audio framework / HAL to suspend the stream
+   ***/
+  virtual bool Suspend() { return false; };
+
+  /***
+    virtual bool Suspend() { return false; }
+    * Called by Audio framework / HAL to stop the stream
+  ***/
+  virtual void Stop() {}
+
+  /***
+   * Called by the Audio framework / HAL to fetch information about audio frames
+   * presented to an external sink, or frames presented fror an internal sink
+   ***/
+  virtual bool GetPresentationPosition(uint64_t*, uint64_t*, timespec*) const {
+    return false;
   }
 
-  // When the Audio framework / HAL wants to change the stream state, it invokes
-  // these 3 functions to control the Bluetooth stack (Audio Control Path).
-  // Note: Both Start() and Suspend() will return ture when there are no errors.
-  // Called by Audio framework / HAL to start the stream
-  bool Start();
-  // Called by Audio framework / HAL to suspend the stream
-  bool Suspend();
-  // Called by Audio framework / HAL to stop the stream
-  void Stop();
+  /***
+   * Called by the Audio framework / HAL when the metadata of the stream's
+   * source has been changed.
+   ***/
+  virtual void UpdateSourceMetadata(const source_metadata*) const {};
 
-  // Called by the Audio framework / HAL to fetch informaiton about audio frames
-  // presented to an external sink, or frames presented fror an internal sink
-  bool GetPresentationPosition(uint64_t* delay_ns, uint64_t* bytes,
-                               timespec* timestamp) const;
-
-  // Called by the Audio framework / HAL when the metadata of the stream's
-  // source has been changed.
-  void UpdateMetadata(const source_metadata* source_metadata) const;
-
-  void UpdateSinkMetadata(const sink_metadata* sink_metadata) const;
-
-  // Return the current BluetoothStreamState
-  BluetoothStreamState GetState() const;
-
-  // Set the current BluetoothStreamState
-  void SetState(BluetoothStreamState state);
-
-  bool IsA2dp() const {
-    return session_type_ == SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
-           session_type_ == SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH;
+  /***
+   * Return the current BluetoothStreamState
+   ***/
+  virtual BluetoothStreamState GetState() const {
+    return static_cast<BluetoothStreamState>(0);
   }
 
-  bool GetPreferredDataIntervalUs(size_t* interval_us) const;
+  /***
+   * Set the current BluetoothStreamState
+   ***/
+  virtual void SetState(BluetoothStreamState state) {}
+
+  virtual bool IsA2dp() const { return false; }
+
+  virtual bool GetPreferredDataIntervalUs(size_t* interval_us) const {
+    return false;
+  };
+
+  virtual size_t WriteData(const void* buffer, size_t bytes) const {
+    return 0;
+  };
+  virtual size_t ReadData(void* buffer, size_t bytes) const { return 0; };
+};
+
+namespace aidl {
+
+using ::aidl::android::hardware::bluetooth::audio::BluetoothAudioStatus;
+using ::aidl::android::hardware::bluetooth::audio::SessionType;
+
+class BluetoothAudioPortAidl : public BluetoothAudioPort {
+ public:
+  BluetoothAudioPortAidl();
+  virtual ~BluetoothAudioPortAidl() = default;
+
+  bool SetUp(audio_devices_t devices) override;
+
+  void TearDown() override;
+
+  void ForcePcmStereoToMono(bool force) override { is_stereo_to_mono_ = force; }
+
+  bool Start() override;
+  bool Suspend() override;
+  void Stop() override;
+
+  bool GetPresentationPosition(uint64_t* delay_ns, uint64_t* byte,
+                               timespec* timestamp) const override;
+
+  void UpdateSourceMetadata(
+      const source_metadata* source_metadata) const override;
+
+  /***
+   * Called by the Audio framework / HAL when the metadata of the stream's
+   * sink has been changed.
+   ***/
+  virtual void UpdateSinkMetadata(const sink_metadata* sink_metadata) const;
+
+  BluetoothStreamState GetState() const override;
+
+  void SetState(BluetoothStreamState state) override;
+
+  bool IsA2dp() const override {
+    return session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+           session_type_ ==
+               SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
+  }
+
+  bool GetPreferredDataIntervalUs(size_t* interval_us) const override;
 
  protected:
   uint16_t cookie_;
   BluetoothStreamState state_;
-  SessionType_2_1 session_type_;
+  SessionType session_type_;
   // WR to support Mono: True if fetching Stereo and mixing into Mono
   bool is_stereo_to_mono_ = false;
-  bool in_use() const;
+  virtual bool in_use() const;
 
  private:
   mutable std::mutex cv_mutex_;
   std::condition_variable internal_cv_;
 
   // Check and initialize session type for |devices| If failed, this
-  // BluetoothAudioPort is not initialized and must be deleted.
+  // BluetoothAudioPortAidl is not initialized and must be deleted.
   bool init_session_type(audio_devices_t device);
 
   bool CondwaitState(BluetoothStreamState state);
 
-  void ControlResultHandler(
-      const ::android::hardware::bluetooth::audio::V2_0::Status& status);
+  void ControlResultHandler(const BluetoothAudioStatus& status);
   void SessionChangedHandler();
 };
 
-class BluetoothAudioPortOut : public BluetoothAudioPort {
+class BluetoothAudioPortAidlOut : public BluetoothAudioPortAidl {
  public:
-  ~BluetoothAudioPortOut() = default;
+  ~BluetoothAudioPortAidlOut();
 
   // The audio data path to the Bluetooth stack (Software encoding)
-  size_t WriteData(const void* buffer, size_t bytes) const;
-  bool LoadAudioConfig(audio_config_t* audio_cfg) const;
+  size_t WriteData(const void* buffer, size_t bytes) const override;
+  bool LoadAudioConfig(audio_config_t* audio_cfg) const override;
 };
 
-class BluetoothAudioPortIn : public BluetoothAudioPort {
+class BluetoothAudioPortAidlIn : public BluetoothAudioPortAidl {
  public:
-  ~BluetoothAudioPortIn() = default;
+  ~BluetoothAudioPortAidlIn();
 
   // The audio data path from the Bluetooth stack (Software decoded)
-  size_t ReadData(void* buffer, size_t bytes) const;
-  bool LoadAudioConfig(audio_config_t* audio_cfg) const;
+  size_t ReadData(void* buffer, size_t bytes) const override;
+  bool LoadAudioConfig(audio_config_t* audio_cfg) const override;
 };
 
+}  // namespace aidl
 }  // namespace audio
 }  // namespace bluetooth
 }  // namespace android
diff --git a/system/audio_bluetooth_hw/device_port_proxy_hidl.cc b/system/audio_bluetooth_hw/device_port_proxy_hidl.cc
new file mode 100644
index 0000000..fbe7745
--- /dev/null
+++ b/system/audio_bluetooth_hw/device_port_proxy_hidl.cc
@@ -0,0 +1,608 @@
+/*
+ * Copyright 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 "BTAudioHalDeviceProxyHIDL"
+
+#include "device_port_proxy_hidl.h"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <audio_utils/primitives.h>
+#include <inttypes.h>
+#include <log/log.h>
+#include <stdlib.h>
+
+#include "BluetoothAudioSessionControl_2_1.h"
+#include "stream_apis.h"
+#include "utils.h"
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+namespace hidl {
+
+using ::android::base::StringPrintf;
+using ::android::bluetooth::audio::BluetoothAudioSessionControl_2_1;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
+using SampleRate = ::android::hardware::bluetooth::audio::V2_0::SampleRate;
+using SampleRate_2_1 = ::android::hardware::bluetooth::audio::V2_1::SampleRate;
+using BluetoothAudioStatusHidl =
+    ::android::hardware::bluetooth::audio::V2_0::Status;
+using ControlResultCallback = std::function<void(
+    uint16_t cookie, bool start_resp, const BluetoothAudioStatusHidl& status)>;
+using SessionChangedCallback = std::function<void(uint16_t cookie)>;
+
+namespace {
+
+unsigned int SampleRateToAudioFormat(SampleRate_2_1 sample_rate) {
+  switch (sample_rate) {
+    case SampleRate_2_1::RATE_8000:
+      return 8000;
+    case SampleRate_2_1::RATE_16000:
+      return 16000;
+    case SampleRate_2_1::RATE_24000:
+      return 24000;
+    case SampleRate_2_1::RATE_32000:
+      return 32000;
+    case SampleRate_2_1::RATE_44100:
+      return 44100;
+    case SampleRate_2_1::RATE_48000:
+      return 48000;
+    case SampleRate_2_1::RATE_88200:
+      return 88200;
+    case SampleRate_2_1::RATE_96000:
+      return 96000;
+    case SampleRate_2_1::RATE_176400:
+      return 176400;
+    case SampleRate_2_1::RATE_192000:
+      return 192000;
+    default:
+      return kBluetoothDefaultSampleRate;
+  }
+}
+audio_channel_mask_t OutputChannelModeToAudioFormat(ChannelMode channel_mode) {
+  switch (channel_mode) {
+    case ChannelMode::MONO:
+      return AUDIO_CHANNEL_OUT_MONO;
+    case ChannelMode::STEREO:
+      return AUDIO_CHANNEL_OUT_STEREO;
+    default:
+      return kBluetoothDefaultOutputChannelModeMask;
+  }
+}
+
+audio_channel_mask_t InputChannelModeToAudioFormat(ChannelMode channel_mode) {
+  switch (channel_mode) {
+    case ChannelMode::MONO:
+      return AUDIO_CHANNEL_IN_MONO;
+    case ChannelMode::STEREO:
+      return AUDIO_CHANNEL_IN_STEREO;
+    default:
+      return kBluetoothDefaultInputChannelModeMask;
+  }
+}
+
+audio_format_t BitsPerSampleToAudioFormat(BitsPerSample bits_per_sample) {
+  switch (bits_per_sample) {
+    case BitsPerSample::BITS_16:
+      return AUDIO_FORMAT_PCM_16_BIT;
+    case BitsPerSample::BITS_24:
+      return AUDIO_FORMAT_PCM_24_BIT_PACKED;
+    case BitsPerSample::BITS_32:
+      return AUDIO_FORMAT_PCM_32_BIT;
+    default:
+      return kBluetoothDefaultAudioFormatBitsPerSample;
+  }
+}
+
+// The maximum time to wait in std::condition_variable::wait_for()
+constexpr unsigned int kMaxWaitingTimeMs = 4500;
+
+}  // namespace
+
+BluetoothAudioPortHidl::BluetoothAudioPortHidl()
+    : session_type_hidl_(SessionType_2_1::UNKNOWN),
+      cookie_(android::bluetooth::audio::kObserversCookieUndefined),
+      state_(BluetoothStreamState::DISABLED) {}
+
+BluetoothAudioPortHidlOut::~BluetoothAudioPortHidlOut() {
+  if (BluetoothAudioPortHidl::in_use()) BluetoothAudioPortHidl::TearDown();
+}
+
+BluetoothAudioPortHidlIn::~BluetoothAudioPortHidlIn() {
+  if (BluetoothAudioPortHidl::in_use()) BluetoothAudioPortHidl::TearDown();
+}
+
+bool BluetoothAudioPortHidl::SetUp(audio_devices_t devices) {
+  if (!init_session_type(devices)) return false;
+
+  state_ = BluetoothStreamState::STANDBY;
+
+  auto control_result_cb = [port = this](
+                               uint16_t cookie, bool start_resp,
+                               const BluetoothAudioStatusHidl& status) {
+    if (!port->in_use()) {
+      LOG(ERROR) << "control_result_cb: BluetoothAudioPort is not in use";
+      return;
+    }
+    if (port->cookie_ != cookie) {
+      LOG(ERROR) << "control_result_cb: proxy of device port (cookie="
+                 << StringPrintf("%#hx", cookie) << ") is corrupted";
+      return;
+    }
+    port->ControlResultHandler(status);
+  };
+  auto session_changed_cb = [port = this](uint16_t cookie) {
+    if (!port->in_use()) {
+      LOG(ERROR) << "session_changed_cb: BluetoothAudioPort is not in use";
+      return;
+    }
+    if (port->cookie_ != cookie) {
+      LOG(ERROR) << "session_changed_cb: proxy of device port (cookie="
+                 << StringPrintf("%#hx", cookie) << ") is corrupted";
+      return;
+    }
+    port->SessionChangedHandler();
+  };
+  ::android::bluetooth::audio::PortStatusCallbacks cbacks = {
+      .control_result_cb_ = control_result_cb,
+      .session_changed_cb_ = session_changed_cb};
+  cookie_ = BluetoothAudioSessionControl_2_1::RegisterControlResultCback(
+      session_type_hidl_, cbacks);
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_);
+
+  return (cookie_ != android::bluetooth::audio::kObserversCookieUndefined);
+}
+
+bool BluetoothAudioPortHidl::init_session_type(audio_devices_t device) {
+  switch (device) {
+    case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+    case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+    case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+      LOG(VERBOSE)
+          << __func__
+          << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
+          << StringPrintf("%#x", device) << ")";
+      session_type_hidl_ = SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH;
+      break;
+    case AUDIO_DEVICE_OUT_HEARING_AID:
+      LOG(VERBOSE) << __func__
+                   << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) ("
+                   << StringPrintf("%#x", device) << ")";
+      session_type_hidl_ =
+          SessionType_2_1::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
+      break;
+    case AUDIO_DEVICE_OUT_BLE_HEADSET:
+      LOG(VERBOSE) << __func__
+                   << ": device=AUDIO_DEVICE_OUT_BLE_HEADSET (MEDIA/VOICE) ("
+                   << StringPrintf("%#x", device) << ")";
+      session_type_hidl_ = SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+      break;
+    case AUDIO_DEVICE_OUT_BLE_SPEAKER:
+      LOG(VERBOSE) << __func__
+                   << ": device=AUDIO_DEVICE_OUT_BLE_SPEAKER (MEDIA) ("
+                   << StringPrintf("%#x", device) << ")";
+      session_type_hidl_ = SessionType_2_1::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH;
+      break;
+    case AUDIO_DEVICE_IN_BLE_HEADSET:
+      LOG(VERBOSE) << __func__
+                   << ": device=AUDIO_DEVICE_IN_BLE_HEADSET (VOICE) ("
+                   << StringPrintf("%#x", device) << ")";
+      session_type_hidl_ = SessionType_2_1::LE_AUDIO_SOFTWARE_DECODED_DATAPATH;
+      break;
+    default:
+      LOG(ERROR) << __func__
+                 << ": unknown device=" << StringPrintf("%#x", device);
+      return false;
+  }
+
+  if (!BluetoothAudioSessionControl_2_1::IsSessionReady(session_type_hidl_)) {
+    LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device)
+               << ", session_type=" << toString(session_type_hidl_)
+               << " is not ready";
+    return false;
+  }
+  return true;
+}
+
+void BluetoothAudioPortHidl::TearDown() {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_hidl_)
+               << ", cookie=" << StringPrintf("%#hx", cookie_)
+               << " unknown monitor";
+    return;
+  }
+
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_);
+  BluetoothAudioSessionControl_2_1::UnregisterControlResultCback(
+      session_type_hidl_, cookie_);
+  cookie_ = android::bluetooth::audio::kObserversCookieUndefined;
+}
+
+void BluetoothAudioPortHidl::ControlResultHandler(
+    const BluetoothAudioStatusHidl& status) {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortis not in use";
+    return;
+  }
+  std::unique_lock<std::mutex> port_lock(cv_mutex_);
+  BluetoothStreamState previous_state = state_;
+  LOG(INFO) << "control_result_cb: session_type="
+            << toString(session_type_hidl_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", previous_state=" << previous_state
+            << ", status=" << toString(status);
+
+  switch (previous_state) {
+    case BluetoothStreamState::STARTING:
+      if (status == BluetoothAudioStatusHidl::SUCCESS) {
+        state_ = BluetoothStreamState::STARTED;
+      } else {
+        // Set to standby since the stack may be busy switching between outputs
+        LOG(WARNING) << "control_result_cb: status=" << toString(status)
+                     << " failure for session_type="
+                     << toString(session_type_hidl_)
+                     << ", cookie=" << StringPrintf("%#hx", cookie_)
+                     << ", previous_state=" << previous_state;
+        state_ = BluetoothStreamState::STANDBY;
+      }
+      break;
+    case BluetoothStreamState::SUSPENDING:
+      if (status == BluetoothAudioStatusHidl::SUCCESS) {
+        state_ = BluetoothStreamState::STANDBY;
+      } else {
+        // It will be failed if the headset is disconnecting, and set to disable
+        // to wait for re-init again
+        LOG(WARNING) << "control_result_cb: status=" << toString(status)
+                     << " failure for session_type="
+                     << toString(session_type_hidl_)
+                     << ", cookie=" << StringPrintf("%#hx", cookie_)
+                     << ", previous_state=" << previous_state;
+        state_ = BluetoothStreamState::DISABLED;
+      }
+      break;
+    default:
+      LOG(ERROR) << "control_result_cb: unexpected status=" << toString(status)
+                 << " for session_type=" << toString(session_type_hidl_)
+                 << ", cookie=" << StringPrintf("%#hx", cookie_)
+                 << ", previous_state=" << previous_state;
+      return;
+  }
+  port_lock.unlock();
+  internal_cv_.notify_all();
+}
+
+void BluetoothAudioPortHidl::SessionChangedHandler() {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    return;
+  }
+  std::unique_lock<std::mutex> port_lock(cv_mutex_);
+  BluetoothStreamState previous_state = state_;
+  LOG(INFO) << "session_changed_cb: session_type="
+            << toString(session_type_hidl_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", previous_state=" << previous_state;
+  state_ = BluetoothStreamState::DISABLED;
+  port_lock.unlock();
+  internal_cv_.notify_all();
+}
+
+bool BluetoothAudioPortHidl::in_use() const {
+  return (cookie_ != android::bluetooth::audio::kObserversCookieUndefined);
+}
+
+bool BluetoothAudioPortHidl::GetPreferredDataIntervalUs(
+    size_t* interval_us) const {
+  if (!in_use()) {
+    return false;
+  }
+
+  const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration&
+      hal_audio_cfg =
+          BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_hidl_);
+  if (hal_audio_cfg.getDiscriminator() !=
+      ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
+          hidl_discriminator::pcmConfig) {
+    return false;
+  }
+
+  const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg =
+      hal_audio_cfg.pcmConfig();
+  *interval_us = pcm_cfg.dataIntervalUs;
+  return true;
+}
+
+bool BluetoothAudioPortHidl::CondwaitState(BluetoothStreamState state) {
+  bool retval;
+  std::unique_lock<std::mutex> port_lock(cv_mutex_);
+  switch (state) {
+    case BluetoothStreamState::STARTING:
+      LOG(VERBOSE) << __func__
+                   << ": session_type=" << toString(session_type_hidl_)
+                   << ", cookie=" << StringPrintf("%#hx", cookie_)
+                   << " waiting for STARTED";
+      retval = internal_cv_.wait_for(
+          port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
+          [this] { return this->state_ != BluetoothStreamState::STARTING; });
+      retval = retval && state_ == BluetoothStreamState::STARTED;
+      break;
+    case BluetoothStreamState::SUSPENDING:
+      LOG(VERBOSE) << __func__
+                   << ": session_type=" << toString(session_type_hidl_)
+                   << ", cookie=" << StringPrintf("%#hx", cookie_)
+                   << " waiting for SUSPENDED";
+      retval = internal_cv_.wait_for(
+          port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
+          [this] { return this->state_ != BluetoothStreamState::SUSPENDING; });
+      retval = retval && state_ == BluetoothStreamState::STANDBY;
+      break;
+    default:
+      LOG(WARNING) << __func__
+                   << ": session_type=" << toString(session_type_hidl_)
+                   << ", cookie=" << StringPrintf("%#hx", cookie_)
+                   << " waiting for KNOWN";
+      return false;
+  }
+
+  return retval;  // false if any failure like timeout
+}
+
+bool BluetoothAudioPortHidl::Start() {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    return false;
+  }
+
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", state=" << state_
+            << ", mono=" << (is_stereo_to_mono_ ? "true" : "false")
+            << " request";
+  bool retval = false;
+  if (state_ == BluetoothStreamState::STANDBY) {
+    state_ = BluetoothStreamState::STARTING;
+    if (BluetoothAudioSessionControl_2_1::StartStream(session_type_hidl_)) {
+      retval = CondwaitState(BluetoothStreamState::STARTING);
+    } else {
+      LOG(ERROR) << __func__
+                 << ": session_type=" << toString(session_type_hidl_)
+                 << ", cookie=" << StringPrintf("%#hx", cookie_)
+                 << ", state=" << state_ << " Hal fails";
+    }
+  }
+
+  if (retval) {
+    LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
+              << ", cookie=" << StringPrintf("%#hx", cookie_)
+              << ", state=" << state_
+              << ", mono=" << (is_stereo_to_mono_ ? "true" : "false")
+              << " done";
+  } else {
+    LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_hidl_)
+               << ", cookie=" << StringPrintf("%#hx", cookie_)
+               << ", state=" << state_ << " failure";
+  }
+
+  return retval;  // false if any failure like timeout
+}
+
+bool BluetoothAudioPortHidl::Suspend() {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    return false;
+  }
+
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", state=" << state_ << " request";
+  bool retval = false;
+  if (state_ == BluetoothStreamState::STARTED) {
+    state_ = BluetoothStreamState::SUSPENDING;
+    if (BluetoothAudioSessionControl_2_1::SuspendStream(session_type_hidl_)) {
+      retval = CondwaitState(BluetoothStreamState::SUSPENDING);
+    } else {
+      LOG(ERROR) << __func__
+                 << ": session_type=" << toString(session_type_hidl_)
+                 << ", cookie=" << StringPrintf("%#hx", cookie_)
+                 << ", state=" << state_ << " Hal fails";
+    }
+  }
+
+  if (retval) {
+    LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
+              << ", cookie=" << StringPrintf("%#hx", cookie_)
+              << ", state=" << state_ << " done";
+  } else {
+    LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_hidl_)
+               << ", cookie=" << StringPrintf("%#hx", cookie_)
+               << ", state=" << state_ << " failure";
+  }
+
+  return retval;  // false if any failure like timeout
+}
+
+void BluetoothAudioPortHidl::Stop() {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    return;
+  }
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", state=" << state_ << " request";
+  state_ = BluetoothStreamState::DISABLED;
+  BluetoothAudioSessionControl_2_1::StopStream(session_type_hidl_);
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_hidl_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", state=" << state_ << " done";
+}
+
+bool BluetoothAudioPortHidl::GetPresentationPosition(
+    uint64_t* delay_ns, uint64_t* bytes, timespec* timestamp) const {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    return false;
+  }
+  bool retval = BluetoothAudioSessionControl_2_1::GetPresentationPosition(
+      session_type_hidl_, delay_ns, bytes, timestamp);
+  LOG(VERBOSE) << __func__
+               << ": session_type=" << StringPrintf("%#hhx", session_type_hidl_)
+               << ", cookie=" << StringPrintf("%#hx", cookie_)
+               << ", state=" << state_ << ", delay=" << *delay_ns
+               << "ns, data=" << *bytes
+               << " bytes, timestamp=" << timestamp->tv_sec << "."
+               << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
+
+  return retval;
+}
+
+void BluetoothAudioPortHidl::UpdateSourceMetadata(
+    const source_metadata* source_metadata) const {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPort is not in use";
+    return;
+  }
+  LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_hidl_)
+             << ", cookie=" << StringPrintf("%#hx", cookie_)
+             << ", state=" << state_ << ", " << source_metadata->track_count
+             << " track(s)";
+  if (source_metadata->track_count == 0) return;
+  BluetoothAudioSessionControl_2_1::UpdateTracksMetadata(session_type_hidl_,
+                                                         source_metadata);
+}
+
+BluetoothStreamState BluetoothAudioPortHidl::GetState() const { return state_; }
+
+void BluetoothAudioPortHidl::SetState(BluetoothStreamState state) {
+  state_ = state;
+}
+
+size_t BluetoothAudioPortHidlOut::WriteData(const void* buffer,
+                                            size_t bytes) const {
+  if (!BluetoothAudioPortHidl::in_use()) return 0;
+  if (!BluetoothAudioPortHidl::is_stereo_to_mono_) {
+    return BluetoothAudioSessionControl_2_1::OutWritePcmData(session_type_hidl_,
+                                                             buffer, bytes);
+  }
+
+  // WAR to mix the stereo into Mono (16 bits per sample)
+  const size_t write_frames = bytes >> 2;
+  if (write_frames == 0) return 0;
+  auto src = static_cast<const int16_t*>(buffer);
+  std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
+  downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
+  // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
+  return BluetoothAudioSessionControl_2_1::OutWritePcmData(
+             session_type_hidl_, dst.get(), write_frames * 2) *
+         2;
+}
+
+size_t BluetoothAudioPortHidlIn::ReadData(void* buffer, size_t bytes) const {
+  if (!BluetoothAudioPortHidl::in_use()) return 0;
+  return BluetoothAudioSessionControl_2_1::InReadPcmData(session_type_hidl_,
+                                                         buffer, bytes);
+}
+
+bool BluetoothAudioPortHidlIn::LoadAudioConfig(
+    audio_config_t* audio_cfg) const {
+  if (!BluetoothAudioPortHidl::in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortIn is not in use";
+    audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
+    audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
+    audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
+    return false;
+  }
+
+  const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration&
+      hal_audio_cfg =
+          BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_hidl_);
+  if (hal_audio_cfg.getDiscriminator() !=
+      ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
+          hidl_discriminator::pcmConfig) {
+    audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
+    audio_cfg->channel_mask = kBluetoothDefaultInputChannelModeMask;
+    audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
+    return false;
+  }
+  const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg =
+      hal_audio_cfg.pcmConfig();
+  LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_hidl_)
+               << ", cookie="
+               << StringPrintf("%#hx", BluetoothAudioPortHidl::cookie_)
+               << ", state=" << BluetoothAudioPortHidl::state_
+               << ", PcmConfig=[" << toString(pcm_cfg) << "]";
+  if (pcm_cfg.sampleRate == SampleRate_2_1::RATE_UNKNOWN ||
+      pcm_cfg.channelMode == ChannelMode::UNKNOWN ||
+      pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
+    return false;
+  }
+
+  audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate);
+  audio_cfg->channel_mask = InputChannelModeToAudioFormat(pcm_cfg.channelMode);
+  audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample);
+  return true;
+}
+
+bool BluetoothAudioPortHidlOut::LoadAudioConfig(
+    audio_config_t* audio_cfg) const {
+  if (!BluetoothAudioPortHidl::in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
+    audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
+    audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
+    audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
+    return false;
+  }
+
+  const ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration&
+      hal_audio_cfg =
+          BluetoothAudioSessionControl_2_1::GetAudioConfig(session_type_hidl_);
+  if (hal_audio_cfg.getDiscriminator() !=
+      ::android::hardware::bluetooth::audio::V2_1::AudioConfiguration::
+          hidl_discriminator::pcmConfig) {
+    audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
+    audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
+    audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
+    return false;
+  }
+  const ::android::hardware::bluetooth::audio::V2_1::PcmParameters& pcm_cfg =
+      hal_audio_cfg.pcmConfig();
+  LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_hidl_)
+               << ", cookie="
+               << StringPrintf("%#hx", BluetoothAudioPortHidl::cookie_)
+               << ", state=" << BluetoothAudioPortHidl::state_
+               << ", PcmConfig=[" << toString(pcm_cfg) << "]";
+  if (pcm_cfg.sampleRate == SampleRate_2_1::RATE_UNKNOWN ||
+      pcm_cfg.channelMode == ChannelMode::UNKNOWN ||
+      pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
+    return false;
+  }
+  audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate);
+  audio_cfg->channel_mask =
+      (BluetoothAudioPortHidl::is_stereo_to_mono_
+           ? AUDIO_CHANNEL_OUT_STEREO
+           : OutputChannelModeToAudioFormat(pcm_cfg.channelMode));
+  audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample);
+  return true;
+}
+
+}  // namespace hidl
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace android
\ No newline at end of file
diff --git a/system/audio_bluetooth_hw/device_port_proxy_hidl.h b/system/audio_bluetooth_hw/device_port_proxy_hidl.h
new file mode 100644
index 0000000..f37370d
--- /dev/null
+++ b/system/audio_bluetooth_hw/device_port_proxy_hidl.h
@@ -0,0 +1,116 @@
+/*
+ * Copyright 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 <android/hardware/bluetooth/audio/2.1/types.h>
+#include <hardware/audio.h>
+
+#include <condition_variable>
+#include <mutex>
+#include <unordered_map>
+
+#include "device_port_proxy.h"
+
+enum class BluetoothStreamState : uint8_t;
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+namespace hidl {
+
+using SessionType_2_1 =
+    ::android::hardware::bluetooth::audio::V2_1::SessionType;
+
+class BluetoothAudioPortHidl : public BluetoothAudioPort {
+ public:
+  BluetoothAudioPortHidl();
+  virtual ~BluetoothAudioPortHidl() = default;
+
+  bool SetUp(audio_devices_t devices) override;
+
+  void TearDown() override;
+
+  void ForcePcmStereoToMono(bool force) override { is_stereo_to_mono_ = force; }
+
+  bool Start() override;
+
+  bool Suspend() override;
+
+  void Stop() override;
+
+  bool GetPresentationPosition(uint64_t* delay_ns, uint64_t* bytes,
+                               timespec* timestamp) const override;
+
+  void UpdateSourceMetadata(
+      const source_metadata* source_metadata) const override;
+
+  BluetoothStreamState GetState() const override;
+
+  void SetState(BluetoothStreamState state) override;
+
+  bool IsA2dp() const override {
+    return session_type_hidl_ ==
+               SessionType_2_1::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+           session_type_hidl_ ==
+               SessionType_2_1::A2DP_HARDWARE_OFFLOAD_DATAPATH;
+  }
+
+  bool GetPreferredDataIntervalUs(size_t* interval_us) const override;
+
+ protected:
+  SessionType_2_1 session_type_hidl_;
+  uint16_t cookie_;
+  BluetoothStreamState state_;
+  // WR to support Mono: True if fetching Stereo and mixing into Mono
+  bool is_stereo_to_mono_ = false;
+
+  bool in_use() const;
+
+ private:
+  mutable std::mutex cv_mutex_;
+  std::condition_variable internal_cv_;
+
+  bool init_session_type(audio_devices_t device);
+
+  bool CondwaitState(BluetoothStreamState state);
+
+  void ControlResultHandler(
+      const ::android::hardware::bluetooth::audio::V2_0::Status& status);
+
+  void SessionChangedHandler();
+};
+
+class BluetoothAudioPortHidlOut : public BluetoothAudioPortHidl {
+ public:
+  ~BluetoothAudioPortHidlOut();
+
+  size_t WriteData(const void* buffer, size_t bytes) const override;
+  bool LoadAudioConfig(audio_config_t* audio_cfg) const override;
+};
+
+class BluetoothAudioPortHidlIn : public BluetoothAudioPortHidl {
+ public:
+  ~BluetoothAudioPortHidlIn();
+
+  size_t ReadData(void* buffer, size_t bytes) const override;
+  bool LoadAudioConfig(audio_config_t* audio_cfg) const override;
+};
+
+}  // namespace hidl
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace android
\ No newline at end of file
diff --git a/system/audio_bluetooth_hw/stream_apis.cc b/system/audio_bluetooth_hw/stream_apis.cc
index 77e1bb0..5bc9923 100644
--- a/system/audio_bluetooth_hw/stream_apis.cc
+++ b/system/audio_bluetooth_hw/stream_apis.cc
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "device_port_proxy.h"
 #define LOG_TAG "BTAudioHalStream"
 
 #include <android-base/logging.h>
@@ -26,11 +27,11 @@
 #include <time.h>
 #include <unistd.h>
 
+#include "BluetoothAudioSession.h"
 #include "stream_apis.h"
 #include "utils.h"
 
 using ::android::base::StringPrintf;
-using ::android::bluetooth::audio::BluetoothAudioPortOut;
 using ::android::bluetooth::audio::utils::GetAudioParamString;
 using ::android::bluetooth::audio::utils::ParseAudioParams;
 
@@ -66,7 +67,7 @@
   bool timestamp_fetched = false;
 
   std::unique_lock<std::mutex> lock(out->mutex_);
-  if (out->bluetooth_output_.GetPresentationPosition(
+  if (out->bluetooth_output_->GetPresentationPosition(
           &delay_report_ns, &absorbed_bytes, &absorbed_timestamp)) {
     delay_report_ms = delay_report_ns / 1000000;
     // assume kMinimumDelayMs (50ms) < delay_report_ns < kMaximumDelayMs
@@ -76,7 +77,7 @@
         delay_report_ms < kMaximumDelayMs) {
       timestamp_fetched = true;
     } else if (delay_report_ms >= kMaximumDelayMs) {
-      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                 << ", delay_report=" << delay_report_ns << "ns abnormal";
     }
   }
@@ -91,10 +92,10 @@
     if (timestamp != nullptr) {
       clock_gettime(CLOCK_MONOTONIC, &absorbed_timestamp);
     }
-    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                  << " uses the legacy delay " << delay_report_ms << " ms";
   }
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", delay=" << delay_report_ms << "ms, data=" << absorbed_bytes
                << " bytes, timestamp=" << absorbed_timestamp.tv_sec << "."
                << StringPrintf("%09ld", absorbed_timestamp.tv_nsec) << "s";
@@ -139,14 +140,14 @@
   struct timespec dispersed_timestamp = {};
 
   std::unique_lock<std::mutex> lock(in->mutex_);
-  in->bluetooth_input_.GetPresentationPosition(
+  in->bluetooth_input_->GetPresentationPosition(
       &delay_report_ns, &dispersed_bytes, &dispersed_timestamp);
   delay_report_ms = delay_report_ns / 1000000;
 
   const uint64_t latency_frames = delay_report_ms * in->sample_rate_ / 1000;
   *frames = dispersed_bytes / audio_stream_in_frame_size(&in->stream_in_);
 
-  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << ", delay=" << delay_report_ms
                << "ms, data=" << dispersed_bytes
                << " bytes, timestamp=" << dispersed_timestamp.tv_sec << "."
@@ -198,12 +199,12 @@
 static uint32_t out_get_sample_rate(const struct audio_stream* stream) {
   const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
   audio_config_t audio_cfg;
-  if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) {
-    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  if (out->bluetooth_output_->LoadAudioConfig(&audio_cfg)) {
+    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                  << " audio_cfg=" << audio_cfg;
     return audio_cfg.sample_rate;
   } else {
-    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                  << ", sample_rate=" << out->sample_rate_ << " failed";
     return out->sample_rate_;
   }
@@ -211,7 +212,7 @@
 
 static int out_set_sample_rate(struct audio_stream* stream, uint32_t rate) {
   auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", sample_rate=" << out->sample_rate_;
   return (rate == out->sample_rate_ ? 0 : -1);
 }
@@ -220,7 +221,7 @@
   const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
   size_t buffer_size =
       out->frames_count_ * audio_stream_out_frame_size(&out->stream_out_);
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", buffer_size=" << buffer_size;
   return buffer_size;
 }
@@ -229,13 +230,14 @@
     const struct audio_stream* stream) {
   const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
   audio_config_t audio_cfg;
-  if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) {
-    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  if (out->bluetooth_output_->LoadAudioConfig(&audio_cfg)) {
+    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                  << " audio_cfg=" << audio_cfg;
     return audio_cfg.channel_mask;
   } else {
-    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
-                 << ", channels=" << StringPrintf("%#x", out->channel_mask_) << " failure";
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState()
+                 << ", channels=" << StringPrintf("%#x", out->channel_mask_)
+                 << " failure";
     return out->channel_mask_;
   }
 }
@@ -243,12 +245,12 @@
 static audio_format_t out_get_format(const struct audio_stream* stream) {
   const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
   audio_config_t audio_cfg;
-  if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) {
-    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  if (out->bluetooth_output_->LoadAudioConfig(&audio_cfg)) {
+    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                  << " audio_cfg=" << audio_cfg;
     return audio_cfg.format;
   } else {
-    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                  << ", format=" << out->format_ << " failure";
     return out->format_;
   }
@@ -256,7 +258,7 @@
 
 static int out_set_format(struct audio_stream* stream, audio_format_t format) {
   auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", format=" << out->format_;
   return (format == out->format_ ? 0 : -1);
 }
@@ -268,23 +270,23 @@
 
   // out->last_write_time_us_ = 0; unnecessary as a stale write time has same
   // effect
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << " being standby (suspend)";
-  if (out->bluetooth_output_.GetState() == BluetoothStreamState::STARTED) {
+  if (out->bluetooth_output_->GetState() == BluetoothStreamState::STARTED) {
     out->frames_rendered_ = 0;
-    retval = (out->bluetooth_output_.Suspend() ? 0 : -EIO);
-  } else if (out->bluetooth_output_.GetState() ==
+    retval = (out->bluetooth_output_->Suspend() ? 0 : -EIO);
+  } else if (out->bluetooth_output_->GetState() ==
                  BluetoothStreamState::STARTING ||
-             out->bluetooth_output_.GetState() ==
+             out->bluetooth_output_->GetState() ==
                  BluetoothStreamState::SUSPENDING) {
-    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                  << " NOT ready to be standby";
     retval = -EBUSY;
   } else {
-    LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+    LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << " standby already";
   }
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << " standby (suspend) retval=" << retval;
 
   return retval;
@@ -292,7 +294,7 @@
 
 static int out_dump(const struct audio_stream* stream, int fd) {
   const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState();
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState();
   return 0;
 }
 
@@ -302,7 +304,7 @@
   std::unique_lock<std::mutex> lock(out->mutex_);
   int retval = 0;
 
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", kvpairs=[" << kvpairs << "]";
 
   std::unordered_map<std::string, std::string> params =
@@ -316,73 +318,78 @@
   if (params.find(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES) != params.end() ||
       params.find(AUDIO_PARAMETER_STREAM_SUP_CHANNELS) != params.end() ||
       params.find(AUDIO_PARAMETER_STREAM_SUP_FORMATS) != params.end()) {
-    if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) {
+    if (out->bluetooth_output_->LoadAudioConfig(&audio_cfg)) {
       out->sample_rate_ = audio_cfg.sample_rate;
       out->channel_mask_ = audio_cfg.channel_mask;
       out->format_ = audio_cfg.format;
-      LOG(VERBOSE) << "state=" << out->bluetooth_output_.GetState() << ", sample_rate=" << out->sample_rate_
-                   << ", channels=" << StringPrintf("%#x", out->channel_mask_) << ", format=" << out->format_;
+      LOG(VERBOSE) << "state=" << out->bluetooth_output_->GetState()
+                   << ", sample_rate=" << out->sample_rate_
+                   << ", channels=" << StringPrintf("%#x", out->channel_mask_)
+                   << ", format=" << out->format_;
     } else {
       LOG(WARNING) << __func__
-                   << ": state=" << out->bluetooth_output_.GetState()
+                   << ": state=" << out->bluetooth_output_->GetState()
                    << " failed to get audio config";
     }
   }
 
   if (params.find("routing") != params.end()) {
     auto routing_param = params.find("routing");
-    LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+    LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState()
               << ", stream param '" << routing_param->first.c_str() << "="
               << routing_param->second.c_str() << "'";
   }
 
   if (params.find("A2dpSuspended") != params.end() &&
-      out->bluetooth_output_.IsA2dp()) {
+      out->bluetooth_output_->IsA2dp()) {
     if (params["A2dpSuspended"] == "true") {
-      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                 << " stream param stopped";
       out->frames_rendered_ = 0;
-      if (out->bluetooth_output_.GetState() == BluetoothStreamState::STARTED) {
-        out->bluetooth_output_.Suspend();
-        out->bluetooth_output_.SetState(BluetoothStreamState::DISABLED);
-      } else if (out->bluetooth_output_.GetState() !=
+      if (out->bluetooth_output_->GetState() == BluetoothStreamState::STARTED) {
+        out->bluetooth_output_->Suspend();
+        out->bluetooth_output_->SetState(BluetoothStreamState::DISABLED);
+      } else if (out->bluetooth_output_->GetState() !=
                  BluetoothStreamState::DISABLED) {
-        out->bluetooth_output_.Stop();
+        out->bluetooth_output_->Stop();
       }
     } else {
-      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                 << " stream param standby";
-      if (out->bluetooth_output_.GetState() == BluetoothStreamState::DISABLED) {
-        out->bluetooth_output_.SetState(BluetoothStreamState::STANDBY);
+      if (out->bluetooth_output_->GetState() ==
+          BluetoothStreamState::DISABLED) {
+        out->bluetooth_output_->SetState(BluetoothStreamState::STANDBY);
       }
     }
   }
 
   if (params.find("closing") != params.end()) {
     if (params["closing"] == "true") {
-      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                 << " stream param closing, disallow any writes?";
-      if (out->bluetooth_output_.GetState() != BluetoothStreamState::DISABLED) {
+      if (out->bluetooth_output_->GetState() !=
+          BluetoothStreamState::DISABLED) {
         out->frames_rendered_ = 0;
         out->frames_presented_ = 0;
-        out->bluetooth_output_.Stop();
+        out->bluetooth_output_->Stop();
       }
     }
   }
 
   if (params.find("exiting") != params.end()) {
     if (params["exiting"] == "1") {
-      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                 << " stream param exiting";
-      if (out->bluetooth_output_.GetState() != BluetoothStreamState::DISABLED) {
+      if (out->bluetooth_output_->GetState() !=
+          BluetoothStreamState::DISABLED) {
         out->frames_rendered_ = 0;
         out->frames_presented_ = 0;
-        out->bluetooth_output_.Stop();
+        out->bluetooth_output_->Stop();
       }
     }
   }
 
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", kvpairs=[" << kvpairs << "], retval=" << retval;
   return retval;
 }
@@ -392,18 +399,18 @@
   const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
   std::unique_lock<std::mutex> lock(out->mutex_);
 
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", keys=[" << keys << "]";
 
   std::unordered_map<std::string, std::string> params = ParseAudioParams(keys);
   if (params.empty()) return strdup("");
 
   audio_config_t audio_cfg;
-  if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) {
-    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  if (out->bluetooth_output_->LoadAudioConfig(&audio_cfg)) {
+    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                  << " audio_cfg=" << audio_cfg;
   } else {
-    LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+    LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << " failed to get audio config";
   }
 
@@ -467,7 +474,7 @@
     result += ptr.first + "=" + ptr.second + ";";
   }
 
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", result=[" << result << "]";
   return strdup(result.c_str());
 }
@@ -476,7 +483,7 @@
   const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
   uint32_t latency_ms = 0;
   out_calculate_feeding_delay_ms(out, &latency_ms);
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", latency=" << latency_ms << "ms";
   return latency_ms;
 }
@@ -484,7 +491,7 @@
 static int out_set_volume(struct audio_stream_out* stream, float left,
                           float right) {
   auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", Left=" << left << ", Right=" << right;
   return -1;
 }
@@ -495,14 +502,15 @@
   std::unique_lock<std::mutex> lock(out->mutex_);
   size_t totalWritten = 0;
 
-  if (out->bluetooth_output_.GetState() != BluetoothStreamState::STARTED) {
-    LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  if (out->bluetooth_output_->GetState() != BluetoothStreamState::STARTED) {
+    LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState()
               << " first time bytes=" << bytes;
     lock.unlock();
     if (stream->resume(stream)) {
-      LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+      LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                  << " failed to resume";
-      if (out->bluetooth_output_.GetState() == BluetoothStreamState::DISABLED) {
+      if (out->bluetooth_output_->GetState() ==
+          BluetoothStreamState::DISABLED) {
         // drop data for cases of A2dpSuspended=true / closing=true
         totalWritten = bytes;
       }
@@ -512,7 +520,7 @@
     lock.lock();
   }
   lock.unlock();
-  totalWritten = out->bluetooth_output_.WriteData(buffer, bytes);
+  totalWritten = out->bluetooth_output_->WriteData(buffer, bytes);
   lock.lock();
 
   struct timespec ts = {.tv_sec = 0, .tv_nsec = 0};
@@ -563,7 +571,7 @@
     *dsp_frames = 0;
   }
 
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", dsp_frames=" << *dsp_frames;
   return 0;
 }
@@ -571,7 +579,7 @@
 static int out_add_audio_effect(const struct audio_stream* stream,
                                 effect_handle_t effect) {
   const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", effect=" << effect;
   return 0;
 }
@@ -579,7 +587,7 @@
 static int out_remove_audio_effect(const struct audio_stream* stream,
                                    effect_handle_t effect) {
   const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", effect=" << effect;
   return 0;
 }
@@ -588,7 +596,7 @@
                                         int64_t* timestamp) {
   const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
   *timestamp = 0;
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", timestamp=" << *timestamp;
   return -EINVAL;
 }
@@ -597,23 +605,23 @@
   auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
   std::unique_lock<std::mutex> lock(out->mutex_);
   int retval = 0;
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", pausing (suspend)";
-  if (out->bluetooth_output_.GetState() == BluetoothStreamState::STARTED) {
+  if (out->bluetooth_output_->GetState() == BluetoothStreamState::STARTED) {
     out->frames_rendered_ = 0;
-    retval = (out->bluetooth_output_.Suspend() ? 0 : -EIO);
-  } else if (out->bluetooth_output_.GetState() ==
+    retval = (out->bluetooth_output_->Suspend() ? 0 : -EIO);
+  } else if (out->bluetooth_output_->GetState() ==
                  BluetoothStreamState::STARTING ||
-             out->bluetooth_output_.GetState() ==
+             out->bluetooth_output_->GetState() ==
                  BluetoothStreamState::SUSPENDING) {
-    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                  << " NOT ready to pause?!";
     retval = -EBUSY;
   } else {
-    LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+    LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << " paused already";
   }
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", pausing (suspend) retval=" << retval;
 
   return retval;
@@ -624,27 +632,27 @@
   std::unique_lock<std::mutex> lock(out->mutex_);
   int retval = 0;
 
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", resuming (start)";
-  if (out->bluetooth_output_.GetState() == BluetoothStreamState::STANDBY) {
-    retval = (out->bluetooth_output_.Start() ? 0 : -EIO);
-  } else if (out->bluetooth_output_.GetState() ==
+  if (out->bluetooth_output_->GetState() == BluetoothStreamState::STANDBY) {
+    retval = (out->bluetooth_output_->Start() ? 0 : -EIO);
+  } else if (out->bluetooth_output_->GetState() ==
                  BluetoothStreamState::STARTING ||
-             out->bluetooth_output_.GetState() ==
+             out->bluetooth_output_->GetState() ==
                  BluetoothStreamState::SUSPENDING) {
-    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                  << " NOT ready to resume?!";
     retval = -EBUSY;
-  } else if (out->bluetooth_output_.GetState() ==
+  } else if (out->bluetooth_output_->GetState() ==
              BluetoothStreamState::DISABLED) {
-    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                  << " NOT allow to resume?!";
     retval = -EINVAL;
   } else {
-    LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+    LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << " resumed already";
   }
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", resuming (start) retval=" << retval;
 
   return retval;
@@ -659,7 +667,7 @@
 
   const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
   out_calculate_feeding_delay_ms(out, nullptr, frames, timestamp);
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", frames=" << *frames << ", timestamp=" << timestamp->tv_sec
                << "." << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
   return 0;
@@ -673,9 +681,9 @@
   if (source_metadata == nullptr || source_metadata->track_count == 0) {
     return;
   }
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", " << source_metadata->track_count << " track(s)";
-  out->bluetooth_output_.UpdateMetadata(source_metadata);
+  out->bluetooth_output_->UpdateSourceMetadata(source_metadata);
 }
 
 static size_t frame_count(size_t microseconds, uint32_t sample_rate) {
@@ -690,7 +698,19 @@
                             const char* address __unused) {
   *stream_out = nullptr;
   auto* out = new BluetoothStreamOut{};
-  if (!out->bluetooth_output_.SetUp(devices)) {
+  if (::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession::
+          IsAidlAvailable()) {
+    out->bluetooth_output_ = std::make_unique<
+        ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlOut>();
+    out->is_aidl = true;
+  } else {
+    out->bluetooth_output_ = std::make_unique<
+        ::android::bluetooth::audio::hidl::BluetoothAudioPortHidlOut>();
+    out->is_aidl = false;
+  }
+  if (!out->bluetooth_output_->SetUp(devices)) {
+    out->bluetooth_output_ = nullptr;
+    LOG(ERROR) << __func__ << ": cannot init HAL";
     delete out;
     return -EINVAL;
   }
@@ -718,15 +738,17 @@
   out->stream_out_.get_presentation_position = out_get_presentation_position;
   out->stream_out_.update_source_metadata = out_update_source_metadata;
 
-  if (!out->bluetooth_output_.LoadAudioConfig(config)) {
-    LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  if (!out->bluetooth_output_->LoadAudioConfig(config)) {
+    LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << " failed to get audio config";
   }
   // WAR to support Mono / 16 bits per sample as the Bluetooth stack required
-  if (config->channel_mask == AUDIO_CHANNEL_OUT_MONO && config->format == AUDIO_FORMAT_PCM_16_BIT) {
-    LOG(INFO) << __func__ << ": force channels=" << StringPrintf("%#x", out->channel_mask_)
+  if (config->channel_mask == AUDIO_CHANNEL_OUT_MONO &&
+      config->format == AUDIO_FORMAT_PCM_16_BIT) {
+    LOG(INFO) << __func__
+              << ": force channels=" << StringPrintf("%#x", out->channel_mask_)
               << " to be AUDIO_CHANNEL_OUT_STEREO";
-    out->bluetooth_output_.ForcePcmStereoToMono(true);
+    out->bluetooth_output_->ForcePcmStereoToMono(true);
     config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
   }
   out->sample_rate_ = config->sample_rate;
@@ -735,7 +757,7 @@
   // frame is number of samples per channel
 
   size_t preferred_data_interval_us = kBluetoothDefaultOutputBufferMs * 1000;
-  if (out->bluetooth_output_.GetPreferredDataIntervalUs(
+  if (out->bluetooth_output_->GetPreferredDataIntervalUs(
           &preferred_data_interval_us) &&
       preferred_data_interval_us != 0) {
     out->preferred_data_interval_us = preferred_data_interval_us;
@@ -766,11 +788,11 @@
     bluetooth_device->opened_stream_outs_.push_back(out);
   }
   *stream_out = &out->stream_out_;
-  LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_->GetState()
             << ", sample_rate=" << out->sample_rate_
             << ", channels=" << StringPrintf("%#x", out->channel_mask_)
-            << ", format=" << out->format_
-            << ", preferred_data_interval_us=" << out->preferred_data_interval_us
+            << ", format=" << out->format_ << ", preferred_data_interval_us="
+            << out->preferred_data_interval_us
             << ", frames=" << out->frames_count_;
   return 0;
 }
@@ -778,20 +800,20 @@
 void adev_close_output_stream(struct audio_hw_device* dev,
                               struct audio_stream_out* stream) {
   auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", stopping";
   {
     auto* bluetooth_device = reinterpret_cast<BluetoothAudioDevice*>(dev);
     std::lock_guard<std::mutex> guard(bluetooth_device->mutex_);
     bluetooth_device->opened_stream_outs_.remove(out);
   }
-  if (out->bluetooth_output_.GetState() != BluetoothStreamState::DISABLED) {
+  if (out->bluetooth_output_->GetState() != BluetoothStreamState::DISABLED) {
     out->frames_rendered_ = 0;
     out->frames_presented_ = 0;
-    out->bluetooth_output_.Stop();
+    out->bluetooth_output_->Stop();
   }
-  out->bluetooth_output_.TearDown();
-  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+  out->bluetooth_output_->TearDown();
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_->GetState()
                << ", stopped";
   delete out;
 }
@@ -812,7 +834,7 @@
 static int in_set_sample_rate(struct audio_stream* stream, uint32_t rate) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
 
-  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << ", sample_rate=" << in->sample_rate_;
   return (rate == in->sample_rate_ ? 0 : -ENOSYS);
 }
@@ -821,7 +843,7 @@
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
   size_t buffer_size =
       in->frames_count_ * audio_stream_in_frame_size(&in->stream_in_);
-  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << ", buffer_size=" << buffer_size;
   return buffer_size;
 }
@@ -829,12 +851,12 @@
 static audio_channel_mask_t in_get_channels(const struct audio_stream* stream) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
   audio_config_t audio_cfg;
-  if (in->bluetooth_input_.LoadAudioConfig(&audio_cfg)) {
-    LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  if (in->bluetooth_input_->LoadAudioConfig(&audio_cfg)) {
+    LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                  << " audio_cfg=" << audio_cfg;
     return audio_cfg.channel_mask;
   } else {
-    LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+    LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                  << ", channels=" << StringPrintf("%#x", in->channel_mask_)
                  << " failure";
     return in->channel_mask_;
@@ -844,12 +866,12 @@
 static audio_format_t in_get_format(const struct audio_stream* stream) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
   audio_config_t audio_cfg;
-  if (in->bluetooth_input_.LoadAudioConfig(&audio_cfg)) {
-    LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  if (in->bluetooth_input_->LoadAudioConfig(&audio_cfg)) {
+    LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                  << " audio_cfg=" << audio_cfg;
     return audio_cfg.format;
   } else {
-    LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+    LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                  << ", format=" << in->format_ << " failure";
     return in->format_;
   }
@@ -857,7 +879,7 @@
 
 static int in_set_format(struct audio_stream* stream, audio_format_t format) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
-  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << ", format=" << in->format_;
   return (format == in->format_ ? 0 : -ENOSYS);
 }
@@ -867,7 +889,7 @@
                                         const BluetoothStreamState& state,
                                         uint16_t timeout_ms) {
   /* Don't loose suspend request, AF will not retry */
-  while (in->bluetooth_input_.GetState() == state) {
+  while (in->bluetooth_input_->GetState() == state) {
     lock.unlock();
     usleep(1000);
     lock.lock();
@@ -888,22 +910,22 @@
   std::unique_lock<std::mutex> lock(in->mutex_);
   int retval = 0;
 
-  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << " being standby (suspend)";
 
   /* Give some time to start up */
   if (!in_state_transition_timeout(in, lock, BluetoothStreamState::STARTING,
                                    kBluetoothDefaultInputStateTimeoutMs)) {
-    LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+    LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << " NOT ready to by standby";
     return retval;
   }
 
-  if (in->bluetooth_input_.GetState() == BluetoothStreamState::STARTED) {
-    retval = (in->bluetooth_input_.Suspend() ? 0 : -EIO);
-  } else if (in->bluetooth_input_.GetState() !=
+  if (in->bluetooth_input_->GetState() == BluetoothStreamState::STARTED) {
+    retval = (in->bluetooth_input_->Suspend() ? 0 : -EIO);
+  } else if (in->bluetooth_input_->GetState() !=
              BluetoothStreamState::SUSPENDING) {
-    LOG(DEBUG) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+    LOG(DEBUG) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << " standby already";
     return retval;
   }
@@ -911,12 +933,12 @@
   /* Give some time to suspend */
   if (!in_state_transition_timeout(in, lock, BluetoothStreamState::SUSPENDING,
                                    kBluetoothDefaultInputStateTimeoutMs)) {
-    LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+    LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << " NOT ready to by standby";
     return 0;
   }
 
-  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << " standby (suspend) retval=" << retval;
 
   return retval;
@@ -924,7 +946,7 @@
 
 static int in_dump(const struct audio_stream* stream, int fd) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
-  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState();
+  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState();
 
   return 0;
 }
@@ -935,7 +957,7 @@
   int retval = 0;
 
   LOG(INFO) << __func__
-            << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState()
+            << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState()
             << ", kvpairs=[" << kvpairs << "]";
 
   std::unordered_map<std::string, std::string> params =
@@ -955,18 +977,18 @@
   std::unique_lock<std::mutex> lock(in->mutex_);
 
   LOG(VERBOSE) << __func__
-               << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState()
+               << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState()
                << ", keys=[" << keys << "]";
 
   std::unordered_map<std::string, std::string> params = ParseAudioParams(keys);
   if (params.empty()) return strdup("");
 
   audio_config_t audio_cfg;
-  if (in->bluetooth_input_.LoadAudioConfig(&audio_cfg)) {
-    LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  if (in->bluetooth_input_->LoadAudioConfig(&audio_cfg)) {
+    LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                  << " audio_cfg=" << audio_cfg;
   } else {
-    LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+    LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << " failed to get audio config";
   }
 
@@ -985,7 +1007,7 @@
 static int in_add_audio_effect(const struct audio_stream* stream,
                                effect_handle_t effect) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
-  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << ", effect=" << effect;
   return 0;
 }
@@ -993,7 +1015,7 @@
 static int in_remove_audio_effect(const struct audio_stream* stream,
                                   effect_handle_t effect) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
-  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << ", effect=" << effect;
   return 0;
 }
@@ -1001,7 +1023,7 @@
 static int in_set_gain(struct audio_stream_in* stream, float gain) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
   LOG(VERBOSE) << __func__
-               << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState();
+               << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState();
 
   return 0;
 }
@@ -1017,41 +1039,41 @@
                                    kBluetoothDefaultInputStateTimeoutMs))
     return -EBUSY;
 
-  if (in->bluetooth_input_.GetState() != BluetoothStreamState::STARTED) {
-    LOG(INFO) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  if (in->bluetooth_input_->GetState() != BluetoothStreamState::STARTED) {
+    LOG(INFO) << __func__ << ": state=" << in->bluetooth_input_->GetState()
               << " first time bytes=" << bytes;
 
     int retval = 0;
-    LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+    LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                  << ", starting";
-    if (in->bluetooth_input_.GetState() == BluetoothStreamState::STANDBY) {
-      retval = (in->bluetooth_input_.Start() ? 0 : -EIO);
-    } else if (in->bluetooth_input_.GetState() ==
+    if (in->bluetooth_input_->GetState() == BluetoothStreamState::STANDBY) {
+      retval = (in->bluetooth_input_->Start() ? 0 : -EIO);
+    } else if (in->bluetooth_input_->GetState() ==
                BluetoothStreamState::SUSPENDING) {
-      LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+      LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                    << " NOT ready to start?!";
       retval = -EBUSY;
-    } else if (in->bluetooth_input_.GetState() ==
+    } else if (in->bluetooth_input_->GetState() ==
                BluetoothStreamState::DISABLED) {
-      LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+      LOG(WARNING) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                    << " NOT allow to start?!";
       retval = -EINVAL;
     } else {
-      LOG(DEBUG) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+      LOG(DEBUG) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                  << " started already";
     }
-    LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+    LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                  << ", starting (start) retval=" << retval;
 
     if (retval) {
-      LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+      LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                  << " failed to start";
       return retval;
     }
   }
 
   lock.unlock();
-  totalRead = in->bluetooth_input_.ReadData(buffer, bytes);
+  totalRead = in->bluetooth_input_->ReadData(buffer, bytes);
   lock.lock();
 
   struct timespec ts = {.tv_sec = 0, .tv_nsec = 0};
@@ -1067,7 +1089,7 @@
 static uint32_t in_get_input_frames_lost(struct audio_stream_in* stream) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
   LOG(VERBOSE) << __func__
-               << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState();
+               << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState();
 
   return 0;
 }
@@ -1079,8 +1101,8 @@
   }
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
 
-  if (in->bluetooth_input_.GetState() == BluetoothStreamState::STANDBY) {
-    LOG(WARNING) << __func__ << ": state= " << in->bluetooth_input_.GetState();
+  if (in->bluetooth_input_->GetState() == BluetoothStreamState::STANDBY) {
+    LOG(WARNING) << __func__ << ": state= " << in->bluetooth_input_->GetState();
     return -ENOSYS;
   }
 
@@ -1092,7 +1114,7 @@
 static int in_start(const struct audio_stream_in* stream) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
   LOG(VERBOSE) << __func__
-               << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState();
+               << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState();
 
   return 0;
 }
@@ -1100,7 +1122,7 @@
 static int in_stop(const struct audio_stream_in* stream) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
   LOG(VERBOSE) << __func__
-               << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState();
+               << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState();
 
   return 0;
 }
@@ -1110,7 +1132,7 @@
                                  struct audio_mmap_buffer_info* info) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
   LOG(VERBOSE) << __func__
-               << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState();
+               << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState();
 
   return -ENOSYS;
 }
@@ -1119,7 +1141,7 @@
                                 struct audio_mmap_position* position) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
   LOG(VERBOSE) << __func__
-               << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState();
+               << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState();
 
   return -ENOSYS;
 }
@@ -1129,7 +1151,7 @@
     struct audio_microphone_characteristic_t* mic_array, size_t* mic_count) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
   LOG(VERBOSE) << __func__
-               << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState();
+               << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState();
 
   return -ENOSYS;
 }
@@ -1138,7 +1160,7 @@
                                        audio_microphone_direction_t direction) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
   LOG(VERBOSE) << __func__
-               << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState();
+               << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState();
 
   return -ENOSYS;
 }
@@ -1147,7 +1169,7 @@
     const struct audio_stream_in* stream, float zoom) {
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
   LOG(VERBOSE) << __func__
-               << ": NOT HANDLED! state=" << in->bluetooth_input_.GetState();
+               << ": NOT HANDLED! state=" << in->bluetooth_input_->GetState();
 
   return -ENOSYS;
 }
@@ -1160,10 +1182,17 @@
   }
 
   const auto* in = reinterpret_cast<const BluetoothStreamIn*>(stream);
-  LOG(INFO) << __func__ << ": state=" << in->bluetooth_input_.GetState() << ", "
-            << sink_metadata->track_count << " track(s)";
+  LOG(INFO) << __func__ << ": state=" << in->bluetooth_input_->GetState()
+            << ", " << sink_metadata->track_count << " track(s)";
 
-  in->bluetooth_input_.UpdateSinkMetadata(sink_metadata);
+  if (!in->is_aidl) {
+    LOG(WARNING) << __func__
+                 << " is only supported in AIDL but using HIDL now!";
+    return;
+  }
+  static_cast<::android::bluetooth::audio::aidl::BluetoothAudioPortAidl*>(
+      in->bluetooth_input_.get())
+      ->UpdateSinkMetadata(sink_metadata);
 }
 
 int adev_open_input_stream(struct audio_hw_device* dev,
@@ -1175,7 +1204,19 @@
                            audio_source_t source __unused) {
   *stream_in = nullptr;
   auto* in = new BluetoothStreamIn{};
-  if (!in->bluetooth_input_.SetUp(devices)) {
+  if (::aidl::android::hardware::bluetooth::audio::BluetoothAudioSession::
+          IsAidlAvailable()) {
+    in->bluetooth_input_ = std::make_unique<
+        ::android::bluetooth::audio::aidl::BluetoothAudioPortAidlIn>();
+    in->is_aidl = true;
+  } else {
+    in->bluetooth_input_ = std::make_unique<
+        ::android::bluetooth::audio::hidl::BluetoothAudioPortHidlIn>();
+    in->is_aidl = false;
+  }
+  if (!in->bluetooth_input_->SetUp(devices)) {
+    in->bluetooth_input_ = nullptr;
+    LOG(ERROR) << __func__ << ": cannot init HAL";
     delete in;
     return -EINVAL;
   }
@@ -1208,8 +1249,8 @@
       in_set_microphone_field_dimension;
   in->stream_in_.update_sink_metadata = in_update_sink_metadata;
 
-  if (!in->bluetooth_input_.LoadAudioConfig(config)) {
-    LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  if (!in->bluetooth_input_->LoadAudioConfig(config)) {
+    LOG(ERROR) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << " failed to get audio config";
     return -EINVAL;
   }
@@ -1220,7 +1261,7 @@
   // frame is number of samples per channel
 
   size_t preferred_data_interval_us = kBluetoothDefaultInputBufferMs * 1000;
-  if (in->bluetooth_input_.GetPreferredDataIntervalUs(
+  if (in->bluetooth_input_->GetPreferredDataIntervalUs(
           &preferred_data_interval_us) &&
       preferred_data_interval_us != 0) {
     in->preferred_data_interval_us = preferred_data_interval_us;
@@ -1233,7 +1274,7 @@
   in->frames_presented_ = 0;
 
   *stream_in = &in->stream_in_;
-  LOG(INFO) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  LOG(INFO) << __func__ << ": state=" << in->bluetooth_input_->GetState()
             << ", sample_rate=" << in->sample_rate_
             << ", channels=" << StringPrintf("%#x", in->channel_mask_)
             << ", format=" << in->format_
@@ -1247,12 +1288,12 @@
                              struct audio_stream_in* stream) {
   auto* in = reinterpret_cast<BluetoothStreamIn*>(stream);
 
-  if (in->bluetooth_input_.GetState() != BluetoothStreamState::DISABLED) {
-    in->bluetooth_input_.Stop();
+  if (in->bluetooth_input_->GetState() != BluetoothStreamState::DISABLED) {
+    in->bluetooth_input_->Stop();
   }
 
-  in->bluetooth_input_.TearDown();
-  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_.GetState()
+  in->bluetooth_input_->TearDown();
+  LOG(VERBOSE) << __func__ << ": state=" << in->bluetooth_input_->GetState()
                << ", stopped";
 
   delete in;
diff --git a/system/audio_bluetooth_hw/stream_apis.h b/system/audio_bluetooth_hw/stream_apis.h
index cf90281..76845d9 100644
--- a/system/audio_bluetooth_hw/stream_apis.h
+++ b/system/audio_bluetooth_hw/stream_apis.h
@@ -18,9 +18,11 @@
 
 #include <hardware/audio.h>
 #include <system/audio.h>
+
 #include <list>
 
 #include "device_port_proxy.h"
+#include "device_port_proxy_hidl.h"
 
 constexpr unsigned int kBluetoothDefaultSampleRate = 44100;
 constexpr audio_format_t kBluetoothDefaultAudioFormatBitsPerSample =
@@ -52,7 +54,9 @@
   // Must be the first member so it can be cast from audio_stream
   // or audio_stream_out pointer
   audio_stream_out stream_out_{};
-  ::android::bluetooth::audio::BluetoothAudioPortOut bluetooth_output_;
+  std::unique_ptr<::android::bluetooth::audio::BluetoothAudioPort>
+      bluetooth_output_;
+  bool is_aidl;
   int64_t last_write_time_us_;
   // Audio PCM Configs
   uint32_t sample_rate_;
@@ -83,7 +87,9 @@
   // Must be the first member so it can be cast from audio_stream
   // or audio_stream_in pointer
   audio_stream_in stream_in_;
-  ::android::bluetooth::audio::BluetoothAudioPortIn bluetooth_input_;
+  std::unique_ptr<::android::bluetooth::audio::BluetoothAudioPort>
+      bluetooth_input_;
+  bool is_aidl;
   int64_t last_read_time_us_;
   // Audio PCM Configs
   uint32_t sample_rate_;