mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-02 02:42:35 +00:00
Merge "Add A2dp decode software and offload session type" am: 0dac5667f5 am: 67fa92a1e5
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2046263 Change-Id: I52ebcbb3439e88a071f5a034b49c2715fde46e5e Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -44,4 +44,6 @@ enum SessionType {
|
|||||||
LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH = 7,
|
LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH = 7,
|
||||||
LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH = 8,
|
LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH = 8,
|
||||||
LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH = 9,
|
LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH = 9,
|
||||||
|
A2DP_SOFTWARE_DECODING_DATAPATH = 10,
|
||||||
|
A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH = 11,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,4 +62,12 @@ enum SessionType {
|
|||||||
* Audio broadcast channels. This is a control path only.
|
* Audio broadcast channels. This is a control path only.
|
||||||
*/
|
*/
|
||||||
LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
|
LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
|
||||||
|
/**
|
||||||
|
* A2DP legacy that AVDTP media is decoded by Bluetooth Stack
|
||||||
|
*/
|
||||||
|
A2DP_SOFTWARE_DECODING_DATAPATH,
|
||||||
|
/**
|
||||||
|
* The decoding of AVDTP media is done by HW and there is control only
|
||||||
|
*/
|
||||||
|
A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,10 +28,18 @@ namespace hardware {
|
|||||||
namespace bluetooth {
|
namespace bluetooth {
|
||||||
namespace audio {
|
namespace audio {
|
||||||
|
|
||||||
A2dpOffloadAudioProvider::A2dpOffloadAudioProvider() {
|
A2dpOffloadEncodingAudioProvider::A2dpOffloadEncodingAudioProvider()
|
||||||
|
: A2dpOffloadAudioProvider() {
|
||||||
session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
|
session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
A2dpOffloadDecodingAudioProvider::A2dpOffloadDecodingAudioProvider()
|
||||||
|
: A2dpOffloadAudioProvider() {
|
||||||
|
session_type_ = SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
A2dpOffloadAudioProvider::A2dpOffloadAudioProvider() {}
|
||||||
|
|
||||||
bool A2dpOffloadAudioProvider::isValid(const SessionType& session_type) {
|
bool A2dpOffloadAudioProvider::isValid(const SessionType& session_type) {
|
||||||
return (session_type == session_type_);
|
return (session_type == session_type_);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,16 @@ class A2dpOffloadAudioProvider : public BluetoothAudioProvider {
|
|||||||
ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
|
ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class A2dpOffloadEncodingAudioProvider : public A2dpOffloadAudioProvider {
|
||||||
|
public:
|
||||||
|
A2dpOffloadEncodingAudioProvider();
|
||||||
|
};
|
||||||
|
|
||||||
|
class A2dpOffloadDecodingAudioProvider : public A2dpOffloadAudioProvider {
|
||||||
|
public:
|
||||||
|
A2dpOffloadDecodingAudioProvider();
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace audio
|
} // namespace audio
|
||||||
} // namespace bluetooth
|
} // namespace bluetooth
|
||||||
} // namespace hardware
|
} // namespace hardware
|
||||||
|
|||||||
@@ -40,6 +40,16 @@ static constexpr uint32_t kBufferSize = kRtpFrameSize * kRtpFrameCount;
|
|||||||
static constexpr uint32_t kBufferCount = 2; // double buffer
|
static constexpr uint32_t kBufferCount = 2; // double buffer
|
||||||
static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
|
static constexpr uint32_t kDataMqSize = kBufferSize * kBufferCount;
|
||||||
|
|
||||||
|
A2dpSoftwareEncodingAudioProvider::A2dpSoftwareEncodingAudioProvider()
|
||||||
|
: A2dpSoftwareAudioProvider() {
|
||||||
|
session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
A2dpSoftwareDecodingAudioProvider::A2dpSoftwareDecodingAudioProvider()
|
||||||
|
: A2dpSoftwareAudioProvider() {
|
||||||
|
session_type_ = SessionType::A2DP_SOFTWARE_DECODING_DATAPATH;
|
||||||
|
}
|
||||||
|
|
||||||
A2dpSoftwareAudioProvider::A2dpSoftwareAudioProvider()
|
A2dpSoftwareAudioProvider::A2dpSoftwareAudioProvider()
|
||||||
: BluetoothAudioProvider(), data_mq_(nullptr) {
|
: BluetoothAudioProvider(), data_mq_(nullptr) {
|
||||||
LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
|
LOG(INFO) << __func__ << " - size of audio buffer " << kDataMqSize
|
||||||
@@ -48,7 +58,6 @@ A2dpSoftwareAudioProvider::A2dpSoftwareAudioProvider()
|
|||||||
new DataMQ(kDataMqSize, /* EventFlag */ true));
|
new DataMQ(kDataMqSize, /* EventFlag */ true));
|
||||||
if (data_mq && data_mq->isValid()) {
|
if (data_mq && data_mq->isValid()) {
|
||||||
data_mq_ = std::move(data_mq);
|
data_mq_ = std::move(data_mq);
|
||||||
session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
|
|
||||||
} else {
|
} else {
|
||||||
ALOGE_IF(!data_mq, "failed to allocate data MQ");
|
ALOGE_IF(!data_mq, "failed to allocate data MQ");
|
||||||
ALOGE_IF(data_mq && !data_mq->isValid(), "data MQ is invalid");
|
ALOGE_IF(data_mq && !data_mq->isValid(), "data MQ is invalid");
|
||||||
|
|||||||
@@ -43,6 +43,16 @@ class A2dpSoftwareAudioProvider : public BluetoothAudioProvider {
|
|||||||
ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
|
ndk::ScopedAStatus onSessionReady(DataMQDesc* _aidl_return) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class A2dpSoftwareEncodingAudioProvider : public A2dpSoftwareAudioProvider {
|
||||||
|
public:
|
||||||
|
A2dpSoftwareEncodingAudioProvider();
|
||||||
|
};
|
||||||
|
|
||||||
|
class A2dpSoftwareDecodingAudioProvider : public A2dpSoftwareAudioProvider {
|
||||||
|
public:
|
||||||
|
A2dpSoftwareDecodingAudioProvider();
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace audio
|
} // namespace audio
|
||||||
} // namespace bluetooth
|
} // namespace bluetooth
|
||||||
} // namespace hardware
|
} // namespace hardware
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider(
|
|||||||
|
|
||||||
switch (session_type) {
|
switch (session_type) {
|
||||||
case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
|
case SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH:
|
||||||
provider = ndk::SharedRefBase::make<A2dpSoftwareAudioProvider>();
|
provider = ndk::SharedRefBase::make<A2dpSoftwareEncodingAudioProvider>();
|
||||||
break;
|
break;
|
||||||
case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
||||||
provider = ndk::SharedRefBase::make<A2dpOffloadAudioProvider>();
|
provider = ndk::SharedRefBase::make<A2dpOffloadEncodingAudioProvider>();
|
||||||
break;
|
break;
|
||||||
case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
|
case SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH:
|
||||||
provider = ndk::SharedRefBase::make<HearingAidAudioProvider>();
|
provider = ndk::SharedRefBase::make<HearingAidAudioProvider>();
|
||||||
@@ -72,6 +72,12 @@ ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider(
|
|||||||
provider =
|
provider =
|
||||||
ndk::SharedRefBase::make<LeAudioOffloadBroadcastAudioProvider>();
|
ndk::SharedRefBase::make<LeAudioOffloadBroadcastAudioProvider>();
|
||||||
break;
|
break;
|
||||||
|
case SessionType::A2DP_SOFTWARE_DECODING_DATAPATH:
|
||||||
|
provider = ndk::SharedRefBase::make<A2dpSoftwareDecodingAudioProvider>();
|
||||||
|
break;
|
||||||
|
case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
||||||
|
provider = ndk::SharedRefBase::make<A2dpOffloadDecodingAudioProvider>();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
provider = nullptr;
|
provider = nullptr;
|
||||||
break;
|
break;
|
||||||
@@ -90,7 +96,8 @@ ndk::ScopedAStatus BluetoothAudioProviderFactory::openProvider(
|
|||||||
ndk::ScopedAStatus BluetoothAudioProviderFactory::getProviderCapabilities(
|
ndk::ScopedAStatus BluetoothAudioProviderFactory::getProviderCapabilities(
|
||||||
const SessionType session_type,
|
const SessionType session_type,
|
||||||
std::vector<AudioCapabilities>* _aidl_return) {
|
std::vector<AudioCapabilities>* _aidl_return) {
|
||||||
if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
|
if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||||
|
session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||||
auto codec_capabilities =
|
auto codec_capabilities =
|
||||||
BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(session_type);
|
BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(session_type);
|
||||||
_aidl_return->resize(codec_capabilities.size());
|
_aidl_return->resize(codec_capabilities.size());
|
||||||
|
|||||||
@@ -201,7 +201,8 @@ class BluetoothAudioProviderFactoryAidl
|
|||||||
ASSERT_EQ(temp_provider_capabilities_[0].getTag(),
|
ASSERT_EQ(temp_provider_capabilities_[0].getTag(),
|
||||||
AudioCapabilities::pcmCapabilities);
|
AudioCapabilities::pcmCapabilities);
|
||||||
} break;
|
} break;
|
||||||
case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH: {
|
case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
||||||
|
case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH: {
|
||||||
std::unordered_set<CodecType> codec_types;
|
std::unordered_set<CodecType> codec_types;
|
||||||
// empty capability means offload is unsupported
|
// empty capability means offload is unsupported
|
||||||
for (auto& audio_capability : temp_provider_capabilities_) {
|
for (auto& audio_capability : temp_provider_capabilities_) {
|
||||||
@@ -250,6 +251,16 @@ class BluetoothAudioProviderFactoryAidl
|
|||||||
AudioCapabilities::leAudioCapabilities);
|
AudioCapabilities::leAudioCapabilities);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case SessionType::A2DP_SOFTWARE_DECODING_DATAPATH: {
|
||||||
|
if (!temp_provider_capabilities_.empty()) {
|
||||||
|
ASSERT_EQ(temp_provider_capabilities_.size(), 1);
|
||||||
|
ASSERT_EQ(temp_provider_capabilities_[0].getTag(),
|
||||||
|
AudioCapabilities::pcmCapabilities);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
default: {
|
||||||
|
ASSERT_TRUE(temp_provider_capabilities_.empty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,7 +277,7 @@ class BluetoothAudioProviderFactoryAidl
|
|||||||
ASSERT_NE(audio_provider_, nullptr);
|
ASSERT_NE(audio_provider_, nullptr);
|
||||||
audio_port_ = ndk::SharedRefBase::make<BluetoothAudioPort>();
|
audio_port_ = ndk::SharedRefBase::make<BluetoothAudioPort>();
|
||||||
} else {
|
} else {
|
||||||
// Hardware offloading is optional
|
// optional session type
|
||||||
ASSERT_TRUE(
|
ASSERT_TRUE(
|
||||||
session_type == SessionType::UNKNOWN ||
|
session_type == SessionType::UNKNOWN ||
|
||||||
session_type ==
|
session_type ==
|
||||||
@@ -277,147 +288,14 @@ class BluetoothAudioProviderFactoryAidl
|
|||||||
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||||
session_type ==
|
session_type ==
|
||||||
SessionType::
|
SessionType::
|
||||||
LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
|
LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||||
|
session_type ==
|
||||||
|
SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
|
||||||
|
session_type == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
|
||||||
ASSERT_EQ(audio_provider_, nullptr);
|
ASSERT_EQ(audio_provider_, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsPcmConfigSupported(const PcmConfiguration& pcm_config) {
|
|
||||||
if (temp_provider_capabilities_.size() != 1 ||
|
|
||||||
temp_provider_capabilities_[0].getTag() !=
|
|
||||||
AudioCapabilities::pcmCapabilities) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
auto pcm_capability = temp_provider_capabilities_[0]
|
|
||||||
.get<AudioCapabilities::pcmCapabilities>();
|
|
||||||
return (contained_in_vector(pcm_capability.channelMode,
|
|
||||||
pcm_config.channelMode) &&
|
|
||||||
contained_in_vector(pcm_capability.sampleRateHz,
|
|
||||||
pcm_config.sampleRateHz) &&
|
|
||||||
contained_in_vector(pcm_capability.bitsPerSample,
|
|
||||||
pcm_config.bitsPerSample));
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<IBluetoothAudioProviderFactory> provider_factory_;
|
|
||||||
std::shared_ptr<IBluetoothAudioProvider> audio_provider_;
|
|
||||||
std::shared_ptr<IBluetoothAudioPort> audio_port_;
|
|
||||||
std::vector<AudioCapabilities> temp_provider_capabilities_;
|
|
||||||
|
|
||||||
static constexpr SessionType kSessionTypes[] = {
|
|
||||||
SessionType::UNKNOWN,
|
|
||||||
SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
|
|
||||||
SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
|
|
||||||
SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
|
|
||||||
SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
|
|
||||||
SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
|
|
||||||
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
|
|
||||||
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
|
|
||||||
SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
|
|
||||||
SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether we can get the FactoryService from HIDL
|
|
||||||
*/
|
|
||||||
TEST_P(BluetoothAudioProviderFactoryAidl, GetProviderFactoryService) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether we can open a provider for each provider returned by
|
|
||||||
* getProviderCapabilities() with non-empty capabalities
|
|
||||||
*/
|
|
||||||
TEST_P(BluetoothAudioProviderFactoryAidl,
|
|
||||||
OpenProviderAndCheckCapabilitiesBySession) {
|
|
||||||
for (auto session_type : kSessionTypes) {
|
|
||||||
GetProviderCapabilitiesHelper(session_type);
|
|
||||||
OpenProviderHelper(session_type);
|
|
||||||
// We must be able to open a provider if its getProviderCapabilities()
|
|
||||||
// returns non-empty list.
|
|
||||||
EXPECT_TRUE(temp_provider_capabilities_.empty() ||
|
|
||||||
audio_provider_ != nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* openProvider A2DP_SOFTWARE_ENCODING_DATAPATH
|
|
||||||
*/
|
|
||||||
class BluetoothAudioProviderA2dpSoftwareAidl
|
|
||||||
: public BluetoothAudioProviderFactoryAidl {
|
|
||||||
public:
|
|
||||||
virtual void SetUp() override {
|
|
||||||
BluetoothAudioProviderFactoryAidl::SetUp();
|
|
||||||
GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
|
|
||||||
OpenProviderHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
|
|
||||||
ASSERT_NE(audio_provider_, nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void TearDown() override {
|
|
||||||
audio_port_ = nullptr;
|
|
||||||
audio_provider_ = nullptr;
|
|
||||||
BluetoothAudioProviderFactoryAidl::TearDown();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether we can open a provider of type
|
|
||||||
*/
|
|
||||||
TEST_P(BluetoothAudioProviderA2dpSoftwareAidl, OpenA2dpSoftwareProvider) {}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Test whether each provider of type
|
|
||||||
* SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
|
|
||||||
* different PCM config
|
|
||||||
*/
|
|
||||||
TEST_P(BluetoothAudioProviderA2dpSoftwareAidl,
|
|
||||||
StartAndEndA2dpSoftwareSessionWithPossiblePcmConfig) {
|
|
||||||
for (auto sample_rate : a2dp_sample_rates) {
|
|
||||||
for (auto bits_per_sample : a2dp_bits_per_samples) {
|
|
||||||
for (auto channel_mode : a2dp_channel_modes) {
|
|
||||||
PcmConfiguration pcm_config{
|
|
||||||
.sampleRateHz = sample_rate,
|
|
||||||
.bitsPerSample = bits_per_sample,
|
|
||||||
.channelMode = channel_mode,
|
|
||||||
};
|
|
||||||
bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
|
|
||||||
DataMQDesc mq_desc;
|
|
||||||
auto aidl_retval = audio_provider_->startSession(
|
|
||||||
audio_port_, AudioConfiguration(pcm_config), latency_modes,
|
|
||||||
&mq_desc);
|
|
||||||
DataMQ data_mq(mq_desc);
|
|
||||||
|
|
||||||
EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
|
|
||||||
if (is_codec_config_valid) {
|
|
||||||
EXPECT_TRUE(data_mq.isValid());
|
|
||||||
}
|
|
||||||
EXPECT_TRUE(audio_provider_->endSession().isOk());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* openProvider A2DP_HARDWARE_OFFLOAD_DATAPATH
|
|
||||||
*/
|
|
||||||
class BluetoothAudioProviderA2dpHardwareAidl
|
|
||||||
: public BluetoothAudioProviderFactoryAidl {
|
|
||||||
public:
|
|
||||||
virtual void SetUp() override {
|
|
||||||
BluetoothAudioProviderFactoryAidl::SetUp();
|
|
||||||
GetProviderCapabilitiesHelper(
|
|
||||||
SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
|
|
||||||
OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
|
|
||||||
ASSERT_TRUE(temp_provider_capabilities_.empty() ||
|
|
||||||
audio_provider_ != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void TearDown() override {
|
|
||||||
audio_port_ = nullptr;
|
|
||||||
audio_provider_ = nullptr;
|
|
||||||
BluetoothAudioProviderFactoryAidl::TearDown();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
|
|
||||||
|
|
||||||
void GetA2dpOffloadCapabilityHelper(const CodecType& codec_type) {
|
void GetA2dpOffloadCapabilityHelper(const CodecType& codec_type) {
|
||||||
temp_codec_capabilities_ = nullptr;
|
temp_codec_capabilities_ = nullptr;
|
||||||
for (auto& codec_capability : temp_provider_capabilities_) {
|
for (auto& codec_capability : temp_provider_capabilities_) {
|
||||||
@@ -641,23 +519,163 @@ class BluetoothAudioProviderA2dpHardwareAidl
|
|||||||
return lc3_codec_specifics;
|
return lc3_codec_specifics;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsPcmConfigSupported(const PcmConfiguration& pcm_config) {
|
||||||
|
if (temp_provider_capabilities_.size() != 1 ||
|
||||||
|
temp_provider_capabilities_[0].getTag() !=
|
||||||
|
AudioCapabilities::pcmCapabilities) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
auto pcm_capability = temp_provider_capabilities_[0]
|
||||||
|
.get<AudioCapabilities::pcmCapabilities>();
|
||||||
|
return (contained_in_vector(pcm_capability.channelMode,
|
||||||
|
pcm_config.channelMode) &&
|
||||||
|
contained_in_vector(pcm_capability.sampleRateHz,
|
||||||
|
pcm_config.sampleRateHz) &&
|
||||||
|
contained_in_vector(pcm_capability.bitsPerSample,
|
||||||
|
pcm_config.bitsPerSample));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<IBluetoothAudioProviderFactory> provider_factory_;
|
||||||
|
std::shared_ptr<IBluetoothAudioProvider> audio_provider_;
|
||||||
|
std::shared_ptr<IBluetoothAudioPort> audio_port_;
|
||||||
|
std::vector<AudioCapabilities> temp_provider_capabilities_;
|
||||||
|
|
||||||
// temp storage saves the specified codec capability by
|
// temp storage saves the specified codec capability by
|
||||||
// GetOffloadCodecCapabilityHelper()
|
// GetOffloadCodecCapabilityHelper()
|
||||||
CodecCapabilities* temp_codec_capabilities_;
|
CodecCapabilities* temp_codec_capabilities_;
|
||||||
|
|
||||||
|
static constexpr SessionType kSessionTypes[] = {
|
||||||
|
SessionType::UNKNOWN,
|
||||||
|
SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH,
|
||||||
|
SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
|
||||||
|
SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH,
|
||||||
|
SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH,
|
||||||
|
SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH,
|
||||||
|
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
|
||||||
|
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH,
|
||||||
|
SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH,
|
||||||
|
SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH,
|
||||||
|
SessionType::A2DP_SOFTWARE_DECODING_DATAPATH,
|
||||||
|
SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether we can get the FactoryService from HIDL
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderFactoryAidl, GetProviderFactoryService) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether we can open a provider for each provider returned by
|
||||||
|
* getProviderCapabilities() with non-empty capabalities
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderFactoryAidl,
|
||||||
|
OpenProviderAndCheckCapabilitiesBySession) {
|
||||||
|
for (auto session_type : kSessionTypes) {
|
||||||
|
GetProviderCapabilitiesHelper(session_type);
|
||||||
|
OpenProviderHelper(session_type);
|
||||||
|
// We must be able to open a provider if its getProviderCapabilities()
|
||||||
|
// returns non-empty list.
|
||||||
|
EXPECT_TRUE(temp_provider_capabilities_.empty() ||
|
||||||
|
audio_provider_ != nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* openProvider A2DP_SOFTWARE_ENCODING_DATAPATH
|
||||||
|
*/
|
||||||
|
class BluetoothAudioProviderA2dpEncodingSoftwareAidl
|
||||||
|
: public BluetoothAudioProviderFactoryAidl {
|
||||||
|
public:
|
||||||
|
virtual void SetUp() override {
|
||||||
|
BluetoothAudioProviderFactoryAidl::SetUp();
|
||||||
|
GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
|
||||||
|
OpenProviderHelper(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
|
||||||
|
ASSERT_NE(audio_provider_, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void TearDown() override {
|
||||||
|
audio_port_ = nullptr;
|
||||||
|
audio_provider_ = nullptr;
|
||||||
|
BluetoothAudioProviderFactoryAidl::TearDown();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether we can open a provider of type
|
* Test whether we can open a provider of type
|
||||||
*/
|
*/
|
||||||
TEST_P(BluetoothAudioProviderA2dpHardwareAidl, OpenA2dpHardwareProvider) {}
|
TEST_P(BluetoothAudioProviderA2dpEncodingSoftwareAidl,
|
||||||
|
OpenA2dpEncodingSoftwareProvider) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether each provider of type
|
||||||
|
* SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH can be started and stopped with
|
||||||
|
* different PCM config
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderA2dpEncodingSoftwareAidl,
|
||||||
|
StartAndEndA2dpEncodingSoftwareSessionWithPossiblePcmConfig) {
|
||||||
|
for (auto sample_rate : a2dp_sample_rates) {
|
||||||
|
for (auto bits_per_sample : a2dp_bits_per_samples) {
|
||||||
|
for (auto channel_mode : a2dp_channel_modes) {
|
||||||
|
PcmConfiguration pcm_config{
|
||||||
|
.sampleRateHz = sample_rate,
|
||||||
|
.bitsPerSample = bits_per_sample,
|
||||||
|
.channelMode = channel_mode,
|
||||||
|
};
|
||||||
|
bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
|
||||||
|
DataMQDesc mq_desc;
|
||||||
|
auto aidl_retval = audio_provider_->startSession(
|
||||||
|
audio_port_, AudioConfiguration(pcm_config), latency_modes,
|
||||||
|
&mq_desc);
|
||||||
|
DataMQ data_mq(mq_desc);
|
||||||
|
|
||||||
|
EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
|
||||||
|
if (is_codec_config_valid) {
|
||||||
|
EXPECT_TRUE(data_mq.isValid());
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(audio_provider_->endSession().isOk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* openProvider A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH
|
||||||
|
*/
|
||||||
|
class BluetoothAudioProviderA2dpEncodingHardwareAidl
|
||||||
|
: public BluetoothAudioProviderFactoryAidl {
|
||||||
|
public:
|
||||||
|
virtual void SetUp() override {
|
||||||
|
BluetoothAudioProviderFactoryAidl::SetUp();
|
||||||
|
GetProviderCapabilitiesHelper(
|
||||||
|
SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
|
||||||
|
OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
|
||||||
|
ASSERT_TRUE(temp_provider_capabilities_.empty() ||
|
||||||
|
audio_provider_ != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void TearDown() override {
|
||||||
|
audio_port_ = nullptr;
|
||||||
|
audio_provider_ = nullptr;
|
||||||
|
BluetoothAudioProviderFactoryAidl::TearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether we can open a provider of type
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
|
||||||
|
OpenA2dpEncodingHardwareProvider) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test whether each provider of type
|
* Test whether each provider of type
|
||||||
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
|
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
|
||||||
* SBC hardware encoding config
|
* SBC hardware encoding config
|
||||||
*/
|
*/
|
||||||
TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
|
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
|
||||||
StartAndEndA2dpSbcHardwareSession) {
|
StartAndEndA2dpSbcEncodingHardwareSession) {
|
||||||
if (!IsOffloadSupported()) {
|
if (!IsOffloadSupported()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -686,8 +704,8 @@ TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
|
|||||||
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
|
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
|
||||||
* AAC hardware encoding config
|
* AAC hardware encoding config
|
||||||
*/
|
*/
|
||||||
TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
|
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
|
||||||
StartAndEndA2dpAacHardwareSession) {
|
StartAndEndA2dpAacEncodingHardwareSession) {
|
||||||
if (!IsOffloadSupported()) {
|
if (!IsOffloadSupported()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -716,8 +734,8 @@ TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
|
|||||||
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
|
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
|
||||||
* LDAC hardware encoding config
|
* LDAC hardware encoding config
|
||||||
*/
|
*/
|
||||||
TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
|
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
|
||||||
StartAndEndA2dpLdacHardwareSession) {
|
StartAndEndA2dpLdacEncodingHardwareSession) {
|
||||||
if (!IsOffloadSupported()) {
|
if (!IsOffloadSupported()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -746,8 +764,8 @@ TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
|
|||||||
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
|
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
|
||||||
* LDAC hardware encoding config
|
* LDAC hardware encoding config
|
||||||
*/
|
*/
|
||||||
TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
|
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
|
||||||
StartAndEndA2dpLc3HardwareSession) {
|
StartAndEndA2dpLc3EncodingHardwareSession) {
|
||||||
if (!IsOffloadSupported()) {
|
if (!IsOffloadSupported()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -776,8 +794,8 @@ TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
|
|||||||
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
|
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
|
||||||
* AptX hardware encoding config
|
* AptX hardware encoding config
|
||||||
*/
|
*/
|
||||||
TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
|
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
|
||||||
StartAndEndA2dpAptxHardwareSession) {
|
StartAndEndA2dpAptxEncodingHardwareSession) {
|
||||||
if (!IsOffloadSupported()) {
|
if (!IsOffloadSupported()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -812,8 +830,8 @@ TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
|
|||||||
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
|
* SessionType::A2DP_HARDWARE_ENCODING_DATAPATH can be started and stopped with
|
||||||
* an invalid codec config
|
* an invalid codec config
|
||||||
*/
|
*/
|
||||||
TEST_P(BluetoothAudioProviderA2dpHardwareAidl,
|
TEST_P(BluetoothAudioProviderA2dpEncodingHardwareAidl,
|
||||||
StartAndEndA2dpHardwareSessionInvalidCodecConfig) {
|
StartAndEndA2dpEncodingHardwareSessionInvalidCodecConfig) {
|
||||||
if (!IsOffloadSupported()) {
|
if (!IsOffloadSupported()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1588,6 +1606,314 @@ TEST_P(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* openProvider A2DP_SOFTWARE_DECODING_DATAPATH
|
||||||
|
*/
|
||||||
|
class BluetoothAudioProviderA2dpDecodingSoftwareAidl
|
||||||
|
: public BluetoothAudioProviderFactoryAidl {
|
||||||
|
public:
|
||||||
|
virtual void SetUp() override {
|
||||||
|
BluetoothAudioProviderFactoryAidl::SetUp();
|
||||||
|
GetProviderCapabilitiesHelper(SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
|
||||||
|
OpenProviderHelper(SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
|
||||||
|
ASSERT_TRUE(temp_provider_capabilities_.empty() ||
|
||||||
|
audio_provider_ != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void TearDown() override {
|
||||||
|
audio_port_ = nullptr;
|
||||||
|
audio_provider_ = nullptr;
|
||||||
|
BluetoothAudioProviderFactoryAidl::TearDown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether we can open a provider of type
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderA2dpDecodingSoftwareAidl,
|
||||||
|
OpenA2dpDecodingSoftwareProvider) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether each provider of type
|
||||||
|
* SessionType::A2DP_SOFTWARE_DECODING_DATAPATH can be started and stopped with
|
||||||
|
* different PCM config
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderA2dpDecodingSoftwareAidl,
|
||||||
|
StartAndEndA2dpDecodingSoftwareSessionWithPossiblePcmConfig) {
|
||||||
|
for (auto sample_rate : a2dp_sample_rates) {
|
||||||
|
for (auto bits_per_sample : a2dp_bits_per_samples) {
|
||||||
|
for (auto channel_mode : a2dp_channel_modes) {
|
||||||
|
PcmConfiguration pcm_config{
|
||||||
|
.sampleRateHz = sample_rate,
|
||||||
|
.bitsPerSample = bits_per_sample,
|
||||||
|
.channelMode = channel_mode,
|
||||||
|
};
|
||||||
|
bool is_codec_config_valid = IsPcmConfigSupported(pcm_config);
|
||||||
|
DataMQDesc mq_desc;
|
||||||
|
auto aidl_retval = audio_provider_->startSession(
|
||||||
|
audio_port_, AudioConfiguration(pcm_config), latency_modes,
|
||||||
|
&mq_desc);
|
||||||
|
DataMQ data_mq(mq_desc);
|
||||||
|
|
||||||
|
EXPECT_EQ(aidl_retval.isOk(), is_codec_config_valid);
|
||||||
|
if (is_codec_config_valid) {
|
||||||
|
EXPECT_TRUE(data_mq.isValid());
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(audio_provider_->endSession().isOk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* openProvider A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH
|
||||||
|
*/
|
||||||
|
class BluetoothAudioProviderA2dpDecodingHardwareAidl
|
||||||
|
: public BluetoothAudioProviderFactoryAidl {
|
||||||
|
public:
|
||||||
|
virtual void SetUp() override {
|
||||||
|
BluetoothAudioProviderFactoryAidl::SetUp();
|
||||||
|
GetProviderCapabilitiesHelper(
|
||||||
|
SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
|
||||||
|
OpenProviderHelper(SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
|
||||||
|
ASSERT_TRUE(temp_provider_capabilities_.empty() ||
|
||||||
|
audio_provider_ != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void TearDown() override {
|
||||||
|
audio_port_ = nullptr;
|
||||||
|
audio_provider_ = nullptr;
|
||||||
|
BluetoothAudioProviderFactoryAidl::TearDown();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsOffloadSupported() { return (temp_provider_capabilities_.size() > 0); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether we can open a provider of type
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
|
||||||
|
OpenA2dpDecodingHardwareProvider) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether each provider of type
|
||||||
|
* SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
|
||||||
|
* SBC hardware encoding config
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
|
||||||
|
StartAndEndA2dpSbcDecodingHardwareSession) {
|
||||||
|
if (!IsOffloadSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecConfiguration codec_config = {
|
||||||
|
.codecType = CodecType::SBC,
|
||||||
|
.encodedAudioBitrate = 328000,
|
||||||
|
.peerMtu = 1005,
|
||||||
|
.isScmstEnabled = false,
|
||||||
|
};
|
||||||
|
auto sbc_codec_specifics = GetSbcCodecSpecificSupportedList(true);
|
||||||
|
|
||||||
|
for (auto& codec_specific : sbc_codec_specifics) {
|
||||||
|
copy_codec_specific(codec_config.config, codec_specific);
|
||||||
|
DataMQDesc mq_desc;
|
||||||
|
auto aidl_retval = audio_provider_->startSession(
|
||||||
|
audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
|
||||||
|
|
||||||
|
ASSERT_TRUE(aidl_retval.isOk());
|
||||||
|
EXPECT_TRUE(audio_provider_->endSession().isOk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether each provider of type
|
||||||
|
* SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
|
||||||
|
* AAC hardware encoding config
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
|
||||||
|
StartAndEndA2dpAacDecodingHardwareSession) {
|
||||||
|
if (!IsOffloadSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecConfiguration codec_config = {
|
||||||
|
.codecType = CodecType::AAC,
|
||||||
|
.encodedAudioBitrate = 320000,
|
||||||
|
.peerMtu = 1005,
|
||||||
|
.isScmstEnabled = false,
|
||||||
|
};
|
||||||
|
auto aac_codec_specifics = GetAacCodecSpecificSupportedList(true);
|
||||||
|
|
||||||
|
for (auto& codec_specific : aac_codec_specifics) {
|
||||||
|
copy_codec_specific(codec_config.config, codec_specific);
|
||||||
|
DataMQDesc mq_desc;
|
||||||
|
auto aidl_retval = audio_provider_->startSession(
|
||||||
|
audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
|
||||||
|
|
||||||
|
ASSERT_TRUE(aidl_retval.isOk());
|
||||||
|
EXPECT_TRUE(audio_provider_->endSession().isOk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether each provider of type
|
||||||
|
* SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
|
||||||
|
* LDAC hardware encoding config
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
|
||||||
|
StartAndEndA2dpLdacDecodingHardwareSession) {
|
||||||
|
if (!IsOffloadSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecConfiguration codec_config = {
|
||||||
|
.codecType = CodecType::LDAC,
|
||||||
|
.encodedAudioBitrate = 990000,
|
||||||
|
.peerMtu = 1005,
|
||||||
|
.isScmstEnabled = false,
|
||||||
|
};
|
||||||
|
auto ldac_codec_specifics = GetLdacCodecSpecificSupportedList(true);
|
||||||
|
|
||||||
|
for (auto& codec_specific : ldac_codec_specifics) {
|
||||||
|
copy_codec_specific(codec_config.config, codec_specific);
|
||||||
|
DataMQDesc mq_desc;
|
||||||
|
auto aidl_retval = audio_provider_->startSession(
|
||||||
|
audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
|
||||||
|
|
||||||
|
ASSERT_TRUE(aidl_retval.isOk());
|
||||||
|
EXPECT_TRUE(audio_provider_->endSession().isOk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether each provider of type
|
||||||
|
* SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
|
||||||
|
* LDAC hardware encoding config
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
|
||||||
|
StartAndEndA2dpLc3DecodingHardwareSession) {
|
||||||
|
if (!IsOffloadSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecConfiguration codec_config = {
|
||||||
|
.codecType = CodecType::LC3,
|
||||||
|
.encodedAudioBitrate = 990000,
|
||||||
|
.peerMtu = 1005,
|
||||||
|
.isScmstEnabled = false,
|
||||||
|
};
|
||||||
|
auto lc3_codec_specifics = GetLc3CodecSpecificSupportedList(true);
|
||||||
|
|
||||||
|
for (auto& codec_specific : lc3_codec_specifics) {
|
||||||
|
copy_codec_specific(codec_config.config, codec_specific);
|
||||||
|
DataMQDesc mq_desc;
|
||||||
|
auto aidl_retval = audio_provider_->startSession(
|
||||||
|
audio_port_, AudioConfiguration(codec_config), latency_modes, &mq_desc);
|
||||||
|
|
||||||
|
ASSERT_TRUE(aidl_retval.isOk());
|
||||||
|
EXPECT_TRUE(audio_provider_->endSession().isOk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether each provider of type
|
||||||
|
* SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
|
||||||
|
* AptX hardware encoding config
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
|
||||||
|
StartAndEndA2dpAptxDecodingHardwareSession) {
|
||||||
|
if (!IsOffloadSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto codec_type : {CodecType::APTX, CodecType::APTX_HD}) {
|
||||||
|
CodecConfiguration codec_config = {
|
||||||
|
.codecType = codec_type,
|
||||||
|
.encodedAudioBitrate =
|
||||||
|
(codec_type == CodecType::APTX ? 352000 : 576000),
|
||||||
|
.peerMtu = 1005,
|
||||||
|
.isScmstEnabled = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
auto aptx_codec_specifics = GetAptxCodecSpecificSupportedList(
|
||||||
|
(codec_type == CodecType::APTX_HD ? true : false), true);
|
||||||
|
|
||||||
|
for (auto& codec_specific : aptx_codec_specifics) {
|
||||||
|
copy_codec_specific(codec_config.config, codec_specific);
|
||||||
|
DataMQDesc mq_desc;
|
||||||
|
auto aidl_retval = audio_provider_->startSession(
|
||||||
|
audio_port_, AudioConfiguration(codec_config), latency_modes,
|
||||||
|
&mq_desc);
|
||||||
|
|
||||||
|
ASSERT_TRUE(aidl_retval.isOk());
|
||||||
|
EXPECT_TRUE(audio_provider_->endSession().isOk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test whether each provider of type
|
||||||
|
* SessionType::A2DP_HARDWARE_DECODING_DATAPATH can be started and stopped with
|
||||||
|
* an invalid codec config
|
||||||
|
*/
|
||||||
|
TEST_P(BluetoothAudioProviderA2dpDecodingHardwareAidl,
|
||||||
|
StartAndEndA2dpDecodingHardwareSessionInvalidCodecConfig) {
|
||||||
|
if (!IsOffloadSupported()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ASSERT_NE(audio_provider_, nullptr);
|
||||||
|
|
||||||
|
std::vector<CodecConfiguration::CodecSpecific> codec_specifics;
|
||||||
|
for (auto codec_type : a2dp_codec_types) {
|
||||||
|
switch (codec_type) {
|
||||||
|
case CodecType::SBC:
|
||||||
|
codec_specifics = GetSbcCodecSpecificSupportedList(false);
|
||||||
|
break;
|
||||||
|
case CodecType::AAC:
|
||||||
|
codec_specifics = GetAacCodecSpecificSupportedList(false);
|
||||||
|
break;
|
||||||
|
case CodecType::LDAC:
|
||||||
|
codec_specifics = GetLdacCodecSpecificSupportedList(false);
|
||||||
|
break;
|
||||||
|
case CodecType::APTX:
|
||||||
|
codec_specifics = GetAptxCodecSpecificSupportedList(false, false);
|
||||||
|
break;
|
||||||
|
case CodecType::APTX_HD:
|
||||||
|
codec_specifics = GetAptxCodecSpecificSupportedList(true, false);
|
||||||
|
break;
|
||||||
|
case CodecType::LC3:
|
||||||
|
codec_specifics = GetLc3CodecSpecificSupportedList(false);
|
||||||
|
continue;
|
||||||
|
case CodecType::APTX_ADAPTIVE:
|
||||||
|
case CodecType::VENDOR:
|
||||||
|
case CodecType::UNKNOWN:
|
||||||
|
codec_specifics.clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (codec_specifics.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodecConfiguration codec_config = {
|
||||||
|
.codecType = codec_type,
|
||||||
|
.encodedAudioBitrate = 328000,
|
||||||
|
.peerMtu = 1005,
|
||||||
|
.isScmstEnabled = false,
|
||||||
|
};
|
||||||
|
for (auto codec_specific : codec_specifics) {
|
||||||
|
copy_codec_specific(codec_config.config, codec_specific);
|
||||||
|
DataMQDesc mq_desc;
|
||||||
|
auto aidl_retval = audio_provider_->startSession(
|
||||||
|
audio_port_, AudioConfiguration(codec_config), latency_modes,
|
||||||
|
&mq_desc);
|
||||||
|
|
||||||
|
// AIDL call should fail on invalid codec
|
||||||
|
ASSERT_FALSE(aidl_retval.isOk());
|
||||||
|
EXPECT_TRUE(audio_provider_->endSession().isOk());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
|
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
|
||||||
BluetoothAudioProviderFactoryAidl);
|
BluetoothAudioProviderFactoryAidl);
|
||||||
INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl,
|
INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl,
|
||||||
@@ -1596,15 +1922,17 @@ INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderFactoryAidl,
|
|||||||
android::PrintInstanceNameToString);
|
android::PrintInstanceNameToString);
|
||||||
|
|
||||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
|
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
|
||||||
BluetoothAudioProviderA2dpSoftwareAidl);
|
BluetoothAudioProviderA2dpEncodingSoftwareAidl);
|
||||||
INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpSoftwareAidl,
|
INSTANTIATE_TEST_SUITE_P(PerInstance,
|
||||||
|
BluetoothAudioProviderA2dpEncodingSoftwareAidl,
|
||||||
testing::ValuesIn(android::getAidlHalInstanceNames(
|
testing::ValuesIn(android::getAidlHalInstanceNames(
|
||||||
IBluetoothAudioProviderFactory::descriptor)),
|
IBluetoothAudioProviderFactory::descriptor)),
|
||||||
android::PrintInstanceNameToString);
|
android::PrintInstanceNameToString);
|
||||||
|
|
||||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
|
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
|
||||||
BluetoothAudioProviderA2dpHardwareAidl);
|
BluetoothAudioProviderA2dpEncodingHardwareAidl);
|
||||||
INSTANTIATE_TEST_SUITE_P(PerInstance, BluetoothAudioProviderA2dpHardwareAidl,
|
INSTANTIATE_TEST_SUITE_P(PerInstance,
|
||||||
|
BluetoothAudioProviderA2dpEncodingHardwareAidl,
|
||||||
testing::ValuesIn(android::getAidlHalInstanceNames(
|
testing::ValuesIn(android::getAidlHalInstanceNames(
|
||||||
IBluetoothAudioProviderFactory::descriptor)),
|
IBluetoothAudioProviderFactory::descriptor)),
|
||||||
android::PrintInstanceNameToString);
|
android::PrintInstanceNameToString);
|
||||||
@@ -1665,6 +1993,22 @@ INSTANTIATE_TEST_SUITE_P(PerInstance,
|
|||||||
IBluetoothAudioProviderFactory::descriptor)),
|
IBluetoothAudioProviderFactory::descriptor)),
|
||||||
android::PrintInstanceNameToString);
|
android::PrintInstanceNameToString);
|
||||||
|
|
||||||
|
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
|
||||||
|
BluetoothAudioProviderA2dpDecodingSoftwareAidl);
|
||||||
|
INSTANTIATE_TEST_SUITE_P(PerInstance,
|
||||||
|
BluetoothAudioProviderA2dpDecodingSoftwareAidl,
|
||||||
|
testing::ValuesIn(android::getAidlHalInstanceNames(
|
||||||
|
IBluetoothAudioProviderFactory::descriptor)),
|
||||||
|
android::PrintInstanceNameToString);
|
||||||
|
|
||||||
|
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
|
||||||
|
BluetoothAudioProviderA2dpDecodingHardwareAidl);
|
||||||
|
INSTANTIATE_TEST_SUITE_P(PerInstance,
|
||||||
|
BluetoothAudioProviderA2dpDecodingHardwareAidl,
|
||||||
|
testing::ValuesIn(android::getAidlHalInstanceNames(
|
||||||
|
IBluetoothAudioProviderFactory::descriptor)),
|
||||||
|
android::PrintInstanceNameToString);
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
::testing::InitGoogleTest(&argc, argv);
|
::testing::InitGoogleTest(&argc, argv);
|
||||||
ABinderProcess_setThreadPoolMaxThreadCount(1);
|
ABinderProcess_setThreadPoolMaxThreadCount(1);
|
||||||
|
|||||||
@@ -323,7 +323,8 @@ BluetoothAudioCodecs::GetSoftwarePcmCapabilities() {
|
|||||||
std::vector<CodecCapabilities>
|
std::vector<CodecCapabilities>
|
||||||
BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(
|
BluetoothAudioCodecs::GetA2dpOffloadCodecCapabilities(
|
||||||
const SessionType& session_type) {
|
const SessionType& session_type) {
|
||||||
if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
|
if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
|
||||||
|
session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
std::vector<CodecCapabilities> offload_a2dp_codec_capabilities =
|
std::vector<CodecCapabilities> offload_a2dp_codec_capabilities =
|
||||||
@@ -389,7 +390,8 @@ bool BluetoothAudioCodecs::IsSoftwarePcmConfigurationValid(
|
|||||||
|
|
||||||
bool BluetoothAudioCodecs::IsOffloadCodecConfigurationValid(
|
bool BluetoothAudioCodecs::IsOffloadCodecConfigurationValid(
|
||||||
const SessionType& session_type, const CodecConfiguration& codec_config) {
|
const SessionType& session_type, const CodecConfiguration& codec_config) {
|
||||||
if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
|
if (session_type != SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH &&
|
||||||
|
session_type != SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||||
LOG(ERROR) << __func__
|
LOG(ERROR) << __func__
|
||||||
<< ": Invalid SessionType=" << toString(session_type);
|
<< ": Invalid SessionType=" << toString(session_type);
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -92,6 +92,7 @@ const AudioConfiguration BluetoothAudioSession::GetAudioConfig() {
|
|||||||
if (!IsSessionReady()) {
|
if (!IsSessionReady()) {
|
||||||
switch (session_type_) {
|
switch (session_type_) {
|
||||||
case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
||||||
|
case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
||||||
return AudioConfiguration(CodecConfiguration{});
|
return AudioConfiguration(CodecConfiguration{});
|
||||||
case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
||||||
case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
||||||
@@ -143,6 +144,7 @@ bool BluetoothAudioSession::IsSessionReady() {
|
|||||||
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
|
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
|
||||||
session_type_ ==
|
session_type_ ==
|
||||||
SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
SessionType::LE_AUDIO_BROADCAST_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||||
|
session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH ||
|
||||||
(data_mq_ != nullptr && data_mq_->isValid()));
|
(data_mq_ != nullptr && data_mq_->isValid()));
|
||||||
return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
|
return stack_iface_ != nullptr && is_mq_valid && audio_config_ != nullptr;
|
||||||
}
|
}
|
||||||
@@ -267,9 +269,11 @@ bool BluetoothAudioSession::UpdateAudioConfig(
|
|||||||
session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
|
session_type_ == SessionType::LE_AUDIO_SOFTWARE_DECODING_DATAPATH ||
|
||||||
session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
|
session_type_ == SessionType::LE_AUDIO_SOFTWARE_ENCODING_DATAPATH ||
|
||||||
session_type_ ==
|
session_type_ ==
|
||||||
SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH);
|
SessionType::LE_AUDIO_BROADCAST_SOFTWARE_ENCODING_DATAPATH ||
|
||||||
|
session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH);
|
||||||
bool is_offload_a2dp_session =
|
bool is_offload_a2dp_session =
|
||||||
(session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH);
|
(session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||||
|
session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH);
|
||||||
bool is_offload_le_audio_session =
|
bool is_offload_le_audio_session =
|
||||||
(session_type_ ==
|
(session_type_ ==
|
||||||
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||||
@@ -468,7 +472,9 @@ void BluetoothAudioSession::UpdateSourceMetadata(
|
|||||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
|
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
|
||||||
<< track_count << " track(s)";
|
<< track_count << " track(s)";
|
||||||
if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
|
if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
|
||||||
session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
|
session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||||
|
session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
|
||||||
|
session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +515,9 @@ void BluetoothAudioSession::UpdateSinkMetadata(
|
|||||||
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
|
LOG(INFO) << __func__ << " - SessionType=" << toString(session_type_) << ","
|
||||||
<< track_count << " track(s)";
|
<< track_count << " track(s)";
|
||||||
if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
|
if (session_type_ == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
|
||||||
session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH) {
|
session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH ||
|
||||||
|
session_type_ == SessionType::A2DP_SOFTWARE_DECODING_DATAPATH ||
|
||||||
|
session_type_ == SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ class BluetoothAudioSessionControl {
|
|||||||
}
|
}
|
||||||
switch (session_type) {
|
switch (session_type) {
|
||||||
case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
case SessionType::A2DP_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
||||||
|
case SessionType::A2DP_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
||||||
return AudioConfiguration(CodecConfiguration{});
|
return AudioConfiguration(CodecConfiguration{});
|
||||||
case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_ENCODING_DATAPATH:
|
||||||
case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
case SessionType::LE_AUDIO_HARDWARE_OFFLOAD_DECODING_DATAPATH:
|
||||||
|
|||||||
Reference in New Issue
Block a user