Implement AIDL effect IFacotry::queryProcessing

Bug: 281572768
Test: atest --test-mapping hardware/interfaces/audio/aidl/vts:presubmit
Change-Id: I0166786d531437ef52690b92067766879b043a1d
Merged-In: I0166786d531437ef52690b92067766879b043a1d
diff --git a/audio/aidl/default/EffectConfig.cpp b/audio/aidl/default/EffectConfig.cpp
index 5a83fef..71d111b 100644
--- a/audio/aidl/default/EffectConfig.cpp
+++ b/audio/aidl/default/EffectConfig.cpp
@@ -14,12 +14,17 @@
  * limitations under the License.
  */
 
+#include <optional>
+#include <string>
 #define LOG_TAG "AHAL_EffectConfig"
 #include <android-base/logging.h>
+#include <system/audio_effects/audio_effects_conf.h>
 #include <system/audio_effects/effect_uuid.h>
 
 #include "effectFactory-impl/EffectConfig.h"
 
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::AudioStreamType;
 using aidl::android::media::audio::common::AudioUuid;
 
 namespace aidl::android::hardware::audio::effect {
@@ -55,14 +60,16 @@
         // Parse pre processing chains
         for (auto& xmlPreprocess : getChildren(xmlConfig, "preprocess")) {
             for (auto& xmlStream : getChildren(xmlPreprocess, "stream")) {
-                registerFailure(parseStream(xmlStream));
+                // AudioSource
+                registerFailure(parseProcessing(Processing::Type::source, xmlStream));
             }
         }
 
         // Parse post processing chains
         for (auto& xmlPostprocess : getChildren(xmlConfig, "postprocess")) {
             for (auto& xmlStream : getChildren(xmlPostprocess, "stream")) {
-                registerFailure(parseStream(xmlStream));
+                // AudioStreamType
+                registerFailure(parseProcessing(Processing::Type::streamType, xmlStream));
             }
         }
     }
@@ -140,21 +147,6 @@
     return true;
 }
 
-bool EffectConfig::parseStream(const tinyxml2::XMLElement& xml) {
-    LOG(DEBUG) << __func__ << dump(xml);
-    const char* type = xml.Attribute("type");
-    RETURN_VALUE_IF(!type, false, "noTypeInProcess");
-    RETURN_VALUE_IF(0 != mProcessingMap.count(type), false, "duplicateType");
-
-    for (auto& apply : getChildren(xml, "apply")) {
-        const char* name = apply.get().Attribute("effect");
-        RETURN_VALUE_IF(!name, false, "noEffectAttribute");
-        mProcessingMap[type].push_back(name);
-        LOG(DEBUG) << __func__ << " " << type << " : " << name;
-    }
-    return true;
-}
-
 bool EffectConfig::parseLibraryUuid(const tinyxml2::XMLElement& xml,
                                     struct LibraryUuid& libraryUuid, bool isProxy) {
     // Retrieve library name only if not effectProxy element
@@ -174,6 +166,80 @@
     return true;
 }
 
+std::optional<Processing::Type> EffectConfig::stringToProcessingType(Processing::Type::Tag typeTag,
+                                                                     const std::string& type) {
+    // see list of audio stream types in audio_stream_type_t:
+    // system/media/audio/include/system/audio_effects/audio_effects_conf.h
+    // AUDIO_STREAM_DEFAULT_TAG is not listed here because according to SYS_RESERVED_DEFAULT in
+    // AudioStreamType.aidl: "Value reserved for system use only. HALs must never return this value
+    // to the system or accept it from the system".
+    static const std::map<const std::string, AudioStreamType> sAudioStreamTypeTable = {
+            {AUDIO_STREAM_VOICE_CALL_TAG, AudioStreamType::VOICE_CALL},
+            {AUDIO_STREAM_SYSTEM_TAG, AudioStreamType::SYSTEM},
+            {AUDIO_STREAM_RING_TAG, AudioStreamType::RING},
+            {AUDIO_STREAM_MUSIC_TAG, AudioStreamType::MUSIC},
+            {AUDIO_STREAM_ALARM_TAG, AudioStreamType::ALARM},
+            {AUDIO_STREAM_NOTIFICATION_TAG, AudioStreamType::NOTIFICATION},
+            {AUDIO_STREAM_BLUETOOTH_SCO_TAG, AudioStreamType::BLUETOOTH_SCO},
+            {AUDIO_STREAM_ENFORCED_AUDIBLE_TAG, AudioStreamType::ENFORCED_AUDIBLE},
+            {AUDIO_STREAM_DTMF_TAG, AudioStreamType::DTMF},
+            {AUDIO_STREAM_TTS_TAG, AudioStreamType::TTS},
+            {AUDIO_STREAM_ASSISTANT_TAG, AudioStreamType::ASSISTANT}};
+
+    // see list of audio sources in audio_source_t:
+    // system/media/audio/include/system/audio_effects/audio_effects_conf.h
+    static const std::map<const std::string, AudioSource> sAudioSourceTable = {
+            {MIC_SRC_TAG, AudioSource::VOICE_CALL},
+            {VOICE_UL_SRC_TAG, AudioSource::VOICE_CALL},
+            {VOICE_DL_SRC_TAG, AudioSource::VOICE_CALL},
+            {VOICE_CALL_SRC_TAG, AudioSource::VOICE_CALL},
+            {CAMCORDER_SRC_TAG, AudioSource::VOICE_CALL},
+            {VOICE_REC_SRC_TAG, AudioSource::VOICE_CALL},
+            {VOICE_COMM_SRC_TAG, AudioSource::VOICE_CALL},
+            {REMOTE_SUBMIX_SRC_TAG, AudioSource::VOICE_CALL},
+            {UNPROCESSED_SRC_TAG, AudioSource::VOICE_CALL},
+            {VOICE_PERFORMANCE_SRC_TAG, AudioSource::VOICE_CALL}};
+
+    if (typeTag == Processing::Type::streamType) {
+        auto typeIter = sAudioStreamTypeTable.find(type);
+        if (typeIter != sAudioStreamTypeTable.end()) {
+            return typeIter->second;
+        }
+    } else if (typeTag == Processing::Type::source) {
+        auto typeIter = sAudioSourceTable.find(type);
+        if (typeIter != sAudioSourceTable.end()) {
+            return typeIter->second;
+        }
+    }
+
+    return std::nullopt;
+}
+
+bool EffectConfig::parseProcessing(Processing::Type::Tag typeTag, const tinyxml2::XMLElement& xml) {
+    LOG(DEBUG) << __func__ << dump(xml);
+    const char* typeStr = xml.Attribute("type");
+    auto aidlType = stringToProcessingType(typeTag, typeStr);
+    RETURN_VALUE_IF(!aidlType.has_value(), false, "illegalStreamType");
+    RETURN_VALUE_IF(0 != mProcessingMap.count(aidlType.value()), false, "duplicateStreamType");
+
+    for (auto& apply : getChildren(xml, "apply")) {
+        const char* name = apply.get().Attribute("effect");
+        if (mEffectsMap.find(name) == mEffectsMap.end()) {
+            LOG(ERROR) << __func__ << " effect " << name << " doesn't exist, skipping";
+            continue;
+        }
+        RETURN_VALUE_IF(!name, false, "noEffectAttribute");
+        mProcessingMap[aidlType.value()].emplace_back(mEffectsMap[name]);
+        LOG(WARNING) << __func__ << " " << typeStr << " : " << name;
+    }
+    return true;
+}
+
+const std::map<Processing::Type, std::vector<EffectConfig::EffectLibraries>>&
+EffectConfig::getProcessingMap() const {
+    return mProcessingMap;
+}
+
 bool EffectConfig::findUuid(const std::string& xmlEffectName, AudioUuid* uuid) {
 // Difference from EFFECT_TYPE_LIST_DEF, there could be multiple name mapping to same Effect Type
 #define EFFECT_XML_TYPE_LIST_DEF(V)                        \
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
index f0687cc..7073a10 100644
--- a/audio/aidl/default/EffectFactory.cpp
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -15,8 +15,10 @@
  */
 
 #include <dlfcn.h>
+#include <algorithm>
 #include <iterator>
 #include <memory>
+#include <optional>
 #include <tuple>
 #include <unordered_set>
 #define LOG_TAG "AHAL_EffectFactory"
@@ -52,6 +54,22 @@
     }
 }
 
+ndk::ScopedAStatus Factory::getDescriptorWithUuid(const AudioUuid& uuid, Descriptor* desc) {
+    RETURN_IF(!desc, EX_NULL_POINTER, "nullDescriptor");
+
+    if (mEffectLibMap.count(uuid)) {
+        auto& entry = mEffectLibMap[uuid];
+        getDlSyms(entry);
+        auto& libInterface = std::get<kMapEntryInterfaceIndex>(entry);
+        RETURN_IF(!libInterface || !libInterface->queryEffectFunc, EX_NULL_POINTER,
+                  "dlNullQueryEffectFunc");
+        RETURN_IF_BINDER_EXCEPTION(libInterface->queryEffectFunc(&uuid, desc));
+        return ndk::ScopedAStatus::ok();
+    }
+
+    return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
 ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type_uuid,
                                          const std::optional<AudioUuid>& in_impl_uuid,
                                          const std::optional<AudioUuid>& in_proxy_uuid,
@@ -69,12 +87,7 @@
     for (const auto& id : idList) {
         if (mEffectLibMap.count(id.uuid)) {
             Descriptor desc;
-            auto& entry = mEffectLibMap[id.uuid];
-            getDlSyms(entry);
-            auto& libInterface = std::get<kMapEntryInterfaceIndex>(entry);
-            RETURN_IF(!libInterface || !libInterface->queryEffectFunc, EX_NULL_POINTER,
-                      "dlNullQueryEffectFunc");
-            RETURN_IF_BINDER_EXCEPTION(libInterface->queryEffectFunc(&id.uuid, &desc));
+            RETURN_IF_ASTATUS_NOT_OK(getDescriptorWithUuid(id.uuid, &desc), "getDescriptorFailed");
             // update proxy UUID with information from config xml
             desc.common.id.proxy = id.proxy;
             _aidl_return->emplace_back(std::move(desc));
@@ -85,12 +98,26 @@
 
 ndk::ScopedAStatus Factory::queryProcessing(const std::optional<Processing::Type>& in_type,
                                             std::vector<Processing>* _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();
+    const auto& processings = mConfig.getProcessingMap();
+    // Processing stream type
+    for (const auto& procIter : processings) {
+        if (!in_type.has_value() || in_type.value() == procIter.first) {
+            Processing process = {.type = procIter.first /* Processing::Type */};
+            for (const auto& libs : procIter.second /* std::vector<struct EffectLibraries> */) {
+                for (const auto& lib : libs.libraries /* std::vector<struct LibraryUuid> */) {
+                    Descriptor desc;
+                    if (libs.proxyLibrary.has_value()) {
+                        desc.common.id.proxy = libs.proxyLibrary.value().uuid;
+                    }
+                    RETURN_IF_ASTATUS_NOT_OK(getDescriptorWithUuid(lib.uuid, &desc),
+                                             "getDescriptorFailed");
+                    process.ids.emplace_back(desc);
+                }
+            }
+            _aidl_return->emplace_back(process);
+        }
     }
-    LOG(DEBUG) << __func__ << " return " << _aidl_return->size();
+
     return ndk::ScopedAStatus::ok();
 }
 
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
index c06742d..6627ae7 100644
--- a/audio/aidl/default/audio_effects_config.xml
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -95,8 +95,17 @@
             <libsw library="bundle" uuid="ce772f20-847d-11df-bb17-0002a5d5c51b"/>
         </effectProxy>
         <effect name="extensioneffect" library="extensioneffect" uuid="fa81dd00-588b-11ed-9b6a-0242ac120002"/>
+        <effect name="acoustic_echo_canceler" library="aecsw" uuid="bb392ec0-8d4d-11e0-a896-0002a5d5c51b"/>
+        <effect name="noise_suppression" library="nssw" uuid="c06c8400-8e06-11e0-9cb6-0002a5d5c51b"/>
     </effects>
 
+    <preprocess>
+        <stream type="voice_communication">
+            <apply effect="acoustic_echo_canceler"/>
+            <apply effect="noise_suppression"/>
+        </stream>
+    </preprocess>
+
     <!-- Audio pre processor configurations.
          The pre processor configuration is described in a "preprocess" element and consists in a
          list of elements each describing pre processor settings for a given use case or "stream".
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectConfig.h b/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
index c627a27..f8a86e1 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
@@ -26,6 +26,7 @@
 #include <cutils/properties.h>
 #include <tinyxml2.h>
 
+#include <aidl/android/hardware/audio/effect/Processing.h>
 #include "effect-impl/EffectTypes.h"
 
 namespace aidl::android::hardware::audio::effect {
@@ -39,11 +40,6 @@
   public:
     explicit EffectConfig(const std::string& file);
 
-    // <library>
-    struct Library {
-        std::string name;
-        std::string path;
-    };
     struct LibraryUuid {
         std::string name;  // library name
         ::aidl::android::media::audio::common::AudioUuid uuid;
@@ -59,13 +55,13 @@
     const std::unordered_map<std::string, struct EffectLibraries> getEffectsMap() const {
         return mEffectsMap;
     }
-    const std::unordered_map<std::string, std::vector<std::string>> getProcessingMap() const {
-        return mProcessingMap;
-    }
 
     static bool findUuid(const std::string& xmlEffectName,
                          ::aidl::android::media::audio::common::AudioUuid* uuid);
 
+    using ProcessingLibrariesMap = std::map<Processing::Type, std::vector<struct EffectLibraries>>;
+    const ProcessingLibrariesMap& getProcessingMap() const;
+
   private:
     static constexpr const char* kEffectLibPath[] =
 #ifdef __LP64__
@@ -79,8 +75,11 @@
     std::unordered_map<std::string, std::string> mLibraryMap;
     /* Parsed Effects result */
     std::unordered_map<std::string, struct EffectLibraries> mEffectsMap;
-    /* Parsed pre/post processing result */
-    std::unordered_map<std::string, std::vector<std::string>> mProcessingMap;
+    /**
+     * For parsed pre/post processing result: {key: AudioStreamType/AudioSource, value:
+     * EffectLibraries}
+     */
+    ProcessingLibrariesMap mProcessingMap;
 
     /** @return all `node`s children that are elements and match the tag if provided. */
     std::vector<std::reference_wrapper<const tinyxml2::XMLElement>> getChildren(
@@ -94,7 +93,7 @@
      */
     bool parseEffect(const tinyxml2::XMLElement& xml);
 
-    bool parseStream(const tinyxml2::XMLElement& xml);
+    bool parseProcessing(Processing::Type::Tag typeTag, const tinyxml2::XMLElement& xml);
 
     // Function to parse effect.library name and effect.uuid from xml
     bool parseLibraryUuid(const tinyxml2::XMLElement& xml, struct LibraryUuid& libraryUuid,
@@ -104,6 +103,9 @@
                      tinyxml2::XMLPrinter&& printer = {}) const;
 
     bool resolveLibrary(const std::string& path, std::string* resolvedPath);
+
+    std::optional<Processing::Type> stringToProcessingType(Processing::Type::Tag typeTag,
+                                                           const std::string& type);
 };
 
 }  // 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 b7f63af..ad59ca7 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
@@ -107,6 +107,10 @@
             const EffectConfig::LibraryUuid& configLib,
             const ::aidl::android::media::audio::common::AudioUuid& typeUuidStr,
             const std::optional<::aidl::android::media::audio::common::AudioUuid> proxyUuid);
+
+    ndk::ScopedAStatus getDescriptorWithUuid(
+            const aidl::android::media::audio::common::AudioUuid& uuid, Descriptor* desc);
+
     void loadEffectLibs();
     /* Get effect_dl_interface_s from library handle */
     void getDlSyms(DlEntry& entry);