From e39cd36545db7c77ce45b8494810d9cd2a976cf1 Mon Sep 17 00:00:00 2001 From: Shunkai Yao Date: Thu, 22 Dec 2022 00:23:34 +0000 Subject: [PATCH] Effect AIDL Add visualizer libeffect implementation Bug: 258124419 Test: atest VtsHalVisualizerTargetTest Change-Id: I4ad827a4e8951a16738580ecf91fe1b9cf65cc20 --- .../hardware/audio/effect/Visualizer.aidl | 12 +-- .../hardware/audio/effect/IEffect.aidl | 10 +- .../hardware/audio/effect/Visualizer.aidl | 18 ++-- audio/aidl/default/Android.bp | 2 +- audio/aidl/default/EffectImpl.cpp | 5 + audio/aidl/default/audio_effects_config.xml | 4 +- .../default/include/effect-impl/EffectUUID.h | 7 ++ .../aidl/default/visualizer/VisualizerSw.cpp | 23 +++-- audio/aidl/default/visualizer/VisualizerSw.h | 24 ++--- audio/aidl/vts/VtsHalVisualizerTargetTest.cpp | 96 +++++++++++++------ 10 files changed, 128 insertions(+), 73 deletions(-) diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl index 9ee19f0e49..25f0b736d4 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl @@ -38,7 +38,7 @@ union Visualizer { android.hardware.audio.effect.VendorExtension vendor; android.hardware.audio.effect.Visualizer.GetOnlyParameters getOnlyParameters; android.hardware.audio.effect.Visualizer.SetOnlyParameters setOnlyParameters; - int captureSizeBytes; + int captureSamples; android.hardware.audio.effect.Visualizer.ScalingMode scalingMode; android.hardware.audio.effect.Visualizer.MeasurementMode measurementMode; @VintfStability @@ -52,12 +52,12 @@ union Visualizer { parcelable Capability { android.hardware.audio.effect.VendorExtension extension; int maxLatencyMs; - android.hardware.audio.effect.Visualizer.CaptureSizeRange captureSizeRange; + android.hardware.audio.effect.Visualizer.CaptureSamplesRange captureSampleRange; } @VintfStability - parcelable CaptureSizeRange { - int minBytes; - int maxBytes; + parcelable CaptureSamplesRange { + int min; + int max; } @VintfStability enum ScalingMode { @@ -72,7 +72,7 @@ union Visualizer { @VintfStability union GetOnlyParameters { android.hardware.audio.effect.Visualizer.GetOnlyParameters.Measurement measurement; - byte[] captureBytes; + byte[] captureSampleBuffer; @VintfStability parcelable Measurement { int rms; diff --git a/audio/aidl/android/hardware/audio/effect/IEffect.aidl b/audio/aidl/android/hardware/audio/effect/IEffect.aidl index 3b957d702d..6097f34ead 100644 --- a/audio/aidl/android/hardware/audio/effect/IEffect.aidl +++ b/audio/aidl/android/hardware/audio/effect/IEffect.aidl @@ -34,12 +34,10 @@ interface IEffect { /** * One of Binder STATUS_* statuses: * - STATUS_OK: the command has completed successfully; - * - STATUS_BAD_VALUE: invalid value in the 'Command' structure; - * - STATUS_INVALID_OPERATION: the mix port is not connected - * to any producer or consumer, thus - * positions can not be reported; - * - STATUS_NOT_ENOUGH_DATA: a read or write error has - * occurred for the 'audio.fmq' queue; + * - STATUS_BAD_VALUE: invalid parameters or state detected in effects; + * - STATUS_INVALID_OPERATION: an internal error happens in effect audio buffer processing; + * - STATUS_NOT_ENOUGH_DATA: a read or write error has occurred for the 'inputDataMQ' or + * 'outputDataMQ'; * */ int status; diff --git a/audio/aidl/android/hardware/audio/effect/Visualizer.aidl b/audio/aidl/android/hardware/audio/effect/Visualizer.aidl index 4c1b71aa1e..dfe29c88fe 100644 --- a/audio/aidl/android/hardware/audio/effect/Visualizer.aidl +++ b/audio/aidl/android/hardware/audio/effect/Visualizer.aidl @@ -63,16 +63,16 @@ union Visualizer { /** * Capture size range. */ - CaptureSizeRange captureSizeRange; + CaptureSamplesRange captureSampleRange; } /** - * Supported capture size range in bytes. + * Supported capture size range in samples. */ @VintfStability - parcelable CaptureSizeRange { - int minBytes; - int maxBytes; + parcelable CaptureSamplesRange { + int min; + int max; } /** @@ -131,9 +131,9 @@ union Visualizer { Measurement measurement; /** - * Gets the latest PCM capture, size of returned vector equals to @c captureSize. + * Get the latest captureSamples of PCM samples (8 bits per sample). */ - byte[] captureBytes; + byte[] captureSampleBuffer; } GetOnlyParameters getOnlyParameters; @@ -152,10 +152,10 @@ union Visualizer { SetOnlyParameters setOnlyParameters; /** - * Current capture size in bytes. The capture size must be a power of 2 in the range + * Current capture size in number of samples. The capture size must be inside * Capability.captureSizeRange. */ - int captureSizeBytes; + int captureSamples; /** * Visualizer capture mode */ diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp index f72896749f..8f0b4bda08 100644 --- a/audio/aidl/default/Android.bp +++ b/audio/aidl/default/Android.bp @@ -160,7 +160,7 @@ cc_binary { "libpresetreverbsw", "libtinyxml2", "libvirtualizersw", - "libvisualizersw", + "libvisualizeraidl", "libvolumesw", ], srcs: [ diff --git a/audio/aidl/default/EffectImpl.cpp b/audio/aidl/default/EffectImpl.cpp index 139f2622fa..b24ca630d3 100644 --- a/audio/aidl/default/EffectImpl.cpp +++ b/audio/aidl/default/EffectImpl.cpp @@ -21,6 +21,7 @@ using aidl::android::hardware::audio::effect::IEffect; using aidl::android::hardware::audio::effect::State; +using aidl::android::media::audio::common::PcmType; extern "C" binder_exception_t destroyEffect(const std::shared_ptr& instanceSp) { State state; @@ -40,6 +41,10 @@ ndk::ScopedAStatus EffectImpl::open(const Parameter::Common& common, const std::optional& specific, OpenEffectReturn* ret) { LOG(DEBUG) << __func__; + // effect only support 32bits float + 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"); RETURN_OK_IF(mState != State::INIT); auto context = createContext(common); RETURN_IF(!context, EX_NULL_POINTER, "createContextFailed"); diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml index 81c8dd4f15..9670e9c08b 100644 --- a/audio/aidl/default/audio_effects_config.xml +++ b/audio/aidl/default/audio_effects_config.xml @@ -41,7 +41,7 @@ - + @@ -82,7 +82,7 @@ - + diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h index 05336b9a5f..6eec29e036 100644 --- a/audio/aidl/default/include/effect-impl/EffectUUID.h +++ b/audio/aidl/default/include/effect-impl/EffectUUID.h @@ -243,6 +243,13 @@ static const AudioUuid kVisualizerSwImplUUID = {static_cast(0xfa81a0f6) 0x11ed, 0x9b6a, {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}}; +// d069d9e0-8329-11df-9168-0002a5d5c51b +// {0xd069d9e0, 0x8329, 0x11df, 0x9168, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}, +static const AudioUuid kVisualizerImplUUID = {static_cast(0xd069d9e0), + 0x8329, + 0x11df, + 0x9168, + {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; // fa81a2b8-588b-11ed-9b6a-0242ac120002 static const AudioUuid kVolumeTypeUUID = {static_cast(0xfa81a2b8), 0x588b, diff --git a/audio/aidl/default/visualizer/VisualizerSw.cpp b/audio/aidl/default/visualizer/VisualizerSw.cpp index 37eb30bc48..735180e7d4 100644 --- a/audio/aidl/default/visualizer/VisualizerSw.cpp +++ b/audio/aidl/default/visualizer/VisualizerSw.cpp @@ -56,9 +56,12 @@ namespace aidl::android::hardware::audio::effect { const std::string VisualizerSw::kEffectName = "VisualizerSw"; /* capabilities */ -const Visualizer::CaptureSizeRange mCaptureSizeRange = {MIN_CAPTURE_SIZE, MAX_CAPTURE_SIZE}; -const Visualizer::Capability VisualizerSw::kCapability = {.maxLatencyMs = MAX_LATENCY, - .captureSizeRange = mCaptureSizeRange}; +const Visualizer::CaptureSamplesRange VisualizerSwContext::kCaptureSamplesRange = { + VisualizerSwContext::kMinCaptureSize, VisualizerSwContext::kMaxCaptureSize}; +const Visualizer::Capability VisualizerSw::kCapability = { + .maxLatencyMs = VisualizerSwContext::kMaxLatencyMs, + .captureSampleRange = VisualizerSwContext::kCaptureSamplesRange}; + const Descriptor VisualizerSw::kDescriptor = { .common = {.id = {.type = kVisualizerTypeUUID, .uuid = kVisualizerSwImplUUID, @@ -84,8 +87,8 @@ ndk::ScopedAStatus VisualizerSw::setParameterSpecific(const Parameter::Specific& auto tag = vsParam.getTag(); switch (tag) { - case Visualizer::captureSizeBytes: { - RETURN_IF(mContext->setVsCaptureSize(vsParam.get()) != + case Visualizer::captureSamples: { + RETURN_IF(mContext->setVsCaptureSize(vsParam.get()) != RetCode::SUCCESS, EX_ILLEGAL_ARGUMENT, "captureSizeNotSupported"); return ndk::ScopedAStatus::ok(); @@ -159,8 +162,8 @@ ndk::ScopedAStatus VisualizerSw::getParameterVisualizer(const Visualizer::Tag& t Visualizer vsParam; switch (tag) { - case Visualizer::captureSizeBytes: { - vsParam.set(mContext->getVsCaptureSize()); + case Visualizer::captureSamples: { + vsParam.set(mContext->getVsCaptureSize()); break; } case Visualizer::scalingMode: { @@ -190,9 +193,9 @@ ndk::ScopedAStatus VisualizerSw::getGetOnlyParameterVisualizer( mContext->getVsMeasurement()); break; } - case Visualizer::GetOnlyParameters::captureBytes: { - getOnlyParam.set( - mContext->getVsCaptureBytes()); + case Visualizer::GetOnlyParameters::captureSampleBuffer: { + getOnlyParam.set( + mContext->getVsCaptureSampleBuffer()); break; } default: { diff --git a/audio/aidl/default/visualizer/VisualizerSw.h b/audio/aidl/default/visualizer/VisualizerSw.h index a95537cb5a..edaf1232fe 100644 --- a/audio/aidl/default/visualizer/VisualizerSw.h +++ b/audio/aidl/default/visualizer/VisualizerSw.h @@ -22,24 +22,24 @@ #include "effect-impl/EffectImpl.h" #include "effect-impl/EffectUUID.h" -#define MIN_CAPTURE_SIZE 128 -#define MAX_CAPTURE_SIZE 1024 -#define MAX_LATENCY 3000 -#define CAPTURE_BUF_SIZE 65536 - namespace aidl::android::hardware::audio::effect { class VisualizerSwContext final : public EffectContext { public: + static const int kMinCaptureSize = 0x80; + static const int kMaxCaptureSize = 0x400; + static const int kMaxLatencyMs = 3000; + static const int kMaxCaptureBufSize = 0xffff; + static const Visualizer::CaptureSamplesRange kCaptureSamplesRange; VisualizerSwContext(int statusDepth, const Parameter::Common& common) : EffectContext(statusDepth, common) { LOG(DEBUG) << __func__; - mCaptureBytes.resize(CAPTURE_BUF_SIZE); - fill(mCaptureBytes.begin(), mCaptureBytes.end(), 0x80); + mCaptureSampleBuffer.resize(kMaxCaptureBufSize); + fill(mCaptureSampleBuffer.begin(), mCaptureSampleBuffer.end(), 0x80); } RetCode setVsCaptureSize(int captureSize) { - if (captureSize < MIN_CAPTURE_SIZE || captureSize > MAX_CAPTURE_SIZE) { + if (captureSize < kMinCaptureSize || captureSize > kMaxCaptureSize) { LOG(ERROR) << __func__ << " invalid captureSize " << captureSize; return RetCode::ERROR_ILLEGAL_PARAMETER; } @@ -64,7 +64,7 @@ class VisualizerSwContext final : public EffectContext { Visualizer::MeasurementMode getVsMeasurementMode() const { return mMeasurementMode; } RetCode setVsLatency(int latency) { - if (latency < 0 || latency > MAX_LATENCY) { + if (latency < 0 || latency > kMaxLatencyMs) { LOG(ERROR) << __func__ << " invalid latency " << latency; return RetCode::ERROR_ILLEGAL_PARAMETER; } @@ -74,15 +74,15 @@ class VisualizerSwContext final : public EffectContext { } Visualizer::GetOnlyParameters::Measurement getVsMeasurement() const { return mMeasurement; } - std::vector getVsCaptureBytes() const { return mCaptureBytes; } + std::vector getVsCaptureSampleBuffer() const { return mCaptureSampleBuffer; } private: - int mCaptureSize = MAX_CAPTURE_SIZE; + int mCaptureSize = kMaxCaptureSize; Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED; Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE; int mLatency; const Visualizer::GetOnlyParameters::Measurement mMeasurement = {0, 0}; - std::vector mCaptureBytes; + std::vector mCaptureSampleBuffer; }; class VisualizerSw final : public EffectImpl { diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp index a7834fbb9c..47d67553c7 100644 --- a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp +++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp @@ -19,6 +19,9 @@ #define LOG_TAG "VtsHalVisualizerTest" #include +#include +#include + #include "EffectHelper.h" using namespace android; @@ -46,18 +49,6 @@ using VisualizerParamTestParam = std::tuple, Descriptor>, int, Visualizer::ScalingMode, Visualizer::MeasurementMode, int>; -const int MIN_CAPTURE_SIZE = 128; -const int MAX_CAPTURE_SIZE = 1024; -const int MAX_LATENCY = 3000; - -const std::vector kCaptureSizeValues = {MIN_CAPTURE_SIZE - 1, MIN_CAPTURE_SIZE, - MAX_CAPTURE_SIZE, MAX_CAPTURE_SIZE + 1}; -const std::vector kScalingModeValues = { - Visualizer::ScalingMode::NORMALIZED, Visualizer::ScalingMode::AS_PLAYED}; -const std::vector kMeasurementModeValues = { - Visualizer::MeasurementMode::NONE, Visualizer::MeasurementMode::PEAK_RMS}; -const std::vector kLatencyValues = {-1, 0, MAX_LATENCY, MAX_LATENCY + 1}; - class VisualizerParamTest : public ::testing::TestWithParam, public EffectHelper { public: @@ -86,19 +77,25 @@ class VisualizerParamTest : public ::testing::TestWithParam(MIN_CAPTURE_SIZE); + Visualizer vs = Visualizer::make( + mDescriptor.capability.get().captureSampleRange.max); Parameter::Specific specific = Parameter::Specific::make(vs); return specific; } + static const std::vector, Descriptor>> kFactoryDescList; + static const std::unordered_set kScalingModeValues; + static const std::unordered_set kMeasurementModeValues; + static const std::unordered_set kLatencyValues; + static const std::unordered_set kCaptureSizeValues; + static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100; std::shared_ptr mFactory; std::shared_ptr mEffect; Descriptor mDescriptor; - int mCaptureSize = MAX_CAPTURE_SIZE; + int mCaptureSize; Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED; Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE; int mLatency = 0; @@ -184,8 +181,8 @@ class VisualizerParamTest : public ::testing::TestWithParam(captureSize); - mCommonTags.push_back({Visualizer::captureSizeBytes, vs}); + vs.set(captureSize); + mCommonTags.push_back({Visualizer::captureSamples, vs}); } void addScalingModeParam(Visualizer::ScalingMode scalingMode) { @@ -213,15 +210,15 @@ class VisualizerParamTest : public ::testing::TestWithParam(); switch (tag) { - case Visualizer::captureSizeBytes: { - int captureSize = vs.get(); + case Visualizer::captureSamples: { + int captureSize = vs.get(); return isCaptureSizeInRange(vsCap, captureSize); } case Visualizer::scalingMode: @@ -243,14 +240,45 @@ class VisualizerParamTest : public ::testing::TestWithParam= cap.captureSizeRange.minBytes && - captureSize <= cap.captureSizeRange.maxBytes); + return (captureSize >= cap.captureSampleRange.min && + captureSize <= cap.captureSampleRange.max); } bool isLatencyInRange(const Visualizer::Capability& cap, int latency) const { return (latency >= 0 && latency <= cap.maxLatencyMs); } + static std::unordered_set getCaptureSizeValues() { + int minCaptureSize = std::numeric_limits::max(); + int maxCaptureSize = std::numeric_limits::min(); + for (const auto& it : kFactoryDescList) { + maxCaptureSize = std::max( + it.second.capability.get().captureSampleRange.max, + maxCaptureSize); + minCaptureSize = std::min( + it.second.capability.get().captureSampleRange.min, + minCaptureSize); + } + return {std::numeric_limits::min(), minCaptureSize - 1, minCaptureSize, + (minCaptureSize + maxCaptureSize) >> 1, maxCaptureSize, maxCaptureSize + 1, + std::numeric_limits::max()}; + } + + static std::unordered_set getLatencyValues() { + const auto max = std::max_element( + kFactoryDescList.begin(), kFactoryDescList.end(), + [](const std::pair, Descriptor>& a, + const std::pair, Descriptor>& b) { + return a.second.capability.get().maxLatencyMs < + b.second.capability.get().maxLatencyMs; + }); + if (max == kFactoryDescList.end()) { + return {0}; + } + int maxDelay = max->second.capability.get().maxLatencyMs; + return {-1, 0, maxDelay >> 1, maxDelay - 1, maxDelay, maxDelay + 1}; + } + private: std::vector> mCommonTags; std::vector> mSetOnlyParamTags; @@ -262,6 +290,20 @@ class VisualizerParamTest : public ::testing::TestWithParam, Descriptor>> + VisualizerParamTest::kFactoryDescList = EffectFactoryHelper::getAllEffectDescriptors( + IFactory::descriptor, kVisualizerTypeUUID); +const std::unordered_set VisualizerParamTest::kCaptureSizeValues = + VisualizerParamTest::getCaptureSizeValues(); +const std::unordered_set VisualizerParamTest::kMeasurementModeValues( + ndk::enum_range().begin(), + ndk::enum_range().end()); +const std::unordered_set VisualizerParamTest::kScalingModeValues( + ndk::enum_range().begin(), + ndk::enum_range().end()); +const std::unordered_set VisualizerParamTest::kLatencyValues = + VisualizerParamTest::getLatencyValues(); + TEST_P(VisualizerParamTest, SetAndGetCaptureSize) { EXPECT_NO_FATAL_FAILURE(addCaptureSizeParam(mCaptureSize)); SetAndGetCommonParameters(); @@ -293,13 +335,13 @@ TEST_P(VisualizerParamTest, GetAndSetCaptureBytes) { } INSTANTIATE_TEST_SUITE_P( - VisualizerTest, VisualizerParamTest, + VisualizerParamTest, VisualizerParamTest, ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors( IFactory::descriptor, kVisualizerTypeUUID)), - testing::ValuesIn(kCaptureSizeValues), - testing::ValuesIn(kScalingModeValues), - testing::ValuesIn(kMeasurementModeValues), - testing::ValuesIn(kLatencyValues)), + testing::ValuesIn(VisualizerParamTest::kCaptureSizeValues), + testing::ValuesIn(VisualizerParamTest::kScalingModeValues), + testing::ValuesIn(VisualizerParamTest::kMeasurementModeValues), + testing::ValuesIn(VisualizerParamTest::kLatencyValues)), [](const testing::TestParamInfo& info) { auto descriptor = std::get(info.param).second; std::string captureSize = std::to_string(std::get(info.param));