Enable HapticGenerator AIDL effect
- Add Haptic and Spatializer compatible check in AudioPolicyManager
- The generated haptic samples is expected to append to the end of input
buffer which needs special handling in both effect and libaudiohal
- Fix the haptic generator effect implementation wrong parameter and add
configuration with each init_params
- Add parameter logging in HapticGenerator AIDL effect
Bug: 330686268
Test: atest --test-mapping hardware/interfaces/audio/aidl/vts:presubmit
Test: atest CtsMediaAudioTestCases
Test: HapticGenerator debug app on Pixel AIDL audio hal
Change-Id: Ia292acc54276d3ae035682ca421dc7ab7d6cff73
Merged-In: Ia292acc54276d3ae035682ca421dc7ab7d6cff73
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
index ff6126d..a13903b 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.cpp
@@ -29,6 +29,7 @@
#include <system/audio_effects/effect_visualizer.h>
#include <utils/Log.h>
+#include <Utils.h>
#include "EffectConversionHelperAidl.h"
#include "EffectProxy.h"
@@ -37,18 +38,20 @@
namespace effect {
using ::aidl::android::aidl_utils::statusTFromBinderStatus;
+using ::aidl::android::hardware::audio::common::getChannelCount;
using ::aidl::android::hardware::audio::effect::CommandId;
using ::aidl::android::hardware::audio::effect::Descriptor;
using ::aidl::android::hardware::audio::effect::Flags;
using ::aidl::android::hardware::audio::effect::IEffect;
using ::aidl::android::hardware::audio::effect::Parameter;
using ::aidl::android::hardware::audio::effect::State;
+using ::aidl::android::media::audio::common::AudioChannelLayout;
using ::aidl::android::media::audio::common::AudioDeviceDescription;
using ::aidl::android::media::audio::common::AudioMode;
using ::aidl::android::media::audio::common::AudioSource;
-using ::android::hardware::EventFlag;
using android::effect::utils::EffectParamReader;
using android::effect::utils::EffectParamWriter;
+using android::hardware::EventFlag;
using ::android::status_t;
@@ -519,5 +522,15 @@
return OK;
}
+size_t EffectConversionHelperAidl::getAudioChannelCount() const {
+ return getChannelCount(mCommon.input.base.channelMask,
+ ~AudioChannelLayout::LAYOUT_HAPTIC_AB /* mask */);
+}
+
+size_t EffectConversionHelperAidl::getHapticChannelCount() const {
+ return getChannelCount(mCommon.input.base.channelMask,
+ AudioChannelLayout::LAYOUT_HAPTIC_AB /* mask */);
+}
+
} // namespace effect
} // namespace android
diff --git a/media/libaudiohal/impl/EffectConversionHelperAidl.h b/media/libaudiohal/impl/EffectConversionHelperAidl.h
index 29c5a83..50b47a9 100644
--- a/media/libaudiohal/impl/EffectConversionHelperAidl.h
+++ b/media/libaudiohal/impl/EffectConversionHelperAidl.h
@@ -49,6 +49,9 @@
::aidl::android::hardware::audio::effect::Descriptor getDescriptor() const;
status_t reopen();
+ size_t getAudioChannelCount() const;
+ size_t getHapticChannelCount() const;
+
uint8_t mOutputAccessMode = EFFECT_BUFFER_ACCESS_WRITE;
protected:
diff --git a/media/libaudiohal/impl/EffectHalAidl.cpp b/media/libaudiohal/impl/EffectHalAidl.cpp
index 0c7f78e..ea4dbf6 100644
--- a/media/libaudiohal/impl/EffectHalAidl.cpp
+++ b/media/libaudiohal/impl/EffectHalAidl.cpp
@@ -15,6 +15,7 @@
*/
#include <cstddef>
+#include <cstring>
#define LOG_TAG "EffectHalAidl"
//#define LOG_NDEBUG 0
@@ -128,6 +129,7 @@
::aidl::android::hardware::audio::effect::getEffectTypeUuidHapticGenerator()) {
mConversion = std::make_unique<android::effect::AidlConversionHapticGenerator>(
effect, sessionId, ioId, desc, mIsProxyEffect);
+ mIsHapticGenerator = true;
} else if (typeUuid ==
::aidl::android::hardware::audio::effect::getEffectTypeUuidLoudnessEnhancer()) {
mConversion = std::make_unique<android::effect::AidlConversionLoudnessEnhancer>(
@@ -200,7 +202,7 @@
::android::OK == efGroup->wait(kEventFlagDataMqUpdate, &efState,
1 /* ns */, true /* retry */) &&
efState & kEventFlagDataMqUpdate) {
- ALOGV("%s %s V%d receive dataMQUpdate eventFlag from HAL", __func__, effectName.c_str(),
+ ALOGD("%s %s V%d receive dataMQUpdate eventFlag from HAL", __func__, effectName.c_str(),
halVersion);
mConversion->reopen();
@@ -216,7 +218,7 @@
}
size_t available = inputQ->availableToWrite();
- size_t floatsToWrite = std::min(available, mInBuffer->getSize() / sizeof(float));
+ const size_t floatsToWrite = std::min(available, mInBuffer->getSize() / sizeof(float));
if (floatsToWrite == 0) {
ALOGE("%s not able to write, floats in buffer %zu, space in FMQ %zu", __func__,
mInBuffer->getSize() / sizeof(float), available);
@@ -248,7 +250,7 @@
}
available = outputQ->availableToRead();
- size_t floatsToRead = std::min(available, mOutBuffer->getSize() / sizeof(float));
+ const size_t floatsToRead = std::min(available, mOutBuffer->getSize() / sizeof(float));
if (floatsToRead == 0) {
ALOGE("%s not able to read, buffer space %zu, floats in FMQ %zu", __func__,
mOutBuffer->getSize() / sizeof(float), available);
@@ -257,7 +259,8 @@
float *outputRawBuffer = mOutBuffer->audioBuffer()->f32;
std::vector<float> tempBuffer;
- if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+ // keep original data in the output buffer for accumulate mode or HapticGenerator effect
+ if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE || mIsHapticGenerator) {
tempBuffer.resize(floatsToRead);
outputRawBuffer = tempBuffer.data();
}
@@ -267,7 +270,31 @@
mOutBuffer->audioBuffer());
return INVALID_OPERATION;
}
- if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+
+ // HapticGenerator needs special handling because the generated haptic samples should append to
+ // the end of audio samples, the generated haptic data pass back from HAL in output FMQ at same
+ // offset as input buffer, here we skip the audio samples in output FMQ and append haptic
+ // samples to the end of input buffer
+ if (mIsHapticGenerator) {
+ static constexpr float kHalFloatSampleLimit = 2.0f;
+ assert(floatsToRead == floatsToWrite);
+ const auto audioChNum = mConversion->getAudioChannelCount();
+ const auto audioSamples =
+ floatsToWrite * audioChNum / (audioChNum + mConversion->getHapticChannelCount());
+ // accumulate or copy input to output, haptic samples remains all zero
+ if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
+ accumulate_float(mOutBuffer->audioBuffer()->f32, mInBuffer->audioBuffer()->f32,
+ audioSamples);
+ } else {
+ memcpy_to_float_from_float_with_clamping(mOutBuffer->audioBuffer()->f32,
+ mInBuffer->audioBuffer()->f32, audioSamples,
+ kHalFloatSampleLimit);
+ }
+ // append the haptic sample at the end of input audio samples
+ memcpy_to_float_from_float_with_clamping(mInBuffer->audioBuffer()->f32 + audioSamples,
+ outputRawBuffer + audioSamples,
+ floatsToRead - audioSamples, kHalFloatSampleLimit);
+ } else if (mConversion->mOutputAccessMode == EFFECT_BUFFER_ACCESS_ACCUMULATE) {
accumulate_float(mOutBuffer->audioBuffer()->f32, outputRawBuffer, floatsToRead);
}
diff --git a/media/libaudiohal/impl/EffectHalAidl.h b/media/libaudiohal/impl/EffectHalAidl.h
index bbcb7e2..4f7de7c 100644
--- a/media/libaudiohal/impl/EffectHalAidl.h
+++ b/media/libaudiohal/impl/EffectHalAidl.h
@@ -73,6 +73,7 @@
const int32_t mSessionId;
const int32_t mIoId;
const bool mIsProxyEffect;
+ bool mIsHapticGenerator = false;
std::unique_ptr<EffectConversionHelperAidl> mConversion;