From 4ee8a655a0b41cec660578081fa1a21248e457cc Mon Sep 17 00:00:00 2001 From: Jeff Sharkey <jsharkey@google.com> Date: Tue, 14 Nov 2023 08:45:56 -0700 Subject: [PATCH] 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 --- core/java/android/util/Xml.java | 68 +++++++++++++++++++ .../internal/util/ArtFastDataInput.java | 15 +++- .../internal/util/ArtFastDataOutput.java | 14 +++- ravenwood/Android.bp | 7 ++ ...ramework-minus-apex-ravenwood-policies.txt | 14 ++++ .../ravenwood-annotation-allowed-classes.txt | 2 + tools/hoststubgen/hoststubgen/Android.bp | 3 + 7 files changed, 117 insertions(+), 6 deletions(-) diff --git a/core/java/android/util/Xml.java b/core/java/android/util/Xml.java index 33058d84b2e5..2a33caaf7e28 100644 --- a/core/java/android/util/Xml.java +++ b/core/java/android/util/Xml.java @@ -26,6 +26,7 @@ import com.android.internal.util.ArtBinaryXmlPullParser; 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.SAXException; 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 @@ public class Xml { /** * 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 @@ public class Xml { } } + /** @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 @@ 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 @@ -148,10 +164,17 @@ public class Xml { * * @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 @@ public class Xml { * * @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 @@ 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(); + } + /** * 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 @@ 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 @@ -227,10 +278,17 @@ public class Xml { * * @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 @@ public class Xml { * * @hide */ + @android.ravenwood.annotation.RavenwoodReplace public static @NonNull TypedXmlSerializer resolveSerializer(@NonNull OutputStream out) throws IOException { final TypedXmlSerializer xml; @@ -257,6 +316,15 @@ public class Xml { 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 3e8916caead9..768ea82e0c71 100644 --- a/core/java/com/android/internal/util/ArtFastDataInput.java +++ b/core/java/com/android/internal/util/ArtFastDataInput.java @@ -21,6 +21,8 @@ import android.util.CharsetUtils; 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 @@ import java.util.concurrent.atomic.AtomicReference; */ 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 @@ public class ArtFastDataInput extends FastDataInput { * Release a {@link ArtFastDataInput} to potentially be recycled. You must not * interact with the object after releasing it. */ + @Override public void release() { super.release(); @@ -75,6 +79,11 @@ public class ArtFastDataInput extends FastDataInput { } } + @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, @@ -86,9 +95,9 @@ public class ArtFastDataInput extends FastDataInput { 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 ac595b6fd151..360ddb814aa2 100644 --- a/core/java/com/android/internal/util/ArtFastDataOutput.java +++ b/core/java/com/android/internal/util/ArtFastDataOutput.java @@ -21,6 +21,8 @@ import android.util.CharsetUtils; 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 @@ import java.util.concurrent.atomic.AtomicReference; */ 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); } /** @@ -72,6 +75,11 @@ public class ArtFastDataOutput extends FastDataOutput { } } + @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, @@ -94,8 +102,8 @@ public class ArtFastDataOutput extends FastDataOutput { // 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 fc4ed1d4d527..b9e34ee97f21 100644 --- a/ravenwood/Android.bp +++ b/ravenwood/Android.bp @@ -33,3 +33,10 @@ java_library { ], 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 692d598ac2bb..3e54c7a06288 100644 --- a/ravenwood/framework-minus-apex-ravenwood-policies.txt +++ b/ravenwood/framework-minus-apex-ravenwood-policies.txt @@ -103,7 +103,21 @@ class android.os.TransactionTooLargeException stubclass # 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 930dfc967cf3..1ac6bf0a7c4d 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 fd4ec8bd5931..5949bca2f9a3 100644 --- a/tools/hoststubgen/hoststubgen/Android.bp +++ b/tools/hoststubgen/hoststubgen/Android.bp @@ -284,6 +284,9 @@ java_library { "hoststubgen-helper-runtime.ravenwood", "framework-minus-apex.ravenwood", ], + static_libs: [ + "core-xml-for-device", + ], } // Defaults for host side test modules. -- GitLab