Allow XML file paths to be customized with sysprop

Three properties are declared as vendor-init-settable:
ro.media.xml_variant.codecs
ro.media.xml_variant.codecs_performance
ro.media.xml_variant.profiles

media_codecs.xml can now be named
media_codecs${ro.media.xml_variant.codecs}.xml

media_codecs_performance.xml can now be named
media_codecs_performance${ro.media.xml_variant.codecs_performance}.xml

media_profiles_V1_0 can now be named
media_profiles${ro.media.xml_variant.profiles}.xml

Test: Rename "media_codecs.xml" to "media_codecs_test.xml",
set ro.media.xml_variant.codecs to "_test", then
call "stagefright -i".

Test: Rename "media_codecs_performance.xml" to
"media_codecs_performance_test.xml",
set ro.media.xml_variant.codecs_performance to "_test", then
run android.media.cts.VideoDecoderPerfTest.

Test: Rename "media_profiles_V1_0.xml" to "media_profiles_test.xml",
set ro.media.xml_variant.profiles to "_test", then
run vts_mediaProfiles_validate_test.

Bug: 142102953
Change-Id: I38fa2924e02363639d1cdc3dd85128e0652343ee
diff --git a/media/libmedia/MediaProfiles.cpp b/media/libmedia/MediaProfiles.cpp
index 98c5497..637322f 100644
--- a/media/libmedia/MediaProfiles.cpp
+++ b/media/libmedia/MediaProfiles.cpp
@@ -29,9 +29,55 @@
 #include <OMX_Video.h>
 #include <sys/stat.h>
 
+#include <array>
+#include <string>
+#include <vector>
+
 namespace android {
 
-constexpr char const * const MediaProfiles::xmlFiles[];
+namespace /* unnamed */ {
+
+// Returns a list of possible paths for the media_profiles XML file.
+std::array<char const*, 5> const& getXmlPaths() {
+    static std::array<std::string const, 5> const paths =
+        []() -> decltype(paths) {
+            // Directories for XML file that will be searched (in this order).
+            constexpr std::array<char const*, 4> searchDirs = {
+                "product/etc/",
+                "odm/etc/",
+                "vendor/etc/",
+                "system/etc/",
+            };
+
+            // The file name may contain a variant if the vendor property
+            // ro.vendor.media_profiles_xml_variant is set.
+            char variant[PROPERTY_VALUE_MAX];
+            property_get("ro.media.xml_variant.profiles",
+                         variant,
+                         "_V1_0");
+
+            std::string fileName =
+                std::string("media_profiles") + variant + ".xml";
+
+            return { searchDirs[0] + fileName,
+                     searchDirs[1] + fileName,
+                     searchDirs[2] + fileName,
+                     searchDirs[3] + fileName,
+                     "system/etc/media_profiles_V1_0.xml" // System fallback
+                   };
+        }();
+    static std::array<char const*, 5> const cPaths = {
+            paths[0].data(),
+            paths[1].data(),
+            paths[2].data(),
+            paths[3].data(),
+            paths[4].data()
+        };
+    return cPaths;
+}
+
+} // unnamed namespace
+
 Mutex MediaProfiles::sLock;
 bool MediaProfiles::sIsInitialized = false;
 MediaProfiles *MediaProfiles::sInstance = NULL;
@@ -48,7 +94,7 @@
     {"amrwb",  AUDIO_ENCODER_AMR_WB},
     {"aac",    AUDIO_ENCODER_AAC},
     {"heaac",  AUDIO_ENCODER_HE_AAC},
-    {"aaceld", AUDIO_ENCODER_AAC_ELD}, 
+    {"aaceld", AUDIO_ENCODER_AAC_ELD},
     {"opus",   AUDIO_ENCODER_OPUS}
 };
 
@@ -610,7 +656,7 @@
         char value[PROPERTY_VALUE_MAX];
         if (property_get("media.settings.xml", value, NULL) <= 0) {
             const char* xmlFile = nullptr;
-            for (auto const& f : xmlFiles) {
+            for (auto const& f : getXmlPaths()) {
                 if (checkXmlFile(f)) {
                     xmlFile = f;
                     break;