PersistableBundle for Ravenwood, with CTS.
We have the XML interfaces from libcore, but the implementations
there are tied closely to things like StringPool. We thankfully
have our own human-readable XML serializer that we could use, but
there's unfortunately not a good pull parser.
To get us unstuck for the moment, pivot the internals to
unconditionally use the binary XML format, which at least we
know is thoroughly tested, and any data written through this path
can then also be parsed.
This is enough to support PersistableBundle, and we'll circle back
to get ourselves a human-readable XML implementation in the future.
Bug: 292141694
Test: atest-dev CtsOsTestCasesRavenwood CtsOsTestCases
Change-Id: I875a3a2b0e95e52861afe187e2a5e9f1e740d8d5
diff --git a/core/java/android/util/Xml.java b/core/java/android/util/Xml.java
index 33058d8..2a33caa 100644
--- a/core/java/android/util/Xml.java
+++ b/core/java/android/util/Xml.java
@@ -26,6 +26,7 @@
import com.android.internal.util.ArtBinaryXmlSerializer;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
+import com.android.modules.utils.BinaryXmlPullParser;
import com.android.modules.utils.BinaryXmlSerializer;
import com.android.modules.utils.TypedXmlPullParser;
import com.android.modules.utils.TypedXmlSerializer;
@@ -38,6 +39,7 @@
import org.xml.sax.XMLReader;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlSerializer;
import java.io.BufferedInputStream;
@@ -115,6 +117,7 @@
/**
* Returns a new pull parser with namespace support.
*/
+ @android.ravenwood.annotation.RavenwoodReplace
public static XmlPullParser newPullParser() {
try {
XmlPullParser parser = XmlObjectFactory.newXmlPullParser();
@@ -126,6 +129,12 @@
}
}
+ /** @hide */
+ public static XmlPullParser newPullParser$ravenwood() {
+ // TODO: remove once we're linking against libcore
+ return new BinaryXmlPullParser();
+ }
+
/**
* Creates a new {@link TypedXmlPullParser} which is optimized for use
* inside the system, typically by supporting only a basic set of features.
@@ -136,10 +145,17 @@
* @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
@@ -148,10 +164,17 @@
*
* @hide
*/
+ @android.ravenwood.annotation.RavenwoodReplace
public static @NonNull TypedXmlPullParser newBinaryPullParser() {
return new ArtBinaryXmlPullParser();
}
+ /** @hide */
+ public static TypedXmlPullParser newBinaryPullParser$ravenwood() {
+ // TODO: remove once we're linking against libcore
+ return new BinaryXmlPullParser();
+ }
+
/**
* Creates a new {@link XmlPullParser} which is optimized for use inside the
* system, typically by supporting only a basic set of features.
@@ -166,6 +189,7 @@
*
* @hide
*/
+ @android.ravenwood.annotation.RavenwoodReplace
public static @NonNull TypedXmlPullParser resolvePullParser(@NonNull InputStream in)
throws IOException {
final byte[] magic = new byte[4];
@@ -198,13 +222,33 @@
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();
+ }
+
/**
* Creates a new {@link XmlSerializer} which is optimized for use inside the
* system, typically by supporting only a basic set of features.
@@ -215,10 +259,17 @@
* @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
@@ -227,10 +278,17 @@
*
* @hide
*/
+ @android.ravenwood.annotation.RavenwoodReplace
public static @NonNull TypedXmlSerializer newBinarySerializer() {
return new ArtBinaryXmlSerializer();
}
+ /** @hide */
+ public static @NonNull TypedXmlSerializer newBinarySerializer$ravenwood() {
+ // TODO: remove once we're linking against libcore
+ return new BinaryXmlSerializer();
+ }
+
/**
* Creates a new {@link XmlSerializer} which is optimized for use inside the
* system, typically by supporting only a basic set of features.
@@ -245,6 +303,7 @@
*
* @hide
*/
+ @android.ravenwood.annotation.RavenwoodReplace
public static @NonNull TypedXmlSerializer resolveSerializer(@NonNull OutputStream out)
throws IOException {
final TypedXmlSerializer xml;
@@ -257,6 +316,15 @@
return xml;
}
+ /** @hide */
+ public static @NonNull TypedXmlSerializer resolveSerializer$ravenwood(@NonNull OutputStream out)
+ throws IOException {
+ // TODO: remove once we're linking against libcore
+ final TypedXmlSerializer xml = new BinaryXmlSerializer();
+ xml.setOutput(out, StandardCharsets.UTF_8.name());
+ return xml;
+ }
+
/**
* Copy the first XML document into the second document.
* <p>
diff --git a/core/java/com/android/internal/util/ArtFastDataInput.java b/core/java/com/android/internal/util/ArtFastDataInput.java
index 3e8916c..768ea82 100644
--- a/core/java/com/android/internal/util/ArtFastDataInput.java
+++ b/core/java/com/android/internal/util/ArtFastDataInput.java
@@ -21,6 +21,8 @@
import com.android.modules.utils.FastDataInput;
+import dalvik.system.VMRuntime;
+
import java.io.DataInput;
import java.io.IOException;
import java.io.InputStream;
@@ -35,13 +37,14 @@
*/
public class ArtFastDataInput extends FastDataInput {
private static AtomicReference<ArtFastDataInput> sInCache = new AtomicReference<>();
+ private static VMRuntime sRuntime = VMRuntime.getRuntime();
private final long mBufferPtr;
public ArtFastDataInput(@NonNull InputStream in, int bufferSize) {
super(in, bufferSize);
- mBufferPtr = mRuntime.addressOf(mBuffer);
+ mBufferPtr = sRuntime.addressOf(mBuffer);
}
/**
@@ -66,6 +69,7 @@
* Release a {@link ArtFastDataInput} to potentially be recycled. You must not
* interact with the object after releasing it.
*/
+ @Override
public void release() {
super.release();
@@ -76,6 +80,11 @@
}
@Override
+ public byte[] newByteArray(int bufferSize) {
+ return (byte[]) sRuntime.newNonMovableArray(byte.class, bufferSize);
+ }
+
+ @Override
public String readUTF() throws IOException {
// Attempt to read directly from buffer space if there's enough room,
// otherwise fall back to chunking into place
@@ -86,9 +95,9 @@
mBufferPos += len;
return res;
} else {
- final byte[] tmp = (byte[]) mRuntime.newNonMovableArray(byte.class, len + 1);
+ final byte[] tmp = (byte[]) sRuntime.newNonMovableArray(byte.class, len + 1);
readFully(tmp, 0, len);
- return CharsetUtils.fromModifiedUtf8Bytes(mRuntime.addressOf(tmp), 0, len);
+ return CharsetUtils.fromModifiedUtf8Bytes(sRuntime.addressOf(tmp), 0, len);
}
}
}
diff --git a/core/java/com/android/internal/util/ArtFastDataOutput.java b/core/java/com/android/internal/util/ArtFastDataOutput.java
index ac595b6..360ddb8 100644
--- a/core/java/com/android/internal/util/ArtFastDataOutput.java
+++ b/core/java/com/android/internal/util/ArtFastDataOutput.java
@@ -21,6 +21,8 @@
import com.android.modules.utils.FastDataOutput;
+import dalvik.system.VMRuntime;
+
import java.io.DataOutput;
import java.io.IOException;
import java.io.OutputStream;
@@ -35,13 +37,14 @@
*/
public class ArtFastDataOutput extends FastDataOutput {
private static AtomicReference<ArtFastDataOutput> sOutCache = new AtomicReference<>();
+ private static VMRuntime sRuntime = VMRuntime.getRuntime();
private final long mBufferPtr;
public ArtFastDataOutput(@NonNull OutputStream out, int bufferSize) {
super(out, bufferSize);
- mBufferPtr = mRuntime.addressOf(mBuffer);
+ mBufferPtr = sRuntime.addressOf(mBuffer);
}
/**
@@ -73,6 +76,11 @@
}
@Override
+ public byte[] newByteArray(int bufferSize) {
+ return (byte[]) sRuntime.newNonMovableArray(byte.class, bufferSize);
+ }
+
+ @Override
public void writeUTF(String s) throws IOException {
// Attempt to write directly to buffer space if there's enough room,
// otherwise fall back to chunking into place
@@ -94,8 +102,8 @@
// Negative value indicates buffer was too small and we need to
// allocate a temporary buffer for encoding
len = -len;
- final byte[] tmp = (byte[]) mRuntime.newNonMovableArray(byte.class, len + 1);
- CharsetUtils.toModifiedUtf8Bytes(s, mRuntime.addressOf(tmp), 0, tmp.length);
+ final byte[] tmp = (byte[]) sRuntime.newNonMovableArray(byte.class, len + 1);
+ CharsetUtils.toModifiedUtf8Bytes(s, sRuntime.addressOf(tmp), 0, tmp.length);
writeShort(len);
write(tmp, 0, len);
}
diff --git a/ravenwood/Android.bp b/ravenwood/Android.bp
index fc4ed1d..b9e34ee 100644
--- a/ravenwood/Android.bp
+++ b/ravenwood/Android.bp
@@ -33,3 +33,10 @@
],
visibility: ["//visibility:public"],
}
+
+java_host_for_device {
+ name: "core-xml-for-device",
+ libs: [
+ "core-xml-for-host",
+ ],
+}
diff --git a/ravenwood/framework-minus-apex-ravenwood-policies.txt b/ravenwood/framework-minus-apex-ravenwood-policies.txt
index 692d598..3e54c7a 100644
--- a/ravenwood/framework-minus-apex-ravenwood-policies.txt
+++ b/ravenwood/framework-minus-apex-ravenwood-policies.txt
@@ -103,7 +103,21 @@
# Containers
class android.os.BaseBundle stubclass
class android.os.Bundle stubclass
+class android.os.PersistableBundle stubclass
# Misc
class android.os.PatternMatcher stubclass
class android.os.ParcelUuid stubclass
+
+# XML
+class com.android.internal.util.XmlPullParserWrapper stubclass
+class com.android.internal.util.XmlSerializerWrapper stubclass
+class com.android.internal.util.XmlUtils stubclass
+
+class com.android.modules.utils.BinaryXmlPullParser stubclass
+class com.android.modules.utils.BinaryXmlSerializer stubclass
+class com.android.modules.utils.FastDataInput stubclass
+class com.android.modules.utils.FastDataOutput stubclass
+class com.android.modules.utils.ModifiedUtf8 stubclass
+class com.android.modules.utils.TypedXmlPullParser stubclass
+class com.android.modules.utils.TypedXmlSerializer stubclass
diff --git a/ravenwood/ravenwood-annotation-allowed-classes.txt b/ravenwood/ravenwood-annotation-allowed-classes.txt
index 930dfc9..1ac6bf0 100644
--- a/ravenwood/ravenwood-annotation-allowed-classes.txt
+++ b/ravenwood/ravenwood-annotation-allowed-classes.txt
@@ -2,6 +2,8 @@
com.android.internal.util.ArrayUtils
+android.util.Xml
+
android.os.Binder
android.os.Binder$IdentitySupplier
android.os.IBinder
diff --git a/tools/hoststubgen/hoststubgen/Android.bp b/tools/hoststubgen/hoststubgen/Android.bp
index fd4ec8b..5949bca 100644
--- a/tools/hoststubgen/hoststubgen/Android.bp
+++ b/tools/hoststubgen/hoststubgen/Android.bp
@@ -284,6 +284,9 @@
"hoststubgen-helper-runtime.ravenwood",
"framework-minus-apex.ravenwood",
],
+ static_libs: [
+ "core-xml-for-device",
+ ],
}
// Defaults for host side test modules.