mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 11:36:00 +00:00
Merge "AIDL effect vts test cases refinement"
This commit is contained in:
@@ -66,6 +66,7 @@ cc_defaults {
|
||||
name: "aidlaudioeffectservice_defaults",
|
||||
defaults: [
|
||||
"latest_android_media_audio_common_types_ndk_shared",
|
||||
"latest_android_hardware_audio_effect_ndk_shared",
|
||||
],
|
||||
vendor: true,
|
||||
shared_libs: [
|
||||
@@ -78,7 +79,6 @@ cc_defaults {
|
||||
"libutils",
|
||||
"android.hardware.common-V2-ndk",
|
||||
"android.hardware.common.fmq-V1-ndk",
|
||||
"android.hardware.audio.effect-V1-ndk",
|
||||
],
|
||||
header_libs: [
|
||||
"libaudioaidl_headers",
|
||||
@@ -111,10 +111,11 @@ cc_binary {
|
||||
"libbassboostsw",
|
||||
"libbundleaidl",
|
||||
"libdynamicsprocessingsw",
|
||||
"libenvreverbsw",
|
||||
"libequalizersw",
|
||||
"libhapticgeneratorsw",
|
||||
"libloudnessenhancersw",
|
||||
"libreverbsw",
|
||||
"libpresetreverbsw",
|
||||
"libtinyxml2",
|
||||
"libvirtualizersw",
|
||||
"libvisualizersw",
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
<library name="equalizersw" path="libequalizersw.so"/>
|
||||
<library name="haptic_generatorsw" path="libhapticgeneratorsw.so"/>
|
||||
<library name="loudness_enhancersw" path="libloudnessenhancersw.so"/>
|
||||
<library name="reverbsw" path="libreverbsw.so"/>
|
||||
<library name="env_reverbsw" path="libenvreverbsw.so"/>
|
||||
<library name="preset_reverbsw" path="libpresetreverbsw.so"/>
|
||||
<library name="virtualizersw" path="libvirtualizersw.so"/>
|
||||
<library name="visualizersw" path="libvisualizersw.so"/>
|
||||
<library name="volumesw" path="libvolumesw.so"/>
|
||||
@@ -64,11 +65,12 @@
|
||||
<effect name="dynamics_processing" library="dynamics_processingsw" uuid="fa818d78-588b-11ed-9b6a-0242ac120002"/>
|
||||
<effect name="haptic_generator" library="haptic_generatorsw" uuid="fa819110-588b-11ed-9b6a-0242ac120002"/>
|
||||
<effect name="loudness_enhancer" library="loudness_enhancersw" uuid="fa819610-588b-11ed-9b6a-0242ac120002"/>
|
||||
<effect name="reverb" library="reverbsw" uuid="fa8199c6-588b-11ed-9b6a-0242ac120002"/>
|
||||
<effect name="env_reverb" library="env_reverbsw" uuid="fa819886-588b-11ed-9b6a-0242ac120002"/>
|
||||
<effect name="preset_reverb" library="preset_reverbsw" uuid="fa8199c6-588b-11ed-9b6a-0242ac120002"/>
|
||||
<effect name="virtualizer" library="virtualizersw" uuid="fa819d86-588b-11ed-9b6a-0242ac120002"/>
|
||||
<effect name="visualizer" library="visualizersw" uuid="fa81a0f6-588b-11ed-9b6a-0242ac120002"/>
|
||||
<effect name="volume" library="volumesw" uuid="fa81a718-588b-11ed-9b6a-0242ac120002"/>
|
||||
<effectProxy name="equalizer" uuid="14804144-a5ee-4d24-aa88-0002a5d5c51b">
|
||||
<effectProxy name="equalizer" uuid="c8e70ecd-48ca-456e-8a4f-0002a5d5c51b">
|
||||
<libsw library="equalizersw" uuid="0bed4300-847d-11df-bb17-0002a5d5c51b"/>
|
||||
<libsw library="bundle" uuid="ce772f20-847d-11df-bb17-0002a5d5c51b"/>
|
||||
</effectProxy>
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
#include "BassBoostSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::BassBoostSw;
|
||||
using aidl::android::hardware::audio::effect::BassBoostSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::kBassBoostSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != BassBoostSwImplUUID) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != kBassBoostSwImplUUID) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ class BassBoostSw final : public EffectImpl {
|
||||
public:
|
||||
BassBoostSw() { LOG(DEBUG) << __func__; }
|
||||
~BassBoostSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
@@ -57,13 +57,14 @@ class BassBoostSw final : public EffectImpl {
|
||||
const BassBoost::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = BassBoostTypeUUID,
|
||||
.uuid = BassBoostSwImplUUID,
|
||||
.common = {.id = {.type = kBassBoostTypeUUID,
|
||||
.uuid = kBassBoostSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "BassBoostSw"},
|
||||
.name = "BassBoostSw",
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = Capability::make<Capability::bassBoost>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
#include "DynamicsProcessingSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::DynamicsProcessingSw;
|
||||
using aidl::android::hardware::audio::effect::DynamicsProcessingSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::kDynamicsProcessingSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != DynamicsProcessingSwImplUUID) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != kDynamicsProcessingSwImplUUID) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ class DynamicsProcessingSw final : public EffectImpl {
|
||||
public:
|
||||
DynamicsProcessingSw() { LOG(DEBUG) << __func__; }
|
||||
~DynamicsProcessingSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
@@ -57,13 +57,14 @@ class DynamicsProcessingSw final : public EffectImpl {
|
||||
const DynamicsProcessing::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = DynamicsProcessingTypeUUID,
|
||||
.uuid = DynamicsProcessingSwImplUUID,
|
||||
.common = {.id = {.type = kDynamicsProcessingTypeUUID,
|
||||
.uuid = kDynamicsProcessingSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "DynamicsProcessingSw"},
|
||||
.name = "DynamicsProcessingSw",
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = Capability::make<Capability::dynamicsProcessing>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
|
||||
@@ -24,14 +24,14 @@ package {
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libreverbsw",
|
||||
name: "libenvreverbsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
"latest_android_media_audio_common_types_ndk_shared",
|
||||
"latest_android_hardware_audio_effect_ndk_shared",
|
||||
],
|
||||
srcs: [
|
||||
"ReverbSw.cpp",
|
||||
"EnvReverbSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
visibility: [
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#define LOG_TAG "AHAL_ReverbSw"
|
||||
#define LOG_TAG "AHAL_EnvReverbSw"
|
||||
#include <Utils.h>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
@@ -23,22 +23,22 @@
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include "ReverbSw.h"
|
||||
#include "EnvReverbSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::EnvReverbSw;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::ReverbSw;
|
||||
using aidl::android::hardware::audio::effect::ReverbSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::kEnvReverbSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != ReverbSwImplUUID) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != kEnvReverbSwImplUUID) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<ReverbSw>();
|
||||
*instanceSpp = ndk::SharedRefBase::make<EnvReverbSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
@@ -64,13 +64,13 @@ extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& inst
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
ndk::ScopedAStatus ReverbSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
ndk::ScopedAStatus EnvReverbSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus ReverbSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
ndk::ScopedAStatus EnvReverbSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::reverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
std::lock_guard lg(mMutex);
|
||||
@@ -81,24 +81,24 @@ ndk::ScopedAStatus ReverbSw::setParameterSpecific(const Parameter::Specific& spe
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus ReverbSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
ndk::ScopedAStatus EnvReverbSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::reverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
specific->set<Parameter::Specific::reverb>(mSpecificParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> ReverbSw::createContext(const Parameter::Common& common) {
|
||||
std::shared_ptr<EffectContext> EnvReverbSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
return mContext;
|
||||
}
|
||||
mContext = std::make_shared<ReverbSwContext>(1 /* statusFmqDepth */, common);
|
||||
mContext = std::make_shared<EnvReverbSwContext>(1 /* statusFmqDepth */, common);
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode ReverbSw::releaseContext() {
|
||||
RetCode EnvReverbSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
@@ -106,7 +106,7 @@ RetCode ReverbSw::releaseContext() {
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status ReverbSw::effectProcessImpl(float* in, float* out, int process) {
|
||||
IEffect::Status EnvReverbSw::effectProcessImpl(float* in, float* out, int process) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
|
||||
for (int i = 0; i < process; i++) {
|
||||
@@ -26,21 +26,21 @@
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class ReverbSwContext final : public EffectContext {
|
||||
class EnvReverbSwContext final : public EffectContext {
|
||||
public:
|
||||
ReverbSwContext(int statusDepth, const Parameter::Common& common)
|
||||
EnvReverbSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
// TODO: add specific context here
|
||||
};
|
||||
|
||||
class ReverbSw final : public EffectImpl {
|
||||
class EnvReverbSw final : public EffectImpl {
|
||||
public:
|
||||
ReverbSw() { LOG(DEBUG) << __func__; }
|
||||
~ReverbSw() {
|
||||
EnvReverbSw() { LOG(DEBUG) << __func__; }
|
||||
~EnvReverbSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
@@ -52,18 +52,19 @@ class ReverbSw final : public EffectImpl {
|
||||
RetCode releaseContext() override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ReverbSwContext> mContext;
|
||||
std::shared_ptr<EnvReverbSwContext> mContext;
|
||||
/* capabilities */
|
||||
const Reverb::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = ReverbTypeUUID,
|
||||
.uuid = ReverbSwImplUUID,
|
||||
.common = {.id = {.type = kEnvReverbTypeUUID,
|
||||
.uuid = kEnvReverbSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "ReverbSw"},
|
||||
.name = "EnvReverbSw",
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = Capability::make<Capability::reverb>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
@@ -26,14 +26,14 @@
|
||||
#include "EqualizerSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::EqualizerSw;
|
||||
using aidl::android::hardware::audio::effect::EqualizerSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::kEqualizerSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != EqualizerSwImplUUID) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != kEqualizerSwImplUUID) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
@@ -82,8 +82,8 @@ class EqualizerSw final : public EffectImpl {
|
||||
public:
|
||||
EqualizerSw() { LOG(DEBUG) << __func__; }
|
||||
~EqualizerSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
@@ -109,13 +109,14 @@ class EqualizerSw final : public EffectImpl {
|
||||
|
||||
const Equalizer::Capability kEqCap = {.bandFrequencies = mBandFrequency, .presets = mPresets};
|
||||
// Effect descriptor.
|
||||
const Descriptor kDesc = {.common = {.id = {.type = EqualizerTypeUUID,
|
||||
.uuid = EqualizerSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
const Descriptor kDesc = {.common = {.id = {.type = kEqualizerTypeUUID,
|
||||
.uuid = kEqualizerSwImplUUID,
|
||||
.proxy = kEqualizerProxyUUID},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "EqualizerSw"},
|
||||
.name = "EqualizerSw",
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = Capability::make<Capability::equalizer>(kEqCap)};
|
||||
|
||||
ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
#include "HapticGeneratorSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::HapticGeneratorSw;
|
||||
using aidl::android::hardware::audio::effect::HapticGeneratorSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::kHapticGeneratorSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != HapticGeneratorSwImplUUID) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != kHapticGeneratorSwImplUUID) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ class HapticGeneratorSw final : public EffectImpl {
|
||||
public:
|
||||
HapticGeneratorSw() { LOG(DEBUG) << __func__; }
|
||||
~HapticGeneratorSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
@@ -57,13 +57,14 @@ class HapticGeneratorSw final : public EffectImpl {
|
||||
const HapticGenerator::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = HapticGeneratorTypeUUID,
|
||||
.uuid = HapticGeneratorSwImplUUID,
|
||||
.common = {.id = {.type = kHapticGeneratorTypeUUID,
|
||||
.uuid = kHapticGeneratorSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "HapticGeneratorSw"},
|
||||
.name = "HapticGeneratorSw",
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = Capability::make<Capability::hapticGenerator>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
|
||||
@@ -30,11 +30,8 @@ namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class EffectImpl : public BnEffect, public EffectWorker {
|
||||
public:
|
||||
EffectImpl() { LOG(DEBUG) << __func__; }
|
||||
~EffectImpl() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
EffectImpl() = default;
|
||||
virtual ~EffectImpl() = default;
|
||||
|
||||
/**
|
||||
* Each effect implementation CAN override these methods if necessary
|
||||
@@ -78,9 +75,9 @@ class EffectImpl : public BnEffect, public EffectWorker {
|
||||
State mState GUARDED_BY(mMutex) = State::INIT;
|
||||
|
||||
IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
|
||||
void cleanUp();
|
||||
|
||||
private:
|
||||
void cleanUp();
|
||||
std::shared_ptr<EffectContext> mContext GUARDED_BY(mMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
|
||||
@@ -23,150 +23,160 @@ namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
using ::aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
// Null UUID
|
||||
static const AudioUuid EffectNullUuid = {static_cast<int32_t>(0xec7178ec),
|
||||
0xe5e1,
|
||||
0x4432,
|
||||
0xa3f4,
|
||||
{0x46, 0x57, 0xe6, 0x79, 0x52, 0x10}};
|
||||
|
||||
// ec7178ec-e5e1-4432-a3f4-4657e6795210
|
||||
static const AudioUuid kEffectNullUuid = {static_cast<int32_t>(0xec7178ec),
|
||||
0xe5e1,
|
||||
0x4432,
|
||||
0xa3f4,
|
||||
{0x46, 0x57, 0xe6, 0x79, 0x52, 0x10}};
|
||||
// Zero UUID
|
||||
static const AudioUuid EffectZeroUuid = {
|
||||
static const AudioUuid kEffectZeroUuid = {
|
||||
static_cast<int32_t>(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
|
||||
|
||||
// Equalizer type UUID.
|
||||
static const AudioUuid EqualizerTypeUUID = {static_cast<int32_t>(0x0bed4300),
|
||||
0xddd6,
|
||||
0x11db,
|
||||
0x8f34,
|
||||
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
|
||||
|
||||
// 0bed4300-847d-11df-bb17-0002a5d5c51b
|
||||
static const AudioUuid EqualizerSwImplUUID = {static_cast<int32_t>(0x0bed4300),
|
||||
0x847d,
|
||||
0x11df,
|
||||
0xbb17,
|
||||
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
|
||||
|
||||
// ce772f20-847d-11df-bb17-0002a5d5c51b
|
||||
static const AudioUuid EqualizerBundleImplUUID = {static_cast<int32_t>(0xce772f20),
|
||||
0x847d,
|
||||
0x11df,
|
||||
0xbb17,
|
||||
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
|
||||
|
||||
// fa8184a4-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid BassBoostTypeUUID = {static_cast<int32_t>(0xfa8184a4),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// 0634f220-ddd4-11db-a0fc-0002a5d5c51b
|
||||
static const AudioUuid kBassBoostTypeUUID = {static_cast<int32_t>(0x0634f220),
|
||||
0xddd4,
|
||||
0x11db,
|
||||
0xa0fc,
|
||||
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
|
||||
// fa8181f2-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid BassBoostSwImplUUID = {static_cast<int32_t>(0xfa8181f2),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa81862a-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid DownmixTypeUUID = {static_cast<int32_t>(0xfa81862a),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa8187ba-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid DownmixSwImplUUID = {static_cast<int32_t>(0xfa8187ba),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa818954-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid DynamicsProcessingTypeUUID = {static_cast<int32_t>(0xfa818954),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa818d78-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid DynamicsProcessingSwImplUUID = {static_cast<int32_t>(0xfa818d78),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa818f62-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid HapticGeneratorTypeUUID = {static_cast<int32_t>(0xfa818f62),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa819110-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid HapticGeneratorSwImplUUID = {static_cast<int32_t>(0xfa819110),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
|
||||
// fa8194a8-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid LoudnessEnhancerTypeUUID = {static_cast<int32_t>(0xfa8194a8),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa819610-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid LoudnessEnhancerSwImplUUID = {static_cast<int32_t>(0xfa819610),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa819886-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid ReverbTypeUUID = {static_cast<int32_t>(0xfa819886),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa8199c6-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid ReverbSwImplUUID = {static_cast<int32_t>(0xfa8199c6),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
|
||||
// fa819af2-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid VirtualizerTypeUUID = {static_cast<int32_t>(0xfa819af2),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa819d86-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid VirtualizerSwImplUUID = {static_cast<int32_t>(0xfa819d86),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
|
||||
// fa819f3e-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid VisualizerTypeUUID = {static_cast<int32_t>(0xfa819f3e),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa81a0f6-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid VisualizerSwImplUUID = {static_cast<int32_t>(0xfa81a0f6),
|
||||
static const AudioUuid kBassBoostSwImplUUID = {static_cast<int32_t>(0xfa8181f2),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
|
||||
// fa81a2b8-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid VolumeTypeUUID = {static_cast<int32_t>(0xfa81a2b8),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa81a718-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid VolumeSwImplUUID = {static_cast<int32_t>(0xfa81a718),
|
||||
// fa81862a-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid kDownmixTypeUUID = {static_cast<int32_t>(0xfa81862a),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa8187ba-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid kDownmixSwImplUUID = {static_cast<int32_t>(0xfa8187ba),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// 0bed4300-ddd6-11db-8f34-0002a5d5c51b.
|
||||
static const AudioUuid kEqualizerTypeUUID = {static_cast<int32_t>(0x0bed4300),
|
||||
0xddd6,
|
||||
0x11db,
|
||||
0x8f34,
|
||||
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
|
||||
// 0bed4300-847d-11df-bb17-0002a5d5c51b
|
||||
static const AudioUuid kEqualizerSwImplUUID = {static_cast<int32_t>(0x0bed4300),
|
||||
0x847d,
|
||||
0x11df,
|
||||
0xbb17,
|
||||
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
|
||||
// ce772f20-847d-11df-bb17-0002a5d5c51b
|
||||
static const AudioUuid kEqualizerBundleImplUUID = {static_cast<int32_t>(0xce772f20),
|
||||
0x847d,
|
||||
0x11df,
|
||||
0xbb17,
|
||||
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
|
||||
// c8e70ecd-48ca-456e-8a4f-0002a5d5c51b
|
||||
static const AudioUuid kEqualizerProxyUUID = {static_cast<int32_t>(0xc8e70ecd),
|
||||
0x48ca,
|
||||
0x456e,
|
||||
0x8a4f,
|
||||
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
|
||||
// 7261676f-6d75-7369-6364-28e2fd3ac39e
|
||||
static const AudioUuid kDynamicsProcessingTypeUUID = {static_cast<int32_t>(0x7261676f),
|
||||
0x6d75,
|
||||
0x7369,
|
||||
0x6364,
|
||||
{0x28, 0xe2, 0xfd, 0x3a, 0xc3, 0x9e}};
|
||||
// fa818d78-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid kDynamicsProcessingSwImplUUID = {static_cast<int32_t>(0xfa818d78),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// 1411e6d6-aecd-4021-a1cf-a6aceb0d71e5
|
||||
static const AudioUuid kHapticGeneratorTypeUUID = {static_cast<int32_t>(0x1411e6d6),
|
||||
0xaecd,
|
||||
0x4021,
|
||||
0xa1cf,
|
||||
{0xa6, 0xac, 0xeb, 0x0d, 0x71, 0xe5}};
|
||||
// fa819110-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid kHapticGeneratorSwImplUUID = {static_cast<int32_t>(0xfa819110),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fe3199be-aed0-413f-87bb-11260eb63cf1
|
||||
static const AudioUuid kLoudnessEnhancerTypeUUID = {static_cast<int32_t>(0xfe3199be),
|
||||
0xaed0,
|
||||
0x413f,
|
||||
0x87bb,
|
||||
{0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}};
|
||||
// fa819610-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid kLoudnessEnhancerSwImplUUID = {static_cast<int32_t>(0xfa819610),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// c2e5d5f0-94bd-4763-9cac-4e234d06839e
|
||||
static const AudioUuid kEnvReverbTypeUUID = {static_cast<int32_t>(0xc2e5d5f0),
|
||||
0x94bd,
|
||||
0x4763,
|
||||
0x9cac,
|
||||
{0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}};
|
||||
// fa819886-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid kEnvReverbSwImplUUID = {static_cast<int32_t>(0xfa819886),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// 47382d60-ddd8-11db-bf3a-0002a5d5c51b
|
||||
static const AudioUuid kPresetReverbTypeUUID = {static_cast<int32_t>(0x47382d60),
|
||||
0xddd8,
|
||||
0x11db,
|
||||
0xbf3a,
|
||||
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
|
||||
// fa8199c6-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid kPresetReverbSwImplUUID = {static_cast<int32_t>(0xfa8199c6),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// 37cc2c00-dddd-11db-8577-0002a5d5c51b
|
||||
static const AudioUuid kVirtualizerTypeUUID = {static_cast<int32_t>(0x37cc2c00),
|
||||
0xdddd,
|
||||
0x11db,
|
||||
0x8577,
|
||||
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
|
||||
// fa819d86-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid kVirtualizerSwImplUUID = {static_cast<int32_t>(0xfa819d86),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa819f3e-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid kVisualizerTypeUUID = {static_cast<int32_t>(0xfa819f3e),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa81a0f6-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid kVisualizerSwImplUUID = {static_cast<int32_t>(0xfa81a0f6),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa81a2b8-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid kVolumeTypeUUID = {static_cast<int32_t>(0xfa81a2b8),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
// fa81a718-588b-11ed-9b6a-0242ac120002
|
||||
static const AudioUuid kVolumeSwImplUUID = {static_cast<int32_t>(0xfa81a718),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
|
||||
/**
|
||||
* @brief A map between effect name and effect type UUID.
|
||||
@@ -174,20 +184,21 @@ static const AudioUuid VolumeSwImplUUID = {static_cast<int32_t>(0xfa81a718),
|
||||
* We need this map is because existing audio_effects.xml don't have a type UUID defined.
|
||||
*/
|
||||
static const std::map<const std::string /* effect type */, const AudioUuid&> kUuidNameTypeMap = {
|
||||
{"bassboost", BassBoostTypeUUID},
|
||||
{"downmix", DownmixTypeUUID},
|
||||
{"dynamics_processing", DynamicsProcessingTypeUUID},
|
||||
{"equalizer", EqualizerTypeUUID},
|
||||
{"haptic_generator", HapticGeneratorTypeUUID},
|
||||
{"loudness_enhancer", LoudnessEnhancerTypeUUID},
|
||||
{"reverb", ReverbTypeUUID},
|
||||
{"reverb_env_aux", ReverbTypeUUID},
|
||||
{"reverb_env_ins", ReverbTypeUUID},
|
||||
{"reverb_pre_aux", ReverbTypeUUID},
|
||||
{"reverb_pre_ins", ReverbTypeUUID},
|
||||
{"virtualizer", VirtualizerTypeUUID},
|
||||
{"visualizer", VisualizerTypeUUID},
|
||||
{"volume", VolumeTypeUUID},
|
||||
{"bassboost", kBassBoostTypeUUID},
|
||||
{"downmix", kDownmixTypeUUID},
|
||||
{"dynamics_processing", kDynamicsProcessingTypeUUID},
|
||||
{"equalizer", kEqualizerTypeUUID},
|
||||
{"haptic_generator", kHapticGeneratorTypeUUID},
|
||||
{"loudness_enhancer", kLoudnessEnhancerTypeUUID},
|
||||
{"env_reverb", kEnvReverbTypeUUID},
|
||||
{"preset_reverb", kPresetReverbTypeUUID},
|
||||
{"reverb_env_aux", kEnvReverbTypeUUID},
|
||||
{"reverb_env_ins", kEnvReverbTypeUUID},
|
||||
{"reverb_pre_aux", kPresetReverbTypeUUID},
|
||||
{"reverb_pre_ins", kPresetReverbTypeUUID},
|
||||
{"virtualizer", kVirtualizerTypeUUID},
|
||||
{"visualizer", kVisualizerTypeUUID},
|
||||
{"volume", kVolumeTypeUUID},
|
||||
};
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
#include "LoudnessEnhancerSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::kLoudnessEnhancerSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::LoudnessEnhancerSw;
|
||||
using aidl::android::hardware::audio::effect::LoudnessEnhancerSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != LoudnessEnhancerSwImplUUID) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != kLoudnessEnhancerSwImplUUID) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
@@ -48,8 +48,8 @@ class LoudnessEnhancerSw final : public EffectImpl {
|
||||
public:
|
||||
LoudnessEnhancerSw() { LOG(DEBUG) << __func__; }
|
||||
~LoudnessEnhancerSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
@@ -66,13 +66,14 @@ class LoudnessEnhancerSw final : public EffectImpl {
|
||||
const LoudnessEnhancer::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = LoudnessEnhancerTypeUUID,
|
||||
.uuid = LoudnessEnhancerSwImplUUID,
|
||||
.common = {.id = {.type = kLoudnessEnhancerTypeUUID,
|
||||
.uuid = kLoudnessEnhancerSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "LoudnessEnhancerSw"},
|
||||
.name = "LoudnessEnhancerSw",
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = Capability::make<Capability::loudnessEnhancer>(kCapability)};
|
||||
|
||||
ndk::ScopedAStatus getParameterLoudnessEnhancer(const LoudnessEnhancer::Tag& tag,
|
||||
|
||||
40
audio/aidl/default/presetReverb/Android.bp
Normal file
40
audio/aidl/default/presetReverb/Android.bp
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package {
|
||||
// See: http://go/android-license-faq
|
||||
// A large-scale-change added 'default_applicable_licenses' to import
|
||||
// all of the 'license_kinds' from "hardware_interfaces_license"
|
||||
// to get the below license kinds:
|
||||
// SPDX-license-identifier-Apache-2.0
|
||||
default_applicable_licenses: ["hardware_interfaces_license"],
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libpresetreverbsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
"latest_android_media_audio_common_types_ndk_shared",
|
||||
"latest_android_hardware_audio_effect_ndk_shared",
|
||||
],
|
||||
srcs: [
|
||||
"PresetReverbSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
118
audio/aidl/default/presetReverb/PresetReverbSw.cpp
Normal file
118
audio/aidl/default/presetReverb/PresetReverbSw.cpp
Normal file
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#define LOG_TAG "AHAL_PresetReverbSw"
|
||||
#include <Utils.h>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include "PresetReverbSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::kPresetReverbSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::PresetReverbSw;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != kPresetReverbSwImplUUID) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<PresetReverbSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
return EX_NONE;
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << " invalid input parameter!";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
|
||||
if (!instanceSp) {
|
||||
return EX_NONE;
|
||||
}
|
||||
State state;
|
||||
ndk::ScopedAStatus status = instanceSp->getState(&state);
|
||||
if (!status.isOk() || State::INIT != state) {
|
||||
LOG(ERROR) << __func__ << " instance " << instanceSp.get()
|
||||
<< " in state: " << toString(state) << ", status: " << status.getDescription();
|
||||
return EX_ILLEGAL_STATE;
|
||||
}
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
ndk::ScopedAStatus PresetReverbSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus PresetReverbSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::reverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
mSpecificParam = specific.get<Parameter::Specific::reverb>();
|
||||
LOG(DEBUG) << __func__ << " success with: " << specific.toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus PresetReverbSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::reverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
specific->set<Parameter::Specific::reverb>(mSpecificParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> PresetReverbSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
return mContext;
|
||||
}
|
||||
mContext = std::make_shared<PresetReverbSwContext>(1 /* statusFmqDepth */, common);
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode PresetReverbSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status PresetReverbSw::effectProcessImpl(float* in, float* out, int process) {
|
||||
// TODO: get data buffer and process.
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
|
||||
for (int i = 0; i < process; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
return {STATUS_OK, process, process};
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
73
audio/aidl/default/presetReverb/PresetReverbSw.h
Normal file
73
audio/aidl/default/presetReverb/PresetReverbSw.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
#include "effect-impl/EffectUUID.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class PresetReverbSwContext final : public EffectContext {
|
||||
public:
|
||||
PresetReverbSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
// TODO: add specific context here
|
||||
};
|
||||
|
||||
class PresetReverbSw final : public EffectImpl {
|
||||
public:
|
||||
PresetReverbSw() { LOG(DEBUG) << __func__; }
|
||||
~PresetReverbSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
|
||||
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) override;
|
||||
IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
|
||||
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
|
||||
RetCode releaseContext() override;
|
||||
|
||||
private:
|
||||
std::shared_ptr<PresetReverbSwContext> mContext;
|
||||
/* capabilities */
|
||||
const Reverb::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = kPresetReverbTypeUUID,
|
||||
.uuid = kPresetReverbSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "PresetReverbSw",
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = Capability::make<Capability::reverb>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
Reverb mSpecificParam;
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -26,14 +26,14 @@
|
||||
#include "VirtualizerSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::kVirtualizerSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::hardware::audio::effect::VirtualizerSw;
|
||||
using aidl::android::hardware::audio::effect::VirtualizerSwImplUUID;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != VirtualizerSwImplUUID) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != kVirtualizerSwImplUUID) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ class VirtualizerSw final : public EffectImpl {
|
||||
public:
|
||||
VirtualizerSw() { LOG(DEBUG) << __func__; }
|
||||
~VirtualizerSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
@@ -57,13 +57,14 @@ class VirtualizerSw final : public EffectImpl {
|
||||
const Virtualizer::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = VirtualizerTypeUUID,
|
||||
.uuid = VirtualizerSwImplUUID,
|
||||
.common = {.id = {.type = kVirtualizerTypeUUID,
|
||||
.uuid = kVirtualizerSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "VirtualizerSw"},
|
||||
.name = "VirtualizerSw",
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = Capability::make<Capability::virtualizer>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
#include "VisualizerSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::kVisualizerSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::hardware::audio::effect::VisualizerSw;
|
||||
using aidl::android::hardware::audio::effect::VisualizerSwImplUUID;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != VisualizerSwImplUUID) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != kVisualizerSwImplUUID) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ class VisualizerSw final : public EffectImpl {
|
||||
public:
|
||||
VisualizerSw() { LOG(DEBUG) << __func__; }
|
||||
~VisualizerSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
@@ -57,13 +57,14 @@ class VisualizerSw final : public EffectImpl {
|
||||
const Visualizer::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = VisualizerTypeUUID,
|
||||
.uuid = VisualizerSwImplUUID,
|
||||
.common = {.id = {.type = kVisualizerTypeUUID,
|
||||
.uuid = kVisualizerSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "VisualizerSw"},
|
||||
.name = "VisualizerSw",
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = Capability::make<Capability::visualizer>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
|
||||
@@ -26,14 +26,14 @@
|
||||
#include "VolumeSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::kVolumeSwImplUUID;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::hardware::audio::effect::VolumeSw;
|
||||
using aidl::android::hardware::audio::effect::VolumeSwImplUUID;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != VolumeSwImplUUID) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != kVolumeSwImplUUID) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
|
||||
@@ -39,8 +39,8 @@ class VolumeSw final : public EffectImpl {
|
||||
public:
|
||||
VolumeSw() { LOG(DEBUG) << __func__; }
|
||||
~VolumeSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
@@ -57,13 +57,14 @@ class VolumeSw final : public EffectImpl {
|
||||
const Volume::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = VolumeTypeUUID,
|
||||
.uuid = VolumeSwImplUUID,
|
||||
.common = {.id = {.type = kVolumeTypeUUID,
|
||||
.uuid = kVolumeSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "VolumeSw"},
|
||||
.name = "VolumeSw",
|
||||
.implementor = "The Android Open Source Project"},
|
||||
.capability = Capability::make<Capability::volume>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
|
||||
@@ -29,10 +29,7 @@
|
||||
using namespace android;
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::EffectNullUuid;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::IFactory;
|
||||
using aidl::android::hardware::audio::effect::Processing;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
class EffectFactoryHelper {
|
||||
@@ -48,122 +45,36 @@ class EffectFactoryHelper {
|
||||
ASSERT_NE(mEffectFactory, nullptr);
|
||||
mEffectFactory = IFactory::fromBinder(binderUtil.restartService());
|
||||
ASSERT_NE(mEffectFactory, nullptr);
|
||||
ClearEffectMap();
|
||||
}
|
||||
|
||||
void QueryEffects(const std::optional<AudioUuid>& in_type,
|
||||
const std::optional<AudioUuid>& in_instance,
|
||||
const std::optional<AudioUuid>& in_proxy,
|
||||
std::vector<Descriptor::Identity>* _aidl_return) {
|
||||
ASSERT_NE(mEffectFactory, nullptr);
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(in_type, in_instance, in_proxy, _aidl_return));
|
||||
mIds = *_aidl_return;
|
||||
}
|
||||
std::shared_ptr<IFactory> GetFactory() const { return mEffectFactory; }
|
||||
|
||||
void QueryProcessing(const std::optional<Processing::Type>& in_type,
|
||||
std::vector<Processing>* _aidl_return) {
|
||||
ASSERT_NE(mEffectFactory, nullptr);
|
||||
EXPECT_IS_OK(mEffectFactory->queryProcessing(in_type, _aidl_return));
|
||||
// only update the whole list if no filter applied
|
||||
if (!in_type.has_value()) {
|
||||
mProcesses = *_aidl_return;
|
||||
}
|
||||
}
|
||||
static std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>>
|
||||
getAllEffectDescriptors(std::string serviceName, std::optional<AudioUuid> type = std::nullopt) {
|
||||
AudioHalBinderServiceUtil util;
|
||||
auto names = android::getAidlHalInstanceNames(serviceName);
|
||||
std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>> result;
|
||||
|
||||
void CreateEffects() {
|
||||
for (const auto& id : mIds) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
|
||||
EXPECT_NE(effect, nullptr) << id.toString();
|
||||
if (effect) {
|
||||
mEffectIdMap[effect] = id;
|
||||
for (const auto& name : names) {
|
||||
auto factory = IFactory::fromBinder(util.connectToService(name));
|
||||
if (factory) {
|
||||
if (std::vector<Descriptor::Identity> ids;
|
||||
factory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids).isOk()) {
|
||||
for (const auto& id : ids) {
|
||||
if (type.has_value() && id.type != type.value()) {
|
||||
continue;
|
||||
}
|
||||
result.emplace_back(factory, id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QueryAndCreateEffects(const AudioUuid& type = EffectNullUuid) {
|
||||
std::vector<Descriptor::Identity> ids;
|
||||
ASSERT_NE(mEffectFactory, nullptr);
|
||||
|
||||
if (type == EffectNullUuid) {
|
||||
EXPECT_IS_OK(
|
||||
mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
|
||||
} else {
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(type, std::nullopt, std::nullopt, &ids));
|
||||
}
|
||||
for (const auto& id : ids) {
|
||||
ASSERT_EQ(id.type, type);
|
||||
std::shared_ptr<IEffect> effect;
|
||||
EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
|
||||
EXPECT_NE(effect, nullptr) << id.toString();
|
||||
if (effect) {
|
||||
mEffectIdMap[effect] = id;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void CreateEffectsAndExpect(
|
||||
const std::vector<std::pair<Descriptor::Identity, binder_exception_t>>& uuid_status) {
|
||||
ASSERT_NE(mEffectFactory, nullptr);
|
||||
for (const auto& it : uuid_status) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
auto status = mEffectFactory->createEffect(it.first.uuid, &effect);
|
||||
EXPECT_STATUS(it.second, status);
|
||||
if (effect) {
|
||||
mEffectIdMap[effect] = it.first;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyEffectAndExpect(std::shared_ptr<IEffect>& instance, binder_exception_t exception) {
|
||||
ASSERT_NE(mEffectFactory, nullptr);
|
||||
auto status = mEffectFactory->destroyEffect(instance);
|
||||
EXPECT_STATUS(exception, status);
|
||||
}
|
||||
|
||||
void QueryAndCreateAllEffects() {
|
||||
ASSERT_NE(mEffectFactory, nullptr);
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt,
|
||||
&mCompleteIds));
|
||||
for (const auto& id : mCompleteIds) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
|
||||
EXPECT_NE(effect, nullptr) << id.toString();
|
||||
mEffectIdMap[effect] = id;
|
||||
}
|
||||
}
|
||||
|
||||
void DestroyEffects(const binder_exception_t expected = EX_NONE, const int remaining = 0) {
|
||||
ASSERT_NE(mEffectFactory, nullptr);
|
||||
|
||||
for (auto it = mEffectIdMap.begin(); it != mEffectIdMap.end();) {
|
||||
auto erased = it++;
|
||||
auto status = mEffectFactory->destroyEffect(erased->first);
|
||||
EXPECT_STATUS(expected, status);
|
||||
if (status.isOk()) {
|
||||
mEffectIdMap.erase(erased);
|
||||
}
|
||||
}
|
||||
EXPECT_EQ((unsigned int)remaining, mEffectIdMap.size());
|
||||
}
|
||||
|
||||
std::shared_ptr<IFactory> GetFactory() { return mEffectFactory; }
|
||||
const std::vector<Descriptor::Identity>& GetEffectIds() { return mIds; }
|
||||
const std::vector<Descriptor::Identity>& GetCompleteEffectIdList() const {
|
||||
return mCompleteIds;
|
||||
}
|
||||
const std::map<std::shared_ptr<IEffect>, Descriptor::Identity>& GetEffectMap() const {
|
||||
return mEffectIdMap;
|
||||
}
|
||||
void ClearEffectMap() { mEffectIdMap.clear(); }
|
||||
|
||||
private:
|
||||
std::shared_ptr<IFactory> mEffectFactory;
|
||||
std::string mServiceName;
|
||||
AudioHalBinderServiceUtil binderUtil;
|
||||
std::vector<Descriptor::Identity> mIds;
|
||||
std::vector<Descriptor::Identity> mCompleteIds;
|
||||
std::vector<Processing> mProcesses;
|
||||
|
||||
std::map<std::shared_ptr<IEffect>, Descriptor::Identity> mEffectIdMap;
|
||||
};
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
@@ -24,7 +25,6 @@
|
||||
#include <aidl/android/hardware/audio/effect/IEffect.h>
|
||||
#include <aidl/android/hardware/audio/effect/IFactory.h>
|
||||
#include <aidl/android/media/audio/common/AudioChannelLayout.h>
|
||||
#include <aidl/android/media/audio/common/AudioDeviceType.h>
|
||||
#include <android/binder_auto_utils.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
@@ -35,275 +35,139 @@
|
||||
using namespace android;
|
||||
using aidl::android::hardware::audio::effect::CommandId;
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::EffectNullUuid;
|
||||
using aidl::android::hardware::audio::effect::EffectZeroUuid;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::Parameter;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
|
||||
using aidl::android::media::audio::common::AudioChannelLayout;
|
||||
using aidl::android::media::audio::common::AudioDeviceType;
|
||||
using aidl::android::media::audio::common::AudioFormatDescription;
|
||||
using aidl::android::media::audio::common::AudioFormatType;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
using aidl::android::media::audio::common::PcmType;
|
||||
|
||||
const AudioFormatDescription DefaultFormat = {
|
||||
const AudioFormatDescription kDefaultFormatDescription = {
|
||||
.type = AudioFormatType::PCM, .pcm = PcmType::FLOAT_32_BIT, .encoding = ""};
|
||||
|
||||
typedef ::android::AidlMessageQueue<IEffect::Status,
|
||||
::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
|
||||
StatusMQ;
|
||||
typedef ::android::AidlMessageQueue<float,
|
||||
::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
|
||||
DataMQ;
|
||||
|
||||
class EffectHelper {
|
||||
public:
|
||||
explicit EffectHelper(const std::string& name) : mFactoryHelper(EffectFactoryHelper(name)) {
|
||||
mFactoryHelper.ConnectToFactoryService();
|
||||
static void create(std::shared_ptr<IFactory> factory, std::shared_ptr<IEffect>& effect,
|
||||
Descriptor::Identity id, binder_status_t status = EX_NONE) {
|
||||
ASSERT_NE(factory, nullptr);
|
||||
EXPECT_STATUS(status, factory->createEffect(id.uuid, &effect));
|
||||
if (status == EX_NONE) {
|
||||
ASSERT_NE(effect, nullptr) << id.uuid.toString();
|
||||
}
|
||||
}
|
||||
|
||||
void OpenEffects(const AudioUuid& type = EffectNullUuid) {
|
||||
auto open = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
IEffect::OpenEffectReturn ret;
|
||||
EXPECT_IS_OK(effect->open(mCommon, mSpecific, &ret));
|
||||
EffectParam params;
|
||||
params.statusMQ = std::make_unique<StatusMQ>(ret.statusMQ);
|
||||
params.inputMQ = std::make_unique<DataMQ>(ret.inputDataMQ);
|
||||
params.outputMQ = std::make_unique<DataMQ>(ret.outputDataMQ);
|
||||
mEffectParams.push_back(std::move(params));
|
||||
};
|
||||
EXPECT_NO_FATAL_FAILURE(ForEachEffect(open, type));
|
||||
static void destroy(std::shared_ptr<IFactory> factory, std::shared_ptr<IEffect> effect,
|
||||
binder_status_t status = EX_NONE) {
|
||||
ASSERT_NE(factory, nullptr);
|
||||
ASSERT_NE(effect, nullptr);
|
||||
EXPECT_STATUS(status, factory->destroyEffect(effect));
|
||||
}
|
||||
|
||||
void CloseEffects(const binder_status_t status = EX_NONE) {
|
||||
auto close = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
static void open(std::shared_ptr<IEffect> effect, const Parameter::Common& common,
|
||||
const std::optional<Parameter::Specific>& specific,
|
||||
IEffect::OpenEffectReturn* ret, binder_status_t status = EX_NONE) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
EXPECT_STATUS(status, effect->open(common, specific, ret));
|
||||
}
|
||||
|
||||
static void open(std::shared_ptr<IEffect> effect, int session = 0,
|
||||
binder_status_t status = EX_NONE) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
Parameter::Common common = EffectHelper::createParamCommon(session);
|
||||
IEffect::OpenEffectReturn ret;
|
||||
open(effect, common, std::nullopt /* specific */, &ret, status);
|
||||
}
|
||||
|
||||
static void close(std::shared_ptr<IEffect> effect, binder_status_t status = EX_NONE) {
|
||||
if (effect) {
|
||||
EXPECT_STATUS(status, effect->close());
|
||||
};
|
||||
|
||||
EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
|
||||
}
|
||||
|
||||
void CreateEffects(const int n = 1) {
|
||||
for (int i = 0; i < n; i++) {
|
||||
ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateAllEffects());
|
||||
}
|
||||
}
|
||||
|
||||
void CreateEffectsWithUUID(const AudioUuid& type = EffectNullUuid) {
|
||||
ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateEffects(type));
|
||||
static void getDescriptor(std::shared_ptr<IEffect> effect, Descriptor& desc,
|
||||
binder_status_t status = EX_NONE) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
EXPECT_STATUS(status, effect->getDescriptor(&desc));
|
||||
}
|
||||
|
||||
void QueryEffects() { ASSERT_NO_FATAL_FAILURE(mFactoryHelper.QueryAndCreateAllEffects()); }
|
||||
|
||||
void DestroyEffects(const binder_status_t status = EX_NONE, const int remaining = 0) {
|
||||
ASSERT_NO_FATAL_FAILURE(mFactoryHelper.DestroyEffects(status, remaining));
|
||||
mEffectDescriptors.clear();
|
||||
static void expectState(std::shared_ptr<IEffect> effect, State expectState,
|
||||
binder_status_t status = EX_NONE) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
State state;
|
||||
EXPECT_STATUS(status, effect->getState(&state));
|
||||
EXPECT_EQ(expectState, state);
|
||||
}
|
||||
|
||||
void GetEffectDescriptors() {
|
||||
auto get = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
Descriptor desc;
|
||||
EXPECT_IS_OK(effect->getDescriptor(&desc));
|
||||
mEffectDescriptors.push_back(std::move(desc));
|
||||
};
|
||||
EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
|
||||
static void command(std::shared_ptr<IEffect> effect, CommandId command,
|
||||
binder_status_t status = EX_NONE) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
EXPECT_STATUS(status, effect->command(command));
|
||||
}
|
||||
|
||||
void CommandEffects(CommandId command) {
|
||||
auto close = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
EXPECT_IS_OK(effect->command(command));
|
||||
};
|
||||
EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
|
||||
static void allocateInputData(const Parameter::Common common, std::unique_ptr<DataMQ>& mq,
|
||||
std::vector<float>& buffer) {
|
||||
ASSERT_NE(mq, nullptr);
|
||||
auto frameSize = android::hardware::audio::common::getFrameSizeInBytes(
|
||||
common.input.base.format, common.input.base.channelMask);
|
||||
const size_t floatsToWrite = mq->availableToWrite();
|
||||
EXPECT_NE(0UL, floatsToWrite);
|
||||
EXPECT_EQ(frameSize * common.input.frameCount, floatsToWrite * sizeof(float));
|
||||
buffer.resize(floatsToWrite);
|
||||
std::fill(buffer.begin(), buffer.end(), 0x5a);
|
||||
}
|
||||
|
||||
void CommandEffectsExpectStatus(CommandId command, const binder_status_t status) {
|
||||
auto func = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
EXPECT_STATUS(status, effect->command(command));
|
||||
};
|
||||
EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
|
||||
static void writeToFmq(std::unique_ptr<DataMQ>& mq, const std::vector<float>& buffer) {
|
||||
const size_t available = mq->availableToWrite();
|
||||
EXPECT_NE(0Ul, available);
|
||||
auto bufferFloats = buffer.size();
|
||||
auto floatsToWrite = std::min(available, bufferFloats);
|
||||
EXPECT_TRUE(mq->write(buffer.data(), floatsToWrite));
|
||||
}
|
||||
|
||||
void ExpectState(State expected) {
|
||||
auto get = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
State state = State::INIT;
|
||||
EXPECT_IS_OK(effect->getState(&state));
|
||||
EXPECT_EQ(expected, state);
|
||||
};
|
||||
EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
|
||||
}
|
||||
|
||||
void SetParameter() {
|
||||
auto func = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
Parameter param;
|
||||
param.set<Parameter::common>(mCommon);
|
||||
EXPECT_IS_OK(effect->setParameter(param));
|
||||
};
|
||||
EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
|
||||
}
|
||||
|
||||
void VerifyParameters() {
|
||||
auto func = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
Parameter paramCommonGet = Parameter(), paramCommonExpect = Parameter();
|
||||
Parameter::Id id;
|
||||
id.set<Parameter::Id::commonTag>(Parameter::common);
|
||||
paramCommonExpect.set<Parameter::common>(mCommon);
|
||||
EXPECT_IS_OK(effect->getParameter(id, ¶mCommonGet));
|
||||
EXPECT_EQ(paramCommonExpect, paramCommonGet)
|
||||
<< paramCommonExpect.toString() << " vs " << paramCommonGet.toString();
|
||||
};
|
||||
EXPECT_NO_FATAL_FAILURE(ForEachEffect(func));
|
||||
}
|
||||
|
||||
void QueryEffects(const std::optional<AudioUuid>& in_type,
|
||||
const std::optional<AudioUuid>& in_instance,
|
||||
const std::optional<AudioUuid>& in_proxy,
|
||||
std::vector<Descriptor::Identity>* _aidl_return) {
|
||||
mFactoryHelper.QueryEffects(in_type, in_instance, in_proxy, _aidl_return);
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
void ForEachEffect(Functor functor, const std::optional<AudioUuid>& type = EffectNullUuid) {
|
||||
auto effectMap = mFactoryHelper.GetEffectMap();
|
||||
for (const auto& it : effectMap) {
|
||||
SCOPED_TRACE(it.second.toString());
|
||||
if (type != EffectNullUuid && it.second.type != type) continue;
|
||||
functor(it.first);
|
||||
static void readFromFmq(std::unique_ptr<StatusMQ>& statusMq, size_t statusNum,
|
||||
std::unique_ptr<DataMQ>& dataMq, size_t expectFloats,
|
||||
std::vector<float>& buffer) {
|
||||
IEffect::Status status{};
|
||||
EXPECT_TRUE(statusMq->readBlocking(&status, statusNum));
|
||||
EXPECT_EQ(STATUS_OK, status.status);
|
||||
if (statusNum != 0) {
|
||||
EXPECT_EQ(expectFloats, (unsigned)status.fmqProduced);
|
||||
EXPECT_EQ(expectFloats, dataMq->availableToRead());
|
||||
if (expectFloats != 0) {
|
||||
EXPECT_TRUE(dataMq->read(buffer.data(), expectFloats));
|
||||
}
|
||||
}
|
||||
}
|
||||
static Parameter::Common createParamCommon(
|
||||
int session = 0, int ioHandle = -1, int iSampleRate = 48000, int oSampleRate = 48000,
|
||||
long iFrameCount = 0x100, long oFrameCount = 0x100,
|
||||
AudioChannelLayout inputChannelLayout =
|
||||
AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
|
||||
AudioChannelLayout::LAYOUT_STEREO),
|
||||
AudioChannelLayout outputChannelLayout =
|
||||
AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
|
||||
AudioChannelLayout::LAYOUT_STEREO)) {
|
||||
Parameter::Common common;
|
||||
common.session = session;
|
||||
common.ioHandle = ioHandle;
|
||||
|
||||
template <typename Functor>
|
||||
void ForEachDescriptor(Functor functor) {
|
||||
for (size_t i = 0; i < mEffectDescriptors.size(); i++) {
|
||||
SCOPED_TRACE(mEffectDescriptors[i].toString());
|
||||
functor(i, mEffectDescriptors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static const size_t mWriteMQBytes = 0x400;
|
||||
|
||||
enum class IO : char { INPUT = 0, OUTPUT = 1, INOUT = 2 };
|
||||
|
||||
void initParamCommonFormat(IO io = IO::INOUT,
|
||||
const AudioFormatDescription& format = DefaultFormat) {
|
||||
if (io == IO::INPUT || io == IO::INOUT) {
|
||||
mCommon.input.base.format = format;
|
||||
}
|
||||
if (io == IO::OUTPUT || io == IO::INOUT) {
|
||||
mCommon.output.base.format = format;
|
||||
}
|
||||
}
|
||||
|
||||
void initParamCommonSampleRate(IO io = IO::INOUT, const int& sampleRate = 48000) {
|
||||
if (io == IO::INPUT || io == IO::INOUT) {
|
||||
mCommon.input.base.sampleRate = sampleRate;
|
||||
}
|
||||
if (io == IO::OUTPUT || io == IO::INOUT) {
|
||||
mCommon.output.base.sampleRate = sampleRate;
|
||||
}
|
||||
}
|
||||
|
||||
void initParamCommonFrameCount(IO io = IO::INOUT, const long& frameCount = 48000) {
|
||||
if (io == IO::INPUT || io == IO::INOUT) {
|
||||
mCommon.input.frameCount = frameCount;
|
||||
}
|
||||
if (io == IO::OUTPUT || io == IO::INOUT) {
|
||||
mCommon.output.frameCount = frameCount;
|
||||
}
|
||||
}
|
||||
void initParamCommon(int session = 0, int ioHandle = -1, int iSampleRate = 48000,
|
||||
int oSampleRate = 48000, long iFrameCount = 0x100,
|
||||
long oFrameCount = 0x100) {
|
||||
mCommon.session = session;
|
||||
mCommon.ioHandle = ioHandle;
|
||||
|
||||
auto& input = mCommon.input;
|
||||
auto& output = mCommon.output;
|
||||
auto& input = common.input;
|
||||
auto& output = common.output;
|
||||
input.base.sampleRate = iSampleRate;
|
||||
input.base.channelMask = mInputChannelLayout;
|
||||
input.base.channelMask = inputChannelLayout;
|
||||
input.base.format = kDefaultFormatDescription;
|
||||
input.frameCount = iFrameCount;
|
||||
input.base.format = DefaultFormat;
|
||||
output.base.sampleRate = oSampleRate;
|
||||
output.base.channelMask = mOutputChannelLayout;
|
||||
output.base.format = DefaultFormat;
|
||||
output.base.channelMask = outputChannelLayout;
|
||||
output.base.format = kDefaultFormatDescription;
|
||||
output.frameCount = oFrameCount;
|
||||
output.base.format = DefaultFormat;
|
||||
inputFrameSize = android::hardware::audio::common::getFrameSizeInBytes(
|
||||
input.base.format, input.base.channelMask);
|
||||
outputFrameSize = android::hardware::audio::common::getFrameSizeInBytes(
|
||||
output.base.format, output.base.channelMask);
|
||||
return common;
|
||||
}
|
||||
|
||||
void setSpecific(Parameter::Specific& specific) { mSpecific = specific; }
|
||||
|
||||
// usually this function only call once.
|
||||
void PrepareInputData(size_t bytes = mWriteMQBytes) {
|
||||
size_t maxInputBytes = mWriteMQBytes;
|
||||
for (auto& it : mEffectParams) {
|
||||
auto& mq = it.inputMQ;
|
||||
EXPECT_NE(nullptr, mq);
|
||||
EXPECT_TRUE(mq->isValid());
|
||||
const size_t bytesToWrite = mq->availableToWrite() * sizeof(float);
|
||||
EXPECT_EQ(inputFrameSize * mCommon.input.frameCount, bytesToWrite);
|
||||
EXPECT_NE(0UL, bytesToWrite);
|
||||
EXPECT_TRUE(bytes <= bytesToWrite);
|
||||
maxInputBytes = std::max(maxInputBytes, bytesToWrite);
|
||||
}
|
||||
mInputBuffer.resize(maxInputBytes / sizeof(float));
|
||||
std::fill(mInputBuffer.begin(), mInputBuffer.end(), 0x5a);
|
||||
}
|
||||
|
||||
void writeToFmq(size_t bytes = mWriteMQBytes) {
|
||||
for (auto& it : mEffectParams) {
|
||||
auto& mq = it.inputMQ;
|
||||
EXPECT_NE(nullptr, mq);
|
||||
const size_t bytesToWrite = mq->availableToWrite() * sizeof(float);
|
||||
EXPECT_NE(0Ul, bytesToWrite);
|
||||
EXPECT_TRUE(bytes <= bytesToWrite);
|
||||
EXPECT_TRUE(mq->write(mInputBuffer.data(), bytes / sizeof(float)));
|
||||
}
|
||||
}
|
||||
|
||||
void readFromFmq(size_t expectBytes = mWriteMQBytes) {
|
||||
for (auto& it : mEffectParams) {
|
||||
IEffect::Status status{};
|
||||
auto& statusMq = it.statusMQ;
|
||||
EXPECT_NE(nullptr, statusMq);
|
||||
EXPECT_TRUE(statusMq->readBlocking(&status, 1));
|
||||
EXPECT_EQ(STATUS_OK, status.status);
|
||||
EXPECT_EQ(expectBytes, (unsigned)status.fmqProduced * sizeof(float));
|
||||
|
||||
auto& outputMq = it.outputMQ;
|
||||
EXPECT_NE(nullptr, outputMq);
|
||||
EXPECT_EQ(expectBytes, outputMq->availableToRead() * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
void setInputChannelLayout(AudioChannelLayout input) { mInputChannelLayout = input; }
|
||||
void setOutputChannelLayout(AudioChannelLayout output) { mOutputChannelLayout = output; }
|
||||
const std::vector<Descriptor::Identity>& GetCompleteEffectIdList() const {
|
||||
return mFactoryHelper.GetCompleteEffectIdList();
|
||||
}
|
||||
const std::vector<Descriptor>& getDescriptorVec() const { return mEffectDescriptors; }
|
||||
|
||||
private:
|
||||
EffectFactoryHelper mFactoryHelper;
|
||||
|
||||
AudioChannelLayout mInputChannelLayout =
|
||||
AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
|
||||
AudioChannelLayout::LAYOUT_STEREO);
|
||||
AudioChannelLayout mOutputChannelLayout =
|
||||
AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
|
||||
AudioChannelLayout::LAYOUT_STEREO);
|
||||
|
||||
Parameter::Common mCommon;
|
||||
std::optional<Parameter::Specific> mSpecific = std::nullopt;
|
||||
|
||||
size_t inputFrameSize, outputFrameSize;
|
||||
std::vector<float> mInputBuffer; // reuse same buffer for all effects testing
|
||||
|
||||
typedef ::android::AidlMessageQueue<
|
||||
IEffect::Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
|
||||
StatusMQ;
|
||||
@@ -317,6 +181,4 @@ class EffectHelper {
|
||||
std::unique_ptr<DataMQ> inputMQ;
|
||||
std::unique_ptr<DataMQ> outputMQ;
|
||||
};
|
||||
std::vector<EffectParam> mEffectParams;
|
||||
std::vector<Descriptor> mEffectDescriptors;
|
||||
};
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -37,23 +38,81 @@
|
||||
using namespace android;
|
||||
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::EffectNullUuid;
|
||||
using aidl::android::hardware::audio::effect::EffectZeroUuid;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::IFactory;
|
||||
using aidl::android::hardware::audio::effect::kEffectNullUuid;
|
||||
using aidl::android::hardware::audio::effect::kEffectZeroUuid;
|
||||
using aidl::android::hardware::audio::effect::Processing;
|
||||
using aidl::android::media::audio::common::AudioSource;
|
||||
using aidl::android::media::audio::common::AudioStreamType;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
/// Effect factory testing.
|
||||
class EffectFactoryTest : public testing::TestWithParam<std::string> {
|
||||
public:
|
||||
void SetUp() override { ASSERT_NO_FATAL_FAILURE(mFactory.ConnectToFactoryService()); }
|
||||
void SetUp() override {
|
||||
mFactoryHelper = std::make_unique<EffectFactoryHelper>(GetParam());
|
||||
connectAndGetFactory();
|
||||
}
|
||||
|
||||
void TearDown() override { mFactory.DestroyEffects(); }
|
||||
void TearDown() override {
|
||||
for (auto& effect : mEffects) {
|
||||
const auto status = mEffectFactory->destroyEffect(effect);
|
||||
EXPECT_STATUS(EX_NONE, status);
|
||||
}
|
||||
}
|
||||
|
||||
EffectFactoryHelper mFactory = EffectFactoryHelper(GetParam());
|
||||
std::unique_ptr<EffectFactoryHelper> mFactoryHelper;
|
||||
std::shared_ptr<IFactory> mEffectFactory;
|
||||
std::vector<std::shared_ptr<IEffect>> mEffects;
|
||||
const Descriptor::Identity kNullDesc = {.uuid = kEffectNullUuid};
|
||||
const Descriptor::Identity kZeroDesc = {.uuid = kEffectZeroUuid};
|
||||
|
||||
const Descriptor::Identity nullDesc = {.uuid = EffectNullUuid};
|
||||
const Descriptor::Identity zeroDesc = {.uuid = EffectZeroUuid};
|
||||
template <typename Functor>
|
||||
void ForEachId(const std::vector<Descriptor::Identity> ids, Functor functor) {
|
||||
for (const auto& id : ids) {
|
||||
SCOPED_TRACE(id.toString());
|
||||
functor(id);
|
||||
}
|
||||
}
|
||||
template <typename Functor>
|
||||
void ForEachEffect(std::vector<std::shared_ptr<IEffect>> effects, Functor functor) {
|
||||
for (auto& effect : effects) {
|
||||
functor(effect);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<IEffect>> createWithIds(
|
||||
const std::vector<Descriptor::Identity> ids,
|
||||
const binder_status_t expectStatus = EX_NONE) {
|
||||
std::vector<std::shared_ptr<IEffect>> effects;
|
||||
for (const auto& id : ids) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
EXPECT_STATUS(expectStatus, mEffectFactory->createEffect(id.uuid, &effect));
|
||||
if (expectStatus == EX_NONE) {
|
||||
EXPECT_NE(effect, nullptr) << " null effect with uuid: " << id.uuid.toString();
|
||||
effects.push_back(std::move(effect));
|
||||
}
|
||||
}
|
||||
return effects;
|
||||
}
|
||||
void destroyEffects(std::vector<std::shared_ptr<IEffect>> effects,
|
||||
const binder_status_t expectStatus = EX_NONE) {
|
||||
for (const auto& effect : effects) {
|
||||
EXPECT_STATUS(expectStatus, mEffectFactory->destroyEffect(effect));
|
||||
}
|
||||
}
|
||||
void creatAndDestroyIds(const std::vector<Descriptor::Identity> ids) {
|
||||
for (const auto& id : ids) {
|
||||
auto effects = createWithIds({id});
|
||||
ASSERT_NO_FATAL_FAILURE(destroyEffects(effects));
|
||||
}
|
||||
}
|
||||
void connectAndGetFactory() {
|
||||
ASSERT_NO_FATAL_FAILURE(mFactoryHelper->ConnectToFactoryService());
|
||||
mEffectFactory = mFactoryHelper->GetFactory();
|
||||
ASSERT_NE(mEffectFactory, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_P(EffectFactoryTest, SetupAndTearDown) {
|
||||
@@ -61,165 +120,160 @@ TEST_P(EffectFactoryTest, SetupAndTearDown) {
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, CanBeRestarted) {
|
||||
ASSERT_NO_FATAL_FAILURE(mFactory.RestartFactoryService());
|
||||
ASSERT_NO_FATAL_FAILURE(mFactoryHelper->RestartFactoryService());
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, QueriedDescriptorList) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
EXPECT_NE(descriptors.size(), 0UL);
|
||||
}
|
||||
/**
|
||||
* @brief Check at least support list of effect must be supported by aosp:
|
||||
* https://developer.android.com/reference/android/media/audiofx/AudioEffect
|
||||
*/
|
||||
TEST_P(EffectFactoryTest, ExpectAllAospEffectTypes) {
|
||||
std::vector<Descriptor::Identity> ids;
|
||||
std::set<AudioUuid> typeUuidSet(
|
||||
{aidl::android::hardware::audio::effect::kBassBoostTypeUUID,
|
||||
aidl::android::hardware::audio::effect::kEqualizerTypeUUID,
|
||||
aidl::android::hardware::audio::effect::kEnvReverbTypeUUID,
|
||||
aidl::android::hardware::audio::effect::kPresetReverbTypeUUID,
|
||||
aidl::android::hardware::audio::effect::kDynamicsProcessingTypeUUID,
|
||||
aidl::android::hardware::audio::effect::kHapticGeneratorTypeUUID,
|
||||
aidl::android::hardware::audio::effect::kVirtualizerTypeUUID});
|
||||
|
||||
TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
// TODO: Factory eventually need to return the full list of MUST supported AOSP effects.
|
||||
for (auto& desc : descriptors) {
|
||||
EXPECT_NE(desc.type, EffectNullUuid);
|
||||
EXPECT_NE(desc.uuid, EffectNullUuid);
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
|
||||
EXPECT_TRUE(ids.size() >= typeUuidSet.size());
|
||||
for (const auto& id : ids) {
|
||||
typeUuidSet.erase(id.type);
|
||||
}
|
||||
std::string msg = " missing type UUID:\n";
|
||||
for (const auto& uuid : typeUuidSet) {
|
||||
msg += (uuid.toString() + "\n");
|
||||
}
|
||||
SCOPED_TRACE(msg);
|
||||
EXPECT_EQ(0UL, typeUuidSet.size());
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, QueriedDescriptorNotExistType) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(EffectNullUuid, std::nullopt, std::nullopt, &descriptors);
|
||||
EXPECT_EQ(descriptors.size(), 0UL);
|
||||
TEST_P(EffectFactoryTest, QueryNullTypeUuid) {
|
||||
std::vector<Descriptor::Identity> ids;
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(kEffectNullUuid, std::nullopt, std::nullopt, &ids));
|
||||
EXPECT_EQ(ids.size(), 0UL);
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, QueriedDescriptorNotExistInstance) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, EffectNullUuid, std::nullopt, &descriptors);
|
||||
EXPECT_EQ(descriptors.size(), 0UL);
|
||||
TEST_P(EffectFactoryTest, QueriedNullImplUuid) {
|
||||
std::vector<Descriptor::Identity> ids;
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, kEffectNullUuid, std::nullopt, &ids));
|
||||
EXPECT_EQ(ids.size(), 0UL);
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, CreateAndDestroyOnce) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
auto numIds = mFactory.GetEffectIds().size();
|
||||
EXPECT_NE(numIds, 0UL);
|
||||
|
||||
auto& effectMap = mFactory.GetEffectMap();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
mFactory.CreateEffects();
|
||||
EXPECT_EQ(effectMap.size(), numIds);
|
||||
mFactory.DestroyEffects();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
TEST_P(EffectFactoryTest, QueriedNullProxyUuid) {
|
||||
std::vector<Descriptor::Identity> ids;
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, kEffectNullUuid, &ids));
|
||||
EXPECT_EQ(ids.size(), 0UL);
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
auto numIds = mFactory.GetEffectIds().size();
|
||||
EXPECT_NE(numIds, 0UL);
|
||||
// create all effects, and then destroy them all together
|
||||
TEST_P(EffectFactoryTest, CreateAndDestroyEffects) {
|
||||
std::vector<Descriptor::Identity> ids;
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
|
||||
EXPECT_NE(ids.size(), 0UL);
|
||||
|
||||
auto& effectMap = mFactory.GetEffectMap();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
mFactory.CreateEffects();
|
||||
EXPECT_EQ(effectMap.size(), numIds);
|
||||
mFactory.DestroyEffects();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
|
||||
// Create and destroy again
|
||||
mFactory.CreateEffects();
|
||||
EXPECT_EQ(effectMap.size(), numIds);
|
||||
mFactory.DestroyEffects();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
std::vector<std::shared_ptr<IEffect>> effects;
|
||||
effects = createWithIds(ids);
|
||||
EXPECT_EQ(ids.size(), effects.size());
|
||||
destroyEffects(effects);
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
auto numIds = mFactory.GetEffectIds().size();
|
||||
EXPECT_NE(numIds, 0UL);
|
||||
std::vector<Descriptor::Identity> ids;
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
|
||||
EXPECT_NE(ids.size(), 0UL);
|
||||
|
||||
auto& effectMap = mFactory.GetEffectMap();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
mFactory.CreateEffects();
|
||||
EXPECT_EQ(effectMap.size(), numIds);
|
||||
// Create effect instances of same implementation
|
||||
mFactory.CreateEffects();
|
||||
EXPECT_EQ(effectMap.size(), 2 * numIds);
|
||||
std::vector<std::shared_ptr<IEffect>> effects = createWithIds(ids);
|
||||
EXPECT_EQ(ids.size(), effects.size());
|
||||
std::vector<std::shared_ptr<IEffect>> effects2 = createWithIds(ids);
|
||||
EXPECT_EQ(ids.size(), effects2.size());
|
||||
std::vector<std::shared_ptr<IEffect>> effects3 = createWithIds(ids);
|
||||
EXPECT_EQ(ids.size(), effects3.size());
|
||||
|
||||
mFactory.CreateEffects();
|
||||
EXPECT_EQ(effectMap.size(), 3 * numIds);
|
||||
destroyEffects(effects);
|
||||
destroyEffects(effects2);
|
||||
destroyEffects(effects3);
|
||||
}
|
||||
|
||||
mFactory.DestroyEffects();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
// create and destroy each effect one by one
|
||||
TEST_P(EffectFactoryTest, CreateAndDestroyEffectsOneByOne) {
|
||||
std::vector<Descriptor::Identity> ids;
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
|
||||
EXPECT_NE(ids.size(), 0UL);
|
||||
|
||||
creatAndDestroyIds(ids);
|
||||
}
|
||||
|
||||
// for each effect: repeat 3 times create and destroy
|
||||
TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
|
||||
std::vector<Descriptor::Identity> ids;
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
|
||||
EXPECT_NE(ids.size(), 0UL);
|
||||
|
||||
creatAndDestroyIds(ids);
|
||||
creatAndDestroyIds(ids);
|
||||
creatAndDestroyIds(ids);
|
||||
}
|
||||
|
||||
// Expect EX_ILLEGAL_ARGUMENT when create with invalid UUID.
|
||||
TEST_P(EffectFactoryTest, CreateWithInvalidUuid) {
|
||||
std::vector<std::pair<Descriptor::Identity, binder_status_t>> descriptors;
|
||||
descriptors.push_back(std::make_pair(nullDesc, EX_ILLEGAL_ARGUMENT));
|
||||
descriptors.push_back(std::make_pair(zeroDesc, EX_ILLEGAL_ARGUMENT));
|
||||
|
||||
auto& effectMap = mFactory.GetEffectMap();
|
||||
mFactory.CreateEffectsAndExpect(descriptors);
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
std::vector<Descriptor::Identity> ids = {kNullDesc, kZeroDesc};
|
||||
auto effects = createWithIds(ids, EX_ILLEGAL_ARGUMENT);
|
||||
EXPECT_EQ(effects.size(), 0UL);
|
||||
}
|
||||
|
||||
// Expect EX_ILLEGAL_ARGUMENT when destroy null interface.
|
||||
TEST_P(EffectFactoryTest, DestroyWithInvalidInterface) {
|
||||
std::shared_ptr<IEffect> spDummyEffect(nullptr);
|
||||
|
||||
mFactory.DestroyEffectAndExpect(spDummyEffect, EX_ILLEGAL_ARGUMENT);
|
||||
destroyEffects({spDummyEffect}, EX_ILLEGAL_ARGUMENT);
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, CreateAndRemoveReference) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
auto numIds = mFactory.GetEffectIds().size();
|
||||
EXPECT_NE(numIds, 0UL);
|
||||
// Same descriptor ID should work after service restart.
|
||||
TEST_P(EffectFactoryTest, CreateDestroyWithRestart) {
|
||||
std::vector<Descriptor::Identity> ids;
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
|
||||
EXPECT_NE(ids.size(), 0UL);
|
||||
creatAndDestroyIds(ids);
|
||||
|
||||
auto& effectMap = mFactory.GetEffectMap();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
mFactory.CreateEffects();
|
||||
EXPECT_EQ(effectMap.size(), numIds);
|
||||
// remove all reference
|
||||
mFactory.ClearEffectMap();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
mFactoryHelper->RestartFactoryService();
|
||||
|
||||
connectAndGetFactory();
|
||||
creatAndDestroyIds(ids);
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, CreateRemoveReferenceAndCreateDestroy) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
auto numIds = mFactory.GetEffectIds().size();
|
||||
EXPECT_NE(numIds, 0UL);
|
||||
// Effect handle invalid after restart.
|
||||
TEST_P(EffectFactoryTest, EffectInvalidAfterRestart) {
|
||||
std::vector<Descriptor::Identity> ids;
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
|
||||
EXPECT_NE(ids.size(), 0UL);
|
||||
std::vector<std::shared_ptr<IEffect>> effects = createWithIds(ids);
|
||||
|
||||
auto& effectMap = mFactory.GetEffectMap();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
mFactory.CreateEffects();
|
||||
EXPECT_EQ(effectMap.size(), numIds);
|
||||
// remove all reference
|
||||
mFactory.ClearEffectMap();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
ASSERT_NO_FATAL_FAILURE(mFactoryHelper->RestartFactoryService());
|
||||
|
||||
// Create and destroy again
|
||||
mFactory.CreateEffects();
|
||||
EXPECT_EQ(effectMap.size(), numIds);
|
||||
mFactory.DestroyEffects();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, CreateRestartAndCreateDestroy) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
auto numIds = mFactory.GetEffectIds().size();
|
||||
auto& effectMap = mFactory.GetEffectMap();
|
||||
mFactory.CreateEffects();
|
||||
EXPECT_EQ(effectMap.size(), numIds);
|
||||
ASSERT_NO_FATAL_FAILURE(mFactory.RestartFactoryService());
|
||||
|
||||
mFactory.CreateEffects();
|
||||
EXPECT_EQ(effectMap.size(), numIds);
|
||||
mFactory.DestroyEffects();
|
||||
EXPECT_EQ(effectMap.size(), 0UL);
|
||||
connectAndGetFactory();
|
||||
destroyEffects(effects, EX_ILLEGAL_ARGUMENT);
|
||||
}
|
||||
|
||||
// expect no error with the queryProcessing interface, but don't check number of processing
|
||||
TEST_P(EffectFactoryTest, QueryProcess) {
|
||||
std::vector<Processing> processing;
|
||||
mFactory.QueryProcessing(std::nullopt, &processing);
|
||||
// TODO: verify the number of process in example implementation after audio_effects.xml migrated
|
||||
EXPECT_IS_OK(mEffectFactory->queryProcessing(std::nullopt, &processing));
|
||||
|
||||
Processing::Type streamType =
|
||||
Processing::Type::make<Processing::Type::streamType>(AudioStreamType::SYSTEM);
|
||||
std::vector<Processing> processingFilteredByStream;
|
||||
EXPECT_IS_OK(mEffectFactory->queryProcessing(streamType, &processingFilteredByStream));
|
||||
|
||||
Processing::Type source =
|
||||
Processing::Type::make<Processing::Type::source>(AudioSource::DEFAULT);
|
||||
std::vector<Processing> processingFilteredBySource;
|
||||
EXPECT_IS_OK(mEffectFactory->queryProcessing(source, &processingFilteredBySource));
|
||||
|
||||
EXPECT_TRUE(processing.size() >= processingFilteredByStream.size());
|
||||
EXPECT_TRUE(processing.size() >= processingFilteredBySource.size());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactoryTest,
|
||||
|
||||
@@ -16,26 +16,24 @@
|
||||
|
||||
#define LOG_TAG "VtsHalAudioEffectTargetTest"
|
||||
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
#include <Utils.h>
|
||||
#include <aidl/Gtest.h>
|
||||
#include <aidl/Vintf.h>
|
||||
#include <aidl/android/hardware/audio/effect/IEffect.h>
|
||||
#include <aidl/android/hardware/audio/effect/IFactory.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android/binder_interface_utils.h>
|
||||
#include <android/binder_manager.h>
|
||||
#include <android/binder_process.h>
|
||||
|
||||
#include <Utils.h>
|
||||
#include <aidl/android/hardware/audio/effect/IEffect.h>
|
||||
#include <aidl/android/hardware/audio/effect/IFactory.h>
|
||||
#include <aidl/android/media/audio/common/AudioDeviceType.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include "AudioHalBinderServiceUtil.h"
|
||||
#include "EffectFactoryHelper.h"
|
||||
#include "EffectHelper.h"
|
||||
#include "TestUtils.h"
|
||||
|
||||
@@ -49,309 +47,725 @@ using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::IFactory;
|
||||
using aidl::android::hardware::audio::effect::Parameter;
|
||||
using aidl::android::hardware::audio::effect::State;
|
||||
using aidl::android::media::audio::common::AudioDeviceType;
|
||||
|
||||
class AudioEffectTest : public testing::TestWithParam<std::string>, public EffectHelper {
|
||||
enum ParamName { PARAM_INSTANCE_NAME };
|
||||
using EffectTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>>;
|
||||
|
||||
class AudioEffectTest : public testing::TestWithParam<EffectTestParam>, public EffectHelper {
|
||||
public:
|
||||
AudioEffectTest() : EffectHelper(GetParam()) {}
|
||||
AudioEffectTest() { std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(GetParam()); }
|
||||
|
||||
void SetUp() override {
|
||||
CreateEffects();
|
||||
initParamCommonFormat();
|
||||
initParamCommon();
|
||||
}
|
||||
void SetUp() override {}
|
||||
void TearDown() override {}
|
||||
|
||||
void TearDown() override {
|
||||
CloseEffects();
|
||||
DestroyEffects();
|
||||
}
|
||||
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
|
||||
std::shared_ptr<IFactory> mFactory;
|
||||
Descriptor::Identity mIdentity;
|
||||
};
|
||||
|
||||
TEST_P(AudioEffectTest, OpenEffectTest) {
|
||||
OpenEffects();
|
||||
TEST_P(AudioEffectTest, SetupAndTearDown) {
|
||||
// Intentionally empty test body.
|
||||
}
|
||||
|
||||
TEST_P(AudioEffectTest, OpenAndCloseEffect) {
|
||||
OpenEffects();
|
||||
CloseEffects();
|
||||
TEST_P(AudioEffectTest, CreateAndDestroy) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
TEST_P(AudioEffectTest, CloseUnopenedEffectTest) {
|
||||
CloseEffects();
|
||||
TEST_P(AudioEffectTest, OpenAndClose) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
TEST_P(AudioEffectTest, DoubleOpenCloseEffects) {
|
||||
OpenEffects();
|
||||
CloseEffects();
|
||||
OpenEffects();
|
||||
CloseEffects();
|
||||
|
||||
OpenEffects();
|
||||
OpenEffects();
|
||||
CloseEffects();
|
||||
|
||||
OpenEffects();
|
||||
CloseEffects();
|
||||
CloseEffects();
|
||||
TEST_P(AudioEffectTest, CloseUnopenedEffect) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
TEST_P(AudioEffectTest, GetDescriptors) {
|
||||
GetEffectDescriptors();
|
||||
TEST_P(AudioEffectTest, DoubleOpenAndClose) {
|
||||
std::shared_ptr<IEffect> effect1, effect2;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect1));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect2, 1 /* session */));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect1));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect2));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect1));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect2));
|
||||
}
|
||||
|
||||
TEST_P(AudioEffectTest, DescriptorIdExistAndUnique) {
|
||||
auto checker = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
Descriptor desc;
|
||||
std::vector<Descriptor::Identity> idList;
|
||||
EXPECT_IS_OK(effect->getDescriptor(&desc));
|
||||
QueryEffects(desc.common.id.type, desc.common.id.uuid, desc.common.id.proxy, &idList);
|
||||
// Must have at least one instance.
|
||||
EXPECT_NE(idList.size(), 0UL);
|
||||
};
|
||||
ForEachEffect(checker);
|
||||
TEST_P(AudioEffectTest, TripleOpenAndClose) {
|
||||
std::shared_ptr<IEffect> effect1, effect2, effect3;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect3, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect1));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect2, 1 /* session */));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect3, 2 /* session */));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect1));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect2));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect3));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect1));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect2));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect3));
|
||||
}
|
||||
|
||||
// Check unique with a set
|
||||
auto stringHash = [](const Descriptor::Identity& id) {
|
||||
return std::hash<std::string>()(id.toString());
|
||||
};
|
||||
auto vec = GetCompleteEffectIdList();
|
||||
std::unordered_set<Descriptor::Identity, decltype(stringHash)> idSet(0, stringHash);
|
||||
for (auto it : vec) {
|
||||
EXPECT_EQ(idSet.count(it), 0UL) << it.toString();
|
||||
idSet.insert(it);
|
||||
TEST_P(AudioEffectTest, GetDescritorBeforeOpen) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
Descriptor desc;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, desc));
|
||||
EXPECT_EQ(mIdentity.toString(), desc.common.id.toString());
|
||||
EXPECT_NE("", desc.common.name);
|
||||
EXPECT_NE("", desc.common.implementor);
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
TEST_P(AudioEffectTest, GetDescritorAfterOpen) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
Descriptor beforeOpen, afterOpen, afterClose;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, beforeOpen));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, afterOpen));
|
||||
EXPECT_EQ(beforeOpen.toString(), afterOpen.toString()) << "\n"
|
||||
<< beforeOpen.toString() << "\n"
|
||||
<< afterOpen.toString();
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, afterClose));
|
||||
EXPECT_EQ(beforeOpen.toString(), afterClose.toString()) << "\n"
|
||||
<< beforeOpen.toString() << "\n"
|
||||
<< afterClose.toString();
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
TEST_P(AudioEffectTest, DescriptorExistAndUnique) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
Descriptor desc;
|
||||
|
||||
auto descList = EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor);
|
||||
std::set<Descriptor::Identity> idSet;
|
||||
for (const auto& it : descList) {
|
||||
auto& id = it.second;
|
||||
EXPECT_EQ(0ul, idSet.count(id));
|
||||
idSet.insert(id);
|
||||
}
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, desc));
|
||||
EXPECT_EQ(1ul, idSet.count(desc.common.id));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
/// State testing.
|
||||
// An effect instance is in INIT state by default after it was created.
|
||||
TEST_P(AudioEffectTest, InitStateAfterCreation) {
|
||||
ExpectState(State::INIT);
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// An effect instance transfer to INIT state after it was open successfully with IEffect.open().
|
||||
// An effect instance transfer to IDLE state after IEffect.ASSERT_NO_FATAL_FAILURE(open().
|
||||
TEST_P(AudioEffectTest, IdleStateAfterOpen) {
|
||||
OpenEffects();
|
||||
ExpectState(State::IDLE);
|
||||
CloseEffects();
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// An effect instance is in PROCESSING state after it receive an START command.
|
||||
TEST_P(AudioEffectTest, ProcessingStateAfterStart) {
|
||||
OpenEffects();
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
CommandEffects(CommandId::STOP);
|
||||
CloseEffects();
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// An effect instance transfer to IDLE state after Command.Id.STOP in PROCESSING state.
|
||||
TEST_P(AudioEffectTest, IdleStateAfterStop) {
|
||||
OpenEffects();
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
CommandEffects(CommandId::STOP);
|
||||
ExpectState(State::IDLE);
|
||||
CloseEffects();
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// An effect instance transfer to IDLE state after Command.Id.RESET in PROCESSING state.
|
||||
TEST_P(AudioEffectTest, IdleStateAfterReset) {
|
||||
OpenEffects();
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
CommandEffects(CommandId::RESET);
|
||||
ExpectState(State::IDLE);
|
||||
CloseEffects();
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// An effect instance transfer to INIT if instance receive a close() call.
|
||||
// An effect instance transfer to INIT after IEffect.ASSERT_NO_FATAL_FAILURE(close().
|
||||
TEST_P(AudioEffectTest, InitStateAfterClose) {
|
||||
OpenEffects();
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
CommandEffects(CommandId::STOP);
|
||||
ExpectState(State::IDLE);
|
||||
CloseEffects();
|
||||
ExpectState(State::INIT);
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// An effect instance shouldn't accept any command before open.
|
||||
TEST_P(AudioEffectTest, NoCommandAcceptedBeforeOpen) {
|
||||
ExpectState(State::INIT);
|
||||
CommandEffectsExpectStatus(CommandId::START, EX_ILLEGAL_STATE);
|
||||
CommandEffectsExpectStatus(CommandId::STOP, EX_ILLEGAL_STATE);
|
||||
CommandEffectsExpectStatus(CommandId::RESET, EX_ILLEGAL_STATE);
|
||||
ExpectState(State::INIT);
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START, EX_ILLEGAL_STATE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP, EX_ILLEGAL_STATE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET, EX_ILLEGAL_STATE));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// No-op when receive STOP command in IDLE state.
|
||||
TEST_P(AudioEffectTest, StopCommandInIdleStateNoOp) {
|
||||
ExpectState(State::INIT);
|
||||
OpenEffects();
|
||||
ExpectState(State::IDLE);
|
||||
CommandEffects(CommandId::STOP);
|
||||
ExpectState(State::IDLE);
|
||||
CloseEffects();
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// No-op when receive STOP command in IDLE state.
|
||||
// No-op when receive RESET command in IDLE state.
|
||||
TEST_P(AudioEffectTest, ResetCommandInIdleStateNoOp) {
|
||||
ExpectState(State::INIT);
|
||||
OpenEffects();
|
||||
ExpectState(State::IDLE);
|
||||
CommandEffects(CommandId::RESET);
|
||||
ExpectState(State::IDLE);
|
||||
CloseEffects();
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Repeat START and STOP command.
|
||||
TEST_P(AudioEffectTest, RepeatStartAndStop) {
|
||||
OpenEffects();
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
CommandEffects(CommandId::STOP);
|
||||
ExpectState(State::IDLE);
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
CommandEffects(CommandId::STOP);
|
||||
ExpectState(State::IDLE);
|
||||
CloseEffects();
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Repeat START and RESET command.
|
||||
TEST_P(AudioEffectTest, RepeatStartAndReset) {
|
||||
OpenEffects();
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
CommandEffects(CommandId::RESET);
|
||||
ExpectState(State::IDLE);
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
CommandEffects(CommandId::RESET);
|
||||
ExpectState(State::IDLE);
|
||||
CloseEffects();
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Repeat START and STOP command, try to close at PROCESSING state.
|
||||
// Try to close an effect instance at PROCESSING state.
|
||||
TEST_P(AudioEffectTest, CloseProcessingStateEffects) {
|
||||
OpenEffects();
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
CommandEffects(CommandId::STOP);
|
||||
ExpectState(State::IDLE);
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
CloseEffects(EX_ILLEGAL_STATE);
|
||||
// cleanup
|
||||
CommandEffects(CommandId::STOP);
|
||||
ExpectState(State::IDLE);
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect, EX_ILLEGAL_STATE));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
|
||||
TEST_P(AudioEffectTest, DestroyOpenEffects) {
|
||||
// cleanup all effects.
|
||||
CloseEffects();
|
||||
DestroyEffects();
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
|
||||
// open effects, destroy without close, expect to get EX_ILLEGAL_STATE status.
|
||||
CreateEffects();
|
||||
OpenEffects();
|
||||
auto vec = GetCompleteEffectIdList();
|
||||
DestroyEffects(EX_ILLEGAL_STATE, vec.size());
|
||||
CloseEffects();
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect, EX_ILLEGAL_STATE));
|
||||
}
|
||||
|
||||
// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
|
||||
TEST_P(AudioEffectTest, DestroyProcessingEffects) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect, EX_ILLEGAL_STATE));
|
||||
}
|
||||
|
||||
TEST_P(AudioEffectTest, NormalSequenceStates) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
/// Parameter testing.
|
||||
// Verify parameters pass in open can be successfully get.
|
||||
TEST_P(AudioEffectTest, VerifyParametersAfterOpen) {
|
||||
OpenEffects();
|
||||
VerifyParameters();
|
||||
CloseEffects();
|
||||
TEST_P(AudioEffectTest, VerifyCommonParametersAfterOpen) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
|
||||
Parameter::Common common = EffectHelper::createParamCommon();
|
||||
IEffect::OpenEffectReturn ret;
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
|
||||
|
||||
Parameter get = Parameter(), expect = Parameter();
|
||||
expect.set<Parameter::common>(common);
|
||||
Parameter::Id id;
|
||||
id.set<Parameter::Id::commonTag>(Parameter::common);
|
||||
EXPECT_IS_OK(effect->getParameter(id, &get));
|
||||
EXPECT_EQ(expect, get) << expect.toString() << " vs " << get.toString();
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Verify parameters pass in set can be successfully get.
|
||||
TEST_P(AudioEffectTest, SetAndGetParameter) {
|
||||
OpenEffects();
|
||||
VerifyParameters();
|
||||
initParamCommon(1 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */,
|
||||
44100 /* oSampleRate */);
|
||||
SetParameter();
|
||||
VerifyParameters();
|
||||
CloseEffects();
|
||||
TEST_P(AudioEffectTest, SetAndGetCommonParameter) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
|
||||
Parameter get = Parameter(), set = Parameter();
|
||||
set.set<Parameter::common>(common);
|
||||
EXPECT_IS_OK(effect->setParameter(set));
|
||||
|
||||
Parameter::Id id;
|
||||
id.set<Parameter::Id::commonTag>(Parameter::common);
|
||||
EXPECT_IS_OK(effect->getParameter(id, &get));
|
||||
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Verify parameters pass in set can be successfully get.
|
||||
// Verify parameters set and get in PROCESSING state.
|
||||
TEST_P(AudioEffectTest, SetAndGetParameterInProcessing) {
|
||||
OpenEffects();
|
||||
VerifyParameters();
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
initParamCommon(1 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */,
|
||||
44100 /* oSampleRate */);
|
||||
SetParameter();
|
||||
VerifyParameters();
|
||||
CommandEffects(CommandId::STOP);
|
||||
ExpectState(State::IDLE);
|
||||
CloseEffects();
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
|
||||
Parameter get = Parameter(), set = Parameter();
|
||||
set.set<Parameter::common>(common);
|
||||
EXPECT_IS_OK(effect->setParameter(set));
|
||||
|
||||
Parameter::Id id;
|
||||
id.set<Parameter::Id::commonTag>(Parameter::common);
|
||||
EXPECT_IS_OK(effect->getParameter(id, &get));
|
||||
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Parameters kept after reset.
|
||||
TEST_P(AudioEffectTest, ResetAndVerifyParameter) {
|
||||
OpenEffects();
|
||||
VerifyParameters();
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
initParamCommon(1 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */,
|
||||
44100 /* oSampleRate */);
|
||||
SetParameter();
|
||||
VerifyParameters();
|
||||
CommandEffects(CommandId::RESET);
|
||||
ExpectState(State::IDLE);
|
||||
VerifyParameters();
|
||||
CloseEffects();
|
||||
// Verify parameters set and get in IDLE state.
|
||||
TEST_P(AudioEffectTest, SetAndGetParameterInIdle) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
|
||||
Parameter get = Parameter(), set = Parameter();
|
||||
set.set<Parameter::common>(common);
|
||||
EXPECT_IS_OK(effect->setParameter(set));
|
||||
|
||||
Parameter::Id id;
|
||||
id.set<Parameter::Id::commonTag>(Parameter::common);
|
||||
EXPECT_IS_OK(effect->getParameter(id, &get));
|
||||
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// TODO: need a way to support setting different sessionId to different effect instances
|
||||
#if 0
|
||||
// Multiple instances of same implementation running.
|
||||
TEST_P(AudioEffectTest, MultipleInstancesRunningWithDiffSessionId) {
|
||||
CreateEffects();
|
||||
ExpectState(State::INIT);
|
||||
OpenEffects();
|
||||
ExpectState(State::IDLE);
|
||||
CommandEffects(CommandId::START);
|
||||
ExpectState(State::PROCESSING);
|
||||
initParamCommon(1 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */,
|
||||
44100 /* oSampleRate */);
|
||||
SetParameter();
|
||||
VerifyParameters();
|
||||
CommandEffects(CommandId::STOP);
|
||||
ExpectState(State::IDLE);
|
||||
VerifyParameters();
|
||||
CloseEffects();
|
||||
}
|
||||
#endif
|
||||
// Verify Parameters kept after stop.
|
||||
TEST_P(AudioEffectTest, SetAndGetParameterAfterStop) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
|
||||
// Send data to effects and expect it to consume by check statusMQ.
|
||||
TEST_P(AudioEffectTest, ExpectEffectsToConsumeDataInMQ) {
|
||||
OpenEffects();
|
||||
PrepareInputData(mWriteMQBytes);
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
|
||||
Parameter get = Parameter(), set = Parameter();
|
||||
set.set<Parameter::common>(common);
|
||||
EXPECT_IS_OK(effect->setParameter(set));
|
||||
|
||||
CommandEffects(CommandId::START);
|
||||
writeToFmq(mWriteMQBytes);
|
||||
readFromFmq(mWriteMQBytes);
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
|
||||
ExpectState(State::PROCESSING);
|
||||
CommandEffects(CommandId::STOP);
|
||||
// cleanup
|
||||
CommandEffects(CommandId::STOP);
|
||||
ExpectState(State::IDLE);
|
||||
CloseEffects();
|
||||
Parameter::Id id;
|
||||
id.set<Parameter::Id::commonTag>(Parameter::common);
|
||||
EXPECT_IS_OK(effect->getParameter(id, &get));
|
||||
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(AudioEffectTestTest, AudioEffectTest,
|
||||
testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
|
||||
android::PrintInstanceNameToString);
|
||||
// Verify Parameters kept after reset.
|
||||
TEST_P(AudioEffectTest, SetAndGetParameterAfterReset) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
|
||||
Parameter get = Parameter(), set = Parameter();
|
||||
set.set<Parameter::common>(common);
|
||||
EXPECT_IS_OK(effect->setParameter(set));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
|
||||
Parameter::Id id;
|
||||
id.set<Parameter::Id::commonTag>(Parameter::common);
|
||||
EXPECT_IS_OK(effect->getParameter(id, &get));
|
||||
EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
/// Data processing test
|
||||
// Send data to effects and expect it to be consumed by checking statusMQ.
|
||||
TEST_P(AudioEffectTest, ConsumeDataInProcessingState) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
|
||||
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
|
||||
IEffect::OpenEffectReturn ret;
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
|
||||
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
|
||||
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
|
||||
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
|
||||
std::vector<float> buffer;
|
||||
EffectHelper::allocateInputData(common, inputMQ, buffer);
|
||||
EffectHelper::writeToFmq(inputMQ, buffer);
|
||||
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Send data to effects and expect it to be consumed after effect restart.
|
||||
TEST_P(AudioEffectTest, ConsumeDataAfterRestart) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
|
||||
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
|
||||
IEffect::OpenEffectReturn ret;
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
|
||||
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
|
||||
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
|
||||
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
|
||||
std::vector<float> buffer;
|
||||
EffectHelper::allocateInputData(common, inputMQ, buffer);
|
||||
EffectHelper::writeToFmq(inputMQ, buffer);
|
||||
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Send data to IDLE effects and expect it to be consumed after effect start.
|
||||
TEST_P(AudioEffectTest, SendDataAtIdleAndConsumeDataInProcessing) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
|
||||
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
|
||||
IEffect::OpenEffectReturn ret;
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
|
||||
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
|
||||
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
|
||||
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
|
||||
|
||||
std::vector<float> buffer;
|
||||
EffectHelper::allocateInputData(common, inputMQ, buffer);
|
||||
EffectHelper::writeToFmq(inputMQ, buffer);
|
||||
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
|
||||
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Send data multiple times.
|
||||
TEST_P(AudioEffectTest, ProcessDataMultipleTimes) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
|
||||
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
|
||||
IEffect::OpenEffectReturn ret;
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
|
||||
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
|
||||
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
|
||||
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
|
||||
|
||||
std::vector<float> buffer;
|
||||
EffectHelper::allocateInputData(common, inputMQ, buffer);
|
||||
EffectHelper::writeToFmq(inputMQ, buffer);
|
||||
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
|
||||
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
|
||||
// expect no status and data after consume
|
||||
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
|
||||
|
||||
EffectHelper::writeToFmq(inputMQ, buffer);
|
||||
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
|
||||
// expect no status and data after consume
|
||||
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Send data to IDLE state effects and expect it not be consumed.
|
||||
TEST_P(AudioEffectTest, NotConsumeDataInIdleState) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
|
||||
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
|
||||
IEffect::OpenEffectReturn ret;
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
|
||||
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
|
||||
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
|
||||
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
|
||||
std::vector<float> buffer;
|
||||
EffectHelper::allocateInputData(common, inputMQ, buffer);
|
||||
EffectHelper::writeToFmq(inputMQ, buffer);
|
||||
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
|
||||
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Send data to closed effects and expect it not be consumed.
|
||||
TEST_P(AudioEffectTest, NotConsumeDataByClosedEffect) {
|
||||
std::shared_ptr<IEffect> effect;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
|
||||
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
|
||||
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
|
||||
IEffect::OpenEffectReturn ret;
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect));
|
||||
|
||||
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
|
||||
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
|
||||
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
|
||||
|
||||
std::vector<float> buffer;
|
||||
EffectHelper::allocateInputData(common, inputMQ, buffer);
|
||||
EffectHelper::writeToFmq(inputMQ, buffer);
|
||||
EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
|
||||
}
|
||||
|
||||
// Send data to multiple effects.
|
||||
TEST_P(AudioEffectTest, ConsumeDataMultipleEffects) {
|
||||
std::shared_ptr<IEffect> effect1, effect2;
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mIdentity));
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mIdentity));
|
||||
|
||||
Parameter::Common common1 = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
|
||||
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
|
||||
Parameter::Common common2 = EffectHelper::createParamCommon(
|
||||
1 /* session */, 1 /* ioHandle */, 48000 /* iSampleRate */, 48000 /* oSampleRate */,
|
||||
2 * kInputFrameCount /* iFrameCount */, 2 * kOutputFrameCount /* oFrameCount */);
|
||||
IEffect::OpenEffectReturn ret1, ret2;
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect1, common1, std::nullopt /* specific */, &ret1, EX_NONE));
|
||||
ASSERT_NO_FATAL_FAILURE(open(effect2, common2, std::nullopt /* specific */, &ret2, EX_NONE));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect1, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect1, State::PROCESSING));
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect2, CommandId::START));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect2, State::PROCESSING));
|
||||
|
||||
auto statusMQ1 = std::make_unique<EffectHelper::StatusMQ>(ret1.statusMQ);
|
||||
auto inputMQ1 = std::make_unique<EffectHelper::DataMQ>(ret1.inputDataMQ);
|
||||
auto outputMQ1 = std::make_unique<EffectHelper::DataMQ>(ret1.outputDataMQ);
|
||||
|
||||
std::vector<float> buffer1, buffer2;
|
||||
EffectHelper::allocateInputData(common1, inputMQ1, buffer1);
|
||||
EffectHelper::writeToFmq(inputMQ1, buffer1);
|
||||
EffectHelper::readFromFmq(statusMQ1, 1, outputMQ1, buffer1.size(), buffer1);
|
||||
|
||||
auto statusMQ2 = std::make_unique<EffectHelper::StatusMQ>(ret2.statusMQ);
|
||||
auto inputMQ2 = std::make_unique<EffectHelper::DataMQ>(ret2.inputDataMQ);
|
||||
auto outputMQ2 = std::make_unique<EffectHelper::DataMQ>(ret2.outputDataMQ);
|
||||
EffectHelper::allocateInputData(common2, inputMQ2, buffer2);
|
||||
EffectHelper::writeToFmq(inputMQ2, buffer2);
|
||||
EffectHelper::readFromFmq(statusMQ2, 1, outputMQ2, buffer2.size(), buffer2);
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect1, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect1, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect1));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect1));
|
||||
|
||||
ASSERT_NO_FATAL_FAILURE(command(effect2, CommandId::STOP));
|
||||
ASSERT_NO_FATAL_FAILURE(expectState(effect2, State::IDLE));
|
||||
ASSERT_NO_FATAL_FAILURE(close(effect2));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect2));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
SingleEffectInstanceTest, AudioEffectTest,
|
||||
::testing::Combine(testing::ValuesIn(
|
||||
EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor))),
|
||||
[](const testing::TestParamInfo<AudioEffectTest::ParamType>& info) {
|
||||
auto msSinceEpoch = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
|
||||
std::ostringstream address;
|
||||
address << msSinceEpoch << "_factory_" << instance.first.get();
|
||||
std::string name = address.str() + "_UUID_timeLow_" +
|
||||
::android::internal::ToString(instance.second.uuid.timeLow) +
|
||||
"_timeMid_" +
|
||||
::android::internal::ToString(instance.second.uuid.timeMid);
|
||||
std::replace_if(
|
||||
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
|
||||
return name;
|
||||
});
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffectTest);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
@@ -35,8 +35,6 @@
|
||||
#include <Utils.h>
|
||||
#include <aidl/android/hardware/audio/effect/IEffect.h>
|
||||
#include <aidl/android/hardware/audio/effect/IFactory.h>
|
||||
#include <aidl/android/media/audio/common/AudioChannelLayout.h>
|
||||
#include <aidl/android/media/audio/common/AudioDeviceType.h>
|
||||
|
||||
#include "AudioHalBinderServiceUtil.h"
|
||||
#include "EffectHelper.h"
|
||||
@@ -47,103 +45,126 @@ using namespace android;
|
||||
|
||||
using aidl::android::hardware::audio::effect::Capability;
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::EffectNullUuid;
|
||||
using aidl::android::hardware::audio::effect::Equalizer;
|
||||
using aidl::android::hardware::audio::effect::EqualizerTypeUUID;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::IFactory;
|
||||
using aidl::android::hardware::audio::effect::kEqualizerTypeUUID;
|
||||
using aidl::android::hardware::audio::effect::Parameter;
|
||||
|
||||
/**
|
||||
* Here we focus on specific parameter checking, general IEffect interfaces testing performed in
|
||||
* VtsAudioEfectTargetTest.
|
||||
* Here we focus on specific effect (equalizer) parameter checking, general IEffect interfaces
|
||||
* testing performed in VtsAudioEfectTargetTest.
|
||||
*/
|
||||
enum ParamName { PARAM_INSTANCE_NAME, PARAM_PRESET_INDEX, PARAM_BAND_INDEX, PARAM_BAND_LEVEL };
|
||||
using EqualizerParamTestParam = std::tuple<std::string, int, int, int>;
|
||||
|
||||
enum ParamName { PARAM_INSTANCE_NAME, PARAM_BAND_LEVEL };
|
||||
using EqualizerParamTestParam =
|
||||
std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>, int>;
|
||||
|
||||
/*
|
||||
Testing parameter range, assuming the parameter supported by effect is in this range.
|
||||
This range is verified with IEffect.getDescriptor(), for any index supported vts expect EX_NONE
|
||||
from IEffect.setParameter(), otherwise expect EX_ILLEGAL_ARGUMENT.
|
||||
*/
|
||||
constexpr std::pair<int, int> kPresetIndexRange = {-1, 10}; // valid range [0, 9]
|
||||
constexpr std::pair<int, int> kBandIndexRange = {-1, 5}; // valid range [0, 4]
|
||||
constexpr std::pair<int, int> kBandLevelRange = {-5, 5}; // needs update with implementation
|
||||
const std::vector<int> kBandLevels = {0, -10, 10}; // needs update with implementation
|
||||
|
||||
class EqualizerParamTest : public ::testing::TestWithParam<EqualizerParamTestParam>,
|
||||
public EffectHelper {
|
||||
class EqualizerTest : public ::testing::TestWithParam<EqualizerParamTestParam>,
|
||||
public EffectHelper {
|
||||
public:
|
||||
EqualizerParamTest()
|
||||
: EffectHelper(std::get<PARAM_INSTANCE_NAME>(GetParam())),
|
||||
mParamPresetIndex(std::get<PARAM_PRESET_INDEX>(GetParam())),
|
||||
mParamBandIndex(std::get<PARAM_BAND_INDEX>(GetParam())),
|
||||
mParamBandLevel(std::get<PARAM_BAND_LEVEL>(GetParam())) {}
|
||||
EqualizerTest() : mBandLevel(std::get<PARAM_BAND_LEVEL>(GetParam())) {
|
||||
std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(GetParam());
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
CreateEffectsWithUUID(EqualizerTypeUUID);
|
||||
initParamCommonFormat();
|
||||
initParamCommon();
|
||||
initParamSpecific();
|
||||
OpenEffects(EqualizerTypeUUID);
|
||||
SCOPED_TRACE(testing::Message() << "preset: " << mParamPresetIndex << " bandIdx "
|
||||
<< mParamBandIndex << " level " << mParamBandLevel);
|
||||
}
|
||||
ASSERT_NE(nullptr, mFactory);
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mIdentity));
|
||||
|
||||
Parameter::Specific specific = getDefaultParamSpecific();
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
|
||||
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
|
||||
IEffect::OpenEffectReturn ret;
|
||||
ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
|
||||
ASSERT_NE(nullptr, mEffect);
|
||||
ASSERT_NO_FATAL_FAILURE(setTagRange());
|
||||
}
|
||||
void TearDown() override {
|
||||
CloseEffects();
|
||||
DestroyEffects();
|
||||
CleanUp();
|
||||
ASSERT_NO_FATAL_FAILURE(close(mEffect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
|
||||
}
|
||||
|
||||
int mParamPresetIndex = 0;
|
||||
int mParamBandIndex = 0;
|
||||
int mParamBandLevel = 0;
|
||||
std::pair<int, int> setPresetIndexRange(const Equalizer::Capability& cap) const {
|
||||
const auto [min, max] =
|
||||
std::minmax_element(cap.presets.begin(), cap.presets.end(),
|
||||
[](const auto& a, const auto& b) { return a.index < b.index; });
|
||||
return {min->index, max->index};
|
||||
}
|
||||
std::pair<int, int> setBandIndexRange(const Equalizer::Capability& cap) const {
|
||||
const auto [min, max] =
|
||||
std::minmax_element(cap.bandFrequencies.begin(), cap.bandFrequencies.end(),
|
||||
[](const auto& a, const auto& b) { return a.index < b.index; });
|
||||
return {min->index, max->index};
|
||||
}
|
||||
void setTagRange() {
|
||||
Descriptor desc;
|
||||
ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
|
||||
Equalizer::Capability& eqCap = desc.capability.get<Capability::equalizer>();
|
||||
mPresetIndex = setPresetIndexRange(eqCap);
|
||||
mBandIndex = setBandIndexRange(eqCap);
|
||||
}
|
||||
|
||||
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
|
||||
std::shared_ptr<IFactory> mFactory;
|
||||
std::shared_ptr<IEffect> mEffect;
|
||||
Descriptor::Identity mIdentity;
|
||||
std::pair<int, int> mPresetIndex;
|
||||
std::pair<int, int> mBandIndex;
|
||||
const int mBandLevel;
|
||||
Descriptor mDesc;
|
||||
|
||||
void SetAndGetEqualizerParameters() {
|
||||
auto functor = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
for (auto& it : mTags) {
|
||||
auto& tag = it.first;
|
||||
auto& eq = it.second;
|
||||
ASSERT_NE(nullptr, mEffect);
|
||||
for (auto& it : mTags) {
|
||||
auto& tag = it.first;
|
||||
auto& eq = it.second;
|
||||
|
||||
// validate parameter
|
||||
Descriptor desc;
|
||||
ASSERT_STATUS(EX_NONE, effect->getDescriptor(&desc));
|
||||
const bool valid = isTagInRange(it.first, it.second, desc);
|
||||
const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
|
||||
// validate parameter
|
||||
const bool valid = isTagInRange(it.first, it.second);
|
||||
const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
|
||||
|
||||
// set
|
||||
Parameter expectParam;
|
||||
Parameter::Specific specific;
|
||||
specific.set<Parameter::Specific::equalizer>(*eq.get());
|
||||
expectParam.set<Parameter::specific>(specific);
|
||||
EXPECT_STATUS(expected, effect->setParameter(expectParam))
|
||||
<< expectParam.toString();
|
||||
// set
|
||||
Parameter expectParam;
|
||||
Parameter::Specific specific;
|
||||
specific.set<Parameter::Specific::equalizer>(eq);
|
||||
expectParam.set<Parameter::specific>(specific);
|
||||
EXPECT_STATUS(expected, mEffect->setParameter(expectParam))
|
||||
<< expectParam.toString() << "\n"
|
||||
<< mDesc.toString();
|
||||
|
||||
// only get if parameter in range and set success
|
||||
if (expected == EX_NONE) {
|
||||
Parameter getParam;
|
||||
Parameter::Id id;
|
||||
Equalizer::Id eqId;
|
||||
eqId.set<Equalizer::Id::commonTag>(tag);
|
||||
id.set<Parameter::Id::equalizerTag>(eqId);
|
||||
// if set success, then get should match
|
||||
EXPECT_STATUS(expected, effect->getParameter(id, &getParam));
|
||||
EXPECT_TRUE(isEqParameterExpected(expectParam, getParam));
|
||||
}
|
||||
// only get if parameter in range and set success
|
||||
if (expected == EX_NONE) {
|
||||
Parameter getParam;
|
||||
Parameter::Id id;
|
||||
Equalizer::Id eqId;
|
||||
eqId.set<Equalizer::Id::commonTag>(tag);
|
||||
id.set<Parameter::Id::equalizerTag>(eqId);
|
||||
// if set success, then get should match
|
||||
EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam));
|
||||
EXPECT_TRUE(isEqParameterExpected(expectParam, getParam))
|
||||
<< "\nexpect:" << expectParam.toString()
|
||||
<< "\ngetParam:" << getParam.toString();
|
||||
}
|
||||
};
|
||||
EXPECT_NO_FATAL_FAILURE(ForEachEffect(functor));
|
||||
}
|
||||
}
|
||||
|
||||
bool isEqParameterExpected(const Parameter& expect, const Parameter& target) {
|
||||
// if parameter same, then for sure matched
|
||||
// if parameter same, then for sure they are matched
|
||||
if (expect == target) return true;
|
||||
|
||||
// if not, see if target include the expect parameter, and others all default (0).
|
||||
/*
|
||||
This is verify the case of client setParameter to a single bandLevel ({3, -1} for
|
||||
example), and return of getParameter must be [{0, 0}, {1, 0}, {2, 0}, {3, -1}, {4, 0}]
|
||||
*/
|
||||
* This is to verify the case of client setParameter to a single bandLevel ({3, -1} for
|
||||
* example), and return of getParameter must be [{0, 0}, {1, 0}, {2, 0}, {3, -1}, {4, 0}]
|
||||
*/
|
||||
EXPECT_EQ(expect.getTag(), Parameter::specific);
|
||||
EXPECT_EQ(target.getTag(), Parameter::specific);
|
||||
|
||||
@@ -160,10 +181,16 @@ class EqualizerParamTest : public ::testing::TestWithParam<EqualizerParamTestPar
|
||||
switch (eqTag) {
|
||||
case Equalizer::bandLevels: {
|
||||
auto expectBl = expectEq.get<Equalizer::bandLevels>();
|
||||
std::sort(expectBl.begin(), expectBl.end(),
|
||||
[](const auto& a, const auto& b) { return a.index < b.index; });
|
||||
expectBl.erase(std::unique(expectBl.begin(), expectBl.end()), expectBl.end());
|
||||
auto targetBl = targetEq.get<Equalizer::bandLevels>();
|
||||
return std::includes(targetBl.begin(), targetBl.end(), expectBl.begin(),
|
||||
expectBl.end());
|
||||
}
|
||||
case Equalizer::preset: {
|
||||
return expectEq.get<Equalizer::preset>() == targetEq.get<Equalizer::preset>();
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -173,27 +200,24 @@ class EqualizerParamTest : public ::testing::TestWithParam<EqualizerParamTestPar
|
||||
void addPresetParam(int preset) {
|
||||
Equalizer eq;
|
||||
eq.set<Equalizer::preset>(preset);
|
||||
mTags.push_back({Equalizer::preset, std::make_unique<Equalizer>(std::move(eq))});
|
||||
mTags.push_back({Equalizer::preset, eq});
|
||||
}
|
||||
|
||||
void addBandLevelsParam(std::vector<Equalizer::BandLevel>& bandLevels) {
|
||||
Equalizer eq;
|
||||
eq.set<Equalizer::bandLevels>(bandLevels);
|
||||
mTags.push_back({Equalizer::bandLevels, std::make_unique<Equalizer>(std::move(eq))});
|
||||
mTags.push_back({Equalizer::bandLevels, eq});
|
||||
}
|
||||
|
||||
bool isTagInRange(const Equalizer::Tag& tag, const std::unique_ptr<Equalizer>& eq,
|
||||
const Descriptor& desc) const {
|
||||
std::cout << "xxx" << toString(tag) << " " << desc.toString();
|
||||
const Equalizer::Capability& eqCap = desc.capability.get<Capability::equalizer>();
|
||||
bool isTagInRange(const Equalizer::Tag& tag, const Equalizer& eq) const {
|
||||
switch (tag) {
|
||||
case Equalizer::preset: {
|
||||
int index = eq->get<Equalizer::preset>();
|
||||
return isPresetIndexInRange(eqCap, index);
|
||||
int index = eq.get<Equalizer::preset>();
|
||||
return index >= mPresetIndex.first && index <= mPresetIndex.second;
|
||||
}
|
||||
case Equalizer::bandLevels: {
|
||||
auto& bandLevel = eq->get<Equalizer::bandLevels>();
|
||||
return isBandIndexInRange(eqCap, bandLevel);
|
||||
auto& bandLevel = eq.get<Equalizer::bandLevels>();
|
||||
return isBandInRange(bandLevel);
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
@@ -201,78 +225,125 @@ class EqualizerParamTest : public ::testing::TestWithParam<EqualizerParamTestPar
|
||||
return false;
|
||||
}
|
||||
|
||||
bool isPresetIndexInRange(const Equalizer::Capability& cap, int idx) const {
|
||||
const auto [min, max] =
|
||||
std::minmax_element(cap.presets.begin(), cap.presets.end(),
|
||||
[](const auto& a, const auto& b) { return a.index < b.index; });
|
||||
return idx >= min->index && idx <= max->index;
|
||||
}
|
||||
|
||||
bool isBandIndexInRange(const Equalizer::Capability& cap,
|
||||
const std::vector<Equalizer::BandLevel>& bandLevel) const {
|
||||
bool isBandInRange(const std::vector<Equalizer::BandLevel>& bandLevel) const {
|
||||
for (auto& it : bandLevel) {
|
||||
if (!isBandIndexInRange(cap, it.index)) return false;
|
||||
if (it.index < mBandIndex.first || it.index > mBandIndex.second) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isBandIndexInRange(const Equalizer::Capability& cap, int idx) const {
|
||||
const auto [min, max] =
|
||||
std::minmax_element(cap.bandFrequencies.begin(), cap.bandFrequencies.end(),
|
||||
[](const auto& a, const auto& b) { return a.index < b.index; });
|
||||
return idx >= min->index && idx <= max->index;
|
||||
Parameter::Specific getDefaultParamSpecific() {
|
||||
Equalizer eq = Equalizer::make<Equalizer::preset>(0);
|
||||
Parameter::Specific specific =
|
||||
Parameter::Specific::make<Parameter::Specific::equalizer>(eq);
|
||||
return specific;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::pair<Equalizer::Tag, std::unique_ptr<Equalizer>>> mTags;
|
||||
std::vector<std::pair<Equalizer::Tag, Equalizer>> mTags;
|
||||
|
||||
bool validCapabilityTag(Capability& cap) { return cap.getTag() == Capability::equalizer; }
|
||||
|
||||
void initParamSpecific() {
|
||||
Equalizer eq;
|
||||
eq.set<Equalizer::preset>(0);
|
||||
Parameter::Specific specific;
|
||||
specific.set<Parameter::Specific::equalizer>(eq);
|
||||
setSpecific(specific);
|
||||
}
|
||||
|
||||
void CleanUp() { mTags.clear(); }
|
||||
};
|
||||
|
||||
TEST_P(EqualizerParamTest, SetAndGetPreset) {
|
||||
EXPECT_NO_FATAL_FAILURE(addPresetParam(mParamPresetIndex));
|
||||
SetAndGetEqualizerParameters();
|
||||
TEST_P(EqualizerTest, SetAndGetPresetOutOfLowerBound) {
|
||||
addPresetParam(mPresetIndex.second - 1);
|
||||
ASSERT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
|
||||
}
|
||||
|
||||
TEST_P(EqualizerParamTest, SetAndGetSingleBand) {
|
||||
std::vector<Equalizer::BandLevel> bandLevels;
|
||||
Equalizer::BandLevel bandLevel = {mParamBandIndex, mParamBandLevel};
|
||||
bandLevels.push_back(bandLevel);
|
||||
EXPECT_NO_FATAL_FAILURE(addBandLevelsParam(bandLevels));
|
||||
SetAndGetEqualizerParameters();
|
||||
TEST_P(EqualizerTest, SetAndGetPresetOutOfUpperBound) {
|
||||
addPresetParam(mPresetIndex.second + 1);
|
||||
EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
|
||||
}
|
||||
|
||||
TEST_P(EqualizerTest, SetAndGetPresetAtLowerBound) {
|
||||
addPresetParam(mPresetIndex.first);
|
||||
EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
|
||||
}
|
||||
|
||||
TEST_P(EqualizerTest, SetAndGetPresetAtHigherBound) {
|
||||
addPresetParam(mPresetIndex.second);
|
||||
EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
|
||||
}
|
||||
|
||||
TEST_P(EqualizerTest, SetAndGetPresetInBound) {
|
||||
addPresetParam((mPresetIndex.first + mPresetIndex.second) >> 1);
|
||||
EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
|
||||
}
|
||||
|
||||
TEST_P(EqualizerTest, SetAndGetBandOutOfLowerBound) {
|
||||
std::vector<Equalizer::BandLevel> bandLevels{{mBandIndex.first - 1, mBandLevel}};
|
||||
addBandLevelsParam(bandLevels);
|
||||
EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
|
||||
}
|
||||
|
||||
TEST_P(EqualizerTest, SetAndGetBandOutOfUpperBound) {
|
||||
std::vector<Equalizer::BandLevel> bandLevels{{mBandIndex.second + 1, mBandLevel}};
|
||||
addBandLevelsParam(bandLevels);
|
||||
EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
|
||||
}
|
||||
|
||||
TEST_P(EqualizerTest, SetAndGetBandAtLowerBound) {
|
||||
std::vector<Equalizer::BandLevel> bandLevels{{mBandIndex.first, mBandLevel}};
|
||||
addBandLevelsParam(bandLevels);
|
||||
EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
|
||||
}
|
||||
|
||||
TEST_P(EqualizerTest, SetAndGetBandAtHigherBound) {
|
||||
std::vector<Equalizer::BandLevel> bandLevels{{mBandIndex.second, mBandLevel}};
|
||||
addBandLevelsParam(bandLevels);
|
||||
EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
|
||||
}
|
||||
|
||||
TEST_P(EqualizerTest, SetAndGetBandInBound) {
|
||||
std::vector<Equalizer::BandLevel> bandLevels{
|
||||
{(mBandIndex.first + mBandIndex.second) >> 1, mBandLevel}};
|
||||
addBandLevelsParam(bandLevels);
|
||||
EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
|
||||
}
|
||||
|
||||
TEST_P(EqualizerTest, SetAndGetMultiBands) {
|
||||
addPresetParam(mPresetIndex.first);
|
||||
std::vector<Equalizer::BandLevel> bandLevels{
|
||||
{mBandIndex.first, mBandLevel},
|
||||
{mBandIndex.second, mBandLevel},
|
||||
{(mBandIndex.first + mBandIndex.second) >> 1, mBandLevel}};
|
||||
addBandLevelsParam(bandLevels);
|
||||
EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
|
||||
}
|
||||
|
||||
TEST_P(EqualizerTest, SetAndGetMultipleParams) {
|
||||
std::vector<Equalizer::BandLevel> bandLevels{
|
||||
{(mBandIndex.first + mBandIndex.second) >> 1, mBandLevel}};
|
||||
addBandLevelsParam(bandLevels);
|
||||
addPresetParam((mPresetIndex.first + mPresetIndex.second) >> 1);
|
||||
EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
EqualizerTest, EqualizerParamTest,
|
||||
::testing::Combine(
|
||||
testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
|
||||
testing::Range(kPresetIndexRange.first, kPresetIndexRange.second),
|
||||
testing::Range(kBandIndexRange.first, kBandIndexRange.second),
|
||||
testing::Range(kBandLevelRange.first, kBandLevelRange.second)),
|
||||
[](const testing::TestParamInfo<EqualizerParamTest::ParamType>& info) {
|
||||
std::string instance = std::get<PARAM_INSTANCE_NAME>(info.param);
|
||||
std::string presetIdx = std::to_string(std::get<PARAM_PRESET_INDEX>(info.param));
|
||||
std::string bandIdx = std::to_string(std::get<PARAM_BAND_INDEX>(info.param));
|
||||
EqualizerTest, EqualizerTest,
|
||||
::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
|
||||
IFactory::descriptor, kEqualizerTypeUUID)),
|
||||
testing::ValuesIn(kBandLevels)),
|
||||
[](const testing::TestParamInfo<EqualizerTest::ParamType>& info) {
|
||||
auto msSinceEpoch = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
|
||||
std::string bandLevel = std::to_string(std::get<PARAM_BAND_LEVEL>(info.param));
|
||||
|
||||
std::string name = instance + "_presetIndex" + presetIdx + "_bandIndex" + bandIdx +
|
||||
"_bandLevel" + bandLevel;
|
||||
std::ostringstream address;
|
||||
address << msSinceEpoch << "_factory_" << instance.first.get();
|
||||
std::string name = address.str() + "_UUID_timeLow_" +
|
||||
::android::internal::ToString(instance.second.uuid.timeLow) +
|
||||
"_timeMid_" +
|
||||
::android::internal::ToString(instance.second.uuid.timeMid) +
|
||||
"_bandLevel_" + bandLevel;
|
||||
std::replace_if(
|
||||
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
|
||||
return name;
|
||||
});
|
||||
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EqualizerParamTest);
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EqualizerTest);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
@@ -27,8 +27,8 @@ using aidl::android::hardware::audio::effect::Capability;
|
||||
using aidl::android::hardware::audio::effect::Descriptor;
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
using aidl::android::hardware::audio::effect::IFactory;
|
||||
using aidl::android::hardware::audio::effect::kLoudnessEnhancerTypeUUID;
|
||||
using aidl::android::hardware::audio::effect::LoudnessEnhancer;
|
||||
using aidl::android::hardware::audio::effect::LoudnessEnhancerTypeUUID;
|
||||
using aidl::android::hardware::audio::effect::Parameter;
|
||||
|
||||
/**
|
||||
@@ -36,7 +36,8 @@ using aidl::android::hardware::audio::effect::Parameter;
|
||||
* VtsAudioEffectTargetTest.
|
||||
*/
|
||||
enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
|
||||
using LoudnessEnhancerParamTestParam = std::tuple<std::string, int>;
|
||||
using LoudnessEnhancerParamTestParam =
|
||||
std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>, int>;
|
||||
|
||||
// Every int 32 bit value is a valid gain, so testing the corner cases and one regular value.
|
||||
// TODO : Update the test values once range/capability is updated by implementation.
|
||||
@@ -46,53 +47,64 @@ const std::vector<int> kGainMbValues = {std::numeric_limits<int>::min(), 100,
|
||||
class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhancerParamTestParam>,
|
||||
public EffectHelper {
|
||||
public:
|
||||
LoudnessEnhancerParamTest()
|
||||
: EffectHelper(std::get<PARAM_INSTANCE_NAME>(GetParam())),
|
||||
mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {}
|
||||
LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
|
||||
std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(GetParam());
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
CreateEffectsWithUUID(LoudnessEnhancerTypeUUID);
|
||||
initParamCommonFormat();
|
||||
initParamCommon();
|
||||
initParamSpecific();
|
||||
OpenEffects(LoudnessEnhancerTypeUUID);
|
||||
SCOPED_TRACE(testing::Message() << "gainMb: " << mParamGainMb);
|
||||
}
|
||||
ASSERT_NE(nullptr, mFactory);
|
||||
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mIdentity));
|
||||
|
||||
Parameter::Specific specific = getDefaultParamSpecific();
|
||||
Parameter::Common common = EffectHelper::createParamCommon(
|
||||
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
|
||||
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
|
||||
IEffect::OpenEffectReturn ret;
|
||||
ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
|
||||
ASSERT_NE(nullptr, mEffect);
|
||||
}
|
||||
void TearDown() override {
|
||||
CloseEffects();
|
||||
DestroyEffects();
|
||||
CleanUp();
|
||||
ASSERT_NO_FATAL_FAILURE(close(mEffect));
|
||||
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
|
||||
}
|
||||
|
||||
Parameter::Specific getDefaultParamSpecific() {
|
||||
LoudnessEnhancer le = LoudnessEnhancer::make<LoudnessEnhancer::gainMb>(0);
|
||||
Parameter::Specific specific =
|
||||
Parameter::Specific::make<Parameter::Specific::loudnessEnhancer>(le);
|
||||
return specific;
|
||||
}
|
||||
|
||||
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
|
||||
std::shared_ptr<IFactory> mFactory;
|
||||
std::shared_ptr<IEffect> mEffect;
|
||||
Descriptor::Identity mIdentity;
|
||||
int mParamGainMb = 0;
|
||||
|
||||
void SetAndGetLoudnessEnhancerParameters() {
|
||||
auto functor = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
for (auto& it : mTags) {
|
||||
auto& tag = it.first;
|
||||
auto& le = it.second;
|
||||
void SetAndGetParameters() {
|
||||
for (auto& it : mTags) {
|
||||
auto& tag = it.first;
|
||||
auto& le = it.second;
|
||||
|
||||
// set parameter
|
||||
Parameter expectParam;
|
||||
Parameter::Specific specific;
|
||||
specific.set<Parameter::Specific::loudnessEnhancer>(le);
|
||||
expectParam.set<Parameter::specific>(specific);
|
||||
// All values are valid, set parameter should succeed
|
||||
EXPECT_STATUS(EX_NONE, effect->setParameter(expectParam)) << expectParam.toString();
|
||||
// set parameter
|
||||
Parameter expectParam;
|
||||
Parameter::Specific specific;
|
||||
specific.set<Parameter::Specific::loudnessEnhancer>(le);
|
||||
expectParam.set<Parameter::specific>(specific);
|
||||
// All values are valid, set parameter should succeed
|
||||
EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectParam)) << expectParam.toString();
|
||||
|
||||
// get parameter
|
||||
Parameter getParam;
|
||||
Parameter::Id id;
|
||||
LoudnessEnhancer::Id leId;
|
||||
leId.set<LoudnessEnhancer::Id::commonTag>(tag);
|
||||
id.set<Parameter::Id::loudnessEnhancerTag>(leId);
|
||||
EXPECT_STATUS(EX_NONE, effect->getParameter(id, &getParam));
|
||||
// get parameter
|
||||
Parameter getParam;
|
||||
Parameter::Id id;
|
||||
LoudnessEnhancer::Id leId;
|
||||
leId.set<LoudnessEnhancer::Id::commonTag>(tag);
|
||||
id.set<Parameter::Id::loudnessEnhancerTag>(leId);
|
||||
EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
|
||||
|
||||
EXPECT_EQ(expectParam, getParam);
|
||||
}
|
||||
};
|
||||
EXPECT_NO_FATAL_FAILURE(ForEachEffect(functor));
|
||||
EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString()
|
||||
<< "\ngetParam:" << getParam.toString();
|
||||
}
|
||||
}
|
||||
|
||||
void addGainMbParam(int gainMb) {
|
||||
@@ -103,33 +115,33 @@ class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhanc
|
||||
|
||||
private:
|
||||
std::vector<std::pair<LoudnessEnhancer::Tag, LoudnessEnhancer>> mTags;
|
||||
|
||||
void initParamSpecific() {
|
||||
LoudnessEnhancer le;
|
||||
le.set<LoudnessEnhancer::gainMb>(0);
|
||||
Parameter::Specific specific;
|
||||
specific.set<Parameter::Specific::loudnessEnhancer>(le);
|
||||
setSpecific(specific);
|
||||
}
|
||||
|
||||
void CleanUp() { mTags.clear(); }
|
||||
};
|
||||
|
||||
TEST_P(LoudnessEnhancerParamTest, SetAndGetGainMb) {
|
||||
EXPECT_NO_FATAL_FAILURE(addGainMbParam(mParamGainMb));
|
||||
SetAndGetLoudnessEnhancerParameters();
|
||||
SetAndGetParameters();
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
LoudnessEnhancerTest, LoudnessEnhancerParamTest,
|
||||
::testing::Combine(
|
||||
testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
|
||||
testing::ValuesIn(kGainMbValues)),
|
||||
::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
|
||||
IFactory::descriptor, kLoudnessEnhancerTypeUUID)),
|
||||
testing::ValuesIn(kGainMbValues)),
|
||||
[](const testing::TestParamInfo<LoudnessEnhancerParamTest::ParamType>& info) {
|
||||
std::string instance = std::get<PARAM_INSTANCE_NAME>(info.param);
|
||||
auto msSinceEpoch = std::chrono::duration_cast<std::chrono::nanoseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
|
||||
std::string gainMb = std::to_string(std::get<PARAM_GAIN_MB>(info.param));
|
||||
|
||||
std::string name = instance + "_gainMb" + gainMb;
|
||||
std::ostringstream address;
|
||||
address << msSinceEpoch << "_factory_" << instance.first.get();
|
||||
std::string name = address.str() + "_UUID_timeLow_" +
|
||||
::android::internal::ToString(instance.second.uuid.timeLow) +
|
||||
"_timeMid_" +
|
||||
::android::internal::ToString(instance.second.uuid.timeMid) +
|
||||
"_gainMb" + gainMb;
|
||||
std::replace_if(
|
||||
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
|
||||
return name;
|
||||
|
||||
Reference in New Issue
Block a user