Merge "Final set of libcore benchmarks." am: 7ec1c694b5 am: 069963bf3b am: 0ee415f589 am: f129e7b7c2

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2122613

Change-Id: Ic164c445f9367b3d890c4379b3bbbd8b9fc876bd
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/apct-tests/perftests/core/Android.bp b/apct-tests/perftests/core/Android.bp
index 2182f0b..23464f8 100644
--- a/apct-tests/perftests/core/Android.bp
+++ b/apct-tests/perftests/core/Android.bp
@@ -43,12 +43,13 @@
         "apct-perftests-resources-manager-apps",
         "apct-perftests-utils",
         "collector-device-lib",
+        "core-tests-support",
         "guava",
     ],
 
     libs: ["android.test.base"],
 
-    java_resources: [ ":GoogleFontDancingScript", ],
+    java_resources: [":GoogleFontDancingScript"],
 
     data: [":perfetto_artifacts"],
 
diff --git a/apct-tests/perftests/core/src/android/libcore/nor_ready/JarFilePerfTest.java b/apct-tests/perftests/core/src/android/libcore/nor_ready/JarFilePerfTest.java
new file mode 100644
index 0000000..5ad5eea
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/nor_ready/JarFilePerfTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public class JarFilePerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Parameters(name = "mFilename={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][] {
+                    {"/system/framework/core-oj.jar"}, {"/system/priv-app/Phonesky/Phonesky.apk"}
+                });
+    }
+
+    @Parameterized.Parameter(0)
+    public String mFilename;
+
+    @Test
+    public void time() throws Exception {
+        File f = new File(mFilename);
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            JarFile jf = new JarFile(f);
+            Manifest m = jf.getManifest();
+            jf.close();
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SSLLoopbackPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SSLLoopbackPerfTest.java
new file mode 100644
index 0000000..694d609
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/SSLLoopbackPerfTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import libcore.java.security.TestKeyStore;
+import libcore.javax.net.ssl.TestSSLContext;
+import libcore.javax.net.ssl.TestSSLSocketPair;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.net.ssl.SSLSocket;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class SSLLoopbackPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void time() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            TestSSLContext context =
+                    TestSSLContext.create(TestKeyStore.getClient(), TestKeyStore.getServer());
+            SSLSocket[] sockets = TestSSLSocketPair.connect(context, null, null);
+            context.close();
+            sockets[0].close();
+            sockets[1].close();
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SSLSocketFactoryPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SSLSocketFactoryPerfTest.java
new file mode 100644
index 0000000..bdbbcb0
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/SSLSocketFactoryPerfTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import javax.net.ssl.SSLSocketFactory;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class SSLSocketFactoryPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void time() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            SSLSocketFactory.getDefault();
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SchemePrefixPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SchemePrefixPerfTest.java
new file mode 100644
index 0000000..42dc581
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/SchemePrefixPerfTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public final class SchemePrefixPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    enum Strategy {
+        JAVA() {
+            @Override
+            String execute(String spec) {
+                int colon = spec.indexOf(':');
+
+                if (colon < 1) {
+                    return null;
+                }
+
+                for (int i = 0; i < colon; i++) {
+                    char c = spec.charAt(i);
+                    if (!isValidSchemeChar(i, c)) {
+                        return null;
+                    }
+                }
+
+                return spec.substring(0, colon).toLowerCase(Locale.US);
+            }
+
+            private boolean isValidSchemeChar(int index, char c) {
+                if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+                    return true;
+                }
+                if (index > 0 && ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.')) {
+                    return true;
+                }
+                return false;
+            }
+        },
+
+        REGEX() {
+            private final Pattern mPattern = Pattern.compile("^([a-zA-Z][a-zA-Z0-9+\\-.]*):");
+
+            @Override
+            String execute(String spec) {
+                Matcher matcher = mPattern.matcher(spec);
+                if (matcher.find()) {
+                    return matcher.group(1).toLowerCase(Locale.US);
+                } else {
+                    return null;
+                }
+            }
+        };
+
+        abstract String execute(String spec);
+    }
+
+    @Parameters(name = "mStrategy={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] {{Strategy.REGEX}, {Strategy.JAVA}});
+    }
+
+    @Parameterized.Parameter(0)
+    public Strategy mStrategy;
+
+    @Test
+    public void timeSchemePrefix() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStrategy.execute("http://android.com");
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SerializationPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SerializationPerfTest.java
new file mode 100644
index 0000000..1ec22d2
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/SerializationPerfTest.java
@@ -0,0 +1,292 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.ObjectStreamClass;
+import java.io.Serializable;
+import java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class SerializationPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private static byte[] bytes(Object o) throws Exception {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+        ObjectOutputStream out = new ObjectOutputStream(baos);
+        out.writeObject(o);
+        out.close();
+        return baos.toByteArray();
+    }
+
+    @Test
+    public void timeReadIntArray() throws Exception {
+        int[] intArray = new int[256];
+        readSingleObject(intArray);
+    }
+
+    @Test
+    public void timeWriteIntArray() throws Exception {
+        int[] intArray = new int[256];
+        writeSingleObject(intArray);
+    }
+
+    @Test
+    public void timeReadArrayListInteger() throws Exception {
+        ArrayList<Integer> object = new ArrayList<Integer>();
+        for (int i = 0; i < 256; ++i) {
+            object.add(i);
+        }
+        readSingleObject(object);
+    }
+
+    @Test
+    public void timeWriteArrayListInteger() throws Exception {
+        ArrayList<Integer> object = new ArrayList<Integer>();
+        for (int i = 0; i < 256; ++i) {
+            object.add(i);
+        }
+        writeSingleObject(object);
+    }
+
+    @Test
+    public void timeReadString() throws Exception {
+        readSingleObject("hello");
+    }
+
+    @Test
+    public void timeReadObjectStreamClass() throws Exception {
+        // A special case because serialization itself requires this class.
+        // (This should really be a unit test.)
+        ObjectStreamClass osc = ObjectStreamClass.lookup(String.class);
+        readSingleObject(osc);
+    }
+
+    @Test
+    public void timeWriteString() throws Exception {
+        // String is a special case that avoids JNI.
+        writeSingleObject("hello");
+    }
+
+    @Test
+    public void timeWriteObjectStreamClass() throws Exception {
+        // A special case because serialization itself requires this class.
+        // (This should really be a unit test.)
+        ObjectStreamClass osc = ObjectStreamClass.lookup(String.class);
+        writeSingleObject(osc);
+    }
+
+    // This is
+    //
+    // @Testa baseline for the others.
+    public void timeWriteNoObjects() throws Exception {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+        ObjectOutputStream out = new ObjectOutputStream(baos);
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            out.reset();
+            baos.reset();
+        }
+        out.close();
+    }
+
+    private void readSingleObject(Object object) throws Exception {
+        byte[] bytes = bytes(object);
+        ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            ObjectInputStream in = new ObjectInputStream(bais);
+            in.readObject();
+            in.close();
+            bais.reset();
+        }
+    }
+
+    private void writeSingleObject(Object o) throws Exception {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
+        ObjectOutputStream out = new ObjectOutputStream(baos);
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            out.writeObject(o);
+            out.reset();
+            baos.reset();
+        }
+        out.close();
+    }
+
+    @Test
+    public void timeWriteEveryKindOfField() throws Exception {
+        writeSingleObject(new LittleBitOfEverything());
+    }
+
+    @Test
+    public void timeWriteSerializableBoolean() throws Exception {
+        writeSingleObject(new SerializableBoolean());
+    }
+
+    @Test
+    public void timeWriteSerializableByte() throws Exception {
+        writeSingleObject(new SerializableByte());
+    }
+
+    @Test
+    public void timeWriteSerializableChar() throws Exception {
+        writeSingleObject(new SerializableChar());
+    }
+
+    @Test
+    public void timeWriteSerializableDouble() throws Exception {
+        writeSingleObject(new SerializableDouble());
+    }
+
+    @Test
+    public void timeWriteSerializableFloat() throws Exception {
+        writeSingleObject(new SerializableFloat());
+    }
+
+    @Test
+    public void timeWriteSerializableInt() throws Exception {
+        writeSingleObject(new SerializableInt());
+    }
+
+    @Test
+    public void timeWriteSerializableLong() throws Exception {
+        writeSingleObject(new SerializableLong());
+    }
+
+    @Test
+    public void timeWriteSerializableShort() throws Exception {
+        writeSingleObject(new SerializableShort());
+    }
+
+    @Test
+    public void timeWriteSerializableReference() throws Exception {
+        writeSingleObject(new SerializableReference());
+    }
+
+    @Test
+    public void timeReadEveryKindOfField() throws Exception {
+        readSingleObject(new LittleBitOfEverything());
+    }
+
+    @Test
+    public void timeReadSerializableBoolean() throws Exception {
+        readSingleObject(new SerializableBoolean());
+    }
+
+    @Test
+    public void timeReadSerializableByte() throws Exception {
+        readSingleObject(new SerializableByte());
+    }
+
+    @Test
+    public void timeReadSerializableChar() throws Exception {
+        readSingleObject(new SerializableChar());
+    }
+
+    @Test
+    public void timeReadSerializableDouble() throws Exception {
+        readSingleObject(new SerializableDouble());
+    }
+
+    @Test
+    public void timeReadSerializableFloat() throws Exception {
+        readSingleObject(new SerializableFloat());
+    }
+
+    @Test
+    public void timeReadSerializableInt() throws Exception {
+        readSingleObject(new SerializableInt());
+    }
+
+    @Test
+    public void timeReadSerializableLong() throws Exception {
+        readSingleObject(new SerializableLong());
+    }
+
+    @Test
+    public void timeReadSerializableShort() throws Exception {
+        readSingleObject(new SerializableShort());
+    }
+
+    @Test
+    public void timeReadSerializableReference() throws Exception {
+        readSingleObject(new SerializableReference());
+    }
+
+    public static class SerializableBoolean implements Serializable {
+        boolean mZ;
+    }
+
+    public static class SerializableByte implements Serializable {
+        byte mB;
+    }
+
+    public static class SerializableChar implements Serializable {
+        char mC;
+    }
+
+    public static class SerializableDouble implements Serializable {
+        double mD;
+    }
+
+    public static class SerializableFloat implements Serializable {
+        float mF;
+    }
+
+    public static class SerializableInt implements Serializable {
+        int mI;
+    }
+
+    public static class SerializableLong implements Serializable {
+        long mJ;
+    }
+
+    public static class SerializableShort implements Serializable {
+        short mS;
+    }
+
+    public static class SerializableReference implements Serializable {
+        Object mL;
+    }
+
+    public static class LittleBitOfEverything implements Serializable {
+        boolean mZ;
+        byte mB;
+        char mC;
+        double mD;
+        float mF;
+        int mI;
+        long mJ;
+        short mS;
+        Object mL;
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SignaturePerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SignaturePerfTest.java
new file mode 100644
index 0000000..a1899b9
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/SignaturePerfTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+/** Tests RSA and DSA mSignature creation and verification. */
+@RunWith(Parameterized.class)
+@LargeTest
+public class SignaturePerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Parameters(name = "mAlgorithm={0}, mImplementation={1}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][] {
+                    {Algorithm.MD5WithRSA, Implementation.OpenSSL},
+                    {Algorithm.SHA1WithRSA, Implementation.OpenSSL},
+                    {Algorithm.SHA256WithRSA, Implementation.OpenSSL},
+                    {Algorithm.SHA384WithRSA, Implementation.OpenSSL},
+                    {Algorithm.SHA512WithRSA, Implementation.OpenSSL},
+                    {Algorithm.SHA1withDSA, Implementation.OpenSSL},
+                    {Algorithm.SHA1withDSA, Implementation.BouncyCastle}
+                });
+    }
+
+    @Parameterized.Parameter(0)
+    public Algorithm mAlgorithm;
+
+    @Parameterized.Parameter(1)
+    public Implementation mImplementation;
+
+    private static final int DATA_SIZE = 8192;
+    private static final byte[] DATA = new byte[DATA_SIZE];
+
+    static {
+        for (int i = 0; i < DATA_SIZE; i++) {
+            DATA[i] = (byte) i;
+        }
+    }
+
+    public enum Algorithm {
+        MD5WithRSA,
+        SHA1WithRSA,
+        SHA256WithRSA,
+        SHA384WithRSA,
+        SHA512WithRSA,
+        SHA1withDSA
+    };
+
+    public enum Implementation {
+        OpenSSL,
+        BouncyCastle
+    };
+
+    // Key generation and signing aren't part of the benchmark for verification
+    // so cache the results
+    private static Map<String, KeyPair> sKeyPairs = new HashMap<String, KeyPair>();
+    private static Map<String, byte[]> sSignatures = new HashMap<String, byte[]>();
+
+    private String mSignatureAlgorithm;
+    private byte[] mSignature;
+    private PrivateKey mPrivateKey;
+    private PublicKey mPublicKey;
+
+    @Before
+    public void setUp() throws Exception {
+        this.mSignatureAlgorithm = mAlgorithm.toString();
+
+        String keyAlgorithm =
+                mSignatureAlgorithm.substring(
+                        mSignatureAlgorithm.length() - 3, mSignatureAlgorithm.length());
+        KeyPair keyPair = sKeyPairs.get(keyAlgorithm);
+        if (keyPair == null) {
+            KeyPairGenerator generator = KeyPairGenerator.getInstance(keyAlgorithm);
+            keyPair = generator.generateKeyPair();
+            sKeyPairs.put(keyAlgorithm, keyPair);
+        }
+        this.mPrivateKey = keyPair.getPrivate();
+        this.mPublicKey = keyPair.getPublic();
+
+        this.mSignature = sSignatures.get(mSignatureAlgorithm);
+        if (this.mSignature == null) {
+            Signature signer = Signature.getInstance(mSignatureAlgorithm);
+            signer.initSign(keyPair.getPrivate());
+            signer.update(DATA);
+            this.mSignature = signer.sign();
+            sSignatures.put(mSignatureAlgorithm, mSignature);
+        }
+    }
+
+    @Test
+    public void timeSign() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Signature signer;
+            switch (mImplementation) {
+                case OpenSSL:
+                    signer = Signature.getInstance(mSignatureAlgorithm, "AndroidOpenSSL");
+                    break;
+                case BouncyCastle:
+                    signer = Signature.getInstance(mSignatureAlgorithm, "BC");
+                    break;
+                default:
+                    throw new RuntimeException(mImplementation.toString());
+            }
+            signer.initSign(mPrivateKey);
+            signer.update(DATA);
+            signer.sign();
+        }
+    }
+
+    @Test
+    public void timeVerify() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Signature verifier;
+            switch (mImplementation) {
+                case OpenSSL:
+                    verifier = Signature.getInstance(mSignatureAlgorithm, "AndroidOpenSSL");
+                    break;
+                case BouncyCastle:
+                    verifier = Signature.getInstance(mSignatureAlgorithm, "BC");
+                    break;
+                default:
+                    throw new RuntimeException(mImplementation.toString());
+            }
+            verifier.initVerify(mPublicKey);
+            verifier.update(DATA);
+            verifier.verify(mSignature);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/SimpleDateFormatPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/SimpleDateFormatPerfTest.java
new file mode 100644
index 0000000..c25b0ce
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/SimpleDateFormatPerfTest.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Benchmark for java.text.SimpleDateFormat. This tests common formatting, parsing and creation
+ * operations with a specific focus on TimeZone handling.
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class SimpleDateFormatPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void time_createFormatWithTimeZone() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd z");
+        }
+    }
+
+    @Test
+    public void time_parseWithTimeZoneShort() throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd z");
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            sdf.parse("2000.01.01 PST");
+        }
+    }
+
+    @Test
+    public void time_parseWithTimeZoneLong() throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd zzzz");
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            sdf.parse("2000.01.01 Pacific Standard Time");
+        }
+    }
+
+    @Test
+    public void time_parseWithoutTimeZone() throws ParseException {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd");
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            sdf.parse("2000.01.01");
+        }
+    }
+
+    @Test
+    public void time_createAndParseWithTimeZoneShort() throws ParseException {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd z");
+            sdf.parse("2000.01.01 PST");
+        }
+    }
+
+    @Test
+    public void time_createAndParseWithTimeZoneLong() throws ParseException {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd zzzz");
+            sdf.parse("2000.01.01 Pacific Standard Time");
+        }
+    }
+
+    @Test
+    public void time_formatWithTimeZoneShort() {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd z");
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            sdf.format(new Date());
+        }
+    }
+
+    @Test
+    public void time_formatWithTimeZoneLong() {
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd zzzz");
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            sdf.format(new Date());
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StrictMathPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StrictMathPerfTest.java
new file mode 100644
index 0000000..eeccb5b
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/StrictMathPerfTest.java
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Many of these tests are bogus in that the cost will vary wildly depending on inputs. For _my_
+ * current purposes, that's okay. But beware!
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class StrictMathPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private final double mDouble = 1.2;
+    private final float mFloat = 1.2f;
+    private final int mInt = 1;
+    private final long mLong = 1L;
+
+    /* Values for full line coverage of ceiling function */
+    private static final double[] CEIL_DOUBLES =
+            new double[] {
+                3245817.2018463886,
+                1418139.083668501,
+                3.572936802189103E15,
+                -4.7828929737254625E249,
+                213596.58636369856,
+                6.891928421440976E-96,
+                -7.9318566885477E-36,
+                -1.9610339084804148E15,
+                -4.696725715628246E10,
+                3742491.296880909,
+                7.140274745333553E11
+            };
+
+    /* Values for full line coverage of floor function */
+    private static final double[] FLOOR_DOUBLES =
+            new double[] {
+                7.140274745333553E11,
+                3742491.296880909,
+                -4.696725715628246E10,
+                -1.9610339084804148E15,
+                7.049948629370372E-56,
+                -7.702933170334643E-16,
+                -1.99657681810579,
+                -1.1659287182288336E236,
+                4.085518816513057E15,
+                -1500948.440658056,
+                -2.2316479921415575E7
+            };
+
+    @Test
+    public void timeAbsD() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.abs(mDouble);
+        }
+    }
+
+    @Test
+    public void timeAbsF() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.abs(mFloat);
+        }
+    }
+
+    @Test
+    public void timeAbsI() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.abs(mInt);
+        }
+    }
+
+    @Test
+    public void timeAbsL() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.abs(mLong);
+        }
+    }
+
+    @Test
+    public void timeAcos() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.acos(mDouble);
+        }
+    }
+
+    @Test
+    public void timeAsin() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.asin(mDouble);
+        }
+    }
+
+    @Test
+    public void timeAtan() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.atan(mDouble);
+        }
+    }
+
+    @Test
+    public void timeAtan2() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.atan2(3, 4);
+        }
+    }
+
+    @Test
+    public void timeCbrt() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.cbrt(mDouble);
+        }
+    }
+
+    @Test
+    public void timeCeilOverInterestingValues() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < CEIL_DOUBLES.length; ++i) {
+                StrictMath.ceil(CEIL_DOUBLES[i]);
+            }
+        }
+    }
+
+    @Test
+    public void timeCopySignD() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.copySign(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeCopySignF() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.copySign(mFloat, mFloat);
+        }
+    }
+
+    @Test
+    public void timeCos() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.cos(mDouble);
+        }
+    }
+
+    @Test
+    public void timeCosh() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.cosh(mDouble);
+        }
+    }
+
+    @Test
+    public void timeExp() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.exp(mDouble);
+        }
+    }
+
+    @Test
+    public void timeExpm1() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.expm1(mDouble);
+        }
+    }
+
+    @Test
+    public void timeFloorOverInterestingValues() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < FLOOR_DOUBLES.length; ++i) {
+                StrictMath.floor(FLOOR_DOUBLES[i]);
+            }
+        }
+    }
+
+    @Test
+    public void timeGetExponentD() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.getExponent(mDouble);
+        }
+    }
+
+    @Test
+    public void timeGetExponentF() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.getExponent(mFloat);
+        }
+    }
+
+    @Test
+    public void timeHypot() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.hypot(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeIEEEremainder() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.IEEEremainder(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeLog() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.log(mDouble);
+        }
+    }
+
+    @Test
+    public void timeLog10() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.log10(mDouble);
+        }
+    }
+
+    @Test
+    public void timeLog1p() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.log1p(mDouble);
+        }
+    }
+
+    @Test
+    public void timeMaxD() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.max(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeMaxF() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.max(mFloat, mFloat);
+        }
+    }
+
+    @Test
+    public void timeMaxI() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.max(mInt, mInt);
+        }
+    }
+
+    @Test
+    public void timeMaxL() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.max(mLong, mLong);
+        }
+    }
+
+    @Test
+    public void timeMinD() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.min(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeMinF() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.min(mFloat, mFloat);
+        }
+    }
+
+    @Test
+    public void timeMinI() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.min(mInt, mInt);
+        }
+    }
+
+    @Test
+    public void timeMinL() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.min(mLong, mLong);
+        }
+    }
+
+    @Test
+    public void timeNextAfterD() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.nextAfter(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeNextAfterF() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.nextAfter(mFloat, mFloat);
+        }
+    }
+
+    @Test
+    public void timeNextUpD() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.nextUp(mDouble);
+        }
+    }
+
+    @Test
+    public void timeNextUpF() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.nextUp(mFloat);
+        }
+    }
+
+    @Test
+    public void timePow() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.pow(mDouble, mDouble);
+        }
+    }
+
+    @Test
+    public void timeRandom() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.random();
+        }
+    }
+
+    @Test
+    public void timeRint() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.rint(mDouble);
+        }
+    }
+
+    @Test
+    public void timeRoundD() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.round(mDouble);
+        }
+    }
+
+    @Test
+    public void timeRoundF() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.round(mFloat);
+        }
+    }
+
+    @Test
+    public void timeScalbD() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.scalb(mDouble, 5);
+        }
+    }
+
+    @Test
+    public void timeScalbF() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.scalb(mFloat, 5);
+        }
+    }
+
+    @Test
+    public void timeSignumD() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.signum(mDouble);
+        }
+    }
+
+    @Test
+    public void timeSignumF() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.signum(mFloat);
+        }
+    }
+
+    @Test
+    public void timeSin() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.sin(mDouble);
+        }
+    }
+
+    @Test
+    public void timeSinh() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.sinh(mDouble);
+        }
+    }
+
+    @Test
+    public void timeSqrt() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.sqrt(mDouble);
+        }
+    }
+
+    @Test
+    public void timeTan() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.tan(mDouble);
+        }
+    }
+
+    @Test
+    public void timeTanh() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.tanh(mDouble);
+        }
+    }
+
+    @Test
+    public void timeToDegrees() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.toDegrees(mDouble);
+        }
+    }
+
+    @Test
+    public void timeToRadians() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.toRadians(mDouble);
+        }
+    }
+
+    @Test
+    public void timeUlpD() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.ulp(mDouble);
+        }
+    }
+
+    @Test
+    public void timeUlpF() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StrictMath.ulp(mFloat);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java
new file mode 100644
index 0000000..34fb88b
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/StringBuilderPerfTest.java
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+/** Tests the performance of various StringBuilder methods. */
+@RunWith(Parameterized.class)
+@LargeTest
+public class StringBuilderPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Parameters(name = "mLength={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] {{1}, {10}, {100}});
+    }
+
+    @Parameterized.Parameter(0)
+    public int mLength;
+
+    @Test
+    public void timeAppendBoolean() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < mLength; ++j) {
+                sb.append(true);
+            }
+        }
+    }
+
+    @Test
+    public void timeAppendChar() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < mLength; ++j) {
+                sb.append('c');
+            }
+        }
+    }
+
+    @Test
+    public void timeAppendCharArray() {
+        char[] chars = "chars".toCharArray();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < mLength; ++j) {
+                sb.append(chars);
+            }
+        }
+    }
+
+    @Test
+    public void timeAppendCharSequence() {
+        CharSequence cs = "chars";
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < mLength; ++j) {
+                sb.append(cs);
+            }
+        }
+    }
+
+    @Test
+    public void timeAppendSubCharSequence() {
+        CharSequence cs = "chars";
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < mLength; ++j) {
+                sb.append(cs);
+            }
+        }
+    }
+
+    @Test
+    public void timeAppendDouble() {
+        double d = 1.2;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < mLength; ++j) {
+                sb.append(d);
+            }
+        }
+    }
+
+    @Test
+    public void timeAppendFloat() {
+        float f = 1.2f;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < mLength; ++j) {
+                sb.append(f);
+            }
+        }
+    }
+
+    @Test
+    public void timeAppendInt() {
+        int n = 123;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < mLength; ++j) {
+                sb.append(n);
+            }
+        }
+    }
+
+    @Test
+    public void timeAppendLong() {
+        long l = 123;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < mLength; ++j) {
+                sb.append(l);
+            }
+        }
+    }
+
+    @Test
+    public void timeAppendObject() {
+        // We don't want to time the toString, so ensure we're calling a trivial one...
+        Object o =
+                new Object() {
+                    @Override
+                    public String toString() {
+                        return "constant";
+                    }
+                };
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < mLength; ++j) {
+                sb.append(o);
+            }
+        }
+    }
+
+    @Test
+    public void timeAppendString() {
+        String s = "chars";
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            StringBuilder sb = new StringBuilder();
+            for (int j = 0; j < mLength; ++j) {
+                sb.append(s);
+            }
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringEqualsPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringEqualsPerfTest.java
new file mode 100644
index 0000000..6854c0d
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/StringEqualsPerfTest.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import junit.framework.Assert;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Benchmarks to measure the performance of String.equals for Strings of varying lengths. Each
+ * benchmarks makes 5 measurements, aiming at covering cases like strings of equal length that are
+ * not equal, identical strings with different references, strings with different endings, interned
+ * strings, and strings of different lengths.
+ */
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class StringEqualsPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private final String mLong1 =
+            "Ahead-of-time compilation is possible as the compiler may just convert an instruction"
+                + " thus: dex code: add-int v1000, v2000, v3000 C code: setIntRegter(1000,"
+                + " call_dex_add_int(getIntRegister(2000), getIntRegister(3000)) This means even"
+                + " lidinstructions may have code generated, however, it is not expected that code"
+                + " generate inthis way will perform well. The job of AOT verification is to tell"
+                + " the compiler thatinstructions are sound and provide tests to detect unsound"
+                + " sequences so slow path codemay be generated. Other than for totally invalid"
+                + " code, the verification may fail at AOrrun-time. At AOT time it can be because"
+                + " of incomplete information, at run-time it can ethat code in a different apk"
+                + " that the application depends upon has changed. The Dalvikverifier would return"
+                + " a bool to state whether a Class were good or bad. In ART the fail case becomes"
+                + " either a soft or hard failure. Classes have new states to represent that a soft"
+                + " failure occurred at compile time and should be re-verified at run-time.";
+
+    private final String mVeryLong =
+            "Garbage collection has two phases. The first distinguishes live objects from garbage"
+                + " objects.  The second is reclaiming the rage of garbage objectIn the mark-sweep"
+                + " algorithm used by Dalvik, the first phase is achievd by computing the closure"
+                + " of all reachable objects in a process known as tracing from theoots.  After"
+                + " thetrace has completed, garbage objects are reclaimed.  Each of these"
+                + " operations can beparallelized and can be interleaved with the operation of the"
+                + " applicationTraditionally,the tracing phase dominates the time spent in garbage"
+                + " collection.  The greatreduction ipause time can be achieved by interleaving as"
+                + " much of this phase as possible with theapplication. If we simply ran the GC in"
+                + " a separate thread with no other changes, normaloperation of an application"
+                + " would confound the trace.  Abstractly, the GC walks the h oall reachable"
+                + " objects.  When the application is paused, the object graph cannot change.The GC"
+                + " can therefore walk this structure and assume that all reachable objects"
+                + " live.When the application is running, this graph may be altered. New nodes may"
+                + " be addnd edgemay be changed.  These changes may cause live objects to be hidden"
+                + " and falsely recla bythe GC.  To avoid this problem a write barrier is used to"
+                + " intercept and record modifionto objects in a separate structure.  After"
+                + " performing its walk, the GC will revisit theupdated objects and re-validate its"
+                + " assumptions.  Without a card table, the garbagecollector would have to visit"
+                + " all objects reached during the trace looking for dirtied objects.  The cost of"
+                + " this operation would be proportional to the amount of live data.With a card"
+                + " table, the cost of this operation is proportional to the amount of updateatThe"
+                + " write barrier in Dalvik is a card marking write barrier.  Card marking is the"
+                + " proceof noting the location of object connectivity changes on a sub-page"
+                + " granularity.  A caris merely a colorful term for a contiguous extent of memory"
+                + " smaller than a page, commonsomewhere between 128- and 512-bytes.  Card marking"
+                + " is implemented by instrumenting alllocations in the virtual machine which can"
+                + " assign a pointer to an object.  After themalpointer assignment has occurred, a"
+                + " byte is written to a byte-map spanning the heap whiccorresponds to the location"
+                + " of the updated object.  This byte map is known as a card taThe garbage"
+                + " collector visits this card table and looks for written bytes to reckon"
+                + " thelocation of updated objects.  It then rescans all objects located on the"
+                + " dirty card,correcting liveness assumptions that were invalidated by the"
+                + " application.  While cardmarking imposes a small burden on the application"
+                + " outside of a garbage collection, theoverhead of maintaining the card table is"
+                + " paid for by the reduced time spent insidegarbage collection. With the"
+                + " concurrent garbage collection thread and a write barriersupported by the"
+                + " interpreter, JIT, and Runtime we modify garbage collection";
+
+    private final String[][] mShortStrings =
+            new String[][] {
+                // Equal, constant comparison
+                {"a", "a"},
+                // Different constants, first character different
+                {":", " :"},
+                // Different constants, last character different, same length
+                {"ja M", "ja N"},
+                // Different constants, different lengths
+                {"$$$", "$$"},
+                // Force execution of code beyond reference equality check
+                {"hi", new String("hi")}
+            };
+
+    private final String[][] mMediumStrings =
+            new String[][] {
+                // Equal, constant comparison
+                {"Hello my name is ", "Hello my name is "},
+                // Different constants, different lengths
+                {"What's your name?", "Whats your name?"},
+                // Force execution of code beyond reference equality check
+                {"Android Runtime", new String("Android Runtime")},
+                // Different constants, last character different, same length
+                {"v3ry Cre@tiVe?****", "v3ry Cre@tiVe?***."},
+                // Different constants, first character different, same length
+                {"!@#$%^&*()_++*^$#@", "0@#$%^&*()_++*^$#@"}
+            };
+
+    private final String[][] mLongStrings =
+            new String[][] {
+                // Force execution of code beyond reference equality check
+                {mLong1, new String(mLong1)},
+                // Different constants, last character different, same length
+                {mLong1 + "fun!", mLong1 + "----"},
+                // Equal, constant comparison
+                {mLong1 + mLong1, mLong1 + mLong1},
+                // Different constants, different lengths
+                {mLong1 + "123456789", mLong1 + "12345678"},
+                // Different constants, first character different, same length
+                {"Android Runtime" + mLong1, "android Runtime" + mLong1}
+            };
+
+    private final String[][] mVeryLongStrings =
+            new String[][] {
+                // Force execution of code beyond reference equality check
+                {mVeryLong, new String(mVeryLong)},
+                // Different constants, different lengths
+                {mVeryLong + mVeryLong, mVeryLong + " " + mVeryLong},
+                // Equal, constant comparison
+                {mVeryLong + mVeryLong + mVeryLong, mVeryLong + mVeryLong + mVeryLong},
+                // Different constants, last character different, same length
+                {mVeryLong + "77777", mVeryLong + "99999"},
+                // Different constants, first character different
+                {"Android Runtime" + mVeryLong, "android Runtime" + mVeryLong}
+            };
+
+    private final String[][] mEndStrings =
+            new String[][] {
+                // Different constants, medium but different lengths
+                {"Hello", "Hello "},
+                // Different constants, long but different lengths
+                {mLong1, mLong1 + "x"},
+                // Different constants, very long but different lengths
+                {mVeryLong, mVeryLong + "?"},
+                // Different constants, same medium lengths
+                {"How are you doing today?", "How are you doing today "},
+                // Different constants, short but different lengths
+                {"1", "1."}
+            };
+
+    private final String mTmpStr1 =
+            "012345678901234567890"
+                    + "0123456789012345678901234567890123456789"
+                    + "0123456789012345678901234567890123456789"
+                    + "0123456789012345678901234567890123456789"
+                    + "0123456789012345678901234567890123456789";
+
+    private final String mTmpStr2 =
+            "z012345678901234567890"
+                    + "0123456789012345678901234567890123456789"
+                    + "0123456789012345678901234567890123456789"
+                    + "0123456789012345678901234567890123456789"
+                    + "012345678901234567890123456789012345678x";
+
+    private final String[][] mNonalignedStrings =
+            new String[][] {
+                // Different non-word aligned medium length strings
+                {mTmpStr1, mTmpStr1.substring(1)},
+                // Different differently non-word aligned medium length strings
+                {mTmpStr2, mTmpStr2.substring(2)},
+                // Different non-word aligned long length strings
+                {mLong1, mLong1.substring(3)},
+                // Different non-word aligned very long length strings
+                {mVeryLong, mVeryLong.substring(1)},
+                // Equal non-word aligned constant strings
+                {"hello", "hello".substring(1)}
+            };
+
+    private final Object[] mObjects =
+            new Object[] {
+                // Compare to Double object
+                new Double(1.5),
+                // Compare to Integer object
+                new Integer(9999999),
+                // Compare to String array
+                new String[] {"h", "i"},
+                // Compare to int array
+                new int[] {1, 2, 3},
+                // Compare to Character object
+                new Character('a')
+            };
+
+    // Check assumptions about how the compiler, new String(String), and String.intern() work.
+    // Any failures here would invalidate these benchmarks.
+    @Before
+    public void setUp() throws Exception {
+        // String constants are the same object
+        Assert.assertSame("abc", "abc");
+        // new String(String) makes a copy
+        Assert.assertNotSame("abc", new String("abc"));
+        // Interned strings are treated like constants, so it is not necessary to
+        // separately benchmark interned strings.
+        Assert.assertSame("abc", "abc".intern());
+        Assert.assertSame("abc", new String("abc").intern());
+        // Compiler folds constant strings into new constants
+        Assert.assertSame(mLong1 + mLong1, mLong1 + mLong1);
+    }
+
+    // Benchmark cases of String.equals(null)
+    @Test
+    public void timeEqualsNull() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < mMediumStrings.length; i++) {
+                mMediumStrings[i][0].equals(null);
+            }
+        }
+    }
+
+    // Benchmark cases with very short (<5 character) Strings
+    @Test
+    public void timeEqualsShort() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < mShortStrings.length; i++) {
+                mShortStrings[i][0].equals(mShortStrings[i][1]);
+            }
+        }
+    }
+
+    // Benchmark cases with medium length (10-15 character) Strings
+    @Test
+    public void timeEqualsMedium() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < mMediumStrings.length; i++) {
+                mMediumStrings[i][0].equals(mMediumStrings[i][1]);
+            }
+        }
+    }
+
+    // Benchmark cases with long (>100 character) Strings
+    @Test
+    public void timeEqualsLong() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < mLongStrings.length; i++) {
+                mLongStrings[i][0].equals(mLongStrings[i][1]);
+            }
+        }
+    }
+
+    // Benchmark cases with very long (>1000 character) Strings
+    @Test
+    public void timeEqualsVeryLong() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < mVeryLongStrings.length; i++) {
+                mVeryLongStrings[i][0].equals(mVeryLongStrings[i][1]);
+            }
+        }
+    }
+
+    // Benchmark cases with non-word aligned Strings
+    @Test
+    public void timeEqualsNonWordAligned() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < mNonalignedStrings.length; i++) {
+                mNonalignedStrings[i][0].equals(mNonalignedStrings[i][1]);
+            }
+        }
+    }
+
+    // Benchmark cases with slight differences in the endings
+    @Test
+    public void timeEqualsEnd() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < mEndStrings.length; i++) {
+                mEndStrings[i][0].equals(mEndStrings[i][1]);
+            }
+        }
+    }
+
+    // Benchmark cases of comparing a string to a non-string object
+    @Test
+    public void timeEqualsNonString() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            for (int i = 0; i < mMediumStrings.length; i++) {
+                mMediumStrings[i][0].equals(mObjects[i]);
+            }
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringIsEmptyPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringIsEmptyPerfTest.java
new file mode 100644
index 0000000..79ff646
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/StringIsEmptyPerfTest.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class StringIsEmptyPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeIsEmpty_NonEmpty() {
+        boolean result = true;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result &= !("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".isEmpty());
+        }
+        if (!result) throw new RuntimeException();
+    }
+
+    @Test
+    public void timeIsEmpty_Empty() {
+        boolean result = true;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result &= ("".isEmpty());
+        }
+        if (!result) throw new RuntimeException();
+    }
+
+    @Test
+    public void timeLengthEqualsZero() {
+        boolean result = true;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result &= !("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".length() == 0);
+        }
+        if (!result) throw new RuntimeException();
+    }
+
+    @Test
+    public void timeEqualsEmpty() {
+        boolean result = true;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            result &= !"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".equals("");
+        }
+        if (!result) throw new RuntimeException();
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringLengthPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringLengthPerfTest.java
new file mode 100644
index 0000000..8dbf9f5
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/StringLengthPerfTest.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class StringLengthPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeLength() {
+        int length = 0;
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            length = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx".length();
+        }
+        if (length != 51) throw new RuntimeException();
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringPerfTest.java
new file mode 100644
index 0000000..02194b1
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/StringPerfTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public class StringPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    enum StringLengths {
+        EMPTY(""),
+        SHORT("short"),
+        EIGHTY(makeString(80)),
+        EIGHT_KI(makeString(8192));
+        final String mValue;
+
+        StringLengths(String value) {
+            this.mValue = value;
+        }
+    }
+
+    @Parameters(name = "mStringLengths={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][] {
+                    {StringLengths.EIGHT_KI},
+                    {StringLengths.EIGHTY},
+                    {StringLengths.SHORT},
+                    {StringLengths.EMPTY}
+                });
+    }
+
+    @Parameterized.Parameter(0)
+    public StringLengths mStringLengths;
+
+    private static String makeString(int length) {
+        StringBuilder result = new StringBuilder(length);
+        for (int i = 0; i < length; ++i) {
+            result.append((char) i);
+        }
+        return result.toString();
+    }
+
+    @Test
+    public void timeHashCode() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.hashCode();
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringReplaceAllPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringReplaceAllPerfTest.java
new file mode 100644
index 0000000..b0d1ee4
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/StringReplaceAllPerfTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public class StringReplaceAllPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    // NOTE: These estimates of MOVEABLE / NON_MOVEABLE are based on a knowledge of
+    // ART implementation details. They make a difference here because JNI calls related
+    // to strings took different paths depending on whether the String in question was
+    // moveable or not.
+    enum StringLengths {
+        EMPTY(""),
+        MOVEABLE_16(makeString(16)),
+        MOVEABLE_256(makeString(256)),
+        MOVEABLE_1024(makeString(1024)),
+        NON_MOVEABLE(makeString(64 * 1024)),
+        BOOT_IMAGE(java.util.jar.JarFile.MANIFEST_NAME);
+
+        private final String mValue;
+
+        StringLengths(String s) {
+            this.mValue = s;
+        }
+    }
+
+    private static String makeString(int length) {
+        final String sequence8 = "abcdefghijklmnop";
+        final int numAppends = (length / 16) - 1;
+        StringBuilder stringBuilder = new StringBuilder(length);
+
+        // (n-1) occurrences of "abcdefghijklmnop"
+        for (int i = 0; i < numAppends; ++i) {
+            stringBuilder.append(sequence8);
+        }
+
+        // and one final occurrence of qrstuvwx.
+        stringBuilder.append("qrstuvwx");
+
+        return stringBuilder.toString();
+    }
+
+    @Parameters(name = "mStringLengths={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][] {
+                    {StringLengths.BOOT_IMAGE},
+                    {StringLengths.EMPTY},
+                    {StringLengths.MOVEABLE_16},
+                    {StringLengths.MOVEABLE_256},
+                    {StringLengths.MOVEABLE_1024},
+                    {StringLengths.NON_MOVEABLE}
+                });
+    }
+
+    @Parameterized.Parameter(0)
+    public StringLengths mStringLengths;
+
+    @Test
+    public void timeReplaceAllTrivialPatternNonExistent() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.replaceAll("fish", "0");
+        }
+    }
+
+    @Test
+    public void timeReplaceTrivialPatternAllRepeated() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.replaceAll("jklm", "0");
+        }
+    }
+
+    @Test
+    public void timeReplaceAllTrivialPatternSingleOccurrence() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.replaceAll("qrst", "0");
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringReplacePerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringReplacePerfTest.java
new file mode 100644
index 0000000..d2e657a
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/StringReplacePerfTest.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public class StringReplacePerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    enum StringLengths {
+        EMPTY(""),
+        L_16(makeString(16)),
+        L_64(makeString(64)),
+        L_256(makeString(256)),
+        L_512(makeString(512));
+
+        private final String mValue;
+
+        StringLengths(String s) {
+            this.mValue = s;
+        }
+    }
+
+    private static String makeString(int length) {
+        final String sequence8 = "abcdefghijklmnop";
+        final int numAppends = (length / 16) - 1;
+        StringBuilder stringBuilder = new StringBuilder(length);
+
+        // (n-1) occurrences of "abcdefghijklmnop"
+        for (int i = 0; i < numAppends; ++i) {
+            stringBuilder.append(sequence8);
+        }
+
+        // and one final occurrence of qrstuvwx.
+        stringBuilder.append("qrstuvwx");
+
+        return stringBuilder.toString();
+    }
+
+    @Parameters(name = "mStringLengths={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][] {
+                    {StringLengths.EMPTY},
+                    {StringLengths.L_16},
+                    {StringLengths.L_64},
+                    {StringLengths.L_256},
+                    {StringLengths.L_512}
+                });
+    }
+
+    @Parameterized.Parameter(0)
+    public StringLengths mStringLengths;
+
+    @Test
+    public void timeReplaceCharNonExistent() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.replace('z', '0');
+        }
+    }
+
+    @Test
+    public void timeReplaceCharRepeated() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.replace('a', '0');
+        }
+    }
+
+    @Test
+    public void timeReplaceSingleChar() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.replace('q', '0');
+        }
+    }
+
+    @Test
+    public void timeReplaceSequenceNonExistent() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.replace("fish", "0");
+        }
+    }
+
+    @Test
+    public void timeReplaceSequenceRepeated() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.replace("jklm", "0");
+        }
+    }
+
+    @Test
+    public void timeReplaceSingleSequence() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.replace("qrst", "0");
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringSplitPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringSplitPerfTest.java
new file mode 100644
index 0000000..2bb25ac
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/StringSplitPerfTest.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.regex.Pattern;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class StringSplitPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeStringSplitComma() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            "this,is,a,simple,example".split(",");
+        }
+    }
+
+    @Test
+    public void timeStringSplitLiteralDot() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            "this.is.a.simple.example".split("\\.");
+        }
+    }
+
+    @Test
+    public void timeStringSplitNewline() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            "this\nis\na\nsimple\nexample\n".split("\n");
+        }
+    }
+
+    @Test
+    public void timePatternSplitComma() {
+        Pattern p = Pattern.compile(",");
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            p.split("this,is,a,simple,example");
+        }
+    }
+
+    @Test
+    public void timePatternSplitLiteralDot() {
+        Pattern p = Pattern.compile("\\.");
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            p.split("this.is.a.simple.example");
+        }
+    }
+
+    @Test
+    public void timeStringSplitHard() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            "this,is,a,harder,example".split("[,]");
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringToBytesPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringToBytesPerfTest.java
new file mode 100644
index 0000000..1efc188
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/StringToBytesPerfTest.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public class StringToBytesPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    enum StringLengths {
+        EMPTY(""),
+        L_16(makeString(16)),
+        L_64(makeString(64)),
+        L_256(makeString(256)),
+        L_512(makeString(512)),
+        A_16(makeAsciiString(16)),
+        A_64(makeAsciiString(64)),
+        A_256(makeAsciiString(256)),
+        A_512(makeAsciiString(512));
+
+        private final String mValue;
+
+        StringLengths(String s) {
+            this.mValue = s;
+        }
+    }
+
+    @Parameters(name = "mStringLengths={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][] {
+                    {StringLengths.EMPTY},
+                    {StringLengths.L_16},
+                    {StringLengths.L_64},
+                    {StringLengths.L_256},
+                    {StringLengths.L_512},
+                    {StringLengths.A_16},
+                    {StringLengths.A_64},
+                    {StringLengths.A_256},
+                    {StringLengths.A_512}
+                });
+    }
+
+    @Parameterized.Parameter(0)
+    public StringLengths mStringLengths;
+
+    private static String makeString(int length) {
+        char[] chars = new char[length];
+        for (int i = 0; i < length; ++i) {
+            chars[i] = (char) i;
+        }
+        return new String(chars);
+    }
+
+    private static String makeAsciiString(int length) {
+        char[] chars = new char[length];
+        for (int i = 0; i < length; ++i) {
+            chars[i] = ((i & 0x7f) != 0) ? (char) (i & 0x7f) : '?';
+        }
+        return new String(chars);
+    }
+
+    @Test
+    public void timeGetBytesUtf8() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.getBytes(StandardCharsets.UTF_8);
+        }
+    }
+
+    @Test
+    public void timeGetBytesIso88591() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.getBytes(StandardCharsets.ISO_8859_1);
+        }
+    }
+
+    @Test
+    public void timeGetBytesAscii() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            mStringLengths.mValue.getBytes(StandardCharsets.US_ASCII);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/StringToRealPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/StringToRealPerfTest.java
new file mode 100644
index 0000000..b01948a
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/StringToRealPerfTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+@RunWith(Parameterized.class)
+@LargeTest
+public class StringToRealPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Parameters(name = "mString={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][] {
+                    {"NaN"},
+                    {"-1"},
+                    {"0"},
+                    {"1"},
+                    {"1.2"},
+                    {"-123.45"},
+                    {"-123.45e8"},
+                    {"-123.45e36"}
+                });
+    }
+
+    @Parameterized.Parameter(0)
+    public String mString;
+
+    @Test
+    public void timeFloat_parseFloat() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Float.parseFloat(mString);
+        }
+    }
+
+    @Test
+    public void timeDouble_parseDouble() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            Double.parseDouble(mString);
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/ThreadLocalPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/ThreadLocalPerfTest.java
new file mode 100644
index 0000000..f256555
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/ThreadLocalPerfTest.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class ThreadLocalPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    private static final ThreadLocal<char[]> BUFFER =
+            new ThreadLocal<char[]>() {
+                @Override
+                protected char[] initialValue() {
+                    return new char[20];
+                }
+            };
+
+    @Test
+    public void timeThreadLocal_get() {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            BUFFER.get();
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/TimeZonePerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/TimeZonePerfTest.java
new file mode 100644
index 0000000..8274512
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/TimeZonePerfTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.TimeZone;
+
+@RunWith(AndroidJUnit4.class)
+@LargeTest
+public class TimeZonePerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Test
+    public void timeTimeZone_getDefault() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            TimeZone.getDefault();
+        }
+    }
+
+    @Test
+    public void timeTimeZone_getTimeZoneUTC() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            TimeZone.getTimeZone("UTC");
+        }
+    }
+
+    @Test
+    public void timeTimeZone_getTimeZone_default() throws Exception {
+        String defaultId = TimeZone.getDefault().getID();
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            TimeZone.getTimeZone(defaultId);
+        }
+    }
+
+    // A time zone with relatively few transitions.
+    @Test
+    public void timeTimeZone_getTimeZone_America_Caracas() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            TimeZone.getTimeZone("America/Caracas");
+        }
+    }
+
+    // A time zone with a lot of transitions.
+    @Test
+    public void timeTimeZone_getTimeZone_America_Santiago() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            TimeZone.getTimeZone("America/Santiago");
+        }
+    }
+
+    @Test
+    public void timeTimeZone_getTimeZone_GMT_plus_10() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            TimeZone.getTimeZone("GMT+10");
+        }
+    }
+}
diff --git a/apct-tests/perftests/core/src/android/libcore/regression/XMLEntitiesPerfTest.java b/apct-tests/perftests/core/src/android/libcore/regression/XMLEntitiesPerfTest.java
new file mode 100644
index 0000000..2ea834d
--- /dev/null
+++ b/apct-tests/perftests/core/src/android/libcore/regression/XMLEntitiesPerfTest.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.libcore.regression;
+
+import android.perftests.utils.BenchmarkState;
+import android.perftests.utils.PerfStatusReporter;
+import android.test.suitebuilder.annotation.LargeTest;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
+import org.xml.sax.InputSource;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserFactory;
+
+import java.io.StringReader;
+import java.util.Arrays;
+import java.util.Collection;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+// http://code.google.com/p/android/issues/detail?id=18102
+@RunWith(Parameterized.class)
+@LargeTest
+public final class XMLEntitiesPerfTest {
+    @Rule public PerfStatusReporter mPerfStatusReporter = new PerfStatusReporter();
+
+    @Parameters(name = "mLength={0}, mEntityFraction={1}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(
+                new Object[][] {
+                    {10, 0},
+                    {10, 0.5f},
+                    {10, 1.0f},
+                    {100, 0},
+                    {100, 0.5f},
+                    {100, 1.0f},
+                    {1000, 0},
+                    {1000, 0.5f},
+                    {1000, 1.0f}
+                });
+    }
+
+    @Parameterized.Parameter(0)
+    public int mLength;
+
+    @Parameterized.Parameter(1)
+    public float mEntityFraction;
+
+    private XmlPullParserFactory mXmlPullParserFactory;
+    private DocumentBuilderFactory mDocumentBuilderFactory;
+
+    /** a string like {@code <doc>&amp;&amp;++</doc>}. */
+    private String mXml;
+
+    @Before
+    public void setUp() throws Exception {
+        mXmlPullParserFactory = XmlPullParserFactory.newInstance();
+        mDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
+
+        StringBuilder xmlBuilder = new StringBuilder();
+        xmlBuilder.append("<doc>");
+        for (int i = 0; i < (mLength * mEntityFraction); i++) {
+            xmlBuilder.append("&amp;");
+        }
+        while (xmlBuilder.length() < mLength) {
+            xmlBuilder.append("+");
+        }
+        xmlBuilder.append("</doc>");
+        mXml = xmlBuilder.toString();
+    }
+
+    @Test
+    public void timeXmlParser() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            XmlPullParser parser = mXmlPullParserFactory.newPullParser();
+            parser.setInput(new StringReader(mXml));
+            while (parser.next() != XmlPullParser.END_DOCUMENT) {
+                // Keep running
+            }
+        }
+    }
+
+    @Test
+    public void timeDocumentBuilder() throws Exception {
+        BenchmarkState state = mPerfStatusReporter.getBenchmarkState();
+        while (state.keepRunning()) {
+            DocumentBuilder documentBuilder = mDocumentBuilderFactory.newDocumentBuilder();
+            documentBuilder.parse(new InputSource(new StringReader(mXml)));
+        }
+    }
+}