From 94aae5e51d4886a222da0a003595a0831718c136 Mon Sep 17 00:00:00 2001 From: Sham Rathod Date: Wed, 23 Nov 2022 12:22:32 +0530 Subject: [PATCH] Visualizer: Add AIDL placeholder implementation and vts test cases Bug: 258124419 Test: atest VtsHalVisualizerTargetTest Change-Id: I8bfdb234d1ac3f57b12096d3f02dd1bad92b1d0f --- audio/aidl/TEST_MAPPING | 3 + .../aidl/default/visualizer/VisualizerSw.cpp | 130 ++++++- audio/aidl/default/visualizer/VisualizerSw.h | 66 +++- audio/aidl/vts/Android.bp | 6 + audio/aidl/vts/VtsHalVisualizerTargetTest.cpp | 329 ++++++++++++++++++ 5 files changed, 519 insertions(+), 15 deletions(-) create mode 100644 audio/aidl/vts/VtsHalVisualizerTargetTest.cpp diff --git a/audio/aidl/TEST_MAPPING b/audio/aidl/TEST_MAPPING index 484320f02a..b4607f9f6f 100644 --- a/audio/aidl/TEST_MAPPING +++ b/audio/aidl/TEST_MAPPING @@ -14,6 +14,9 @@ }, { "name": "VtsHalLoudnessEnhancerTargetTest" + }, + { + "name": "VtsHalVisualizerTargetTest" } ] } diff --git a/audio/aidl/default/visualizer/VisualizerSw.cpp b/audio/aidl/default/visualizer/VisualizerSw.cpp index b898c009aa..37eb30bc48 100644 --- a/audio/aidl/default/visualizer/VisualizerSw.cpp +++ b/audio/aidl/default/visualizer/VisualizerSw.cpp @@ -14,14 +14,9 @@ * limitations under the License. */ -#include #define LOG_TAG "AHAL_VisualizerSw" -#include -#include -#include #include -#include #include "VisualizerSw.h" @@ -60,7 +55,10 @@ extern "C" binder_exception_t queryEffect(const AudioUuid* in_impl_uuid, Descrip namespace aidl::android::hardware::audio::effect { const std::string VisualizerSw::kEffectName = "VisualizerSw"; -const Visualizer::Capability VisualizerSw::kCapability; +/* capabilities */ +const Visualizer::CaptureSizeRange mCaptureSizeRange = {MIN_CAPTURE_SIZE, MAX_CAPTURE_SIZE}; +const Visualizer::Capability VisualizerSw::kCapability = {.maxLatencyMs = MAX_LATENCY, + .captureSizeRange = mCaptureSizeRange}; const Descriptor VisualizerSw::kDescriptor = { .common = {.id = {.type = kVisualizerTypeUUID, .uuid = kVisualizerSwImplUUID, @@ -82,8 +80,53 @@ ndk::ScopedAStatus VisualizerSw::setParameterSpecific(const Parameter::Specific& RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT, "EffectNotSupported"); - mSpecificParam = specific.get(); - LOG(DEBUG) << __func__ << " success with: " << specific.toString(); + auto& vsParam = specific.get(); + auto tag = vsParam.getTag(); + + switch (tag) { + case Visualizer::captureSizeBytes: { + RETURN_IF(mContext->setVsCaptureSize(vsParam.get()) != + RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "captureSizeNotSupported"); + return ndk::ScopedAStatus::ok(); + } + case Visualizer::scalingMode: { + RETURN_IF(mContext->setVsScalingMode(vsParam.get()) != + RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "scalingModeNotSupported"); + return ndk::ScopedAStatus::ok(); + } + case Visualizer::measurementMode: { + RETURN_IF(mContext->setVsMeasurementMode(vsParam.get()) != + RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "measurementModeNotSupported"); + return ndk::ScopedAStatus::ok(); + } + case Visualizer::setOnlyParameters: { + return setSetOnlyParameterVisualizer(vsParam.get()); + } + case Visualizer::getOnlyParameters: { + LOG(ERROR) << __func__ << " unsupported settable getOnlyParam"; + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "SetofGetOnlyParamsNotSupported"); + } + default: { + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, + "VisualizerTagNotSupported"); + } + } +} + +ndk::ScopedAStatus VisualizerSw::setSetOnlyParameterVisualizer( + Visualizer::SetOnlyParameters setOnlyParam) { + auto tag = setOnlyParam.getTag(); + RETURN_IF(Visualizer::SetOnlyParameters::latencyMs != tag, EX_ILLEGAL_ARGUMENT, + "SetOnlyParametersTagNotSupported"); + RETURN_IF( + mContext->setVsLatency(setOnlyParam.get()) != + RetCode::SUCCESS, + EX_ILLEGAL_ARGUMENT, "latencyNotSupported"); return ndk::ScopedAStatus::ok(); } @@ -91,7 +134,76 @@ ndk::ScopedAStatus VisualizerSw::getParameterSpecific(const Parameter::Id& id, Parameter::Specific* specific) { auto tag = id.getTag(); RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag"); - specific->set(mSpecificParam); + auto vsId = id.get(); + auto vsIdTag = vsId.getTag(); + switch (vsIdTag) { + case Visualizer::Id::commonTag: + return getParameterVisualizer(vsId.get(), specific); + case Visualizer::Id::getOnlyParamTag: + return getGetOnlyParameterVisualizer(vsId.get(), + specific); + case Visualizer::Id::setOnlyParamTag: { + LOG(ERROR) << __func__ << " unsupported gettable setOnlyParam"; + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "GetofSetOnlyParamsNotSupported"); + } + default: + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, + "VisualizerTagNotSupported"); + } +} +ndk::ScopedAStatus VisualizerSw::getParameterVisualizer(const Visualizer::Tag& tag, + Parameter::Specific* specific) { + RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext"); + + Visualizer vsParam; + switch (tag) { + case Visualizer::captureSizeBytes: { + vsParam.set(mContext->getVsCaptureSize()); + break; + } + case Visualizer::scalingMode: { + vsParam.set(mContext->getVsScalingMode()); + break; + } + case Visualizer::measurementMode: { + vsParam.set(mContext->getVsMeasurementMode()); + break; + } + default: { + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, + "VisualizerTagNotSupported"); + } + } + specific->set(vsParam); + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus VisualizerSw::getGetOnlyParameterVisualizer( + const Visualizer::GetOnlyParameters::Tag& tag, Parameter::Specific* specific) { + Visualizer::GetOnlyParameters getOnlyParam; + switch (tag) { + case Visualizer::GetOnlyParameters::measurement: { + getOnlyParam.set( + mContext->getVsMeasurement()); + break; + } + case Visualizer::GetOnlyParameters::captureBytes: { + getOnlyParam.set( + mContext->getVsCaptureBytes()); + break; + } + default: { + LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag); + return ndk::ScopedAStatus::fromExceptionCodeWithMessage( + EX_ILLEGAL_ARGUMENT, "GetOnlyParameterTagNotSupported"); + } + } + Visualizer vsParam; + vsParam.set(getOnlyParam); + specific->set(vsParam); return ndk::ScopedAStatus::ok(); } diff --git a/audio/aidl/default/visualizer/VisualizerSw.h b/audio/aidl/default/visualizer/VisualizerSw.h index 24b92dde4d..a95537cb5a 100644 --- a/audio/aidl/default/visualizer/VisualizerSw.h +++ b/audio/aidl/default/visualizer/VisualizerSw.h @@ -17,13 +17,16 @@ #pragma once #include -#include -#include -#include +#include #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 { @@ -31,8 +34,55 @@ class VisualizerSwContext final : public EffectContext { VisualizerSwContext(int statusDepth, const Parameter::Common& common) : EffectContext(statusDepth, common) { LOG(DEBUG) << __func__; + mCaptureBytes.resize(CAPTURE_BUF_SIZE); + fill(mCaptureBytes.begin(), mCaptureBytes.end(), 0x80); } - // TODO: add specific context here + + RetCode setVsCaptureSize(int captureSize) { + if (captureSize < MIN_CAPTURE_SIZE || captureSize > MAX_CAPTURE_SIZE) { + LOG(ERROR) << __func__ << " invalid captureSize " << captureSize; + return RetCode::ERROR_ILLEGAL_PARAMETER; + } + // TODO : Add implementation to apply new captureSize + mCaptureSize = captureSize; + return RetCode::SUCCESS; + } + int getVsCaptureSize() const { return mCaptureSize; } + + RetCode setVsScalingMode(Visualizer::ScalingMode scalingMode) { + // TODO : Add implementation to apply new scalingMode + mScalingMode = scalingMode; + return RetCode::SUCCESS; + } + Visualizer::ScalingMode getVsScalingMode() const { return mScalingMode; } + + RetCode setVsMeasurementMode(Visualizer::MeasurementMode measurementMode) { + // TODO : Add implementation to apply new measurementMode + mMeasurementMode = measurementMode; + return RetCode::SUCCESS; + } + Visualizer::MeasurementMode getVsMeasurementMode() const { return mMeasurementMode; } + + RetCode setVsLatency(int latency) { + if (latency < 0 || latency > MAX_LATENCY) { + LOG(ERROR) << __func__ << " invalid latency " << latency; + return RetCode::ERROR_ILLEGAL_PARAMETER; + } + // TODO : Add implementation to modify latency + mLatency = latency; + return RetCode::SUCCESS; + } + + Visualizer::GetOnlyParameters::Measurement getVsMeasurement() const { return mMeasurement; } + std::vector getVsCaptureBytes() const { return mCaptureBytes; } + + private: + int mCaptureSize = MAX_CAPTURE_SIZE; + Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED; + Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE; + int mLatency; + const Visualizer::GetOnlyParameters::Measurement mMeasurement = {0, 0}; + std::vector mCaptureBytes; }; class VisualizerSw final : public EffectImpl { @@ -60,7 +110,11 @@ class VisualizerSw final : public EffectImpl { private: std::shared_ptr mContext; - /* parameters */ - Visualizer mSpecificParam; + + ndk::ScopedAStatus setSetOnlyParameterVisualizer(Visualizer::SetOnlyParameters setOnlyParam); + ndk::ScopedAStatus getParameterVisualizer(const Visualizer::Tag& tag, + Parameter::Specific* specific); + ndk::ScopedAStatus getGetOnlyParameterVisualizer(const Visualizer::GetOnlyParameters::Tag& tag, + Parameter::Specific* specific); }; } // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp index 068742d862..4414e26e95 100644 --- a/audio/aidl/vts/Android.bp +++ b/audio/aidl/vts/Android.bp @@ -83,3 +83,9 @@ cc_test { defaults: ["VtsHalAudioTargetTestDefaults"], srcs: ["VtsHalLoudnessEnhancerTargetTest.cpp"], } + +cc_test { + name: "VtsHalVisualizerTargetTest", + defaults: ["VtsHalAudioTargetTestDefaults"], + srcs: ["VtsHalVisualizerTargetTest.cpp"], +} diff --git a/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp new file mode 100644 index 0000000000..a7834fbb9c --- /dev/null +++ b/audio/aidl/vts/VtsHalVisualizerTargetTest.cpp @@ -0,0 +1,329 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#define LOG_TAG "VtsHalVisualizerTest" + +#include +#include "EffectHelper.h" + +using namespace android; + +using aidl::android::hardware::audio::effect::Capability; +using aidl::android::hardware::audio::effect::Descriptor; +using aidl::android::hardware::audio::effect::IEffect; +using aidl::android::hardware::audio::effect::IFactory; +using aidl::android::hardware::audio::effect::kVisualizerTypeUUID; +using aidl::android::hardware::audio::effect::Parameter; +using aidl::android::hardware::audio::effect::Visualizer; + +/** + * Here we focus on specific parameter checking, general IEffect interfaces testing performed in + * VtsAudioEffectTargetTest. + */ +enum ParamName { + PARAM_INSTANCE_NAME, + PARAM_CAPTURE_SIZE, + PARAM_SCALING_MODE, + PARAM_MEASUREMENT_MODE, + PARAM_LATENCY, +}; +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: + VisualizerParamTest() + : mCaptureSize(std::get(GetParam())), + mScalingMode(std::get(GetParam())), + mMeasurementMode(std::get(GetParam())), + mLatency(std::get(GetParam())) { + std::tie(mFactory, mDescriptor) = std::get(GetParam()); + } + + void SetUp() override { + ASSERT_NE(nullptr, mFactory); + ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor)); + + Parameter::Specific specific = getDefaultParamSpecific(); + 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, specific, &ret, EX_NONE)); + ASSERT_NE(nullptr, mEffect); + } + + void TearDown() override { + ASSERT_NO_FATAL_FAILURE(close(mEffect)); + ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect)); + } + + Parameter::Specific getDefaultParamSpecific() { + Visualizer vs = Visualizer::make(MIN_CAPTURE_SIZE); + Parameter::Specific specific = + Parameter::Specific::make(vs); + return specific; + } + + static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100; + std::shared_ptr mFactory; + std::shared_ptr mEffect; + Descriptor mDescriptor; + int mCaptureSize = MAX_CAPTURE_SIZE; + Visualizer::ScalingMode mScalingMode = Visualizer::ScalingMode::NORMALIZED; + Visualizer::MeasurementMode mMeasurementMode = Visualizer::MeasurementMode::NONE; + int mLatency = 0; + + void SetAndGetCommonParameters() { + for (auto& it : mCommonTags) { + auto& tag = it.first; + auto& vs = it.second; + + // validate parameter + Descriptor desc; + ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc)); + const bool valid = isTagInRange(tag, vs, desc); + const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT; + + // set parameter + Parameter expectParam; + Parameter::Specific specific; + specific.set(vs); + expectParam.set(specific); + EXPECT_STATUS(expected, mEffect->setParameter(expectParam)) << expectParam.toString(); + + // only get if parameter in range and set success + if (expected == EX_NONE) { + Parameter getParam; + Parameter::Id id; + Visualizer::Id vsId; + vsId.set(tag); + id.set(vsId); + EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam)); + + EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString() + << "\ngetParam:" << getParam.toString(); + } + } + } + + void SetAndGetSetOnlyParameters() { + for (auto& it : mSetOnlyParamTags) { + auto& tag = it.first; + auto& vs = it.second; + + // validate parameter + Descriptor desc; + ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc)); + const bool valid = isSetOnlyParamTagInRange(tag, vs, desc); + const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT; + + // set parameter + Parameter expectParam; + Parameter::Specific specific; + specific.set(vs); + expectParam.set(specific); + ASSERT_STATUS(expected, mEffect->setParameter(expectParam)); + + // parameter defined in this setOnlyParameter union must be settable via + // setParameter(), but must not be gettable + Parameter getParam; + Parameter::Id id; + Visualizer::Id vsId; + vsId.set(tag); + id.set(vsId); + EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, mEffect->getParameter(id, &getParam)); + } + } + + void GetandSetGetOnlyParameters() { + for (auto& tag : mGetOnlyParamTags) { + // get parameter + Parameter getParam; + Parameter::Id id; + Visualizer::Id vsId; + vsId.set(tag); + id.set(vsId); + ASSERT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam)); + + // parameter defined in this getOnlyParameter union must be gettable via + // getParameter(), but must not be settable + // set parameter + ASSERT_STATUS(EX_ILLEGAL_ARGUMENT, mEffect->setParameter(getParam)); + } + } + + void addCaptureSizeParam(int captureSize) { + Visualizer vs; + vs.set(captureSize); + mCommonTags.push_back({Visualizer::captureSizeBytes, vs}); + } + + void addScalingModeParam(Visualizer::ScalingMode scalingMode) { + Visualizer vs; + vs.set(scalingMode); + mCommonTags.push_back({Visualizer::scalingMode, vs}); + } + + void addMeasurementModeParam(Visualizer::MeasurementMode measurementMode) { + Visualizer vs; + vs.set(measurementMode); + mCommonTags.push_back({Visualizer::measurementMode, vs}); + } + + void addLatencyParam(int latency) { + Visualizer vs; + Visualizer::SetOnlyParameters setOnlyParam; + setOnlyParam.set(latency); + vs.set(setOnlyParam); + mSetOnlyParamTags.push_back({Visualizer::SetOnlyParameters::latencyMs, vs}); + } + + void addMeasurementTag() { + mGetOnlyParamTags.push_back(Visualizer::GetOnlyParameters::measurement); + } + + void addCaptureBytesTag() { + mGetOnlyParamTags.push_back(Visualizer::GetOnlyParameters::captureBytes); + } + + bool isTagInRange(const Visualizer::Tag& tag, const Visualizer& vs, + const Descriptor& desc) const { + const Visualizer::Capability& vsCap = desc.capability.get(); + switch (tag) { + case Visualizer::captureSizeBytes: { + int captureSize = vs.get(); + return isCaptureSizeInRange(vsCap, captureSize); + } + case Visualizer::scalingMode: + case Visualizer::measurementMode: + return true; + default: + return false; + } + } + + bool isSetOnlyParamTagInRange(Visualizer::SetOnlyParameters::Tag, const Visualizer& vs, + const Descriptor& desc) const { + const Visualizer::Capability& vsCap = desc.capability.get(); + if (vs.getTag() != Visualizer::setOnlyParameters) return false; + Visualizer::SetOnlyParameters setOnlyParam = vs.get(); + if (setOnlyParam.getTag() != Visualizer::SetOnlyParameters::latencyMs) return false; + int latency = setOnlyParam.get(); + return isLatencyInRange(vsCap, latency); + } + + bool isCaptureSizeInRange(const Visualizer::Capability& cap, int captureSize) const { + return (captureSize >= cap.captureSizeRange.minBytes && + captureSize <= cap.captureSizeRange.maxBytes); + } + + bool isLatencyInRange(const Visualizer::Capability& cap, int latency) const { + return (latency >= 0 && latency <= cap.maxLatencyMs); + } + + private: + std::vector> mCommonTags; + std::vector> mSetOnlyParamTags; + std::vector mGetOnlyParamTags; + void CleanUp() { + mCommonTags.clear(); + mSetOnlyParamTags.clear(); + mGetOnlyParamTags.clear(); + } +}; + +TEST_P(VisualizerParamTest, SetAndGetCaptureSize) { + EXPECT_NO_FATAL_FAILURE(addCaptureSizeParam(mCaptureSize)); + SetAndGetCommonParameters(); +} + +TEST_P(VisualizerParamTest, SetAndGetScalingMode) { + EXPECT_NO_FATAL_FAILURE(addScalingModeParam(mScalingMode)); + SetAndGetCommonParameters(); +} + +TEST_P(VisualizerParamTest, SetAndGetMeasurementMode) { + EXPECT_NO_FATAL_FAILURE(addMeasurementModeParam(mMeasurementMode)); + SetAndGetCommonParameters(); +} + +TEST_P(VisualizerParamTest, SetAndGetLatency) { + EXPECT_NO_FATAL_FAILURE(addLatencyParam(mLatency)); + SetAndGetSetOnlyParameters(); +} + +TEST_P(VisualizerParamTest, GetAndSetMeasurement) { + EXPECT_NO_FATAL_FAILURE(addMeasurementTag()); + GetandSetGetOnlyParameters(); +} + +TEST_P(VisualizerParamTest, GetAndSetCaptureBytes) { + EXPECT_NO_FATAL_FAILURE(addCaptureBytesTag()); + GetandSetGetOnlyParameters(); +} + +INSTANTIATE_TEST_SUITE_P( + VisualizerTest, VisualizerParamTest, + ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors( + IFactory::descriptor, kVisualizerTypeUUID)), + testing::ValuesIn(kCaptureSizeValues), + testing::ValuesIn(kScalingModeValues), + testing::ValuesIn(kMeasurementModeValues), + testing::ValuesIn(kLatencyValues)), + [](const testing::TestParamInfo& info) { + auto descriptor = std::get(info.param).second; + std::string captureSize = std::to_string(std::get(info.param)); + std::string scalingMode = + std::to_string(static_cast(std::get(info.param))); + std::string measurementMode = + std::to_string(static_cast(std::get(info.param))); + std::string latency = std::to_string(std::get(info.param)); + + std::string name = "Implementor_" + descriptor.common.implementor + "_name_" + + descriptor.common.name + "_UUID_" + + descriptor.common.id.uuid.toString() + "_captureSize" + captureSize + + "_scalingMode" + scalingMode + "_measurementMode" + measurementMode + + "_latency" + latency; + std::replace_if( + name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_'); + return name; + }); + +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VisualizerParamTest); + +int main(int argc, char** argv) { + ::testing::InitGoogleTest(&argc, argv); + ABinderProcess_setThreadPoolMaxThreadCount(1); + ABinderProcess_startThreadPool(); + return RUN_ALL_TESTS(); +} \ No newline at end of file