Effect factory: Load config from /odm, /vendor or /system
The effect framework only supports loading its config from /vendor/etc/.
As the audioeffects.conf supported to be loaded from /system and we want
to ease transition to xml,
As the audio policy config and the effect HW modules are can be loaded
from {"/odm/etc", "/vendor/etc", "/system/etc"},
Search for the audio effects xml config in /odm, then /vendor then
/vendor.
Bug: 38184704
Change-Id: I92a4e182fd16659eee2cf6481f8c2a646bf4f427
Test: media.audio_flinger dumpsys with config in /vendor and /system
are identical
Signed-off-by: Kevin Rocard <krocard@google.com>
diff --git a/media/libeffects/config/include/media/EffectsConfig.h b/media/libeffects/config/include/media/EffectsConfig.h
index 811730c..55b946f 100644
--- a/media/libeffects/config/include/media/EffectsConfig.h
+++ b/media/libeffects/config/include/media/EffectsConfig.h
@@ -32,8 +32,13 @@
namespace android {
namespace effectsConfig {
-/** Default path of effect configuration file. */
-constexpr char DEFAULT_PATH[] = "/vendor/etc/audio_effects.xml";
+/** Default path of effect configuration file. Relative to DEFAULT_LOCATIONS. */
+constexpr const char* DEFAULT_NAME = "audio_effects.xml";
+
+/** Default path of effect configuration file.
+ * The /vendor partition is the recommended one, the others are deprecated.
+ */
+constexpr const char* DEFAULT_LOCATIONS[] = {"/odm/etc", "/vendor/etc", "/system/etc"};
/** Directories where the effect libraries will be search for. */
constexpr const char* LD_EFFECT_LIBRARY_PATH[] =
@@ -91,13 +96,16 @@
/** Parsed config, nullptr if the xml lib could not load the file */
std::unique_ptr<Config> parsedConfig;
size_t nbSkippedElement; //< Number of skipped invalid library, effect or processing chain
+ const char* configPath; //< Path to the loaded configuration
};
/** Parses the provided effect configuration.
* Parsing do not stop of first invalid element, but continues to the next.
+ * @param[in] path of the configuration file do load
+ * if nullptr, look for DEFAULT_NAME in DEFAULT_LOCATIONS.
* @see ParsingResult::nbSkippedElement
*/
-ParsingResult parse(const char* path = DEFAULT_PATH);
+ParsingResult parse(const char* path = nullptr);
} // namespace effectsConfig
} // namespace android
diff --git a/media/libeffects/config/src/EffectsConfig.cpp b/media/libeffects/config/src/EffectsConfig.cpp
index 97462f8..18c406d 100644
--- a/media/libeffects/config/src/EffectsConfig.cpp
+++ b/media/libeffects/config/src/EffectsConfig.cpp
@@ -20,6 +20,7 @@
#include <cstdint>
#include <functional>
#include <string>
+#include <unistd.h>
#include <tinyxml2.h>
#include <log/log.h>
@@ -85,7 +86,7 @@
constexpr std::enable_if<false, Enum> STREAM_NAME_MAP;
/** All output stream types which support effects.
- * This need to be kept in sink with the xsd streamOutputType.
+ * This need to be kept in sync with the xsd streamOutputType.
*/
template <>
constexpr std::pair<audio_stream_type_t, const char*> STREAM_NAME_MAP<audio_stream_type_t>[] = {
@@ -102,7 +103,7 @@
};
/** All input stream types which support effects.
- * This need to be kept in sink with the xsd streamOutputType.
+ * This need to be kept in sync with the xsd streamOutputType.
*/
template <>
constexpr std::pair<audio_source_t, const char*> STREAM_NAME_MAP<audio_source_t>[] = {
@@ -142,7 +143,7 @@
}
/** Find an element in a collection by its name.
- * @return nullptr if not found, the ellements address if found.
+ * @return nullptr if not found, the element address if found.
*/
template <class T>
T* findByName(const char* name, std::vector<T>& collection) {
@@ -249,15 +250,14 @@
return true;
}
-}; // namespace
-
-ParsingResult parse(const char* path) {
+/** Internal version of the public parse(const char* path) with precondition `path != nullptr`. */
+ParsingResult parseWithPath(const char* path) {
XMLDocument doc;
doc.LoadFile(path);
if (doc.Error()) {
ALOGE("Failed to parse %s: Tinyxml2 error (%d): %s %s", path,
doc.ErrorID(), doc.GetErrorStr1(), doc.GetErrorStr2());
- return {nullptr, 0};
+ return {nullptr, 0, path};
}
auto config = std::make_unique<Config>();
@@ -295,7 +295,29 @@
}
}
}
- return {std::move(config), nbSkippedElements};
+ return {std::move(config), nbSkippedElements, path};
+}
+
+}; // namespace
+
+ParsingResult parse(const char* path) {
+ if (path != nullptr) {
+ return parseWithPath(path);
+ }
+
+ for (std::string location : DEFAULT_LOCATIONS) {
+ std::string defaultPath = location + '/' + DEFAULT_NAME;
+ if (access(defaultPath.c_str(), R_OK) != 0) {
+ continue;
+ }
+ auto result = parseWithPath(defaultPath.c_str());
+ if (result.parsedConfig != nullptr) {
+ return result;
+ }
+ }
+
+ ALOGE("Could not parse effect configuration in any of the default locations.");
+ return {nullptr, 0, nullptr};
}
} // namespace effectsConfig
diff --git a/media/libeffects/factory/EffectsXmlConfigLoader.cpp b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
index 438b787..7a7d431 100644
--- a/media/libeffects/factory/EffectsXmlConfigLoader.cpp
+++ b/media/libeffects/factory/EffectsXmlConfigLoader.cpp
@@ -327,7 +327,7 @@
&gSkippedEffects, &gSubEffectList);
ALOGE_IF(result.nbSkippedElement != 0, "%zu errors during loading of configuration: %s",
- result.nbSkippedElement, path ?: effectsConfig::DEFAULT_PATH);
+ result.nbSkippedElement, result.configPath ?: "No config file found");
return result.nbSkippedElement;
}