audiohal: Re-implement effect process using FMQ and IMemory
Result: no hwbinder calls due music processing.
Added IEffect.close method for explicitly freeing up of resources
consumed by the effect before automatic server objects reaping
gets to it.
Added IEffect.setProcessBuffers method for updating the input /
output buffers on the go.
Test: make, use Play Music with effects, check traces
Bug: 30222631
Change-Id: Ia1e1bc7098fab59aa970e0ce4acdb48007409644
diff --git a/audio/effect/2.0/IEffect.hal b/audio/effect/2.0/IEffect.hal
index 615a460..9027c68 100644
--- a/audio/effect/2.0/IEffect.hal
+++ b/audio/effect/2.0/IEffect.hal
@@ -226,49 +226,47 @@
getDescriptor() generates (Result retval, EffectDescriptor descriptor);
/*
- * Effect process function. Takes input samples as specified (count and
- * location) in input buffer and returns processed samples as specified in
- * output buffer. If the buffer descriptor is empty the function must use
- * either the buffer or the buffer provider callback installed by the
- * setConfig command. The effect framework must call the 'process' function
- * after the 'enable' command is received and until the 'disable' is
- * received. When the engine receives the 'disable' command it should turn
- * off the effect gracefully and when done indicate that it is OK to stop
- * calling the 'process' function by returning the INVALID_STATE status.
+ * Set up required transports for passing audio buffers to the effect.
*
- * Output audio buffer must contain no more frames than the input audio
- * buffer. Since the effect may transform input channels into a different
- * amount of channels, the caller provides the output frame size.
+ * The transport consists of shared memory and a message queue for reporting
+ * effect processing operation status. The shared memory is set up
+ * separately using 'setProcessBuffers' method.
*
- * @param inBuffer input audio buffer.
- * @param outFrameSize output frame size in bytes.
- * @return retval operation completion status.
- * @return outBuffer output audio buffer.
+ * Processing is requested by setting 'REQUEST_PROCESS' or
+ * 'REQUEST_PROCESS_REVERSE' EventFlags associated with the status message
+ * queue. The result of processing may be one of the following:
+ * OK if there were no errors during processing;
+ * INVALID_ARGUMENTS if audio buffers are invalid;
+ * INVALID_STATE if the engine has finished the disable phase;
+ * NOT_INITIALIZED if the audio buffers were not set;
+ * NOT_SUPPORTED if the requested processing type is not supported by
+ * the effect.
+ *
+ * @return retval OK if both message queues were created successfully.
+ * INVALID_STATE if the method was already called.
+ * INVALID_ARGUMENTS if there was a problem setting up
+ * the queue.
+ * @return statusMQ a message queue used for passing status from the effect.
*/
- // TODO(mnaganov): replace with FMQ version.
- @callflow(next={"*"})
- process(AudioBuffer inBuffer, uint32_t outFrameSize)
- generates (Result retval, AudioBuffer outBuffer);
+ prepareForProcessing() generates (Result retval, fmq_sync<Result> statusMQ);
/*
- * Process reverse stream function. This function is used to pass a
- * reference stream to the effect engine. If the engine does not need a
- * reference stream, this function MUST return NOT_SUPPORTED. For example,
- * this function would typically implemented by an Echo Canceler.
+ * Set up input and output buffers for processing audio data. The effect
+ * may modify both the input and the output buffer during the operation.
+ * Buffers may be set multiple times during effect lifetime.
*
- * Output audio buffer must contain no more frames than the input audio
- * buffer. Since the effect may transform input channels into a different
- * amount of channels, the caller provides the output frame size.
+ * The input and the output buffer may be reused between different effects,
+ * and the input buffer may be used as an output buffer. Buffers are
+ * distinguished using 'AudioBuffer.id' field.
*
* @param inBuffer input audio buffer.
- * @param outFrameSize output frame size in bytes.
- * @return retval operation completion status.
- * @return outBuffer output audio buffer.
+ * @param outBuffer output audio buffer.
+ * @return retval OK if both buffers were mapped successfully.
+ * INVALID_ARGUMENTS if there was a problem with mapping
+ * any of the buffers.
*/
- // TODO(mnaganov): replace with FMQ version.
- @callflow(next={"*"})
- processReverse(AudioBuffer inBuffer, uint32_t outFrameSize)
- generates (Result retval, AudioBuffer outBuffer);
+ setProcessBuffers(AudioBuffer inBuffer, AudioBuffer outBuffer) generates (
+ Result retval);
/*
* Execute a vendor specific command on the effect. The command code
@@ -406,4 +404,14 @@
*/
setCurrentConfigForFeature(uint32_t featureId, vec<uint8_t> configData)
generates (Result retval);
+
+ /*
+ * Called by the framework to deinitialize the effect and free up
+ * all the currently allocated resources. It is recommended to close
+ * the effect on the client side as soon as it is becomes unused.
+ *
+ * @return retval OK in case the success.
+ * INVALID_STATE if the effect was already closed.
+ */
+ close() generates (Result retval);
};
diff --git a/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp b/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp
index 341466f..f6e72bf 100644
--- a/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp
+++ b/audio/effect/2.0/default/AcousticEchoCancelerEffect.cpp
@@ -115,16 +115,14 @@
return mEffect->getDescriptor(_hidl_cb);
}
-Return<void> AcousticEchoCancelerEffect::process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
- return mEffect->process(inBuffer, outFrameSize, _hidl_cb);
+Return<void> AcousticEchoCancelerEffect::prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) {
+ return mEffect->prepareForProcessing(_hidl_cb);
}
-Return<void> AcousticEchoCancelerEffect::processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) {
- return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb);
+Return<Result> AcousticEchoCancelerEffect::setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
Return<void> AcousticEchoCancelerEffect::command(
@@ -167,6 +165,10 @@
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
+Return<Result> AcousticEchoCancelerEffect::close() {
+ return mEffect->close();
+}
+
// Methods from ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect follow.
Return<Result> AcousticEchoCancelerEffect::setEchoDelay(uint32_t echoDelayMs) {
return mEffect->setParam(AEC_PARAM_ECHO_DELAY, echoDelayMs);
diff --git a/audio/effect/2.0/default/AcousticEchoCancelerEffect.h b/audio/effect/2.0/default/AcousticEchoCancelerEffect.h
index 71fcc97..c777b02 100644
--- a/audio/effect/2.0/default/AcousticEchoCancelerEffect.h
+++ b/audio/effect/2.0/default/AcousticEchoCancelerEffect.h
@@ -69,12 +69,9 @@
Return<Result> setAudioSource(AudioSource source) override;
Return<Result> offload(const EffectOffloadParameter& param) override;
Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
- Return<void> process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override;
- Return<void> processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) override;
+ Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+ Return<Result> setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override;
Return<void> command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -97,6 +94,7 @@
getCurrentConfigForFeature_cb _hidl_cb) override;
Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const hidl_vec<uint8_t>& configData) override;
+ Return<Result> close() override;
// Methods from ::android::hardware::audio::effect::V2_0::IAcousticEchoCancelerEffect follow.
Return<Result> setEchoDelay(uint32_t echoDelayMs) override;
diff --git a/audio/effect/2.0/default/Android.mk b/audio/effect/2.0/default/Android.mk
index 9b99737..18076ed 100644
--- a/audio/effect/2.0/default/Android.mk
+++ b/audio/effect/2.0/default/Android.mk
@@ -5,6 +5,7 @@
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := \
AcousticEchoCancelerEffect.cpp \
+ AudioBufferManager.cpp \
AutomaticGainControlEffect.cpp \
BassBoostEffect.cpp \
Conversions.cpp \
@@ -20,14 +21,19 @@
VisualizerEffect.cpp \
LOCAL_SHARED_LIBRARIES := \
+ libbase \
+ libcutils \
+ libeffects \
+ libfmq \
libhidlbase \
+ libhidlmemory \
libhidltransport \
libhwbinder \
- libutils \
- libeffects \
liblog \
+ libutils \
android.hardware.audio.common@2.0 \
android.hardware.audio.common@2.0-util \
android.hardware.audio.effect@2.0 \
+ android.hidl.memory@1.0 \
include $(BUILD_SHARED_LIBRARY)
diff --git a/audio/effect/2.0/default/AudioBufferManager.cpp b/audio/effect/2.0/default/AudioBufferManager.cpp
new file mode 100644
index 0000000..603dbb8
--- /dev/null
+++ b/audio/effect/2.0/default/AudioBufferManager.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2017 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 <atomic>
+
+#include <hidlmemory/mapping.h>
+
+#include "AudioBufferManager.h"
+
+namespace android {
+
+ANDROID_SINGLETON_STATIC_INSTANCE(AudioBufferManager);
+
+bool AudioBufferManager::wrap(const AudioBuffer& buffer, sp<AudioBufferWrapper>* wrapper) {
+ // Check if we have this buffer already
+ std::lock_guard<std::mutex> lock(mLock);
+ ssize_t idx = mBuffers.indexOfKey(buffer.id);
+ if (idx >= 0) {
+ *wrapper = mBuffers[idx].promote();
+ if (*wrapper != nullptr) return true;
+ mBuffers.removeItemsAt(idx);
+ }
+ // Need to create and init a new AudioBufferWrapper.
+ sp<AudioBufferWrapper> tempBuffer(new AudioBufferWrapper(buffer));
+ if (!tempBuffer->init()) return false;
+ *wrapper = tempBuffer;
+ mBuffers.add(buffer.id, *wrapper);
+ return true;
+}
+
+void AudioBufferManager::removeEntry(uint64_t id) {
+ std::lock_guard<std::mutex> lock(mLock);
+ ssize_t idx = mBuffers.indexOfKey(id);
+ if (idx >= 0) mBuffers.removeItemsAt(idx);
+}
+
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+AudioBufferWrapper::AudioBufferWrapper(const AudioBuffer& buffer) :
+ mHidlBuffer(buffer), mHalBuffer{ 0, { nullptr } } {
+}
+
+AudioBufferWrapper::~AudioBufferWrapper() {
+ AudioBufferManager::getInstance().removeEntry(mHidlBuffer.id);
+}
+
+bool AudioBufferWrapper::init() {
+ if (mHalBuffer.raw != nullptr) {
+ ALOGE("An attempt to init AudioBufferWrapper twice");
+ return false;
+ }
+ mHidlMemory = mapMemory(mHidlBuffer.data);
+ if (mHidlMemory == nullptr) {
+ ALOGE("Could not map HIDL memory to IMemory");
+ return false;
+ }
+ mHalBuffer.raw = static_cast<void*>(mHidlMemory->getPointer());
+ if (mHalBuffer.raw == nullptr) {
+ ALOGE("IMemory buffer pointer is null");
+ return false;
+ }
+ mHalBuffer.frameCount = mHidlBuffer.frameCount;
+ return true;
+}
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace effect
+} // namespace audio
+} // namespace hardware
+} // namespace android
diff --git a/audio/effect/2.0/default/AudioBufferManager.h b/audio/effect/2.0/default/AudioBufferManager.h
new file mode 100644
index 0000000..6d65995
--- /dev/null
+++ b/audio/effect/2.0/default/AudioBufferManager.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+#ifndef android_hardware_audio_effect_V2_0_AudioBufferManager_H_
+#define android_hardware_audio_effect_V2_0_AudioBufferManager_H_
+
+#include <mutex>
+
+#include <android/hardware/audio/effect/2.0/types.h>
+#include <android/hidl/memory/1.0/IMemory.h>
+#include <system/audio_effect.h>
+#include <utils/RefBase.h>
+#include <utils/KeyedVector.h>
+#include <utils/Singleton.h>
+
+using ::android::hardware::audio::effect::V2_0::AudioBuffer;
+using ::android::hidl::memory::V1_0::IMemory;
+
+namespace android {
+namespace hardware {
+namespace audio {
+namespace effect {
+namespace V2_0 {
+namespace implementation {
+
+class AudioBufferWrapper : public RefBase {
+ public:
+ explicit AudioBufferWrapper(const AudioBuffer& buffer);
+ virtual ~AudioBufferWrapper();
+ bool init();
+ audio_buffer_t* getHalBuffer() { return &mHalBuffer; }
+ private:
+ AudioBufferWrapper(const AudioBufferWrapper&) = delete;
+ void operator=(AudioBufferWrapper) = delete;
+
+ AudioBuffer mHidlBuffer;
+ sp<IMemory> mHidlMemory;
+ audio_buffer_t mHalBuffer;
+};
+
+} // namespace implementation
+} // namespace V2_0
+} // namespace effect
+} // namespace audio
+} // namespace hardware
+} // namespace android
+
+using ::android::hardware::audio::effect::V2_0::implementation::AudioBufferWrapper;
+
+namespace android {
+
+// This class needs to be in 'android' ns because Singleton macros require that.
+class AudioBufferManager : public Singleton<AudioBufferManager> {
+ public:
+ bool wrap(const AudioBuffer& buffer, sp<AudioBufferWrapper>* wrapper);
+
+ private:
+ friend class hardware::audio::effect::V2_0::implementation::AudioBufferWrapper;
+
+ // Called by AudioBufferWrapper.
+ void removeEntry(uint64_t id);
+
+ std::mutex mLock;
+ KeyedVector<uint64_t, wp<AudioBufferWrapper>> mBuffers;
+};
+
+} // namespace android
+
+#endif // android_hardware_audio_effect_V2_0_AudioBufferManager_H_
diff --git a/audio/effect/2.0/default/AutomaticGainControlEffect.cpp b/audio/effect/2.0/default/AutomaticGainControlEffect.cpp
index 6ebfb3c..2c386d3 100644
--- a/audio/effect/2.0/default/AutomaticGainControlEffect.cpp
+++ b/audio/effect/2.0/default/AutomaticGainControlEffect.cpp
@@ -130,16 +130,14 @@
return mEffect->getDescriptor(_hidl_cb);
}
-Return<void> AutomaticGainControlEffect::process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
- return mEffect->process(inBuffer, outFrameSize, _hidl_cb);
+Return<void> AutomaticGainControlEffect::prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) {
+ return mEffect->prepareForProcessing(_hidl_cb);
}
-Return<void> AutomaticGainControlEffect::processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) {
- return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb);
+Return<Result> AutomaticGainControlEffect::setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
Return<void> AutomaticGainControlEffect::command(
@@ -182,6 +180,10 @@
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
+Return<Result> AutomaticGainControlEffect::close() {
+ return mEffect->close();
+}
+
// Methods from ::android::hardware::audio::effect::V2_0::IAutomaticGainControlEffect follow.
Return<Result> AutomaticGainControlEffect::setTargetLevel(int16_t targetLevelMb) {
return mEffect->setParam(AGC_PARAM_TARGET_LEVEL, targetLevelMb);
diff --git a/audio/effect/2.0/default/AutomaticGainControlEffect.h b/audio/effect/2.0/default/AutomaticGainControlEffect.h
index 1696d3c..73d94a5 100644
--- a/audio/effect/2.0/default/AutomaticGainControlEffect.h
+++ b/audio/effect/2.0/default/AutomaticGainControlEffect.h
@@ -71,12 +71,9 @@
Return<Result> setAudioSource(AudioSource source) override;
Return<Result> offload(const EffectOffloadParameter& param) override;
Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
- Return<void> process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override;
- Return<void> processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) override;
+ Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+ Return<Result> setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override;
Return<void> command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -99,6 +96,7 @@
getCurrentConfigForFeature_cb _hidl_cb) override;
Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const hidl_vec<uint8_t>& configData) override;
+ Return<Result> close() override;
// Methods from ::android::hardware::audio::effect::V2_0::IAutomaticGainControlEffect follow.
Return<Result> setTargetLevel(int16_t targetLevelMb) override;
diff --git a/audio/effect/2.0/default/BassBoostEffect.cpp b/audio/effect/2.0/default/BassBoostEffect.cpp
index 8a64806..4120e6e 100644
--- a/audio/effect/2.0/default/BassBoostEffect.cpp
+++ b/audio/effect/2.0/default/BassBoostEffect.cpp
@@ -115,16 +115,14 @@
return mEffect->getDescriptor(_hidl_cb);
}
-Return<void> BassBoostEffect::process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
- return mEffect->process(inBuffer, outFrameSize, _hidl_cb);
+Return<void> BassBoostEffect::prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) {
+ return mEffect->prepareForProcessing(_hidl_cb);
}
-Return<void> BassBoostEffect::processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) {
- return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb);
+Return<Result> BassBoostEffect::setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
Return<void> BassBoostEffect::command(
@@ -167,6 +165,10 @@
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
+Return<Result> BassBoostEffect::close() {
+ return mEffect->close();
+}
+
// Methods from ::android::hardware::audio::effect::V2_0::IBassBoostEffect follow.
Return<void> BassBoostEffect::isStrengthSupported(isStrengthSupported_cb _hidl_cb) {
return mEffect->getIntegerParam(BASSBOOST_PARAM_STRENGTH_SUPPORTED, _hidl_cb);
diff --git a/audio/effect/2.0/default/BassBoostEffect.h b/audio/effect/2.0/default/BassBoostEffect.h
index 6636717..1861937 100644
--- a/audio/effect/2.0/default/BassBoostEffect.h
+++ b/audio/effect/2.0/default/BassBoostEffect.h
@@ -69,12 +69,9 @@
Return<Result> setAudioSource(AudioSource source) override;
Return<Result> offload(const EffectOffloadParameter& param) override;
Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
- Return<void> process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override;
- Return<void> processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) override;
+ Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+ Return<Result> setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override;
Return<void> command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -97,6 +94,7 @@
getCurrentConfigForFeature_cb _hidl_cb) override;
Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const hidl_vec<uint8_t>& configData) override;
+ Return<Result> close() override;
// Methods from ::android::hardware::audio::effect::V2_0::IBassBoostEffect follow.
Return<void> isStrengthSupported(isStrengthSupported_cb _hidl_cb) override;
diff --git a/audio/effect/2.0/default/DownmixEffect.cpp b/audio/effect/2.0/default/DownmixEffect.cpp
index 40bb5ec..41497d0 100644
--- a/audio/effect/2.0/default/DownmixEffect.cpp
+++ b/audio/effect/2.0/default/DownmixEffect.cpp
@@ -115,16 +115,14 @@
return mEffect->getDescriptor(_hidl_cb);
}
-Return<void> DownmixEffect::process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
- return mEffect->process(inBuffer, outFrameSize, _hidl_cb);
+Return<void> DownmixEffect::prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) {
+ return mEffect->prepareForProcessing(_hidl_cb);
}
-Return<void> DownmixEffect::processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) {
- return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb);
+Return<Result> DownmixEffect::setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
Return<void> DownmixEffect::command(
@@ -167,6 +165,10 @@
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
+Return<Result> DownmixEffect::close() {
+ return mEffect->close();
+}
+
// Methods from ::android::hardware::audio::effect::V2_0::IDownmixEffect follow.
Return<Result> DownmixEffect::setType(IDownmixEffect::Type preset) {
return mEffect->setParam(DOWNMIX_PARAM_TYPE, static_cast<downmix_type_t>(preset));
diff --git a/audio/effect/2.0/default/DownmixEffect.h b/audio/effect/2.0/default/DownmixEffect.h
index c7e1b9b..1d4c3a9 100644
--- a/audio/effect/2.0/default/DownmixEffect.h
+++ b/audio/effect/2.0/default/DownmixEffect.h
@@ -69,12 +69,9 @@
Return<Result> setAudioSource(AudioSource source) override;
Return<Result> offload(const EffectOffloadParameter& param) override;
Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
- Return<void> process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override;
- Return<void> processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) override;
+ Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+ Return<Result> setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override;
Return<void> command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -97,6 +94,7 @@
getCurrentConfigForFeature_cb _hidl_cb) override;
Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const hidl_vec<uint8_t>& configData) override;
+ Return<Result> close() override;
// Methods from ::android::hardware::audio::effect::V2_0::IDownmixEffect follow.
Return<Result> setType(IDownmixEffect::Type preset) override;
diff --git a/audio/effect/2.0/default/Effect.cpp b/audio/effect/2.0/default/Effect.cpp
index 1a7ea9c..9ca5834 100644
--- a/audio/effect/2.0/default/Effect.cpp
+++ b/audio/effect/2.0/default/Effect.cpp
@@ -17,8 +17,8 @@
#include <memory.h>
#define LOG_TAG "EffectHAL"
-#include <media/EffectsFactoryApi.h>
#include <android/log.h>
+#include <media/EffectsFactoryApi.h>
#include "Conversions.h"
#include "Effect.h"
@@ -33,20 +33,108 @@
using ::android::hardware::audio::common::V2_0::AudioChannelMask;
using ::android::hardware::audio::common::V2_0::AudioFormat;
+using ::android::hardware::audio::effect::V2_0::MessageQueueFlagBits;
+
+namespace {
+
+class ProcessThread : public Thread {
+ public:
+ // ProcessThread's lifespan never exceeds Effect's lifespan.
+ ProcessThread(std::atomic<bool>* stop,
+ effect_handle_t effect,
+ std::atomic<audio_buffer_t*>* inBuffer,
+ std::atomic<audio_buffer_t*>* outBuffer,
+ Effect::StatusMQ* statusMQ,
+ EventFlag* efGroup)
+ : Thread(false /*canCallJava*/),
+ mStop(stop),
+ mEffect(effect),
+ mHasProcessReverse((*mEffect)->process_reverse != NULL),
+ mInBuffer(inBuffer),
+ mOutBuffer(outBuffer),
+ mStatusMQ(statusMQ),
+ mEfGroup(efGroup) {
+ }
+ virtual ~ProcessThread() {}
+
+ private:
+ std::atomic<bool>* mStop;
+ effect_handle_t mEffect;
+ bool mHasProcessReverse;
+ std::atomic<audio_buffer_t*>* mInBuffer;
+ std::atomic<audio_buffer_t*>* mOutBuffer;
+ Effect::StatusMQ* mStatusMQ;
+ EventFlag* mEfGroup;
+
+ bool threadLoop() override;
+};
+
+bool ProcessThread::threadLoop() {
+ // This implementation doesn't return control back to the Thread until it decides to stop,
+ // as the Thread uses mutexes, and this can lead to priority inversion.
+ while(!std::atomic_load_explicit(mStop, std::memory_order_acquire)) {
+ uint32_t efState = 0;
+ mEfGroup->wait(
+ static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL),
+ &efState,
+ NS_PER_SEC);
+ if (!(efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_ALL))) {
+ continue; // Nothing to do.
+ }
+ Result retval = Result::OK;
+ if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS_REVERSE)
+ && !mHasProcessReverse) {
+ retval = Result::NOT_SUPPORTED;
+ }
+
+ if (retval == Result::OK) {
+ // affects both buffer pointers and their contents.
+ std::atomic_thread_fence(std::memory_order_acquire);
+ int32_t processResult;
+ audio_buffer_t* inBuffer =
+ std::atomic_load_explicit(mInBuffer, std::memory_order_relaxed);
+ audio_buffer_t* outBuffer =
+ std::atomic_load_explicit(mOutBuffer, std::memory_order_relaxed);
+ if (inBuffer != nullptr && outBuffer != nullptr) {
+ if (efState & static_cast<uint32_t>(MessageQueueFlagBits::REQUEST_PROCESS)) {
+ processResult = (*mEffect)->process(mEffect, inBuffer, outBuffer);
+ } else {
+ processResult = (*mEffect)->process_reverse(mEffect, inBuffer, outBuffer);
+ }
+ std::atomic_thread_fence(std::memory_order_release);
+ } else {
+ ALOGE("processing buffers were not set before calling 'process'");
+ processResult = -ENODEV;
+ }
+ switch(processResult) {
+ case 0: retval = Result::OK; break;
+ case -ENODATA: retval = Result::INVALID_STATE; break;
+ case -EINVAL: retval = Result::INVALID_ARGUMENTS; break;
+ default: retval = Result::NOT_INITIALIZED;
+ }
+ }
+ if (!mStatusMQ->write(&retval)) {
+ ALOGW("status message queue write failed");
+ }
+ mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::DONE_PROCESSING));
+ }
+
+ return false;
+}
+
+} // namespace
// static
const char *Effect::sContextResultOfCommand = "returned status";
const char *Effect::sContextCallToCommand = "error";
const char *Effect::sContextCallFunction = sContextCallToCommand;
-Effect::Effect(effect_handle_t handle) : mHandle(handle) {
+Effect::Effect(effect_handle_t handle)
+ : mIsClosed(false), mHandle(handle), mEfGroup(nullptr), mStopProcessThread(false) {
}
Effect::~Effect() {
- int status = EffectRelease(mHandle);
- ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
- EffectMap::getInstance().remove(mHandle);
- mHandle = 0;
+ close();
}
// static
@@ -83,9 +171,6 @@
// static
void Effect::effectBufferConfigFromHal(
const buffer_config_t& halConfig, EffectBufferConfig* config) {
- // TODO(mnaganov): Use FMQ instead of AudioBuffer.
- (void)halConfig.buffer.frameCount;
- (void)halConfig.buffer.raw;
config->samplingRateHz = halConfig.samplingRate;
config->channels = AudioChannelMask(halConfig.channels);
config->format = AudioFormat(halConfig.format);
@@ -95,12 +180,13 @@
// static
void Effect::effectBufferConfigToHal(const EffectBufferConfig& config, buffer_config_t* halConfig) {
- // TODO(mnaganov): Use FMQ instead of AudioBuffer.
+ // Note: setting the buffers directly is considered obsolete. They need to be set
+ // using 'setProcessBuffers'.
halConfig->buffer.frameCount = 0;
halConfig->buffer.raw = NULL;
halConfig->samplingRate = config.samplingRateHz;
halConfig->channels = static_cast<uint32_t>(config.channels);
- // TODO(mnaganov): As the calling code does not use BP for now, implement later.
+ // TODO(mnaganov): The framework code currently does not use BP, implement later.
halConfig->bufferProvider.cookie = NULL;
halConfig->bufferProvider.getBuffer = NULL;
halConfig->bufferProvider.releaseBuffer = NULL;
@@ -250,31 +336,66 @@
});
}
-void Effect::processImpl(
- ProcessFunction process,
- const char* funcName,
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- ProcessCallback cb) {
- audio_buffer_t halInBuffer;
- halInBuffer.frameCount = inBuffer.frameCount;
- halInBuffer.u8 = const_cast<uint8_t*>(&inBuffer.data[0]);
- audio_buffer_t halOutBuffer;
- halOutBuffer.frameCount = halInBuffer.frameCount;
- // TODO(mnaganov): Consider stashing the buffer to avoid reallocating it every time.
- std::unique_ptr<uint8_t[]> halOutBufferData(
- new uint8_t[halOutBuffer.frameCount * outFrameSize]);
- halOutBuffer.u8 = &halOutBufferData[0];
- status_t status = process(mHandle, &halInBuffer, &halOutBuffer);
- Result retval = analyzeStatus(funcName, "", sContextCallFunction, status);
- AudioBuffer outBuffer;
- if (status == OK) {
- outBuffer.frameCount = halOutBuffer.frameCount;
- outBuffer.data.setToExternal(halOutBuffer.u8, halOutBuffer.frameCount * outFrameSize);
- } else {
- outBuffer.frameCount = 0;
+Return<void> Effect::prepareForProcessing(prepareForProcessing_cb _hidl_cb) {
+ status_t status;
+ // Create message queue.
+ if (mStatusMQ) {
+ ALOGE("the client attempts to call prepareForProcessing_cb twice");
+ _hidl_cb(Result::INVALID_STATE, StatusMQ::Descriptor());
+ return Void();
}
- cb(retval, outBuffer);
+ std::unique_ptr<StatusMQ> tempStatusMQ(new StatusMQ(1, true /*EventFlag*/));
+ if (!tempStatusMQ->isValid()) {
+ ALOGE_IF(!tempStatusMQ->isValid(), "status MQ is invalid");
+ _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
+ return Void();
+ }
+ status = EventFlag::createEventFlag(tempStatusMQ->getEventFlagWord(), &mEfGroup);
+ if (status != OK || !mEfGroup) {
+ ALOGE("failed creating event flag for status MQ: %s", strerror(-status));
+ _hidl_cb(Result::INVALID_ARGUMENTS, StatusMQ::Descriptor());
+ return Void();
+ }
+
+ // Create and launch the thread.
+ mProcessThread = new ProcessThread(
+ &mStopProcessThread,
+ mHandle,
+ &mHalInBufferPtr,
+ &mHalOutBufferPtr,
+ tempStatusMQ.get(),
+ mEfGroup);
+ status = mProcessThread->run("effect", PRIORITY_URGENT_AUDIO);
+ if (status != OK) {
+ ALOGW("failed to start effect processing thread: %s", strerror(-status));
+ _hidl_cb(Result::INVALID_ARGUMENTS, MQDescriptorSync<Result>());
+ return Void();
+ }
+
+ mStatusMQ = std::move(tempStatusMQ);
+ _hidl_cb(Result::OK, *mStatusMQ->getDesc());
+ return Void();
+}
+
+Return<Result> Effect::setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+ AudioBufferManager& manager = AudioBufferManager::getInstance();
+ sp<AudioBufferWrapper> tempInBuffer, tempOutBuffer;
+ if (!manager.wrap(inBuffer, &tempInBuffer)) {
+ ALOGE("Could not map memory of the input buffer");
+ return Result::INVALID_ARGUMENTS;
+ }
+ if (!manager.wrap(outBuffer, &tempOutBuffer)) {
+ ALOGE("Could not map memory of the output buffer");
+ return Result::INVALID_ARGUMENTS;
+ }
+ mInBuffer = tempInBuffer;
+ mOutBuffer = tempOutBuffer;
+ // The processing thread only reads these pointers after waking up by an event flag,
+ // so it's OK to update the pair non-atomically.
+ mHalInBufferPtr.store(mInBuffer->getHalBuffer(), std::memory_order_release);
+ mHalOutBufferPtr.store(mOutBuffer->getHalBuffer(), std::memory_order_release);
+ return Result::OK;
}
Result Effect::sendCommand(int commandCode, const char* commandName) {
@@ -510,23 +631,6 @@
return Void();
}
-Return<void> Effect::process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
- processImpl((*mHandle)->process, "process", inBuffer, outFrameSize, _hidl_cb);
- return Void();
-}
-
-Return<void> Effect::processReverse(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, processReverse_cb _hidl_cb) {
- if ((*mHandle)->process_reverse != NULL) {
- processImpl(
- (*mHandle)->process_reverse, "process_reverse", inBuffer, outFrameSize, _hidl_cb);
- } else {
- _hidl_cb(Result::NOT_SUPPORTED, AudioBuffer());
- }
- return Void();
-}
-
Return<void> Effect::command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -611,6 +715,27 @@
EFFECT_CMD_SET_FEATURE_CONFIG, "SET_FEATURE_CONFIG", sizeof(halCmd), halCmd);
}
+Return<Result> Effect::close() {
+ if (mIsClosed) return Result::INVALID_STATE;
+ mIsClosed = true;
+ if (mProcessThread.get()) {
+ mStopProcessThread.store(true, std::memory_order_release);
+ status_t status = mProcessThread->requestExitAndWait();
+ ALOGE_IF(status, "processing thread exit error: %s", strerror(-status));
+ }
+ if (mEfGroup) {
+ status_t status = EventFlag::deleteEventFlag(&mEfGroup);
+ ALOGE_IF(status, "processing MQ event flag deletion error: %s", strerror(-status));
+ }
+ mInBuffer.clear();
+ mOutBuffer.clear();
+ int status = EffectRelease(mHandle);
+ ALOGW_IF(status, "Error releasing effect %p: %s", mHandle, strerror(-status));
+ EffectMap::getInstance().remove(mHandle);
+ mHandle = 0;
+ return Result::OK;
+}
+
} // namespace implementation
} // namespace V2_0
} // namespace effect
diff --git a/audio/effect/2.0/default/Effect.h b/audio/effect/2.0/default/Effect.h
index 61d0121..8daffb8 100644
--- a/audio/effect/2.0/default/Effect.h
+++ b/audio/effect/2.0/default/Effect.h
@@ -17,16 +17,21 @@
#ifndef ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECT_H
#define ANDROID_HARDWARE_AUDIO_EFFECT_V2_0_EFFECT_H
+#include <atomic>
#include <memory>
#include <vector>
#include <android/hardware/audio/effect/2.0/IEffect.h>
-#include <hidl/Status.h>
-
+#include <fmq/EventFlag.h>
+#include <fmq/MessageQueue.h>
#include <hidl/MQDescriptor.h>
+#include <hidl/Status.h>
+#include <utils/Thread.h>
#include <hardware/audio_effect.h>
+#include "AudioBufferManager.h"
+
namespace android {
namespace hardware {
namespace audio {
@@ -54,6 +59,8 @@
using ::android::sp;
struct Effect : public IEffect {
+ typedef MessageQueue<Result, kSynchronizedReadWrite> StatusMQ;
+
explicit Effect(effect_handle_t handle);
// Methods from ::android::hardware::audio::effect::V2_0::IEffect follow.
@@ -83,12 +90,9 @@
Return<Result> setAudioSource(AudioSource source) override;
Return<Result> offload(const EffectOffloadParameter& param) override;
Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
- Return<void> process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override;
- Return<void> processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) override;
+ Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+ Return<Result> setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override;
Return<void> command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -111,6 +115,7 @@
getCurrentConfigForFeature_cb _hidl_cb) override;
Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const hidl_vec<uint8_t>& configData) override;
+ Return<Result> close() override;
// Utility methods for extending interfaces.
template<typename T> Return<void> getIntegerParam(
@@ -161,8 +166,6 @@
friend struct VirtualizerEffect; // for getParameterImpl
friend struct VisualizerEffect; // to allow executing commands
- typedef int32_t (*ProcessFunction)(
- effect_handle_t self, audio_buffer_t* inBuffer, audio_buffer_t* outBuffer);
using CommandSuccessCallback = std::function<void()>;
using GetConfigCallback = std::function<void(Result retval, const EffectConfig& config)>;
using GetCurrentConfigSuccessCallback = std::function<void(void* configData)>;
@@ -170,13 +173,21 @@
std::function<void(uint32_t valueSize, const void* valueData)>;
using GetSupportedConfigsSuccessCallback =
std::function<void(uint32_t supportedConfigs, void* configsData)>;
- using ProcessCallback = std::function<void(Result retval, const AudioBuffer& outBuffer)>;
static const char *sContextResultOfCommand;
static const char *sContextCallToCommand;
static const char *sContextCallFunction;
+ bool mIsClosed;
effect_handle_t mHandle;
+ sp<AudioBufferWrapper> mInBuffer;
+ sp<AudioBufferWrapper> mOutBuffer;
+ std::atomic<audio_buffer_t*> mHalInBufferPtr;
+ std::atomic<audio_buffer_t*> mHalOutBufferPtr;
+ std::unique_ptr<StatusMQ> mStatusMQ;
+ EventFlag* mEfGroup;
+ std::atomic<bool> mStopProcessThread;
+ sp<Thread> mProcessThread;
virtual ~Effect();
@@ -218,12 +229,6 @@
uint32_t maxConfigs,
uint32_t configSize,
GetSupportedConfigsSuccessCallback onSuccess);
- void processImpl(
- ProcessFunction process,
- const char* funcName,
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- ProcessCallback cb);
Result sendCommand(int commandCode, const char* commandName);
Result sendCommand(int commandCode, const char* commandName, uint32_t size, void* data);
Result sendCommandReturningData(
diff --git a/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp b/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp
index db1ad51..2c1fd68 100644
--- a/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp
+++ b/audio/effect/2.0/default/EnvironmentalReverbEffect.cpp
@@ -144,16 +144,14 @@
return mEffect->getDescriptor(_hidl_cb);
}
-Return<void> EnvironmentalReverbEffect::process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
- return mEffect->process(inBuffer, outFrameSize, _hidl_cb);
+Return<void> EnvironmentalReverbEffect::prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) {
+ return mEffect->prepareForProcessing(_hidl_cb);
}
-Return<void> EnvironmentalReverbEffect::processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) {
- return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb);
+Return<Result> EnvironmentalReverbEffect::setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
Return<void> EnvironmentalReverbEffect::command(
@@ -196,6 +194,9 @@
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
+Return<Result> EnvironmentalReverbEffect::close() {
+ return mEffect->close();
+}
// Methods from ::android::hardware::audio::effect::V2_0::IEnvironmentalReverbEffect follow.
Return<Result> EnvironmentalReverbEffect::setBypass(bool bypass) {
diff --git a/audio/effect/2.0/default/EnvironmentalReverbEffect.h b/audio/effect/2.0/default/EnvironmentalReverbEffect.h
index edb5747..d0c8962 100644
--- a/audio/effect/2.0/default/EnvironmentalReverbEffect.h
+++ b/audio/effect/2.0/default/EnvironmentalReverbEffect.h
@@ -81,12 +81,9 @@
Return<Result> setAudioSource(AudioSource source) override;
Return<Result> offload(const EffectOffloadParameter& param) override;
Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
- Return<void> process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override;
- Return<void> processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) override;
+ Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+ Return<Result> setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override;
Return<void> command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -109,6 +106,7 @@
getCurrentConfigForFeature_cb _hidl_cb) override;
Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const hidl_vec<uint8_t>& configData) override;
+ Return<Result> close() override;
// Methods from ::android::hardware::audio::effect::V2_0::IEnvironmentalReverbEffect follow.
Return<Result> setBypass(bool bypass) override;
diff --git a/audio/effect/2.0/default/EqualizerEffect.cpp b/audio/effect/2.0/default/EqualizerEffect.cpp
index 490a300..833ea5b 100644
--- a/audio/effect/2.0/default/EqualizerEffect.cpp
+++ b/audio/effect/2.0/default/EqualizerEffect.cpp
@@ -135,16 +135,14 @@
return mEffect->getDescriptor(_hidl_cb);
}
-Return<void> EqualizerEffect::process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
- return mEffect->process(inBuffer, outFrameSize, _hidl_cb);
+Return<void> EqualizerEffect::prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) {
+ return mEffect->prepareForProcessing(_hidl_cb);
}
-Return<void> EqualizerEffect::processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) {
- return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb);
+Return<Result> EqualizerEffect::setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
Return<void> EqualizerEffect::command(
@@ -187,6 +185,9 @@
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
+Return<Result> EqualizerEffect::close() {
+ return mEffect->close();
+}
// Methods from ::android::hardware::audio::effect::V2_0::IEqualizerEffect follow.
Return<void> EqualizerEffect::getNumBands(getNumBands_cb _hidl_cb) {
diff --git a/audio/effect/2.0/default/EqualizerEffect.h b/audio/effect/2.0/default/EqualizerEffect.h
index ba99e2b..200ca1a 100644
--- a/audio/effect/2.0/default/EqualizerEffect.h
+++ b/audio/effect/2.0/default/EqualizerEffect.h
@@ -83,12 +83,9 @@
Return<Result> setAudioSource(AudioSource source) override;
Return<Result> offload(const EffectOffloadParameter& param) override;
Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
- Return<void> process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override;
- Return<void> processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) override;
+ Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+ Return<Result> setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override;
Return<void> command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -111,6 +108,7 @@
getCurrentConfigForFeature_cb _hidl_cb) override;
Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const hidl_vec<uint8_t>& configData) override;
+ Return<Result> close() override;
// Methods from ::android::hardware::audio::effect::V2_0::IEqualizerEffect follow.
Return<void> getNumBands(getNumBands_cb _hidl_cb) override;
diff --git a/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp b/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp
index a49019c..1f7124b 100644
--- a/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp
+++ b/audio/effect/2.0/default/LoudnessEnhancerEffect.cpp
@@ -117,16 +117,14 @@
return mEffect->getDescriptor(_hidl_cb);
}
-Return<void> LoudnessEnhancerEffect::process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
- return mEffect->process(inBuffer, outFrameSize, _hidl_cb);
+Return<void> LoudnessEnhancerEffect::prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) {
+ return mEffect->prepareForProcessing(_hidl_cb);
}
-Return<void> LoudnessEnhancerEffect::processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) {
- return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb);
+Return<Result> LoudnessEnhancerEffect::setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
Return<void> LoudnessEnhancerEffect::command(
@@ -169,6 +167,9 @@
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
+Return<Result> LoudnessEnhancerEffect::close() {
+ return mEffect->close();
+}
// Methods from ::android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect follow.
Return<Result> LoudnessEnhancerEffect::setTargetGain(int32_t targetGainMb) {
diff --git a/audio/effect/2.0/default/LoudnessEnhancerEffect.h b/audio/effect/2.0/default/LoudnessEnhancerEffect.h
index 8ca6e94..308c47f 100644
--- a/audio/effect/2.0/default/LoudnessEnhancerEffect.h
+++ b/audio/effect/2.0/default/LoudnessEnhancerEffect.h
@@ -79,12 +79,9 @@
Return<Result> setAudioSource(AudioSource source) override;
Return<Result> offload(const EffectOffloadParameter& param) override;
Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
- Return<void> process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override;
- Return<void> processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) override;
+ Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+ Return<Result> setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override;
Return<void> command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -107,6 +104,7 @@
getCurrentConfigForFeature_cb _hidl_cb) override;
Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const hidl_vec<uint8_t>& configData) override;
+ Return<Result> close() override;
// Methods from ::android::hardware::audio::effect::V2_0::ILoudnessEnhancerEffect follow.
Return<Result> setTargetGain(int32_t targetGainMb) override;
diff --git a/audio/effect/2.0/default/NoiseSuppressionEffect.cpp b/audio/effect/2.0/default/NoiseSuppressionEffect.cpp
index 69a1226..b0b929f 100644
--- a/audio/effect/2.0/default/NoiseSuppressionEffect.cpp
+++ b/audio/effect/2.0/default/NoiseSuppressionEffect.cpp
@@ -128,16 +128,14 @@
return mEffect->getDescriptor(_hidl_cb);
}
-Return<void> NoiseSuppressionEffect::process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
- return mEffect->process(inBuffer, outFrameSize, _hidl_cb);
+Return<void> NoiseSuppressionEffect::prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) {
+ return mEffect->prepareForProcessing(_hidl_cb);
}
-Return<void> NoiseSuppressionEffect::processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) {
- return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb);
+Return<Result> NoiseSuppressionEffect::setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
Return<void> NoiseSuppressionEffect::command(
@@ -180,6 +178,9 @@
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
+Return<Result> NoiseSuppressionEffect::close() {
+ return mEffect->close();
+}
// Methods from ::android::hardware::audio::effect::V2_0::INoiseSuppressionEffect follow.
Return<Result> NoiseSuppressionEffect::setSuppressionLevel(INoiseSuppressionEffect::Level level) {
diff --git a/audio/effect/2.0/default/NoiseSuppressionEffect.h b/audio/effect/2.0/default/NoiseSuppressionEffect.h
index b73727e..5e3a5c1 100644
--- a/audio/effect/2.0/default/NoiseSuppressionEffect.h
+++ b/audio/effect/2.0/default/NoiseSuppressionEffect.h
@@ -81,12 +81,9 @@
Return<Result> setAudioSource(AudioSource source) override;
Return<Result> offload(const EffectOffloadParameter& param) override;
Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
- Return<void> process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override;
- Return<void> processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) override;
+ Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+ Return<Result> setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override;
Return<void> command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -109,6 +106,7 @@
getCurrentConfigForFeature_cb _hidl_cb) override;
Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const hidl_vec<uint8_t>& configData) override;
+ Return<Result> close() override;
// Methods from ::android::hardware::audio::effect::V2_0::INoiseSuppressionEffect follow.
Return<Result> setSuppressionLevel(INoiseSuppressionEffect::Level level) override;
diff --git a/audio/effect/2.0/default/PresetReverbEffect.cpp b/audio/effect/2.0/default/PresetReverbEffect.cpp
index 0e6d1b8..803c9be 100644
--- a/audio/effect/2.0/default/PresetReverbEffect.cpp
+++ b/audio/effect/2.0/default/PresetReverbEffect.cpp
@@ -115,16 +115,14 @@
return mEffect->getDescriptor(_hidl_cb);
}
-Return<void> PresetReverbEffect::process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
- return mEffect->process(inBuffer, outFrameSize, _hidl_cb);
+Return<void> PresetReverbEffect::prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) {
+ return mEffect->prepareForProcessing(_hidl_cb);
}
-Return<void> PresetReverbEffect::processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) {
- return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb);
+Return<Result> PresetReverbEffect::setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
Return<void> PresetReverbEffect::command(
@@ -167,6 +165,9 @@
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
+Return<Result> PresetReverbEffect::close() {
+ return mEffect->close();
+}
// Methods from ::android::hardware::audio::effect::V2_0::IPresetReverbEffect follow.
Return<Result> PresetReverbEffect::setPreset(IPresetReverbEffect::Preset preset) {
diff --git a/audio/effect/2.0/default/PresetReverbEffect.h b/audio/effect/2.0/default/PresetReverbEffect.h
index 4d39569..f6a900c 100644
--- a/audio/effect/2.0/default/PresetReverbEffect.h
+++ b/audio/effect/2.0/default/PresetReverbEffect.h
@@ -79,12 +79,9 @@
Return<Result> setAudioSource(AudioSource source) override;
Return<Result> offload(const EffectOffloadParameter& param) override;
Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
- Return<void> process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override;
- Return<void> processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) override;
+ Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+ Return<Result> setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override;
Return<void> command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -107,6 +104,7 @@
getCurrentConfigForFeature_cb _hidl_cb) override;
Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const hidl_vec<uint8_t>& configData) override;
+ Return<Result> close() override;
// Methods from ::android::hardware::audio::effect::V2_0::IPresetReverbEffect follow.
Return<Result> setPreset(IPresetReverbEffect::Preset preset) override;
diff --git a/audio/effect/2.0/default/VirtualizerEffect.cpp b/audio/effect/2.0/default/VirtualizerEffect.cpp
index 313674d..4f193e7 100644
--- a/audio/effect/2.0/default/VirtualizerEffect.cpp
+++ b/audio/effect/2.0/default/VirtualizerEffect.cpp
@@ -127,16 +127,14 @@
return mEffect->getDescriptor(_hidl_cb);
}
-Return<void> VirtualizerEffect::process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
- return mEffect->process(inBuffer, outFrameSize, _hidl_cb);
+Return<void> VirtualizerEffect::prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) {
+ return mEffect->prepareForProcessing(_hidl_cb);
}
-Return<void> VirtualizerEffect::processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) {
- return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb);
+Return<Result> VirtualizerEffect::setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
Return<void> VirtualizerEffect::command(
@@ -179,6 +177,9 @@
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
+Return<Result> VirtualizerEffect::close() {
+ return mEffect->close();
+}
// Methods from ::android::hardware::audio::effect::V2_0::IVirtualizerEffect follow.
Return<bool> VirtualizerEffect::isStrengthSupported() {
diff --git a/audio/effect/2.0/default/VirtualizerEffect.h b/audio/effect/2.0/default/VirtualizerEffect.h
index ba89a61..5b0773d 100644
--- a/audio/effect/2.0/default/VirtualizerEffect.h
+++ b/audio/effect/2.0/default/VirtualizerEffect.h
@@ -80,12 +80,9 @@
Return<Result> setAudioSource(AudioSource source) override;
Return<Result> offload(const EffectOffloadParameter& param) override;
Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
- Return<void> process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override;
- Return<void> processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) override;
+ Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+ Return<Result> setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override;
Return<void> command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -108,6 +105,7 @@
getCurrentConfigForFeature_cb _hidl_cb) override;
Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const hidl_vec<uint8_t>& configData) override;
+ Return<Result> close() override;
// Methods from ::android::hardware::audio::effect::V2_0::IVirtualizerEffect follow.
Return<bool> isStrengthSupported() override;
diff --git a/audio/effect/2.0/default/VisualizerEffect.cpp b/audio/effect/2.0/default/VisualizerEffect.cpp
index a53eabc..141817b 100644
--- a/audio/effect/2.0/default/VisualizerEffect.cpp
+++ b/audio/effect/2.0/default/VisualizerEffect.cpp
@@ -115,16 +115,14 @@
return mEffect->getDescriptor(_hidl_cb);
}
-Return<void> VisualizerEffect::process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) {
- return mEffect->process(inBuffer, outFrameSize, _hidl_cb);
+Return<void> VisualizerEffect::prepareForProcessing(
+ prepareForProcessing_cb _hidl_cb) {
+ return mEffect->prepareForProcessing(_hidl_cb);
}
-Return<void> VisualizerEffect::processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) {
- return mEffect->processReverse(inBuffer, outFrameSize, _hidl_cb);
+Return<Result> VisualizerEffect::setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) {
+ return mEffect->setProcessBuffers(inBuffer, outBuffer);
}
Return<void> VisualizerEffect::command(
@@ -167,6 +165,9 @@
return mEffect->setCurrentConfigForFeature(featureId, configData);
}
+Return<Result> VisualizerEffect::close() {
+ return mEffect->close();
+}
// Methods from ::android::hardware::audio::effect::V2_0::IVisualizerEffect follow.
Return<Result> VisualizerEffect::setCaptureSize(uint16_t captureSize) {
diff --git a/audio/effect/2.0/default/VisualizerEffect.h b/audio/effect/2.0/default/VisualizerEffect.h
index ae0b05c..b6dc768 100644
--- a/audio/effect/2.0/default/VisualizerEffect.h
+++ b/audio/effect/2.0/default/VisualizerEffect.h
@@ -79,12 +79,9 @@
Return<Result> setAudioSource(AudioSource source) override;
Return<Result> offload(const EffectOffloadParameter& param) override;
Return<void> getDescriptor(getDescriptor_cb _hidl_cb) override;
- Return<void> process(
- const AudioBuffer& inBuffer, uint32_t outFrameSize, process_cb _hidl_cb) override;
- Return<void> processReverse(
- const AudioBuffer& inBuffer,
- uint32_t outFrameSize,
- processReverse_cb _hidl_cb) override;
+ Return<void> prepareForProcessing(prepareForProcessing_cb _hidl_cb) override;
+ Return<Result> setProcessBuffers(
+ const AudioBuffer& inBuffer, const AudioBuffer& outBuffer) override;
Return<void> command(
uint32_t commandId,
const hidl_vec<uint8_t>& data,
@@ -107,6 +104,7 @@
getCurrentConfigForFeature_cb _hidl_cb) override;
Return<Result> setCurrentConfigForFeature(
uint32_t featureId, const hidl_vec<uint8_t>& configData) override;
+ Return<Result> close() override;
// Methods from ::android::hardware::audio::effect::V2_0::IVisualizerEffect follow.
Return<Result> setCaptureSize(uint16_t captureSize) override;
diff --git a/audio/effect/2.0/types.hal b/audio/effect/2.0/types.hal
index ad7f4ce..0cac59a 100644
--- a/audio/effect/2.0/types.hal
+++ b/audio/effect/2.0/types.hal
@@ -222,10 +222,10 @@
* samples for all channels at a given time. Frame size for unspecified format
* (AUDIO_FORMAT_OTHER) is 8 bit by definition.
*/
-// TODO(mnaganov): replace with FMQ version.
struct AudioBuffer {
+ uint64_t id;
uint32_t frameCount;
- vec<uint8_t> data;
+ memory data;
};
@export(name="effect_buffer_access_e", value_prefix="EFFECT_BUFFER_")
@@ -284,3 +284,14 @@
AudioIoHandle ioHandle; // io handle of the playback thread
// the effect is attached to
};
+
+/*
+ * The message queue flags used to synchronize reads and writes from
+ * the status message queue used by effects.
+ */
+enum MessageQueueFlagBits : uint32_t {
+ DONE_PROCESSING = 1 << 0,
+ REQUEST_PROCESS = 1 << 1,
+ REQUEST_PROCESS_REVERSE = 1 << 2,
+ REQUEST_PROCESS_ALL = REQUEST_PROCESS | REQUEST_PROCESS_REVERSE
+};