Merge "Test case DecimalFormat failure with leading 0." into nyc-dev
diff --git a/JavaLibrary.mk b/JavaLibrary.mk
index b75bc5b..c07c5ee 100644
--- a/JavaLibrary.mk
+++ b/JavaLibrary.mk
@@ -204,6 +204,7 @@
 LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
 LOCAL_NO_STANDARD_LIBRARIES := true
 LOCAL_JAVA_LIBRARIES := core-oj core-libart core-junit bouncycastle
+LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-bcpkix bouncycastle-ocsp
 LOCAL_JAVACFLAGS := $(local_javac_flags)
 LOCAL_MODULE := core-tests-support
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/JavaLibrary.mk
@@ -319,6 +320,7 @@
     LOCAL_JAVA_RESOURCE_DIRS := $(test_resource_dirs)
     LOCAL_NO_STANDARD_LIBRARIES := true
     LOCAL_JAVA_LIBRARIES := core-oj-hostdex core-libart-hostdex core-junit-hostdex bouncycastle-hostdex
+    LOCAL_STATIC_JAVA_LIBRARIES := bouncycastle-bcpkix-hostdex bouncycastle-ocsp-hostdex
     LOCAL_JAVACFLAGS := $(local_javac_flags)
     LOCAL_MODULE_TAGS := optional
     LOCAL_MODULE := core-tests-support-hostdex
diff --git a/dalvik/src/main/java/dalvik/system/DexFile.java b/dalvik/src/main/java/dalvik/system/DexFile.java
index 1d33339..c30972b 100644
--- a/dalvik/src/main/java/dalvik/system/DexFile.java
+++ b/dalvik/src/main/java/dalvik/system/DexFile.java
@@ -452,6 +452,15 @@
     public native static boolean isProfileGuidedCompilerFilter(String filter);
 
     /**
+     * Returns the version of the compiler filter that is not based on profiles.
+     * If the input is not a valid filter, or the filter is already not based on
+     * profiles, this returns the input.
+     *
+     * @hide
+     */
+    public native static String getNonProfileGuidedCompilerFilter(String filter);
+
+    /**
      * Returns the VM's opinion of what kind of dexopt is needed to make the
      * apk/jar file up to date, where {@code targetMode} is used to indicate what
      * type of compilation the caller considers up-to-date, and {@code newProfile}
diff --git a/dex/src/main/java/com/android/dex/DexFormat.java b/dex/src/main/java/com/android/dex/DexFormat.java
index 9319bc2..c598eee 100644
--- a/dex/src/main/java/com/android/dex/DexFormat.java
+++ b/dex/src/main/java/com/android/dex/DexFormat.java
@@ -27,7 +27,7 @@
      * API level to target in order to produce the most modern file
      * format
      */
-    public static final int API_CURRENT = 14;
+    public static final int API_CURRENT = 24;
 
     /** API level to target in order to suppress extended opcode usage */
     public static final int API_NO_EXTENDED_OPCODES = 13;
@@ -44,8 +44,14 @@
     /** common suffix for all dex file "magic numbers" */
     public static final String MAGIC_SUFFIX = "\0";
 
-    /** dex file version number for the current format variant */
-    public static final String VERSION_CURRENT = "036";
+    /**
+     * Dex file version number for dalvik.
+     * <p>
+     * Note: Dex version 36 was loadable in some versions of Dalvik but was never fully supported or
+     * completed and is not considered a valid dex file format.
+     * </p>
+     */
+    public static final String VERSION_CURRENT = "037";
 
     /** dex file version number for API level 13 and earlier */
     public static final String VERSION_FOR_API_13 = "035";
@@ -88,7 +94,7 @@
         if (version.equals(VERSION_CURRENT)) {
             return API_CURRENT;
         } else if (version.equals(VERSION_FOR_API_13)) {
-            return 13;
+            return API_NO_EXTENDED_OPCODES;
         }
 
         return -1;
@@ -108,4 +114,9 @@
 
         return MAGIC_PREFIX + version + MAGIC_SUFFIX;
     }
+
+    public static boolean isSupportedDexMagic(byte[] magic) {
+        int api = magicToApi(magic);
+        return api == API_NO_EXTENDED_OPCODES || api == API_CURRENT;
+    }
 }
diff --git a/dex/src/main/java/com/android/dex/TableOfContents.java b/dex/src/main/java/com/android/dex/TableOfContents.java
index d1b87ac..583f195 100644
--- a/dex/src/main/java/com/android/dex/TableOfContents.java
+++ b/dex/src/main/java/com/android/dex/TableOfContents.java
@@ -53,6 +53,7 @@
             debugInfos, annotations, encodedArrays, annotationsDirectories
     };
 
+    public int apiLevel;
     public int checksum;
     public byte[] signature;
     public int fileSize;
@@ -73,12 +74,12 @@
 
     private void readHeader(Dex.Section headerIn) throws UnsupportedEncodingException {
         byte[] magic = headerIn.readByteArray(8);
-        int apiTarget = DexFormat.magicToApi(magic);
 
-        if (apiTarget != DexFormat.API_NO_EXTENDED_OPCODES) {
+        if (!DexFormat.isSupportedDexMagic(magic)) {
             throw new DexException("Unexpected magic: " + Arrays.toString(magic));
         }
 
+        apiLevel = DexFormat.magicToApi(magic);
         checksum = headerIn.readInt();
         signature = headerIn.readByteArray(20);
         fileSize = headerIn.readInt();
@@ -163,8 +164,8 @@
         throw new IllegalArgumentException("No such map item: " + type);
     }
 
-    public void writeHeader(Dex.Section out) throws IOException {
-        out.write(DexFormat.apiToMagic(DexFormat.API_NO_EXTENDED_OPCODES).getBytes("UTF-8"));
+    public void writeHeader(Dex.Section out, int api) throws IOException {
+        out.write(DexFormat.apiToMagic(api).getBytes("UTF-8"));
         out.writeInt(checksum);
         out.write(signature);
         out.writeInt(fileSize);
diff --git a/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/DatagramChannelTest.java b/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/DatagramChannelTest.java
index 12aaae0..6bfe85e 100644
--- a/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/DatagramChannelTest.java
+++ b/harmony-tests/src/test/java/org/apache/harmony/tests/java/nio/channels/DatagramChannelTest.java
@@ -17,6 +17,8 @@
 
 package org.apache.harmony.tests.java.nio.channels;
 
+import android.system.ErrnoException;
+import android.system.OsConstants;
 import java.io.IOException;
 import java.net.DatagramPacket;
 import java.net.DatagramSocket;
@@ -33,8 +35,10 @@
 import java.nio.channels.UnresolvedAddressException;
 import java.nio.channels.UnsupportedAddressTypeException;
 import java.nio.channels.spi.SelectorProvider;
+import java.util.concurrent.atomic.AtomicReference;
 import junit.framework.TestCase;
 import libcore.io.IoUtils;
+import libcore.io.Libcore;
 
 /**
  * Test for DatagramChannel
@@ -2518,4 +2522,40 @@
 
         dc.socket().getLocalSocketAddress();
     }
+
+    // b/27294715
+    public void test_concurrentShutdown() throws Exception {
+        DatagramChannel dc = DatagramChannel.open();
+        dc.configureBlocking(true);
+        dc.bind(new InetSocketAddress(Inet6Address.LOOPBACK, 0));
+        // Set 4s timeout
+        dc.socket().setSoTimeout(4000);
+
+        final AtomicReference<Exception> killerThreadException = new AtomicReference<Exception>(null);
+        final Thread killer = new Thread(new Runnable() {
+            public void run() {
+                try {
+                    Thread.sleep(2000);
+                    try {
+                        Libcore.os.shutdown(dc.socket().getFileDescriptor$(), OsConstants.SHUT_RDWR);
+                    } catch (ErrnoException expected) {
+                        if (OsConstants.ENOTCONN != expected.errno) {
+                            killerThreadException.set(expected);
+                        }
+                    }
+                } catch (Exception ex) {
+                    killerThreadException.set(ex);
+                }
+            }
+        });
+        killer.start();
+
+        ByteBuffer dst = ByteBuffer.allocate(CAPACITY_NORMAL);
+        assertEquals(null, dc.receive(dst));
+        assertEquals(0, dst.position());
+        dc.close();
+
+        killer.join();
+        assertNull(killerThreadException.get());
+    }
 }
diff --git a/luni/src/main/native/libcore_io_Posix.cpp b/luni/src/main/native/libcore_io_Posix.cpp
index 27fa0d7..3fa4dee 100644
--- a/luni/src/main/native/libcore_io_Posix.cpp
+++ b/luni/src/main/native/libcore_io_Posix.cpp
@@ -376,8 +376,8 @@
         const struct sockaddr_nl* nl_addr = reinterpret_cast<const struct sockaddr_nl*>(&ss);
         static jmethodID ctor = env->GetMethodID(JniConstants::netlinkSocketAddressClass,
                 "<init>", "(II)V");
-        return env->NewObject(JniConstants::netlinkSocketAddressClass, ctor, 
-                static_cast<jint>(nl_addr->nl_pid), 
+        return env->NewObject(JniConstants::netlinkSocketAddressClass, ctor,
+                static_cast<jint>(nl_addr->nl_pid),
                 static_cast<jint>(nl_addr->nl_groups));
     } else if (ss.ss_family == AF_PACKET) {
         const struct sockaddr_ll* sll = reinterpret_cast<const struct sockaddr_ll*>(&ss);
@@ -1516,10 +1516,9 @@
     sockaddr* from = (javaInetSocketAddress != NULL) ? reinterpret_cast<sockaddr*>(&ss) : NULL;
     socklen_t* fromLength = (javaInetSocketAddress != NULL) ? &sl : 0;
     jint recvCount = NET_FAILURE_RETRY(env, ssize_t, recvfrom, javaFd, bytes.get() + byteOffset, byteCount, flags, from, fromLength);
-    if (recvCount == -1) {
-        return recvCount;
+    if (recvCount > 0) {
+        fillInetSocketAddress(env, javaInetSocketAddress, ss);
     }
-    fillInetSocketAddress(env, javaInetSocketAddress, ss);
     return recvCount;
 }
 
diff --git a/luni/src/test/java/libcore/io/OsTest.java b/luni/src/test/java/libcore/io/OsTest.java
index 552c2a1..49a592d 100644
--- a/luni/src/test/java/libcore/io/OsTest.java
+++ b/luni/src/test/java/libcore/io/OsTest.java
@@ -34,10 +34,12 @@
 import java.net.InetSocketAddress;
 import java.net.NetworkInterface;
 import java.net.ServerSocket;
+import java.net.SocketOptions;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Locale;
+import java.util.concurrent.atomic.AtomicReference;
 import junit.framework.TestCase;
 import static android.system.OsConstants.*;
 
@@ -457,6 +459,42 @@
     }
   }
 
+  // b/27294715
+  public void test_recvfrom_concurrentShutdown() throws Exception {
+      final FileDescriptor serverFd = Libcore.os.socket(AF_INET, SOCK_DGRAM, 0);
+      Libcore.os.bind(serverFd, InetAddress.getByName("127.0.0.1"), 0);
+      // Set 4s timeout
+      IoBridge.setSocketOption(serverFd, SocketOptions.SO_TIMEOUT, new Integer(4000));
+
+      final AtomicReference<Exception> killerThreadException = new AtomicReference<Exception>(null);
+      final Thread killer = new Thread(new Runnable() {
+          public void run() {
+              try {
+                  Thread.sleep(2000);
+                  try {
+                      Libcore.os.shutdown(serverFd, SHUT_RDWR);
+                  } catch (ErrnoException expected) {
+                      if (OsConstants.ENOTCONN != expected.errno) {
+                          killerThreadException.set(expected);
+                      }
+                  }
+              } catch (Exception ex) {
+                  killerThreadException.set(ex);
+              }
+          }
+      });
+      killer.start();
+
+      ByteBuffer buffer = ByteBuffer.allocate(16);
+      InetSocketAddress srcAddress = new InetSocketAddress();
+      int received = Libcore.os.recvfrom(serverFd, buffer, 0, srcAddress);
+      assertTrue(received == 0);
+      Libcore.os.close(serverFd);
+
+      killer.join();
+      assertNull(killerThreadException.get());
+  }
+
   public void test_xattr() throws Exception {
     final String NAME_TEST = "user.meow";
 
diff --git a/luni/src/test/java/libcore/java/lang/BooleanTest.java b/luni/src/test/java/libcore/java/lang/BooleanTest.java
index 1ee5421..b1f536f 100644
--- a/luni/src/test/java/libcore/java/lang/BooleanTest.java
+++ b/luni/src/test/java/libcore/java/lang/BooleanTest.java
@@ -33,4 +33,9 @@
         assertTrue(Boolean.compare(false, true) < 0);
         assertTrue(Boolean.compare(true, false) > 0);
     }
+
+    public void testStaticHashCode() {
+        assertEquals(Boolean.TRUE.hashCode(), Boolean.hashCode(true));
+        assertEquals(Boolean.FALSE.hashCode(), Boolean.hashCode(false));
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/ByteTest.java b/luni/src/test/java/libcore/java/lang/ByteTest.java
index 761a7f9..75d09b0 100644
--- a/luni/src/test/java/libcore/java/lang/ByteTest.java
+++ b/luni/src/test/java/libcore/java/lang/ByteTest.java
@@ -31,4 +31,12 @@
         assertTrue(Byte.compare(min,  zero) < 0);
         assertTrue(Byte.compare(min,  max)  < 0);
     }
+
+    public void testStaticHashCode() {
+        assertEquals(new Byte((byte) 567).hashCode(), Byte.hashCode((byte) 567));
+    }
+
+    public void testBYTES() {
+        assertEquals(1, Byte.BYTES);
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/CharacterTest.java b/luni/src/test/java/libcore/java/lang/CharacterTest.java
index 8c6f06f..ecf06d1 100644
--- a/luni/src/test/java/libcore/java/lang/CharacterTest.java
+++ b/luni/src/test/java/libcore/java/lang/CharacterTest.java
@@ -289,4 +289,12 @@
     assertEquals(Character.DIRECTIONALITY_UNDEFINED, Character.getDirectionality(0x2068));
     assertEquals(Character.DIRECTIONALITY_UNDEFINED, Character.getDirectionality(0x2069));
   }
+
+  public void testStaticHashCode() {
+    assertEquals(new Character('A').hashCode(), Character.hashCode('A'));
+  }
+
+  public void testBYTES() {
+    assertEquals(2, Character.BYTES);
+  }
 }
diff --git a/luni/src/test/java/libcore/java/lang/DoubleTest.java b/luni/src/test/java/libcore/java/lang/DoubleTest.java
index 6fc6c5e..3d2b2c8 100644
--- a/luni/src/test/java/libcore/java/lang/DoubleTest.java
+++ b/luni/src/test/java/libcore/java/lang/DoubleTest.java
@@ -164,4 +164,8 @@
         double b = 578.0;
         assertEquals(a + b, Double.sum(a, b));
     }
+
+    public void testBYTES() {
+        assertEquals(8, Double.BYTES);
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/FloatTest.java b/luni/src/test/java/libcore/java/lang/FloatTest.java
index c25bd5c..b989cf4 100644
--- a/luni/src/test/java/libcore/java/lang/FloatTest.java
+++ b/luni/src/test/java/libcore/java/lang/FloatTest.java
@@ -137,4 +137,30 @@
         assertEquals(1.1754944e-38f, Float.parseFloat("11754942807573644E-54"));
         assertEquals(1.1754944e-38f, Float.parseFloat("11754942807573645E-54"));
     }
+
+    public void testStaticHashCode() {
+        assertEquals(Float.valueOf(567.0f).hashCode(), Float.hashCode(567.0f));
+    }
+
+    public void testMax() {
+        float a = 567.0f;
+        float b = 578.0f;
+        assertEquals(Math.max(a, b), Float.max(a, b));
+    }
+
+    public void testMin() {
+        float a = 567.0f;
+        float b = 578.0f;
+        assertEquals(Math.min(a, b), Float.min(a, b));
+    }
+
+    public void testSum() {
+        float a = 567.0f;
+        float b = 578.0f;
+        assertEquals(a + b, Float.sum(a, b));
+    }
+
+    public void testBYTES() {
+        assertEquals(4, Float.BYTES);
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/IntegerTest.java b/luni/src/test/java/libcore/java/lang/IntegerTest.java
index 44028fe..64449a4 100644
--- a/luni/src/test/java/libcore/java/lang/IntegerTest.java
+++ b/luni/src/test/java/libcore/java/lang/IntegerTest.java
@@ -153,4 +153,8 @@
         int b = 578;
         assertEquals(a + b, Integer.sum(a, b));
     }
+
+    public void testBYTES() {
+      assertEquals(4, Integer.BYTES);
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/LongTest.java b/luni/src/test/java/libcore/java/lang/LongTest.java
index 4e68933..adf6303 100644
--- a/luni/src/test/java/libcore/java/lang/LongTest.java
+++ b/luni/src/test/java/libcore/java/lang/LongTest.java
@@ -159,4 +159,8 @@
         long b = 578L;
         assertEquals(a + b, Long.sum(a, b));
     }
+
+    public void testBYTES() {
+        assertEquals(8, Long.BYTES);
+    }
 }
diff --git a/luni/src/test/java/libcore/java/lang/ShortTest.java b/luni/src/test/java/libcore/java/lang/ShortTest.java
index ab987bd..9a1d5a5 100644
--- a/luni/src/test/java/libcore/java/lang/ShortTest.java
+++ b/luni/src/test/java/libcore/java/lang/ShortTest.java
@@ -31,4 +31,12 @@
         assertTrue(Short.compare(min,  zero) < 0);
         assertTrue(Short.compare(min,  max)  < 0);
     }
+
+    public void testStaticHashCode() {
+        assertEquals(Short.valueOf((short) 567).hashCode(), Short.hashCode((short) 567));
+    }
+
+    public void testBYTES() {
+        assertEquals(2, Short.BYTES);
+    }
 }
diff --git a/luni/src/test/java/libcore/java/net/URLTest.java b/luni/src/test/java/libcore/java/net/URLTest.java
index 2717d14..789e3e9 100644
--- a/luni/src/test/java/libcore/java/net/URLTest.java
+++ b/luni/src/test/java/libcore/java/net/URLTest.java
@@ -750,4 +750,11 @@
             BlockGuard.setThreadPolicy(oldPolicy);
         }
     }
+
+    // http://27444667
+    public void testEmptyQueryAndAnchor() throws Exception {
+        assertEquals("/some/path", new URL("http://foobar.com/some/path?").getFile());
+        assertEquals("/some/path", new URL("http://foobar.com/some/path#").getFile());
+        assertEquals("/some/path", new URL("http://foobar.com/some/path?#").getFile());
+    }
 }
diff --git a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelTest.java
index 609a990..5169e9b 100644
--- a/luni/src/test/java/libcore/java/nio/channels/DatagramChannelTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/DatagramChannelTest.java
@@ -17,6 +17,7 @@
 package libcore.java.nio.channels;
 
 import java.io.IOException;
+import java.net.BindException;
 import java.net.DatagramSocket;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
@@ -25,10 +26,9 @@
 import java.net.NetworkInterface;
 import java.net.StandardSocketOptions;
 import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyBoundException;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.DatagramChannel;
-import java.nio.channels.SocketChannel;
-import java.nio.channels.UnresolvedAddressException;
 import java.util.Enumeration;
 import java.util.Set;
 
@@ -181,6 +181,49 @@
         assertNotNull(socket.getFileDescriptor$());
     }
 
+    public void test_bind() throws IOException {
+        InetSocketAddress socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0);
+        DatagramChannel channel = DatagramChannel.open();
+        channel.bind(socketAddress);
+        assertEquals(socketAddress.getAddress(),
+                ((InetSocketAddress)(channel.getLocalAddress())).getAddress());
+        assertTrue(((InetSocketAddress)(channel.getLocalAddress())).getPort() > 0);
+
+        try {
+            channel.bind(socketAddress);
+            fail();
+        } catch (AlreadyBoundException expected) {
+        }
+
+        socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK,
+                ((InetSocketAddress)(channel.getLocalAddress())).getPort());
+        try {
+            DatagramChannel.open().bind(socketAddress);
+            fail();
+        } catch (BindException expected) {}
+
+        channel.close();
+        socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0);
+        try {
+            channel.bind(socketAddress);
+        } catch (ClosedChannelException expected) {}
+    }
+
+    public void test_getRemoteAddress() throws IOException {
+        InetSocketAddress socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0);
+        DatagramChannel clientChannel = DatagramChannel.open();
+        DatagramChannel serverChannel = DatagramChannel.open();
+        serverChannel.bind(socketAddress);
+
+        assertNull(clientChannel.getRemoteAddress());
+
+        clientChannel.connect(serverChannel.getLocalAddress());
+        assertEquals(socketAddress.getAddress(),
+                ((InetSocketAddress)(clientChannel.getRemoteAddress())).getAddress());
+        assertEquals(((InetSocketAddress)(serverChannel.getLocalAddress())).getPort(),
+                ((InetSocketAddress)(clientChannel.getRemoteAddress())).getPort());
+    }
+
     private static InetAddress getNonLoopbackNetworkInterfaceAddress(boolean ipv4) throws IOException {
         Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
         while (networkInterfaces.hasMoreElements()) {
diff --git a/luni/src/test/java/libcore/java/nio/channels/ServerSocketChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/ServerSocketChannelTest.java
index 1178b70..380b404 100644
--- a/luni/src/test/java/libcore/java/nio/channels/ServerSocketChannelTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/ServerSocketChannelTest.java
@@ -22,10 +22,13 @@
 import java.net.NetworkInterface;
 import java.net.ServerSocket;
 import java.net.SocketException;
+import java.net.StandardSocketOptions;
+import java.nio.channels.AlreadyBoundException;
 import java.nio.channels.ClosedChannelException;
 import java.nio.channels.ServerSocketChannel;
 import java.nio.channels.SocketChannel;
 import java.nio.channels.UnresolvedAddressException;
+import java.nio.channels.UnsupportedAddressTypeException;
 import java.util.Enumeration;
 import java.util.Set;
 
@@ -136,6 +139,58 @@
         ssc.close();
     }
 
+    public void test_bind$SocketAddress() throws IOException {
+        ServerSocketChannel ssc = ServerSocketChannel.open();
+        ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0));
+        assertEquals(InetAddress.getLoopbackAddress(),
+                ((InetSocketAddress)(ssc.getLocalAddress())).getAddress());
+        assertTrue(((InetSocketAddress)(ssc.getLocalAddress())).getPort() > 0);
+
+        try {
+            ssc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(),
+                    ((InetSocketAddress)(ssc.getLocalAddress())).getPort()));
+            fail();
+        } catch (AlreadyBoundException expected) {
+        }
+
+        try {
+            ServerSocketChannel ssc1 = ServerSocketChannel.open();
+            ssc1.bind(new InetSocketAddress("1.1.1.1.1.1.1", 0));
+            fail();
+        } catch (UnresolvedAddressException expected) {
+        }
+
+        ssc.close();
+        try {
+            ssc.bind(new InetSocketAddress("1.1.1.1.1.1.1", 0));
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    public void test_setOption() throws Exception {
+        ServerSocketChannel sc = ServerSocketChannel.open();
+        sc.setOption(StandardSocketOptions.SO_REUSEADDR, true);
+
+        // Assert that we can read back the option from the channel...
+        assertTrue(sc.getOption(StandardSocketOptions.SO_REUSEADDR));
+
+        sc.setOption(StandardSocketOptions.SO_REUSEADDR, false);
+
+        // Assert that we can read back the option from the channel...
+        assertEquals(false, (boolean)sc.getOption(StandardSocketOptions.SO_REUSEADDR));
+
+        sc.setOption(StandardSocketOptions.SO_RCVBUF, 1120);
+        assertEquals((Integer)1120, sc.getOption(StandardSocketOptions.SO_RCVBUF));
+
+        sc.close();
+        try {
+            sc.setOption(StandardSocketOptions.SO_RCVBUF, 2000);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
     private static boolean canConnect(InetSocketAddress address) {
         try {
             SocketChannel socketChannel = SocketChannel.open(address);
diff --git a/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java b/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
index d31b222..72609ee 100644
--- a/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
+++ b/luni/src/test/java/libcore/java/nio/channels/SocketChannelTest.java
@@ -20,278 +20,378 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.reflect.Field;
+import java.net.BindException;
 import java.net.ConnectException;
-import java.net.Socket;
-import java.net.SocketImpl;
+import java.net.Inet4Address;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketImpl;
 import java.net.StandardSocketOptions;
 import java.nio.ByteBuffer;
+import java.nio.channels.AlreadyBoundException;
 import java.nio.channels.ClosedChannelException;
-import java.nio.channels.SocketChannel;
-import java.nio.channels.Selector;
+import java.nio.channels.NotYetConnectedException;
 import java.nio.channels.SelectionKey;
-import java.nio.channels.UnresolvedAddressException;
-import java.util.Set;
-
-import static android.system.OsConstants.*;
+import java.nio.channels.Selector;
+import java.nio.channels.SocketChannel;
 
 public class SocketChannelTest extends junit.framework.TestCase {
 
-  public void test_read_intoReadOnlyByteArrays() throws Exception {
-    ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer();
-    ServerSocket ss = new ServerSocket(0);
-    ss.setReuseAddress(true);
-    SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
-    try {
-      sc.read(readOnly);
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
-    try {
-      sc.read(new ByteBuffer[] { readOnly });
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
-    try {
-      sc.read(new ByteBuffer[] { readOnly }, 0, 1);
-      fail();
-    } catch (IllegalArgumentException expected) {
-    }
-  }
-
-  // https://code.google.com/p/android/issues/detail?id=56684
-  public void test_56684() throws Exception {
-    SocketChannel sc = SocketChannel.open();
-    sc.configureBlocking(false);
-
-    Selector selector = Selector.open();
-    SelectionKey selectionKey = sc.register(selector, SelectionKey.OP_CONNECT);
-
-    try {
-      // This test originally mocked the connect syscall to return ENETUNREACH.
-      // This is not easily doable in openJdk libcore, but a connect to broadcast
-      // address (255.255.255.255) for a TCP connection produces ENETUNREACH
-      // Kernel code that does it is at
-      // http://lxr.free-electrons.com/source/net/ipv4/tcp_ipv4.c?v=3.18#L182
-      sc.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[] {
-                    (byte) 255, (byte) 255, (byte)255, (byte)255 }), 0));
-      fail();
-    } catch (ConnectException ex) {
+    public void test_read_intoReadOnlyByteArrays() throws Exception {
+        ByteBuffer readOnly = ByteBuffer.allocate(1).asReadOnlyBuffer();
+        ServerSocket ss = new ServerSocket(0);
+        ss.setReuseAddress(true);
+        SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
+        try {
+            sc.read(readOnly);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            sc.read(new ByteBuffer[] { readOnly });
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
+        try {
+            sc.read(new ByteBuffer[] { readOnly }, 0, 1);
+            fail();
+        } catch (IllegalArgumentException expected) {
+        }
     }
 
-    try {
-      sc.finishConnect();
-      fail();
-    } catch (ClosedChannelException expected) {
-    }
-  }
+    // https://code.google.com/p/android/issues/detail?id=56684
+    public void test_56684() throws Exception {
+        SocketChannel sc = SocketChannel.open();
+        sc.configureBlocking(false);
 
-  /** Checks that closing a Socket's output stream also closes the Socket and SocketChannel. */
-  public void test_channelSocketOutputStreamClosureState() throws Exception {
-    ServerSocket ss = new ServerSocket(0);
+        Selector selector = Selector.open();
+        SelectionKey selectionKey = sc.register(selector, SelectionKey.OP_CONNECT);
 
-    SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
-    sc.configureBlocking(true);
+        try {
+            // This test originally mocked the connect syscall to return ENETUNREACH.
+            // This is not easily doable in openJdk libcore, but a connect to broadcast
+            // address (255.255.255.255) for a TCP connection produces ENETUNREACH
+            // Kernel code that does it is at
+            // http://lxr.free-electrons.com/source/net/ipv4/tcp_ipv4.c?v=3.18#L182
+            sc.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[] {
+                    (byte) 255, (byte) 255, (byte) 255, (byte) 255 }), 0));
+            fail();
+        } catch (ConnectException ex) {
+        }
 
-    Socket scSocket = sc.socket();
-    OutputStream os = scSocket.getOutputStream();
-
-    assertTrue(sc.isOpen());
-    assertFalse(scSocket.isClosed());
-
-    os.close();
-
-    assertFalse(sc.isOpen());
-    assertTrue(scSocket.isClosed());
-
-    ss.close();
-  }
-
-  /** Checks that closing a Socket's input stream also closes the Socket and SocketChannel. */
-  public void test_channelSocketInputStreamClosureState() throws Exception {
-    ServerSocket ss = new ServerSocket(0);
-
-    SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
-    sc.configureBlocking(true);
-
-    Socket scSocket = sc.socket();
-    InputStream is = scSocket.getInputStream();
-
-    assertTrue(sc.isOpen());
-    assertFalse(scSocket.isClosed());
-
-    is.close();
-
-    assertFalse(sc.isOpen());
-    assertTrue(scSocket.isClosed());
-
-    ss.close();
-  }
-
-  /** Checks the state of the SocketChannel and associated Socket after open() */
-  public void test_open_initialState() throws Exception {
-    SocketChannel sc = SocketChannel.open();
-    try {
-      assertNull(sc.socket().getLocalSocketAddress());
-
-      Socket socket = sc.socket();
-      assertFalse(socket.isBound());
-      assertFalse(socket.isClosed());
-      assertFalse(socket.isConnected());
-      assertEquals(-1, socket.getLocalPort());
-      assertTrue(socket.getLocalAddress().isAnyLocalAddress());
-      assertNull(socket.getLocalSocketAddress());
-      assertNull(socket.getInetAddress());
-      assertEquals(0, socket.getPort());
-      assertNull(socket.getRemoteSocketAddress());
-      assertFalse(socket.getReuseAddress());
-
-      assertSame(sc, socket.getChannel());
-    } finally {
-      sc.close();
-    }
-  }
-
-  public void test_bind_unresolvedAddress() throws IOException {
-    SocketChannel sc = SocketChannel.open();
-    try {
-      sc.socket().bind(new InetSocketAddress("unresolvedname", 31415));
-      fail();
-    } catch (IOException expected) {
+        try {
+            sc.finishConnect();
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
     }
 
-    assertNull(sc.socket().getLocalSocketAddress());
-    assertTrue(sc.isOpen());
-    assertFalse(sc.isConnected());
+    /** Checks that closing a Socket's output stream also closes the Socket and SocketChannel. */
+    public void test_channelSocketOutputStreamClosureState() throws Exception {
+        ServerSocket ss = new ServerSocket(0);
 
-    sc.close();
-  }
+        SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
+        sc.configureBlocking(true);
 
-  /** Checks that the SocketChannel and associated Socket agree on the socket state. */
-  public void test_bind_socketStateSync() throws IOException {
-    SocketChannel sc = SocketChannel.open();
-    assertNull(sc.socket().getLocalSocketAddress());
+        Socket scSocket = sc.socket();
+        OutputStream os = scSocket.getOutputStream();
 
-    Socket socket = sc.socket();
-    assertNull(socket.getLocalSocketAddress());
-    assertFalse(socket.isBound());
+        assertTrue(sc.isOpen());
+        assertFalse(scSocket.isClosed());
 
-    InetSocketAddress bindAddr = new InetSocketAddress("localhost", 0);
-    sc.socket().bind(bindAddr);
+        os.close();
 
-    InetSocketAddress actualAddr = (InetSocketAddress) sc.socket().getLocalSocketAddress();
-    assertEquals(actualAddr, socket.getLocalSocketAddress());
-    assertEquals(bindAddr.getHostName(), actualAddr.getHostName());
-    assertTrue(socket.isBound());
-    assertFalse(socket.isConnected());
-    assertFalse(socket.isClosed());
+        assertFalse(sc.isOpen());
+        assertTrue(scSocket.isClosed());
 
-    sc.close();
+        ss.close();
+    }
 
-    assertFalse(sc.isOpen());
-    assertTrue(socket.isClosed());
-  }
+    /** Checks that closing a Socket's input stream also closes the Socket and SocketChannel. */
+    public void test_channelSocketInputStreamClosureState() throws Exception {
+        ServerSocket ss = new ServerSocket(0);
 
-  /**
-   * Checks that the SocketChannel and associated Socket agree on the socket state, even if
-   * the Socket object is requested/created after bind().
-   */
-  public void test_bind_socketObjectCreationAfterBind() throws IOException {
-    SocketChannel sc = SocketChannel.open();
-    assertNull(sc.socket().getLocalSocketAddress());
+        SocketChannel sc = SocketChannel.open(ss.getLocalSocketAddress());
+        sc.configureBlocking(true);
 
-    InetSocketAddress bindAddr = new InetSocketAddress("localhost", 0);
-    sc.socket().bind(bindAddr);
+        Socket scSocket = sc.socket();
+        InputStream is = scSocket.getInputStream();
 
-    // Socket object creation after bind().
-    Socket socket = sc.socket();
-    InetSocketAddress actualAddr = (InetSocketAddress) sc.socket().getLocalSocketAddress();
-    assertEquals(actualAddr, socket.getLocalSocketAddress());
-    assertEquals(bindAddr.getHostName(), actualAddr.getHostName());
-    assertTrue(socket.isBound());
-    assertFalse(socket.isConnected());
-    assertFalse(socket.isClosed());
+        assertTrue(sc.isOpen());
+        assertFalse(scSocket.isClosed());
 
-    sc.close();
+        is.close();
 
-    assertFalse(sc.isOpen());
-    assertTrue(socket.isClosed());
-  }
+        assertFalse(sc.isOpen());
+        assertTrue(scSocket.isClosed());
 
-  /**
-   * Tests connect() and object state for a blocking SocketChannel. Blocking mode is the default.
-   */
-  public void test_connect_blocking() throws Exception {
-    ServerSocket ss = new ServerSocket(0);
+        ss.close();
+    }
 
-    SocketChannel sc = SocketChannel.open();
-    assertTrue(sc.isBlocking());
+    /** Checks the state of the SocketChannel and associated Socket after open() */
+    public void test_open_initialState() throws Exception {
+        SocketChannel sc = SocketChannel.open();
+        try {
+            assertNull(sc.socket().getLocalSocketAddress());
 
-    assertTrue(sc.connect(ss.getLocalSocketAddress()));
+            Socket socket = sc.socket();
+            assertFalse(socket.isBound());
+            assertFalse(socket.isClosed());
+            assertFalse(socket.isConnected());
+            assertEquals(-1, socket.getLocalPort());
+            assertTrue(socket.getLocalAddress().isAnyLocalAddress());
+            assertNull(socket.getLocalSocketAddress());
+            assertNull(socket.getInetAddress());
+            assertEquals(0, socket.getPort());
+            assertNull(socket.getRemoteSocketAddress());
+            assertFalse(socket.getReuseAddress());
 
-    assertTrue(sc.socket().isBound());
-    assertTrue(sc.isConnected());
-    assertTrue(sc.socket().isConnected());
-    assertFalse(sc.socket().isClosed());
-    assertTrue(sc.isBlocking());
+            assertSame(sc, socket.getChannel());
+        } finally {
+            sc.close();
+        }
+    }
 
-    ss.close();
-    sc.close();
-  }
+    public void test_bind_unresolvedAddress() throws IOException {
+        SocketChannel sc = SocketChannel.open();
+        try {
+            sc.socket().bind(new InetSocketAddress("unresolvedname", 31415));
+            fail();
+        } catch (IOException expected) {
+        }
 
-  /** Tests connect() and object state for a non-blocking SocketChannel. */
-  public void test_connect_nonBlocking() throws Exception {
-    ServerSocket ss = new ServerSocket(0);
-
-    SocketChannel sc = SocketChannel.open();
-    assertTrue(sc.isBlocking());
-    sc.configureBlocking(false);
-    assertFalse(sc.isBlocking());
-
-    if (!sc.connect(ss.getLocalSocketAddress())) {
-      do {
-        assertTrue(sc.socket().isBound());
+        assertNull(sc.socket().getLocalSocketAddress());
+        assertTrue(sc.isOpen());
         assertFalse(sc.isConnected());
-        assertFalse(sc.socket().isConnected());
+
+        sc.close();
+    }
+
+    /** Checks that the SocketChannel and associated Socket agree on the socket state. */
+    public void test_bind_socketStateSync() throws IOException {
+        SocketChannel sc = SocketChannel.open();
+        assertNull(sc.socket().getLocalSocketAddress());
+
+        Socket socket = sc.socket();
+        assertNull(socket.getLocalSocketAddress());
+        assertFalse(socket.isBound());
+
+        InetSocketAddress bindAddr = new InetSocketAddress("localhost", 0);
+        sc.socket().bind(bindAddr);
+
+        InetSocketAddress actualAddr = (InetSocketAddress) sc.socket().getLocalSocketAddress();
+        assertEquals(actualAddr, socket.getLocalSocketAddress());
+        assertEquals(bindAddr.getHostName(), actualAddr.getHostName());
+        assertTrue(socket.isBound());
+        assertFalse(socket.isConnected());
+        assertFalse(socket.isClosed());
+
+        sc.close();
+
+        assertFalse(sc.isOpen());
+        assertTrue(socket.isClosed());
+    }
+
+    /**
+     * Checks that the SocketChannel and associated Socket agree on the socket state, even if
+     * the Socket object is requested/created after bind().
+     */
+    public void test_bind_socketObjectCreationAfterBind() throws IOException {
+        SocketChannel sc = SocketChannel.open();
+        assertNull(sc.socket().getLocalSocketAddress());
+
+        InetSocketAddress bindAddr = new InetSocketAddress("localhost", 0);
+        sc.socket().bind(bindAddr);
+
+        // Socket object creation after bind().
+        Socket socket = sc.socket();
+        InetSocketAddress actualAddr = (InetSocketAddress) sc.socket().getLocalSocketAddress();
+        assertEquals(actualAddr, socket.getLocalSocketAddress());
+        assertEquals(bindAddr.getHostName(), actualAddr.getHostName());
+        assertTrue(socket.isBound());
+        assertFalse(socket.isConnected());
+        assertFalse(socket.isClosed());
+
+        sc.close();
+
+        assertFalse(sc.isOpen());
+        assertTrue(socket.isClosed());
+    }
+
+    /**
+     * Tests connect() and object state for a blocking SocketChannel. Blocking mode is the default.
+     */
+    public void test_connect_blocking() throws Exception {
+        ServerSocket ss = new ServerSocket(0);
+
+        SocketChannel sc = SocketChannel.open();
+        assertTrue(sc.isBlocking());
+
+        assertTrue(sc.connect(ss.getLocalSocketAddress()));
+
+        assertTrue(sc.socket().isBound());
+        assertTrue(sc.isConnected());
+        assertTrue(sc.socket().isConnected());
         assertFalse(sc.socket().isClosed());
-      } while (!sc.finishConnect());
+        assertTrue(sc.isBlocking());
+
+        ss.close();
+        sc.close();
     }
-    assertTrue(sc.socket().isBound());
-    assertTrue(sc.isConnected());
-    assertTrue(sc.socket().isConnected());
-    assertFalse(sc.socket().isClosed());
-    assertFalse(sc.isBlocking());
 
-    ss.close();
-    sc.close();
-  }
+    /** Tests connect() and object state for a non-blocking SocketChannel. */
+    public void test_connect_nonBlocking() throws Exception {
+        ServerSocket ss = new ServerSocket(0);
 
-  public void test_Socket_impl_notNull() throws Exception {
-    SocketChannel sc = SocketChannel.open();
-    Socket socket = sc.socket();
-    Field f_impl = Socket.class.getDeclaredField("impl");
-    f_impl.setAccessible(true);
-    Object implFieldValue = f_impl.get(socket);
-    assertNotNull(implFieldValue);
-    assertTrue(implFieldValue instanceof SocketImpl);
-  }
+        SocketChannel sc = SocketChannel.open();
+        assertTrue(sc.isBlocking());
+        sc.configureBlocking(false);
+        assertFalse(sc.isBlocking());
 
-  public void test_setOption() throws Exception {
-    SocketChannel sc = SocketChannel.open();
-    sc.setOption(StandardSocketOptions.SO_LINGER, 1000);
+        if (!sc.connect(ss.getLocalSocketAddress())) {
+            do {
+                assertTrue(sc.socket().isBound());
+                assertFalse(sc.isConnected());
+                assertFalse(sc.socket().isConnected());
+                assertFalse(sc.socket().isClosed());
+            } while (!sc.finishConnect());
+        }
+        assertTrue(sc.socket().isBound());
+        assertTrue(sc.isConnected());
+        assertTrue(sc.socket().isConnected());
+        assertFalse(sc.socket().isClosed());
+        assertFalse(sc.isBlocking());
 
-    // Assert that we can read back the option from the channel...
-    assertEquals(1000, (int) sc.<Integer>getOption(StandardSocketOptions.SO_LINGER));
-    // ... and its socket adaptor.
-    assertEquals(1000, sc.socket().getSoLinger());
-
-    sc.close();
-    try {
-        sc.setOption(StandardSocketOptions.SO_LINGER, 2000);
-        fail();
-    } catch (ClosedChannelException expected) {
+        ss.close();
+        sc.close();
     }
-  }
+
+    public void test_Socket_impl_notNull() throws Exception {
+        SocketChannel sc = SocketChannel.open();
+        Socket socket = sc.socket();
+        Field f_impl = Socket.class.getDeclaredField("impl");
+        f_impl.setAccessible(true);
+        Object implFieldValue = f_impl.get(socket);
+        assertNotNull(implFieldValue);
+        assertTrue(implFieldValue instanceof SocketImpl);
+    }
+
+    public void test_setOption() throws Exception {
+        SocketChannel sc = SocketChannel.open();
+        sc.setOption(StandardSocketOptions.SO_LINGER, 1000);
+
+        // Assert that we can read back the option from the channel...
+        assertEquals(1000, (int) sc.<Integer>getOption(StandardSocketOptions.SO_LINGER));
+        // ... and its socket adaptor.
+        assertEquals(1000, sc.socket().getSoLinger());
+
+        sc.close();
+        try {
+            sc.setOption(StandardSocketOptions.SO_LINGER, 2000);
+            fail();
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    public void test_bind() throws IOException {
+        InetSocketAddress socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0);
+        SocketChannel sc = SocketChannel.open();
+        sc.bind(socketAddress);
+        assertEquals(socketAddress.getAddress(),
+                ((InetSocketAddress) (sc.getLocalAddress())).getAddress());
+        assertTrue(((InetSocketAddress) (sc.getLocalAddress())).getPort() > 0);
+
+        try {
+            sc.bind(socketAddress);
+            fail();
+        } catch (AlreadyBoundException expected) {
+        }
+
+        socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK,
+                ((InetSocketAddress) (sc.getLocalAddress())).getPort());
+        try {
+            SocketChannel.open().bind(socketAddress);
+            fail();
+        } catch (BindException expected) {
+        }
+
+        sc.close();
+        socketAddress = new InetSocketAddress(Inet4Address.LOOPBACK, 0);
+        try {
+            sc.bind(socketAddress);
+        } catch (ClosedChannelException expected) {
+        }
+    }
+
+    public void test_getRemoteAddress() throws IOException {
+        SocketChannel sc = SocketChannel.open();
+        ServerSocket ss = new ServerSocket(0);
+
+        assertNull(sc.getRemoteAddress());
+
+        sc.connect(ss.getLocalSocketAddress());
+        assertEquals(sc.getRemoteAddress(), ss.getLocalSocketAddress());
+    }
+
+    public void test_shutdownInput() throws IOException {
+        SocketChannel channel1 = SocketChannel.open();
+        ServerSocket server1 = new ServerSocket(0);
+        InetSocketAddress localAddr1 = new InetSocketAddress("127.0.0.1", server1.getLocalPort());
+
+        // initialize write content
+        byte[] writeContent = new byte[10];
+        for (int i = 0; i < writeContent.length; i++) {
+            writeContent[i] = (byte) i;
+        }
+
+        // establish connection
+        channel1.connect(localAddr1);
+        Socket acceptedSocket = server1.accept();
+        // use OutputStream.write to write bytes data.
+        OutputStream out = acceptedSocket.getOutputStream();
+        out.write(writeContent);
+        // use close to guarantee all data is sent
+        acceptedSocket.close();
+
+        channel1.configureBlocking(false);
+        ByteBuffer readContent = ByteBuffer.allocate(10 + 1);
+        channel1.shutdownInput();
+        assertEquals(-1, channel1.read(readContent));
+    }
+
+    public void test_shutdownOutput() throws IOException {
+        SocketChannel channel1 = SocketChannel.open();
+        ServerSocket server1 = new ServerSocket(0);
+        InetSocketAddress localAddr1 = new InetSocketAddress("127.0.0.1", server1.getLocalPort());
+
+        // initialize write content
+        ByteBuffer writeContent = ByteBuffer.allocate(10);
+        for (int i = 0; i < 10; i++) {
+            writeContent.put((byte) i);
+        }
+        writeContent.flip();
+
+        try {
+            channel1.shutdownOutput();
+            fail();
+        } catch (NotYetConnectedException expected) {}
+
+        // establish connection
+        channel1.connect(localAddr1);
+        channel1.shutdownOutput();
+
+        try {
+            channel1.write(writeContent);
+            fail();
+        } catch (ClosedChannelException expected) {}
+
+        channel1.close();
+
+        try {
+            channel1.shutdownOutput();
+            fail();
+        } catch(ClosedChannelException expected) {}
+    }
 }
diff --git a/luni/src/test/java/libcore/java/security/ProviderTest.java b/luni/src/test/java/libcore/java/security/ProviderTest.java
index d3ccae1..7d9e633 100644
--- a/luni/src/test/java/libcore/java/security/ProviderTest.java
+++ b/luni/src/test/java/libcore/java/security/ProviderTest.java
@@ -38,6 +38,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
@@ -45,6 +46,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import javax.crypto.Cipher;
+import javax.crypto.EncryptedPrivateKeyInfo;
 import javax.crypto.NoSuchPaddingException;
 import junit.framework.TestCase;
 import libcore.javax.crypto.MockKey;
@@ -550,6 +552,58 @@
         }
     }
 
+    @SuppressWarnings("serial")
+    public void testProviderService_AliasDoesNotEraseCanonical_Success()
+            throws Exception {
+        // Make sure we start with a "known good" alias for this OID.
+        {
+            EncryptedPrivateKeyInfo epki1 = new EncryptedPrivateKeyInfo("OID.1.2.840.113549.1.1.5",
+                    new byte[1]);
+            assertEquals("SHA1WITHRSA", epki1.getAlgName().toUpperCase(Locale.US));
+        }
+
+        Provider provider = new MockProvider("MockProvider") {
+            public void setup() {
+                put("Signature.FOO", MockSpi.class.getName());
+                put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.5", "FOO");
+            }
+        };
+
+        Security.addProvider(provider);
+        try {
+            // This triggers a re-indexing of the algorithm id data:
+            try {
+                new EncryptedPrivateKeyInfo("nonexistent", new byte[1]);
+                fail("Should not find 'nonexistent' algorithm");
+            } catch (NoSuchAlgorithmException expected) {
+            }
+
+            EncryptedPrivateKeyInfo epki2 = new EncryptedPrivateKeyInfo("OID.1.2.840.113549.1.1.5", new byte[1]);
+            assertEquals("SHA1WITHRSA", epki2.getAlgName().toUpperCase(Locale.US));
+        } finally {
+            Security.removeProvider(provider.getName());
+        }
+    }
+
+    @SuppressWarnings("serial")
+    public void testProviderService_CanFindNewOID_Success()
+            throws Exception {
+        Provider provider = new MockProvider("MockProvider") {
+            public void setup() {
+                put("Signature.NEWALG", MockSpi.class.getName());
+                put("Alg.Alias.Signature.OID.1.2.9999.9999.9999", "NEWALG");
+            }
+        };
+
+        Security.addProvider(provider);
+        try {
+            EncryptedPrivateKeyInfo epki2 = new EncryptedPrivateKeyInfo("OID.1.2.9999.9999.9999", new byte[1]);
+            assertEquals("NEWALG", epki2.getAlgName().toUpperCase(Locale.US));
+        } finally {
+            Security.removeProvider(provider.getName());
+        }
+    }
+
     public void testProvider_removeProvider_Success() throws Exception {
         MockProvider provider = new MockProvider("MockProvider");
         assertNull(Security.getProvider(provider.getName()));
diff --git a/luni/src/test/java/libcore/java/security/cert/PKIXRevocationCheckerTest.java b/luni/src/test/java/libcore/java/security/cert/PKIXRevocationCheckerTest.java
new file mode 100644
index 0000000..4b10030
--- /dev/null
+++ b/luni/src/test/java/libcore/java/security/cert/PKIXRevocationCheckerTest.java
@@ -0,0 +1,109 @@
+package libcore.java.security.cert;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.security.KeyStore.PrivateKeyEntry;
+import java.security.cert.CertPathBuilder;
+import java.security.cert.CertPathChecker;
+import java.security.cert.Extension;
+import java.security.cert.PKIXRevocationChecker;
+import java.security.cert.PKIXRevocationChecker.Option;
+import java.security.cert.X509Certificate;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Map;
+
+import junit.framework.TestCase;
+import libcore.java.security.TestKeyStore;
+
+public class PKIXRevocationCheckerTest extends TestCase {
+    PKIXRevocationChecker checker;
+
+    PrivateKeyEntry entity;
+
+    PrivateKeyEntry issuer;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
+        CertPathChecker rc = cpb.getRevocationChecker();
+        assertNotNull(rc);
+        assertTrue(rc instanceof PKIXRevocationChecker);
+        checker = (PKIXRevocationChecker) rc;
+
+        TestKeyStore server = TestKeyStore.getServer();
+        TestKeyStore intermediate = TestKeyStore.getIntermediateCa();
+
+        entity = server.getPrivateKey("RSA", "RSA");
+        issuer = intermediate.getPrivateKey("RSA", "RSA");
+    }
+
+    public void test_Initializes() throws Exception {
+        assertEquals(0, checker.getOcspResponses().size());
+        assertEquals(0, checker.getOcspExtensions().size());
+        assertEquals(0, checker.getOptions().size());
+        assertEquals(0, checker.getSoftFailExceptions().size());
+        assertNull(checker.getSupportedExtensions());
+        assertNull(checker.getOcspResponderCert());
+        assertNull(checker.getOcspResponder());
+    }
+
+    public void test_CanSetOCSPResponse() throws Exception {
+        byte[] goodOCSPResponse = TestKeyStore.getOCSPResponseForGood(entity, issuer);
+
+        Map<X509Certificate, byte[]> ocspResponses = Collections
+                .singletonMap((X509Certificate) entity.getCertificate(), goodOCSPResponse);
+        checker.setOcspResponses(ocspResponses);
+
+        Map<X509Certificate, byte[]> returnedResponses = checker.getOcspResponses();
+        assertEquals(1, returnedResponses.size());
+        byte[] returnedResponse = returnedResponses.get(entity.getCertificate());
+        assertNotNull(returnedResponse);
+        assertEquals(Arrays.toString(goodOCSPResponse), Arrays.toString(returnedResponse));
+    }
+
+    public void test_getOcspResponder() throws Exception {
+        URI url = new URI("http://localhost/");
+        checker.setOcspResponder(url);
+        assertEquals(url, checker.getOcspResponder());
+    }
+
+    public void test_getOcspResponderCert() throws Exception {
+        checker.setOcspResponderCert((X509Certificate) issuer.getCertificate());
+        assertEquals((X509Certificate) issuer.getCertificate(), checker.getOcspResponderCert());
+    }
+
+    public void test_getOptions() throws Exception {
+        checker.setOptions(Collections.singleton(Option.SOFT_FAIL));
+        assertEquals(Collections.singleton(Option.SOFT_FAIL), checker.getOptions());
+    }
+
+    public void test_getOcspExtensions() throws Exception {
+        checker.setOcspExtensions(Collections.singletonList(new Extension() {
+            @Override
+            public boolean isCritical() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public byte[] getValue() {
+                throw new UnsupportedOperationException();
+            }
+
+            @Override
+            public String getId() {
+                return "TestExtension";
+            }
+
+            @Override
+            public void encode(OutputStream out) throws IOException {
+                throw new UnsupportedOperationException();
+            }
+        }));
+        assertEquals(1, checker.getOcspExtensions().size());
+        assertEquals("TestExtension", checker.getOcspExtensions().get(0).getId());
+    }
+}
diff --git a/luni/src/test/java/libcore/java/util/LinkedHashMapTest.java b/luni/src/test/java/libcore/java/util/LinkedHashMapTest.java
index c7de1f6..e82e66d 100644
--- a/luni/src/test/java/libcore/java/util/LinkedHashMapTest.java
+++ b/luni/src/test/java/libcore/java/util/LinkedHashMapTest.java
@@ -18,6 +18,8 @@
 
 import java.util.LinkedHashMap;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 public class LinkedHashMapTest extends junit.framework.TestCase {
 
@@ -205,4 +207,31 @@
         assertEquals("key1", newest.getKey());
         assertEquals("value3", newest.getValue());
     }
+
+    // http://b/27929722
+    // This tests the behaviour is consistent with earlier Android releases.
+    // This behaviour is NOT consistent with the RI. Future Android releases
+    // might change this.
+    public void test_removeEldestEntry() {
+        final AtomicBoolean removeEldestEntryReturnValue = new AtomicBoolean(false);
+        final AtomicInteger removeEldestEntryCallCount = new AtomicInteger(0);
+        LinkedHashMap<String, String> m = new LinkedHashMap<String, String>() {
+            @Override
+            protected boolean removeEldestEntry(Entry eldest) {
+                removeEldestEntryCallCount.incrementAndGet();
+                return removeEldestEntryReturnValue.get();
+            }
+        };
+
+        m.put("foo", "bar");
+        assertEquals(0, removeEldestEntryCallCount.get());
+        m.put("baz", "quux");
+        assertEquals(1, removeEldestEntryCallCount.get());
+
+        removeEldestEntryReturnValue.set(true);
+        m.put("foob", "faab");
+        assertEquals(2, removeEldestEntryCallCount.get());
+        assertEquals(2, m.size());
+        assertFalse(m.containsKey("foo"));
+    }
 }
diff --git a/luni/src/test/java/tests/security/cert/CertPathValidatorExceptionTest.java b/luni/src/test/java/tests/security/cert/CertPathValidatorExceptionTest.java
index 1eac1f7..1f45443 100644
--- a/luni/src/test/java/tests/security/cert/CertPathValidatorExceptionTest.java
+++ b/luni/src/test/java/tests/security/cert/CertPathValidatorExceptionTest.java
@@ -24,9 +24,14 @@
 
 import junit.framework.TestCase;
 
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.doReturn;
+
 import java.security.cert.CertPath;
 import java.security.cert.CertPathValidatorException;
+import java.security.cert.CertPathValidatorException.BasicReason;
 import java.security.cert.Certificate;
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
 import java.util.StringTokenizer;
@@ -431,6 +436,27 @@
         }
     }
 
+    public void testCertPathValidatorException_constructsCorrectlyWithReason() throws Exception {
+        Throwable cause = mock(Throwable.class);
+        CertPath certPath = mock(CertPath.class);
+
+        Certificate cert1 = mock(Certificate.class);
+        Certificate cert2 = mock(Certificate.class);
+        List<Certificate> certList = new ArrayList<Certificate>();
+        certList.add(cert1);
+        certList.add(cert2);
+        doReturn(certList).when(certPath).getCertificates();
+
+        CertPathValidatorException exception = new CertPathValidatorException("Test exception",
+                cause, certPath, 1, BasicReason.REVOKED);
+
+        assertEquals("Test exception", exception.getMessage());
+        assertEquals(cause, exception.getCause());
+        assertEquals(certPath, exception.getCertPath());
+        assertEquals(1, exception.getIndex());
+        assertEquals(BasicReason.REVOKED, exception.getReason());
+    }
+
     class myCertPath extends CertPath {
 
         private static final long serialVersionUID = 5871603047244722511L;
diff --git a/luni/src/test/java/tests/security/cert/CertPathValidatorSpiTest.java b/luni/src/test/java/tests/security/cert/CertPathValidatorSpiTest.java
deleted file mode 100644
index f69a3e5..0000000
--- a/luni/src/test/java/tests/security/cert/CertPathValidatorSpiTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  See the NOTICE file distributed with
- *  this work for additional information regarding copyright ownership.
- *  The ASF licenses this file to You 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.
- */
-
-/**
-* @author Vera Y. Petrashkova
-* @version $Revision$
-*/
-
-package tests.security.cert;
-
-import junit.framework.TestCase;
-
-import java.security.InvalidAlgorithmParameterException;
-import java.security.cert.CertPath;
-import java.security.cert.CertPathParameters;
-import java.security.cert.CertPathValidatorException;
-import java.security.cert.CertPathValidatorResult;
-import java.security.cert.CertPathValidatorSpi;
-
-import org.apache.harmony.security.tests.support.cert.MyCertPathValidatorSpi;
-/**
- * Tests for <code>CertPathValidatorSpi</code> class constructors and methods.
- *
- */
-public class CertPathValidatorSpiTest extends TestCase {
-
-    /**
-     * Test for <code>CertPathValidatorSpi</code> constructor Assertion:
-     * constructs CertPathValidatorSpi
-     */
-    public void testCertPathValidatorSpi01() throws CertPathValidatorException,
-            InvalidAlgorithmParameterException {
-        CertPathValidatorSpi certPathValid = new MyCertPathValidatorSpi();
-        CertPathParameters params = null;
-        CertPath certPath = null;
-        CertPathValidatorResult cpvResult = certPathValid.engineValidate(
-                certPath, params);
-        assertNull("Not null CertPathValidatorResult", cpvResult);
-        try {
-            certPathValid.engineValidate(certPath, params);
-            fail("CertPathValidatorException must be thrown");
-        } catch (CertPathValidatorException e) {
-        }
-        try {
-            certPathValid.engineValidate(certPath, params);
-            fail("InvalidAlgorithmParameterException must be thrown");
-        } catch (InvalidAlgorithmParameterException e) {
-        }
-    }
-}
diff --git a/luni/src/test/java/tests/security/cert/CertificateRevocationExceptionTest.java b/luni/src/test/java/tests/security/cert/CertificateRevocationExceptionTest.java
index c3894f8..3951da6 100644
--- a/luni/src/test/java/tests/security/cert/CertificateRevocationExceptionTest.java
+++ b/luni/src/test/java/tests/security/cert/CertificateRevocationExceptionTest.java
@@ -130,6 +130,10 @@
         assertTrue(firstDate.compareTo(exception.getInvalidityDate()) > 0);
     }
 
+    public void testGetAuthorityName() throws Exception {
+        CertificateRevokedException exception = getTestException();
+        assertEquals(new X500Principal("CN=test1"), exception.getAuthorityName());
+    }
 
     /**
      * serialization/deserialization compatibility.
@@ -160,6 +164,8 @@
         assertEquals(expected.getRevocationDate(), actual.getRevocationDate());
         assertNotSame(expected.getRevocationDate(), actual.getRevocationDate());
         assertEquals(expected.getRevocationReason(), expected.getRevocationReason());
+        assertEquals(expected.getAuthorityName(), actual.getAuthorityName());
+        assertNotSame(expected.getAuthorityName(), actual.getAuthorityName());
 
         assertEquals(expected.getExtensions().size(), actual.getExtensions().size());
         assertEquals(expected.getExtensions().keySet(), actual.getExtensions().keySet());
diff --git a/ojluni/src/main/java/java/lang/Boolean.java b/ojluni/src/main/java/java/lang/Boolean.java
index 64d732e..cac469b 100755
--- a/ojluni/src/main/java/java/lang/Boolean.java
+++ b/ojluni/src/main/java/java/lang/Boolean.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -201,6 +201,18 @@
     }
 
     /**
+     * Returns a hash code for a {@code boolean} value; compatible with
+     * {@code Boolean.hashCode()}.
+     *
+     * @param value the value to hash
+     * @return a hash code value for a {@code boolean} value.
+     * @since 1.8
+     */
+    public static int hashCode(boolean value) {
+        return value ? 1231 : 1237;
+    }
+
+   /**
      * Returns {@code true} if and only if the argument is not
      * {@code null} and is a {@code Boolean} object that
      * represents the same {@code boolean} value as this object.
diff --git a/ojluni/src/main/java/java/lang/Byte.java b/ojluni/src/main/java/java/lang/Byte.java
index a753b4b..47ad37e 100755
--- a/ojluni/src/main/java/java/lang/Byte.java
+++ b/ojluni/src/main/java/java/lang/Byte.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -385,6 +385,18 @@
      * @return a hash code value for this {@code Byte}
      */
     public int hashCode() {
+        return Byte.hashCode(value);
+    }
+
+    /**
+     * Returns a hash code for a {@code byte} value; compatible with
+     * {@code Byte.hashCode()}.
+     *
+     * @param value the value to hash
+     * @return a hash code value for a {@code byte} value.
+     * @since 1.8
+     */
+    public static int hashCode(byte value) {
         return (int)value;
     }
 
@@ -448,6 +460,14 @@
      */
     public static final int SIZE = 8;
 
+    /**
+     * The number of bytes used to represent a {@code byte} value in two's
+     * complement binary form.
+     *
+     * @since 1.8
+     */
+    public static final int BYTES = SIZE / Byte.SIZE;
+
     /** use serialVersionUID from JDK 1.1. for interoperability */
     private static final long serialVersionUID = -7183698231559129828L;
 
diff --git a/ojluni/src/main/java/java/lang/Character.java b/ojluni/src/main/java/java/lang/Character.java
index b7f2c2a..bb69d91 100755
--- a/ojluni/src/main/java/java/lang/Character.java
+++ b/ojluni/src/main/java/java/lang/Character.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -4433,6 +4433,19 @@
      * @return a hash code value for this {@code Character}
      */
     public int hashCode() {
+        return Character.hashCode(value);
+    }
+
+    /**
+     * Returns a hash code for a {@code char} value; compatible with
+     * {@code Character.hashCode()}.
+     *
+     * @since 1.8
+     *
+     * @param value The {@code char} for which to return a hash code.
+     * @return a hash code value for a {@code char} value.
+     */
+    public static int hashCode(char value) {
         return (int)value;
     }
 
@@ -7101,6 +7114,14 @@
     public static final int SIZE = 16;
 
     /**
+     * The number of bytes used to represent a {@code char} value in unsigned
+     * binary form.
+     *
+     * @since 1.8
+     */
+    public static final int BYTES = SIZE / Byte.SIZE;
+
+    /**
      * Returns the value obtained by reversing the order of the bytes in the
      * specified <tt>char</tt> value.
      *
diff --git a/ojluni/src/main/java/java/lang/Double.java b/ojluni/src/main/java/java/lang/Double.java
index 50712c4..59f8088 100755
--- a/ojluni/src/main/java/java/lang/Double.java
+++ b/ojluni/src/main/java/java/lang/Double.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/lang/Float.java b/ojluni/src/main/java/java/lang/Float.java
index 3b513c9..d75953e 100755
--- a/ojluni/src/main/java/java/lang/Float.java
+++ b/ojluni/src/main/java/java/lang/Float.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -122,6 +122,13 @@
     public static final int SIZE = 32;
 
     /**
+     * The number of bytes used to represent a {@code float} value.
+     *
+     * @since 1.8
+     */
+    public static final int BYTES = SIZE / Byte.SIZE;
+
+    /**
      * The {@code Class} instance representing the primitive type
      * {@code float}.
      *
@@ -648,6 +655,18 @@
     }
 
     /**
+     * Returns a hash code for a {@code float} value; compatible with
+     * {@code Float.hashCode()}.
+     *
+     * @param value the value to hash
+     * @return a hash code value for a {@code float} value.
+     * @since 1.8
+     */
+    public static int hashCode(float value) {
+        return floatToIntBits(value);
+    }
+
+    /**
 
      * Compares this object against the specified object.  The result
      * is {@code true} if and only if the argument is not
@@ -901,6 +920,48 @@
                  1));                          // (0.0, -0.0) or (NaN, !NaN)
     }
 
+    /**
+     * Adds two {@code float} values together as per the + operator.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the sum of {@code a} and {@code b}
+     * @jls 4.2.4 Floating-Point Operations
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static float sum(float a, float b) {
+        return a + b;
+    }
+
+    /**
+     * Returns the greater of two {@code float} values
+     * as if by calling {@link Math#max(float, float) Math.max}.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the greater of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static float max(float a, float b) {
+        return Math.max(a, b);
+    }
+
+    /**
+     * Returns the smaller of two {@code float} values
+     * as if by calling {@link Math#min(float, float) Math.min}.
+     *
+     * @param a the first operand
+     * @param b the second operand
+     * @return the smaller of {@code a} and {@code b}
+     * @see java.util.function.BinaryOperator
+     * @since 1.8
+     */
+    public static float min(float a, float b) {
+        return Math.min(a, b);
+    }
+
     /** use serialVersionUID from JDK 1.0.2 for interoperability */
     private static final long serialVersionUID = -2671257302660747028L;
 }
diff --git a/ojluni/src/main/java/java/lang/Integer.java b/ojluni/src/main/java/java/lang/Integer.java
index 2b573e7..fe36907 100755
--- a/ojluni/src/main/java/java/lang/Integer.java
+++ b/ojluni/src/main/java/java/lang/Integer.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
diff --git a/ojluni/src/main/java/java/lang/Long.java b/ojluni/src/main/java/java/lang/Long.java
index c40be4a..bf123c0 100755
--- a/ojluni/src/main/java/java/lang/Long.java
+++ b/ojluni/src/main/java/java/lang/Long.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1994, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -997,6 +997,14 @@
     public static final int SIZE = 64;
 
     /**
+     * The number of bytes used to represent a {@code long} value in two's
+     * complement binary form.
+     *
+     * @since 1.8
+     */
+    public static final int BYTES = SIZE / Byte.SIZE;
+
+    /**
      * Returns a {@code long} value with at most a single one-bit, in the
      * position of the highest-order ("leftmost") one-bit in the specified
      * {@code long} value.  Returns zero if the specified value has no
diff --git a/ojluni/src/main/java/java/lang/Short.java b/ojluni/src/main/java/java/lang/Short.java
index 8b002c5..c701d81 100755
--- a/ojluni/src/main/java/java/lang/Short.java
+++ b/ojluni/src/main/java/java/lang/Short.java
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2014 The Android Open Source Project
- * Copyright (c) 1996, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -390,6 +390,18 @@
      * @return a hash code value for this {@code Short}
      */
     public int hashCode() {
+        return Short.hashCode(value);
+    }
+
+    /**
+     * Returns a hash code for a {@code short} value; compatible with
+     * {@code Short.hashCode()}.
+     *
+     * @param value the value to hash
+     * @return a hash code value for a {@code short} value.
+     * @since 1.8
+     */
+    public static int hashCode(short value) {
         return (int)value;
     }
 
@@ -453,6 +465,14 @@
     public static final int SIZE = 16;
 
     /**
+     * The number of bytes used to represent a {@code short} value in two's
+     * complement binary form.
+     *
+     * @since 1.8
+     */
+    public static final int BYTES = SIZE / Byte.SIZE;
+
+    /**
      * Returns the value obtained by reversing the order of the bytes in the
      * two's complement representation of the specified {@code short} value.
      *
diff --git a/ojluni/src/main/java/java/net/URL.java b/ojluni/src/main/java/java/net/URL.java
index b585e2b..70825a0 100755
--- a/ojluni/src/main/java/java/net/URL.java
+++ b/ojluni/src/main/java/java/net/URL.java
@@ -708,7 +708,7 @@
             this.protocol = protocol;
             this.host = host;
             this.port = port;
-            this.file = query == null ? path : path + "?" + query;
+            this.file = (query == null || query.isEmpty()) ? path : path + "?" + query;
             this.userInfo = userInfo;
             this.path = path;
             this.ref = ref;
diff --git a/ojluni/src/main/java/java/net/URLStreamHandler.java b/ojluni/src/main/java/java/net/URLStreamHandler.java
index e64b9b8..e177363 100755
--- a/ojluni/src/main/java/java/net/URLStreamHandler.java
+++ b/ojluni/src/main/java/java/net/URLStreamHandler.java
@@ -337,6 +337,10 @@
             // Remove trailing .
             if (path.endsWith("/."))
                 path = path.substring(0, path.length() -1);
+
+            // Remove trailing ?
+            if (path.endsWith("?"))
+                path = path.substring(0, path.length() -1);
         }
 
         setURL(u, protocol, host, port, authority, userInfo, path, query, ref);
diff --git a/ojluni/src/main/java/java/nio/channels/ServerSocketChannel.java b/ojluni/src/main/java/java/nio/channels/ServerSocketChannel.java
index 127fb5b..63ed42f 100755
--- a/ojluni/src/main/java/java/nio/channels/ServerSocketChannel.java
+++ b/ojluni/src/main/java/java/nio/channels/ServerSocketChannel.java
@@ -138,7 +138,7 @@
      * @return  This channel
      *
      * @throws  AlreadyBoundException               {@inheritDoc}
-     * @throws  UnsupportedAddressTypeException     {@inheritDoc}
+     * @throws  UnresolvedAddressException
      * @throws  ClosedChannelException              {@inheritDoc}
      * @throws  IOException                         {@inheritDoc}
      * @throws  SecurityException
diff --git a/ojluni/src/main/java/java/security/Permission.java b/ojluni/src/main/java/java/security/Permission.java
index 1d8e7f5..9f04ac4 100755
--- a/ojluni/src/main/java/java/security/Permission.java
+++ b/ojluni/src/main/java/java/security/Permission.java
@@ -41,5 +41,5 @@
 
     public abstract String getActions();
 
-    public PermissionCollection newPermissionCollection() { return null; }
+    public PermissionCollection newPermissionCollection() { return new Permissions(); }
 }
diff --git a/ojluni/src/main/java/java/util/LinkedHashMap.java b/ojluni/src/main/java/java/util/LinkedHashMap.java
index 81b8a7a..7853d46 100755
--- a/ojluni/src/main/java/java/util/LinkedHashMap.java
+++ b/ojluni/src/main/java/java/util/LinkedHashMap.java
@@ -440,13 +440,27 @@
      * removes the eldest entry if appropriate.
      */
     void addEntry(int hash, K key, V value, int bucketIndex) {
-        super.addEntry(hash, key, value, bucketIndex);
+        // Previous Android releases called removeEldestEntry() before actually
+        // inserting a value but after increasing the size.
+        // The RI is documented to call it afterwards.
+        // **** THIS CHANGE WILL BE REVERTED IN A FUTURE ANDROID RELEASE ****
 
         // Remove eldest entry if instructed
         LinkedHashMapEntry<K,V> eldest = header.after;
-        if (removeEldestEntry(eldest)) {
-            removeEntryForKey(eldest.key);
+        if (eldest != header) {
+            boolean removeEldest;
+            size++;
+            try {
+                removeEldest = removeEldestEntry(eldest);
+            } finally {
+                size--;
+            }
+            if (removeEldest) {
+                removeEntryForKey(eldest.key);
+            }
         }
+
+        super.addEntry(hash, key, value, bucketIndex);
     }
 
     /**
@@ -473,7 +487,12 @@
         size++;
     }
 
-    /**
+    // Intentionally make this not JavaDoc, as the we don't conform to
+    // the behaviour documented here (we call removeEldestEntry before
+    // inserting the new value to be consistent with previous Android
+    // releases).
+    // **** THIS CHANGE WILL BE REVERTED IN A FUTURE ANDROID RELEASE ****
+    /*
      * Returns <tt>true</tt> if this map should remove its eldest entry.
      * This method is invoked by <tt>put</tt> and <tt>putAll</tt> after
      * inserting a new entry into the map.  It provides the implementor
diff --git a/ojluni/src/main/java/sun/security/x509/AlgorithmId.java b/ojluni/src/main/java/sun/security/x509/AlgorithmId.java
index 620a13d..f2de8ab 100755
--- a/ojluni/src/main/java/sun/security/x509/AlgorithmId.java
+++ b/ojluni/src/main/java/sun/security/x509/AlgorithmId.java
@@ -250,6 +250,13 @@
                 // ignore
             }
         }
+
+        // Try to update the name <-> OID mapping table.
+        synchronized (oidTable) {
+            reinitializeMappingTableLocked();
+            algName = nameTable.get(algid);
+        }
+
         return (algName == null) ? algid.toString() : algName;
     }
 
@@ -547,58 +554,73 @@
 
         // See if any of the installed providers supply a mapping from
         // the given algorithm name to an OID string
-        String oidString;
         synchronized (oidTable) {
-            // Android-changed: Update the table only if the OID changed. Also synchronize
-            // on oidTable for thread safety.
-            int currentVersion = Security.getVersion();
-            if (initOidTableVersion != currentVersion) {
-                Provider[] provs = Security.getProviders();
-                for (int i=0; i<provs.length; i++) {
-                    for (Enumeration<Object> enum_ = provs[i].keys();
-                         enum_.hasMoreElements(); ) {
-                        String alias = (String)enum_.nextElement();
-                        String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH);
-                        int index;
-                        if (upperCaseAlias.startsWith("ALG.ALIAS")) {
-                            if ((index=upperCaseAlias.indexOf("OID.", 0)) != -1) {
-                                index += "OID.".length();
-                                if (index == alias.length()) {
-                                    // invalid alias entry
-                                    break;
-                                }
-                                oidString = alias.substring(index);
-                                String stdAlgName = provs[i].getProperty(alias);
-                                if (stdAlgName != null) {
-                                    stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH);
-                                }
-                                if (stdAlgName != null &&
-                                        oidTable.get(stdAlgName) == null) {
-                                    ObjectIdentifier oid =
-                                        new ObjectIdentifier(oidString);
-                                    oidTable.put(stdAlgName, oid);
-                                    nameTable.put(oid, stdAlgName);
-                                }
-                            } else {
-                                // Android-changed: If the alias isn't specified with an explicit
-                                // "OID." in the name, we still attempt to parse it as one.
-                                final int sep = alias.indexOf('.', "ALG.ALIAS.".length());
-                                String suffix = alias.substring(sep + 1);
+            reinitializeMappingTableLocked();
+            return oidTable.get(name.toUpperCase(Locale.ENGLISH));
+        }
+    }
+
+    private static void reinitializeMappingTableLocked() {
+        // Android-changed: Update the table only if the OID changed. Also synchronize
+        // on oidTable for thread safety.
+        int currentVersion = Security.getVersion();
+        if (initOidTableVersion != currentVersion) {
+            Provider[] provs = Security.getProviders();
+            for (int i=0; i<provs.length; i++) {
+                for (Enumeration<Object> enum_ = provs[i].keys();
+                     enum_.hasMoreElements(); ) {
+                    String alias = (String)enum_.nextElement();
+                    String upperCaseAlias = alias.toUpperCase(Locale.ENGLISH);
+                    int index;
+                    if (upperCaseAlias.startsWith("ALG.ALIAS")) {
+                        if ((index=upperCaseAlias.indexOf("OID.", 0)) != -1) {
+                            index += "OID.".length();
+                            if (index == alias.length()) {
+                                // invalid alias entry
+                                break;
+                            }
+                            String oidString = alias.substring(index);
+                            String stdAlgName = provs[i].getProperty(alias);
+                            if (stdAlgName != null) {
+                                stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH);
 
                                 ObjectIdentifier oid = null;
                                 try {
-                                    oid = new ObjectIdentifier(suffix);
+                                    oid = new ObjectIdentifier(oidString);
                                 } catch (IOException e) {
                                     // Not an OID.
                                 }
 
                                 if (oid != null) {
-                                    String stdAlgName = provs[i].getProperty(alias);
-                                    if (stdAlgName != null) {
-                                        stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH);
-                                    }
-                                    if (stdAlgName != null && oidTable.get(stdAlgName) == null) {
+                                    if (!oidTable.containsKey(stdAlgName)) {
                                         oidTable.put(stdAlgName, oid);
+                                    }
+                                    if (!nameTable.containsKey(oid)) {
+                                        nameTable.put(oid, stdAlgName);
+                                    }
+                                }
+                            }
+                        } else {
+                            // Android-changed: If the alias isn't specified with an explicit
+                            // "OID." in the name, we still attempt to parse it as one.
+                            final int sep = alias.indexOf('.', "ALG.ALIAS.".length());
+                            String suffix = alias.substring(sep + 1);
+
+                            ObjectIdentifier oid = null;
+                            try {
+                                oid = new ObjectIdentifier(suffix);
+                            } catch (IOException e) {
+                                // Not an OID.
+                            }
+
+                            if (oid != null) {
+                                String stdAlgName = provs[i].getProperty(alias);
+                                if (stdAlgName != null) {
+                                    stdAlgName = stdAlgName.toUpperCase(Locale.ENGLISH);
+                                    if (!oidTable.containsKey(stdAlgName)) {
+                                        oidTable.put(stdAlgName, oid);
+                                    }
+                                    if (!nameTable.containsKey(oid)) {
                                         nameTable.put(oid, stdAlgName);
                                     }
                                 }
@@ -606,11 +628,9 @@
                         }
                     }
                 }
-
-                initOidTableVersion = currentVersion;
             }
 
-            return oidTable.get(name.toUpperCase(Locale.ENGLISH));
+            initOidTableVersion = currentVersion;
         }
     }
 
diff --git a/ojluni/src/main/native/DatagramChannelImpl.c b/ojluni/src/main/native/DatagramChannelImpl.c
index 473a98d..471c62b 100644
--- a/ojluni/src/main/native/DatagramChannelImpl.c
+++ b/ojluni/src/main/native/DatagramChannelImpl.c
@@ -169,6 +169,15 @@
         }
     } while (retry == JNI_TRUE);
 
+    // Peer (or other thread) has performed an orderly shutdown, sockaddr will be
+    // invalid.
+    if (n == 0) {
+        // zero the sender field, so receive() returns null and not
+        // random garbage
+        (*env)->SetObjectField(env, this, dci_senderID, NULL);
+        return n;
+    }
+
     /*
      * If the source address and port match the cached address
      * and port in DatagramChannelImpl then we don't need to
diff --git a/ojluni/src/main/native/Inet4AddressImpl.c b/ojluni/src/main/native/Inet4AddressImpl.c
index c424337..2856576 100755
--- a/ojluni/src/main/native/Inet4AddressImpl.c
+++ b/ojluni/src/main/native/Inet4AddressImpl.c
@@ -99,6 +99,7 @@
     if (netif != NULL) {
       if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
         NET_ThrowNew(env, errno, "Can't bind socket");
+        untagSocket(env, fd);
         close(fd);
         return JNI_FALSE;
       }
@@ -137,6 +138,7 @@
            */
 #endif /*__linux__ */
           NET_ThrowNew(env, errno, "Can't send ICMP packet");
+        untagSocket(env, fd);
         close(fd);
         return JNI_FALSE;
       }
@@ -158,11 +160,13 @@
           if (icmplen >= 8 && icmp->icmp_type == ICMP_ECHOREPLY
                && (ntohs(icmp->icmp_id) == pid)) {
             if ((him->sin_addr.s_addr == sa_recv.sin_addr.s_addr)) {
+              untagSocket(env, fd);
               close(fd);
               return JNI_TRUE;
             }
 
             if (him->sin_addr.s_addr == 0) {
+              untagSocket(env, fd);
               close(fd);
               return JNI_TRUE;
             }
@@ -172,6 +176,7 @@
       } while (tmout2 > 0);
       timeout -= 1000;
     } while (timeout >0);
+    untagSocket(env, fd);
     close(fd);
     return JNI_FALSE;
 }
@@ -240,6 +245,7 @@
       /*
        * It didn't fail, so we can use ICMP_ECHO requests.
        */
+      tagSocket(env, fd);
       return ping4(env, fd, &him, timeout, netif, ttl);
     }
 
@@ -255,6 +261,8 @@
         NET_ThrowNew(env, errno, "Can't create socket");
         return JNI_FALSE;
     }
+    tagSocket(env, fd);
+
     if (ttl > 0) {
       setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl));
     }
@@ -265,6 +273,7 @@
     if (netif != NULL) {
       if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in)) < 0) {
         NET_ThrowNew(env, errno, "Can't bind socket");
+        untagSocket(env, fd);
         close(fd);
         return JNI_FALSE;
       }
@@ -284,6 +293,7 @@
      * we were able to reach the host!
      */
     if (connect_rv == 0 || errno == ECONNREFUSED) {
+        untagSocket(env, fd);
         close(fd);
         return JNI_TRUE;
     } else {
@@ -302,6 +312,7 @@
            * When that happens, don't throw an exception, just return false.
            */
 #endif /* __linux__ */
+          untagSocket(env, fd);
           close(fd);
           return JNI_FALSE;
         }
@@ -309,6 +320,7 @@
         if (errno != EINPROGRESS) {
           NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
                                        "connect failed");
+          untagSocket(env, fd);
           close(fd);
           return JNI_FALSE;
         }
@@ -322,10 +334,12 @@
             connect_rv = errno;
           }
           if (connect_rv == 0 || connect_rv == ECONNREFUSED) {
+            untagSocket(env, fd);
             close(fd);
             return JNI_TRUE;
           }
         }
+        untagSocket(env, fd);
         close(fd);
         return JNI_FALSE;
     }
diff --git a/ojluni/src/main/native/Inet6AddressImpl.c b/ojluni/src/main/native/Inet6AddressImpl.c
index 27f03ce..ec766c9 100755
--- a/ojluni/src/main/native/Inet6AddressImpl.c
+++ b/ojluni/src/main/native/Inet6AddressImpl.c
@@ -180,6 +180,7 @@
     if (netif != NULL) {
       if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
         NET_ThrowNew(env, errno, "Can't bind socket");
+        untagSocket(env, fd);
         close(fd);
         return JNI_FALSE;
       }
@@ -209,6 +210,7 @@
            */
 #endif /*__linux__ */
         NET_ThrowNew(env, errno, "Can't send ICMP packet");
+        untagSocket(env, fd);
         close(fd);
         return JNI_FALSE;
       }
@@ -230,10 +232,12 @@
           if (n >= 8 && icmp6->icmp6_type == ICMP6_ECHO_REPLY &&
               (ntohs(icmp6->icmp6_id) == pid)) {
             if (NET_IsEqual(caddr, recv_caddr)) {
+              untagSocket(env, fd);
               close(fd);
               return JNI_TRUE;
             }
             if (NET_IsZeroAddr(caddr)) {
+              untagSocket(env, fd);
               close(fd);
               return JNI_TRUE;
             }
@@ -242,6 +246,7 @@
       } while (tmout2 > 0);
       timeout -= 1000;
     } while (timeout > 0);
+    untagSocket(env, fd);
     close(fd);
     return JNI_FALSE;
 }
@@ -322,6 +327,7 @@
     fd = JVM_Socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6);
 
     if (fd != -1) { /* Good to go, let's do a ping */
+        tagSocket(env, fd);
         return ping6(env, fd, &him6, timeout, netif, ttl);
     }
 
@@ -335,6 +341,8 @@
         NET_ThrowNew(env, errno, "Can't create socket");
         return JNI_FALSE;
     }
+    tagSocket(env, fd);
+
     if (ttl > 0) {
       setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl));
     }
@@ -345,6 +353,7 @@
     if (netif != NULL) {
       if (bind(fd, (struct sockaddr*)netif, sizeof(struct sockaddr_in6)) <0) {
         NET_ThrowNew(env, errno, "Can't bind socket");
+        untagSocket(env, fd);
         close(fd);
         return JNI_FALSE;
       }
@@ -360,6 +369,7 @@
      * we were able to reach the host!
      */
     if (connect_rv == 0 || errno == ECONNREFUSED) {
+        untagSocket(env, fd);
         close(fd);
         return JNI_TRUE;
     } else {
@@ -378,6 +388,7 @@
            * When that happens, don't throw an exception, just return false.
            */
 #endif /* __linux__ */
+          untagSocket(env, fd);
           close(fd);
           return JNI_FALSE;
         }
@@ -385,6 +396,7 @@
         if (errno != EINPROGRESS) {
             NET_ThrowByNameWithLastError(env, JNU_JAVANETPKG "ConnectException",
                                          "connect failed");
+            untagSocket(env, fd);
             close(fd);
             return JNI_FALSE;
         }
@@ -399,10 +411,12 @@
             connect_rv = errno;
           }
           if (connect_rv == 0 || ECONNREFUSED) {
+            untagSocket(env, fd);
             close(fd);
             return JNI_TRUE;
           }
         }
+        untagSocket(env, fd);
         close(fd);
         return JNI_FALSE;
     }
diff --git a/ojluni/src/main/native/Net.c b/ojluni/src/main/native/Net.c
index 3bdbf4d..e7cd5d7 100644
--- a/ojluni/src/main/native/Net.c
+++ b/ojluni/src/main/native/Net.c
@@ -167,6 +167,7 @@
 #endif
 
     fd = socket(domain, type, 0);
+    tagSocket(env, fd);
     if (fd < 0) {
         return handleSocketError(env, errno);
     }
@@ -180,6 +181,7 @@
             JNU_ThrowByNameWithLastError(env,
                                          JNU_JAVANETPKG "SocketException",
                                          "sun.nio.ch.Net.setIntOption");
+            untagSocket(env, fd);
             close(fd);
             return -1;
         }
@@ -193,6 +195,7 @@
             JNU_ThrowByNameWithLastError(env,
                                          JNU_JAVANETPKG "SocketException",
                                          "sun.nio.ch.Net.setIntOption");
+            untagSocket(env, fd);
             close(fd);
             return -1;
         }
@@ -206,6 +209,7 @@
             JNU_ThrowByNameWithLastError(env,
                                          JNU_JAVANETPKG "SocketException",
                                          "sun.nio.ch.Net.setIntOption");
+            untagSocket(env, fd);
             close(fd);
             return -1;
         }
diff --git a/ojluni/src/main/native/NetworkInterface.c b/ojluni/src/main/native/NetworkInterface.c
index ff80041..94cdd03 100755
--- a/ojluni/src/main/native/NetworkInterface.c
+++ b/ojluni/src/main/native/NetworkInterface.c
@@ -452,6 +452,7 @@
 
   (*env)->ReleaseStringUTFChars(env, name, name_utf);
 
+  untagSocket(env, sock);
   close(sock);
   return ret;
 }
@@ -475,6 +476,7 @@
 
   ret = getFlags(sock, name_utf, &flags);
 
+  untagSocket(env, sock);
   close(sock);
   (*env)->ReleaseStringUTFChars(env, name, name_utf);
 
@@ -705,6 +707,7 @@
   }
 
   freeifaddrs(origifa);
+  untagSocket(env, sock);
   close(sock);
 
   return ifs;
@@ -985,6 +988,7 @@
     return -1;
   }
 
+  tagSocket(env, sock);
   return sock;
 }
 
@@ -1015,6 +1019,7 @@
   /* Linux starting from 2.6.? kernel allows ioctl call with either IPv4 or IPv6 socket regardless of type
      of address of an interface */
 
+  tagSocket(env, sock);
   return sock;
 }
 
diff --git a/ojluni/src/main/native/PlainDatagramSocketImpl.c b/ojluni/src/main/native/PlainDatagramSocketImpl.c
index f4857df..1b1e3f6 100755
--- a/ojluni/src/main/native/PlainDatagramSocketImpl.c
+++ b/ojluni/src/main/native/PlainDatagramSocketImpl.c
@@ -987,6 +987,7 @@
                        "Error creating socket");
         return;
     }
+    tagSocket(env, fd);
 
 #ifdef AF_INET6
     /* Disable IPV6_V6ONLY to ensure dual-socket support */
@@ -995,6 +996,7 @@
         if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
                        sizeof(int)) < 0) {
             NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
+            untagSocket(env, fd);
             close(fd);
             return;
         }
@@ -1059,6 +1061,7 @@
         return;
     }
     (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
+    untagSocket(env, fd);
     NET_SocketClose(fd);
 }
 
diff --git a/ojluni/src/main/native/PlainSocketImpl.c b/ojluni/src/main/native/PlainSocketImpl.c
index 5010851..db25104 100755
--- a/ojluni/src/main/native/PlainSocketImpl.c
+++ b/ojluni/src/main/native/PlainSocketImpl.c
@@ -180,6 +180,7 @@
         NET_ThrowNew(env, errno, "can't create socket");
         return;
     }
+    tagSocket(env, fd);
 
 #ifdef AF_INET6
     /* Disable IPV6_V6ONLY to ensure dual-socket support */
@@ -188,6 +189,7 @@
         if (setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&arg,
                        sizeof(int)) < 0) {
             NET_ThrowNew(env, errno, "cannot set IPPROTO_IPV6");
+            untagSocket(env, fd);
             close(fd);
             return;
         }
@@ -205,6 +207,7 @@
         if (JVM_SetSockOpt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg,
                            sizeof(arg)) < 0) {
             NET_ThrowNew(env, errno, "cannot set SO_REUSEADDR");
+            untagSocket(env, fd);
             close(fd);
             return;
         }
@@ -746,6 +749,7 @@
     socketAddressObj = NET_SockaddrToInetAddress(env, (struct sockaddr *)&him, &port);
     if (socketAddressObj == NULL) {
         /* should be pending exception */
+        untagSocket(env, fd);
         close(newfd);
         return;
     }
@@ -815,6 +819,7 @@
     }
     if (fd != -1) {
       (*env)->SetIntField(env, fdObj, IO_fd_fdID, -1);
+      untagSocket(env, fd);
       NET_SocketClose(fd);
     }
 }
diff --git a/ojluni/src/main/native/net_util_md.c b/ojluni/src/main/native/net_util_md.c
index 27a45ad..c41d8bc 100755
--- a/ojluni/src/main/native/net_util_md.c
+++ b/ojluni/src/main/native/net_util_md.c
@@ -412,6 +412,7 @@
             /**
              * SIOCGLIFNUM failed - assume IPv6 not configured
              */
+            untagSocket(env, fd);
             close(fd);
             return JNI_FALSE;
         }
diff --git a/ojluni/src/main/native/net_util_md.h b/ojluni/src/main/native/net_util_md.h
index cc0c033..46fa8dd 100755
--- a/ojluni/src/main/native/net_util_md.h
+++ b/ojluni/src/main/native/net_util_md.h
@@ -59,6 +59,9 @@
 extern int NET_Poll(struct pollfd *ufds, unsigned int nfds, int timeout);
 #endif
 
+extern int tagSocket(JNIEnv* env, int fd);
+extern void untagSocket(JNIEnv* env, int fd);
+
 #else
 
 #define NET_Timeout     JVM_Timeout
@@ -75,6 +78,9 @@
 #define NET_Select      select
 #define NET_Poll        poll
 
+#define tagSocket(env,fd)    (void)0
+#define untagSocket(env,fd)  (void)0
+
 #endif
 
 
diff --git a/ojluni/src/main/native/openjdksub.mk b/ojluni/src/main/native/openjdksub.mk
index 6ec6be1..1f88335 100644
--- a/ojluni/src/main/native/openjdksub.mk
+++ b/ojluni/src/main/native/openjdksub.mk
@@ -66,6 +66,7 @@
     Bits.c \
     Character.cpp \
     Register.cpp \
+    socket_tagger_util.cpp \
 
 LOCAL_C_INCLUDES += \
        libcore/$(srcdir) \
diff --git a/ojluni/src/main/native/socket_tagger_util.cpp b/ojluni/src/main/native/socket_tagger_util.cpp
new file mode 100644
index 0000000..b03d0aa
--- /dev/null
+++ b/ojluni/src/main/native/socket_tagger_util.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Google designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Google in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "JNIHelp.h"
+#include "JniConstants.h"
+
+extern "C" {
+
+int tagSocket(JNIEnv* env, int fd) {
+    if (env->ExceptionOccurred()) { return fd; }
+    jmethodID get = env->GetStaticMethodID(JniConstants::socketTaggerClass,
+                                           "get", "()Ldalvik/system/SocketTagger;");
+    jobject socketTagger =
+        env->CallStaticObjectMethod(JniConstants::socketTaggerClass, get);
+    jmethodID tag = env->GetMethodID(JniConstants::socketTaggerClass,
+                                     "tag", "(Ljava/io/FileDescriptor;)V");
+
+    jobject fileDescriptor = jniCreateFileDescriptor(env, fd);
+    env->CallVoidMethod(socketTagger, tag, fileDescriptor);
+    return fd;
+}
+
+void untagSocket(JNIEnv* env, int fd) {
+    if (env->ExceptionOccurred()) { return; }
+    jmethodID get = env->GetStaticMethodID(JniConstants::socketTaggerClass,
+                                           "get", "()Ldalvik/system/SocketTagger;");
+    jobject socketTagger =
+        env->CallStaticObjectMethod(JniConstants::socketTaggerClass, get);
+    jmethodID untag = env->GetMethodID(JniConstants::socketTaggerClass,
+                                       "untag", "(Ljava/io/FileDescriptor;)V");
+
+    jobject fileDescriptor = jniCreateFileDescriptor(env, fd);
+    env->CallVoidMethod(socketTagger, untag, fileDescriptor);
+}
+
+}
diff --git a/support/src/test/java/libcore/java/security/TestKeyStore.java b/support/src/test/java/libcore/java/security/TestKeyStore.java
index 0fb8f2a..d6e6c91 100644
--- a/support/src/test/java/libcore/java/security/TestKeyStore.java
+++ b/support/src/test/java/libcore/java/security/TestKeyStore.java
@@ -18,6 +18,7 @@
 
 import com.android.org.bouncycastle.asn1.DEROctetString;
 import com.android.org.bouncycastle.asn1.x509.BasicConstraints;
+import com.android.org.bouncycastle.asn1.x509.CRLReason;
 import com.android.org.bouncycastle.asn1.x509.ExtendedKeyUsage;
 import com.android.org.bouncycastle.asn1.x509.GeneralName;
 import com.android.org.bouncycastle.asn1.x509.GeneralNames;
@@ -25,13 +26,28 @@
 import com.android.org.bouncycastle.asn1.x509.KeyPurposeId;
 import com.android.org.bouncycastle.asn1.x509.KeyUsage;
 import com.android.org.bouncycastle.asn1.x509.NameConstraints;
+import com.android.org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
 import com.android.org.bouncycastle.asn1.x509.X509Extensions;
+import com.android.org.bouncycastle.cert.X509CertificateHolder;
+import com.android.org.bouncycastle.cert.jcajce.JcaX509CertificateHolder;
+import com.android.org.bouncycastle.cert.ocsp.BasicOCSPResp;
+import com.android.org.bouncycastle.cert.ocsp.BasicOCSPRespBuilder;
+import com.android.org.bouncycastle.cert.ocsp.CertificateID;
+import com.android.org.bouncycastle.cert.ocsp.CertificateStatus;
+import com.android.org.bouncycastle.cert.ocsp.OCSPException;
+import com.android.org.bouncycastle.cert.ocsp.OCSPResp;
+import com.android.org.bouncycastle.cert.ocsp.OCSPRespBuilder;
+import com.android.org.bouncycastle.cert.ocsp.RevokedStatus;
 import com.android.org.bouncycastle.jce.provider.BouncyCastleProvider;
+import com.android.org.bouncycastle.operator.DigestCalculatorProvider;
+import com.android.org.bouncycastle.operator.OperatorCreationException;
+import com.android.org.bouncycastle.operator.bc.BcDigestCalculatorProvider;
+import com.android.org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
 import com.android.org.bouncycastle.x509.X509V3CertificateGenerator;
 import java.io.ByteArrayInputStream;
+import java.io.IOException;
 import java.io.PrintStream;
 import java.math.BigInteger;
-import java.security.KeyFactory;
 import java.security.KeyPair;
 import java.security.KeyPairGenerator;
 import java.security.KeyStore;
@@ -48,16 +64,14 @@
 import java.security.UnrecoverableEntryException;
 import java.security.UnrecoverableKeyException;
 import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.security.cert.X509Certificate;
-import java.security.interfaces.ECPrivateKey;
-import java.security.spec.PKCS8EncodedKeySpec;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
-import java.util.Vector;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
 import javax.net.ssl.TrustManager;
@@ -431,9 +445,9 @@
          * name.
          *
          * If a CA is provided, it will be used to sign the generated
-         * certificate. Otherwise, the certificate will be self
-         * signed. The certificate will be valid for one day before and
-         * one day after the time of creation.
+         * certificate and OCSP responses. Otherwise, the certificate
+         * will be self signed. The certificate will be valid for one
+         * day before and one day after the time of creation.
          *
          * Based on:
          * org.bouncycastle.jce.provider.test.SigTest
@@ -581,7 +595,11 @@
         long now = System.currentTimeMillis();
         Date start = new Date(now - millisPerDay);
         Date end = new Date(now + millisPerDay);
-        BigInteger serial = BigInteger.valueOf(1);
+
+        // Generate a random serial number.
+        byte[] serialBytes = new byte[16];
+        new SecureRandom().nextBytes(serialBytes);
+        BigInteger serial = new BigInteger(1, serialBytes);
 
         String keyAlgorithm = privateKey.getAlgorithm();
         String signatureAlgorithm;
@@ -808,6 +826,53 @@
         return rootCertificate(keyStore, algorithm);
     }
 
+    private static OCSPResp generateOCSPResponse(PrivateKeyEntry server, PrivateKeyEntry issuer,
+            CertificateStatus status) throws CertificateException {
+        try {
+            X509Certificate serverCertJca = (X509Certificate) server.getCertificate();
+            X509Certificate caCertJca = (X509Certificate) issuer.getCertificate();
+
+            X509CertificateHolder caCert = new JcaX509CertificateHolder(caCertJca);
+
+            DigestCalculatorProvider digCalcProv = new BcDigestCalculatorProvider();
+            BasicOCSPRespBuilder basicBuilder = new BasicOCSPRespBuilder(
+                    SubjectPublicKeyInfo.getInstance(caCertJca.getPublicKey().getEncoded()),
+                    digCalcProv.get(CertificateID.HASH_SHA1));
+
+            CertificateID certId = new CertificateID(digCalcProv.get(CertificateID.HASH_SHA1),
+                    caCert, serverCertJca.getSerialNumber());
+
+            basicBuilder.addResponse(certId, status);
+
+            BasicOCSPResp resp = basicBuilder.build(
+                    new JcaContentSignerBuilder("SHA256withRSA").build(issuer.getPrivateKey()),
+                    null, new Date());
+
+            OCSPRespBuilder builder = new OCSPRespBuilder();
+            return builder.build(OCSPRespBuilder.SUCCESSFUL, resp);
+        } catch (Exception e) {
+            throw new CertificateException("cannot generate OCSP response", e);
+        }
+    }
+
+    public static byte[] getOCSPResponseForGood(PrivateKeyEntry server, PrivateKeyEntry issuer) throws CertificateException {
+        try {
+            return generateOCSPResponse(server, issuer, CertificateStatus.GOOD).getEncoded();
+        } catch (IOException e) {
+            throw new CertificateException(e);
+        }
+    }
+
+    public static byte[] getOCSPResponseForRevoked(PrivateKeyEntry server, PrivateKeyEntry issuer)
+            throws CertificateException {
+        try {
+            return generateOCSPResponse(server, issuer,
+                    new RevokedStatus(new Date(), CRLReason.keyCompromise)).getEncoded();
+        } catch (IOException e) {
+            throw new CertificateException(e);
+        }
+    }
+
     /**
      * Return the only self-signed root certificate in a keystore for
      * the given algorithm. Throws IllegalStateException if there are