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_;