Relax error handling in MediaCodecsXmlParser
Test: m stagefright && adb sync && adb shell stagefright -p
Bug: 111892331
Bug: 117647173
Change-Id: I5febae71d18d5085232a0d1375e497e7386f1c81
Merged-In: I5febae71d18d5085232a0d1375e497e7386f1c81
(cherry picked from commit 768409031786376246e9f06d93890d33c889eacd)
diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
index ffd30ea..d98e123 100644
--- a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
+++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
@@ -91,18 +91,18 @@
status_t limitFoundMissingAttr(const char* name, const char *attr, bool found = true) {
ALOGE("limit '%s' with %s'%s' attribute", name,
(found ? "" : "no "), attr);
- return -EINVAL;
+ return BAD_VALUE;
}
status_t limitError(const char* name, const char *msg) {
ALOGE("limit '%s' %s", name, msg);
- return -EINVAL;
+ return BAD_VALUE;
}
status_t limitInvalidAttr(const char* name, const char* attr, const char* value) {
ALOGE("limit '%s' with invalid '%s' attribute (%s)", name,
attr, value);
- return -EINVAL;
+ return BAD_VALUE;
}
}; // unnamed namespace
@@ -231,12 +231,12 @@
while (attrs[i] != nullptr) {
if (strEq(attrs[i], "href")) {
if (attrs[++i] == nullptr) {
- return -EINVAL;
+ return BAD_VALUE;
}
href = attrs[i];
} else {
ALOGE("includeXMLFile: unrecognized attribute: %s", attrs[i]);
- return -EINVAL;
+ return BAD_VALUE;
}
++i;
}
@@ -251,32 +251,32 @@
continue;
}
ALOGE("invalid include file name: %s", href);
- return -EINVAL;
+ return BAD_VALUE;
}
std::string filename = href;
if (filename.compare(0, 13, "media_codecs_") != 0 ||
filename.compare(filename.size() - 4, 4, ".xml") != 0) {
ALOGE("invalid include file name: %s", href);
- return -EINVAL;
+ return BAD_VALUE;
}
filename.insert(0, mHrefBase);
+ status_t oldParsingStatus = mParsingStatus;
+
parseXMLFile(filename.c_str());
- return mParsingStatus;
+
+ status_t newParsingStatus = mParsingStatus;
+ mParsingStatus = oldParsingStatus;
+ return newParsingStatus;
}
void MediaCodecsXmlParser::startElementHandler(
const char *name, const char **attrs) {
- if (mParsingStatus != OK) {
- return;
- }
-
bool inType = true;
if (strEq(name, "Include")) {
- mParsingStatus = includeXMLFile(attrs);
- if (mParsingStatus == OK) {
+ if (includeXMLFile(attrs) == OK) {
mSectionStack.push_back(mCurrentSection);
mCurrentSection = SECTION_INCLUDE;
}
@@ -299,7 +299,7 @@
case SECTION_SETTINGS:
{
if (strEq(name, "Setting")) {
- mParsingStatus = addSettingFromAttributes(attrs);
+ (void)addSettingFromAttributes(attrs);
}
break;
}
@@ -307,9 +307,7 @@
case SECTION_DECODERS:
{
if (strEq(name, "MediaCodec")) {
- mParsingStatus =
- addMediaCodecFromAttributes(false /* encoder */, attrs);
-
+ (void)addMediaCodecFromAttributes(false /* encoder */, attrs);
mCurrentSection = SECTION_DECODER;
}
break;
@@ -318,9 +316,7 @@
case SECTION_ENCODERS:
{
if (strEq(name, "MediaCodec")) {
- mParsingStatus =
- addMediaCodecFromAttributes(true /* encoder */, attrs);
-
+ (void)addMediaCodecFromAttributes(true /* encoder */, attrs);
mCurrentSection = SECTION_ENCODER;
}
break;
@@ -330,9 +326,9 @@
case SECTION_ENCODER:
{
if (strEq(name, "Quirk")) {
- mParsingStatus = addQuirk(attrs);
+ (void)addQuirk(attrs);
} else if (strEq(name, "Type")) {
- mParsingStatus = addTypeFromAttributes(attrs,
+ (void)addTypeFromAttributes(attrs,
(mCurrentSection == SECTION_ENCODER));
mCurrentSection =
(mCurrentSection == SECTION_DECODER ?
@@ -352,9 +348,9 @@
(strEq(name, "Limit") || strEq(name, "Feature"))) {
ALOGW("ignoring %s specified outside of a Type", name);
} else if (strEq(name, "Limit")) {
- mParsingStatus = addLimit(attrs);
+ (void)addLimit(attrs);
} else if (strEq(name, "Feature")) {
- mParsingStatus = addFeature(attrs);
+ (void)addFeature(attrs);
}
break;
}
@@ -366,10 +362,6 @@
}
void MediaCodecsXmlParser::endElementHandler(const char *name) {
- if (mParsingStatus != OK) {
- return;
- }
-
switch (mCurrentSection) {
case SECTION_SETTINGS:
{
@@ -451,31 +443,31 @@
if (strEq(attrs[i], "name")) {
if (attrs[++i] == nullptr) {
ALOGE("addSettingFromAttributes: name is null");
- return -EINVAL;
+ return BAD_VALUE;
}
name = attrs[i];
} else if (strEq(attrs[i], "value")) {
if (attrs[++i] == nullptr) {
ALOGE("addSettingFromAttributes: value is null");
- return -EINVAL;
+ return BAD_VALUE;
}
value = attrs[i];
} else if (strEq(attrs[i], "update")) {
if (attrs[++i] == nullptr) {
ALOGE("addSettingFromAttributes: update is null");
- return -EINVAL;
+ return BAD_VALUE;
}
update = attrs[i];
} else {
ALOGE("addSettingFromAttributes: unrecognized attribute: %s", attrs[i]);
- return -EINVAL;
+ return BAD_VALUE;
}
++i;
}
if (name == nullptr || value == nullptr) {
ALOGE("addSettingFromAttributes: name or value unspecified");
- return -EINVAL;
+ return BAD_VALUE;
}
// Boolean values are converted to "0" or "1".
@@ -488,7 +480,7 @@
if (attribute == mServiceAttributeMap.end()) { // New attribute name
if (mUpdate) {
ALOGE("addSettingFromAttributes: updating non-existing setting");
- return -EINVAL;
+ return BAD_VALUE;
}
mServiceAttributeMap.insert(Attribute(name, value));
} else { // Existing attribute name
@@ -512,39 +504,40 @@
if (strEq(attrs[i], "name")) {
if (attrs[++i] == nullptr) {
ALOGE("addMediaCodecFromAttributes: name is null");
- return -EINVAL;
+ return BAD_VALUE;
}
name = attrs[i];
} else if (strEq(attrs[i], "type")) {
if (attrs[++i] == nullptr) {
ALOGE("addMediaCodecFromAttributes: type is null");
- return -EINVAL;
+ return BAD_VALUE;
}
type = attrs[i];
} else if (strEq(attrs[i], "update")) {
if (attrs[++i] == nullptr) {
ALOGE("addMediaCodecFromAttributes: update is null");
- return -EINVAL;
+ return BAD_VALUE;
}
update = attrs[i];
} else {
ALOGE("addMediaCodecFromAttributes: unrecognized attribute: %s", attrs[i]);
- return -EINVAL;
+ return BAD_VALUE;
}
++i;
}
if (name == nullptr) {
ALOGE("addMediaCodecFromAttributes: name not found");
- return -EINVAL;
+ return BAD_VALUE;
}
mUpdate = (update != nullptr) && parseBoolean(update);
mCurrentCodec = mCodecMap.find(name);
if (mCurrentCodec == mCodecMap.end()) { // New codec name
if (mUpdate) {
- ALOGE("addMediaCodecFromAttributes: updating non-existing codec");
- return -EINVAL;
+ ALOGW("addMediaCodecFromAttributes: cannot update "
+ "non-existing codec \"%s\".", name);
+ return BAD_VALUE;
}
// Create a new codec in mCodecMap
mCurrentCodec = mCodecMap.insert(
@@ -559,18 +552,26 @@
mCurrentCodec->second.order = mCodecCounter++;
} else { // Existing codec name
if (!mUpdate) {
- ALOGE("addMediaCodecFromAttributes: adding existing codec");
- return -EINVAL;
+ ALOGW("addMediaCodecFromAttributes: trying to add "
+ "existing codec \"%s\"", name);
+ return ALREADY_EXISTS;
}
if (type != nullptr) {
mCurrentType = mCurrentCodec->second.typeMap.find(type);
if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
- ALOGE("addMediaCodecFromAttributes: updating non-existing type");
- return -EINVAL;
+ ALOGE("addMediaCodecFromAttributes: cannot update "
+ "non-existing type \"%s\" for codec \"%s\"",
+ type, name);
+ return BAD_VALUE;
}
} else {
// This should happen only when the codec has at most one type.
mCurrentType = mCurrentCodec->second.typeMap.begin();
+ if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
+ ALOGE("addMediaCodecFromAttributes: cannot update "
+ "codec \"%s\" without type specified", name);
+ return BAD_VALUE;
+ }
}
}
@@ -578,6 +579,10 @@
}
status_t MediaCodecsXmlParser::addQuirk(const char **attrs) {
+ if (mCurrentCodec == mCodecMap.end()) {
+ return BAD_VALUE;
+ }
+
const char *name = nullptr;
size_t i = 0;
@@ -585,19 +590,19 @@
if (strEq(attrs[i], "name")) {
if (attrs[++i] == nullptr) {
ALOGE("addQuirk: name is null");
- return -EINVAL;
+ return BAD_VALUE;
}
name = attrs[i];
} else {
ALOGE("addQuirk: unrecognized attribute: %s", attrs[i]);
- return -EINVAL;
+ return BAD_VALUE;
}
++i;
}
if (name == nullptr) {
ALOGE("addQuirk: name not found");
- return -EINVAL;
+ return BAD_VALUE;
}
mCurrentCodec->second.quirkSet.emplace(name);
@@ -605,6 +610,10 @@
}
status_t MediaCodecsXmlParser::addTypeFromAttributes(const char **attrs, bool encoder) {
+ if (mCurrentCodec == mCodecMap.end()) {
+ return BAD_VALUE;
+ }
+
const char *name = nullptr;
const char *update = nullptr;
@@ -613,42 +622,51 @@
if (strEq(attrs[i], "name")) {
if (attrs[++i] == nullptr) {
ALOGE("addTypeFromAttributes: name is null");
- return -EINVAL;
+ return BAD_VALUE;
}
name = attrs[i];
} else if (strEq(attrs[i], "update")) {
if (attrs[++i] == nullptr) {
ALOGE("addTypeFromAttributes: update is null");
- return -EINVAL;
+ return BAD_VALUE;
}
update = attrs[i];
} else {
ALOGE("addTypeFromAttributes: unrecognized attribute: %s", attrs[i]);
- return -EINVAL;
+ return BAD_VALUE;
}
++i;
}
if (name == nullptr) {
- return -EINVAL;
+ return BAD_VALUE;
}
mCurrentCodec->second.isEncoder = encoder;
mCurrentType = mCurrentCodec->second.typeMap.find(name);
if (!mUpdate) {
if (mCurrentType != mCurrentCodec->second.typeMap.end()) {
- ALOGE("addTypeFromAttributes: re-defining existing type without update");
- return -EINVAL;
+ ALOGW("addTypeFromAttributes: trying to update "
+ "existing type \"%s\"", name);
+ return ALREADY_EXISTS;
}
mCurrentType = mCurrentCodec->second.typeMap.insert(
Type(name, AttributeMap())).first;
} else if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
ALOGE("addTypeFromAttributes: updating non-existing type");
+ return BAD_VALUE;
}
return OK;
}
status_t MediaCodecsXmlParser::addLimit(const char **attrs) {
+ if (mCurrentCodec == mCodecMap.end()) {
+ return BAD_VALUE;
+ }
+ if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
+ return BAD_VALUE;
+ }
+
const char* a_name = nullptr;
const char* a_default = nullptr;
const char* a_in = nullptr;
@@ -664,78 +682,73 @@
if (strEq(attrs[i], "name")) {
if (attrs[++i] == nullptr) {
ALOGE("addLimit: name is null");
- return -EINVAL;
+ return BAD_VALUE;
}
a_name = attrs[i];
} else if (strEq(attrs[i], "default")) {
if (attrs[++i] == nullptr) {
ALOGE("addLimit: default is null");
- return -EINVAL;
+ return BAD_VALUE;
}
a_default = attrs[i];
} else if (strEq(attrs[i], "in")) {
if (attrs[++i] == nullptr) {
ALOGE("addLimit: in is null");
- return -EINVAL;
+ return BAD_VALUE;
}
a_in = attrs[i];
} else if (strEq(attrs[i], "max")) {
if (attrs[++i] == nullptr) {
ALOGE("addLimit: max is null");
- return -EINVAL;
+ return BAD_VALUE;
}
a_max = attrs[i];
} else if (strEq(attrs[i], "min")) {
if (attrs[++i] == nullptr) {
ALOGE("addLimit: min is null");
- return -EINVAL;
+ return BAD_VALUE;
}
a_min = attrs[i];
} else if (strEq(attrs[i], "range")) {
if (attrs[++i] == nullptr) {
ALOGE("addLimit: range is null");
- return -EINVAL;
+ return BAD_VALUE;
}
a_range = attrs[i];
} else if (strEq(attrs[i], "ranges")) {
if (attrs[++i] == nullptr) {
ALOGE("addLimit: ranges is null");
- return -EINVAL;
+ return BAD_VALUE;
}
a_ranges = attrs[i];
} else if (strEq(attrs[i], "scale")) {
if (attrs[++i] == nullptr) {
ALOGE("addLimit: scale is null");
- return -EINVAL;
+ return BAD_VALUE;
}
a_scale = attrs[i];
} else if (strEq(attrs[i], "value")) {
if (attrs[++i] == nullptr) {
ALOGE("addLimit: value is null");
- return -EINVAL;
+ return BAD_VALUE;
}
a_value = attrs[i];
} else {
ALOGE("addLimit: unrecognized limit: %s", attrs[i]);
- return -EINVAL;
+ return BAD_VALUE;
}
++i;
}
if (a_name == nullptr) {
ALOGE("limit with no 'name' attribute");
- return -EINVAL;
+ return BAD_VALUE;
}
// size, blocks, bitrate, frame-rate, blocks-per-second, aspect-ratio,
// measured-frame-rate, measured-blocks-per-second: range
// quality: range + default + [scale]
// complexity: range + default
- if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
- ALOGW("ignoring null type");
- return OK;
- }
-
std::string range;
if (strEq(a_name, "aspect-ratio") ||
strEq(a_name, "bitrate") ||
@@ -879,6 +892,13 @@
}
status_t MediaCodecsXmlParser::addFeature(const char **attrs) {
+ if (mCurrentCodec == mCodecMap.end()) {
+ return BAD_VALUE;
+ }
+ if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
+ return BAD_VALUE;
+ }
+
size_t i = 0;
const char *name = nullptr;
int32_t optional = -1;
@@ -889,30 +909,30 @@
if (strEq(attrs[i], "name")) {
if (attrs[++i] == nullptr) {
ALOGE("addFeature: name is null");
- return -EINVAL;
+ return BAD_VALUE;
}
name = attrs[i];
} else if (strEq(attrs[i], "optional")) {
if (attrs[++i] == nullptr) {
ALOGE("addFeature: optional is null");
- return -EINVAL;
+ return BAD_VALUE;
}
optional = parseBoolean(attrs[i]) ? 1 : 0;
} else if (strEq(attrs[i], "required")) {
if (attrs[++i] == nullptr) {
ALOGE("addFeature: required is null");
- return -EINVAL;
+ return BAD_VALUE;
}
required = parseBoolean(attrs[i]) ? 1 : 0;
} else if (strEq(attrs[i], "value")) {
if (attrs[++i] == nullptr) {
ALOGE("addFeature: value is null");
- return -EINVAL;
+ return BAD_VALUE;
}
value = attrs[i];
} else {
ALOGE("addFeature: unrecognized attribute: %s", attrs[i]);
- return -EINVAL;
+ return BAD_VALUE;
}
++i;
}
@@ -920,23 +940,18 @@
// Every feature must have a name.
if (name == nullptr) {
ALOGE("feature with no 'name' attribute");
- return -EINVAL;
- }
-
- if (mCurrentType == mCurrentCodec->second.typeMap.end()) {
- ALOGW("ignoring null type");
- return OK;
+ return BAD_VALUE;
}
if ((optional != -1) || (required != -1)) {
if (optional == required) {
ALOGE("feature '%s' is both/neither optional and required", name);
- return -EINVAL;
+ return BAD_VALUE;
}
if ((optional == 1) || (required == 1)) {
if (value != nullptr) {
ALOGE("feature '%s' cannot have extra 'value'", name);
- return -EINVAL;
+ return BAD_VALUE;
}
mCurrentType->second[std::string("feature-") + name] =
optional == 1 ? "0" : "1";