diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp index ad933bc78b..d6e6f50ae9 100644 --- a/audio/aidl/Android.bp +++ b/audio/aidl/Android.bp @@ -166,3 +166,19 @@ aidl_interface { }, }, } + +latest_android_hardware_audio_effect = "android.hardware.audio.effect-V1" + +cc_defaults { + name: "latest_android_hardware_audio_effect_ndk_shared", + shared_libs: [ + latest_android_hardware_audio_effect + "-ndk", + ], +} + +cc_defaults { + name: "latest_android_hardware_audio_effect_ndk_static", + static_libs: [ + latest_android_hardware_audio_effect + "-ndk", + ], +} diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp index 5d63347569..53ed908908 100644 --- a/audio/aidl/default/Android.bp +++ b/audio/aidl/default/Android.bp @@ -68,6 +68,7 @@ cc_defaults { "libbase", "libbinder_ndk", "android.hardware.audio.effect-V1-ndk", + "libequalizer", ], cflags: [ "-Wall", @@ -80,7 +81,10 @@ cc_defaults { cc_library_static { name: "libaudioeffectserviceexampleimpl", defaults: ["aidlaudioeffectservice_defaults"], - export_include_dirs: ["include"], + export_include_dirs: [ + "include", + "include/equalizer-impl/", + ], srcs: [ "EffectFactory.cpp", ], diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp index a31e23f8db..ea9d470e9c 100644 --- a/audio/aidl/default/EffectFactory.cpp +++ b/audio/aidl/default/EffectFactory.cpp @@ -36,6 +36,8 @@ Factory::Factory() { {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; id.uuid = EqualizerUUID; mIdentityList.push_back(id); + // TODO: Add visualizer with default implementation later +#if 0 id.type = {static_cast(0xd3467faa), 0xacc7, 0x4d34, @@ -43,6 +45,7 @@ Factory::Factory() { {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; id.uuid = VisualizerUUID; mIdentityList.push_back(id); +#endif } ndk::ScopedAStatus Factory::queryEffects(const std::optional& in_type, @@ -56,4 +59,28 @@ ndk::ScopedAStatus Factory::queryEffects(const std::optional& in_type return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus Factory::createEffect( + const AudioUuid& in_impl_uuid, + std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>* _aidl_return) { + LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString(); + if (in_impl_uuid == EqualizerUUID) { + *_aidl_return = ndk::SharedRefBase::make(); + } else { + LOG(ERROR) << __func__ << ": UUID " + << " not supported"; + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Factory::destroyEffect( + const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_handle) { + if (in_handle) { + // TODO: b/245393900 need check the instance state with IEffect.getState before destroy. + return ndk::ScopedAStatus::ok(); + } else { + return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT); + } +} + } // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/EffectMain.cpp b/audio/aidl/default/EffectMain.cpp index 3b3c39b7aa..b30f2e7c12 100644 --- a/audio/aidl/default/EffectMain.cpp +++ b/audio/aidl/default/EffectMain.cpp @@ -23,10 +23,11 @@ int main() { // This is a debug implementation, always enable debug logging. android::base::SetMinimumLogSeverity(::android::base::DEBUG); - ABinderProcess_setThreadPoolMaxThreadCount(16); + ABinderProcess_setThreadPoolMaxThreadCount(1); auto effectFactory = ndk::SharedRefBase::make(); + std::string serviceName = std::string() + effectFactory->descriptor + "/default"; binder_status_t status = AServiceManager_addService(effectFactory->asBinder().get(), serviceName.c_str()); diff --git a/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc b/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc index 01c0e6e6e6..68bbf5b076 100644 --- a/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc +++ b/audio/aidl/default/android.hardware.audio.effect.service-aidl.example.rc @@ -2,7 +2,7 @@ service vendor.audio-effect-hal-aidl /vendor/bin/hw/android.hardware.audio.effec class hal user audioserver # media gid needed for /dev/fm (radio) and for /data/misc/media (tee) - group audio camera drmrpc inet media mediadrm net_bt net_bt_admin net_bw_acct wakelock context_hub + group audio media capabilities BLOCK_SUSPEND ioprio rt 4 task_profiles ProcessCapacityHigh HighPerformance diff --git a/audio/aidl/default/equalizer/Android.bp b/audio/aidl/default/equalizer/Android.bp new file mode 100644 index 0000000000..b842149241 --- /dev/null +++ b/audio/aidl/default/equalizer/Android.bp @@ -0,0 +1,45 @@ +/* + * 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. + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "hardware_interfaces_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["hardware_interfaces_license"], +} + +cc_library_shared { + name: "libequalizer", + vendor: true, + shared_libs: [ + "libbase", + "libbinder_ndk", + "libstagefright_foundation", + ], + defaults: [ + "latest_android_media_audio_common_types_ndk_shared", + "latest_android_hardware_audio_effect_ndk_shared", + ], + include_dirs: ["hardware/interfaces/audio/aidl/default/include/equalizer-impl"], + srcs: [ + "Equalizer.cpp", + ], + visibility: [ + "//hardware/interfaces/audio/aidl/default", + ], +} diff --git a/audio/aidl/default/equalizer/Equalizer.cpp b/audio/aidl/default/equalizer/Equalizer.cpp new file mode 100644 index 0000000000..dae3ab7737 --- /dev/null +++ b/audio/aidl/default/equalizer/Equalizer.cpp @@ -0,0 +1,49 @@ +/* + * 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. + */ + +#define LOG_TAG "AHAL_Equalizer" +#include + +#include "Equalizer.h" + +namespace aidl::android::hardware::audio::effect { + +Equalizer::Equalizer() { + // Implementation UUID + mDesc.common.id.uuid = {static_cast(0xce772f20), + 0x847d, + 0x11df, + 0xbb17, + {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; +} + +ndk::ScopedAStatus Equalizer::open() { + LOG(DEBUG) << __func__; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Equalizer::close() { + LOG(DEBUG) << __func__; + return ndk::ScopedAStatus::ok(); +} + +ndk::ScopedAStatus Equalizer::getDescriptor(Descriptor* _aidl_return) { + LOG(DEBUG) << __func__ << "descriptor " << mDesc.toString(); + *_aidl_return = mDesc; + return ndk::ScopedAStatus::ok(); +} + +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h index 7670250834..8da55258cf 100644 --- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h +++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h @@ -40,6 +40,28 @@ class Factory : public BnFactory { const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_instance, std::vector* out_descriptor) override; + /** + * @brief Create an effect instance for a certain implementation (identified by UUID). + * + * @param in_impl_uuid Effect implementation UUID. + * @param _aidl_return A pointer to created effect instance. + * @return ndk::ScopedAStatus + */ + ndk::ScopedAStatus createEffect( + const ::aidl::android::media::audio::common::AudioUuid& in_impl_uuid, + std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>* _aidl_return) + override; + + /** + * @brief Destroy an effect instance. + * + * @param in_handle Effect instance handle. + * @return ndk::ScopedAStatus + */ + ndk::ScopedAStatus destroyEffect( + const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_handle) + override; + private: // List of effect descriptors supported by the devices. std::vector mIdentityList; diff --git a/audio/aidl/default/include/equalizer-impl/Equalizer.h b/audio/aidl/default/include/equalizer-impl/Equalizer.h index 86f8c3ad2e..44b1d6deff 100644 --- a/audio/aidl/default/include/equalizer-impl/Equalizer.h +++ b/audio/aidl/default/include/equalizer-impl/Equalizer.h @@ -16,16 +16,28 @@ #pragma once +#include #include namespace aidl::android::hardware::audio::effect { // Equalizer implementation UUID. static const ::aidl::android::media::audio::common::AudioUuid EqualizerUUID = { - static_cast(0xce772f20), - 0x847d, - 0x11df, - 0xbb17, + static_cast(0x0bed4300), + 0xddd6, + 0x11db, + 0x8f34, {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}}; -} // namespace aidl::android::hardware::audio::effect \ No newline at end of file +class Equalizer : public BnEffect { + public: + Equalizer(); + ndk::ScopedAStatus open() override; + ndk::ScopedAStatus close() override; + ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override; + + private: + // Effect descriptor. + Descriptor mDesc = {.common.id.type = EqualizerUUID}; +}; +} // namespace aidl::android::hardware::audio::effect diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp index f70948c3be..9b100b1959 100644 --- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp +++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp @@ -14,7 +14,11 @@ * limitations under the License. */ +#include #include +#include +#include +#include #define LOG_TAG "VtsHalAudioEffect" @@ -35,37 +39,88 @@ using namespace android; using ndk::ScopedAStatus; using aidl::android::hardware::audio::effect::Descriptor; +using aidl::android::hardware::audio::effect::IEffect; using aidl::android::hardware::audio::effect::IFactory; using aidl::android::media::audio::common::AudioUuid; -namespace ndk { -std::ostream& operator<<(std::ostream& str, const ScopedAStatus& status) { - str << status.getDescription(); - return str; -} -} // namespace ndk - -class EffectFactory : public testing::TestWithParam { +class EffectFactoryHelper { public: - void SetUp() override { ASSERT_NO_FATAL_FAILURE(ConnectToService()); } + EffectFactoryHelper(const std::string& name) : mServiceName(name) {} - void TearDown() override {} - - void ConnectToService() { - serviceName = GetParam(); - factory = IFactory::fromBinder(binderUtil.connectToService(serviceName)); - ASSERT_NE(factory, nullptr); + void ConnectToFactoryService() { + mEffectFactory = IFactory::fromBinder(binderUtil.connectToService(mServiceName)); + ASSERT_NE(mEffectFactory, nullptr); } - void RestartService() { - ASSERT_NE(factory, nullptr); - factory = IFactory::fromBinder(binderUtil.restartService()); - ASSERT_NE(factory, nullptr); + void RestartFactoryService() { + ASSERT_NE(mEffectFactory, nullptr); + mEffectFactory = IFactory::fromBinder(binderUtil.restartService()); + ASSERT_NE(mEffectFactory, nullptr); } - std::shared_ptr factory; - std::string serviceName; + void QueryAllEffects() { + EXPECT_NE(mEffectFactory, nullptr); + ScopedAStatus status = + mEffectFactory->queryEffects(std::nullopt, std::nullopt, &mCompleteIds); + EXPECT_EQ(status.getExceptionCode(), EX_NONE); + } + + void QueryEffects(const std::optional& in_type, + const std::optional& in_instance, + std::vector* _aidl_return) { + EXPECT_NE(mEffectFactory, nullptr); + ScopedAStatus status = mEffectFactory->queryEffects(in_type, in_instance, _aidl_return); + EXPECT_EQ(status.getExceptionCode(), EX_NONE); + mIds = *_aidl_return; + } + + void CreateEffects() { + EXPECT_NE(mEffectFactory, nullptr); + ScopedAStatus status; + for (const auto& id : mIds) { + std::shared_ptr effect; + status = mEffectFactory->createEffect(id.uuid, &effect); + EXPECT_EQ(status.getExceptionCode(), EX_NONE) << id.toString(); + EXPECT_NE(effect, nullptr) << id.toString(); + mEffectIdMap[effect] = id; + } + } + + void DestroyEffects() { + EXPECT_NE(mEffectFactory, nullptr); + ScopedAStatus status; + for (const auto& it : mEffectIdMap) { + status = mEffectFactory->destroyEffect(it.first); + EXPECT_EQ(status.getExceptionCode(), EX_NONE) << it.second.toString(); + } + mEffectIdMap.clear(); + } + + std::shared_ptr GetFactory() { return mEffectFactory; } + const std::vector& GetEffectIds() { return mIds; } + const std::vector& GetCompleteEffectIdList() { return mCompleteIds; } + const std::unordered_map, Descriptor::Identity>& GetEffectMap() { + return mEffectIdMap; + } + + private: + std::shared_ptr mEffectFactory; + std::string mServiceName; AudioHalBinderServiceUtil binderUtil; + std::vector mIds; + std::vector mCompleteIds; + std::unordered_map, Descriptor::Identity> mEffectIdMap; +}; + +/// Effect factory testing. +class EffectFactoryTest : public testing::TestWithParam { + public: + void SetUp() override { ASSERT_NO_FATAL_FAILURE(mFactory.ConnectToFactoryService()); } + + void TearDown() override { mFactory.DestroyEffects(); } + + EffectFactoryHelper mFactory = EffectFactoryHelper(GetParam()); + // TODO: these UUID can get from config file // ec7178ec-e5e1-4432-a3f4-4657e6795210 const AudioUuid nullUuid = {static_cast(0xec7178ec), @@ -77,25 +132,23 @@ class EffectFactory : public testing::TestWithParam { static_cast(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; }; -TEST_P(EffectFactory, SetupAndTearDown) { +TEST_P(EffectFactoryTest, SetupAndTearDown) { // Intentionally empty test body. } -TEST_P(EffectFactory, CanBeRestarted) { - ASSERT_NO_FATAL_FAILURE(RestartService()); +TEST_P(EffectFactoryTest, CanBeRestarted) { + ASSERT_NO_FATAL_FAILURE(mFactory.RestartFactoryService()); } -TEST_P(EffectFactory, QueriedDescriptorList) { +TEST_P(EffectFactoryTest, QueriedDescriptorList) { std::vector descriptors; - ScopedAStatus status = factory->queryEffects(std::nullopt, std::nullopt, &descriptors); - EXPECT_EQ(EX_NONE, status.getExceptionCode()); + mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors); EXPECT_NE(static_cast(descriptors.size()), 0); } -TEST_P(EffectFactory, DescriptorUUIDNotNull) { +TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) { std::vector descriptors; - ScopedAStatus status = factory->queryEffects(std::nullopt, std::nullopt, &descriptors); - EXPECT_EQ(EX_NONE, status.getExceptionCode()); + mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors); // TODO: Factory eventually need to return the full list of MUST supported AOSP effects. for (auto& desc : descriptors) { EXPECT_NE(desc.type, zeroUuid); @@ -103,28 +156,176 @@ TEST_P(EffectFactory, DescriptorUUIDNotNull) { } } -TEST_P(EffectFactory, QueriedDescriptorNotExistType) { +TEST_P(EffectFactoryTest, QueriedDescriptorNotExistType) { std::vector descriptors; - ScopedAStatus status = factory->queryEffects(nullUuid, std::nullopt, &descriptors); - EXPECT_EQ(EX_NONE, status.getExceptionCode()); + mFactory.QueryEffects(nullUuid, std::nullopt, &descriptors); EXPECT_EQ(static_cast(descriptors.size()), 0); } -TEST_P(EffectFactory, QueriedDescriptorNotExistInstance) { +TEST_P(EffectFactoryTest, QueriedDescriptorNotExistInstance) { std::vector descriptors; - ScopedAStatus status = factory->queryEffects(std::nullopt, nullUuid, &descriptors); - EXPECT_EQ(EX_NONE, status.getExceptionCode()); + mFactory.QueryEffects(std::nullopt, nullUuid, &descriptors); EXPECT_EQ(static_cast(descriptors.size()), 0); } -INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactory, +TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) { + std::vector descriptors; + mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors); + int numIds = static_cast(mFactory.GetEffectIds().size()); + EXPECT_NE(numIds, 0); + + EXPECT_EQ(static_cast(mFactory.GetEffectMap().size()), 0); + mFactory.CreateEffects(); + EXPECT_EQ(static_cast(mFactory.GetEffectMap().size()), numIds); + mFactory.DestroyEffects(); + EXPECT_EQ(static_cast(mFactory.GetEffectMap().size()), 0); + + // Create and destroy again + mFactory.CreateEffects(); + EXPECT_EQ(static_cast(mFactory.GetEffectMap().size()), numIds); + mFactory.DestroyEffects(); + EXPECT_EQ(static_cast(mFactory.GetEffectMap().size()), 0); +} + +TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) { + std::vector descriptors; + mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors); + int numIds = static_cast(mFactory.GetEffectIds().size()); + EXPECT_NE(numIds, 0); + + EXPECT_EQ(static_cast(mFactory.GetEffectMap().size()), 0); + mFactory.CreateEffects(); + EXPECT_EQ(static_cast(mFactory.GetEffectMap().size()), numIds); + // Create effect instances of same implementation + mFactory.CreateEffects(); + EXPECT_EQ(static_cast(mFactory.GetEffectMap().size()), 2 * numIds); + + mFactory.CreateEffects(); + EXPECT_EQ(static_cast(mFactory.GetEffectMap().size()), 3 * numIds); + + mFactory.DestroyEffects(); + EXPECT_EQ(static_cast(mFactory.GetEffectMap().size()), 0); +} + +INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactoryTest, testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)), android::PrintInstanceNameToString); -GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EffectFactory); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EffectFactoryTest); + +/// Effect testing. +class AudioEffect : public testing::TestWithParam { + public: + void SetUp() override { + ASSERT_NO_FATAL_FAILURE(mFactory.ConnectToFactoryService()); + ASSERT_NO_FATAL_FAILURE(mFactory.CreateEffects()); + } + + void TearDown() override { + CloseEffects(); + ASSERT_NO_FATAL_FAILURE(mFactory.DestroyEffects()); + } + + void OpenEffects() { + auto open = [](const std::shared_ptr& effect) { + ScopedAStatus status = effect->open(); + EXPECT_EQ(status.getExceptionCode(), EX_NONE); + }; + EXPECT_NO_FATAL_FAILURE(ForEachEffect(open)); + } + + void CloseEffects() { + auto close = [](const std::shared_ptr& effect) { + ScopedAStatus status = effect->close(); + EXPECT_EQ(status.getExceptionCode(), EX_NONE); + }; + EXPECT_NO_FATAL_FAILURE(ForEachEffect(close)); + } + + void GetEffectDescriptors() { + auto get = [](const std::shared_ptr& effect) { + Descriptor desc; + ScopedAStatus status = effect->getDescriptor(&desc); + EXPECT_EQ(status.getExceptionCode(), EX_NONE); + }; + EXPECT_NO_FATAL_FAILURE(ForEachEffect(get)); + } + + template + void ForEachEffect(Functor functor) { + auto effectMap = mFactory.GetEffectMap(); + ScopedAStatus status; + for (const auto& it : effectMap) { + SCOPED_TRACE(it.second.toString()); + functor(it.first); + } + } + + EffectFactoryHelper mFactory = EffectFactoryHelper(GetParam()); +}; + +TEST_P(AudioEffect, OpenEffectTest) { + EXPECT_NO_FATAL_FAILURE(OpenEffects()); +} + +TEST_P(AudioEffect, OpenAndCloseEffect) { + EXPECT_NO_FATAL_FAILURE(OpenEffects()); + EXPECT_NO_FATAL_FAILURE(CloseEffects()); +} + +TEST_P(AudioEffect, CloseUnopenedEffectTest) { + EXPECT_NO_FATAL_FAILURE(CloseEffects()); +} + +TEST_P(AudioEffect, DoubleOpenCloseEffects) { + EXPECT_NO_FATAL_FAILURE(OpenEffects()); + EXPECT_NO_FATAL_FAILURE(CloseEffects()); + EXPECT_NO_FATAL_FAILURE(OpenEffects()); + EXPECT_NO_FATAL_FAILURE(CloseEffects()); + + EXPECT_NO_FATAL_FAILURE(OpenEffects()); + EXPECT_NO_FATAL_FAILURE(OpenEffects()); + EXPECT_NO_FATAL_FAILURE(CloseEffects()); + + EXPECT_NO_FATAL_FAILURE(OpenEffects()); + EXPECT_NO_FATAL_FAILURE(CloseEffects()); + EXPECT_NO_FATAL_FAILURE(CloseEffects()); +} + +TEST_P(AudioEffect, GetDescriptors) { + EXPECT_NO_FATAL_FAILURE(GetEffectDescriptors()); +} + +TEST_P(AudioEffect, DescriptorIdExistAndUnique) { + auto checker = [&](const std::shared_ptr& effect) { + Descriptor desc; + std::vector idList; + ScopedAStatus status = effect->getDescriptor(&desc); + EXPECT_EQ(status.getExceptionCode(), EX_NONE); + mFactory.QueryEffects(desc.common.id.type, desc.common.id.uuid, &idList); + EXPECT_EQ(static_cast(idList.size()), 1); + }; + EXPECT_NO_FATAL_FAILURE(ForEachEffect(checker)); + + // Check unique with a set + auto stringHash = [](const Descriptor::Identity& id) { + return std::hash()(id.toString()); + }; + auto vec = mFactory.GetCompleteEffectIdList(); + std::unordered_set idSet(0, stringHash); + for (auto it : vec) { + EXPECT_EQ(static_cast(idSet.count(it)), 0); + idSet.insert(it); + } +} + +INSTANTIATE_TEST_SUITE_P(AudioEffectTest, AudioEffect, + testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)), + android::PrintInstanceNameToString); +GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffect); 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 diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml index 894797787b..5f5f95db64 100644 --- a/compatibility_matrices/compatibility_matrix.current.xml +++ b/compatibility_matrices/compatibility_matrix.current.xml @@ -16,7 +16,7 @@ default - + android.hardware.audio.effect 6.0 7.0 @@ -37,7 +37,7 @@ default - + android.hardware.audio.effect 1