diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp index 40aa22922d..4e50b7ab50 100644 --- a/audio/aidl/Android.bp +++ b/audio/aidl/Android.bp @@ -156,6 +156,7 @@ aidl_interface { "android/hardware/audio/effect/IEffect.aidl", "android/hardware/audio/effect/IFactory.aidl", "android/hardware/audio/effect/Parameter.aidl", + "android/hardware/audio/effect/Processing.aidl", "android/hardware/audio/effect/State.aidl", ], imports: [ diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl index 1c86cf3f3a..07b25f8896 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl @@ -53,10 +53,11 @@ parcelable Descriptor { parcelable Identity { android.media.audio.common.AudioUuid type; android.media.audio.common.AudioUuid uuid; + @nullable android.media.audio.common.AudioUuid proxy; + android.hardware.audio.effect.Flags flags; } @VintfStability parcelable Common { android.hardware.audio.effect.Descriptor.Identity id; - android.hardware.audio.effect.Flags flags; } } diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl index db06475cde..a22c591cd3 100644 --- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl @@ -35,6 +35,7 @@ package android.hardware.audio.effect; @VintfStability interface IFactory { android.hardware.audio.effect.Descriptor.Identity[] queryEffects(in @nullable android.media.audio.common.AudioUuid type, in @nullable android.media.audio.common.AudioUuid implementation); + android.hardware.audio.effect.Processing[] queryProcessing(in @nullable android.hardware.audio.effect.Processing.Type type); android.hardware.audio.effect.IEffect createEffect(in android.media.audio.common.AudioUuid implUuid); void destroyEffect(in android.hardware.audio.effect.IEffect handle); } diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl new file mode 100644 index 0000000000..a779ae4c84 --- /dev/null +++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl @@ -0,0 +1,44 @@ +/* + * 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. + */ +/////////////////////////////////////////////////////////////////////////////// +// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. // +/////////////////////////////////////////////////////////////////////////////// + +// This file is a snapshot of an AIDL file. Do not edit it manually. There are +// two cases: +// 1). this is a frozen version file - do not edit this in any case. +// 2). this is a 'current' file. If you make a backwards compatible change to +// the interface (from the latest frozen version), the build system will +// prompt you to update this file with `m -update-api`. +// +// You must not make a backward incompatible change to any AIDL file built +// with the aidl_interface module type with versions property set. The module +// type is used to build AIDL files in a way that they can be used across +// independently updatable components of the system. If a device is shipped +// with such a backward incompatible change, it has a high risk of breaking +// later when a module using the interface is updated, e.g., Mainline modules. + +package android.hardware.audio.effect; +@VintfStability +parcelable Processing { + android.hardware.audio.effect.Processing.Type type; + android.hardware.audio.effect.Descriptor.Identity[] ids; + @VintfStability + union Type { + android.media.audio.common.AudioStreamType streamType = android.media.audio.common.AudioStreamType.INVALID; + android.media.audio.common.AudioSource source; + } +} diff --git a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl index aca9bbe326..9c18f2ef0f 100644 --- a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl +++ b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl @@ -23,6 +23,13 @@ import android.media.audio.common.AudioUuid; /** * Descriptor contains all information (capabilities, attributes, etc) for an effect implementation. * The client uses this information to decide when and how to apply an effect implementation. + * + * Each type of effect can have more than one implementation (differentiated by implementation + * UUID), the effect proxy act as a combination of two implementations (usually one software and + * one offload implementation), so effect processing can be seamlessly switched between + * implementations in same proxy depending on the configuration and/or use case. If the optional + * proxy UUID is specified in Descriptor.Identity, then client must consider the effect instance as + * part of the effect proxy. */ @VintfStability parcelable Descriptor { @@ -69,6 +76,15 @@ parcelable Descriptor { * UUID for this particular implementation. */ AudioUuid uuid; + /** + * Optional proxy UUID. This field must be set to the proxy effect type UUID if the effect + * implementation is part of a proxy effect. + */ + @nullable AudioUuid proxy; + /** + * Capability flags defined for the effect implementation. + */ + Flags flags; } // Common attributes of all effect implementation. @@ -78,10 +94,6 @@ parcelable Descriptor { * Identity of effect implementation. */ Identity id; - /** - * Effect engine defined capabilities/requirements flags. - */ - Flags flags; } Common common; diff --git a/audio/aidl/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/android/hardware/audio/effect/IFactory.aidl index 4873d3a825..db26e613de 100644 --- a/audio/aidl/android/hardware/audio/effect/IFactory.aidl +++ b/audio/aidl/android/hardware/audio/effect/IFactory.aidl @@ -18,6 +18,7 @@ package android.hardware.audio.effect; import android.hardware.audio.effect.Descriptor; import android.hardware.audio.effect.IEffect; +import android.hardware.audio.effect.Processing; import android.media.audio.common.AudioUuid; /** @@ -44,6 +45,16 @@ interface IFactory { Descriptor.Identity[] queryEffects( in @nullable AudioUuid type, in @nullable AudioUuid implementation); + /** + * Return a list of defined processings, with the optional filter by Processing type. + * An effect can exist more than once in the returned list, which means this effect must be used + * in more than one processing type. + * + * @param type Type of processing to query, can be AudioStreamType or AudioSource. + * @return list of processing defined with the optional filter by Processing.Type. + */ + Processing[] queryProcessing(in @nullable Processing.Type type); + /** * Called by the audio framework to create the effect (identified by the implementation UUID * parameter). diff --git a/audio/aidl/android/hardware/audio/effect/Processing.aidl b/audio/aidl/android/hardware/audio/effect/Processing.aidl new file mode 100644 index 0000000000..ef32e8c904 --- /dev/null +++ b/audio/aidl/android/hardware/audio/effect/Processing.aidl @@ -0,0 +1,44 @@ +/* + * 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 android.hardware.audio.effect; + +import android.hardware.audio.effect.Descriptor; +import android.media.audio.common.AudioSource; +import android.media.audio.common.AudioStreamType; +import android.media.audio.common.AudioUuid; + +/** + * List of effects which must be used for certain pre-processing or post-processing. + */ +@VintfStability +parcelable Processing { + @VintfStability + union Type { + AudioStreamType streamType = AudioStreamType.INVALID; + AudioSource source; + } + + /** + * Specifies the type of processing by referring to the output stream type (AudioStreamType) or + * the input stream source (AudioSource). + */ + Type type; + /** + * List of effect identities for this processing. + */ + Descriptor.Identity[] ids; +} diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp index 4877956ef7..8e107a2bca 100644 --- a/audio/aidl/default/EffectFactory.cpp +++ b/audio/aidl/default/EffectFactory.cpp @@ -73,6 +73,17 @@ ndk::ScopedAStatus Factory::queryEffects(const std::optional& in_type return ndk::ScopedAStatus::ok(); } +ndk::ScopedAStatus Factory::queryProcessing(const std::optional& in_type, + std::vector* _aidl_return) { + // TODO: implement this with audio_effect.xml. + if (in_type.has_value()) { + // return all matching process filter + LOG(DEBUG) << __func__ << " process type: " << in_type.value().toString(); + } + LOG(DEBUG) << __func__ << " return " << _aidl_return->size(); + return ndk::ScopedAStatus::ok(); +} + #define RETURN_IF_BINDER_EXCEPTION(functor) \ { \ binder_exception_t exception = functor; \ diff --git a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h index d3730489bb..6195d8a25e 100644 --- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h +++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h @@ -42,6 +42,16 @@ class Factory : public BnFactory { const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_instance, std::vector* out_descriptor) override; + /** + * @brief Query list of defined processing, with the optional filter by AudioStreamType + * + * @param in_type Type of processing, could be AudioStreamType or AudioSource. Optional. + * @param _aidl_return List of processing filtered by in_type. + * @return ndk::ScopedAStatus + */ + ndk::ScopedAStatus queryProcessing(const std::optional& in_type, + std::vector* _aidl_return) override; + /** * @brief Create an effect instance for a certain implementation (identified by UUID). * diff --git a/audio/aidl/vts/EffectFactoryHelper.h b/audio/aidl/vts/EffectFactoryHelper.h index 3cbca45eb4..cf94e580b4 100644 --- a/audio/aidl/vts/EffectFactoryHelper.h +++ b/audio/aidl/vts/EffectFactoryHelper.h @@ -31,6 +31,7 @@ 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::Parameter; +using aidl::android::hardware::audio::effect::Processing; using aidl::android::media::audio::common::AudioUuid; class EffectFactoryHelper { @@ -57,6 +58,16 @@ class EffectFactoryHelper { mIds = *_aidl_return; } + void QueryProcessing(const std::optional& in_type, + std::vector* _aidl_return) { + ASSERT_NE(mEffectFactory, nullptr); + EXPECT_IS_OK(mEffectFactory->queryProcessing(in_type, _aidl_return)); + // only update the whole list if no filter applied + if (!in_type.has_value()) { + mProcesses = *_aidl_return; + } + } + void CreateEffects() { ASSERT_NE(mEffectFactory, nullptr); for (const auto& id : mIds) { @@ -127,6 +138,7 @@ class EffectFactoryHelper { AudioHalBinderServiceUtil binderUtil; std::vector mIds; std::vector mCompleteIds; + std::vector mProcesses; std::map, Descriptor::Identity> mEffectIdMap; }; diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp index dd17a6fc0d..454ce29e6c 100644 --- a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp +++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp @@ -38,6 +38,7 @@ using namespace android; using aidl::android::hardware::audio::effect::Descriptor; using aidl::android::hardware::audio::effect::IFactory; +using aidl::android::hardware::audio::effect::Processing; using aidl::android::media::audio::common::AudioUuid; /// Effect factory testing. @@ -222,6 +223,12 @@ TEST_P(EffectFactoryTest, CreateRestartAndCreateDestroy) { EXPECT_EQ(effectMap.size(), 0UL); } +TEST_P(EffectFactoryTest, QueryProcess) { + std::vector processing; + mFactory.QueryProcessing(std::nullopt, &processing); + // TODO: verify the number of process in example implementation after audio_effects.xml migrated +} + INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactoryTest, testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)), android::PrintInstanceNameToString);