Audio policy: Parse new audio policy configuration file

For treble, files shared between vendor and system must have a schema.
As .conf did not support such feature, transition to an xml based
configuration file.

This new format has several changes:
 - library path are now relative to the standard effect directories
 - effect parameters are no longer supported (nobody used them)

Test: Check that the dumpsys is similar than with the legacy formal
Bug: 37492580
Change-Id: Ie6bd84ed88124991600fa238cc13714874eefad9
Signed-off-by: Kevin Rocard <krocard@google.com>
diff --git a/services/audiopolicy/Android.mk b/services/audiopolicy/Android.mk
index ad340e5..65571f9 100644
--- a/services/audiopolicy/Android.mk
+++ b/services/audiopolicy/Android.mk
@@ -24,7 +24,8 @@
     libhardware_legacy \
     libserviceutility \
     libaudiopolicymanager \
-    libmedia_helper
+    libmedia_helper \
+    libeffectsconfig
 
 LOCAL_STATIC_LIBRARIES := \
     libaudiopolicycomponents
diff --git a/services/audiopolicy/service/AudioPolicyEffects.cpp b/services/audiopolicy/service/AudioPolicyEffects.cpp
index 654465d..84b1073 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.cpp
+++ b/services/audiopolicy/service/AudioPolicyEffects.cpp
@@ -20,8 +20,10 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <memory>
 #include <cutils/misc.h>
 #include <media/AudioEffect.h>
+#include <media/EffectsConfig.h>
 #include <system/audio.h>
 #include <system/audio_effects/audio_effects_conf.h>
 #include <utils/Vector.h>
@@ -39,11 +41,17 @@
 
 AudioPolicyEffects::AudioPolicyEffects()
 {
-    // load automatic audio effect modules
-    if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
-        loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
-    } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
-        loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+    status_t loadResult = loadAudioEffectXmlConfig();
+    if (loadResult < 0) {
+        ALOGW("Failed to load XML effect configuration, fallback to .conf");
+        // load automatic audio effect modules
+        if (access(AUDIO_EFFECT_VENDOR_CONFIG_FILE, R_OK) == 0) {
+            loadAudioEffectConfig(AUDIO_EFFECT_VENDOR_CONFIG_FILE);
+        } else if (access(AUDIO_EFFECT_DEFAULT_CONFIG_FILE, R_OK) == 0) {
+            loadAudioEffectConfig(AUDIO_EFFECT_DEFAULT_CONFIG_FILE);
+        }
+    } else if (loadResult > 0) {
+        ALOGE("Effect config is partially invalid, skipped %d elements", loadResult);
     }
 }
 
@@ -685,6 +693,28 @@
     return NO_ERROR;
 }
 
+status_t AudioPolicyEffects::loadAudioEffectXmlConfig() {
+    auto result = effectsConfig::parse();
+    if (result.parsedConfig == nullptr) {
+        return -ENOENT;
+    }
+
+    auto loadProcessingChain = [](auto& processingChain, auto& streams) {
+        for (auto& stream : processingChain) {
+            auto effectDescs = std::make_unique<EffectDescVector>();
+            for (auto& effect : stream.effects) {
+                effectDescs->mEffects.add(
+                        new EffectDesc{effect.get().name.c_str(), effect.get().uuid});
+            }
+            streams.add(stream.type, effectDescs.release());
+        }
+    };
+    loadProcessingChain(result.parsedConfig->preprocess, mInputSources);
+    loadProcessingChain(result.parsedConfig->postprocess, mOutputStreams);
+    // Casting from ssize_t to status_t is probably safe, there should not be more than 2^31 errors
+    return result.nbSkippedElement;
+}
+
 status_t AudioPolicyEffects::loadAudioEffectConfig(const char *path)
 {
     cnode *root;
diff --git a/services/audiopolicy/service/AudioPolicyEffects.h b/services/audiopolicy/service/AudioPolicyEffects.h
index 0c74d87..59d5d14 100644
--- a/services/audiopolicy/service/AudioPolicyEffects.h
+++ b/services/audiopolicy/service/AudioPolicyEffects.h
@@ -155,7 +155,8 @@
     audio_stream_type_t streamNameToEnum(const char *name);
 
     // Parse audio_effects.conf
-    status_t loadAudioEffectConfig(const char *path);
+    status_t loadAudioEffectConfig(const char *path); // TODO: add legacy in the name
+    status_t loadAudioEffectXmlConfig(); // TODO: remove "Xml" in the name
 
     // Load all effects descriptors in configuration file
     status_t loadEffects(cnode *root, Vector <EffectDesc *>& effects);