Skip to content
Snippets Groups Projects
Commit 1e92835f authored by Jeff Sharkey's avatar Jeff Sharkey
Browse files

Human-readable XML on Ravenwood.

We had temporarily been using the binary XML implementation in all
situations, but this change brings in the existing `kxml2-android`
library to offer reading/writing of human-readable XML.  We also
use the upstream SAX parser to offer an event-based parser.

In all cases we carefully keep the existing XML libraries in place
untouched on physical devices to avoid regressions.

Bug: 324417456
Test: atest CtsUtilTestCasesRavenwood
Test: atest FrameworksCoreTestsRavenwood
Test: atest FrameworksUtilTestsRavenwood
Change-Id: I2effc7fca5c586968658073f9652d13cf50a2c66
parent 7816eba7
No related branches found
No related tags found
No related merge requests found
......@@ -94,14 +94,19 @@ java_library {
android_ravenwood_libgroup {
name: "ravenwood-runtime",
libs: [
// Prefixed with "200" to ensure it's sorted early in Tradefed classpath
// so that we provide a concrete implementation before Mainline stubs
"200-kxml2-android",
"all-updatable-modules-system-stubs",
"android.test.mock.ravenwood",
"framework-minus-apex.ravenwood",
"hoststubgen-helper-runtime.ravenwood",
"hoststubgen-helper-framework-runtime.ravenwood",
"all-updatable-modules-system-stubs",
"hoststubgen-helper-runtime.ravenwood",
// Provide runtime versions of utils linked in below
"junit",
"truth",
"ravenwood-junit-impl",
"android.test.mock.ravenwood",
"mockito-ravenwood-prebuilt",
"inline-mockito-ravenwood-prebuilt",
],
......
......@@ -53,9 +53,12 @@ import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import javax.xml.parsers.SAXParserFactory;
/**
* XML utility methods.
*/
@android.ravenwood.annotation.RavenwoodKeepWholeClass
public class Xml {
private Xml() {}
......@@ -73,8 +76,33 @@ public class Xml {
*
* @hide
*/
public static final boolean ENABLE_BINARY_DEFAULT = SystemProperties
.getBoolean("persist.sys.binary_xml", true);
public static final boolean ENABLE_BINARY_DEFAULT = shouldEnableBinaryDefault();
@android.ravenwood.annotation.RavenwoodReplace
private static boolean shouldEnableBinaryDefault() {
return SystemProperties.getBoolean("persist.sys.binary_xml", true);
}
private static boolean shouldEnableBinaryDefault$ravenwood() {
return true;
}
/**
* Feature flag: when set, {@link #resolvePullParser(InputStream)}} will attempt to sniff
* using {@code pread} optimization.
*
* @hide
*/
public static final boolean ENABLE_RESOLVE_OPTIMIZATIONS = shouldEnableResolveOptimizations();
@android.ravenwood.annotation.RavenwoodReplace
private static boolean shouldEnableResolveOptimizations() {
return true;
}
private static boolean shouldEnableResolveOptimizations$ravenwood() {
return false;
}
/**
* Parses the given xml string and fires events on the given SAX handler.
......@@ -82,7 +110,7 @@ public class Xml {
public static void parse(String xml, ContentHandler contentHandler)
throws SAXException {
try {
XMLReader reader = XmlObjectFactory.newXMLReader();
XMLReader reader = newXMLReader();
reader.setContentHandler(contentHandler);
reader.parse(new InputSource(new StringReader(xml)));
} catch (IOException e) {
......@@ -96,7 +124,7 @@ public class Xml {
*/
public static void parse(Reader in, ContentHandler contentHandler)
throws IOException, SAXException {
XMLReader reader = XmlObjectFactory.newXMLReader();
XMLReader reader = newXMLReader();
reader.setContentHandler(contentHandler);
reader.parse(new InputSource(in));
}
......@@ -107,7 +135,7 @@ public class Xml {
*/
public static void parse(InputStream in, Encoding encoding,
ContentHandler contentHandler) throws IOException, SAXException {
XMLReader reader = XmlObjectFactory.newXMLReader();
XMLReader reader = newXMLReader();
reader.setContentHandler(contentHandler);
InputSource source = new InputSource(in);
source.setEncoding(encoding.expatName);
......@@ -120,19 +148,26 @@ public class Xml {
@android.ravenwood.annotation.RavenwoodReplace
public static XmlPullParser newPullParser() {
try {
XmlPullParser parser = XmlObjectFactory.newXmlPullParser();
XmlPullParser parser = newXmlPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_DOCDECL, true);
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
return parser;
} catch (XmlPullParserException e) {
throw new AssertionError();
throw new AssertionError(e);
}
}
/** @hide */
public static XmlPullParser newPullParser$ravenwood() {
// TODO: remove once we're linking against libcore
return new BinaryXmlPullParser();
try {
// Prebuilt kxml2-android does not support FEATURE_PROCESS_DOCDECL, so omit here;
// it's quite rare and all tests are passing
XmlPullParser parser = newXmlPullParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
return parser;
} catch (XmlPullParserException e) {
throw new AssertionError(e);
}
}
/**
......@@ -145,17 +180,10 @@ public class Xml {
* @hide
*/
@SuppressWarnings("AndroidFrameworkEfficientXml")
@android.ravenwood.annotation.RavenwoodReplace
public static @NonNull TypedXmlPullParser newFastPullParser() {
return XmlUtils.makeTyped(newPullParser());
}
/** @hide */
public static TypedXmlPullParser newFastPullParser$ravenwood() {
// TODO: remove once we're linking against libcore
return new BinaryXmlPullParser();
}
/**
* Creates a new {@link XmlPullParser} that reads XML documents using a
* custom binary wire protocol which benchmarking has shown to be 8.5x
......@@ -189,11 +217,10 @@ public class Xml {
*
* @hide
*/
@android.ravenwood.annotation.RavenwoodReplace
public static @NonNull TypedXmlPullParser resolvePullParser(@NonNull InputStream in)
throws IOException {
final byte[] magic = new byte[4];
if (in instanceof FileInputStream) {
if (ENABLE_RESOLVE_OPTIMIZATIONS && in instanceof FileInputStream) {
try {
Os.pread(((FileInputStream) in).getFD(), magic, 0, magic.length, 0);
} catch (ErrnoException e) {
......@@ -222,31 +249,11 @@ public class Xml {
return xml;
}
/** @hide */
public static @NonNull TypedXmlPullParser resolvePullParser$ravenwood(@NonNull InputStream in)
throws IOException {
// TODO: remove once we're linking against libcore
final TypedXmlPullParser xml = new BinaryXmlPullParser();
try {
xml.setInput(in, StandardCharsets.UTF_8.name());
} catch (XmlPullParserException e) {
throw new IOException(e);
}
return xml;
}
/**
* Creates a new xml serializer.
*/
@android.ravenwood.annotation.RavenwoodReplace
public static XmlSerializer newSerializer() {
return XmlObjectFactory.newXmlSerializer();
}
/** @hide */
public static XmlSerializer newSerializer$ravenwood() {
// TODO: remove once we're linking against libcore
return new BinaryXmlSerializer();
return newXmlSerializer();
}
/**
......@@ -259,17 +266,10 @@ public class Xml {
* @hide
*/
@SuppressWarnings("AndroidFrameworkEfficientXml")
@android.ravenwood.annotation.RavenwoodReplace
public static @NonNull TypedXmlSerializer newFastSerializer() {
return XmlUtils.makeTyped(new FastXmlSerializer());
}
/** @hide */
public static @NonNull TypedXmlSerializer newFastSerializer$ravenwood() {
// TODO: remove once we're linking against libcore
return new BinaryXmlSerializer();
}
/**
* Creates a new {@link XmlSerializer} that writes XML documents using a
* custom binary wire protocol which benchmarking has shown to be 4.4x
......@@ -334,7 +334,6 @@ public class Xml {
*
* @hide
*/
@android.ravenwood.annotation.RavenwoodKeep
public static void copy(@NonNull XmlPullParser in, @NonNull XmlSerializer out)
throws XmlPullParserException, IOException {
// Some parsers may have already consumed the event that starts the
......@@ -394,7 +393,6 @@ public class Xml {
* unsupported, which can confuse serializers. This method normalizes empty
* strings to be {@code null}.
*/
@android.ravenwood.annotation.RavenwoodKeep
private static @Nullable String normalizeNamespace(@Nullable String namespace) {
if (namespace == null || namespace.isEmpty()) {
return null;
......@@ -457,4 +455,45 @@ public class Xml {
? (AttributeSet) parser
: new XmlPullAttributes(parser);
}
@android.ravenwood.annotation.RavenwoodReplace
private static @NonNull XmlSerializer newXmlSerializer() {
return XmlObjectFactory.newXmlSerializer();
}
private static @NonNull XmlSerializer newXmlSerializer$ravenwood() {
try {
return XmlPullParserFactory.newInstance().newSerializer();
} catch (XmlPullParserException e) {
throw new UnsupportedOperationException(e);
}
}
@android.ravenwood.annotation.RavenwoodReplace
private static @NonNull XmlPullParser newXmlPullParser() {
return XmlObjectFactory.newXmlPullParser();
}
private static @NonNull XmlPullParser newXmlPullParser$ravenwood() {
try {
return XmlPullParserFactory.newInstance().newPullParser();
} catch (XmlPullParserException e) {
throw new UnsupportedOperationException(e);
}
}
@android.ravenwood.annotation.RavenwoodReplace
private static @NonNull XMLReader newXMLReader() {
return XmlObjectFactory.newXMLReader();
}
private static @NonNull XMLReader newXMLReader$ravenwood() {
try {
final SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
return factory.newSAXParser().getXMLReader();
} catch (Exception e) {
throw new UnsupportedOperationException(e);
}
}
}
......@@ -45,7 +45,6 @@ import java.nio.charset.StandardCharsets;
*/
@SmallTest
@RunWith(AndroidJUnit4.class)
@IgnoreUnderRavenwood(blockedBy = Xml.class)
public class FastXmlSerializerTest {
private static final String TAG = "FastXmlSerializerTest";
......@@ -146,6 +145,7 @@ public class FastXmlSerializerTest {
@Test
@LargeTest
@IgnoreUnderRavenwood(reason = "Long test runtime")
public void testAllCharacters() throws Exception {
boolean ok = true;
for (int i = 0; i < 0xffff; i++) {
......
......@@ -58,11 +58,14 @@ java_library {
visibility: ["//visibility:public"],
}
java_host_for_device {
name: "core-xml-for-device",
libs: [
"core-xml-for-host",
java_library {
// Prefixed with "200" to ensure it's sorted early in Tradefed classpath
// so that we provide a concrete implementation before Mainline stubs
name: "200-kxml2-android",
static_libs: [
"kxml2-android",
],
visibility: ["//frameworks/base"],
}
java_host_for_device {
......
......@@ -89,6 +89,7 @@ class android.util.UtilConfig stubclass
# Internals
class com.android.internal.util.FileRotator stubclass
class com.android.internal.util.FastXmlSerializer stubclass
class com.android.internal.util.HexDump stubclass
class com.android.internal.util.MessageUtils stubclass
class com.android.internal.util.Preconditions stubclass
......
......@@ -180,7 +180,6 @@ java_library {
"framework-minus-apex.ravenwood",
],
static_libs: [
"core-xml-for-device",
"hoststubgen-helper-libcore-runtime.ravenwood",
],
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment