Merge changes from topic "effect_reopen" into main am: 3eb2a2c14f am: 4aaefb8831

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

Change-Id: I9cc7d6b5782f792ebb1f1b4681cc9ea3b69545d3
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Shunkai Yao
2024-01-12 22:00:21 +00:00
committed by Automerger Merge Worker
44 changed files with 735 additions and 447 deletions

View File

@@ -226,6 +226,7 @@ cc_defaults {
filegroup {
name: "effectCommonFile",
srcs: [
"EffectContext.cpp",
"EffectThread.cpp",
"EffectImpl.cpp",
],

View File

@@ -0,0 +1,227 @@
/*
* Copyright (C) 2024 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 <memory>
#define LOG_TAG "AHAL_EffectContext"
#include "effect-impl/EffectContext.h"
#include "include/effect-impl/EffectTypes.h"
using aidl::android::hardware::audio::common::getChannelCount;
using aidl::android::hardware::audio::common::getFrameSizeInBytes;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::media::audio::common::PcmType;
using ::android::hardware::EventFlag;
namespace aidl::android::hardware::audio::effect {
EffectContext::EffectContext(size_t statusDepth, const Parameter::Common& common) {
LOG_ALWAYS_FATAL_IF(RetCode::SUCCESS != setCommon(common), "illegalCommonParameter");
// in/outBuffer size in float (FMQ data format defined for DataMQ)
size_t inBufferSizeInFloat = common.input.frameCount * mInputFrameSize / sizeof(float);
size_t outBufferSizeInFloat = common.output.frameCount * mOutputFrameSize / sizeof(float);
// only status FMQ use the EventFlag
mStatusMQ = std::make_shared<StatusMQ>(statusDepth, true /*configureEventFlagWord*/);
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";
}
::android::status_t status =
EventFlag::createEventFlag(mStatusMQ->getEventFlagWord(), &mEfGroup);
LOG_ALWAYS_FATAL_IF(status != ::android::OK || !mEfGroup, " create EventFlagGroup failed ");
mWorkBuffer.reserve(std::max(inBufferSizeInFloat, outBufferSizeInFloat));
}
// reset buffer status by abandon input data in FMQ
void EffectContext::resetBuffer() {
auto buffer = static_cast<float*>(mWorkBuffer.data());
std::vector<IEffect::Status> status(mStatusMQ->availableToRead());
if (mInputMQ) {
mInputMQ->read(buffer, mInputMQ->availableToRead());
}
}
void EffectContext::dupeFmqWithReopen(IEffect::OpenEffectReturn* effectRet) {
if (!mInputMQ) {
mInputMQ = std::make_shared<DataMQ>(mCommon.input.frameCount * mInputFrameSize /
sizeof(float));
}
if (!mOutputMQ) {
mOutputMQ = std::make_shared<DataMQ>(mCommon.output.frameCount * mOutputFrameSize /
sizeof(float));
}
dupeFmq(effectRet);
}
void EffectContext::dupeFmq(IEffect::OpenEffectReturn* effectRet) {
if (effectRet) {
effectRet->statusMQ = mStatusMQ->dupeDesc();
effectRet->inputDataMQ = mInputMQ->dupeDesc();
effectRet->outputDataMQ = mOutputMQ->dupeDesc();
}
}
float* EffectContext::getWorkBuffer() {
return static_cast<float*>(mWorkBuffer.data());
}
std::shared_ptr<EffectContext::StatusMQ> EffectContext::getStatusFmq() const {
return mStatusMQ;
}
std::shared_ptr<EffectContext::DataMQ> EffectContext::getInputDataFmq() const {
return mInputMQ;
}
std::shared_ptr<EffectContext::DataMQ> EffectContext::getOutputDataFmq() const {
return mOutputMQ;
}
size_t EffectContext::getInputFrameSize() const {
return mInputFrameSize;
}
size_t EffectContext::getOutputFrameSize() const {
return mOutputFrameSize;
}
int EffectContext::getSessionId() const {
return mCommon.session;
}
int EffectContext::getIoHandle() const {
return mCommon.ioHandle;
}
RetCode EffectContext::setOutputDevice(
const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& device) {
mOutputDevice = device;
return RetCode::SUCCESS;
}
std::vector<aidl::android::media::audio::common::AudioDeviceDescription>
EffectContext::getOutputDevice() {
return mOutputDevice;
}
RetCode EffectContext::setAudioMode(const aidl::android::media::audio::common::AudioMode& mode) {
mMode = mode;
return RetCode::SUCCESS;
}
aidl::android::media::audio::common::AudioMode EffectContext::getAudioMode() {
return mMode;
}
RetCode EffectContext::setAudioSource(
const aidl::android::media::audio::common::AudioSource& source) {
mSource = source;
return RetCode::SUCCESS;
}
aidl::android::media::audio::common::AudioSource EffectContext::getAudioSource() {
return mSource;
}
RetCode EffectContext::setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) {
mVolumeStereo = volumeStereo;
return RetCode::SUCCESS;
}
Parameter::VolumeStereo EffectContext::getVolumeStereo() {
return mVolumeStereo;
}
RetCode EffectContext::setCommon(const Parameter::Common& common) {
LOG(VERBOSE) << __func__ << common.toString();
auto& input = common.input;
auto& output = common.output;
if (input.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT ||
output.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT) {
LOG(ERROR) << __func__ << " illegal IO, input "
<< ::android::internal::ToString(input.base.format) << ", output "
<< ::android::internal::ToString(output.base.format);
return RetCode::ERROR_ILLEGAL_PARAMETER;
}
if (auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) {
return ret;
}
mInputChannelCount = getChannelCount(input.base.channelMask);
mOutputChannelCount = getChannelCount(output.base.channelMask);
if (mInputChannelCount == 0 || mOutputChannelCount == 0) {
LOG(ERROR) << __func__ << " illegal channel count input " << mInputChannelCount
<< ", output " << mOutputChannelCount;
return RetCode::ERROR_ILLEGAL_PARAMETER;
}
mCommon = common;
return RetCode::SUCCESS;
}
Parameter::Common EffectContext::getCommon() {
LOG(VERBOSE) << __func__ << mCommon.toString();
return mCommon;
}
EventFlag* EffectContext::getStatusEventFlag() {
return mEfGroup;
}
RetCode EffectContext::updateIOFrameSize(const Parameter::Common& common) {
const auto iFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes(
common.input.base.format, common.input.base.channelMask);
const auto oFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes(
common.output.base.format, common.output.base.channelMask);
bool needUpdateMq = false;
if (mInputMQ &&
(mInputFrameSize != iFrameSize || mCommon.input.frameCount != common.input.frameCount)) {
mInputMQ.reset();
needUpdateMq = true;
}
if (mOutputMQ &&
(mOutputFrameSize != oFrameSize || mCommon.output.frameCount != common.output.frameCount)) {
mOutputMQ.reset();
needUpdateMq = true;
}
mInputFrameSize = iFrameSize;
mOutputFrameSize = oFrameSize;
if (needUpdateMq) {
return notifyDataMqUpdate();
}
return RetCode::SUCCESS;
}
RetCode EffectContext::notifyDataMqUpdate() {
if (!mEfGroup) {
LOG(ERROR) << __func__ << ": invalid EventFlag group";
return RetCode::ERROR_EVENT_FLAG_ERROR;
}
if (const auto ret = mEfGroup->wake(kEventFlagDataMqUpdate); ret != ::android::OK) {
LOG(ERROR) << __func__ << ": wake failure with ret " << ret;
return RetCode::ERROR_EVENT_FLAG_ERROR;
}
LOG(DEBUG) << __func__ << " : signal client for reopen";
return RetCode::SUCCESS;
}
} // namespace aidl::android::hardware::audio::effect

View File

@@ -14,6 +14,7 @@
* limitations under the License.
*/
#include <memory>
#define LOG_TAG "AHAL_EffectImpl"
#include "effect-impl/EffectImpl.h"
#include "effect-impl/EffectTypes.h"
@@ -22,6 +23,7 @@
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::State;
using aidl::android::media::audio::common::PcmType;
using ::android::hardware::EventFlag;
extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
State state;
@@ -45,50 +47,62 @@ ndk::ScopedAStatus EffectImpl::open(const Parameter::Common& common,
RETURN_IF(common.input.base.format.pcm != common.output.base.format.pcm ||
common.input.base.format.pcm != PcmType::FLOAT_32_BIT,
EX_ILLEGAL_ARGUMENT, "dataMustBe32BitsFloat");
std::lock_guard lg(mImplMutex);
RETURN_OK_IF(mState != State::INIT);
auto context = createContext(common);
RETURN_IF(!context, EX_NULL_POINTER, "createContextFailed");
mImplContext = createContext(common);
RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext");
mEventFlag = mImplContext->getStatusEventFlag();
if (specific.has_value()) {
RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(specific.value()), "setSpecParamErr");
}
mState = State::IDLE;
context->dupeFmq(ret);
RETURN_IF(createThread(context, getEffectName()) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
mImplContext->dupeFmq(ret);
RETURN_IF(createThread(getEffectName()) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
"FailedToCreateWorker");
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus EffectImpl::reopen(OpenEffectReturn* ret) {
std::lock_guard lg(mImplMutex);
RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "alreadyClosed");
// TODO: b/302036943 add reopen implementation
auto context = getContext();
RETURN_IF(!context, EX_NULL_POINTER, "nullContext");
context->dupeFmq(ret);
RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext");
mImplContext->dupeFmqWithReopen(ret);
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus EffectImpl::close() {
RETURN_OK_IF(mState == State::INIT);
RETURN_IF(mState == State::PROCESSING, EX_ILLEGAL_STATE, "closeAtProcessing");
{
std::lock_guard lg(mImplMutex);
RETURN_OK_IF(mState == State::INIT);
RETURN_IF(mState == State::PROCESSING, EX_ILLEGAL_STATE, "closeAtProcessing");
mState = State::INIT;
}
RETURN_IF(notifyEventFlag(kEventFlagNotEmpty) != RetCode::SUCCESS, EX_ILLEGAL_STATE,
"notifyEventFlagFailed");
// stop the worker thread, ignore the return code
RETURN_IF(destroyThread() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
"FailedToDestroyWorker");
mState = State::INIT;
RETURN_IF(releaseContext() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
"FailedToCreateWorker");
{
std::lock_guard lg(mImplMutex);
releaseContext();
mImplContext.reset();
}
LOG(DEBUG) << getEffectName() << __func__;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus EffectImpl::setParameter(const Parameter& param) {
std::lock_guard lg(mImplMutex);
LOG(VERBOSE) << getEffectName() << __func__ << " with: " << param.toString();
const auto tag = param.getTag();
const auto& tag = param.getTag();
switch (tag) {
case Parameter::common:
case Parameter::deviceDescription:
@@ -110,8 +124,8 @@ ndk::ScopedAStatus EffectImpl::setParameter(const Parameter& param) {
}
ndk::ScopedAStatus EffectImpl::getParameter(const Parameter::Id& id, Parameter* param) {
auto tag = id.getTag();
switch (tag) {
std::lock_guard lg(mImplMutex);
switch (id.getTag()) {
case Parameter::Id::commonTag: {
RETURN_IF_ASTATUS_NOT_OK(getParameterCommon(id.get<Parameter::Id::commonTag>(), param),
"CommonParamNotSupported");
@@ -131,30 +145,30 @@ ndk::ScopedAStatus EffectImpl::getParameter(const Parameter::Id& id, Parameter*
}
ndk::ScopedAStatus EffectImpl::setParameterCommon(const Parameter& param) {
auto context = getContext();
RETURN_IF(!context, EX_NULL_POINTER, "nullContext");
RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext");
auto tag = param.getTag();
const auto& tag = param.getTag();
switch (tag) {
case Parameter::common:
RETURN_IF(context->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
RETURN_IF(mImplContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
EX_ILLEGAL_ARGUMENT, "setCommFailed");
break;
case Parameter::deviceDescription:
RETURN_IF(context->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
RETURN_IF(mImplContext->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
RetCode::SUCCESS,
EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
break;
case Parameter::mode:
RETURN_IF(context->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
RETURN_IF(mImplContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
EX_ILLEGAL_ARGUMENT, "setModeFailed");
break;
case Parameter::source:
RETURN_IF(context->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
RETURN_IF(mImplContext->setAudioSource(param.get<Parameter::source>()) !=
RetCode::SUCCESS,
EX_ILLEGAL_ARGUMENT, "setSourceFailed");
break;
case Parameter::volumeStereo:
RETURN_IF(context->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
RETURN_IF(mImplContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
RetCode::SUCCESS,
EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed");
break;
@@ -169,28 +183,27 @@ ndk::ScopedAStatus EffectImpl::setParameterCommon(const Parameter& param) {
}
ndk::ScopedAStatus EffectImpl::getParameterCommon(const Parameter::Tag& tag, Parameter* param) {
auto context = getContext();
RETURN_IF(!context, EX_NULL_POINTER, "nullContext");
RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext");
switch (tag) {
case Parameter::common: {
param->set<Parameter::common>(context->getCommon());
param->set<Parameter::common>(mImplContext->getCommon());
break;
}
case Parameter::deviceDescription: {
param->set<Parameter::deviceDescription>(context->getOutputDevice());
param->set<Parameter::deviceDescription>(mImplContext->getOutputDevice());
break;
}
case Parameter::mode: {
param->set<Parameter::mode>(context->getAudioMode());
param->set<Parameter::mode>(mImplContext->getAudioMode());
break;
}
case Parameter::source: {
param->set<Parameter::source>(context->getAudioSource());
param->set<Parameter::source>(mImplContext->getAudioSource());
break;
}
case Parameter::volumeStereo: {
param->set<Parameter::volumeStereo>(context->getVolumeStereo());
param->set<Parameter::volumeStereo>(mImplContext->getVolumeStereo());
break;
}
default: {
@@ -202,30 +215,34 @@ ndk::ScopedAStatus EffectImpl::getParameterCommon(const Parameter::Tag& tag, Par
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus EffectImpl::getState(State* state) {
ndk::ScopedAStatus EffectImpl::getState(State* state) NO_THREAD_SAFETY_ANALYSIS {
*state = mState;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus EffectImpl::command(CommandId command) {
RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "CommandStateError");
std::lock_guard lg(mImplMutex);
RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "instanceNotOpen");
LOG(DEBUG) << getEffectName() << __func__ << ": receive command: " << toString(command)
<< " at state " << toString(mState);
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(commandImpl(command), "commandImplFailed");
startThread();
mState = State::PROCESSING;
RETURN_IF(notifyEventFlag(kEventFlagNotEmpty) != RetCode::SUCCESS, EX_ILLEGAL_STATE,
"notifyEventFlagFailed");
startThread();
break;
case CommandId::STOP:
case CommandId::RESET:
RETURN_OK_IF(mState == State::IDLE);
mState = State::IDLE;
RETURN_IF(notifyEventFlag(kEventFlagNotEmpty) != RetCode::SUCCESS, EX_ILLEGAL_STATE,
"notifyEventFlagFailed");
stopThread();
RETURN_IF_ASTATUS_NOT_OK(commandImpl(command), "commandImplFailed");
mState = State::IDLE;
break;
default:
LOG(ERROR) << getEffectName() << __func__ << " instance still processing";
@@ -237,19 +254,41 @@ ndk::ScopedAStatus EffectImpl::command(CommandId command) {
}
ndk::ScopedAStatus EffectImpl::commandImpl(CommandId command) {
auto context = getContext();
RETURN_IF(!context, EX_NULL_POINTER, "nullContext");
RETURN_IF(!mImplContext, EX_NULL_POINTER, "nullContext");
if (command == CommandId::RESET) {
context->resetBuffer();
mImplContext->resetBuffer();
}
return ndk::ScopedAStatus::ok();
}
std::shared_ptr<EffectContext> EffectImpl::createContext(const Parameter::Common& common) {
return std::make_shared<EffectContext>(1 /* statusMqDepth */, common);
}
RetCode EffectImpl::releaseContext() {
if (mImplContext) {
mImplContext.reset();
}
return RetCode::SUCCESS;
}
void EffectImpl::cleanUp() {
command(CommandId::STOP);
close();
}
RetCode EffectImpl::notifyEventFlag(uint32_t flag) {
if (!mEventFlag) {
LOG(ERROR) << getEffectName() << __func__ << ": StatusEventFlag invalid";
return RetCode::ERROR_EVENT_FLAG_ERROR;
}
if (const auto ret = mEventFlag->wake(flag); ret != ::android::OK) {
LOG(ERROR) << getEffectName() << __func__ << ": wake failure with ret " << ret;
return RetCode::ERROR_EVENT_FLAG_ERROR;
}
return RetCode::SUCCESS;
}
IEffect::Status EffectImpl::status(binder_status_t status, size_t consumed, size_t produced) {
IEffect::Status ret;
ret.status = status;
@@ -258,6 +297,48 @@ IEffect::Status EffectImpl::status(binder_status_t status, size_t consumed, size
return ret;
}
void EffectImpl::process() {
/**
* wait for the EventFlag without lock, it's ok because the mEfGroup pointer will not change
* in the life cycle of workerThread (threadLoop).
*/
uint32_t efState = 0;
if (!mEventFlag ||
::android::OK != mEventFlag->wait(kEventFlagNotEmpty, &efState, 0 /* no timeout */,
true /* retry */) ||
!(efState & kEventFlagNotEmpty)) {
LOG(ERROR) << getEffectName() << __func__ << ": StatusEventFlag - " << mEventFlag
<< " efState - " << std::hex << efState;
return;
}
{
std::lock_guard lg(mImplMutex);
if (mState != State::PROCESSING) {
LOG(DEBUG) << getEffectName() << " skip process in state: " << toString(mState);
return;
}
RETURN_VALUE_IF(!mImplContext, void(), "nullContext");
auto statusMQ = mImplContext->getStatusFmq();
auto inputMQ = mImplContext->getInputDataFmq();
auto outputMQ = mImplContext->getOutputDataFmq();
auto buffer = mImplContext->getWorkBuffer();
if (!inputMQ || !outputMQ) {
return;
}
auto processSamples = inputMQ->availableToRead();
if (processSamples) {
inputMQ->read(buffer, processSamples);
IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples);
outputMQ->write(buffer, status.fmqProduced);
statusMQ->writeBlocking(&status, 1);
LOG(VERBOSE) << getEffectName() << __func__ << ": done processing, effect consumed "
<< status.fmqConsumed << " produced " << status.fmqProduced;
}
}
}
// A placeholder processing implementation to copy samples from input to output
IEffect::Status EffectImpl::effectProcessImpl(float* in, float* out, int samples) {
for (int i = 0; i < samples; i++) {

View File

@@ -25,8 +25,6 @@
#include "effect-impl/EffectThread.h"
#include "effect-impl/EffectTypes.h"
using ::android::hardware::EventFlag;
namespace aidl::android::hardware::audio::effect {
EffectThread::EffectThread() {
@@ -38,31 +36,18 @@ EffectThread::~EffectThread() {
LOG(DEBUG) << __func__ << " done";
}
RetCode EffectThread::createThread(std::shared_ptr<EffectContext> context, const std::string& name,
int priority) {
RetCode EffectThread::createThread(const std::string& name, int priority) {
if (mThread.joinable()) {
LOG(WARNING) << mName << __func__ << " thread already created, no-op";
return RetCode::SUCCESS;
}
mName = name;
mPriority = priority;
{
std::lock_guard lg(mThreadMutex);
mStop = true;
mExit = false;
mThreadContext = std::move(context);
auto statusMQ = mThreadContext->getStatusFmq();
EventFlag* efGroup = nullptr;
::android::status_t status =
EventFlag::createEventFlag(statusMQ->getEventFlagWord(), &efGroup);
if (status != ::android::OK || !efGroup) {
LOG(ERROR) << mName << __func__ << " create EventFlagGroup failed " << status
<< " efGroup " << efGroup;
return RetCode::ERROR_THREAD;
}
mEfGroup.reset(efGroup);
// kickoff and wait for commands (CommandId::START/STOP) or IEffect.close from client
mEfGroup->wake(kEventFlagNotEmpty);
}
mThread = std::thread(&EffectThread::threadLoop, this);
@@ -75,16 +60,12 @@ RetCode EffectThread::destroyThread() {
std::lock_guard lg(mThreadMutex);
mStop = mExit = true;
}
mCv.notify_one();
mCv.notify_one();
if (mThread.joinable()) {
mThread.join();
}
{
std::lock_guard lg(mThreadMutex);
mThreadContext.reset();
}
LOG(DEBUG) << mName << __func__;
return RetCode::SUCCESS;
}
@@ -96,7 +77,6 @@ RetCode EffectThread::startThread() {
mCv.notify_one();
}
mEfGroup->wake(kEventFlagNotEmpty);
LOG(DEBUG) << mName << __func__;
return RetCode::SUCCESS;
}
@@ -108,7 +88,6 @@ RetCode EffectThread::stopThread() {
mCv.notify_one();
}
mEfGroup->wake(kEventFlagNotEmpty);
LOG(DEBUG) << mName << __func__;
return RetCode::SUCCESS;
}
@@ -117,13 +96,6 @@ void EffectThread::threadLoop() {
pthread_setname_np(pthread_self(), mName.substr(0, kMaxTaskNameLen - 1).c_str());
setpriority(PRIO_PROCESS, 0, mPriority);
while (true) {
/**
* wait for the EventFlag without lock, it's ok because the mEfGroup pointer will not change
* in the life cycle of workerThread (threadLoop).
*/
uint32_t efState = 0;
mEfGroup->wait(kEventFlagNotEmpty, &efState);
{
std::unique_lock l(mThreadMutex);
::android::base::ScopedLockAssertion lock_assertion(mThreadMutex);
@@ -132,27 +104,8 @@ void EffectThread::threadLoop() {
LOG(INFO) << __func__ << " EXIT!";
return;
}
process_l();
}
}
}
void EffectThread::process_l() {
RETURN_VALUE_IF(!mThreadContext, void(), "nullContext");
auto statusMQ = mThreadContext->getStatusFmq();
auto inputMQ = mThreadContext->getInputDataFmq();
auto outputMQ = mThreadContext->getOutputDataFmq();
auto buffer = mThreadContext->getWorkBuffer();
auto processSamples = inputMQ->availableToRead();
if (processSamples) {
inputMQ->read(buffer, processSamples);
IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples);
outputMQ->write(buffer, status.fmqProduced);
statusMQ->writeBlocking(&status, 1);
LOG(VERBOSE) << mName << __func__ << ": done processing, effect consumed "
<< status.fmqConsumed << " produced " << status.fmqProduced;
process();
}
}

View File

@@ -168,10 +168,6 @@ std::shared_ptr<EffectContext> AcousticEchoCancelerSw::createContext(
return mContext;
}
std::shared_ptr<EffectContext> AcousticEchoCancelerSw::getContext() {
return mContext;
}
RetCode AcousticEchoCancelerSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -52,21 +52,23 @@ class AcousticEchoCancelerSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; };
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
private:
static const std::vector<Range::AcousticEchoCancelerRange> kRanges;
std::shared_ptr<AcousticEchoCancelerSwContext> mContext;
std::shared_ptr<AcousticEchoCancelerSwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterAcousticEchoCanceler(const AcousticEchoCanceler::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific)
REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -177,10 +177,6 @@ std::shared_ptr<EffectContext> AutomaticGainControlV1Sw::createContext(
return mContext;
}
std::shared_ptr<EffectContext> AutomaticGainControlV1Sw::getContext() {
return mContext;
}
RetCode AutomaticGainControlV1Sw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -53,21 +53,24 @@ class AutomaticGainControlV1Sw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; };
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
private:
static const std::vector<Range::AutomaticGainControlV1Range> kRanges;
std::shared_ptr<AutomaticGainControlV1SwContext> mContext;
std::shared_ptr<AutomaticGainControlV1SwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterAutomaticGainControlV1(const AutomaticGainControlV1::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific)
REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -180,10 +180,6 @@ std::shared_ptr<EffectContext> AutomaticGainControlV2Sw::createContext(
return mContext;
}
std::shared_ptr<EffectContext> AutomaticGainControlV2Sw::getContext() {
return mContext;
}
RetCode AutomaticGainControlV2Sw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -59,21 +59,24 @@ class AutomaticGainControlV2Sw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; };
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
private:
static const std::vector<Range::AutomaticGainControlV2Range> kRanges;
std::shared_ptr<AutomaticGainControlV2SwContext> mContext;
std::shared_ptr<AutomaticGainControlV2SwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterAutomaticGainControlV2(const AutomaticGainControlV2::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific)
REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -151,10 +151,6 @@ std::shared_ptr<EffectContext> BassBoostSw::createContext(const Parameter::Commo
return mContext;
}
std::shared_ptr<EffectContext> BassBoostSw::getContext() {
return mContext;
}
RetCode BassBoostSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -51,21 +51,23 @@ class BassBoostSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; };
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
private:
static const std::vector<Range::BassBoostRange> kRanges;
std::shared_ptr<BassBoostSwContext> mContext;
std::shared_ptr<BassBoostSwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterBassBoost(const BassBoost::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific) REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -144,10 +144,6 @@ std::shared_ptr<EffectContext> DownmixSw::createContext(const Parameter::Common&
return mContext;
}
std::shared_ptr<EffectContext> DownmixSw::getContext() {
return mContext;
}
RetCode DownmixSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -55,20 +55,23 @@ class DownmixSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; };
IEffect::Status effectProcessImpl(float* in, float* out, int sample) override;
IEffect::Status effectProcessImpl(float* in, float* out, int sample)
REQUIRES(mImplMutex) override;
private:
std::shared_ptr<DownmixSwContext> mContext;
std::shared_ptr<DownmixSwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific);
ndk::ScopedAStatus getParameterDownmix(const Downmix::Tag& tag, Parameter::Specific* specific)
REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -260,10 +260,6 @@ std::shared_ptr<EffectContext> DynamicsProcessingSw::createContext(
return mContext;
}
std::shared_ptr<EffectContext> DynamicsProcessingSw::getContext() {
return mContext;
}
RetCode DynamicsProcessingSw::releaseContext() {
if (mContext) {
mContext.reset();
@@ -282,6 +278,9 @@ IEffect::Status DynamicsProcessingSw::effectProcessImpl(float* in, float* out, i
}
RetCode DynamicsProcessingSwContext::setCommon(const Parameter::Common& common) {
if (auto ret = updateIOFrameSize(common); ret != RetCode::SUCCESS) {
return ret;
}
mCommon = common;
mChannelCount = ::aidl::android::hardware::audio::common::getChannelCount(
common.input.base.channelMask);

View File

@@ -113,15 +113,17 @@ class DynamicsProcessingSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; };
private:
@@ -130,9 +132,10 @@ class DynamicsProcessingSw final : public EffectImpl {
static const Range::DynamicsProcessingRange kPreEqBandRange;
static const Range::DynamicsProcessingRange kPostEqBandRange;
static const std::vector<Range::DynamicsProcessingRange> kRanges;
std::shared_ptr<DynamicsProcessingSwContext> mContext;
std::shared_ptr<DynamicsProcessingSwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterDynamicsProcessing(const DynamicsProcessing::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific)
REQUIRES(mImplMutex);
}; // DynamicsProcessingSw

View File

@@ -267,10 +267,6 @@ std::shared_ptr<EffectContext> EnvReverbSw::createContext(const Parameter::Commo
return mContext;
}
std::shared_ptr<EffectContext> EnvReverbSw::getContext() {
return mContext;
}
RetCode EnvReverbSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -100,21 +100,23 @@ class EnvReverbSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
std::string getEffectName() override { return kEffectName; }
private:
static const std::vector<Range::EnvironmentalReverbRange> kRanges;
std::shared_ptr<EnvReverbSwContext> mContext;
std::shared_ptr<EnvReverbSwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterEnvironmentalReverb(const EnvironmentalReverb::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific)
REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -198,10 +198,6 @@ std::shared_ptr<EffectContext> EqualizerSw::createContext(const Parameter::Commo
return mContext;
}
std::shared_ptr<EffectContext> EqualizerSw::getContext() {
return mContext;
}
RetCode EqualizerSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -97,15 +97,17 @@ class EqualizerSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; }
private:
@@ -113,7 +115,7 @@ class EqualizerSw final : public EffectImpl {
static const std::vector<Equalizer::Preset> kPresets;
static const std::vector<Range::EqualizerRange> kRanges;
ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific) REQUIRES(mImplMutex);
std::shared_ptr<EqualizerSwContext> mContext;
};

View File

@@ -123,10 +123,6 @@ std::shared_ptr<EffectContext> ExtensionEffect::createContext(const Parameter::C
return mContext;
}
std::shared_ptr<EffectContext> ExtensionEffect::getContext() {
return mContext;
}
RetCode ExtensionEffect::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -54,18 +54,20 @@ class ExtensionEffect final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; };
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
private:
std::shared_ptr<ExtensionEffectContext> mContext;
std::shared_ptr<ExtensionEffectContext> mContext GUARDED_BY(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -158,10 +158,6 @@ std::shared_ptr<EffectContext> HapticGeneratorSw::createContext(const Parameter:
return mContext;
}
std::shared_ptr<EffectContext> HapticGeneratorSw::getContext() {
return mContext;
}
RetCode HapticGeneratorSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -67,21 +67,24 @@ class HapticGeneratorSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; }
private:
std::shared_ptr<HapticGeneratorSwContext> mContext;
std::shared_ptr<HapticGeneratorSwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterHapticGenerator(const HapticGenerator::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific)
REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -21,6 +21,7 @@
#include <Utils.h>
#include <android-base/logging.h>
#include <fmq/AidlMessageQueue.h>
#include <fmq/EventFlag.h>
#include <aidl/android/hardware/audio/effect/BnEffect.h>
#include "EffectTypes.h"
@@ -36,127 +37,73 @@ class EffectContext {
float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
DataMQ;
EffectContext(size_t statusDepth, const Parameter::Common& common) {
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");
size_t inputChannelCount =
::aidl::android::hardware::audio::common::getChannelCount(input.base.channelMask);
LOG_ALWAYS_FATAL_IF(inputChannelCount == 0, "inputChannelCountNotValid");
size_t outputChannelCount =
::aidl::android::hardware::audio::common::getChannelCount(output.base.channelMask);
LOG_ALWAYS_FATAL_IF(outputChannelCount == 0, "outputChannelCountNotValid");
mInputFrameSize = ::aidl::android::hardware::audio::common::getFrameSizeInBytes(
input.base.format, input.base.channelMask);
mOutputFrameSize = ::aidl::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);
// only status FMQ use the EventFlag
mStatusMQ = std::make_shared<StatusMQ>(statusDepth, true /*configureEventFlagWord*/);
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";
EffectContext(size_t statusDepth, const Parameter::Common& common);
virtual ~EffectContext() {
if (mEfGroup) {
::android::hardware::EventFlag::deleteEventFlag(&mEfGroup);
}
mWorkBuffer.reserve(std::max(inBufferSizeInFloat, outBufferSizeInFloat));
mCommon = common;
}
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() const;
std::shared_ptr<DataMQ> getInputDataFmq() const;
std::shared_ptr<DataMQ> getOutputDataFmq() const;
float* getWorkBuffer() { return static_cast<float*>(mWorkBuffer.data()); }
float* getWorkBuffer();
// reset buffer status by abandon input data in FMQ
void resetBuffer() {
auto buffer = static_cast<float*>(mWorkBuffer.data());
std::vector<IEffect::Status> status(mStatusMQ->availableToRead());
mInputMQ->read(buffer, mInputMQ->availableToRead());
}
void resetBuffer();
void dupeFmq(IEffect::OpenEffectReturn* effectRet);
size_t getInputFrameSize() const;
size_t getOutputFrameSize() const;
int getSessionId() const;
int getIoHandle() const;
void dupeFmq(IEffect::OpenEffectReturn* effectRet) {
if (effectRet) {
effectRet->statusMQ = mStatusMQ->dupeDesc();
effectRet->inputDataMQ = mInputMQ->dupeDesc();
effectRet->outputDataMQ = mOutputMQ->dupeDesc();
}
}
size_t getInputFrameSize() { return mInputFrameSize; }
size_t getOutputFrameSize() { return mOutputFrameSize; }
int getSessionId() { return mCommon.session; }
int getIoHandle() { return mCommon.ioHandle; }
virtual void dupeFmqWithReopen(IEffect::OpenEffectReturn* effectRet);
virtual RetCode setOutputDevice(
const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>&
device) {
mOutputDevice = device;
return RetCode::SUCCESS;
}
const std::vector<aidl::android::media::audio::common::AudioDeviceDescription>& device);
virtual std::vector<aidl::android::media::audio::common::AudioDeviceDescription>
getOutputDevice() {
return mOutputDevice;
}
getOutputDevice();
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 setAudioMode(const aidl::android::media::audio::common::AudioMode& mode);
virtual aidl::android::media::audio::common::AudioMode getAudioMode();
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 setAudioSource(const aidl::android::media::audio::common::AudioSource& source);
virtual aidl::android::media::audio::common::AudioSource getAudioSource();
virtual RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) {
mVolumeStereo = volumeStereo;
return RetCode::SUCCESS;
}
virtual Parameter::VolumeStereo getVolumeStereo() { return mVolumeStereo; }
virtual RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo);
virtual Parameter::VolumeStereo getVolumeStereo();
virtual RetCode setCommon(const Parameter::Common& common) {
mCommon = common;
LOG(VERBOSE) << __func__ << mCommon.toString();
return RetCode::SUCCESS;
}
virtual Parameter::Common getCommon() {
LOG(VERBOSE) << __func__ << mCommon.toString();
return mCommon;
}
virtual RetCode setCommon(const Parameter::Common& common);
virtual Parameter::Common getCommon();
virtual ::android::hardware::EventFlag* getStatusEventFlag();
protected:
// common parameters
size_t mInputFrameSize;
size_t mOutputFrameSize;
Parameter::Common mCommon;
std::vector<aidl::android::media::audio::common::AudioDeviceDescription> mOutputDevice;
aidl::android::media::audio::common::AudioMode mMode;
aidl::android::media::audio::common::AudioSource mSource;
Parameter::VolumeStereo mVolumeStereo;
size_t mInputChannelCount;
size_t mOutputChannelCount;
Parameter::Common mCommon = {};
std::vector<aidl::android::media::audio::common::AudioDeviceDescription> mOutputDevice = {};
aidl::android::media::audio::common::AudioMode mMode =
aidl::android::media::audio::common::AudioMode::SYS_RESERVED_INVALID;
aidl::android::media::audio::common::AudioSource mSource =
aidl::android::media::audio::common::AudioSource::SYS_RESERVED_INVALID;
Parameter::VolumeStereo mVolumeStereo = {};
RetCode updateIOFrameSize(const Parameter::Common& common);
RetCode notifyDataMqUpdate();
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
// std::shared_ptr<IEffect::OpenEffectReturn> mRet;
// work buffer set by effect instances, the access and update are in same thread
std::vector<float> mWorkBuffer;
::android::hardware::EventFlag* mEfGroup;
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -49,33 +49,54 @@ class EffectImpl : public BnEffect, public EffectThread {
virtual ndk::ScopedAStatus setParameter(const Parameter& param) override;
virtual ndk::ScopedAStatus getParameter(const Parameter::Id& id, Parameter* param) override;
virtual ndk::ScopedAStatus setParameterCommon(const Parameter& param);
virtual ndk::ScopedAStatus getParameterCommon(const Parameter::Tag& tag, Parameter* param);
virtual ndk::ScopedAStatus setParameterCommon(const Parameter& param) REQUIRES(mImplMutex);
virtual ndk::ScopedAStatus getParameterCommon(const Parameter::Tag& tag, Parameter* param)
REQUIRES(mImplMutex);
/* 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 setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) = 0;
virtual ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
Parameter::Specific* specific) = 0;
Parameter::Specific* specific)
REQUIRES(mImplMutex) = 0;
virtual std::string getEffectName() = 0;
virtual IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
virtual std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex);
virtual RetCode releaseContext() REQUIRES(mImplMutex) = 0;
/**
* Effect context methods must be implemented by each effect.
* Each effect can derive from EffectContext and define its own context, but must upcast to
* EffectContext for EffectImpl to use.
* @brief effectProcessImpl is running in worker thread which created in EffectThread.
*
* EffectThread will make sure effectProcessImpl only be called after startThread() successful
* and before stopThread() successful.
*
* effectProcessImpl implementation must not call any EffectThread interface, otherwise it will
* cause deadlock.
*
* @param in address of input float buffer.
* @param out address of output float buffer.
* @param samples number of samples to process.
* @return IEffect::Status
*/
virtual std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) = 0;
virtual std::shared_ptr<EffectContext> getContext() = 0;
virtual RetCode releaseContext() = 0;
virtual IEffect::Status effectProcessImpl(float* in, float* out, int samples) = 0;
/**
* process() get data from data MQs, and call effectProcessImpl() for effect data processing.
* Its important for the implementation to use mImplMutex for context synchronization.
*/
void process() override;
protected:
State mState = State::INIT;
State mState GUARDED_BY(mImplMutex) = State::INIT;
IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
void cleanUp();
std::mutex mImplMutex;
std::shared_ptr<EffectContext> mImplContext GUARDED_BY(mImplMutex);
/**
* Optional CommandId handling methods for effects to override.
* For CommandId::START, EffectImpl call commandImpl before starting the EffectThread
@@ -83,6 +104,9 @@ class EffectImpl : public BnEffect, public EffectThread {
* For CommandId::STOP and CommandId::RESET, EffectImpl call commandImpl after stop the
* EffectThread processing.
*/
virtual ndk::ScopedAStatus commandImpl(CommandId id);
virtual ndk::ScopedAStatus commandImpl(CommandId id) REQUIRES(mImplMutex);
RetCode notifyEventFlag(uint32_t flag);
::android::hardware::EventFlag* mEventFlag;
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -36,8 +36,7 @@ class EffectThread {
virtual ~EffectThread();
// called by effect implementation.
RetCode createThread(std::shared_ptr<EffectContext> context, const std::string& name,
int priority = ANDROID_PRIORITY_URGENT_AUDIO);
RetCode createThread(const std::string& name, int priority = ANDROID_PRIORITY_URGENT_AUDIO);
RetCode destroyThread();
RetCode startThread();
RetCode stopThread();
@@ -45,33 +44,12 @@ class EffectThread {
// Will call process() in a loop if the thread is running.
void threadLoop();
/**
* @brief effectProcessImpl is running in worker thread which created in EffectThread.
*
* Effect implementation should think about concurrency in the implementation if necessary.
* Parameter setting usually implemented in context (derived from EffectContext), and some
* parameter maybe used in the processing, then effect implementation should consider using a
* mutex to protect these parameter.
*
* EffectThread will make sure effectProcessImpl only be called after startThread() successful
* and before stopThread() successful.
*
* effectProcessImpl implementation must not call any EffectThread interface, otherwise it will
* cause deadlock.
*
* @param in address of input float buffer.
* @param out address of output float buffer.
* @param samples number of samples to process.
* @return IEffect::Status
*/
virtual IEffect::Status effectProcessImpl(float* in, float* out, int samples) = 0;
/**
* process() call effectProcessImpl() for effect data processing, it is necessary for the
* processing to be called under Effect thread mutex mThreadMutex, to avoid the effect state
* change before/during data processing, and keep the thread and effect state consistent.
*/
virtual void process_l() REQUIRES(mThreadMutex);
virtual void process() = 0;
private:
static constexpr int kMaxTaskNameLen = 15;
@@ -80,16 +58,7 @@ class EffectThread {
std::condition_variable mCv;
bool mStop GUARDED_BY(mThreadMutex) = true;
bool mExit GUARDED_BY(mThreadMutex) = false;
std::shared_ptr<EffectContext> mThreadContext GUARDED_BY(mThreadMutex);
struct EventFlagDeleter {
void operator()(::android::hardware::EventFlag* flag) const {
if (flag) {
::android::hardware::EventFlag::deleteEventFlag(&flag);
}
}
};
std::unique_ptr<::android::hardware::EventFlag, EventFlagDeleter> mEfGroup;
std::thread mThread;
int mPriority;
std::string mName;

View File

@@ -46,7 +46,8 @@ enum class RetCode {
ERROR_NULL_POINTER, /* NULL pointer */
ERROR_ALIGNMENT_ERROR, /* Memory alignment error */
ERROR_BLOCK_SIZE_EXCEED, /* Maximum block size exceeded */
ERROR_EFFECT_LIB_ERROR
ERROR_EFFECT_LIB_ERROR, /* Effect implementation library error */
ERROR_EVENT_FLAG_ERROR /* Error with effect event flags */
};
static const int INVALID_AUDIO_SESSION_ID = -1;
@@ -67,6 +68,8 @@ inline std::ostream& operator<<(std::ostream& out, const RetCode& code) {
return out << "ERROR_BLOCK_SIZE_EXCEED";
case RetCode::ERROR_EFFECT_LIB_ERROR:
return out << "ERROR_EFFECT_LIB_ERROR";
case RetCode::ERROR_EVENT_FLAG_ERROR:
return out << "ERROR_EVENT_FLAG_ERROR";
}
return out << "EnumError: " << code;

View File

@@ -147,10 +147,6 @@ std::shared_ptr<EffectContext> LoudnessEnhancerSw::createContext(const Parameter
return mContext;
}
std::shared_ptr<EffectContext> LoudnessEnhancerSw::getContext() {
return mContext;
}
RetCode LoudnessEnhancerSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -54,20 +54,23 @@ class LoudnessEnhancerSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; }
private:
std::shared_ptr<LoudnessEnhancerSwContext> mContext;
std::shared_ptr<LoudnessEnhancerSwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterLoudnessEnhancer(const LoudnessEnhancer::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific)
REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -155,10 +155,6 @@ std::shared_ptr<EffectContext> NoiseSuppressionSw::createContext(const Parameter
return mContext;
}
std::shared_ptr<EffectContext> NoiseSuppressionSw::getContext() {
return mContext;
}
RetCode NoiseSuppressionSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -55,20 +55,23 @@ class NoiseSuppressionSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; };
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
private:
std::shared_ptr<NoiseSuppressionSwContext> mContext;
std::shared_ptr<NoiseSuppressionSwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterNoiseSuppression(const NoiseSuppression::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific)
REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -161,10 +161,6 @@ std::shared_ptr<EffectContext> PresetReverbSw::createContext(const Parameter::Co
return mContext;
}
std::shared_ptr<EffectContext> PresetReverbSw::getContext() {
return mContext;
}
RetCode PresetReverbSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -56,21 +56,23 @@ class PresetReverbSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; }
private:
std::shared_ptr<PresetReverbSwContext> mContext;
std::shared_ptr<PresetReverbSwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterPresetReverb(const PresetReverb::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific) REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -141,10 +141,6 @@ std::shared_ptr<EffectContext> SpatializerSw::createContext(const Parameter::Com
return mContext;
}
std::shared_ptr<EffectContext> SpatializerSw::getContext() {
return mContext;
}
RetCode SpatializerSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -50,19 +50,21 @@ class SpatializerSw final : public EffectImpl {
~SpatializerSw();
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; };
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
private:
static const std::vector<Range::SpatializerRange> kRanges;
std::shared_ptr<SpatializerSwContext> mContext = nullptr;
std::shared_ptr<SpatializerSwContext> mContext GUARDED_BY(mImplMutex) = nullptr;
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -203,10 +203,6 @@ std::shared_ptr<EffectContext> VirtualizerSw::createContext(const Parameter::Com
return mContext;
}
std::shared_ptr<EffectContext> VirtualizerSw::getContext() {
return mContext;
}
RetCode VirtualizerSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -59,24 +59,25 @@ class VirtualizerSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
std::string getEffectName() override { return kEffectName; }
private:
static const std::vector<Range::VirtualizerRange> kRanges;
std::shared_ptr<VirtualizerSwContext> mContext;
std::shared_ptr<VirtualizerSwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterVirtualizer(const Virtualizer::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific) REQUIRES(mImplMutex);
ndk::ScopedAStatus getSpeakerAngles(const Virtualizer::SpeakerAnglesPayload payload,
Parameter::Specific* specific);
Parameter::Specific* specific) REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -190,10 +190,6 @@ std::shared_ptr<EffectContext> VisualizerSw::createContext(const Parameter::Comm
return mContext;
}
std::shared_ptr<EffectContext> VisualizerSw::getContext() {
return mContext;
}
RetCode VisualizerSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -72,21 +72,23 @@ class VisualizerSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; }
private:
static const std::vector<Range::VisualizerRange> kRanges;
std::shared_ptr<VisualizerSwContext> mContext;
std::shared_ptr<VisualizerSwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag,
Parameter::Specific* specific);
Parameter::Specific* specific) REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -160,10 +160,6 @@ std::shared_ptr<EffectContext> VolumeSw::createContext(const Parameter::Common&
return mContext;
}
std::shared_ptr<EffectContext> VolumeSw::getContext() {
return mContext;
}
RetCode VolumeSw::releaseContext() {
if (mContext) {
mContext.reset();

View File

@@ -57,21 +57,24 @@ class VolumeSw final : public EffectImpl {
}
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;
ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific)
REQUIRES(mImplMutex) override;
ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific)
REQUIRES(mImplMutex) override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
std::shared_ptr<EffectContext> getContext() override;
RetCode releaseContext() override;
std::shared_ptr<EffectContext> createContext(const Parameter::Common& common)
REQUIRES(mImplMutex) override;
RetCode releaseContext() REQUIRES(mImplMutex) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples) override;
IEffect::Status effectProcessImpl(float* in, float* out, int samples)
REQUIRES(mImplMutex) override;
std::string getEffectName() override { return kEffectName; }
private:
static const std::vector<Range::VolumeRange> kRanges;
std::shared_ptr<VolumeSwContext> mContext;
std::shared_ptr<VolumeSwContext> mContext GUARDED_BY(mImplMutex);
ndk::ScopedAStatus getParameterVolume(const Volume::Tag& tag, Parameter::Specific* specific);
ndk::ScopedAStatus getParameterVolume(const Volume::Tag& tag, Parameter::Specific* specific)
REQUIRES(mImplMutex);
};
} // namespace aidl::android::hardware::audio::effect

View File

@@ -43,6 +43,7 @@ using namespace android;
using aidl::android::hardware::audio::effect::CommandId;
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::kEventFlagDataMqUpdate;
using aidl::android::hardware::audio::effect::kEventFlagNotEmpty;
using aidl::android::hardware::audio::effect::Parameter;
using aidl::android::hardware::audio::effect::Range;
@@ -191,6 +192,16 @@ class EffectHelper {
ASSERT_TRUE(dataMq->read(buffer.data(), expectFloats));
}
}
static void expectDataMqUpdateEventFlag(std::unique_ptr<StatusMQ>& statusMq) {
EventFlag* efGroup;
ASSERT_EQ(::android::OK,
EventFlag::createEventFlag(statusMq->getEventFlagWord(), &efGroup));
ASSERT_NE(nullptr, efGroup);
uint32_t efState = 0;
EXPECT_EQ(::android::OK, efGroup->wait(kEventFlagDataMqUpdate, &efState, 1'000'000 /*1ms*/,
true /* retry */));
EXPECT_TRUE(efState & kEventFlagDataMqUpdate);
}
static Parameter::Common createParamCommon(
int session = 0, int ioHandle = -1, int iSampleRate = 48000, int oSampleRate = 48000,
long iFrameCount = 0x100, long oFrameCount = 0x100,

View File

@@ -609,6 +609,49 @@ TEST_P(AudioEffectTest, SetAndGetParameterVolume) {
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Verify Parameters kept after reset.
TEST_P(AudioEffectTest, SetCommonParameterAndReopen) {
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
IEffect::OpenEffectReturn ret;
ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
ASSERT_TRUE(outputMQ->isValid());
Parameter::Id id = Parameter::Id::make<Parameter::Id::commonTag>(Parameter::common);
common.input.frameCount++;
ASSERT_NO_FATAL_FAILURE(setAndGetParameter(id, Parameter::make<Parameter::common>(common)));
ASSERT_TRUE(statusMQ->isValid());
expectDataMqUpdateEventFlag(statusMQ);
EXPECT_IS_OK(mEffect->reopen(&ret));
inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
ASSERT_TRUE(statusMQ->isValid());
ASSERT_TRUE(inputMQ->isValid());
ASSERT_TRUE(outputMQ->isValid());
common.output.frameCount++;
ASSERT_NO_FATAL_FAILURE(setAndGetParameter(id, Parameter::make<Parameter::common>(common)));
ASSERT_TRUE(statusMQ->isValid());
expectDataMqUpdateEventFlag(statusMQ);
EXPECT_IS_OK(mEffect->reopen(&ret));
inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
ASSERT_TRUE(statusMQ->isValid());
ASSERT_TRUE(inputMQ->isValid());
ASSERT_TRUE(outputMQ->isValid());
ASSERT_NO_FATAL_FAILURE(close(mEffect));
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
/// Data processing test
// Send data to effects and expect it to be consumed by checking statusMQ.
// Effects exposing bypass flags or operating in offload mode will be skipped.
@@ -684,6 +727,59 @@ TEST_P(AudioEffectDataPathTest, ConsumeDataAfterRestart) {
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data to effects and expect it to be consumed after effect reopen (IO AudioConfig change).
// Effects exposing bypass flags or operating in offload mode will be skipped.
TEST_P(AudioEffectDataPathTest, ConsumeDataAfterReopen) {
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
IEffect::OpenEffectReturn ret;
ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt /* specific */, &ret, EX_NONE));
auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
ASSERT_TRUE(statusMQ->isValid());
auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
ASSERT_TRUE(inputMQ->isValid());
auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
ASSERT_TRUE(outputMQ->isValid());
std::vector<float> buffer;
ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::START));
ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::PROCESSING));
EXPECT_NO_FATAL_FAILURE(EffectHelper::allocateInputData(common, inputMQ, buffer));
EXPECT_NO_FATAL_FAILURE(EffectHelper::writeToFmq(statusMQ, inputMQ, buffer));
EXPECT_NO_FATAL_FAILURE(
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer));
// set a new common parameter with different IO frameCount, reopen
Parameter::Id id = Parameter::Id::make<Parameter::Id::commonTag>(Parameter::common);
common.input.frameCount += 4;
common.output.frameCount += 4;
ASSERT_NO_FATAL_FAILURE(setAndGetParameter(id, Parameter::make<Parameter::common>(common)));
ASSERT_TRUE(statusMQ->isValid());
expectDataMqUpdateEventFlag(statusMQ);
EXPECT_IS_OK(mEffect->reopen(&ret));
inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
ASSERT_TRUE(statusMQ->isValid());
ASSERT_TRUE(inputMQ->isValid());
ASSERT_TRUE(outputMQ->isValid());
// verify data consume again
EXPECT_NO_FATAL_FAILURE(EffectHelper::allocateInputData(common, inputMQ, buffer));
EXPECT_NO_FATAL_FAILURE(EffectHelper::writeToFmq(statusMQ, inputMQ, buffer));
EXPECT_NO_FATAL_FAILURE(
EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer));
ASSERT_NO_FATAL_FAILURE(command(mEffect, CommandId::STOP));
ASSERT_NO_FATAL_FAILURE(expectState(mEffect, State::IDLE));
EXPECT_NO_FATAL_FAILURE(EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer));
ASSERT_NO_FATAL_FAILURE(close(mEffect));
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
// Send data to IDLE effects and expect it to be consumed after effect start.
// Effects exposing bypass flags or operating in offload mode will be skipped.
TEST_P(AudioEffectDataPathTest, SendDataAtIdleAndConsumeDataInProcessing) {