Merge "add MediaCodec XML minsdk=# attribute"
diff --git a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
index 67c6102..8c1ef3b 100644
--- a/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
+++ b/media/libstagefright/xmlparser/MediaCodecsXmlParser.cpp
@@ -19,6 +19,8 @@
#include <media/stagefright/xmlparser/MediaCodecsXmlParser.h>
+#include <android/api-level.h>
+
#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/properties.h>
@@ -30,6 +32,7 @@
#include <expat.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
@@ -360,7 +363,7 @@
status_t updateMediaCodec(
const char *rank, const StringSet &domain, const StringSet &variants,
- const char *enabled);
+ const char *enabled, const char *minsdk);
};
status_t parseXmlFilesInSearchDirs(
@@ -493,6 +496,9 @@
}
}
+// current SDK for this device; filled in when initializing the parser.
+static int mysdk = 0;
+
MediaCodecsXmlParser::Impl::Parser::Parser(State *state, std::string path)
: mState(state),
mPath(path),
@@ -502,6 +508,20 @@
if (end != std::string::npos) {
mHrefBase = path.substr(0, end + 1);
}
+
+#if defined(__ANDROID_API_U__)
+ // this is sdk calculation is intended only for devices >= U
+ static std::once_flag sCheckOnce;
+
+ std::call_once(sCheckOnce, [&](){
+ mysdk = android_get_device_api_level();
+
+ // work around main development branch being on same SDK as the last dessert release.
+ if (__ANDROID_API__ == __ANDROID_API_FUTURE__) {
+ mysdk++;
+ }
+ });
+#endif // __ANDROID_API_U__
}
void MediaCodecsXmlParser::Impl::Parser::parseXmlFile() {
@@ -930,6 +950,7 @@
const char *a_domain = nullptr;
const char *a_variant = nullptr;
const char *a_enabled = nullptr;
+ const char *a_minsdk = nullptr;
size_t i = 0;
while (attrs[i] != nullptr) {
@@ -953,6 +974,8 @@
a_variant = attrs[++i];
} else if (strEq(attrs[i], "enabled")) {
a_enabled = attrs[++i];
+ } else if (strEq(attrs[i], "minsdk")) {
+ a_minsdk = attrs[++i];
} else {
PLOGD("MediaCodec: ignoring unrecognized attribute '%s'", attrs[i]);
++i;
@@ -981,7 +1004,7 @@
return updateMediaCodec(
a_rank, parseCommaSeparatedStringSet(a_domain),
- parseCommaSeparatedStringSet(a_variant), a_enabled);
+ parseCommaSeparatedStringSet(a_variant), a_enabled, a_minsdk);
}
MediaCodecsXmlParser::Impl::Result
@@ -1035,7 +1058,7 @@
status_t MediaCodecsXmlParser::Impl::Parser::updateMediaCodec(
const char *rank, const StringSet &domains, const StringSet &variants,
- const char *enabled) {
+ const char *enabled, const char *minsdk) {
CHECK(mState->inCodec());
CodecProperties &codec = mState->codec();
@@ -1048,6 +1071,7 @@
codec.variantSet = variants;
+ // we allow sets of domains...
for (const std::string &domain : domains) {
if (domain.size() && domain.at(0) == '!') {
codec.domainSet.erase(domain.substr(1));
@@ -1065,6 +1089,49 @@
ALOGD("disabling %s", mState->codecName().c_str());
}
}
+
+ // evaluate against passed minsdk, with lots of logging to explain the logic
+ //
+ // if current sdk >= minsdk, we want to enable the codec
+ // this OVERRIDES any enabled="true|false" setting on the codec.
+ // (enabled=true minsdk=35 on a sdk 34 device results in a disabled codec)
+ //
+ // Although minsdk is not parsed before Android U, we can carry media_codecs.xml
+ // using this to devices earlier (e.g. as part of mainline). An example is appropriate.
+ //
+ // we have a codec that we want enabled in Android V (sdk=35), so we use:
+ // <MediaCodec ..... enabled="false" minsdk="35" >
+ //
+ // on Q/R/S/T: it sees enabled=false, but ignores the unrecognized minsdk
+ // so the codec will be disabled
+ // on U: it sees enabled=false, and sees minsdk=35, but U==34 and 34 < 35
+ // so the codec will be disabled
+ // on V: it sees enabled=false, and sees minsdk=35, V==35 and 35 >= 35
+ // so the codec will be enabled
+ //
+ // if we know the XML files will be used only on devices >= U, we can skip the enabled=false
+ // piece. Android mainline's support horizons say we will be using the enabled=false for
+ // another 4-5 years after U.
+ //
+ if (minsdk != nullptr) {
+ char *p = nullptr;
+ int sdk = strtol(minsdk, &p, 0);
+ if (p == minsdk || sdk < 0) {
+ ALOGE("minsdk parsing '%s' yielded %d, mapping to 0", minsdk, sdk);
+ sdk = 0;
+ }
+ // minsdk="#" means: "enable if sdk is >= #, disable otherwise"
+ if (mysdk < sdk) {
+ ALOGI("codec %s disabled, device sdk %d < required %d",
+ mState->codecName().c_str(), mysdk, sdk);
+ codec.quirkSet.emplace("attribute::disabled");
+ } else {
+ ALOGI("codec %s enabled, device sdk %d >= required %d",
+ mState->codecName().c_str(), mysdk, sdk);
+ codec.quirkSet.erase("attribute::disabled");
+ }
+ }
+
return OK;
}
diff --git a/media/libstagefright/xmlparser/api/current.txt b/media/libstagefright/xmlparser/api/current.txt
index ecfd85e..95c347a 100644
--- a/media/libstagefright/xmlparser/api/current.txt
+++ b/media/libstagefright/xmlparser/api/current.txt
@@ -84,6 +84,7 @@
method public java.util.List<media.codecs.Feature> getFeature_optional();
method public java.util.List<media.codecs.Limit> getLimit_optional();
method public java.util.List<media.codecs.Mapping> getMapping_optional();
+ method public String getMinsdk();
method public String getName();
method public java.util.List<media.codecs.Quirk> getQuirk_optional();
method public String getRank();
@@ -95,6 +96,7 @@
method public java.util.List<media.codecs.Variant> getVariant_optional();
method public void setDomain(String);
method public void setEnabled(String);
+ method public void setMinsdk(String);
method public void setName(String);
method public void setRank(String);
method public void setType(String);
diff --git a/media/libstagefright/xmlparser/media_codecs.xsd b/media/libstagefright/xmlparser/media_codecs.xsd
index c9a7efc..33f3a27 100644
--- a/media/libstagefright/xmlparser/media_codecs.xsd
+++ b/media/libstagefright/xmlparser/media_codecs.xsd
@@ -74,6 +74,7 @@
<xs:attribute name="domain" type="xs:string"/>
<xs:attribute name="variant" type="xs:string"/>
<xs:attribute name="enabled" type="xs:string"/>
+ <xs:attribute name="minsdk" type="xs:string"/>
</xs:complexType>
<xs:complexType name="Quirk">
<xs:attribute name="name" type="xs:string"/>
diff --git a/media/libstagefright/xmlparser/test/XMLParserTest.cpp b/media/libstagefright/xmlparser/test/XMLParserTest.cpp
index 7629d97..2c5821e 100644
--- a/media/libstagefright/xmlparser/test/XMLParserTest.cpp
+++ b/media/libstagefright/xmlparser/test/XMLParserTest.cpp
@@ -145,6 +145,33 @@
},
{}, "");
+ // minsdk
+ setCodecProperties("test12.encoder", true, 12, {"attribute::disabled"}, {}, {}, "video/t12",
+ {
+ pair<string, string>("tuning-enable-goal", "no"),
+ },
+ {}, "");
+ setCodecProperties("test13.encoder", true, 13, {"attribute::disabled"}, {}, {}, "video/t13",
+ {
+ pair<string, string>("tuning-enable-goal", "no"),
+ },
+ {}, "");
+ setCodecProperties("test14.encoder", true, 14, {"attribute::disabled"}, {}, {}, "video/t14",
+ {
+ pair<string, string>("tuning-enable-goal", "no"),
+ },
+ {}, "");
+ setCodecProperties("test15.encoder", true, 15, {}, {}, {}, "video/t15",
+ {
+ pair<string, string>("tuning-enable-goal", "yes"),
+ },
+ {}, "");
+ setCodecProperties("test16.encoder", true, 16, {}, {}, {}, "video/t16",
+ {
+ pair<string, string>("tuning-enable-goal", "yes"),
+ },
+ {}, "");
+
setRoleProperties("audio_decoder.mp3", false, 1, "audio/mpeg", "test1.decoder",
{pair<string, string>("attribute::disabled", "present"),
pair<string, string>("rank", "4")});
@@ -191,6 +218,22 @@
pair<string, string>("tuning-pi", "3.1415")
});
+ // minsdk
+ setRoleProperties("video_encoder.t12", true, 12, "video/t12", "test12.encoder",
+ {pair<string, string>("tuning-enable-goal", "no"),
+ pair<string, string>("attribute::disabled", "present") });
+ setRoleProperties("video_encoder.t13", true, 13, "video/t13", "test13.encoder",
+ {pair<string, string>("tuning-enable-goal", "no"),
+ pair<string, string>("attribute::disabled", "present") });
+ setRoleProperties("video_encoder.t14", true, 14, "video/t14", "test14.encoder",
+ {pair<string, string>("tuning-enable-goal", "no"),
+ pair<string, string>("attribute::disabled", "present") });
+ setRoleProperties("video_encoder.t15", true, 15, "video/t15", "test15.encoder",
+ {pair<string, string>("tuning-enable-goal", "yes")});
+ setRoleProperties("video_encoder.t16", true, 16, "video/t16", "test16.encoder",
+ {pair<string, string>("tuning-enable-goal", "yes")});
+
+
setServiceAttribute(
{pair<string, string>("domain-telephony", "0"), pair<string, string>("domain-tv", "0"),
pair<string, string>("setting2", "0"), pair<string, string>("variant-variant1", "0")});
diff --git a/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml b/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml
index 8cae423..e066927 100644
--- a/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml
+++ b/media/libstagefright/xmlparser/test/testdata/media_codecs_unit_test.xml
@@ -88,5 +88,21 @@
<Tuning name="hungry" value="yes"/>
<Tuning name="pi" value="3.1415"/>
</MediaCodec>
+ <!-- test minsdk -->
+ <MediaCodec name="test12.encoder" type="video/t12" minsdk="100">
+ <Tuning name="enable-goal" value="no"/>
+ </MediaCodec>
+ <MediaCodec name="test13.encoder" type="video/t13" enabled="false" minsdk="100">
+ <Tuning name="enable-goal" value="no"/>
+ </MediaCodec>
+ <MediaCodec name="test14.encoder" type="video/t14" enabled="true" minsdk="100">
+ <Tuning name="enable-goal" value="no"/>
+ </MediaCodec>
+ <MediaCodec name="test15.encoder" type="video/t15" minsdk="34">
+ <Tuning name="enable-goal" value="yes"/>
+ </MediaCodec>
+ <MediaCodec name="test16.encoder" type="video/t16" enabled="false" minsdk="34">
+ <Tuning name="enable-goal" value="yes"/>
+ </MediaCodec>
</Encoders>
</Included>