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;
diff --git a/media/libmedia/include/media/MediaProfiles.h b/media/libmedia/include/media/MediaProfiles.h
index 3e8e7c8..4cc5b95 100644
--- a/media/libmedia/include/media/MediaProfiles.h
+++ b/media/libmedia/include/media/MediaProfiles.h
@@ -1,18 +1,18 @@
/*
- **
- ** Copyright 2010, 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.
+ *
+ * Copyright 2010, 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.
*/
#ifndef ANDROID_MEDIAPROFILES_H
@@ -82,29 +82,12 @@
{
public:
- /*
- * If property media.settings.xml is not set:
- *
- * getInstance() will search through paths listed in xmlFiles.
- * The search goes through members of xmlFiles in the order that they are
- * defined, so files at lower indices have higher priority than those at
- * higher indices.
- *
- * TODO: Add runtime validation of xml files. A search should be considered
- * successful only when validation is successful.
- */
- static constexpr char const * const xmlFiles[] = {
- "odm/etc/media_profiles_V1_0.xml",
- "vendor/etc/media_profiles_V1_0.xml",
- "system/etc/media_profiles.xml"
- };
-
/**
* Returns the singleton instance for subsequence queries or NULL if error.
*
* If property media.settings.xml is set, getInstance() will attempt to read
* from file path in media.settings.xml. Otherwise, getInstance() will
- * search through the list xmlFiles as described above.
+ * search through the list of preset XML file paths.
*
* If the search is unsuccessful, the default instance will be created
* instead.
diff --git a/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp b/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp
index 7729d52..4f3951a 100644
--- a/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp
+++ b/media/libmedia/xsd/vts/ValidateMediaProfiles.cpp
@@ -14,23 +14,68 @@
* limitations under the License.
*/
+#include <fstream>
#include <string>
#include <android-base/file.h>
#include <android-base/properties.h>
#include "utility/ValidateXml.h"
+bool isFileReadable(std::string const& path) {
+ std::ifstream f(path);
+ return f.good();
+}
+
TEST(CheckConfig, mediaProfilesValidation) {
RecordProperty("description",
"Verify that the media profiles file "
"is valid according to the schema");
+ // Schema path.
+ constexpr char const* xsdPath = "/data/local/tmp/media_profiles.xsd";
+
+ // If "media.settings.xml" is set, it will be used as an absolute path.
std::string mediaSettingsPath = android::base::GetProperty("media.settings.xml", "");
if (mediaSettingsPath.empty()) {
- mediaSettingsPath.assign("/vendor/etc/media_profiles_V1_0.xml");
- }
+ // If "media.settings.xml" is not set, we will search through a list of
+ // file paths.
- EXPECT_ONE_VALID_XML_MULTIPLE_LOCATIONS(android::base::Basename(mediaSettingsPath).c_str(),
- {android::base::Dirname(mediaSettingsPath).c_str()},
- "/data/local/tmp/media_profiles.xsd");
+ constexpr char const* xmlSearchDirs[] = {
+ "/product/etc/",
+ "/odm/etc/",
+ "/vendor/etc/",
+ };
+
+ // The vendor may provide a vendor variant for the file name.
+ std::string variant = android::base::GetProperty(
+ "ro.media.xml_variant.profiles", "_V1_0");
+ std::string fileName = "media_profiles" + variant + ".xml";
+
+ // Fallback path does not depend on the property defined from the vendor
+ // partition.
+ constexpr char const* fallbackXmlPath =
+ "/system/etc/media_profiles_V1_0.xml";
+
+ std::vector<std::string> xmlPaths = {
+ xmlSearchDirs[0] + fileName,
+ xmlSearchDirs[1] + fileName,
+ xmlSearchDirs[2] + fileName,
+ fallbackXmlPath
+ };
+
+ auto findXmlPath =
+ std::find_if(xmlPaths.begin(), xmlPaths.end(), isFileReadable);
+ ASSERT_TRUE(findXmlPath != xmlPaths.end())
+ << "Cannot read from " << fileName
+ << " in any search directories ("
+ << xmlSearchDirs[0] << ", "
+ << xmlSearchDirs[1] << ", "
+ << xmlSearchDirs[2] << ") and from "
+ << fallbackXmlPath << ".";
+
+ char const* xmlPath = findXmlPath->c_str();
+ EXPECT_VALID_XML(xmlPath, xsdPath);
+ } else {
+ EXPECT_VALID_XML(mediaSettingsPath.c_str(), xsdPath);
+ }
}