mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
AIDL effect: Add all aosp effects default implementation
Bug: 238913361 Test: atest VtsHalAudioEffectTargetTest atest VtsHalAudioEffectFactoryTargetTest atest VtsHalEqualizerTargetTest Change-Id: I6825ba77ae0707f97e852f0faa52ce3486ba2af5
This commit is contained in:
@@ -68,10 +68,20 @@ cc_defaults {
|
||||
],
|
||||
vendor: true,
|
||||
shared_libs: [
|
||||
"libaudioaidlcommon",
|
||||
"libbase",
|
||||
"libbinder_ndk",
|
||||
"libcutils",
|
||||
"libfmq",
|
||||
"liblog",
|
||||
"libutils",
|
||||
"android.hardware.common-V2-ndk",
|
||||
"android.hardware.common.fmq-V1-ndk",
|
||||
"android.hardware.audio.effect-V1-ndk",
|
||||
"libequalizer",
|
||||
],
|
||||
header_libs: [
|
||||
"libaudioaidl_headers",
|
||||
"libsystem_headers",
|
||||
],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
@@ -81,24 +91,12 @@ cc_defaults {
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "libaudioeffectserviceexampleimpl",
|
||||
defaults: ["aidlaudioeffectservice_defaults"],
|
||||
export_include_dirs: ["include"],
|
||||
srcs: [
|
||||
"EffectFactory.cpp",
|
||||
],
|
||||
header_libs: [
|
||||
"libsystem_headers",
|
||||
],
|
||||
visibility: [
|
||||
":__subpackages__",
|
||||
],
|
||||
}
|
||||
|
||||
filegroup {
|
||||
name: "effectCommonFile",
|
||||
srcs: ["EffectThread.cpp"],
|
||||
srcs: [
|
||||
"EffectThread.cpp",
|
||||
"EffectImpl.cpp",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
@@ -107,10 +105,21 @@ cc_binary {
|
||||
init_rc: ["android.hardware.audio.effect.service-aidl.example.rc"],
|
||||
vintf_fragments: ["android.hardware.audio.effect.service-aidl.xml"],
|
||||
defaults: ["aidlaudioeffectservice_defaults"],
|
||||
static_libs: [
|
||||
"libaudioeffectserviceexampleimpl",
|
||||
shared_libs: [
|
||||
"libbassboostsw",
|
||||
"libdynamicsprocessingsw",
|
||||
"libequalizersw",
|
||||
"libhapticgeneratorsw",
|
||||
"libloudnessenhancersw",
|
||||
"libreverbsw",
|
||||
"libvirtualizersw",
|
||||
"libvisualizersw",
|
||||
"libvolumesw",
|
||||
],
|
||||
srcs: [
|
||||
"EffectMain.cpp",
|
||||
"EffectFactory.cpp",
|
||||
],
|
||||
srcs: ["EffectMain.cpp"],
|
||||
}
|
||||
|
||||
cc_library_headers {
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <android-base/logging.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include "effect-impl/EffectTypes.h"
|
||||
#include "effect-impl/EffectUUID.h"
|
||||
#include "effectFactory-impl/EffectFactory.h"
|
||||
|
||||
@@ -26,27 +27,21 @@ using aidl::android::media::audio::common::AudioUuid;
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
Factory::Factory() {
|
||||
std::function<void(void*)> dlClose = [](void* handle) -> void {
|
||||
if (handle && dlclose(handle)) {
|
||||
LOG(ERROR) << "dlclose failed " << dlerror();
|
||||
}
|
||||
};
|
||||
// TODO: implement this with audio_effect.xml.
|
||||
auto libHandle =
|
||||
std::unique_ptr<void, decltype(dlClose)>{dlopen("libequalizer.so", RTLD_LAZY), dlClose};
|
||||
if (!libHandle) {
|
||||
LOG(ERROR) << __func__ << ": dlopen failed, err: " << dlerror();
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(DEBUG) << __func__ << " dlopen uuid: " << EqualizerSwImplUUID.toString() << " handle "
|
||||
<< libHandle;
|
||||
mEffectLibMap.insert({EqualizerSwImplUUID, std::make_pair(std::move(libHandle), nullptr)});
|
||||
|
||||
Descriptor::Identity id;
|
||||
id.type = EqualizerTypeUUID;
|
||||
id.uuid = EqualizerSwImplUUID;
|
||||
mIdentityList.push_back(id);
|
||||
// TODO: get list of library UUID and name from audio_effect.xml.
|
||||
openEffectLibrary(EqualizerTypeUUID, EqualizerSwImplUUID, std::nullopt, "libequalizersw.so");
|
||||
openEffectLibrary(EqualizerTypeUUID, EqualizerBundleImplUUID, std::nullopt, "libbundleaidl.so");
|
||||
openEffectLibrary(BassBoostTypeUUID, BassBoostSwImplUUID, std::nullopt, "libbassboostsw.so");
|
||||
openEffectLibrary(DynamicsProcessingTypeUUID, DynamicsProcessingSwImplUUID, std::nullopt,
|
||||
"libdynamicsprocessingsw.so");
|
||||
openEffectLibrary(HapticGeneratorTypeUUID, HapticGeneratorSwImplUUID, std::nullopt,
|
||||
"libhapticgeneratorsw.so");
|
||||
openEffectLibrary(LoudnessEnhancerTypeUUID, LoudnessEnhancerSwImplUUID, std::nullopt,
|
||||
"libloudnessenhancersw.so");
|
||||
openEffectLibrary(ReverbTypeUUID, ReverbSwImplUUID, std::nullopt, "libreverbsw.so");
|
||||
openEffectLibrary(VirtualizerTypeUUID, VirtualizerSwImplUUID, std::nullopt,
|
||||
"libvirtualizersw.so");
|
||||
openEffectLibrary(VisualizerTypeUUID, VisualizerSwImplUUID, std::nullopt, "libvisualizersw.so");
|
||||
openEffectLibrary(VolumeTypeUUID, VolumeSwImplUUID, std::nullopt, "libvolumesw.so");
|
||||
}
|
||||
|
||||
Factory::~Factory() {
|
||||
@@ -64,12 +59,16 @@ 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(mIdentityList.begin(), mIdentityList.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);
|
||||
});
|
||||
std::copy_if(
|
||||
mIdentityList.begin(), mIdentityList.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()));
|
||||
});
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
@@ -96,43 +95,37 @@ ndk::ScopedAStatus Factory::queryProcessing(const std::optional<Processing::Type
|
||||
ndk::ScopedAStatus Factory::createEffect(const AudioUuid& in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString();
|
||||
if (in_impl_uuid == EqualizerSwImplUUID) {
|
||||
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();
|
||||
struct effect_interface_s intf = {
|
||||
.createEffectFunc = (EffectCreateFunctor)dlsym(libHandle, "createEffect"),
|
||||
.destroyEffectFunc =
|
||||
(EffectDestroyFunctor)dlsym(libHandle, "destroyEffect")};
|
||||
auto dlInterface = std::make_unique<struct effect_interface_s>(intf);
|
||||
if (!dlInterface->createEffectFunc || !dlInterface->destroyEffectFunc) {
|
||||
LOG(ERROR) << __func__
|
||||
<< ": create or destroy symbol not exist in library: " << libHandle
|
||||
<< "!";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
|
||||
}
|
||||
lib.second = std::move(dlInterface);
|
||||
}
|
||||
|
||||
auto& libInterface = lib.second;
|
||||
std::shared_ptr<IEffect> effectSp;
|
||||
RETURN_IF_BINDER_EXCEPTION(libInterface->createEffectFunc(&effectSp));
|
||||
if (!effectSp) {
|
||||
LOG(ERROR) << __func__ << ": library created null instance without return error!";
|
||||
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);
|
||||
}
|
||||
*_aidl_return = effectSp;
|
||||
mEffectUuidMap[std::weak_ptr<IEffect>(effectSp)] = in_impl_uuid;
|
||||
LOG(DEBUG) << __func__ << ": instance " << effectSp.get() << " created successfully";
|
||||
return ndk::ScopedAStatus::ok();
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << ": library doesn't exist";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||
lib.second = std::move(dlInterface);
|
||||
}
|
||||
|
||||
auto& libInterface = lib.second;
|
||||
std::shared_ptr<IEffect> effectSp;
|
||||
RETURN_IF_BINDER_EXCEPTION(libInterface->createEffectFunc(&in_impl_uuid, &effectSp));
|
||||
if (!effectSp) {
|
||||
LOG(ERROR) << __func__ << ": library created null instance without return error!";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
|
||||
}
|
||||
*_aidl_return = effectSp;
|
||||
mEffectUuidMap[std::weak_ptr<IEffect>(effectSp)] = in_impl_uuid;
|
||||
LOG(DEBUG) << __func__ << ": instance " << effectSp.get() << " created successfully";
|
||||
return ndk::ScopedAStatus::ok();
|
||||
} else {
|
||||
LOG(ERROR) << __func__ << ": UUID not supported";
|
||||
LOG(ERROR) << __func__ << ": library doesn't exist";
|
||||
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
@@ -179,4 +172,34 @@ ndk::ScopedAStatus Factory::destroyEffect(const std::shared_ptr<IEffect>& in_han
|
||||
return status;
|
||||
}
|
||||
|
||||
void Factory::openEffectLibrary(const AudioUuid& type, const AudioUuid& impl,
|
||||
const std::optional<AudioUuid>& proxy, const std::string& libName) {
|
||||
std::function<void(void*)> dlClose = [](void* handle) -> void {
|
||||
if (handle && dlclose(handle)) {
|
||||
LOG(ERROR) << "dlclose failed " << dlerror();
|
||||
}
|
||||
};
|
||||
|
||||
auto libHandle =
|
||||
std::unique_ptr<void, decltype(dlClose)>{dlopen(libName.c_str(), RTLD_LAZY), dlClose};
|
||||
if (!libHandle) {
|
||||
LOG(ERROR) << __func__ << ": dlopen failed, err: " << dlerror();
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(DEBUG) << __func__ << " dlopen lib:" << libName << " for uuid:\ntype:" << type.toString()
|
||||
<< "\nimpl:" << impl.toString()
|
||||
<< "\nproxy:" << (proxy.has_value() ? proxy.value().toString() : "null")
|
||||
<< "\nhandle:" << libHandle;
|
||||
mEffectLibMap.insert({impl, std::make_pair(std::move(libHandle), nullptr)});
|
||||
|
||||
Descriptor::Identity id;
|
||||
id.type = type;
|
||||
id.uuid = impl;
|
||||
if (proxy.has_value()) {
|
||||
id.proxy = proxy.value();
|
||||
}
|
||||
mIdentityList.push_back(id);
|
||||
}
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
|
||||
256
audio/aidl/default/EffectImpl.cpp
Normal file
256
audio/aidl/default/EffectImpl.cpp
Normal file
@@ -0,0 +1,256 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#define LOG_TAG "AHAL_EffectImpl"
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
#include "effect-impl/EffectTypes.h"
|
||||
#include "include/effect-impl/EffectTypes.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
ndk::ScopedAStatus EffectImpl::open(const Parameter::Common& common,
|
||||
const std::optional<Parameter::Specific>& specific,
|
||||
OpenEffectReturn* ret) {
|
||||
LOG(DEBUG) << __func__;
|
||||
{
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_OK_IF(mState != State::INIT);
|
||||
mContext = createContext(common);
|
||||
RETURN_IF(!mContext, EX_ILLEGAL_ARGUMENT, "createContextFailed");
|
||||
setContext(mContext);
|
||||
}
|
||||
|
||||
RETURN_IF_ASTATUS_NOT_OK(setParameterCommon(common), "setCommParamErr");
|
||||
if (specific.has_value()) {
|
||||
RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(specific.value()), "setSpecParamErr");
|
||||
}
|
||||
|
||||
RETURN_IF(createThread(LOG_TAG) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
|
||||
"FailedToCreateWorker");
|
||||
|
||||
{
|
||||
std::lock_guard lg(mMutex);
|
||||
mContext->dupeFmq(ret);
|
||||
mState = State::IDLE;
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EffectImpl::close() {
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_OK_IF(mState == State::INIT);
|
||||
RETURN_IF(mState == State::PROCESSING, EX_ILLEGAL_STATE, "closeAtProcessing");
|
||||
|
||||
// stop the worker thread, ignore the return code
|
||||
RETURN_IF(destroyThread() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
|
||||
"FailedToDestroyWorker");
|
||||
RETURN_IF(releaseContext() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
|
||||
"FailedToCreateWorker");
|
||||
mState = State::INIT;
|
||||
LOG(DEBUG) << __func__;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EffectImpl::setParameter(const Parameter& param) {
|
||||
LOG(DEBUG) << __func__ << " with: " << param.toString();
|
||||
|
||||
auto tag = param.getTag();
|
||||
switch (tag) {
|
||||
case Parameter::common:
|
||||
case Parameter::deviceDescription:
|
||||
case Parameter::mode:
|
||||
case Parameter::source:
|
||||
FALLTHROUGH_INTENDED;
|
||||
case Parameter::volumeStereo:
|
||||
return setParameterCommon(param);
|
||||
case Parameter::specific: {
|
||||
return setParameterSpecific(param.get<Parameter::specific>());
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"ParameterNotSupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EffectImpl::getParameter(const Parameter::Id& id, Parameter* param) {
|
||||
LOG(DEBUG) << __func__ << id.toString();
|
||||
auto tag = id.getTag();
|
||||
switch (tag) {
|
||||
case Parameter::Id::commonTag: {
|
||||
RETURN_IF_ASTATUS_NOT_OK(getParameterCommon(id.get<Parameter::Id::commonTag>(), param),
|
||||
"CommonParamNotSupported");
|
||||
break;
|
||||
}
|
||||
case Parameter::Id::vendorEffectTag: {
|
||||
LOG(DEBUG) << __func__ << " noop for vendor tag";
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"vendortagNotSupported");
|
||||
}
|
||||
default: {
|
||||
Parameter::Specific specific;
|
||||
RETURN_IF_ASTATUS_NOT_OK(getParameterSpecific(id, &specific), "SpecParamNotSupported");
|
||||
param->set<Parameter::specific>(specific);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LOG(DEBUG) << __func__ << param->toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EffectImpl::setParameterCommon(const Parameter& param) {
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
auto tag = param.getTag();
|
||||
switch (tag) {
|
||||
case Parameter::common:
|
||||
RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setCommFailed");
|
||||
break;
|
||||
case Parameter::deviceDescription:
|
||||
RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
|
||||
break;
|
||||
case Parameter::mode:
|
||||
RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setModeFailed");
|
||||
break;
|
||||
case Parameter::source:
|
||||
RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setSourceFailed");
|
||||
break;
|
||||
case Parameter::volumeStereo:
|
||||
RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed");
|
||||
break;
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"commonParamNotSupported");
|
||||
}
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EffectImpl::getParameterCommon(const Parameter::Tag& tag, Parameter* param) {
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
switch (tag) {
|
||||
case Parameter::common: {
|
||||
param->set<Parameter::common>(mContext->getCommon());
|
||||
break;
|
||||
}
|
||||
case Parameter::deviceDescription: {
|
||||
param->set<Parameter::deviceDescription>(mContext->getOutputDevice());
|
||||
break;
|
||||
}
|
||||
case Parameter::mode: {
|
||||
param->set<Parameter::mode>(mContext->getAudioMode());
|
||||
break;
|
||||
}
|
||||
case Parameter::source: {
|
||||
param->set<Parameter::source>(mContext->getAudioSource());
|
||||
break;
|
||||
}
|
||||
case Parameter::volumeStereo: {
|
||||
param->set<Parameter::volumeStereo>(mContext->getVolumeStereo());
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
LOG(DEBUG) << __func__ << " unsupported tag " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"tagNotSupported");
|
||||
}
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EffectImpl::getState(State* state) {
|
||||
std::lock_guard lg(mMutex);
|
||||
*state = mState;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EffectImpl::command(CommandId command) {
|
||||
std::lock_guard lg(mMutex);
|
||||
LOG(DEBUG) << __func__ << ": receive command: " << toString(command) << " at state "
|
||||
<< toString(mState);
|
||||
RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "CommandStateError");
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
switch (command) {
|
||||
case CommandId::START:
|
||||
RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "instanceNotOpen");
|
||||
RETURN_OK_IF(mState == State::PROCESSING);
|
||||
RETURN_IF_ASTATUS_NOT_OK(commandStart(), "commandStartFailed");
|
||||
mState = State::PROCESSING;
|
||||
startThread();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
case CommandId::STOP:
|
||||
RETURN_OK_IF(mState == State::IDLE);
|
||||
mState = State::IDLE;
|
||||
RETURN_IF_ASTATUS_NOT_OK(commandStop(), "commandStopFailed");
|
||||
stopThread();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
case CommandId::RESET:
|
||||
RETURN_OK_IF(mState == State::IDLE);
|
||||
mState = State::IDLE;
|
||||
RETURN_IF_ASTATUS_NOT_OK(commandStop(), "commandStopFailed");
|
||||
stopThread();
|
||||
mContext->resetBuffer();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " instance still processing";
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"CommandIdNotSupported");
|
||||
}
|
||||
LOG(DEBUG) << __func__ << " transfer to state: " << toString(mState);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
void EffectImpl::cleanUp() {
|
||||
command(CommandId::STOP);
|
||||
close();
|
||||
}
|
||||
|
||||
IEffect::Status EffectImpl::status(binder_status_t status, size_t consumed, size_t produced) {
|
||||
IEffect::Status ret;
|
||||
ret.status = status;
|
||||
ret.fmqConsumed = consumed;
|
||||
ret.fmqProduced = produced;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// A placeholder processing implementation to copy samples from input to output
|
||||
IEffect::Status EffectImpl::effectProcessImpl(float* in, float* out, int processSamples) {
|
||||
// lock before access context/parameters
|
||||
std::lock_guard lg(mMutex);
|
||||
IEffect::Status status = {EX_NULL_POINTER, 0, 0};
|
||||
RETURN_VALUE_IF(!mContext, status, "nullContext");
|
||||
auto frameSize = mContext->getInputFrameSize();
|
||||
RETURN_VALUE_IF(0 == frameSize, status, "frameSizeIs0");
|
||||
LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << processSamples
|
||||
<< " frames " << processSamples * sizeof(float) / frameSize;
|
||||
for (int i = 0; i < processSamples; i++) {
|
||||
*out++ = *in++;
|
||||
}
|
||||
LOG(DEBUG) << __func__ << " done processing " << processSamples << " samples";
|
||||
return {STATUS_OK, processSamples, processSamples};
|
||||
}
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
40
audio/aidl/default/bassboost/Android.bp
Normal file
40
audio/aidl/default/bassboost/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: "libbassboostsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
"latest_android_media_audio_common_types_ndk_shared",
|
||||
"latest_android_hardware_audio_effect_ndk_shared",
|
||||
],
|
||||
srcs: [
|
||||
"BassBoostSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
118
audio/aidl/default/bassboost/BassBoostSw.cpp
Normal file
118
audio/aidl/default/bassboost/BassBoostSw.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_BassBoostSw"
|
||||
#include <Utils.h>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#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::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) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<BassBoostSw>();
|
||||
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 BassBoostSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus BassBoostSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::bassBoost != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
mSpecificParam = specific.get<Parameter::Specific::bassBoost>();
|
||||
LOG(DEBUG) << __func__ << " success with: " << specific.toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus BassBoostSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::bassBoostTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
specific->set<Parameter::Specific::bassBoost>(mSpecificParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> BassBoostSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
return mContext;
|
||||
}
|
||||
mContext = std::make_shared<BassBoostSwContext>(1 /* statusFmqDepth */, common);
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode BassBoostSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status BassBoostSw::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
|
||||
72
audio/aidl/default/bassboost/BassBoostSw.h
Normal file
72
audio/aidl/default/bassboost/BassBoostSw.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 BassBoostSwContext : public EffectContext {
|
||||
public:
|
||||
BassBoostSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
// TODO: add specific context here
|
||||
};
|
||||
|
||||
class BassBoostSw : public EffectImpl {
|
||||
public:
|
||||
BassBoostSw() { LOG(DEBUG) << __func__; }
|
||||
~BassBoostSw() {
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
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<BassBoostSwContext> mContext;
|
||||
/* capabilities */
|
||||
const BassBoost::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = BassBoostTypeUUID,
|
||||
.uuid = BassBoostSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "BassBoostSw"},
|
||||
.capability = Capability::make<Capability::bassBoost>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
BassBoost mSpecificParam;
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
40
audio/aidl/default/dynamicProcessing/Android.bp
Normal file
40
audio/aidl/default/dynamicProcessing/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: "libdynamicsprocessingsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
"latest_android_media_audio_common_types_ndk_shared",
|
||||
"latest_android_hardware_audio_effect_ndk_shared",
|
||||
],
|
||||
srcs: [
|
||||
"DynamicsProcessingSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
119
audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
Normal file
119
audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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_DynamicsProcessingSw"
|
||||
#include <Utils.h>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#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::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) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<DynamicsProcessingSw>();
|
||||
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 DynamicsProcessingSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus DynamicsProcessingSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
mSpecificParam = specific.get<Parameter::Specific::dynamicsProcessing>();
|
||||
LOG(DEBUG) << __func__ << " success with: " << specific.toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus DynamicsProcessingSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::dynamicsProcessingTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
specific->set<Parameter::Specific::dynamicsProcessing>(mSpecificParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> DynamicsProcessingSw::createContext(
|
||||
const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
return mContext;
|
||||
}
|
||||
mContext = std::make_shared<DynamicsProcessingSwContext>(1 /* statusFmqDepth */, common);
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode DynamicsProcessingSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status DynamicsProcessingSw::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
|
||||
72
audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
Normal file
72
audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 DynamicsProcessingSwContext : public EffectContext {
|
||||
public:
|
||||
DynamicsProcessingSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
// TODO: add specific context here
|
||||
};
|
||||
|
||||
class DynamicsProcessingSw : public EffectImpl {
|
||||
public:
|
||||
DynamicsProcessingSw() { LOG(DEBUG) << __func__; }
|
||||
~DynamicsProcessingSw() {
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
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<DynamicsProcessingSwContext> mContext;
|
||||
/* capabilities */
|
||||
const DynamicsProcessing::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = DynamicsProcessingTypeUUID,
|
||||
.uuid = DynamicsProcessingSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "DynamicsProcessingSw"},
|
||||
.capability = Capability::make<Capability::dynamicsProcessing>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
DynamicsProcessing mSpecificParam;
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -24,15 +24,9 @@ package {
|
||||
}
|
||||
|
||||
cc_library_shared {
|
||||
name: "libequalizer",
|
||||
vendor: true,
|
||||
shared_libs: [
|
||||
"libaudioaidlcommon",
|
||||
"libbase",
|
||||
"android.hardware.common-V2-ndk",
|
||||
],
|
||||
name: "libequalizersw",
|
||||
defaults: [
|
||||
"aidlaudioservice_defaults",
|
||||
"aidlaudioeffectservice_defaults",
|
||||
"latest_android_media_audio_common_types_ndk_shared",
|
||||
"latest_android_hardware_audio_effect_ndk_shared",
|
||||
],
|
||||
@@ -40,12 +34,6 @@ cc_library_shared {
|
||||
"Equalizer.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
cflags: [
|
||||
"-Wall",
|
||||
"-Wextra",
|
||||
"-Werror",
|
||||
"-Wthread-safety",
|
||||
],
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#define LOG_TAG "AHAL_EqualizerSw"
|
||||
#include <Utils.h>
|
||||
#include <algorithm>
|
||||
@@ -24,11 +25,18 @@
|
||||
|
||||
#include "equalizer-impl/EqualizerSw.h"
|
||||
|
||||
using android::hardware::audio::common::getFrameSizeInBytes;
|
||||
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::State;
|
||||
using aidl::android::media::audio::common::AudioUuid;
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
extern "C" binder_exception_t createEffect(std::shared_ptr<IEffect>* instanceSpp) {
|
||||
extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
|
||||
std::shared_ptr<IEffect>* instanceSpp) {
|
||||
if (!in_impl_uuid || *in_impl_uuid != EqualizerSwImplUUID) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<EqualizerSw>();
|
||||
LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
|
||||
@@ -51,212 +59,39 @@ extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& inst
|
||||
return EX_NONE;
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::open(const Parameter::Common& common,
|
||||
const Parameter::Specific& specific,
|
||||
OpenEffectReturn* _aidl_return) {
|
||||
LOG(DEBUG) << __func__;
|
||||
if (mState != State::INIT) {
|
||||
LOG(WARNING) << __func__ << " eq already open";
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
// Set essential parameters before create worker thread.
|
||||
setCommonParameter(common);
|
||||
setSpecificParameter(specific);
|
||||
|
||||
LOG(DEBUG) << " common: " << common.toString() << " specific " << specific.toString();
|
||||
|
||||
auto& input = common.input;
|
||||
auto& output = common.output;
|
||||
size_t inputFrameSize = getFrameSizeInBytes(input.base.format, input.base.channelMask);
|
||||
size_t outputFrameSize = getFrameSizeInBytes(output.base.format, output.base.channelMask);
|
||||
mContext = std::make_shared<EqualizerSwContext>(1, input.frameCount * inputFrameSize,
|
||||
output.frameCount * outputFrameSize);
|
||||
if (!mContext) {
|
||||
LOG(ERROR) << __func__ << " created EqualizerSwContext failed";
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION,
|
||||
"FailedToCreateFmq");
|
||||
}
|
||||
setContext(mContext);
|
||||
|
||||
// create the worker thread
|
||||
if (RetCode::SUCCESS != createThread(LOG_TAG)) {
|
||||
LOG(ERROR) << __func__ << " created worker thread failed";
|
||||
mContext.reset();
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_UNSUPPORTED_OPERATION,
|
||||
"FailedToCreateWorker");
|
||||
}
|
||||
|
||||
_aidl_return->statusMQ = mContext->getStatusFmq()->dupeDesc();
|
||||
_aidl_return->inputDataMQ = mContext->getInputDataFmq()->dupeDesc();
|
||||
_aidl_return->outputDataMQ = mContext->getOutputDataFmq()->dupeDesc();
|
||||
mState = State::IDLE;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::close() {
|
||||
if (mState == State::INIT) {
|
||||
LOG(WARNING) << __func__ << " instance already closed";
|
||||
return ndk::ScopedAStatus::ok();
|
||||
} else if (mState == State::PROCESSING) {
|
||||
LOG(ERROR) << __func__ << " instance still processing";
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
|
||||
"EqInstanceProcessing");
|
||||
}
|
||||
|
||||
// stop the worker thread
|
||||
mState = State::INIT;
|
||||
destroyThread();
|
||||
mContext.reset();
|
||||
|
||||
LOG(DEBUG) << __func__;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << mDesc.toString();
|
||||
*_aidl_return = mDesc;
|
||||
LOG(DEBUG) << __func__ << kDesc.toString();
|
||||
*_aidl_return = kDesc;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::command(CommandId in_commandId) {
|
||||
LOG(DEBUG) << __func__ << ": receive command:" << toString(in_commandId);
|
||||
if (mState == State::INIT) {
|
||||
LOG(ERROR) << __func__ << ": instance not open yet";
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE,
|
||||
"CommandStateError");
|
||||
}
|
||||
switch (in_commandId) {
|
||||
case CommandId::START:
|
||||
// start processing.
|
||||
mState = State::PROCESSING;
|
||||
startThread();
|
||||
LOG(DEBUG) << __func__ << " state: " << toString(mState);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
case CommandId::STOP:
|
||||
// stop processing.
|
||||
mState = State::IDLE;
|
||||
stopThread();
|
||||
LOG(DEBUG) << __func__ << " state: " << toString(mState);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
case CommandId::RESET:
|
||||
// TODO: reset buffer status.
|
||||
mState = State::IDLE;
|
||||
stopThread();
|
||||
LOG(DEBUG) << __func__ << " state: " << toString(mState);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
default:
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"CommandIdNotSupported");
|
||||
}
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::setParameter(const Parameter& in_param) {
|
||||
if (mState == State::INIT) {
|
||||
LOG(ERROR) << __func__ << ": instance not open yet";
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_STATE, "StateError");
|
||||
}
|
||||
LOG(DEBUG) << __func__ << " with: " << in_param.toString();
|
||||
auto tag = in_param.getTag();
|
||||
switch (tag) {
|
||||
case Parameter::common: {
|
||||
return setCommonParameter(in_param.get<Parameter::common>());
|
||||
}
|
||||
case Parameter::specific: {
|
||||
return setSpecificParameter(in_param.get<Parameter::specific>());
|
||||
}
|
||||
default:
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"ParameterNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::getParameter(const Parameter::Id& in_paramId,
|
||||
Parameter* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << in_paramId.toString();
|
||||
auto tag = in_paramId.getTag();
|
||||
switch (tag) {
|
||||
case Parameter::Id::commonTag: {
|
||||
_aidl_return->set<Parameter::common>(mCommonParam);
|
||||
LOG(DEBUG) << __func__ << " get: " << _aidl_return->toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case Parameter::Id::specificId: {
|
||||
auto& id = in_paramId.get<Parameter::Id::specificId>();
|
||||
Parameter::Specific specific;
|
||||
ndk::ScopedAStatus status = getSpecificParameter(id, &specific);
|
||||
if (!status.isOk()) {
|
||||
LOG(ERROR) << __func__
|
||||
<< " getSpecificParameter error: " << status.getDescription();
|
||||
return status;
|
||||
}
|
||||
_aidl_return->set<Parameter::specific>(specific);
|
||||
LOG(DEBUG) << __func__ << _aidl_return->toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case Parameter::Id::vendorTag: {
|
||||
LOG(DEBUG) << __func__ << " noop for vendor tag now";
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
}
|
||||
LOG(ERROR) << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"Parameter:IdNotSupported");
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::getState(State* _aidl_return) {
|
||||
*_aidl_return = mState;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
/// Private methods.
|
||||
ndk::ScopedAStatus EqualizerSw::setCommonParameter(const Parameter::Common& common) {
|
||||
mCommonParam = common;
|
||||
LOG(DEBUG) << __func__ << " set: " << mCommonParam.toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::setSpecificParameter(const Parameter::Specific& specific) {
|
||||
if (Parameter::Specific::equalizer != specific.getTag()) {
|
||||
LOG(ERROR) << " unsupported effect: " << specific.toString();
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
}
|
||||
ndk::ScopedAStatus EqualizerSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::equalizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
auto& eqParam = specific.get<Parameter::Specific::equalizer>();
|
||||
auto tag = eqParam.getTag();
|
||||
switch (tag) {
|
||||
case Equalizer::bandLevels: {
|
||||
auto& bandLevels = eqParam.get<Equalizer::bandLevels>();
|
||||
const auto& [minItem, maxItem] = std::minmax_element(
|
||||
bandLevels.begin(), bandLevels.end(),
|
||||
[](const auto& a, const auto& b) { return a.index < b.index; });
|
||||
if (bandLevels.size() >= NUM_OF_BANDS || minItem->index < 0 ||
|
||||
maxItem->index >= NUM_OF_BANDS) {
|
||||
LOG(ERROR) << " bandLevels " << bandLevels.size() << "minIndex " << minItem->index
|
||||
<< "maxIndex " << maxItem->index << " illegal ";
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"ExceedMaxBandNum");
|
||||
}
|
||||
mBandLevels = bandLevels;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case Equalizer::preset: {
|
||||
int preset = eqParam.get<Equalizer::preset>();
|
||||
if (preset < 0 || preset >= NUM_OF_PRESETS) {
|
||||
LOG(ERROR) << " preset: " << preset << " invalid";
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"ExceedMaxBandNum");
|
||||
}
|
||||
mPreset = preset;
|
||||
LOG(DEBUG) << __func__ << " preset set to " << mPreset;
|
||||
RETURN_IF(mContext->setEqPreset(eqParam.get<Equalizer::preset>()) != RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
case Equalizer::vendor: {
|
||||
LOG(DEBUG) << __func__ << " noop for vendor tag now";
|
||||
case Equalizer::bandLevels: {
|
||||
RETURN_IF(mContext->setEqBandLevels(eqParam.get<Equalizer::bandLevels>()) !=
|
||||
RetCode::SUCCESS,
|
||||
EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"EqTagNotSupported");
|
||||
}
|
||||
}
|
||||
|
||||
LOG(ERROR) << __func__ << " unsupported eq param tag: " << toString(tag);
|
||||
@@ -264,59 +99,72 @@ ndk::ScopedAStatus EqualizerSw::setSpecificParameter(const Parameter::Specific&
|
||||
"ParamNotSupported");
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::getSpecificParameter(Parameter::Specific::Id id,
|
||||
ndk::ScopedAStatus EqualizerSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
Equalizer eqParam;
|
||||
auto tag = id.getTag();
|
||||
if (tag != Parameter::Specific::Id::equalizerTag) {
|
||||
LOG(ERROR) << " invalid tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"UnsupportedTag");
|
||||
RETURN_IF(Parameter::Id::equalizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
auto eqId = id.get<Parameter::Id::equalizerTag>();
|
||||
auto eqIdTag = eqId.getTag();
|
||||
switch (eqIdTag) {
|
||||
case Equalizer::Id::commonTag:
|
||||
return getParameterEqualizer(eqId.get<Equalizer::Id::commonTag>(), specific);
|
||||
default:
|
||||
LOG(ERROR) << __func__ << " tag " << toString(eqIdTag) << " not supported";
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"EqualizerTagNotSupported");
|
||||
}
|
||||
auto eqTag = id.get<Parameter::Specific::Id::equalizerTag>();
|
||||
switch (eqTag) {
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus EqualizerSw::getParameterEqualizer(const Equalizer::Tag& tag,
|
||||
Parameter::Specific* specific) {
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
Equalizer eqParam;
|
||||
switch (tag) {
|
||||
case Equalizer::bandLevels: {
|
||||
eqParam.set<Equalizer::bandLevels>(mBandLevels);
|
||||
specific->set<Parameter::Specific::equalizer>(eqParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
eqParam.set<Equalizer::bandLevels>(mContext->getEqBandLevels());
|
||||
break;
|
||||
}
|
||||
case Equalizer::preset: {
|
||||
eqParam.set<Equalizer::preset>(mPreset);
|
||||
LOG(DEBUG) << __func__ << " preset " << mPreset;
|
||||
specific->set<Parameter::Specific::equalizer>(eqParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
eqParam.set<Equalizer::preset>(mContext->getEqPreset());
|
||||
break;
|
||||
}
|
||||
case Equalizer::vendor: {
|
||||
LOG(DEBUG) << __func__ << " noop for vendor tag now";
|
||||
return ndk::ScopedAStatus::ok();
|
||||
default: {
|
||||
LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"unsupportedTag");
|
||||
}
|
||||
}
|
||||
LOG(ERROR) << __func__ << " unsupported eq param: " << toString(eqTag);
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
|
||||
"ParamNotSupported");
|
||||
|
||||
specific->set<Parameter::Specific::equalizer>(eqParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
void EqualizerSw::cleanUp() {
|
||||
if (State::PROCESSING == mState) {
|
||||
command(CommandId::STOP);
|
||||
}
|
||||
if (State::INIT != mState) {
|
||||
close();
|
||||
std::shared_ptr<EffectContext> EqualizerSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
return mContext;
|
||||
}
|
||||
mContext = std::make_shared<EqualizerSwContext>(1 /* statusFmqDepth */, common);
|
||||
return mContext;
|
||||
}
|
||||
|
||||
IEffect::Status EqualizerSw::status(binder_status_t status, size_t consumed, size_t produced) {
|
||||
IEffect::Status ret;
|
||||
ret.status = status;
|
||||
ret.fmqByteConsumed = consumed;
|
||||
ret.fmqByteProduced = produced;
|
||||
return ret;
|
||||
RetCode EqualizerSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status EqualizerSw::effectProcessImpl() {
|
||||
IEffect::Status EqualizerSw::effectProcessImpl(float* in, float* out, int process) {
|
||||
// TODO: get data buffer and process.
|
||||
return status(STATUS_OK, mContext->availableToRead(), mContext->availableToWrite());
|
||||
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
|
||||
|
||||
40
audio/aidl/default/hapticGenerator/Android.bp
Normal file
40
audio/aidl/default/hapticGenerator/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: "libhapticgeneratorsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
"latest_android_media_audio_common_types_ndk_shared",
|
||||
"latest_android_hardware_audio_effect_ndk_shared",
|
||||
],
|
||||
srcs: [
|
||||
"HapticGeneratorSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
118
audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
Normal file
118
audio/aidl/default/hapticGenerator/HapticGeneratorSw.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_HapticGeneratorSw"
|
||||
#include <Utils.h>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#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::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) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<HapticGeneratorSw>();
|
||||
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 HapticGeneratorSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus HapticGeneratorSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::hapticGenerator != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
mSpecificParam = specific.get<Parameter::Specific::hapticGenerator>();
|
||||
LOG(DEBUG) << __func__ << " success with: " << specific.toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus HapticGeneratorSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::hapticGeneratorTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
specific->set<Parameter::Specific::hapticGenerator>(mSpecificParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> HapticGeneratorSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
return mContext;
|
||||
}
|
||||
mContext = std::make_shared<HapticGeneratorSwContext>(1 /* statusFmqDepth */, common);
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode HapticGeneratorSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status HapticGeneratorSw::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
|
||||
72
audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
Normal file
72
audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 HapticGeneratorSwContext : public EffectContext {
|
||||
public:
|
||||
HapticGeneratorSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
// TODO: add specific context here
|
||||
};
|
||||
|
||||
class HapticGeneratorSw : public EffectImpl {
|
||||
public:
|
||||
HapticGeneratorSw() { LOG(DEBUG) << __func__; }
|
||||
~HapticGeneratorSw() {
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
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<HapticGeneratorSwContext> mContext;
|
||||
/* capabilities */
|
||||
const HapticGenerator::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = HapticGeneratorTypeUUID,
|
||||
.uuid = HapticGeneratorSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "HapticGeneratorSw"},
|
||||
.capability = Capability::make<Capability::hapticGenerator>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
HapticGenerator mSpecificParam;
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -15,6 +15,10 @@
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <Utils.h>
|
||||
#include <android-base/logging.h>
|
||||
#include <utils/Log.h>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
@@ -22,6 +26,7 @@
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
#include "EffectTypes.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
@@ -31,35 +36,122 @@ class EffectContext {
|
||||
IEffect::Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
|
||||
StatusMQ;
|
||||
typedef ::android::AidlMessageQueue<
|
||||
int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
|
||||
float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
|
||||
DataMQ;
|
||||
|
||||
EffectContext(size_t statusDepth, size_t inBufferSize, size_t outBufferSize) {
|
||||
EffectContext(size_t statusDepth, const Parameter::Common& common) {
|
||||
mSessionId = common.session;
|
||||
auto& input = common.input;
|
||||
auto& output = common.output;
|
||||
|
||||
LOG_ALWAYS_FATAL_IF(
|
||||
input.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT,
|
||||
"inputFormatNotFloat");
|
||||
LOG_ALWAYS_FATAL_IF(output.base.format.pcm !=
|
||||
aidl::android::media::audio::common::PcmType::FLOAT_32_BIT,
|
||||
"outputFormatNotFloat");
|
||||
mInputFrameSize = ::android::hardware::audio::common::getFrameSizeInBytes(
|
||||
input.base.format, input.base.channelMask);
|
||||
mOutputFrameSize = ::android::hardware::audio::common::getFrameSizeInBytes(
|
||||
output.base.format, output.base.channelMask);
|
||||
// in/outBuffer size in float (FMQ data format defined for DataMQ)
|
||||
size_t inBufferSizeInFloat = input.frameCount * mInputFrameSize / sizeof(float);
|
||||
size_t outBufferSizeInFloat = output.frameCount * mOutputFrameSize / sizeof(float);
|
||||
|
||||
mStatusMQ = std::make_shared<StatusMQ>(statusDepth, true /*configureEventFlagWord*/);
|
||||
mInputMQ = std::make_shared<DataMQ>(inBufferSize);
|
||||
mOutputMQ = std::make_shared<DataMQ>(outBufferSize);
|
||||
mInputMQ = std::make_shared<DataMQ>(inBufferSizeInFloat);
|
||||
mOutputMQ = std::make_shared<DataMQ>(outBufferSizeInFloat);
|
||||
|
||||
if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) {
|
||||
LOG(ERROR) << __func__ << " created invalid FMQ";
|
||||
}
|
||||
mWorkBuffer.reserve(std::max(inBufferSize, outBufferSize));
|
||||
};
|
||||
mWorkBuffer.reserve(std::max(inBufferSizeInFloat, outBufferSizeInFloat));
|
||||
}
|
||||
virtual ~EffectContext() {}
|
||||
|
||||
std::shared_ptr<StatusMQ> getStatusFmq() { return mStatusMQ; };
|
||||
std::shared_ptr<DataMQ> getInputDataFmq() { return mInputMQ; };
|
||||
std::shared_ptr<DataMQ> getOutputDataFmq() { return mOutputMQ; };
|
||||
std::shared_ptr<StatusMQ> getStatusFmq() { return mStatusMQ; }
|
||||
std::shared_ptr<DataMQ> getInputDataFmq() { return mInputMQ; }
|
||||
std::shared_ptr<DataMQ> getOutputDataFmq() { return mOutputMQ; }
|
||||
|
||||
int8_t* getWorkBuffer() { return static_cast<int8_t*>(mWorkBuffer.data()); };
|
||||
float* getWorkBuffer() { return static_cast<float*>(mWorkBuffer.data()); }
|
||||
// TODO: update with actual available size
|
||||
size_t availableToRead() { return mWorkBuffer.capacity(); };
|
||||
size_t availableToWrite() { return mWorkBuffer.capacity(); };
|
||||
size_t availableToRead() { return mWorkBuffer.capacity(); }
|
||||
size_t availableToWrite() { return mWorkBuffer.capacity(); }
|
||||
|
||||
// reset buffer status by abandon all data and status in FMQ
|
||||
void resetBuffer() {
|
||||
auto buffer = getWorkBuffer();
|
||||
std::vector<IEffect::Status> status(mStatusMQ->availableToRead());
|
||||
mInputMQ->read(buffer, mInputMQ->availableToRead());
|
||||
mOutputMQ->read(buffer, mOutputMQ->availableToRead());
|
||||
mStatusMQ->read(status.data(), mStatusMQ->availableToRead());
|
||||
}
|
||||
|
||||
void dupeFmq(IEffect::OpenEffectReturn* effectRet) {
|
||||
if (effectRet) {
|
||||
effectRet->statusMQ = getStatusFmq()->dupeDesc();
|
||||
effectRet->inputDataMQ = getInputDataFmq()->dupeDesc();
|
||||
effectRet->outputDataMQ = getOutputDataFmq()->dupeDesc();
|
||||
}
|
||||
}
|
||||
size_t getInputFrameSize() { return mInputFrameSize; }
|
||||
size_t getOutputFrameSize() { return mOutputFrameSize; }
|
||||
int getSessionId() { return mSessionId; }
|
||||
|
||||
virtual RetCode setOutputDevice(
|
||||
const aidl::android::media::audio::common::AudioDeviceDescription& device) {
|
||||
mOutputDevice = device;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
virtual aidl::android::media::audio::common::AudioDeviceDescription getOutputDevice() {
|
||||
return mOutputDevice;
|
||||
}
|
||||
|
||||
virtual RetCode setAudioMode(const aidl::android::media::audio::common::AudioMode& mode) {
|
||||
mMode = mode;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
virtual aidl::android::media::audio::common::AudioMode getAudioMode() { return mMode; }
|
||||
|
||||
virtual RetCode setAudioSource(const aidl::android::media::audio::common::AudioSource& source) {
|
||||
mSource = source;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
virtual aidl::android::media::audio::common::AudioSource getAudioSource() { return mSource; }
|
||||
|
||||
virtual RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) {
|
||||
mVolumeStereo = volumeStereo;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
virtual Parameter::VolumeStereo getVolumeStereo() { return mVolumeStereo; }
|
||||
|
||||
virtual RetCode setCommon(const Parameter::Common& common) {
|
||||
mCommon = common;
|
||||
LOG(ERROR) << __func__ << mCommon.toString();
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
virtual Parameter::Common getCommon() {
|
||||
LOG(ERROR) << __func__ << mCommon.toString();
|
||||
return mCommon;
|
||||
}
|
||||
|
||||
protected:
|
||||
// common parameters
|
||||
int mSessionId = INVALID_AUDIO_SESSION_ID;
|
||||
size_t mInputFrameSize, mOutputFrameSize;
|
||||
Parameter::Common mCommon;
|
||||
aidl::android::media::audio::common::AudioDeviceDescription mOutputDevice;
|
||||
aidl::android::media::audio::common::AudioMode mMode;
|
||||
aidl::android::media::audio::common::AudioSource mSource;
|
||||
Parameter::VolumeStereo mVolumeStereo;
|
||||
|
||||
private:
|
||||
// fmq and buffers
|
||||
std::shared_ptr<StatusMQ> mStatusMQ;
|
||||
std::shared_ptr<DataMQ> mInputMQ;
|
||||
std::shared_ptr<DataMQ> mOutputMQ;
|
||||
// TODO handle effect process input and output
|
||||
// work buffer set by effect instances, the access and update are in same thread
|
||||
std::vector<int8_t> mWorkBuffer;
|
||||
std::vector<float> mWorkBuffer;
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
|
||||
86
audio/aidl/default/include/effect-impl/EffectImpl.h
Normal file
86
audio/aidl/default/include/effect-impl/EffectImpl.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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 <mutex>
|
||||
|
||||
#include "EffectTypes.h"
|
||||
#include "effect-impl/EffectContext.h"
|
||||
#include "effect-impl/EffectTypes.h"
|
||||
#include "effect-impl/EffectWorker.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class EffectImpl : public BnEffect, public EffectWorker {
|
||||
public:
|
||||
EffectImpl() { LOG(DEBUG) << __func__; }
|
||||
~EffectImpl() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
/**
|
||||
* Each effect implementation CAN override these methods if necessary
|
||||
* If you would like implement IEffect::open completely, override EffectImpl::open(), if you
|
||||
* want to keep most of EffectImpl logic but have a little customize, try override openImpl().
|
||||
* openImpl() will be called at the beginning of EffectImpl::open() without lock protection.
|
||||
*
|
||||
* Same for closeImpl().
|
||||
*/
|
||||
virtual ndk::ScopedAStatus open(const Parameter::Common& common,
|
||||
const std::optional<Parameter::Specific>& specific,
|
||||
OpenEffectReturn* ret) override;
|
||||
virtual ndk::ScopedAStatus close() override;
|
||||
virtual ndk::ScopedAStatus command(CommandId id) override;
|
||||
virtual ndk::ScopedAStatus commandStart() { return ndk::ScopedAStatus::ok(); }
|
||||
virtual ndk::ScopedAStatus commandStop() { return ndk::ScopedAStatus::ok(); }
|
||||
virtual ndk::ScopedAStatus commandReset() { return ndk::ScopedAStatus::ok(); }
|
||||
|
||||
virtual ndk::ScopedAStatus getState(State* state) override;
|
||||
virtual ndk::ScopedAStatus setParameter(const Parameter& param) override;
|
||||
virtual ndk::ScopedAStatus getParameter(const Parameter::Id& id, Parameter* param) override;
|
||||
virtual IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
|
||||
|
||||
virtual ndk::ScopedAStatus setParameterCommon(const Parameter& param);
|
||||
virtual ndk::ScopedAStatus getParameterCommon(const Parameter::Tag& tag, Parameter* param);
|
||||
|
||||
/* Methods MUST be implemented by each effect instances */
|
||||
virtual ndk::ScopedAStatus getDescriptor(Descriptor* desc) = 0;
|
||||
virtual ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) = 0;
|
||||
virtual ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) = 0;
|
||||
virtual std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) = 0;
|
||||
virtual RetCode releaseContext() = 0;
|
||||
|
||||
protected:
|
||||
/*
|
||||
* Lock is required if effectProcessImpl (which is running in an independent thread) needs to
|
||||
* access state and parameters.
|
||||
*/
|
||||
std::mutex mMutex;
|
||||
State mState GUARDED_BY(mMutex) = State::INIT;
|
||||
|
||||
IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
|
||||
|
||||
private:
|
||||
void cleanUp();
|
||||
std::shared_ptr<EffectContext> mContext GUARDED_BY(mMutex);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -18,6 +18,19 @@
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
|
||||
#include <aidl/android/hardware/audio/effect/BnEffect.h>
|
||||
|
||||
typedef binder_exception_t (*EffectCreateFunctor)(
|
||||
const ::aidl::android::media::audio::common::AudioUuid*,
|
||||
std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>*);
|
||||
typedef binder_exception_t (*EffectDestroyFunctor)(
|
||||
const std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>&);
|
||||
|
||||
struct effect_dl_interface_s {
|
||||
EffectCreateFunctor createEffectFunc;
|
||||
EffectDestroyFunctor destroyEffectFunc;
|
||||
};
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
enum class RetCode {
|
||||
@@ -26,9 +39,12 @@ enum class RetCode {
|
||||
ERROR_THREAD, /* Effect thread error */
|
||||
ERROR_NULL_POINTER, /* NULL pointer */
|
||||
ERROR_ALIGNMENT_ERROR, /* Memory alignment error */
|
||||
ERROR_BLOCK_SIZE_EXCEED /* Maximum block size exceeded */
|
||||
ERROR_BLOCK_SIZE_EXCEED, /* Maximum block size exceeded */
|
||||
ERROR_EFFECT_LIB_ERROR
|
||||
};
|
||||
|
||||
static const int INVALID_AUDIO_SESSION_ID = -1;
|
||||
|
||||
inline std::ostream& operator<<(std::ostream& out, const RetCode& code) {
|
||||
switch (code) {
|
||||
case RetCode::SUCCESS:
|
||||
@@ -43,9 +59,46 @@ inline std::ostream& operator<<(std::ostream& out, const RetCode& code) {
|
||||
return out << "ERROR_ALIGNMENT_ERROR";
|
||||
case RetCode::ERROR_BLOCK_SIZE_EXCEED:
|
||||
return out << "ERROR_BLOCK_SIZE_EXCEED";
|
||||
case RetCode::ERROR_EFFECT_LIB_ERROR:
|
||||
return out << "ERROR_EFFECT_LIB_ERROR";
|
||||
}
|
||||
|
||||
return out << "EnumError: " << code;
|
||||
}
|
||||
|
||||
#define RETURN_IF_ASTATUS_NOT_OK(status, message) \
|
||||
do { \
|
||||
const ::ndk::ScopedAStatus curr_status = (status); \
|
||||
if (!curr_status.isOk()) { \
|
||||
LOG(ERROR) << __func__ << ":" << __LINE__ \
|
||||
<< "return with status: " << curr_status.getDescription() << (message); \
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage( \
|
||||
curr_status.getExceptionCode(), (message)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RETURN_IF(expr, exception, message) \
|
||||
do { \
|
||||
if (expr) { \
|
||||
LOG(ERROR) << __func__ << ":" << __LINE__ << " return with expr " << #expr; \
|
||||
return ndk::ScopedAStatus::fromExceptionCodeWithMessage((exception), (message)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RETURN_OK_IF(expr) \
|
||||
do { \
|
||||
if (expr) { \
|
||||
LOG(INFO) << __func__ << ":" << __LINE__ << " return with expr " << #expr; \
|
||||
return ndk::ScopedAStatus::ok(); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define RETURN_VALUE_IF(expr, ret, log) \
|
||||
do { \
|
||||
if (expr) { \
|
||||
LOG(ERROR) << __func__ << ":" << __LINE__ << " return with expr " << #expr << (log); \
|
||||
return ret; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
|
||||
@@ -46,11 +46,124 @@ static const AudioUuid EqualizerSwImplUUID = {static_cast<int32_t>(0x0bed4300),
|
||||
0xbb17,
|
||||
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
|
||||
|
||||
// Visualizer type UUID.
|
||||
static const AudioUuid VisualizerTypeUUID = {static_cast<int32_t>(0x1d4033c0),
|
||||
0x8557,
|
||||
0x11df,
|
||||
0x9f2d,
|
||||
{0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
|
||||
// Equalizer bundle implementation UUID.
|
||||
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}};
|
||||
// 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),
|
||||
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),
|
||||
0x588b,
|
||||
0x11ed,
|
||||
0x9b6a,
|
||||
{0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
|
||||
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
|
||||
@@ -36,34 +36,33 @@ class EffectWorker : public EffectThread {
|
||||
|
||||
// handle FMQ and call effect implemented virtual function
|
||||
void process() override {
|
||||
if (!mContext) {
|
||||
LOG(ERROR) << __func__ << " invalid context!";
|
||||
return;
|
||||
}
|
||||
RETURN_VALUE_IF(!mContext, void(), "nullContext");
|
||||
std::shared_ptr<EffectContext::StatusMQ> statusMQ = mContext->getStatusFmq();
|
||||
std::shared_ptr<EffectContext::DataMQ> inputMQ = mContext->getInputDataFmq();
|
||||
std::shared_ptr<EffectContext::DataMQ> outputMQ = mContext->getOutputDataFmq();
|
||||
|
||||
// Only this worker will read from input data MQ and write to output data MQ.
|
||||
auto readSize = inputMQ->availableToRead(), writeSize = outputMQ->availableToWrite();
|
||||
if (readSize && writeSize) {
|
||||
LOG(DEBUG) << __func__ << " available to read " << readSize << " available to write "
|
||||
<< writeSize;
|
||||
auto readSamples = inputMQ->availableToRead(), writeSamples = outputMQ->availableToWrite();
|
||||
if (readSamples && writeSamples) {
|
||||
auto processSamples = std::min(readSamples, writeSamples);
|
||||
LOG(DEBUG) << __func__ << " available to read " << readSamples << " available to write "
|
||||
<< writeSamples << " process " << processSamples;
|
||||
|
||||
auto buffer = mContext->getWorkBuffer();
|
||||
inputMQ->read(buffer, readSize);
|
||||
IEffect::Status status = effectProcessImpl();
|
||||
writeSize = std::min((int32_t)writeSize, status.fmqByteProduced);
|
||||
outputMQ->write(buffer, writeSize);
|
||||
inputMQ->read(buffer, processSamples);
|
||||
|
||||
IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples);
|
||||
outputMQ->write(buffer, status.fmqProduced);
|
||||
statusMQ->writeBlocking(&status, 1);
|
||||
LOG(DEBUG) << __func__ << " done processing, effect consumed " << status.fmqByteConsumed
|
||||
<< " produced " << status.fmqByteProduced;
|
||||
LOG(DEBUG) << __func__ << " done processing, effect consumed " << status.fmqConsumed
|
||||
<< " produced " << status.fmqProduced;
|
||||
} else {
|
||||
// TODO: maybe add some sleep here to avoid busy waiting
|
||||
}
|
||||
}
|
||||
|
||||
// must implement by each effect implementation
|
||||
virtual IEffect::Status effectProcessImpl() = 0;
|
||||
virtual IEffect::Status effectProcessImpl(float* in, float* out, int processSamples) = 0;
|
||||
|
||||
private:
|
||||
// make sure the context only set once.
|
||||
|
||||
@@ -34,12 +34,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 .
|
||||
* @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;
|
||||
|
||||
/**
|
||||
@@ -79,16 +81,9 @@ class Factory : public BnFactory {
|
||||
// List of effect descriptors supported by the devices.
|
||||
std::vector<Descriptor::Identity> mIdentityList;
|
||||
|
||||
typedef binder_exception_t (*EffectCreateFunctor)(std::shared_ptr<IEffect>*);
|
||||
typedef binder_exception_t (*EffectDestroyFunctor)(const std::shared_ptr<IEffect>&);
|
||||
struct effect_interface_s {
|
||||
EffectCreateFunctor createEffectFunc;
|
||||
EffectDestroyFunctor destroyEffectFunc;
|
||||
};
|
||||
|
||||
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_interface_s>>>
|
||||
std::unique_ptr<struct effect_dl_interface_s>>>
|
||||
mEffectLibMap;
|
||||
std::map<std::weak_ptr<IEffect>, aidl::android::media::audio::common::AudioUuid,
|
||||
std::owner_less<>>
|
||||
@@ -96,5 +91,10 @@ class Factory : public BnFactory {
|
||||
|
||||
ndk::ScopedAStatus destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle);
|
||||
void cleanupEffectMap();
|
||||
void openEffectLibrary(
|
||||
const ::aidl::android::media::audio::common::AudioUuid& type,
|
||||
const ::aidl::android::media::audio::common::AudioUuid& impl,
|
||||
const std::optional<::aidl::android::media::audio::common::AudioUuid>& proxy,
|
||||
const std::string& libName);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
|
||||
@@ -21,85 +21,104 @@
|
||||
#include <cstdlib>
|
||||
#include <memory>
|
||||
|
||||
#include "effect-impl/EffectContext.h"
|
||||
#include "effect-impl/EffectTypes.h"
|
||||
#include "effect-impl/EffectImpl.h"
|
||||
#include "effect-impl/EffectUUID.h"
|
||||
#include "effect-impl/EffectWorker.h"
|
||||
|
||||
namespace aidl::android::hardware::audio::effect {
|
||||
|
||||
class EqualizerSwContext : public EffectContext {
|
||||
public:
|
||||
EqualizerSwContext(int statusDepth, int inBufferSize, int outBufferSize)
|
||||
: EffectContext(statusDepth, inBufferSize, outBufferSize) {
|
||||
EqualizerSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
|
||||
RetCode setEqPreset(const int& presetIdx) {
|
||||
if (presetIdx < 0 || presetIdx >= NUM_OF_PRESETS) {
|
||||
return RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
}
|
||||
mPreset = presetIdx;
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
int getEqPreset() { return mPreset; }
|
||||
|
||||
RetCode setEqBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels) {
|
||||
if (bandLevels.size() > NUM_OF_BANDS) {
|
||||
LOG(ERROR) << __func__ << " return because size exceed " << NUM_OF_BANDS;
|
||||
return RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
}
|
||||
RetCode ret = RetCode::SUCCESS;
|
||||
for (auto& it : bandLevels) {
|
||||
if (it.index >= NUM_OF_BANDS || it.index < 0) {
|
||||
LOG(ERROR) << __func__ << " index illegal, skip: " << it.index << " - "
|
||||
<< it.levelMb;
|
||||
ret = RetCode::ERROR_ILLEGAL_PARAMETER;
|
||||
}
|
||||
mBandLevels[it.index] = it.levelMb;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<Equalizer::BandLevel> getEqBandLevels() {
|
||||
std::vector<Equalizer::BandLevel> bandLevels;
|
||||
for (int i = 0; i < NUM_OF_BANDS; i++) {
|
||||
bandLevels.push_back({i, mBandLevels[i]});
|
||||
}
|
||||
return bandLevels;
|
||||
}
|
||||
|
||||
private:
|
||||
static const int NUM_OF_BANDS = 5;
|
||||
static const int NUM_OF_PRESETS = 10;
|
||||
static const int PRESET_CUSTOM = -1;
|
||||
// preset band level
|
||||
int mPreset = PRESET_CUSTOM;
|
||||
int32_t mBandLevels[NUM_OF_BANDS] = {3, 0, 0, 0, 3};
|
||||
|
||||
// Add equalizer specific context for processing here
|
||||
};
|
||||
|
||||
class EqualizerSw : public BnEffect, EffectWorker {
|
||||
class EqualizerSw : public EffectImpl {
|
||||
public:
|
||||
EqualizerSw() {
|
||||
Equalizer::Capability eqCap = {.bandFrequencies = mBandFrequency, .presets = mPresets};
|
||||
mDesc.capability.set<Capability::equalizer>(eqCap);
|
||||
LOG(DEBUG) << __func__;
|
||||
};
|
||||
EqualizerSw() { LOG(DEBUG) << __func__; }
|
||||
~EqualizerSw() {
|
||||
cleanUp();
|
||||
LOG(DEBUG) << __func__;
|
||||
};
|
||||
ndk::ScopedAStatus open(const Parameter::Common& common, const Parameter::Specific& specific,
|
||||
OpenEffectReturn* _aidl_return) override;
|
||||
ndk::ScopedAStatus close() override;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
|
||||
|
||||
ndk::ScopedAStatus getState(State* _aidl_return) override;
|
||||
ndk::ScopedAStatus command(CommandId in_commandId) override;
|
||||
ndk::ScopedAStatus setParameter(const Parameter& in_param) override;
|
||||
ndk::ScopedAStatus getParameter(const Parameter::Id& in_paramId,
|
||||
Parameter* _aidl_return) override;
|
||||
|
||||
IEffect::Status effectProcessImpl() 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:
|
||||
// Effect descriptor.
|
||||
Descriptor mDesc = {.common = {.id = {.type = EqualizerTypeUUID, .uuid = EqualizerSwImplUUID}}};
|
||||
|
||||
// Parameters.
|
||||
Parameter::Common mCommonParam;
|
||||
Equalizer mEqualizerParam; // TODO: the equalizer parameter needs to update
|
||||
|
||||
// Instance state INIT by default.
|
||||
State mState = State::INIT;
|
||||
|
||||
int mPreset = PRESET_CUSTOM; // the current preset
|
||||
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}};
|
||||
// preset band level
|
||||
std::vector<Equalizer::BandLevel> mBandLevels = {{0, 3}, {1, 0}, {2, 0}, {3, 0}, {4, 3}};
|
||||
// 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"}};
|
||||
static const int NUM_OF_BANDS = 5;
|
||||
static const int NUM_OF_PRESETS = 10;
|
||||
static const int PRESET_CUSTOM = -1;
|
||||
|
||||
// Equalizer worker context
|
||||
std::shared_ptr<EqualizerSwContext> mContext;
|
||||
const Equalizer::Capability kEqCap = {.bandFrequencies = mBandFrequency, .presets = mPresets};
|
||||
// Effect descriptor.
|
||||
const Descriptor kDesc = {.common = {.id = {.type = EqualizerTypeUUID,
|
||||
.uuid = EqualizerSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "EqualizerSw"},
|
||||
.capability = Capability::make<Capability::equalizer>(kEqCap)};
|
||||
|
||||
ndk::ScopedAStatus setCommonParameter(const Parameter::Common& common_param);
|
||||
ndk::ScopedAStatus setSpecificParameter(const Parameter::Specific& specific);
|
||||
ndk::ScopedAStatus getSpecificParameter(Parameter::Specific::Id id,
|
||||
Parameter::Specific* specific);
|
||||
|
||||
void cleanUp();
|
||||
|
||||
IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
|
||||
ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
|
||||
Parameter::Specific* specific);
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
|
||||
40
audio/aidl/default/loudnessEnhancer/Android.bp
Normal file
40
audio/aidl/default/loudnessEnhancer/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: "libloudnessenhancersw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
"latest_android_media_audio_common_types_ndk_shared",
|
||||
"latest_android_hardware_audio_effect_ndk_shared",
|
||||
],
|
||||
srcs: [
|
||||
"LoudnessEnhancerSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
118
audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.cpp
Normal file
118
audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.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_LoudnessEnhancerSw"
|
||||
#include <Utils.h>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include "LoudnessEnhancerSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
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) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<LoudnessEnhancerSw>();
|
||||
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 LoudnessEnhancerSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus LoudnessEnhancerSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::loudnessEnhancer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
mSpecificParam = specific.get<Parameter::Specific::loudnessEnhancer>();
|
||||
LOG(DEBUG) << __func__ << " success with: " << specific.toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus LoudnessEnhancerSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::loudnessEnhancerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
specific->set<Parameter::Specific::loudnessEnhancer>(mSpecificParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> LoudnessEnhancerSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
return mContext;
|
||||
}
|
||||
mContext = std::make_shared<LoudnessEnhancerSwContext>(1 /* statusFmqDepth */, common);
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode LoudnessEnhancerSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status LoudnessEnhancerSw::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
|
||||
72
audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h
Normal file
72
audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 LoudnessEnhancerSwContext : public EffectContext {
|
||||
public:
|
||||
LoudnessEnhancerSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
// TODO: add specific context here
|
||||
};
|
||||
|
||||
class LoudnessEnhancerSw : public EffectImpl {
|
||||
public:
|
||||
LoudnessEnhancerSw() { LOG(DEBUG) << __func__; }
|
||||
~LoudnessEnhancerSw() {
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
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<LoudnessEnhancerSwContext> mContext;
|
||||
/* capabilities */
|
||||
const LoudnessEnhancer::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = LoudnessEnhancerTypeUUID,
|
||||
.uuid = LoudnessEnhancerSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "LoudnessEnhancerSw"},
|
||||
.capability = Capability::make<Capability::loudnessEnhancer>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
LoudnessEnhancer mSpecificParam;
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
40
audio/aidl/default/reverb/Android.bp
Normal file
40
audio/aidl/default/reverb/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: "libreverbsw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
"latest_android_media_audio_common_types_ndk_shared",
|
||||
"latest_android_hardware_audio_effect_ndk_shared",
|
||||
],
|
||||
srcs: [
|
||||
"ReverbSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
118
audio/aidl/default/reverb/ReverbSw.cpp
Normal file
118
audio/aidl/default/reverb/ReverbSw.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_ReverbSw"
|
||||
#include <Utils.h>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include "ReverbSw.h"
|
||||
|
||||
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::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) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<ReverbSw>();
|
||||
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 ReverbSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus ReverbSw::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 ReverbSw::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) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
return mContext;
|
||||
}
|
||||
mContext = std::make_shared<ReverbSwContext>(1 /* statusFmqDepth */, common);
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode ReverbSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status ReverbSw::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
|
||||
72
audio/aidl/default/reverb/ReverbSw.h
Normal file
72
audio/aidl/default/reverb/ReverbSw.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 ReverbSwContext : public EffectContext {
|
||||
public:
|
||||
ReverbSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
// TODO: add specific context here
|
||||
};
|
||||
|
||||
class ReverbSw : public EffectImpl {
|
||||
public:
|
||||
ReverbSw() { LOG(DEBUG) << __func__; }
|
||||
~ReverbSw() {
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
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<ReverbSwContext> mContext;
|
||||
/* capabilities */
|
||||
const Reverb::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = ReverbTypeUUID,
|
||||
.uuid = ReverbSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "ReverbSw"},
|
||||
.capability = Capability::make<Capability::reverb>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
Reverb mSpecificParam;
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
40
audio/aidl/default/virtualizer/Android.bp
Normal file
40
audio/aidl/default/virtualizer/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: "libvirtualizersw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
"latest_android_media_audio_common_types_ndk_shared",
|
||||
"latest_android_hardware_audio_effect_ndk_shared",
|
||||
],
|
||||
srcs: [
|
||||
"VirtualizerSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
118
audio/aidl/default/virtualizer/VirtualizerSw.cpp
Normal file
118
audio/aidl/default/virtualizer/VirtualizerSw.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_VirtualizerSw"
|
||||
#include <Utils.h>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include "VirtualizerSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
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) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<VirtualizerSw>();
|
||||
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 VirtualizerSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VirtualizerSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::virtualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
mSpecificParam = specific.get<Parameter::Specific::virtualizer>();
|
||||
LOG(DEBUG) << __func__ << " success with: " << specific.toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VirtualizerSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::virtualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
specific->set<Parameter::Specific::virtualizer>(mSpecificParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> VirtualizerSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
return mContext;
|
||||
}
|
||||
mContext = std::make_shared<VirtualizerSwContext>(1 /* statusFmqDepth */, common);
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode VirtualizerSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status VirtualizerSw::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
|
||||
72
audio/aidl/default/virtualizer/VirtualizerSw.h
Normal file
72
audio/aidl/default/virtualizer/VirtualizerSw.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 VirtualizerSwContext : public EffectContext {
|
||||
public:
|
||||
VirtualizerSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
// TODO: add specific context here
|
||||
};
|
||||
|
||||
class VirtualizerSw : public EffectImpl {
|
||||
public:
|
||||
VirtualizerSw() { LOG(DEBUG) << __func__; }
|
||||
~VirtualizerSw() {
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
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<VirtualizerSwContext> mContext;
|
||||
/* capabilities */
|
||||
const Virtualizer::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = VirtualizerTypeUUID,
|
||||
.uuid = VirtualizerSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "VirtualizerSw"},
|
||||
.capability = Capability::make<Capability::virtualizer>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
Virtualizer mSpecificParam;
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
40
audio/aidl/default/visualizer/Android.bp
Normal file
40
audio/aidl/default/visualizer/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: "libvisualizersw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
"latest_android_media_audio_common_types_ndk_shared",
|
||||
"latest_android_hardware_audio_effect_ndk_shared",
|
||||
],
|
||||
srcs: [
|
||||
"VisualizerSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
118
audio/aidl/default/visualizer/VisualizerSw.cpp
Normal file
118
audio/aidl/default/visualizer/VisualizerSw.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_VisualizerSw"
|
||||
#include <Utils.h>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include "VisualizerSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
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) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<VisualizerSw>();
|
||||
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 VisualizerSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VisualizerSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
mSpecificParam = specific.get<Parameter::Specific::visualizer>();
|
||||
LOG(DEBUG) << __func__ << " success with: " << specific.toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VisualizerSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
specific->set<Parameter::Specific::visualizer>(mSpecificParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> VisualizerSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
return mContext;
|
||||
}
|
||||
mContext = std::make_shared<VisualizerSwContext>(1 /* statusFmqDepth */, common);
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode VisualizerSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status VisualizerSw::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
|
||||
72
audio/aidl/default/visualizer/VisualizerSw.h
Normal file
72
audio/aidl/default/visualizer/VisualizerSw.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 VisualizerSwContext : public EffectContext {
|
||||
public:
|
||||
VisualizerSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
// TODO: add specific context here
|
||||
};
|
||||
|
||||
class VisualizerSw : public EffectImpl {
|
||||
public:
|
||||
VisualizerSw() { LOG(DEBUG) << __func__; }
|
||||
~VisualizerSw() {
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
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<VisualizerSwContext> mContext;
|
||||
/* capabilities */
|
||||
const Visualizer::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = VisualizerTypeUUID,
|
||||
.uuid = VisualizerSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "VisualizerSw"},
|
||||
.capability = Capability::make<Capability::visualizer>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
Visualizer mSpecificParam;
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
40
audio/aidl/default/volume/Android.bp
Normal file
40
audio/aidl/default/volume/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: "libvolumesw",
|
||||
defaults: [
|
||||
"aidlaudioeffectservice_defaults",
|
||||
"latest_android_media_audio_common_types_ndk_shared",
|
||||
"latest_android_hardware_audio_effect_ndk_shared",
|
||||
],
|
||||
srcs: [
|
||||
"VolumeSw.cpp",
|
||||
":effectCommonFile",
|
||||
],
|
||||
visibility: [
|
||||
"//hardware/interfaces/audio/aidl/default",
|
||||
],
|
||||
}
|
||||
118
audio/aidl/default/volume/VolumeSw.cpp
Normal file
118
audio/aidl/default/volume/VolumeSw.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_VolumeSw"
|
||||
#include <Utils.h>
|
||||
#include <algorithm>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <fmq/AidlMessageQueue.h>
|
||||
|
||||
#include "VolumeSw.h"
|
||||
|
||||
using aidl::android::hardware::audio::effect::IEffect;
|
||||
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) {
|
||||
LOG(ERROR) << __func__ << "uuid not supported";
|
||||
return EX_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
if (instanceSpp) {
|
||||
*instanceSpp = ndk::SharedRefBase::make<VolumeSw>();
|
||||
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 VolumeSw::getDescriptor(Descriptor* _aidl_return) {
|
||||
LOG(DEBUG) << __func__ << kDescriptor.toString();
|
||||
*_aidl_return = kDescriptor;
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VolumeSw::setParameterSpecific(const Parameter::Specific& specific) {
|
||||
RETURN_IF(Parameter::Specific::volume != specific.getTag(), EX_ILLEGAL_ARGUMENT,
|
||||
"EffectNotSupported");
|
||||
std::lock_guard lg(mMutex);
|
||||
RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
|
||||
|
||||
mSpecificParam = specific.get<Parameter::Specific::volume>();
|
||||
LOG(DEBUG) << __func__ << " success with: " << specific.toString();
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
ndk::ScopedAStatus VolumeSw::getParameterSpecific(const Parameter::Id& id,
|
||||
Parameter::Specific* specific) {
|
||||
auto tag = id.getTag();
|
||||
RETURN_IF(Parameter::Id::volumeTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
|
||||
specific->set<Parameter::Specific::volume>(mSpecificParam);
|
||||
return ndk::ScopedAStatus::ok();
|
||||
}
|
||||
|
||||
std::shared_ptr<EffectContext> VolumeSw::createContext(const Parameter::Common& common) {
|
||||
if (mContext) {
|
||||
LOG(DEBUG) << __func__ << " context already exist";
|
||||
return mContext;
|
||||
}
|
||||
mContext = std::make_shared<VolumeSwContext>(1 /* statusFmqDepth */, common);
|
||||
return mContext;
|
||||
}
|
||||
|
||||
RetCode VolumeSw::releaseContext() {
|
||||
if (mContext) {
|
||||
mContext.reset();
|
||||
}
|
||||
return RetCode::SUCCESS;
|
||||
}
|
||||
|
||||
// Processing method running in EffectWorker thread.
|
||||
IEffect::Status VolumeSw::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
|
||||
72
audio/aidl/default/volume/VolumeSw.h
Normal file
72
audio/aidl/default/volume/VolumeSw.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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 VolumeSwContext : public EffectContext {
|
||||
public:
|
||||
VolumeSwContext(int statusDepth, const Parameter::Common& common)
|
||||
: EffectContext(statusDepth, common) {
|
||||
LOG(DEBUG) << __func__;
|
||||
}
|
||||
// TODO: add specific context here
|
||||
};
|
||||
|
||||
class VolumeSw : public EffectImpl {
|
||||
public:
|
||||
VolumeSw() { LOG(DEBUG) << __func__; }
|
||||
~VolumeSw() {
|
||||
LOG(DEBUG) << __func__;
|
||||
releaseContext();
|
||||
}
|
||||
|
||||
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<VolumeSwContext> mContext;
|
||||
/* capabilities */
|
||||
const Volume::Capability kCapability;
|
||||
/* Effect descriptor */
|
||||
const Descriptor kDescriptor = {
|
||||
.common = {.id = {.type = VolumeTypeUUID,
|
||||
.uuid = VolumeSwImplUUID,
|
||||
.proxy = std::nullopt},
|
||||
.flags = {.type = Flags::Type::INSERT,
|
||||
.insert = Flags::Insert::FIRST,
|
||||
.volume = Flags::Volume::CTRL},
|
||||
.name = "VolumeSw"},
|
||||
.capability = Capability::make<Capability::volume>(kCapability)};
|
||||
|
||||
/* parameters */
|
||||
Volume mSpecificParam;
|
||||
};
|
||||
} // namespace aidl::android::hardware::audio::effect
|
||||
@@ -53,9 +53,10 @@ class EffectFactoryHelper {
|
||||
|
||||
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, _aidl_return));
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(in_type, in_instance, in_proxy, _aidl_return));
|
||||
mIds = *_aidl_return;
|
||||
}
|
||||
|
||||
@@ -85,9 +86,10 @@ class EffectFactoryHelper {
|
||||
ASSERT_NE(mEffectFactory, nullptr);
|
||||
|
||||
if (type == EffectNullUuid) {
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, &ids));
|
||||
EXPECT_IS_OK(
|
||||
mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
|
||||
} else {
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(type, std::nullopt, &ids));
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(type, std::nullopt, std::nullopt, &ids));
|
||||
}
|
||||
for (const auto& id : ids) {
|
||||
ASSERT_EQ(id.type, type);
|
||||
@@ -121,7 +123,8 @@ class EffectFactoryHelper {
|
||||
|
||||
void QueryAndCreateAllEffects() {
|
||||
ASSERT_NE(mEffectFactory, nullptr);
|
||||
EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, &mCompleteIds));
|
||||
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));
|
||||
|
||||
@@ -49,7 +49,7 @@ using aidl::android::media::audio::common::AudioUuid;
|
||||
using aidl::android::media::audio::common::PcmType;
|
||||
|
||||
const AudioFormatDescription DefaultFormat = {
|
||||
.type = AudioFormatType::PCM, .pcm = PcmType::INT_16_BIT, .encoding = ""};
|
||||
.type = AudioFormatType::PCM, .pcm = PcmType::FLOAT_32_BIT, .encoding = ""};
|
||||
|
||||
class EffectHelper {
|
||||
public:
|
||||
@@ -59,6 +59,7 @@ class EffectHelper {
|
||||
|
||||
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;
|
||||
@@ -72,6 +73,7 @@ class EffectHelper {
|
||||
|
||||
void CloseEffects(const binder_status_t status = EX_NONE) {
|
||||
auto close = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
ASSERT_NE(effect, nullptr);
|
||||
EXPECT_STATUS(status, effect->close());
|
||||
};
|
||||
|
||||
@@ -97,6 +99,7 @@ class EffectHelper {
|
||||
|
||||
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));
|
||||
@@ -106,6 +109,7 @@ class EffectHelper {
|
||||
|
||||
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));
|
||||
@@ -113,6 +117,7 @@ class EffectHelper {
|
||||
|
||||
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));
|
||||
@@ -120,6 +125,7 @@ class EffectHelper {
|
||||
|
||||
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);
|
||||
@@ -129,6 +135,7 @@ class EffectHelper {
|
||||
|
||||
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));
|
||||
@@ -138,9 +145,10 @@ class EffectHelper {
|
||||
|
||||
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>(0);
|
||||
id.set<Parameter::Id::commonTag>(Parameter::common);
|
||||
paramCommonExpect.set<Parameter::common>(mCommon);
|
||||
EXPECT_IS_OK(effect->getParameter(id, ¶mCommonGet));
|
||||
EXPECT_EQ(paramCommonExpect, paramCommonGet)
|
||||
@@ -151,8 +159,9 @@ class EffectHelper {
|
||||
|
||||
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, _aidl_return);
|
||||
mFactoryHelper.QueryEffects(in_type, in_instance, in_proxy, _aidl_return);
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
@@ -173,7 +182,7 @@ class EffectHelper {
|
||||
}
|
||||
}
|
||||
|
||||
static const size_t mWriteMQSize = 0x400;
|
||||
static const size_t mWriteMQBytes = 0x400;
|
||||
|
||||
enum class IO : char { INPUT = 0, OUTPUT = 1, INOUT = 2 };
|
||||
|
||||
@@ -204,7 +213,7 @@ class EffectHelper {
|
||||
mCommon.output.frameCount = frameCount;
|
||||
}
|
||||
}
|
||||
void initParamCommon(int session = -1, int ioHandle = -1, int iSampleRate = 48000,
|
||||
void initParamCommon(int session = 0, int ioHandle = -1, int iSampleRate = 48000,
|
||||
int oSampleRate = 48000, long iFrameCount = 0x100,
|
||||
long oFrameCount = 0x100) {
|
||||
mCommon.session = session;
|
||||
@@ -215,10 +224,12 @@ class EffectHelper {
|
||||
input.base.sampleRate = iSampleRate;
|
||||
input.base.channelMask = mInputChannelLayout;
|
||||
input.frameCount = iFrameCount;
|
||||
input.base.format = DefaultFormat;
|
||||
output.base.sampleRate = oSampleRate;
|
||||
output.base.channelMask = mOutputChannelLayout;
|
||||
output.base.format = DefaultFormat;
|
||||
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(
|
||||
@@ -228,45 +239,45 @@ class EffectHelper {
|
||||
void setSpecific(Parameter::Specific& specific) { mSpecific = specific; }
|
||||
|
||||
// usually this function only call once.
|
||||
void PrepareInputData(size_t s = mWriteMQSize) {
|
||||
size_t maxInputSize = s;
|
||||
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();
|
||||
const size_t bytesToWrite = mq->availableToWrite() * sizeof(float);
|
||||
EXPECT_EQ(inputFrameSize * mCommon.input.frameCount, bytesToWrite);
|
||||
EXPECT_NE(0UL, bytesToWrite);
|
||||
EXPECT_TRUE(s <= bytesToWrite);
|
||||
maxInputSize = std::max(maxInputSize, bytesToWrite);
|
||||
EXPECT_TRUE(bytes <= bytesToWrite);
|
||||
maxInputBytes = std::max(maxInputBytes, bytesToWrite);
|
||||
}
|
||||
mInputBuffer.resize(maxInputSize);
|
||||
mInputBuffer.resize(maxInputBytes / sizeof(float));
|
||||
std::fill(mInputBuffer.begin(), mInputBuffer.end(), 0x5a);
|
||||
}
|
||||
|
||||
void writeToFmq(size_t s = mWriteMQSize) {
|
||||
void writeToFmq(size_t bytes = mWriteMQBytes) {
|
||||
for (auto& it : mEffectParams) {
|
||||
auto& mq = it.inputMQ;
|
||||
EXPECT_NE(nullptr, mq);
|
||||
const size_t bytesToWrite = mq->availableToWrite();
|
||||
const size_t bytesToWrite = mq->availableToWrite() * sizeof(float);
|
||||
EXPECT_NE(0Ul, bytesToWrite);
|
||||
EXPECT_TRUE(s <= bytesToWrite);
|
||||
EXPECT_TRUE(mq->write(mInputBuffer.data(), s));
|
||||
EXPECT_TRUE(bytes <= bytesToWrite);
|
||||
EXPECT_TRUE(mq->write(mInputBuffer.data(), bytes / sizeof(float)));
|
||||
}
|
||||
}
|
||||
|
||||
void readFromFmq(size_t expectSize = mWriteMQSize) {
|
||||
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(expectSize, (unsigned)status.fmqByteProduced);
|
||||
EXPECT_EQ(expectBytes, (unsigned)status.fmqProduced * sizeof(float));
|
||||
|
||||
auto& outputMq = it.outputMQ;
|
||||
EXPECT_NE(nullptr, outputMq);
|
||||
EXPECT_EQ(expectSize, outputMq->availableToRead());
|
||||
EXPECT_EQ(expectBytes, outputMq->availableToRead() * sizeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,16 +299,16 @@ class EffectHelper {
|
||||
AudioChannelLayout::LAYOUT_STEREO);
|
||||
|
||||
Parameter::Common mCommon;
|
||||
Parameter::Specific mSpecific;
|
||||
std::optional<Parameter::Specific> mSpecific = std::nullopt;
|
||||
|
||||
size_t inputFrameSize, outputFrameSize;
|
||||
std::vector<int8_t> mInputBuffer; // reuse same buffer for all effects testing
|
||||
std::vector<float> mInputBuffer; // reuse same buffer for all effects testing
|
||||
|
||||
typedef ::android::AidlMessageQueue<
|
||||
IEffect::Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
|
||||
StatusMQ;
|
||||
typedef ::android::AidlMessageQueue<
|
||||
int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
|
||||
float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
|
||||
DataMQ;
|
||||
|
||||
class EffectParam {
|
||||
|
||||
@@ -66,13 +66,13 @@ TEST_P(EffectFactoryTest, CanBeRestarted) {
|
||||
|
||||
TEST_P(EffectFactoryTest, QueriedDescriptorList) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
EXPECT_NE(descriptors.size(), 0UL);
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, &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);
|
||||
@@ -82,19 +82,19 @@ TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) {
|
||||
|
||||
TEST_P(EffectFactoryTest, QueriedDescriptorNotExistType) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(EffectNullUuid, std::nullopt, &descriptors);
|
||||
mFactory.QueryEffects(EffectNullUuid, std::nullopt, std::nullopt, &descriptors);
|
||||
EXPECT_EQ(descriptors.size(), 0UL);
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, QueriedDescriptorNotExistInstance) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, EffectNullUuid, &descriptors);
|
||||
mFactory.QueryEffects(std::nullopt, EffectNullUuid, std::nullopt, &descriptors);
|
||||
EXPECT_EQ(descriptors.size(), 0UL);
|
||||
}
|
||||
|
||||
TEST_P(EffectFactoryTest, CreateAndDestroyOnce) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
auto numIds = mFactory.GetEffectIds().size();
|
||||
EXPECT_NE(numIds, 0UL);
|
||||
|
||||
@@ -108,7 +108,7 @@ TEST_P(EffectFactoryTest, CreateAndDestroyOnce) {
|
||||
|
||||
TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
auto numIds = mFactory.GetEffectIds().size();
|
||||
EXPECT_NE(numIds, 0UL);
|
||||
|
||||
@@ -128,7 +128,7 @@ TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
|
||||
|
||||
TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
auto numIds = mFactory.GetEffectIds().size();
|
||||
EXPECT_NE(numIds, 0UL);
|
||||
|
||||
@@ -167,7 +167,7 @@ TEST_P(EffectFactoryTest, DestroyWithInvalidInterface) {
|
||||
|
||||
TEST_P(EffectFactoryTest, CreateAndRemoveReference) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
auto numIds = mFactory.GetEffectIds().size();
|
||||
EXPECT_NE(numIds, 0UL);
|
||||
|
||||
@@ -182,7 +182,7 @@ TEST_P(EffectFactoryTest, CreateAndRemoveReference) {
|
||||
|
||||
TEST_P(EffectFactoryTest, CreateRemoveReferenceAndCreateDestroy) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
auto numIds = mFactory.GetEffectIds().size();
|
||||
EXPECT_NE(numIds, 0UL);
|
||||
|
||||
@@ -203,7 +203,7 @@ TEST_P(EffectFactoryTest, CreateRemoveReferenceAndCreateDestroy) {
|
||||
|
||||
TEST_P(EffectFactoryTest, CreateRestartAndCreateDestroy) {
|
||||
std::vector<Descriptor::Identity> descriptors;
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
|
||||
mFactory.QueryEffects(std::nullopt, std::nullopt, std::nullopt, &descriptors);
|
||||
auto numIds = mFactory.GetEffectIds().size();
|
||||
auto& effectMap = mFactory.GetEffectMap();
|
||||
mFactory.CreateEffects();
|
||||
|
||||
@@ -59,7 +59,6 @@ class AudioEffectTest : public testing::TestWithParam<std::string>, public Effec
|
||||
CreateEffects();
|
||||
initParamCommonFormat();
|
||||
initParamCommon();
|
||||
// initParamSpecific();
|
||||
}
|
||||
|
||||
void TearDown() override {
|
||||
@@ -105,8 +104,9 @@ TEST_P(AudioEffectTest, DescriptorIdExistAndUnique) {
|
||||
Descriptor desc;
|
||||
std::vector<Descriptor::Identity> idList;
|
||||
EXPECT_IS_OK(effect->getDescriptor(&desc));
|
||||
QueryEffects(desc.common.id.type, desc.common.id.uuid, &idList);
|
||||
EXPECT_EQ(idList.size(), 1UL);
|
||||
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);
|
||||
|
||||
@@ -117,7 +117,7 @@ TEST_P(AudioEffectTest, DescriptorIdExistAndUnique) {
|
||||
auto vec = GetCompleteEffectIdList();
|
||||
std::unordered_set<Descriptor::Identity, decltype(stringHash)> idSet(0, stringHash);
|
||||
for (auto it : vec) {
|
||||
EXPECT_EQ(idSet.count(it), 0UL);
|
||||
EXPECT_EQ(idSet.count(it), 0UL) << it.toString();
|
||||
idSet.insert(it);
|
||||
}
|
||||
}
|
||||
@@ -256,7 +256,8 @@ TEST_P(AudioEffectTest, DestroyOpenEffects) {
|
||||
// open effects, destroy without close, expect to get EX_ILLEGAL_STATE status.
|
||||
CreateEffects();
|
||||
OpenEffects();
|
||||
DestroyEffects(EX_ILLEGAL_STATE, 1);
|
||||
auto vec = GetCompleteEffectIdList();
|
||||
DestroyEffects(EX_ILLEGAL_STATE, vec.size());
|
||||
CloseEffects();
|
||||
}
|
||||
|
||||
@@ -310,9 +311,11 @@ TEST_P(AudioEffectTest, ResetAndVerifyParameter) {
|
||||
CloseEffects();
|
||||
}
|
||||
|
||||
// TODO: need a way to support setting different sessionId to different effect instances
|
||||
#if 0
|
||||
// Multiple instances of same implementation running.
|
||||
TEST_P(AudioEffectTest, MultipleInstancesRunning) {
|
||||
CreateEffects(3);
|
||||
TEST_P(AudioEffectTest, MultipleInstancesRunningWithDiffSessionId) {
|
||||
CreateEffects();
|
||||
ExpectState(State::INIT);
|
||||
OpenEffects();
|
||||
ExpectState(State::IDLE);
|
||||
@@ -327,15 +330,16 @@ TEST_P(AudioEffectTest, MultipleInstancesRunning) {
|
||||
VerifyParameters();
|
||||
CloseEffects();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Send data to effects and expect it to consume by check statusMQ.
|
||||
TEST_P(AudioEffectTest, ExpectEffectsToConsumeDataInMQ) {
|
||||
OpenEffects();
|
||||
PrepareInputData(mWriteMQSize);
|
||||
PrepareInputData(mWriteMQBytes);
|
||||
|
||||
CommandEffects(CommandId::START);
|
||||
writeToFmq(mWriteMQSize);
|
||||
readFromFmq(mWriteMQSize);
|
||||
writeToFmq(mWriteMQBytes);
|
||||
readFromFmq(mWriteMQBytes);
|
||||
|
||||
ExpectState(State::PROCESSING);
|
||||
CommandEffects(CommandId::STOP);
|
||||
|
||||
@@ -95,9 +95,9 @@ class EqualizerParamTest : public ::testing::TestWithParam<EqualizerParamTestPar
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
const int mParamPresetIndex;
|
||||
const int mParamBandIndex;
|
||||
const int mParamBandLevel;
|
||||
int mParamPresetIndex = 0;
|
||||
int mParamBandIndex = 0;
|
||||
int mParamBandLevel = 0;
|
||||
|
||||
void SetAndGetEqualizerParameters() {
|
||||
auto functor = [&](const std::shared_ptr<IEffect>& effect) {
|
||||
@@ -122,19 +122,54 @@ class EqualizerParamTest : public ::testing::TestWithParam<EqualizerParamTestPar
|
||||
// only get if parameter in range and set success
|
||||
if (expected == EX_NONE) {
|
||||
Parameter getParam;
|
||||
Parameter::Specific::Id id;
|
||||
id.set<Parameter::Specific::Id::equalizerTag>(tag);
|
||||
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_EQ(expectParam, getParam) << "\n"
|
||||
<< expectParam.toString() << "\n"
|
||||
<< getParam.toString();
|
||||
EXPECT_TRUE(isEqParameterExpected(expectParam, getParam));
|
||||
}
|
||||
}
|
||||
};
|
||||
EXPECT_NO_FATAL_FAILURE(ForEachEffect(functor));
|
||||
}
|
||||
|
||||
bool isEqParameterExpected(const Parameter& expect, const Parameter& target) {
|
||||
// if parameter same, then for sure 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}]
|
||||
*/
|
||||
EXPECT_EQ(expect.getTag(), Parameter::specific);
|
||||
EXPECT_EQ(target.getTag(), Parameter::specific);
|
||||
|
||||
Parameter::Specific expectSpec = expect.get<Parameter::specific>(),
|
||||
targetSpec = target.get<Parameter::specific>();
|
||||
EXPECT_EQ(expectSpec.getTag(), Parameter::Specific::equalizer);
|
||||
EXPECT_EQ(targetSpec.getTag(), Parameter::Specific::equalizer);
|
||||
|
||||
Equalizer expectEq = expectSpec.get<Parameter::Specific::equalizer>(),
|
||||
targetEq = targetSpec.get<Parameter::Specific::equalizer>();
|
||||
EXPECT_EQ(expectEq.getTag(), targetEq.getTag());
|
||||
|
||||
auto eqTag = targetEq.getTag();
|
||||
switch (eqTag) {
|
||||
case Equalizer::bandLevels: {
|
||||
auto expectBl = expectEq.get<Equalizer::bandLevels>();
|
||||
auto targetBl = targetEq.get<Equalizer::bandLevels>();
|
||||
return std::includes(targetBl.begin(), targetBl.end(), expectBl.begin(),
|
||||
expectBl.end());
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void addPresetParam(int preset) {
|
||||
Equalizer eq;
|
||||
eq.set<Equalizer::preset>(preset);
|
||||
@@ -189,7 +224,6 @@ class EqualizerParamTest : public ::testing::TestWithParam<EqualizerParamTestPar
|
||||
}
|
||||
|
||||
private:
|
||||
Equalizer::VendorExtension mVendorExtension;
|
||||
std::vector<std::pair<Equalizer::Tag, std::unique_ptr<Equalizer>>> mTags;
|
||||
|
||||
bool validCapabilityTag(Capability& cap) { return cap.getTag() == Capability::equalizer; }
|
||||
@@ -211,8 +245,8 @@ TEST_P(EqualizerParamTest, SetAndGetPreset) {
|
||||
}
|
||||
|
||||
TEST_P(EqualizerParamTest, SetAndGetSingleBand) {
|
||||
Equalizer::BandLevel bandLevel = {mParamBandIndex, mParamBandLevel};
|
||||
std::vector<Equalizer::BandLevel> bandLevels;
|
||||
Equalizer::BandLevel bandLevel = {mParamBandIndex, mParamBandLevel};
|
||||
bandLevels.push_back(bandLevel);
|
||||
EXPECT_NO_FATAL_FAILURE(addBandLevelsParam(bandLevels));
|
||||
SetAndGetEqualizerParameters();
|
||||
|
||||
Reference in New Issue
Block a user