Merge "Effect AIDL: queryEffect with Descriptor for all effects implementation" am: f0a217d07a am: 8918d907d1

Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2344310

Change-Id: Ifc1abc3b759f657226c05b55fe47b7f28d4543ea
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Shunkai Yao
2022-12-13 16:26:33 +00:00
committed by Automerger Merge Worker
27 changed files with 436 additions and 389 deletions

View File

@@ -14,6 +14,10 @@
* limitations under the License.
*/
#include <iterator>
#include <memory>
#include <tuple>
#include "include/effect-impl/EffectTypes.h"
#define LOG_TAG "AHAL_EffectFactory"
#include <dlfcn.h>
#include <unordered_set>
@@ -51,15 +55,29 @@ Factory::~Factory() {
ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type_uuid,
const std::optional<AudioUuid>& in_impl_uuid,
const std::optional<AudioUuid>& in_proxy_uuid,
std::vector<Descriptor::Identity>* _aidl_return) {
std::copy_if(
mIdentitySet.begin(), mIdentitySet.end(), std::back_inserter(*_aidl_return),
[&](auto& desc) {
return (!in_type_uuid.has_value() || in_type_uuid.value() == desc.type) &&
(!in_impl_uuid.has_value() || in_impl_uuid.value() == desc.uuid) &&
(!in_proxy_uuid.has_value() ||
(desc.proxy.has_value() && in_proxy_uuid.value() == desc.proxy.value()));
});
std::vector<Descriptor>* _aidl_return) {
// get the matching list
std::vector<Descriptor::Identity> idList;
std::copy_if(mIdentitySet.begin(), mIdentitySet.end(), std::back_inserter(idList),
[&](auto& id) {
return (!in_type_uuid.has_value() || in_type_uuid.value() == id.type) &&
(!in_impl_uuid.has_value() || in_impl_uuid.value() == id.uuid) &&
(!in_proxy_uuid.has_value() ||
(id.proxy.has_value() && in_proxy_uuid.value() == id.proxy.value()));
});
// query through the matching list
for (const auto& id : idList) {
if (mEffectLibMap.count(id.uuid)) {
Descriptor desc;
auto& entry = mEffectLibMap[id.uuid];
getDlSyms(entry);
auto& libInterface = std::get<kMapEntryInterfaceIndex>(entry);
RETURN_IF(!libInterface || !libInterface->queryEffectFunc, EX_NULL_POINTER,
"dlNullQueryEffectFunc");
RETURN_IF_BINDER_EXCEPTION(libInterface->queryEffectFunc(&id.uuid, &desc));
_aidl_return->emplace_back(std::move(desc));
}
}
return ndk::ScopedAStatus::ok();
}
@@ -74,37 +92,16 @@ ndk::ScopedAStatus Factory::queryProcessing(const std::optional<Processing::Type
return ndk::ScopedAStatus::ok();
}
#define RETURN_IF_BINDER_EXCEPTION(functor) \
{ \
binder_exception_t exception = functor; \
if (EX_NONE != exception) { \
LOG(ERROR) << #functor << ": failed with error " << exception; \
return ndk::ScopedAStatus::fromExceptionCode(exception); \
} \
}
ndk::ScopedAStatus Factory::createEffect(const AudioUuid& in_impl_uuid,
std::shared_ptr<IEffect>* _aidl_return) {
LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString();
if (mEffectLibMap.count(in_impl_uuid)) {
auto& lib = mEffectLibMap[in_impl_uuid];
// didn't do dlsym yet
if (nullptr == lib.second) {
void* libHandle = lib.first.get();
auto dlInterface = std::make_unique<struct effect_dl_interface_s>();
dlInterface->createEffectFunc = (EffectCreateFunctor)dlsym(libHandle, "createEffect");
dlInterface->destroyEffectFunc =
(EffectDestroyFunctor)dlsym(libHandle, "destroyEffect");
if (!dlInterface->createEffectFunc || !dlInterface->destroyEffectFunc) {
LOG(ERROR) << __func__
<< ": create or destroy symbol not exist in library: " << libHandle
<< " with dlerror: " << dlerror();
return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
}
lib.second = std::move(dlInterface);
}
auto& entry = mEffectLibMap[in_impl_uuid];
getDlSyms(entry);
auto& libInterface = lib.second;
auto& libInterface = std::get<kMapEntryInterfaceIndex>(entry);
RETURN_IF(!libInterface || !libInterface->createEffectFunc, EX_NULL_POINTER,
"dlNullcreateEffectFunc");
std::shared_ptr<IEffect> effectSp;
RETURN_IF_BINDER_EXCEPTION(libInterface->createEffectFunc(&in_impl_uuid, &effectSp));
if (!effectSp) {
@@ -131,9 +128,10 @@ ndk::ScopedAStatus Factory::destroyEffectImpl(const std::shared_ptr<IEffect>& in
auto& uuid = uuidIt->second;
// find implementation library with UUID
if (auto libIt = mEffectLibMap.find(uuid); libIt != mEffectLibMap.end()) {
if (libIt->second.second->destroyEffectFunc) {
RETURN_IF_BINDER_EXCEPTION(libIt->second.second->destroyEffectFunc(in_handle));
}
auto& interface = std::get<kMapEntryInterfaceIndex>(libIt->second);
RETURN_IF(!interface || !interface->destroyEffectFunc, EX_NULL_POINTER,
"dlNulldestroyEffectFunc");
RETURN_IF_BINDER_EXCEPTION(interface->destroyEffectFunc(in_handle));
} else {
LOG(ERROR) << __func__ << ": UUID " << uuid.toString() << " does not exist in libMap!";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
@@ -179,9 +177,13 @@ void Factory::openEffectLibrary(const AudioUuid& impl, const std::string& libNam
return;
}
LOG(DEBUG) << __func__ << " dlopen lib:" << libName << "\nimpl:" << impl.toString()
<< "\nhandle:" << libHandle;
mEffectLibMap.insert({impl, std::make_pair(std::move(libHandle), nullptr)});
LOG(INFO) << __func__ << " dlopen lib:" << libName << "\nimpl:" << impl.toString()
<< "\nhandle:" << libHandle;
auto interface = new effect_dl_interface_s{nullptr, nullptr, nullptr};
mEffectLibMap.insert(
{impl,
std::make_tuple(std::move(libHandle),
std::unique_ptr<struct effect_dl_interface_s>(interface), libName)});
}
void Factory::createIdentityWithConfig(const EffectConfig::LibraryUuid& configLib,
@@ -226,4 +228,32 @@ void Factory::loadEffectLibs() {
}
}
void Factory::getDlSyms(DlEntry& entry) {
auto& dlHandle = std::get<kMapEntryHandleIndex>(entry);
RETURN_VALUE_IF(!dlHandle, void(), "dlNullHandle");
// Get the reference of the DL interfaces in library map tuple.
auto& dlInterface = std::get<kMapEntryInterfaceIndex>(entry);
// return if interface already exist
if (!dlInterface->createEffectFunc) {
dlInterface->createEffectFunc = (EffectCreateFunctor)dlsym(dlHandle.get(), "createEffect");
}
if (!dlInterface->queryEffectFunc) {
dlInterface->queryEffectFunc = (EffectQueryFunctor)dlsym(dlHandle.get(), "queryEffect");
}
if (!dlInterface->destroyEffectFunc) {
dlInterface->destroyEffectFunc =
(EffectDestroyFunctor)dlsym(dlHandle.get(), "destroyEffect");
}
if (!dlInterface->createEffectFunc || !dlInterface->destroyEffectFunc ||
!dlInterface->queryEffectFunc) {
LOG(ERROR) << __func__ << ": create (" << dlInterface->createEffectFunc << "), query ("
<< dlInterface->queryEffectFunc << "), or destroy ("
<< dlInterface->destroyEffectFunc
<< ") not exist in library: " << std::get<kMapEntryLibNameIndex>(entry)
<< " handle: " << dlHandle << " with dlerror: " << dlerror();
return;
}
}
} // namespace aidl::android::hardware::audio::effect

View File

@@ -19,6 +19,21 @@
#include "effect-impl/EffectTypes.h"
#include "include/effect-impl/EffectTypes.h"
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::State;
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
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 EffectImpl::open(const Parameter::Common& common,

View File

@@ -27,6 +27,7 @@
#include "BassBoostSw.h"
using aidl::android::hardware::audio::effect::BassBoostSw;
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kBassBoostSwImplUUID;
using aidl::android::hardware::audio::effect::State;
@@ -48,23 +49,31 @@ extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
}
}
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
if (!instanceSp) {
return EX_NONE;
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
if (!in_impl_uuid || *in_impl_uuid != kBassBoostSwImplUUID) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
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";
*_aidl_return = BassBoostSw::kDescriptor;
return EX_NONE;
}
namespace aidl::android::hardware::audio::effect {
const std::string BassBoostSw::kEffectName = "BassBoostSw";
const bool BassBoostSw::kStrengthSupported = true;
const BassBoost::Capability BassBoostSw::kCapability = {.strengthSupported = kStrengthSupported};
const Descriptor BassBoostSw::kDescriptor = {
.common = {.id = {.type = kBassBoostTypeUUID,
.uuid = kBassBoostSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = BassBoostSw::kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::bassBoost>(BassBoostSw::kCapability)};
ndk::ScopedAStatus BassBoostSw::getDescriptor(Descriptor* _aidl_return) {
LOG(DEBUG) << __func__ << kDescriptor.toString();
*_aidl_return = kDescriptor;
@@ -81,7 +90,7 @@ ndk::ScopedAStatus BassBoostSw::setParameterSpecific(const Parameter::Specific&
switch (tag) {
case BassBoost::strengthPm: {
RETURN_IF(!mStrengthSupported, EX_ILLEGAL_ARGUMENT, "SettingStrengthNotSupported");
RETURN_IF(!kStrengthSupported, EX_ILLEGAL_ARGUMENT, "SettingStrengthNotSupported");
RETURN_IF(mContext->setBbStrengthPm(bbParam.get<BassBoost::strengthPm>()) !=
RetCode::SUCCESS,

View File

@@ -51,6 +51,10 @@ class BassBoostSwContext final : public EffectContext {
class BassBoostSw final : public EffectImpl {
public:
static const std::string kEffectName;
static const bool kStrengthSupported;
static const BassBoost::Capability kCapability;
static const Descriptor kDescriptor;
BassBoostSw() { LOG(DEBUG) << __func__; }
~BassBoostSw() {
cleanUp();
@@ -70,23 +74,7 @@ class BassBoostSw final : public EffectImpl {
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
private:
const std::string kEffectName = "BassBoostSw";
std::shared_ptr<BassBoostSwContext> mContext;
/* capabilities */
const bool mStrengthSupported = true;
const BassBoost::Capability kCapability = {.strengthSupported = mStrengthSupported};
/* Effect descriptor */
const Descriptor kDescriptor = {
.common = {.id = {.type = kBassBoostTypeUUID,
.uuid = kBassBoostSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::bassBoost>(kCapability)};
ndk::ScopedAStatus getParameterBassBoost(const BassBoost::Tag& tag,
Parameter::Specific* specific);
};

View File

@@ -25,6 +25,7 @@
#include "DynamicsProcessingSw.h"
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::DynamicsProcessingSw;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kDynamicsProcessingSwImplUUID;
@@ -47,23 +48,31 @@ extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
}
}
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
if (!instanceSp) {
return EX_NONE;
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
if (!in_impl_uuid || *in_impl_uuid != kDynamicsProcessingSwImplUUID) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
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";
*_aidl_return = DynamicsProcessingSw::kDescriptor;
return EX_NONE;
}
namespace aidl::android::hardware::audio::effect {
const std::string DynamicsProcessingSw::kEffectName = "DynamicsProcessingSw";
const DynamicsProcessing::Capability DynamicsProcessingSw::kCapability;
const Descriptor DynamicsProcessingSw::kDescriptor = {
.common = {.id = {.type = kDynamicsProcessingTypeUUID,
.uuid = kDynamicsProcessingSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = DynamicsProcessingSw::kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::dynamicsProcessing>(
DynamicsProcessingSw::kCapability)};
ndk::ScopedAStatus DynamicsProcessingSw::getDescriptor(Descriptor* _aidl_return) {
LOG(DEBUG) << __func__ << kDescriptor.toString();
*_aidl_return = kDescriptor;

View File

@@ -37,6 +37,9 @@ class DynamicsProcessingSwContext final : public EffectContext {
class DynamicsProcessingSw final : public EffectImpl {
public:
static const std::string kEffectName;
static const DynamicsProcessing::Capability kCapability;
static const Descriptor kDescriptor;
DynamicsProcessingSw() { LOG(DEBUG) << __func__; }
~DynamicsProcessingSw() {
cleanUp();
@@ -56,22 +59,7 @@ class DynamicsProcessingSw final : public EffectImpl {
std::string getEffectName() override { return kEffectName; };
private:
const std::string kEffectName = "DynamicsProcessingSw";
std::shared_ptr<DynamicsProcessingSwContext> mContext;
/* capabilities */
const DynamicsProcessing::Capability kCapability;
/* Effect descriptor */
const Descriptor kDescriptor = {
.common = {.id = {.type = kDynamicsProcessingTypeUUID,
.uuid = kDynamicsProcessingSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::dynamicsProcessing>(kCapability)};
/* parameters */
DynamicsProcessing mSpecificParam;
};

View File

@@ -25,6 +25,7 @@
#include "EnvReverbSw.h"
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::EnvReverbSw;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kEnvReverbSwImplUUID;
@@ -47,23 +48,30 @@ extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
}
}
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
if (!instanceSp) {
return EX_NONE;
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
if (!in_impl_uuid || *in_impl_uuid != kEnvReverbSwImplUUID) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
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";
*_aidl_return = EnvReverbSw::kDescriptor;
return EX_NONE;
}
namespace aidl::android::hardware::audio::effect {
const std::string EnvReverbSw::kEffectName = "EnvReverbSw";
const EnvironmentalReverb::Capability EnvReverbSw::kCapability;
const Descriptor EnvReverbSw::kDescriptor = {
.common = {.id = {.type = kEnvReverbTypeUUID,
.uuid = kEnvReverbSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = EnvReverbSw::kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::environmentalReverb>(EnvReverbSw::kCapability)};
ndk::ScopedAStatus EnvReverbSw::getDescriptor(Descriptor* _aidl_return) {
LOG(DEBUG) << __func__ << kDescriptor.toString();
*_aidl_return = kDescriptor;
@@ -71,10 +79,10 @@ ndk::ScopedAStatus EnvReverbSw::getDescriptor(Descriptor* _aidl_return) {
}
ndk::ScopedAStatus EnvReverbSw::setParameterSpecific(const Parameter::Specific& specific) {
RETURN_IF(Parameter::Specific::reverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
RETURN_IF(Parameter::Specific::environmentalReverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
"EffectNotSupported");
mSpecificParam = specific.get<Parameter::Specific::reverb>();
mSpecificParam = specific.get<Parameter::Specific::environmentalReverb>();
LOG(DEBUG) << __func__ << " success with: " << specific.toString();
return ndk::ScopedAStatus::ok();
}
@@ -82,8 +90,8 @@ ndk::ScopedAStatus EnvReverbSw::setParameterSpecific(const Parameter::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_IF(Parameter::Id::environmentalReverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
specific->set<Parameter::Specific::environmentalReverb>(mSpecificParam);
return ndk::ScopedAStatus::ok();
}

View File

@@ -37,6 +37,9 @@ class EnvReverbSwContext final : public EffectContext {
class EnvReverbSw final : public EffectImpl {
public:
static const std::string kEffectName;
static const EnvironmentalReverb::Capability kCapability;
static const Descriptor kDescriptor;
EnvReverbSw() { LOG(DEBUG) << __func__; }
~EnvReverbSw() {
cleanUp();
@@ -56,23 +59,8 @@ class EnvReverbSw final : public EffectImpl {
std::string getEffectName() override { return kEffectName; }
private:
const std::string kEffectName = "EnvReverbSw";
std::shared_ptr<EnvReverbSwContext> mContext;
/* capabilities */
const Reverb::Capability kCapability;
/* Effect descriptor */
const Descriptor kDescriptor = {
.common = {.id = {.type = kEnvReverbTypeUUID,
.uuid = kEnvReverbSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::reverb>(kCapability)};
/* parameters */
Reverb mSpecificParam;
EnvironmentalReverb mSpecificParam;
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -25,6 +25,7 @@
#include "EqualizerSw.h"
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::EqualizerSw;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kEqualizerSwImplUUID;
@@ -47,20 +48,41 @@ extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
}
}
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
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;
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
if (!in_impl_uuid || *in_impl_uuid != kEqualizerSwImplUUID) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
*_aidl_return = EqualizerSw::kDesc;
return EX_NONE;
}
namespace aidl::android::hardware::audio::effect {
const std::string EqualizerSw::kEffectName = "EqualizerSw";
const std::vector<Equalizer::BandFrequency> EqualizerSw::kBandFrequency = {{0, 30000, 120000},
{1, 120001, 460000},
{2, 460001, 1800000},
{3, 1800001, 7000000},
{4, 7000001, 20000000}};
const std::vector<Equalizer::Preset> EqualizerSw::kPresets = {
{0, "Normal"}, {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
{5, "Heavy Metal"}, {6, "Hip Hop"}, {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}};
const Equalizer::Capability EqualizerSw::kEqCap = {.bandFrequencies = kBandFrequency,
.presets = kPresets};
const Descriptor EqualizerSw::kDesc = {
.common = {.id = {.type = kEqualizerTypeUUID,
.uuid = kEqualizerSwImplUUID,
.proxy = kEqualizerProxyUUID},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = EqualizerSw::kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::equalizer>(EqualizerSw::kEqCap)};
ndk::ScopedAStatus EqualizerSw::getDescriptor(Descriptor* _aidl_return) {
LOG(DEBUG) << __func__ << kDesc.toString();
*_aidl_return = kDesc;

View File

@@ -80,6 +80,12 @@ class EqualizerSwContext final : public EffectContext {
class EqualizerSw final : public EffectImpl {
public:
static const std::string kEffectName;
static const std::vector<Equalizer::BandFrequency> kBandFrequency;
static const std::vector<Equalizer::Preset> kPresets;
static const Equalizer::Capability kEqCap;
static const Descriptor kDesc;
EqualizerSw() { LOG(DEBUG) << __func__; }
~EqualizerSw() {
cleanUp();
@@ -99,32 +105,9 @@ class EqualizerSw final : public EffectImpl {
std::string getEffectName() override { return kEffectName; }
private:
const std::string kEffectName = "EqualizerSw";
std::shared_ptr<EqualizerSwContext> mContext;
/* capabilities */
const std::vector<Equalizer::BandFrequency> mBandFrequency = {{0, 30000, 120000},
{1, 120001, 460000},
{2, 460001, 1800000},
{3, 1800001, 7000000},
{4, 7000001, 20000000}};
// presets supported by the device
const std::vector<Equalizer::Preset> mPresets = {
{0, "Normal"}, {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
{5, "Heavy Metal"}, {6, "Hip Hop"}, {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}};
const Equalizer::Capability kEqCap = {.bandFrequencies = mBandFrequency, .presets = mPresets};
// Effect descriptor.
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 = kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::equalizer>(kEqCap)};
ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
Parameter::Specific* specific);
std::shared_ptr<EqualizerSwContext> mContext;
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -25,6 +25,7 @@
#include "HapticGeneratorSw.h"
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::HapticGeneratorSw;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kHapticGeneratorSwImplUUID;
@@ -47,23 +48,33 @@ extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
}
}
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
if (!instanceSp) {
return EX_NONE;
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
if (!in_impl_uuid || *in_impl_uuid != kHapticGeneratorSwImplUUID) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
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";
*_aidl_return = HapticGeneratorSw::kDescriptor;
return EX_NONE;
}
namespace aidl::android::hardware::audio::effect {
const std::string HapticGeneratorSw::kEffectName = "HapticGeneratorSw";
/* capabilities */
const HapticGenerator::Capability HapticGeneratorSw::kCapability;
/* Effect descriptor */
const Descriptor HapticGeneratorSw::kDescriptor = {
.common = {.id = {.type = kHapticGeneratorTypeUUID,
.uuid = kHapticGeneratorSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = HapticGeneratorSw::kEffectName,
.implementor = "The Android Open Source Project"},
.capability =
Capability::make<Capability::hapticGenerator>(HapticGeneratorSw::kCapability)};
ndk::ScopedAStatus HapticGeneratorSw::getDescriptor(Descriptor* _aidl_return) {
LOG(DEBUG) << __func__ << kDescriptor.toString();
*_aidl_return = kDescriptor;

View File

@@ -37,6 +37,9 @@ class HapticGeneratorSwContext final : public EffectContext {
class HapticGeneratorSw final : public EffectImpl {
public:
static const std::string kEffectName;
static const HapticGenerator::Capability kCapability;
static const Descriptor kDescriptor;
HapticGeneratorSw() { LOG(DEBUG) << __func__; }
~HapticGeneratorSw() {
cleanUp();
@@ -56,22 +59,7 @@ class HapticGeneratorSw final : public EffectImpl {
std::string getEffectName() override { return kEffectName; }
private:
const std::string kEffectName = "HapticGeneratorSw";
std::shared_ptr<HapticGeneratorSwContext> mContext;
/* capabilities */
const HapticGenerator::Capability kCapability;
/* Effect descriptor */
const Descriptor kDescriptor = {
.common = {.id = {.type = kHapticGeneratorTypeUUID,
.uuid = kHapticGeneratorSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::hapticGenerator>(kCapability)};
/* parameters */
HapticGenerator mSpecificParam;
};

View File

@@ -28,6 +28,9 @@
#include "effect-impl/EffectThread.h"
#include "effect-impl/EffectTypes.h"
extern "C" binder_exception_t destroyEffect(
const std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>& instanceSp);
namespace aidl::android::hardware::audio::effect {
class EffectImpl : public BnEffect, public EffectThread {

View File

@@ -26,10 +26,14 @@ typedef binder_exception_t (*EffectCreateFunctor)(
std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>*);
typedef binder_exception_t (*EffectDestroyFunctor)(
const std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>&);
typedef binder_exception_t (*EffectQueryFunctor)(
const ::aidl::android::media::audio::common::AudioUuid*,
aidl::android::hardware::audio::effect::Descriptor*);
struct effect_dl_interface_s {
EffectCreateFunctor createEffectFunc;
EffectDestroyFunctor destroyEffectFunc;
EffectQueryFunctor queryEffectFunc;
};
namespace aidl::android::hardware::audio::effect {
@@ -102,6 +106,15 @@ inline std::ostream& operator<<(std::ostream& out, const RetCode& code) {
} \
} while (0)
#define RETURN_IF_BINDER_EXCEPTION(functor) \
{ \
binder_exception_t exception = functor; \
if (EX_NONE != exception) { \
LOG(ERROR) << #functor << ": failed with error " << exception; \
return ndk::ScopedAStatus::fromExceptionCode(exception); \
} \
}
static inline bool stringToUuid(const char* str,
::aidl::android::media::audio::common::AudioUuid* uuid) {
RETURN_VALUE_IF(!uuid || !str, false, "nullPtr");

View File

@@ -20,6 +20,7 @@
#include <map>
#include <optional>
#include <set>
#include <tuple>
#include <vector>
#include <aidl/android/hardware/audio/effect/BnFactory.h>
@@ -37,14 +38,14 @@ class Factory : public BnFactory {
* @param in_type Type UUID.
* @param in_instance Instance UUID.
* @param in_proxy Proxy UUID.
* @param out_descriptor List of identities .
* @param out_descriptor List of Descriptors.
* @return ndk::ScopedAStatus
*/
ndk::ScopedAStatus queryEffects(
const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_type,
const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_instance,
const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_proxy,
std::vector<Descriptor::Identity>* out_descriptor) override;
std::vector<Descriptor>* out_descriptor) override;
/**
* @brief Query list of defined processing, with the optional filter by AudioStreamType
@@ -82,12 +83,19 @@ class Factory : public BnFactory {
const EffectConfig mConfig;
~Factory();
// Set of effect descriptors supported by the devices.
std::set<Descriptor> mDescSet;
std::set<Descriptor::Identity> mIdentitySet;
std::map<aidl::android::media::audio::common::AudioUuid /* implementationUUID */,
std::pair<std::unique_ptr<void, std::function<void(void*)>> /* dlHandle */,
std::unique_ptr<struct effect_dl_interface_s>>>
mEffectLibMap;
static constexpr int kMapEntryHandleIndex = 0;
static constexpr int kMapEntryInterfaceIndex = 1;
static constexpr int kMapEntryLibNameIndex = 2;
typedef std::tuple<std::unique_ptr<void, std::function<void(void*)>> /* dlHandle */,
std::unique_ptr<struct effect_dl_interface_s> /* interfaces */,
std::string /* library name */>
DlEntry;
std::map<aidl::android::media::audio::common::AudioUuid /* implUUID */, DlEntry> mEffectLibMap;
std::map<std::weak_ptr<IEffect>, aidl::android::media::audio::common::AudioUuid,
std::owner_less<>>
mEffectUuidMap;
@@ -101,6 +109,8 @@ class Factory : public BnFactory {
const ::aidl::android::media::audio::common::AudioUuid& typeUuid,
const std::optional<::aidl::android::media::audio::common::AudioUuid> proxyUuid);
void loadEffectLibs();
/* Get effect_dl_interface_s from library handle */
void getDlSyms(DlEntry& entry);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -25,6 +25,7 @@
#include "LoudnessEnhancerSw.h"
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kLoudnessEnhancerSwImplUUID;
using aidl::android::hardware::audio::effect::LoudnessEnhancerSw;
@@ -47,23 +48,28 @@ extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
}
}
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
if (!instanceSp) {
return EX_NONE;
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
if (!in_impl_uuid || *in_impl_uuid != kLoudnessEnhancerSwImplUUID) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
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";
*_aidl_return = LoudnessEnhancerSw::kDescriptor;
return EX_NONE;
}
namespace aidl::android::hardware::audio::effect {
const std::string LoudnessEnhancerSw::kEffectName = "LoudnessEnhancerSw";
const Descriptor LoudnessEnhancerSw::kDescriptor = {
.common = {.id = {.type = kLoudnessEnhancerTypeUUID,
.uuid = kLoudnessEnhancerSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = LoudnessEnhancerSw::kEffectName,
.implementor = "The Android Open Source Project"}};
ndk::ScopedAStatus LoudnessEnhancerSw::getDescriptor(Descriptor* _aidl_return) {
LOG(DEBUG) << __func__ << kDescriptor.toString();
*_aidl_return = kDescriptor;

View File

@@ -46,6 +46,9 @@ class LoudnessEnhancerSwContext final : public EffectContext {
class LoudnessEnhancerSw final : public EffectImpl {
public:
static const std::string kEffectName;
static const LoudnessEnhancer::Capability kCapability;
static const Descriptor kDescriptor;
LoudnessEnhancerSw() { LOG(DEBUG) << __func__; }
~LoudnessEnhancerSw() {
cleanUp();
@@ -65,22 +68,7 @@ class LoudnessEnhancerSw final : public EffectImpl {
std::string getEffectName() override { return kEffectName; }
private:
const std::string kEffectName = "LoudnessEnhancerSw";
std::shared_ptr<LoudnessEnhancerSwContext> mContext;
/* capabilities */
const LoudnessEnhancer::Capability kCapability;
/* Effect descriptor */
const Descriptor kDescriptor = {
.common = {.id = {.type = kLoudnessEnhancerTypeUUID,
.uuid = kLoudnessEnhancerSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::loudnessEnhancer>(kCapability)};
ndk::ScopedAStatus getParameterLoudnessEnhancer(const LoudnessEnhancer::Tag& tag,
Parameter::Specific* specific);
};

View File

@@ -25,6 +25,7 @@
#include "PresetReverbSw.h"
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kPresetReverbSwImplUUID;
using aidl::android::hardware::audio::effect::PresetReverbSw;
@@ -47,23 +48,30 @@ extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
}
}
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
if (!instanceSp) {
return EX_NONE;
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
if (!in_impl_uuid || *in_impl_uuid != kPresetReverbSwImplUUID) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
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";
*_aidl_return = PresetReverbSw::kDescriptor;
return EX_NONE;
}
namespace aidl::android::hardware::audio::effect {
const std::string PresetReverbSw::kEffectName = "PresetReverbSw";
const PresetReverb::Capability PresetReverbSw::kCapability;
const Descriptor PresetReverbSw::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::kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::presetReverb>(PresetReverbSw::kCapability)};
ndk::ScopedAStatus PresetReverbSw::getDescriptor(Descriptor* _aidl_return) {
LOG(DEBUG) << __func__ << kDescriptor.toString();
*_aidl_return = kDescriptor;
@@ -71,10 +79,10 @@ ndk::ScopedAStatus PresetReverbSw::getDescriptor(Descriptor* _aidl_return) {
}
ndk::ScopedAStatus PresetReverbSw::setParameterSpecific(const Parameter::Specific& specific) {
RETURN_IF(Parameter::Specific::reverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
RETURN_IF(Parameter::Specific::presetReverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
"EffectNotSupported");
mSpecificParam = specific.get<Parameter::Specific::reverb>();
mSpecificParam = specific.get<Parameter::Specific::presetReverb>();
LOG(DEBUG) << __func__ << " success with: " << specific.toString();
return ndk::ScopedAStatus::ok();
}
@@ -82,8 +90,8 @@ ndk::ScopedAStatus PresetReverbSw::setParameterSpecific(const Parameter::Specifi
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_IF(Parameter::Id::presetReverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
specific->set<Parameter::Specific::presetReverb>(mSpecificParam);
return ndk::ScopedAStatus::ok();
}

View File

@@ -37,6 +37,9 @@ class PresetReverbSwContext final : public EffectContext {
class PresetReverbSw final : public EffectImpl {
public:
static const std::string kEffectName;
static const PresetReverb::Capability kCapability;
static const Descriptor kDescriptor;
PresetReverbSw() { LOG(DEBUG) << __func__; }
~PresetReverbSw() {
cleanUp();
@@ -56,23 +59,8 @@ class PresetReverbSw final : public EffectImpl {
std::string getEffectName() override { return kEffectName; }
private:
const std::string kEffectName = "PresetReverbSw";
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 = kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::reverb>(kCapability)};
/* parameters */
Reverb mSpecificParam;
PresetReverb mSpecificParam;
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -25,6 +25,7 @@
#include "VirtualizerSw.h"
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kVirtualizerSwImplUUID;
using aidl::android::hardware::audio::effect::State;
@@ -47,23 +48,30 @@ extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
}
}
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
if (!instanceSp) {
return EX_NONE;
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
if (!in_impl_uuid || *in_impl_uuid != kVirtualizerSwImplUUID) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
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";
*_aidl_return = VirtualizerSw::kDescriptor;
return EX_NONE;
}
namespace aidl::android::hardware::audio::effect {
const std::string VirtualizerSw::kEffectName = "VirtualizerSw";
const Virtualizer::Capability VirtualizerSw::kCapability;
const Descriptor VirtualizerSw::kDescriptor = {
.common = {.id = {.type = kVirtualizerTypeUUID,
.uuid = kVirtualizerSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = VirtualizerSw::kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::virtualizer>(VirtualizerSw::kCapability)};
ndk::ScopedAStatus VirtualizerSw::getDescriptor(Descriptor* _aidl_return) {
LOG(DEBUG) << __func__ << kDescriptor.toString();
*_aidl_return = kDescriptor;

View File

@@ -37,6 +37,9 @@ class VirtualizerSwContext final : public EffectContext {
class VirtualizerSw final : public EffectImpl {
public:
static const std::string kEffectName;
static const Virtualizer::Capability kCapability;
static const Descriptor kDescriptor;
VirtualizerSw() { LOG(DEBUG) << __func__; }
~VirtualizerSw() {
cleanUp();
@@ -56,22 +59,7 @@ class VirtualizerSw final : public EffectImpl {
std::string getEffectName() override { return kEffectName; }
private:
const std::string kEffectName = "VirtualizerSw";
std::shared_ptr<VirtualizerSwContext> mContext;
/* capabilities */
const Virtualizer::Capability kCapability;
/* Effect descriptor */
const Descriptor kDescriptor = {
.common = {.id = {.type = kVirtualizerTypeUUID,
.uuid = kVirtualizerSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::virtualizer>(kCapability)};
/* parameters */
Virtualizer mSpecificParam;
};

View File

@@ -25,6 +25,7 @@
#include "VisualizerSw.h"
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kVisualizerSwImplUUID;
using aidl::android::hardware::audio::effect::State;
@@ -47,23 +48,30 @@ extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
}
}
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
if (!instanceSp) {
return EX_NONE;
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
if (!in_impl_uuid || *in_impl_uuid != kVisualizerSwImplUUID) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
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";
*_aidl_return = VisualizerSw::kDescriptor;
return EX_NONE;
}
namespace aidl::android::hardware::audio::effect {
const std::string VisualizerSw::kEffectName = "VisualizerSw";
const Visualizer::Capability VisualizerSw::kCapability;
const Descriptor VisualizerSw::kDescriptor = {
.common = {.id = {.type = kVisualizerTypeUUID,
.uuid = kVisualizerSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = VisualizerSw::kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::visualizer>(VisualizerSw::kCapability)};
ndk::ScopedAStatus VisualizerSw::getDescriptor(Descriptor* _aidl_return) {
LOG(DEBUG) << __func__ << kDescriptor.toString();
*_aidl_return = kDescriptor;

View File

@@ -37,6 +37,9 @@ class VisualizerSwContext final : public EffectContext {
class VisualizerSw final : public EffectImpl {
public:
static const std::string kEffectName;
static const Visualizer::Capability kCapability;
static const Descriptor kDescriptor;
VisualizerSw() { LOG(DEBUG) << __func__; }
~VisualizerSw() {
cleanUp();
@@ -56,22 +59,7 @@ class VisualizerSw final : public EffectImpl {
std::string getEffectName() override { return kEffectName; }
private:
const std::string kEffectName = "VisualizerSw";
std::shared_ptr<VisualizerSwContext> mContext;
/* capabilities */
const Visualizer::Capability kCapability;
/* Effect descriptor */
const Descriptor kDescriptor = {
.common = {.id = {.type = kVisualizerTypeUUID,
.uuid = kVisualizerSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::visualizer>(kCapability)};
/* parameters */
Visualizer mSpecificParam;
};

View File

@@ -25,6 +25,7 @@
#include "VolumeSw.h"
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kVolumeSwImplUUID;
using aidl::android::hardware::audio::effect::State;
@@ -47,23 +48,30 @@ extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
}
}
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
if (!instanceSp) {
return EX_NONE;
extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descriptor* _aidl_return) {
if (!in_impl_uuid || *in_impl_uuid != kVolumeSwImplUUID) {
LOG(ERROR) << __func__ << "uuid not supported";
return EX_ILLEGAL_ARGUMENT;
}
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";
*_aidl_return = VolumeSw::kDescriptor;
return EX_NONE;
}
namespace aidl::android::hardware::audio::effect {
const std::string VolumeSw::kEffectName = "VolumeSw";
const Volume::Capability VolumeSw::kCapability;
const Descriptor VolumeSw::kDescriptor = {
.common = {.id = {.type = kVolumeTypeUUID,
.uuid = kVolumeSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = VolumeSw::kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::volume>(VolumeSw::kCapability)};
ndk::ScopedAStatus VolumeSw::getDescriptor(Descriptor* _aidl_return) {
LOG(DEBUG) << __func__ << kDescriptor.toString();
*_aidl_return = kDescriptor;

View File

@@ -37,6 +37,9 @@ class VolumeSwContext final : public EffectContext {
class VolumeSw final : public EffectImpl {
public:
static const std::string kEffectName;
static const Volume::Capability kCapability;
static const Descriptor kDescriptor;
VolumeSw() { LOG(DEBUG) << __func__; }
~VolumeSw() {
cleanUp();
@@ -56,22 +59,7 @@ class VolumeSw final : public EffectImpl {
std::string getEffectName() override { return kEffectName; }
private:
const std::string kEffectName = "VolumeSw";
std::shared_ptr<VolumeSwContext> mContext;
/* capabilities */
const Volume::Capability kCapability;
/* Effect descriptor */
const Descriptor kDescriptor = {
.common = {.id = {.type = kVolumeTypeUUID,
.uuid = kVolumeSwImplUUID,
.proxy = std::nullopt},
.flags = {.type = Flags::Type::INSERT,
.insert = Flags::Insert::FIRST,
.volume = Flags::Volume::CTRL},
.name = kEffectName,
.implementor = "The Android Open Source Project"},
.capability = Capability::make<Capability::volume>(kCapability)};
/* parameters */
Volume mSpecificParam;
};

View File

@@ -58,9 +58,11 @@ class EffectFactoryHelper {
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 (std::vector<Descriptor> descs;
factory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs)
.isOk()) {
for (const auto& desc : descs) {
const auto& id = desc.common.id;
if (type.has_value() && id.type != type.value()) {
continue;
}

View File

@@ -65,8 +65,10 @@ class EffectFactoryTest : public testing::TestWithParam<std::string> {
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 kNullId = {.uuid = kEffectNullUuid};
const Descriptor::Identity kZeroId = {.uuid = kEffectZeroUuid};
const Descriptor kNullDesc = {.common.id = kNullId};
const Descriptor kZeroDesc = {.common.id = kZeroId};
template <typename Functor>
void ForEachId(const std::vector<Descriptor::Identity> ids, Functor functor) {
@@ -82,15 +84,15 @@ class EffectFactoryTest : public testing::TestWithParam<std::string> {
}
}
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>> createWithDescs(
const std::vector<Descriptor> descs, const binder_status_t expectStatus = EX_NONE) {
std::vector<std::shared_ptr<IEffect>> effects;
for (const auto& id : ids) {
for (const auto& desc : descs) {
const auto& uuid = desc.common.id.uuid;
std::shared_ptr<IEffect> effect;
EXPECT_STATUS(expectStatus, mEffectFactory->createEffect(id.uuid, &effect));
EXPECT_STATUS(expectStatus, mEffectFactory->createEffect(uuid, &effect));
if (expectStatus == EX_NONE) {
EXPECT_NE(effect, nullptr) << " null effect with uuid: " << id.uuid.toString();
EXPECT_NE(effect, nullptr) << " null effect with uuid: " << uuid.toString();
effects.push_back(std::move(effect));
}
}
@@ -102,9 +104,9 @@ class EffectFactoryTest : public testing::TestWithParam<std::string> {
EXPECT_STATUS(expectStatus, mEffectFactory->destroyEffect(effect));
}
}
void creatAndDestroyIds(const std::vector<Descriptor::Identity> ids) {
for (const auto& id : ids) {
auto effects = createWithIds({id});
void creatAndDestroyDescs(const std::vector<Descriptor> descs) {
for (const auto& desc : descs) {
auto effects = createWithDescs({desc});
ASSERT_NO_FATAL_FAILURE(destroyEffects(effects));
}
}
@@ -128,7 +130,7 @@ TEST_P(EffectFactoryTest, CanBeRestarted) {
* https://developer.android.com/reference/android/media/audiofx/AudioEffect
*/
TEST_P(EffectFactoryTest, ExpectAllAospEffectTypes) {
std::vector<Descriptor::Identity> ids;
std::vector<Descriptor> descs;
std::set<AudioUuid> typeUuidSet(
{aidl::android::hardware::audio::effect::kBassBoostTypeUUID,
aidl::android::hardware::audio::effect::kEqualizerTypeUUID,
@@ -138,10 +140,10 @@ TEST_P(EffectFactoryTest, ExpectAllAospEffectTypes) {
aidl::android::hardware::audio::effect::kHapticGeneratorTypeUUID,
aidl::android::hardware::audio::effect::kVirtualizerTypeUUID});
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);
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
EXPECT_TRUE(descs.size() >= typeUuidSet.size());
for (const auto& desc : descs) {
typeUuidSet.erase(desc.common.id.type);
}
std::string msg = " missing type UUID:\n";
for (const auto& uuid : typeUuidSet) {
@@ -152,46 +154,46 @@ TEST_P(EffectFactoryTest, ExpectAllAospEffectTypes) {
}
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);
std::vector<Descriptor> descs;
EXPECT_IS_OK(mEffectFactory->queryEffects(kEffectNullUuid, std::nullopt, std::nullopt, &descs));
EXPECT_EQ(descs.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);
std::vector<Descriptor> descs;
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, kEffectNullUuid, std::nullopt, &descs));
EXPECT_EQ(descs.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);
std::vector<Descriptor> descs;
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, kEffectNullUuid, &descs));
EXPECT_EQ(descs.size(), 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);
std::vector<Descriptor> descs;
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
EXPECT_NE(descs.size(), 0UL);
std::vector<std::shared_ptr<IEffect>> effects;
effects = createWithIds(ids);
EXPECT_EQ(ids.size(), effects.size());
effects = createWithDescs(descs);
EXPECT_EQ(descs.size(), effects.size());
destroyEffects(effects);
}
TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
std::vector<Descriptor::Identity> ids;
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
EXPECT_NE(ids.size(), 0UL);
std::vector<Descriptor> descs;
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
EXPECT_NE(descs.size(), 0UL);
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());
std::vector<std::shared_ptr<IEffect>> effects = createWithDescs(descs);
EXPECT_EQ(descs.size(), effects.size());
std::vector<std::shared_ptr<IEffect>> effects2 = createWithDescs(descs);
EXPECT_EQ(descs.size(), effects2.size());
std::vector<std::shared_ptr<IEffect>> effects3 = createWithDescs(descs);
EXPECT_EQ(descs.size(), effects3.size());
destroyEffects(effects);
destroyEffects(effects2);
@@ -200,28 +202,28 @@ TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
// 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);
std::vector<Descriptor> descs;
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
EXPECT_NE(descs.size(), 0UL);
creatAndDestroyIds(ids);
creatAndDestroyDescs(descs);
}
// 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);
std::vector<Descriptor> descs;
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
EXPECT_NE(descs.size(), 0UL);
creatAndDestroyIds(ids);
creatAndDestroyIds(ids);
creatAndDestroyIds(ids);
creatAndDestroyDescs(descs);
creatAndDestroyDescs(descs);
creatAndDestroyDescs(descs);
}
// Expect EX_ILLEGAL_ARGUMENT when create with invalid UUID.
TEST_P(EffectFactoryTest, CreateWithInvalidUuid) {
std::vector<Descriptor::Identity> ids = {kNullDesc, kZeroDesc};
auto effects = createWithIds(ids, EX_ILLEGAL_ARGUMENT);
std::vector<Descriptor> descs = {kNullDesc, kZeroDesc};
auto effects = createWithDescs(descs, EX_ILLEGAL_ARGUMENT);
EXPECT_EQ(effects.size(), 0UL);
}
@@ -233,23 +235,23 @@ TEST_P(EffectFactoryTest, DestroyWithInvalidInterface) {
// 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);
std::vector<Descriptor> descs;
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
EXPECT_NE(descs.size(), 0UL);
creatAndDestroyDescs(descs);
mFactoryHelper->RestartFactoryService();
connectAndGetFactory();
creatAndDestroyIds(ids);
creatAndDestroyDescs(descs);
}
// 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);
std::vector<Descriptor> descs;
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &descs));
EXPECT_NE(descs.size(), 0UL);
std::vector<std::shared_ptr<IEffect>> effects = createWithDescs(descs);
ASSERT_NO_FATAL_FAILURE(mFactoryHelper->RestartFactoryService());