Merge commit '405aeb8a97eb0a5194c2803dde3968e10e1e509e' into HEAD
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index 9987055..99b4232 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -84,9 +84,6 @@
 LOCAL_MODULE := core-libart
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
 LOCAL_REQUIRED_MODULES := tzdata
-# Should not be dex-preopted as it isn't really a Dalvik boot jar or a
-# regular java library, but part of the image for ART.
-LOCAL_DEX_PREOPT := false
 include $(BUILD_JAVA_LIBRARY)
 
 ifeq ($(LIBCORE_SKIP_TESTS),)
@@ -152,9 +149,6 @@
 LOCAL_MODULE := core-libart-hostdex
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
 LOCAL_REQUIRED_MODULES := tzdata-host
-# Should not be dex-preopted as it isn't really a Dalvik boot jar or a
-# regular java library, but part of the image for ART.
-LOCAL_DEX_PREOPT := false
 include $(BUILD_HOST_DALVIK_JAVA_LIBRARY)
 
 # Make the core-tests library.
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
index e3e1207..d531301 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/net/MulticastSocketTest.java
@@ -56,6 +56,7 @@
     private NetworkInterface loopbackInterface;
     private NetworkInterface ipv4NetworkInterface;
     private NetworkInterface ipv6NetworkInterface;
+    private boolean supportsMulticast;
 
     @Override
     protected void setUp() throws Exception {
@@ -69,6 +70,14 @@
         Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
         assertNotNull(interfaces);
 
+        // Determine if the device is marked to support multicast or not. If this propery is not
+        // set we assume the device has an interface capable of supporting multicast.
+        supportsMulticast = Boolean.valueOf(
+                System.getProperty("android.cts.device.multicast", "true"));
+        if (!supportsMulticast) {
+            return;
+        }
+
         while (interfaces.hasMoreElements()
                 && (ipv4NetworkInterface == null || ipv6NetworkInterface == null)) {
             NetworkInterface nextInterface = interfaces.nextElement();
@@ -90,6 +99,9 @@
     }
 
     public void test_Constructor() throws IOException {
+        if (!supportsMulticast) {
+            return;
+        }
         // Regression test for 497.
         MulticastSocket s = new MulticastSocket();
         // Regression test for Harmony-1162.
@@ -99,6 +111,9 @@
     }
 
     public void test_ConstructorI() throws IOException {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket orig = new MulticastSocket();
         int port = orig.getLocalPort();
         orig.close();
@@ -110,6 +125,9 @@
     }
 
     public void test_getInterface() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         // Validate that we get the expected response when one was not set.
         MulticastSocket mss = new MulticastSocket(0);
         // We expect an ANY address in this case.
@@ -134,6 +152,9 @@
     }
 
     public void test_getNetworkInterface() throws IOException {
+        if (!supportsMulticast) {
+            return;
+        }
         // Validate that we get the expected response when one was not set.
         MulticastSocket mss = new MulticastSocket(0);
         NetworkInterface theInterface = mss.getNetworkInterface();
@@ -176,6 +197,9 @@
     }
 
     public void test_getTimeToLive() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket mss = new MulticastSocket();
         mss.setTimeToLive(120);
         assertEquals("Returned incorrect 1st TTL", 120, mss.getTimeToLive());
@@ -185,6 +209,9 @@
     }
 
     public void test_getTTL() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket mss = new MulticastSocket();
         mss.setTTL((byte) 120);
         assertEquals("Returned incorrect TTL", 120, mss.getTTL());
@@ -192,10 +219,16 @@
     }
 
     public void test_joinGroupLjava_net_InetAddress_IPv4() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_joinGroupLjava_net_InetAddress(GOOD_IPv4);
     }
 
     public void test_joinGroupLjava_net_InetAddress_IPv6() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_joinGroupLjava_net_InetAddress(GOOD_IPv6);
     }
 
@@ -220,6 +253,9 @@
     }
 
     public void test_joinGroup_null_null() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket mss = new MulticastSocket(0);
         try {
             mss.joinGroup(null, null);
@@ -230,6 +266,9 @@
     }
 
     public void test_joinGroup_non_multicast_address_IPv4() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket mss = new MulticastSocket(0);
         try {
             mss.joinGroup(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0), null);
@@ -240,6 +279,9 @@
     }
 
     public void test_joinGroup_non_multicast_address_IPv6() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket mss = new MulticastSocket(0);
         try {
             mss.joinGroup(new InetSocketAddress(InetAddress.getByName("::1"), 0), null);
@@ -251,12 +293,18 @@
 
     public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
             throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
                 ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
     }
 
     public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
             throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
                 ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
     }
@@ -310,6 +358,9 @@
     }
 
     public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         // Check that we can join on specific interfaces and that we only receive if data is
         // received on that interface. This test is only really useful on devices with multiple
         // non-loopback interfaces.
@@ -378,12 +429,18 @@
 
     public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv4()
             throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
                 ipv4NetworkInterface, GOOD_IPv4);
     }
 
     public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins_IPv6()
             throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface_multiple_joins(
                 ipv6NetworkInterface, GOOD_IPv6);
     }
@@ -405,10 +462,16 @@
     }
 
     public void test_leaveGroupLjava_net_InetAddress_IPv4() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_leaveGroupLjava_net_InetAddress(GOOD_IPv4);
     }
 
     public void test_leaveGroupLjava_net_InetAddress_IPv6() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_leaveGroupLjava_net_InetAddress(GOOD_IPv6);
     }
 
@@ -428,6 +491,9 @@
     }
 
     public void test_leaveGroup_null_null() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket mss = new MulticastSocket(0);
         try {
             mss.leaveGroup(null, null);
@@ -438,6 +504,9 @@
     }
 
     public void test_leaveGroup_non_multicast_address_IPv4() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket mss = new MulticastSocket(0);
         try {
             mss.leaveGroup(new InetSocketAddress(InetAddress.getByName("127.0.0.1"), 0), null);
@@ -448,6 +517,9 @@
     }
 
     public void test_leaveGroup_non_multicast_address_IPv6() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket mss = new MulticastSocket(0);
         try {
             mss.leaveGroup(new InetSocketAddress(InetAddress.getByName("::1"), 0), null);
@@ -459,12 +531,18 @@
 
     public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv4()
             throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
                 ipv4NetworkInterface, GOOD_IPv4, BAD_IPv4);
     }
 
     public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface_IPv6()
             throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface(
                 ipv6NetworkInterface, GOOD_IPv6, BAD_IPv6);
     }
@@ -505,10 +583,16 @@
     }
 
     public void test_sendLjava_net_DatagramPacketB_IPv4() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_sendLjava_net_DatagramPacketB(GOOD_IPv4);
     }
 
     public void test_sendLjava_net_DatagramPacketB_IPv6() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_sendLjava_net_DatagramPacketB(GOOD_IPv6);
     }
 
@@ -531,6 +615,9 @@
     }
 
     public void test_setInterfaceLjava_net_InetAddress() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket mss = new MulticastSocket();
         mss.setInterface(InetAddress.getLocalHost());
         InetAddress theInterface = mss.getInterface();
@@ -549,10 +636,16 @@
     }
 
     public void test_setInterface_unbound_address_IPv4() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_setInterface_unbound_address(GOOD_IPv4);
     }
 
     public void test_setInterface_unbound_address_IPv6() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_setInterface_unbound_address(GOOD_IPv6);
     }
 
@@ -568,6 +661,9 @@
     }
 
     public void test_setNetworkInterfaceLjava_net_NetworkInterface_null() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         // Validate that null interface is handled ok.
         MulticastSocket mss = new MulticastSocket();
         try {
@@ -579,6 +675,9 @@
     }
 
     public void test_setNetworkInterfaceLjava_net_NetworkInterface_round_trip() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         // Validate that we can get and set the interface.
         MulticastSocket mss = new MulticastSocket();
         mss.setNetworkInterface(ipv4NetworkInterface);
@@ -588,10 +687,16 @@
     }
 
     public void test_setNetworkInterfaceLjava_net_NetworkInterface_IPv4() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv4);
     }
 
     public void test_setNetworkInterfaceLjava_net_NetworkInterface_IPv6() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_setNetworkInterfaceLjava_net_NetworkInterface(GOOD_IPv6);
     }
 
@@ -630,6 +735,9 @@
     }
 
     public void test_setTimeToLiveI() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket mss = new MulticastSocket();
         mss.setTimeToLive(120);
         assertEquals("Returned incorrect 1st TTL", 120, mss.getTimeToLive());
@@ -639,6 +747,9 @@
     }
 
     public void test_setTTLB() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket mss = new MulticastSocket();
         mss.setTTL((byte) 120);
         assertEquals("Failed to set TTL", 120, mss.getTTL());
@@ -646,6 +757,9 @@
     }
 
     public void test_ConstructorLjava_net_SocketAddress() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket ms = new MulticastSocket((SocketAddress) null);
         assertTrue("should not be bound", !ms.isBound() && !ms.isClosed() && !ms.isConnected());
         ms.bind(null);
@@ -677,6 +791,9 @@
     }
 
     public void test_getLoopbackMode() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket ms = new MulticastSocket(null);
         assertTrue("should not be bound", !ms.isBound() && !ms.isClosed() && !ms.isConnected());
         ms.getLoopbackMode();
@@ -686,6 +803,9 @@
     }
 
     public void test_setLoopbackModeZ() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         MulticastSocket ms = new MulticastSocket();
         ms.setLoopbackMode(true);
         assertTrue("loopback should be true", ms.getLoopbackMode());
@@ -696,10 +816,16 @@
     }
 
     public void test_setLoopbackModeSendReceive_IPv4() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_setLoopbackModeSendReceive(GOOD_IPv4);
     }
 
     public void test_setLoopbackModeSendReceive_IPv6() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         test_setLoopbackModeSendReceive(GOOD_IPv6);
     }
 
@@ -726,6 +852,9 @@
     }
 
     public void test_setReuseAddressZ() throws Exception {
+        if (!supportsMulticast) {
+            return;
+        }
         // Test case were we to set ReuseAddress to false.
         MulticastSocket theSocket1 = new MulticastSocket(null);
         theSocket1.setReuseAddress(false);
@@ -797,5 +926,4 @@
     private static String extractMessage(DatagramPacket rdp) {
         return new String(rdp.getData(), 0, rdp.getLength());
     }
-
 }
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java
index f55829d..0bc8920 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/util/jar/JarFileTest.java
@@ -37,7 +37,14 @@
 import java.security.cert.X509Certificate;
 import java.util.Arrays;
 import java.util.Enumeration;
+import java.util.List;
 import java.util.Vector;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 import java.util.jar.Attributes;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
@@ -97,6 +104,27 @@
 
     private final String emptyEntryJar = "EmptyEntries_signed.jar";
 
+    /*
+     * /usr/bin/openssl genrsa 2048 > root1.pem
+     * /usr/bin/openssl req -new -key root1.pem -out root1.csr -subj '/CN=root1'
+     * /usr/bin/openssl x509 -req -days 3650 -in root1.csr -signkey root1.pem -out root1.crt
+     * /usr/bin/openssl genrsa 2048 > root2.pem
+     * /usr/bin/openssl req -new -key root2.pem -out root2.csr -subj '/CN=root2'
+     * echo 4000 > root1.srl
+     * echo 8000 > root2.srl
+     * /usr/bin/openssl x509 -req -days 3650 -in root2.csr -CA root1.crt -CAkey root1.pem -out root2.crt
+     * /usr/bin/openssl x509 -req -days 3650 -in root1.csr -CA root2.crt -CAkey root2.pem -out root1.crt
+     * /usr/bin/openssl genrsa 2048 > signer.pem
+     * /usr/bin/openssl req -new -key signer.pem -out signer.csr -subj '/CN=signer'
+     * /usr/bin/openssl x509 -req -days 3650 -in signer.csr -CA root1.crt -CAkey root1.pem -out signer.crt
+     * /usr/bin/openssl pkcs12 -inkey signer.pem -in signer.crt -export -out signer.p12 -name signer -passout pass:certloop
+     * keytool -importkeystore -srckeystore signer.p12 -srcstoretype PKCS12 -destkeystore signer.jks -srcstorepass certloop -deststorepass certloop
+     * cat signer.crt root1.crt root2.crt > chain.crt
+     * zip -d hyts_certLoop.jar 'META-INF/*'
+     * jarsigner -keystore signer.jks -certchain chain.crt -storepass certloop hyts_certLoop.jar signer
+     */
+    private final String certLoopJar = "hyts_certLoop.jar";
+
     private final String emptyEntry1 = "subfolder/internalSubset01.js";
 
     private final String emptyEntry2 = "svgtest.js";
@@ -616,6 +644,9 @@
 
         // JAR with a signature that has PKCS#7 Authenticated Attributes
         checkSignedJar(authAttrsJar);
+
+        // JAR with certificates that loop
+        checkSignedJar(certLoopJar, 3);
     }
 
     /**
@@ -628,29 +659,52 @@
         checkSignedJar(jarName9);
     }
 
+    /**
+     * Checks that a JAR is signed correctly with a signature length of 1.
+     */
     private void checkSignedJar(String jarName) throws Exception {
+        checkSignedJar(jarName, 1);
+    }
+
+    /**
+     * Checks that a JAR is signed correctly with a signature length of sigLength.
+     */
+    private void checkSignedJar(String jarName, final int sigLength) throws Exception {
         Support_Resources.copyFile(resources, null, jarName);
 
-        File file = new File(resources, jarName);
-        boolean foundCerts = false;
+        final File file = new File(resources, jarName);
 
-        JarFile jarFile = new JarFile(file, true);
-        try {
-
-            Enumeration<JarEntry> e = jarFile.entries();
-            while (e.hasMoreElements()) {
-                JarEntry entry = e.nextElement();
-                InputStream is = jarFile.getInputStream(entry);
-                is.skip(100000);
-                is.close();
-                Certificate[] certs = entry.getCertificates();
-                if (certs != null && certs.length > 0) {
-                    foundCerts = true;
-                    break;
+        ExecutorService executor = Executors.newSingleThreadExecutor();
+        Future<Boolean> future = executor.submit(new Callable<Boolean>() {
+            @Override
+            public Boolean call() throws Exception {
+                JarFile jarFile = new JarFile(file, true);
+                try {
+                    Enumeration<JarEntry> e = jarFile.entries();
+                    while (e.hasMoreElements()) {
+                        JarEntry entry = e.nextElement();
+                        InputStream is = jarFile.getInputStream(entry);
+                        is.skip(100000);
+                        is.close();
+                        Certificate[] certs = entry.getCertificates();
+                        if (certs != null && certs.length > 0) {
+                            assertEquals(sigLength, certs.length);
+                            return true;
+                        }
+                    }
+                    return false;
+                } finally {
+                    jarFile.close();
                 }
             }
-        } finally {
-            jarFile.close();
+        });
+        executor.shutdown();
+        final boolean foundCerts;
+        try {
+            foundCerts = future.get(10, TimeUnit.SECONDS);
+        } catch (TimeoutException e) {
+            fail("Could not finish building chain; possibly confused by loops");
+            return; // Not actually reached.
         }
 
         assertTrue(
diff --git a/luni/src/main/files/cacerts/04f60c28.0 b/luni/src/main/files/cacerts/04f60c28.0
new file mode 100644
index 0000000..dec2f4e
--- /dev/null
+++ b/luni/src/main/files/cacerts/04f60c28.0
@@ -0,0 +1,54 @@
+-----BEGIN CERTIFICATE-----
+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL
+MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl
+eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT
+JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
+Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg
+VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo
+I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng
+o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G
+A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB
+zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW
+RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            5c:8b:99:c5:5a:94:c5:d2:71:56:de:cd:89:80:cc:26
+    Signature Algorithm: ecdsa-with-SHA384
+        Issuer: C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust ECC Certification Authority
+        Validity
+            Not Before: Feb  1 00:00:00 2010 GMT
+            Not After : Jan 18 23:59:59 2038 GMT
+        Subject: C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust ECC Certification Authority
+        Subject Public Key Info:
+            Public Key Algorithm: id-ecPublicKey
+                Public-Key: (384 bit)
+                pub: 
+                    04:1a:ac:54:5a:a9:f9:68:23:e7:7a:d5:24:6f:53:
+                    c6:5a:d8:4b:ab:c6:d5:b6:d1:e6:73:71:ae:dd:9c:
+                    d6:0c:61:fd:db:a0:89:03:b8:05:14:ec:57:ce:ee:
+                    5d:3f:e2:21:b3:ce:f7:d4:8a:79:e0:a3:83:7e:2d:
+                    97:d0:61:c4:f1:99:dc:25:91:63:ab:7f:30:a3:b4:
+                    70:e2:c7:a1:33:9c:f3:bf:2e:5c:53:b1:5f:b3:7d:
+                    32:7f:8a:34:e3:79:79
+                ASN1 OID: secp384r1
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                3A:E1:09:86:D4:CF:19:C2:96:76:74:49:76:DC:E0:35:C6:63:63:9A
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+    Signature Algorithm: ecdsa-with-SHA384
+         30:65:02:30:36:67:a1:16:08:dc:e4:97:00:41:1d:4e:be:e1:
+         63:01:cf:3b:aa:42:11:64:a0:9d:94:39:02:11:79:5c:7b:1d:
+         fa:64:b9:ee:16:42:b3:bf:8a:c2:09:c4:ec:e4:b1:4d:02:31:
+         00:e9:2a:61:47:8c:52:4a:4b:4e:18:70:f6:d6:44:d6:6e:f5:
+         83:ba:6d:58:bd:24:d9:56:48:ea:ef:c4:a2:46:81:88:6a:3a:
+         46:d1:a9:9b:4d:c9:61:da:d1:5d:57:6a:18
+SHA1 Fingerprint=D1:CB:CA:5D:B2:D5:2A:7F:69:3B:67:4D:E5:F0:5A:1D:0C:95:7D:F0
diff --git a/luni/src/main/files/cacerts/0d69c7e1.0 b/luni/src/main/files/cacerts/0d69c7e1.0
new file mode 100644
index 0000000..84c387e
--- /dev/null
+++ b/luni/src/main/files/cacerts/0d69c7e1.0
@@ -0,0 +1,47 @@
+-----BEGIN CERTIFICATE-----
+MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ
+FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F
+uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX
+kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs
+ewv4n4Q=
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            2a:38:a4:1c:96:0a:04:de:42:b2:28:a5:0b:e8:34:98:02
+    Signature Algorithm: ecdsa-with-SHA256
+        Issuer: OU=GlobalSign ECC Root CA - R4, O=GlobalSign, CN=GlobalSign
+        Validity
+            Not Before: Nov 13 00:00:00 2012 GMT
+            Not After : Jan 19 03:14:07 2038 GMT
+        Subject: OU=GlobalSign ECC Root CA - R4, O=GlobalSign, CN=GlobalSign
+        Subject Public Key Info:
+            Public Key Algorithm: id-ecPublicKey
+                Public-Key: (256 bit)
+                pub: 
+                    04:b8:c6:79:d3:8f:6c:25:0e:9f:2e:39:19:1c:03:
+                    a4:ae:9a:e5:39:07:09:16:ca:63:b1:b9:86:f8:8a:
+                    57:c1:57:ce:42:fa:73:a1:f7:65:42:ff:1e:c1:00:
+                    b2:6e:73:0e:ff:c7:21:e5:18:a4:aa:d9:71:3f:a8:
+                    d4:b9:ce:8c:1d
+                ASN1 OID: prime256v1
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                54:B0:7B:AD:45:B8:E2:40:7F:FB:0A:6E:FB:BE:33:C9:3C:A3:84:D5
+    Signature Algorithm: ecdsa-with-SHA256
+         30:45:02:21:00:dc:92:a1:a0:13:a6:cf:03:b0:e6:c4:21:97:
+         90:fa:14:57:2d:03:ec:ee:3c:d3:6e:ca:a8:6c:76:bc:a2:de:
+         bb:02:20:27:a8:85:27:35:9b:56:c6:a3:f2:47:d2:b7:6e:1b:
+         02:00:17:aa:67:a6:15:91:de:fa:94:ec:7b:0b:f8:9f:84
+SHA1 Fingerprint=69:69:56:2E:40:80:F4:24:A1:E7:19:9F:14:BA:F3:EE:58:AB:6A:BB
diff --git a/luni/src/main/files/cacerts/2add47b6.0 b/luni/src/main/files/cacerts/2add47b6.0
new file mode 100644
index 0000000..aa88539
--- /dev/null
+++ b/luni/src/main/files/cacerts/2add47b6.0
@@ -0,0 +1,52 @@
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc
+8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke
+hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI
+KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg
+515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO
+xwy8p2Fp8fc74SrL+SvzZpA3
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            60:59:49:e0:26:2e:bb:55:f9:0a:77:8a:71:f9:4a:d8:6c
+    Signature Algorithm: ecdsa-with-SHA384
+        Issuer: OU=GlobalSign ECC Root CA - R5, O=GlobalSign, CN=GlobalSign
+        Validity
+            Not Before: Nov 13 00:00:00 2012 GMT
+            Not After : Jan 19 03:14:07 2038 GMT
+        Subject: OU=GlobalSign ECC Root CA - R5, O=GlobalSign, CN=GlobalSign
+        Subject Public Key Info:
+            Public Key Algorithm: id-ecPublicKey
+                Public-Key: (384 bit)
+                pub: 
+                    04:47:45:0e:96:fb:7d:5d:bf:e9:39:d1:21:f8:9f:
+                    0b:b6:d5:7b:1e:92:3a:48:59:1c:f0:62:31:2d:c0:
+                    7a:28:fe:1a:a7:5c:b3:b6:cc:97:e7:45:d4:58:fa:
+                    d1:77:6d:43:a2:c0:87:65:34:0a:1f:7a:dd:eb:3c:
+                    33:a1:c5:9d:4d:a4:6f:41:95:38:7f:c9:1e:84:eb:
+                    d1:9e:49:92:87:94:87:0c:3a:85:4a:66:9f:9d:59:
+                    93:4d:97:61:06:86:4a
+                ASN1 OID: secp384r1
+        X509v3 extensions:
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+            X509v3 Subject Key Identifier: 
+                3D:E6:29:48:9B:EA:07:CA:21:44:4A:26:DE:6E:DE:D2:83:D0:9F:59
+    Signature Algorithm: ecdsa-with-SHA384
+         30:65:02:31:00:e5:69:12:c9:6e:db:c6:31:ba:09:41:e1:97:
+         f8:fb:fd:9a:e2:7d:12:c9:ed:7c:64:d3:cb:05:25:8b:56:d9:
+         a0:e7:5e:5d:4e:0b:83:9c:5b:76:29:a0:09:26:21:6a:62:02:
+         30:71:d2:b5:8f:5c:ea:3b:e1:78:09:85:a8:75:92:3b:c8:5c:
+         fd:48:ef:0d:74:22:a8:08:e2:6e:c5:49:ce:c7:0c:bc:a7:61:
+         69:f1:f7:3b:e1:2a:cb:f9:2b:f3:66:90:37
+SHA1 Fingerprint=1F:24:C6:30:CD:A4:18:EF:20:69:FF:AD:4F:DD:5F:46:3A:1B:69:AA
diff --git a/luni/src/main/files/cacerts/35105088.0 b/luni/src/main/files/cacerts/35105088.0
new file mode 100644
index 0000000..3728c3b
--- /dev/null
+++ b/luni/src/main/files/cacerts/35105088.0
@@ -0,0 +1,123 @@
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
+MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
+BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
+3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
+tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
+Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
+VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
+79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
+c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
+Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
+c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
+UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
+Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
+Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
+VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
+ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
+8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
+iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
+Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
+XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
+qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
+VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
+L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
+jjxDah2nGN59PRbxYvnKkKj9
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            01:fd:6d:30:fc:a3:ca:51:a8:1b:bc:64:0e:35:03:2d
+    Signature Algorithm: sha384WithRSAEncryption
+        Issuer: C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
+        Validity
+            Not Before: Feb  1 00:00:00 2010 GMT
+            Not After : Jan 18 23:59:59 2038 GMT
+        Subject: C=US, ST=New Jersey, L=Jersey City, O=The USERTRUST Network, CN=USERTrust RSA Certification Authority
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (4096 bit)
+                Modulus:
+                    00:80:12:65:17:36:0e:c3:db:08:b3:d0:ac:57:0d:
+                    76:ed:cd:27:d3:4c:ad:50:83:61:e2:aa:20:4d:09:
+                    2d:64:09:dc:ce:89:9f:cc:3d:a9:ec:f6:cf:c1:dc:
+                    f1:d3:b1:d6:7b:37:28:11:2b:47:da:39:c6:bc:3a:
+                    19:b4:5f:a6:bd:7d:9d:a3:63:42:b6:76:f2:a9:3b:
+                    2b:91:f8:e2:6f:d0:ec:16:20:90:09:3e:e2:e8:74:
+                    c9:18:b4:91:d4:62:64:db:7f:a3:06:f1:88:18:6a:
+                    90:22:3c:bc:fe:13:f0:87:14:7b:f6:e4:1f:8e:d4:
+                    e4:51:c6:11:67:46:08:51:cb:86:14:54:3f:bc:33:
+                    fe:7e:6c:9c:ff:16:9d:18:bd:51:8e:35:a6:a7:66:
+                    c8:72:67:db:21:66:b1:d4:9b:78:03:c0:50:3a:e8:
+                    cc:f0:dc:bc:9e:4c:fe:af:05:96:35:1f:57:5a:b7:
+                    ff:ce:f9:3d:b7:2c:b6:f6:54:dd:c8:e7:12:3a:4d:
+                    ae:4c:8a:b7:5c:9a:b4:b7:20:3d:ca:7f:22:34:ae:
+                    7e:3b:68:66:01:44:e7:01:4e:46:53:9b:33:60:f7:
+                    94:be:53:37:90:73:43:f3:32:c3:53:ef:db:aa:fe:
+                    74:4e:69:c7:6b:8c:60:93:de:c4:c7:0c:df:e1:32:
+                    ae:cc:93:3b:51:78:95:67:8b:ee:3d:56:fe:0c:d0:
+                    69:0f:1b:0f:f3:25:26:6b:33:6d:f7:6e:47:fa:73:
+                    43:e5:7e:0e:a5:66:b1:29:7c:32:84:63:55:89:c4:
+                    0d:c1:93:54:30:19:13:ac:d3:7d:37:a7:eb:5d:3a:
+                    6c:35:5c:db:41:d7:12:da:a9:49:0b:df:d8:80:8a:
+                    09:93:62:8e:b5:66:cf:25:88:cd:84:b8:b1:3f:a4:
+                    39:0f:d9:02:9e:eb:12:4c:95:7c:f3:6b:05:a9:5e:
+                    16:83:cc:b8:67:e2:e8:13:9d:cc:5b:82:d3:4c:b3:
+                    ed:5b:ff:de:e5:73:ac:23:3b:2d:00:bf:35:55:74:
+                    09:49:d8:49:58:1a:7f:92:36:e6:51:92:0e:f3:26:
+                    7d:1c:4d:17:bc:c9:ec:43:26:d0:bf:41:5f:40:a9:
+                    44:44:f4:99:e7:57:87:9e:50:1f:57:54:a8:3e:fd:
+                    74:63:2f:b1:50:65:09:e6:58:42:2e:43:1a:4c:b4:
+                    f0:25:47:59:fa:04:1e:93:d4:26:46:4a:50:81:b2:
+                    de:be:78:b7:fc:67:15:e1:c9:57:84:1e:0f:63:d6:
+                    e9:62:ba:d6:5f:55:2e:ea:5c:c6:28:08:04:25:39:
+                    b8:0e:2b:a9:f2:4c:97:1c:07:3f:0d:52:f5:ed:ef:
+                    2f:82:0f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                53:79:BF:5A:AA:2B:4A:CF:54:80:E1:D8:9B:C0:9D:F2:B2:03:66:CB
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+    Signature Algorithm: sha384WithRSAEncryption
+         5c:d4:7c:0d:cf:f7:01:7d:41:99:65:0c:73:c5:52:9f:cb:f8:
+         cf:99:06:7f:1b:da:43:15:9f:9e:02:55:57:96:14:f1:52:3c:
+         27:87:94:28:ed:1f:3a:01:37:a2:76:fc:53:50:c0:84:9b:c6:
+         6b:4e:ba:8c:21:4f:a2:8e:55:62:91:f3:69:15:d8:bc:88:e3:
+         c4:aa:0b:fd:ef:a8:e9:4b:55:2a:06:20:6d:55:78:29:19:ee:
+         5f:30:5c:4b:24:11:55:ff:24:9a:6e:5e:2a:2b:ee:0b:4d:9f:
+         7f:f7:01:38:94:14:95:43:07:09:fb:60:a9:ee:1c:ab:12:8c:
+         a0:9a:5e:a7:98:6a:59:6d:8b:3f:08:fb:c8:d1:45:af:18:15:
+         64:90:12:0f:73:28:2e:c5:e2:24:4e:fc:58:ec:f0:f4:45:fe:
+         22:b3:eb:2f:8e:d2:d9:45:61:05:c1:97:6f:a8:76:72:8f:8b:
+         8c:36:af:bf:0d:05:ce:71:8d:e6:a6:6f:1f:6c:a6:71:62:c5:
+         d8:d0:83:72:0c:f1:67:11:89:0c:9c:13:4c:72:34:df:bc:d5:
+         71:df:aa:71:dd:e1:b9:6c:8c:3c:12:5d:65:da:bd:57:12:b6:
+         43:6b:ff:e5:de:4d:66:11:51:cf:99:ae:ec:17:b6:e8:71:91:
+         8c:de:49:fe:dd:35:71:a2:15:27:94:1c:cf:61:e3:26:bb:6f:
+         a3:67:25:21:5d:e6:dd:1d:0b:2e:68:1b:3b:82:af:ec:83:67:
+         85:d4:98:51:74:b1:b9:99:80:89:ff:7f:78:19:5c:79:4a:60:
+         2e:92:40:ae:4c:37:2a:2c:c9:c7:62:c8:0e:5d:f7:36:5b:ca:
+         e0:25:25:01:b4:dd:1a:07:9c:77:00:3f:d0:dc:d5:ec:3d:d4:
+         fa:bb:3f:cc:85:d6:6f:7f:a9:2d:df:b9:02:f7:f5:97:9a:b5:
+         35:da:c3:67:b0:87:4a:a9:28:9e:23:8e:ff:5c:27:6b:e1:b0:
+         4f:f3:07:ee:00:2e:d4:59:87:cb:52:41:95:ea:f4:47:d7:ee:
+         64:41:55:7c:8d:59:02:95:dd:62:9d:c2:b9:ee:5a:28:74:84:
+         a5:9b:b7:90:c7:0c:07:df:f5:89:36:74:32:d6:28:c1:b0:b0:
+         0b:e0:9c:4c:c3:1c:d6:fc:e3:69:b5:47:46:81:2f:a2:82:ab:
+         d3:63:44:70:c4:8d:ff:2d:33:ba:ad:8f:7b:b5:70:88:ae:3e:
+         19:cf:40:28:d8:fc:c8:90:bb:5d:99:22:f5:52:e6:58:c5:1f:
+         88:31:43:ee:88:1d:d7:c6:8e:3c:43:6a:1d:a7:18:de:7d:3d:
+         16:f1:62:f9:ca:90:a8:fd
+SHA1 Fingerprint=2B:8F:1B:57:33:0D:BB:A2:D0:7A:6C:51:F7:0E:E9:0D:DA:B9:AD:8E
diff --git a/luni/src/main/files/cacerts/d4c339cb.0 b/luni/src/main/files/cacerts/d4c339cb.0
new file mode 100644
index 0000000..3f5e924
--- /dev/null
+++ b/luni/src/main/files/cacerts/d4c339cb.0
@@ -0,0 +1,123 @@
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
+6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
+pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
+9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
+/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
+Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
+qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
+SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
+u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
+Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
+crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
+wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
+4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
+2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
+FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
+CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
+boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
+jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
+S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
+QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
+0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
+NVOFBkpdn627G190
+-----END CERTIFICATE-----
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number:
+            4c:aa:f9:ca:db:63:6f:e0:1f:f7:4e:d8:5b:03:86:9d
+    Signature Algorithm: sha384WithRSAEncryption
+        Issuer: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Certification Authority
+        Validity
+            Not Before: Jan 19 00:00:00 2010 GMT
+            Not After : Jan 18 23:59:59 2038 GMT
+        Subject: C=GB, ST=Greater Manchester, L=Salford, O=COMODO CA Limited, CN=COMODO RSA Certification Authority
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                Public-Key: (4096 bit)
+                Modulus:
+                    00:91:e8:54:92:d2:0a:56:b1:ac:0d:24:dd:c5:cf:
+                    44:67:74:99:2b:37:a3:7d:23:70:00:71:bc:53:df:
+                    c4:fa:2a:12:8f:4b:7f:10:56:bd:9f:70:72:b7:61:
+                    7f:c9:4b:0f:17:a7:3d:e3:b0:04:61:ee:ff:11:97:
+                    c7:f4:86:3e:0a:fa:3e:5c:f9:93:e6:34:7a:d9:14:
+                    6b:e7:9c:b3:85:a0:82:7a:76:af:71:90:d7:ec:fd:
+                    0d:fa:9c:6c:fa:df:b0:82:f4:14:7e:f9:be:c4:a6:
+                    2f:4f:7f:99:7f:b5:fc:67:43:72:bd:0c:00:d6:89:
+                    eb:6b:2c:d3:ed:8f:98:1c:14:ab:7e:e5:e3:6e:fc:
+                    d8:a8:e4:92:24:da:43:6b:62:b8:55:fd:ea:c1:bc:
+                    6c:b6:8b:f3:0e:8d:9a:e4:9b:6c:69:99:f8:78:48:
+                    30:45:d5:ad:e1:0d:3c:45:60:fc:32:96:51:27:bc:
+                    67:c3:ca:2e:b6:6b:ea:46:c7:c7:20:a0:b1:1f:65:
+                    de:48:08:ba:a4:4e:a9:f2:83:46:37:84:eb:e8:cc:
+                    81:48:43:67:4e:72:2a:9b:5c:bd:4c:1b:28:8a:5c:
+                    22:7b:b4:ab:98:d9:ee:e0:51:83:c3:09:46:4e:6d:
+                    3e:99:fa:95:17:da:7c:33:57:41:3c:8d:51:ed:0b:
+                    b6:5c:af:2c:63:1a:df:57:c8:3f:bc:e9:5d:c4:9b:
+                    af:45:99:e2:a3:5a:24:b4:ba:a9:56:3d:cf:6f:aa:
+                    ff:49:58:be:f0:a8:ff:f4:b8:ad:e9:37:fb:ba:b8:
+                    f4:0b:3a:f9:e8:43:42:1e:89:d8:84:cb:13:f1:d9:
+                    bb:e1:89:60:b8:8c:28:56:ac:14:1d:9c:0a:e7:71:
+                    eb:cf:0e:dd:3d:a9:96:a1:48:bd:3c:f7:af:b5:0d:
+                    22:4c:c0:11:81:ec:56:3b:f6:d3:a2:e2:5b:b7:b2:
+                    04:22:52:95:80:93:69:e8:8e:4c:65:f1:91:03:2d:
+                    70:74:02:ea:8b:67:15:29:69:52:02:bb:d7:df:50:
+                    6a:55:46:bf:a0:a3:28:61:7f:70:d0:c3:a2:aa:2c:
+                    21:aa:47:ce:28:9c:06:45:76:bf:82:18:27:b4:d5:
+                    ae:b4:cb:50:e6:6b:f4:4c:86:71:30:e9:a6:df:16:
+                    86:e0:d8:ff:40:dd:fb:d0:42:88:7f:a3:33:3a:2e:
+                    5c:1e:41:11:81:63:ce:18:71:6b:2b:ec:a6:8a:b7:
+                    31:5c:3a:6a:47:e0:c3:79:59:d6:20:1a:af:f2:6a:
+                    98:aa:72:bc:57:4a:d2:4b:9d:bb:10:fc:b0:4c:41:
+                    e5:ed:1d:3d:5e:28:9d:9c:cc:bf:b3:51:da:a7:47:
+                    e5:84:53
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Subject Key Identifier: 
+                BB:AF:7E:02:3D:FA:A6:F1:3C:84:8E:AD:EE:38:98:EC:D9:32:32:D4
+            X509v3 Key Usage: critical
+                Certificate Sign, CRL Sign
+            X509v3 Basic Constraints: critical
+                CA:TRUE
+    Signature Algorithm: sha384WithRSAEncryption
+         0a:f1:d5:46:84:b7:ae:51:bb:6c:b2:4d:41:14:00:93:4c:9c:
+         cb:e5:c0:54:cf:a0:25:8e:02:f9:fd:b0:a2:0d:f5:20:98:3c:
+         13:2d:ac:56:a2:b0:d6:7e:11:92:e9:2e:ba:9e:2e:9a:72:b1:
+         bd:19:44:6c:61:35:a2:9a:b4:16:12:69:5a:8c:e1:d7:3e:a4:
+         1a:e8:2f:03:f4:ae:61:1d:10:1b:2a:a4:8b:7a:c5:fe:05:a6:
+         e1:c0:d6:c8:fe:9e:ae:8f:2b:ba:3d:99:f8:d8:73:09:58:46:
+         6e:a6:9c:f4:d7:27:d3:95:da:37:83:72:1c:d3:73:e0:a2:47:
+         99:03:38:5d:d5:49:79:00:29:1c:c7:ec:9b:20:1c:07:24:69:
+         57:78:b2:39:fc:3a:84:a0:b5:9c:7c:8d:bf:2e:93:62:27:b7:
+         39:da:17:18:ae:bd:3c:09:68:ff:84:9b:3c:d5:d6:0b:03:e3:
+         57:9e:14:f7:d1:eb:4f:c8:bd:87:23:b7:b6:49:43:79:85:5c:
+         ba:eb:92:0b:a1:c6:e8:68:a8:4c:16:b1:1a:99:0a:e8:53:2c:
+         92:bb:a1:09:18:75:0c:65:a8:7b:cb:23:b7:1a:c2:28:85:c3:
+         1b:ff:d0:2b:62:ef:a4:7b:09:91:98:67:8c:14:01:cd:68:06:
+         6a:63:21:75:03:80:88:8a:6e:81:c6:85:f2:a9:a4:2d:e7:f4:
+         a5:24:10:47:83:ca:cd:f4:8d:79:58:b1:06:9b:e7:1a:2a:d9:
+         9d:01:d7:94:7d:ed:03:4a:ca:f0:db:e8:a9:01:3e:f5:56:99:
+         c9:1e:8e:49:3d:bb:e5:09:b9:e0:4f:49:92:3d:16:82:40:cc:
+         cc:59:c6:e6:3a:ed:12:2e:69:3c:6c:95:b1:fd:aa:1d:7b:7f:
+         86:be:1e:0e:32:46:fb:fb:13:8f:75:7f:4c:8b:4b:46:63:fe:
+         00:34:40:70:c1:c3:b9:a1:dd:a6:70:e2:04:b3:41:bc:e9:80:
+         91:ea:64:9c:7a:e1:22:03:a9:9c:6e:6f:0e:65:4f:6c:87:87:
+         5e:f3:6e:a0:f9:75:a5:9b:40:e8:53:b2:27:9d:4a:b9:c0:77:
+         21:8d:ff:87:f2:de:bc:8c:ef:17:df:b7:49:0b:d1:f2:6e:30:
+         0b:1a:0e:4e:76:ed:11:fc:f5:e9:56:b2:7d:bf:c7:6d:0a:93:
+         8c:a5:d0:c0:b6:1d:be:3a:4e:94:a2:d7:6e:6c:0b:c2:8a:7c:
+         fa:20:f3:c4:e4:e5:cd:0d:a8:cb:91:92:b1:7c:85:ec:b5:14:
+         69:66:0e:82:e7:cd:ce:c8:2d:a6:51:7f:21:c1:35:53:85:06:
+         4a:5d:9f:ad:bb:1b:5f:74
+SHA1 Fingerprint=AF:E5:D2:44:A8:D1:19:42:30:FF:47:9F:E2:F8:97:BB:CD:7A:8C:B4
diff --git a/luni/src/main/java/java/util/Locale.java b/luni/src/main/java/java/util/Locale.java
index b1a056a..9889c2f 100644
--- a/luni/src/main/java/java/util/Locale.java
+++ b/luni/src/main/java/java/util/Locale.java
@@ -95,7 +95,7 @@
  *     <td><a href="http://site.icu-project.org/download/51">ICU 51</a></td>
  *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-23">CLDR 23</a></td>
  *     <td><a href="http://www.unicode.org/versions/Unicode6.2.0/">Unicode 6.2</a></td></tr>
- * <tr><td>Android 4.? (STOPSHIP)</td>
+ * <tr><td>Android 5.0 (Lollipop)</td>
  *     <td><a href="http://site.icu-project.org/download/53">ICU 53</a></td>
  *     <td><a href="http://cldr.unicode.org/index/downloads/cldr-25">CLDR 25</a></td>
  *     <td><a href="http://www.unicode.org/versions/Unicode6.3.0/">Unicode 6.3</a></td></tr>
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
index 33584d8..020663e 100644
--- a/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
+++ b/luni/src/main/java/org/apache/harmony/security/utils/JarUtils.java
@@ -31,6 +31,7 @@
 import java.security.Principal;
 import java.security.Signature;
 import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
 import java.util.ArrayList;
@@ -82,8 +83,10 @@
         CertificateFactory cf = CertificateFactory.getInstance("X.509");
         int i = 0;
         for (org.apache.harmony.security.x509.Certificate encCert : encCerts) {
-            final InputStream is = new ByteArrayInputStream(encCert.getEncoded());
-            certs[i++] = (X509Certificate) cf.generateCertificate(is);
+            final byte[] encoded = encCert.getEncoded();
+            final InputStream is = new ByteArrayInputStream(encoded);
+            certs[i++] = new VerbatimX509Certificate((X509Certificate) cf.generateCertificate(is),
+                    encoded);
         }
 
         List<SignerInfo> sigInfos = signedData.getSignerInfos();
@@ -246,6 +249,10 @@
             }
             chain.add(issuerCert);
             count++;
+            /* Prevent growing infinitely if there is a loop */
+            if (count > candidates.length) {
+                break;
+            }
             issuer = issuerCert.getIssuerDN();
             if (issuerCert.getSubjectDN().equals(issuer)) {
                 break;
@@ -263,4 +270,22 @@
         return null;
     }
 
+    /**
+     * For legacy reasons we need to return exactly the original encoded
+     * certificate bytes, instead of letting the underlying implementation have
+     * a shot at re-encoding the data.
+     */
+    private static class VerbatimX509Certificate extends WrappedX509Certificate {
+        private byte[] encodedVerbatim;
+
+        public VerbatimX509Certificate(X509Certificate wrapped, byte[] encodedVerbatim) {
+            super(wrapped);
+            this.encodedVerbatim = encodedVerbatim;
+        }
+
+        @Override
+        public byte[] getEncoded() throws CertificateEncodingException {
+            return encodedVerbatim;
+        }
+    }
 }
diff --git a/luni/src/main/java/org/apache/harmony/security/utils/WrappedX509Certificate.java b/luni/src/main/java/org/apache/harmony/security/utils/WrappedX509Certificate.java
new file mode 100644
index 0000000..2b09309
--- /dev/null
+++ b/luni/src/main/java/org/apache/harmony/security/utils/WrappedX509Certificate.java
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2014 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 org.apache.harmony.security.utils;
+
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.Set;
+
+public class WrappedX509Certificate extends X509Certificate {
+    private final X509Certificate wrapped;
+
+    public WrappedX509Certificate(X509Certificate wrapped) {
+        this.wrapped = wrapped;
+    }
+
+    @Override
+    public Set<String> getCriticalExtensionOIDs() {
+        return wrapped.getCriticalExtensionOIDs();
+    }
+
+    @Override
+    public byte[] getExtensionValue(String oid) {
+        return wrapped.getExtensionValue(oid);
+    }
+
+    @Override
+    public Set<String> getNonCriticalExtensionOIDs() {
+        return wrapped.getNonCriticalExtensionOIDs();
+    }
+
+    @Override
+    public boolean hasUnsupportedCriticalExtension() {
+        return wrapped.hasUnsupportedCriticalExtension();
+    }
+
+    @Override
+    public void checkValidity() throws CertificateExpiredException,
+            CertificateNotYetValidException {
+        wrapped.checkValidity();
+    }
+
+    @Override
+    public void checkValidity(Date date) throws CertificateExpiredException,
+            CertificateNotYetValidException {
+        wrapped.checkValidity(date);
+    }
+
+    @Override
+    public int getVersion() {
+        return wrapped.getVersion();
+    }
+
+    @Override
+    public BigInteger getSerialNumber() {
+        return wrapped.getSerialNumber();
+    }
+
+    @Override
+    public Principal getIssuerDN() {
+        return wrapped.getIssuerDN();
+    }
+
+    @Override
+    public Principal getSubjectDN() {
+        return wrapped.getSubjectDN();
+    }
+
+    @Override
+    public Date getNotBefore() {
+        return wrapped.getNotBefore();
+    }
+
+    @Override
+    public Date getNotAfter() {
+        return wrapped.getNotAfter();
+    }
+
+    @Override
+    public byte[] getTBSCertificate() throws CertificateEncodingException {
+        return wrapped.getTBSCertificate();
+    }
+
+    @Override
+    public byte[] getSignature() {
+        return wrapped.getSignature();
+    }
+
+    @Override
+    public String getSigAlgName() {
+        return wrapped.getSigAlgName();
+    }
+
+    @Override
+    public String getSigAlgOID() {
+        return wrapped.getSigAlgOID();
+    }
+
+    @Override
+    public byte[] getSigAlgParams() {
+        return wrapped.getSigAlgParams();
+    }
+
+    @Override
+    public boolean[] getIssuerUniqueID() {
+        return wrapped.getIssuerUniqueID();
+    }
+
+    @Override
+    public boolean[] getSubjectUniqueID() {
+        return wrapped.getSubjectUniqueID();
+    }
+
+    @Override
+    public boolean[] getKeyUsage() {
+        return wrapped.getKeyUsage();
+    }
+
+    @Override
+    public int getBasicConstraints() {
+        return wrapped.getBasicConstraints();
+    }
+
+    @Override
+    public byte[] getEncoded() throws CertificateEncodingException {
+        return wrapped.getEncoded();
+    }
+
+    @Override
+    public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException,
+            InvalidKeyException, NoSuchProviderException, SignatureException {
+        wrapped.verify(key);
+    }
+
+    @Override
+    public void verify(PublicKey key, String sigProvider) throws CertificateException,
+            NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException,
+            SignatureException {
+        verify(key, sigProvider);
+    }
+
+    @Override
+    public String toString() {
+        return wrapped.toString();
+    }
+
+    @Override
+    public PublicKey getPublicKey() {
+        return wrapped.getPublicKey();
+    }
+}
diff --git a/luni/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java b/luni/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java
index d1079c8..040a012 100644
--- a/luni/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java
+++ b/luni/src/main/java/org/apache/harmony/xml/parsers/DocumentBuilderImpl.java
@@ -416,11 +416,13 @@
 
     private String resolveCharacterReference(String value, int base) {
         try {
-            int ch = Integer.parseInt(value, base);
-            if (ch < 0 || ch > Character.MAX_VALUE) {
-                return null;
+            int codePoint = Integer.parseInt(value, base);
+            if (Character.isBmpCodePoint(codePoint)) {
+                return String.valueOf((char) codePoint);
+            } else {
+                char[] surrogatePair = Character.toChars(codePoint);
+                return new String(surrogatePair);
             }
-            return String.valueOf((char) ch);
         } catch (NumberFormatException ex) {
             return null;
         }
diff --git a/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java b/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
index ae85595..f356e68 100644
--- a/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
+++ b/luni/src/test/java/libcore/icu/DateIntervalFormatTest.java
@@ -408,4 +408,16 @@
     assertEquals("یکشنبه د ۱۹۸۰ د فبروري ۱۰", formatDateRange(new Locale("ps"), utc, thisYear, thisYear, flags));
     assertEquals("วันอาทิตย์ 10 กุมภาพันธ์ 1980", formatDateRange(new Locale("th"), utc, thisYear, thisYear, flags));
   }
+
+  // http://b/13234532
+  public void test13234532() throws Exception {
+    Locale l = Locale.US;
+    TimeZone utc = TimeZone.getTimeZone("UTC");
+
+    int flags = FORMAT_SHOW_TIME | FORMAT_ABBREV_ALL | FORMAT_12HOUR;
+
+    assertEquals("10 – 11 AM", formatDateRange(l, utc, 10*HOUR, 11*HOUR, flags));
+    assertEquals("11 AM – 1 PM", formatDateRange(l, utc, 11*HOUR, 13*HOUR, flags));
+    assertEquals("2 – 3 PM", formatDateRange(l, utc, 14*HOUR, 15*HOUR, flags));
+  }
 }
diff --git a/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java b/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
index 1a24667..07ecd12 100644
--- a/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
+++ b/luni/src/test/java/libcore/javax/net/ssl/DefaultHostnameVerifierTest.java
@@ -198,6 +198,11 @@
         assertFalse(verifyWithDomainNamePattern("ddd.", "d*d."));
     }
 
+    public void testNoPrefixMatch() {
+        assertFalse(verifyWithDomainNamePattern("imap.google.com.au", "imap.google.com"));
+        assertFalse(verifyWithDomainNamePattern("imap.google.com.au", "*.google.com"));
+    }
+
     public void testVerifyHostName() {
         assertTrue(verifyWithDomainNamePattern("a.b.c.d", "a.b.c.d"));
         assertTrue(verifyWithDomainNamePattern("a.b.c.d", "*.b.c.d"));
diff --git a/luni/src/test/java/libcore/xml/KxmlSerializerTest.java b/luni/src/test/java/libcore/xml/KxmlSerializerTest.java
index 6a75a9b..5f68a99 100644
--- a/luni/src/test/java/libcore/xml/KxmlSerializerTest.java
+++ b/luni/src/test/java/libcore/xml/KxmlSerializerTest.java
@@ -22,7 +22,9 @@
 import junit.framework.TestCase;
 import org.kxml2.io.KXmlSerializer;
 import org.w3c.dom.Document;
+import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
 import org.xmlpull.v1.XmlSerializer;
 import static tests.support.Support_Xml.domOf;
 
@@ -87,12 +89,67 @@
         return serializer;
     }
 
+    public String fromCodePoint(int codePoint) {
+        if (codePoint > Character.MAX_VALUE) {
+            return new String(Character.toChars(codePoint));
+        }
+        return Character.toString((char) codePoint);
+    }
+
+    // http://b/17960630
+    public void testSpeakNoEvilMonkeys() throws Exception {
+        StringWriter stringWriter = new StringWriter();
+        XmlSerializer serializer = new KXmlSerializer();
+        serializer.setOutput(stringWriter);
+        serializer.startDocument("UTF-8", null);
+        serializer.startTag(NAMESPACE, "tag");
+        serializer.attribute(NAMESPACE, "attr", "a\ud83d\ude4ab");
+        serializer.text("c\ud83d\ude4ad");
+        serializer.cdsect("e\ud83d\ude4af");
+        serializer.endTag(NAMESPACE, "tag");
+        serializer.endDocument();
+        assertXmlEquals("<tag attr=\"a&#128586;b\">" +
+                        "c&#128586;d" +
+                        "<![CDATA[e]]>&#128586;<![CDATA[f]]>" +
+                        "</tag>", stringWriter.toString());
+
+        // Check we can parse what we just output.
+        Document doc = domOf(stringWriter.toString());
+        Node root = doc.getDocumentElement();
+        assertEquals("a\ud83d\ude4ab", root.getAttributes().getNamedItem("attr").getNodeValue());
+        Text text = (Text) root.getFirstChild();
+        assertEquals("c\ud83d\ude4ade\ud83d\ude4af", text.getNodeValue());
+    }
+
+    public void testBadSurrogates() throws Exception {
+        StringWriter stringWriter = new StringWriter();
+        XmlSerializer serializer = new KXmlSerializer();
+        serializer.setOutput(stringWriter);
+        serializer.startDocument("UTF-8", null);
+        serializer.startTag(NAMESPACE, "tag");
+        try {
+            serializer.attribute(NAMESPACE, "attr", "a\ud83d\u0040b");
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            serializer.text("c\ud83d\u0040d");
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            serializer.cdsect("e\ud83d\u0040f");
+        } catch (IllegalArgumentException expected) {
+        }
+    }
+
+    // Cover all the BMP code points plus a few that require us to use surrogates.
+    private static int MAX_TEST_CODE_POINT = 0x10008;
+
     public void testInvalidCharactersInText() throws IOException {
         XmlSerializer serializer = newSerializer();
         serializer.startTag(NAMESPACE, "root");
-        for (int ch = 0; ch <= 0xffff; ++ch) {
-            final String s = Character.toString((char) ch);
-            if (isValidXmlCodePoint(ch)) {
+        for (int c = 0; c <= MAX_TEST_CODE_POINT; ++c) {
+            final String s = fromCodePoint(c);
+            if (isValidXmlCodePoint(c)) {
                 serializer.text("a" + s + "b");
             } else {
                 try {
@@ -108,9 +165,9 @@
     public void testInvalidCharactersInAttributeValues() throws IOException {
         XmlSerializer serializer = newSerializer();
         serializer.startTag(NAMESPACE, "root");
-        for (int ch = 0; ch <= 0xffff; ++ch) {
-            final String s = Character.toString((char) ch);
-            if (isValidXmlCodePoint(ch)) {
+        for (int c = 0; c <= MAX_TEST_CODE_POINT; ++c) {
+            final String s = fromCodePoint(c);
+            if (isValidXmlCodePoint(c)) {
                 serializer.attribute(NAMESPACE, "a", "a" + s + "b");
             } else {
                 try {
@@ -126,9 +183,9 @@
     public void testInvalidCharactersInCdataSections() throws IOException {
         XmlSerializer serializer = newSerializer();
         serializer.startTag(NAMESPACE, "root");
-        for (int ch = 0; ch <= 0xffff; ++ch) {
-            final String s = Character.toString((char) ch);
-            if (isValidXmlCodePoint(ch)) {
+        for (int c = 0; c <= MAX_TEST_CODE_POINT; ++c) {
+            final String s = fromCodePoint(c);
+            if (isValidXmlCodePoint(c)) {
                 serializer.cdsect("a" + s + "b");
             } else {
                 try {
diff --git a/support/src/test/java/libcore/java/security/TestKeyStore.java b/support/src/test/java/libcore/java/security/TestKeyStore.java
index 203c028..bd64360 100644
--- a/support/src/test/java/libcore/java/security/TestKeyStore.java
+++ b/support/src/test/java/libcore/java/security/TestKeyStore.java
@@ -47,6 +47,7 @@
 import java.security.PublicKey;
 import java.security.SecureRandom;
 import java.security.Security;
+import java.security.UnrecoverableEntryException;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateFactory;
@@ -260,6 +261,7 @@
         private X500Principal subject;
         private int keyUsage;
         private boolean ca;
+        private PrivateKeyEntry privateEntry;
         private PrivateKeyEntry signer;
         private Certificate rootCa;
         private final List<KeyPurposeId> extendedKeyUsages = new ArrayList<KeyPurposeId>();
@@ -314,6 +316,12 @@
             return this;
         }
 
+        /** a private key entry to use for the generation of the certificate */
+        public Builder privateEntry(PrivateKeyEntry privateEntry) {
+            this.privateEntry = privateEntry;
+            return this;
+        }
+
         /** a private key entry to be used for signing, otherwise self-sign */
         public Builder signer(PrivateKeyEntry signer) {
             this.signer = signer;
@@ -368,21 +376,32 @@
                     }
                 }
 
+                /*
+                 * This is not implemented for other key types because the logic
+                 * would be long to write and it's not needed currently.
+                 */
+                if (privateEntry != null
+                        && (keyAlgorithms.length != 1 || !"RSA".equals(keyAlgorithms[0]))) {
+                    throw new IllegalStateException(
+                            "Only reusing an existing key is implemented for RSA");
+                }
+
                 KeyStore keyStore = createKeyStore();
                 for (String keyAlgorithm : keyAlgorithms) {
                     String publicAlias  = aliasPrefix + "-public-"  + keyAlgorithm;
                     String privateAlias = aliasPrefix + "-private-" + keyAlgorithm;
                     if ((keyAlgorithm.equals("EC_RSA") || keyAlgorithm.equals("DH_RSA"))
                             && signer == null && rootCa == null) {
-                        createKeys(keyStore, keyAlgorithm, publicAlias, privateAlias,
-                                   privateKey(keyStore, keyPassword, "RSA", "RSA"));
+                        createKeys(keyStore, keyAlgorithm, publicAlias, privateAlias, null,
+                                privateKey(keyStore, keyPassword, "RSA", "RSA"));
                         continue;
                     } else if (keyAlgorithm.equals("DH_DSA") && signer == null && rootCa == null) {
-                        createKeys(keyStore, keyAlgorithm, publicAlias, privateAlias,
+                        createKeys(keyStore, keyAlgorithm, publicAlias, privateAlias, null,
                                 privateKey(keyStore, keyPassword, "DSA", "DSA"));
                         continue;
                     }
-                    createKeys(keyStore, keyAlgorithm, publicAlias, privateAlias, signer);
+                    createKeys(keyStore, keyAlgorithm, publicAlias, privateAlias, privateEntry,
+                            signer);
                 }
                 if (rootCa != null) {
                     keyStore.setCertificateEntry(aliasPrefix
@@ -416,6 +435,7 @@
                 String keyAlgorithm,
                 String publicAlias,
                 String privateAlias,
+                PrivateKeyEntry privateEntry,
                 PrivateKeyEntry signer) throws Exception {
             PrivateKey caKey;
             X509Certificate caCert;
@@ -430,42 +450,51 @@
                 caCertChain = (X509Certificate[])signer.getCertificateChain();
             }
 
-            PrivateKey privateKey;
+            final PrivateKey privateKey;
+            final PublicKey publicKey;
             X509Certificate x509c;
             if (publicAlias == null && privateAlias == null) {
                 // don't want anything apparently
                 privateKey = null;
+                publicKey = null;
                 x509c = null;
             } else {
-                // 1.) we make the keys
-                int keySize;
-                if (keyAlgorithm.equals("RSA")) {
-                    // 512 breaks SSL_RSA_EXPORT_* on RI and TLS_ECDHE_RSA_WITH_RC4_128_SHA for us
-                    keySize =  1024;
-                } else if (keyAlgorithm.equals("DH_RSA")) {
-                    keySize = 512;
-                    keyAlgorithm = "DH";
-                } else if (keyAlgorithm.equals("DSA")) {
-                    keySize = 512;
-                } else if (keyAlgorithm.equals("DH_DSA")) {
-                    keySize = 512;
-                    keyAlgorithm = "DH";
-                } else if (keyAlgorithm.equals("EC")) {
-                    keySize = 256;
-                } else if (keyAlgorithm.equals("EC_RSA")) {
-                    keySize = 256;
-                    keyAlgorithm = "EC";
+                if (privateEntry == null) {
+                    // 1a.) we make the keys
+                    int keySize;
+                    if (keyAlgorithm.equals("RSA")) {
+                        // 512 breaks SSL_RSA_EXPORT_* on RI and
+                        // TLS_ECDHE_RSA_WITH_RC4_128_SHA for us
+                        keySize = 1024;
+                    } else if (keyAlgorithm.equals("DH_RSA")) {
+                        keySize = 512;
+                        keyAlgorithm = "DH";
+                    } else if (keyAlgorithm.equals("DSA")) {
+                        keySize = 512;
+                    } else if (keyAlgorithm.equals("DH_DSA")) {
+                        keySize = 512;
+                        keyAlgorithm = "DH";
+                    } else if (keyAlgorithm.equals("EC")) {
+                        keySize = 256;
+                    } else if (keyAlgorithm.equals("EC_RSA")) {
+                        keySize = 256;
+                        keyAlgorithm = "EC";
+                    } else {
+                        throw new IllegalArgumentException("Unknown key algorithm " + keyAlgorithm);
+                    }
+
+                    KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyAlgorithm);
+                    kpg.initialize(keySize, new SecureRandom());
+
+                    KeyPair kp = kpg.generateKeyPair();
+                    privateKey = kp.getPrivate();
+                    publicKey = kp.getPublic();
                 } else {
-                    throw new IllegalArgumentException("Unknown key algorithm " + keyAlgorithm);
+                    // 1b.) we use the previous keys
+                    privateKey = privateEntry.getPrivateKey();
+                    publicKey = privateEntry.getCertificate().getPublicKey();
                 }
 
-                KeyPairGenerator kpg = KeyPairGenerator.getInstance(keyAlgorithm);
-                kpg.initialize(keySize, new SecureRandom());
-
-                KeyPair kp = kpg.generateKeyPair();
-                privateKey = kp.getPrivate();
-                PublicKey publicKey  = kp.getPublic();
-
                 // 2.) use keys to make certificate
                 X500Principal issuer = ((caCert != null)
                                         ? caCert.getSubjectX500Principal()
@@ -820,6 +849,24 @@
     }
 
     /**
+     * Return an {@code X509Certificate that matches the given {@code alias}.
+     */
+    public KeyStore.Entry getEntryByAlias(String alias) {
+        return entryByAlias(keyStore, alias);
+    }
+
+    /**
+     * Finds an entry in the keystore by the given alias.
+     */
+    public static KeyStore.Entry entryByAlias(KeyStore keyStore, String alias) {
+        try {
+            return keyStore.getEntry(alias, null);
+        } catch (NoSuchAlgorithmException | UnrecoverableEntryException | KeyStoreException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
      * Create a client key store that only contains self-signed certificates but no private keys
      */
     public static KeyStore createClient(KeyStore caKeyStore) {
diff --git a/support/src/test/java/tests/resources/hyts_certLoop.jar b/support/src/test/java/tests/resources/hyts_certLoop.jar
new file mode 100644
index 0000000..cb4ebe1
--- /dev/null
+++ b/support/src/test/java/tests/resources/hyts_certLoop.jar
Binary files differ
diff --git a/xml/src/main/java/org/kxml2/io/KXmlSerializer.java b/xml/src/main/java/org/kxml2/io/KXmlSerializer.java
index 8fa2756..bfdeece 100644
--- a/xml/src/main/java/org/kxml2/io/KXmlSerializer.java
+++ b/xml/src/main/java/org/kxml2/io/KXmlSerializer.java
@@ -125,14 +125,18 @@
                     // otherwise generate.
                     // Note: tab, newline, and carriage return have already been
                     // handled above.
-                    boolean valid = (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
-                    if (!valid) {
-                        reportInvalidCharacter(c);
-                    }
-                    if (unicode || c < 127) {
-                        writer.write(c);
+                    boolean allowedInXml = (c >= 0x20 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xfffd);
+                    if (allowedInXml) {
+                        if (unicode || c < 127) {
+                            writer.write(c);
+                        } else {
+                            writer.write("&#" + ((int) c) + ";");
+                        }
+                    } else if (Character.isHighSurrogate(c) && i < s.length() - 1) {
+                        writeSurrogate(c, s.charAt(i + 1));
+                        ++i;
                     } else {
-                        writer.write("&#" + ((int) c) + ";");
+                        reportInvalidCharacter(c);
                     }
                     // END android-changed
             }
@@ -141,7 +145,7 @@
 
     // BEGIN android-added
     private static void reportInvalidCharacter(char ch) {
-        throw new IllegalArgumentException("Illegal character (" + Integer.toHexString((int) ch) + ")");
+        throw new IllegalArgumentException("Illegal character (U+" + Integer.toHexString((int) ch) + ")");
     }
     // END android-added
 
@@ -548,22 +552,41 @@
         // BEGIN android-changed: ]]> is not allowed within a CDATA,
         // so break and start a new one when necessary.
         data = data.replace("]]>", "]]]]><![CDATA[>");
-        char[] chars = data.toCharArray();
-        // We also aren't allowed any invalid characters.
-        for (char ch : chars) {
-            boolean valid = (ch >= 0x20 && ch <= 0xd7ff) ||
+        writer.write("<![CDATA[");
+        for (int i = 0; i < data.length(); ++i) {
+            char ch = data.charAt(i);
+            boolean allowedInCdata = (ch >= 0x20 && ch <= 0xd7ff) ||
                     (ch == '\t' || ch == '\n' || ch == '\r') ||
                     (ch >= 0xe000 && ch <= 0xfffd);
-            if (!valid) {
+            if (allowedInCdata) {
+                writer.write(ch);
+            } else if (Character.isHighSurrogate(ch) && i < data.length() - 1) {
+                // Character entities aren't valid in CDATA, so break out for this.
+                writer.write("]]>");
+                writeSurrogate(ch, data.charAt(++i));
+                writer.write("<![CDATA[");
+            } else {
                 reportInvalidCharacter(ch);
             }
         }
-        writer.write("<![CDATA[");
-        writer.write(chars, 0, chars.length);
         writer.write("]]>");
         // END android-changed
     }
 
+    // BEGIN android-added
+    private void writeSurrogate(char high, char low) throws IOException {
+        if (!Character.isLowSurrogate(low)) {
+            throw new IllegalArgumentException("Bad surrogate pair (U+" + Integer.toHexString((int) high) +
+                                               " U+" + Integer.toHexString((int) low) + ")");
+        }
+        // Java-style surrogate pairs aren't allowed in XML. We could use the > 3-byte encodings, but that
+        // seems likely to upset anything expecting modified UTF-8 rather than "real" UTF-8. It seems more
+        // conservative in a Java environment to use an entity reference instead.
+        int codePoint = Character.toCodePoint(high, low);
+        writer.write("&#" + codePoint + ";");
+    }
+    // END android-added
+
     public void comment(String comment) throws IOException {
         check(false);
         writer.write("<!--");