Merge change I410514c5

* changes:
  Expose hooks for more efficient log handling in Android apps.
diff --git a/dalvikvm/Android.mk b/dalvikvm/Android.mk
index f463c85..0b9f6bb 100644
--- a/dalvikvm/Android.mk
+++ b/dalvikvm/Android.mk
@@ -61,9 +61,15 @@
         libdvm-host
 
     ifeq ($(HOST_OS)-$(HOST_ARCH),darwin-x86)
-        # OSX comes with libz and libssl, so there is no need to build them.
-        LOCAL_LDLIBS := -lssl -lz
+        # OSX comes with libffi, libssl, and libz, so there is no need
+        # to build any of them.
+        LOCAL_LDLIBS := -lffi -lssl -lz
     else
+        # In this case, include libssl and libz, but libffi isn't listed:
+        # The recommendation is that host builds should always either
+        # have sufficient custom code so that libffi isn't needed at all,
+        # or they should use the platform's provided libffi (as is done
+        # for darwin-x86 above).
         LOCAL_STATIC_LIBRARIES += libssl libz
     endif
 
diff --git a/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java b/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
index 365388a..f9411ca 100644
--- a/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
+++ b/libcore/dalvik/src/main/java/dalvik/system/VMDebug.java
@@ -284,10 +284,18 @@
     public static native boolean cacheRegisterMap(String classAndMethodDesc);
 
     /**
-     * Crashes the VM.  Seriously.  Dumps the stack trace for the current
-     * thread and then aborts the VM so you can see the native stack trace.
-     * Useful for figuring out how you got somewhere when lots of native
-     * code is involved.
+     * Dumps the contents of the VM reference tables (e.g. JNI locals and
+     * globals) to the log file.
+     *
+     * @hide
+     */
+    public static native void dumpReferenceTables();
+
+    /**
+     * Crashes the VM.  Seriously.  Dumps the interpreter stack trace for
+     * the current thread and then aborts the VM so you can see the native
+     * stack trace.  Useful for figuring out how you got somewhere when
+     * lots of native code is involved.
      *
      * @hide
      */
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java b/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
index 9a3ae6e..a04dfd7 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
@@ -560,10 +560,7 @@
         if (shutdownInput) {
             return -1;
         }
-        // BEGIN android-changed
-        // call receiveStream() instead of read()
-        int read = netImpl.receiveStream(fd, buffer, offset, count, receiveTimeout);
-        // END android-changed
+        int read = netImpl.read(fd, buffer, offset, count, receiveTimeout);
         // Return of zero bytes for a blocking socket means a timeout occurred
         if (read == 0) {
             throw new SocketTimeoutException();
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java
index 6e8028a..f7a0209 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/IMemorySystem.java
@@ -515,7 +515,7 @@
      *
      * @param fileDescriptor
      *            a handle to the file that is to be memory mapped.
-     * @param alignment
+     * @param offset
      *            the offset in the file where the mapping should begin.
      * @param size
      *            the number of bytes that are requested to map.
@@ -528,8 +528,10 @@
      * @throws IOException
      *             if an exception occurs mapping the file into memory.
      */
-    public int mmap(int fileDescriptor, long alignment, long size,  int mapMode)
+    // BEGIN android-changed: rename 'alignment' to 'offset'.
+    public int mmap(int fileDescriptor, long offset, long size, int mapMode)
             throws IOException;
+    // END android-changed
 
     /**
      * TODO: JavaDoc
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
index d2498ec..bf2effe 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
@@ -57,7 +57,7 @@
     public int read(FileDescriptor aFD, byte[] data, int offset, int count,
             int timeout) throws IOException;
 
-    public int readDirect(FileDescriptor aFD, int address, int offset, int count,
+    public int readDirect(FileDescriptor aFD, int address, int count,
             int timeout) throws IOException;
 
     public int write(FileDescriptor fd, byte[] data, int offset, int count)
@@ -126,13 +126,6 @@
     public void connectDatagram(FileDescriptor aFD, int port, int trafficClass,
             InetAddress inetAddress) throws SocketException;
 
-    /**
-     * @deprecated Use {@link #read(FileDescriptor, byte[], int, int, int)}
-     */
-    @Deprecated
-    public int receiveStream(FileDescriptor aFD, byte[] data, int offset,
-            int count, int timeout) throws IOException;
-
     // BEGIN android-added
     public int sendStream(FileDescriptor fd, byte[] data, int offset, int count)
             throws IOException;
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
index 8d06b1c..b490da5 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSMemory.java
@@ -608,18 +608,17 @@
      */
     public native void setAddress(int address, int value);
 
-    /*
-         * Memory mapped file
-         */
-    private native int mmapImpl(int fileDescriptor, long alignment,
-            long size, int mapMode);
+    // BEGIN android-changed: more error checking, rename 'alignment' to 'offset'.
+    private native int mmapImpl(int fd, long offset, long size, int mapMode);
 
-    public int mmap(int fileDescriptor, long alignment, long size,
-            int mapMode) throws IOException {
-        // No need to check mmapImpl return as it throws IOException in error cases
-        int address = mmapImpl(fileDescriptor, alignment, size, mapMode);
-        return address;
+    public int mmap(int fd, long offset, long size, int mapMode) throws IOException {
+        // Check just those errors mmap(2) won't detect.
+        if (offset < 0 || size < 0 || offset > Integer.MAX_VALUE || size > Integer.MAX_VALUE) {
+            throw new IllegalArgumentException("offset=" + offset + " size=" + size);
+        }
+        return mmapImpl(fd, offset, size, mapMode);
     }
+    // END android-changed
 
     private native void unmapImpl(int addr, long size);
 
diff --git a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
index 20c6e84..f6f9e83 100644
--- a/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
+++ b/libcore/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
@@ -375,6 +375,12 @@
      */
     public int read(FileDescriptor fd, byte[] data, int offset, int count,
             int timeout) throws IOException {
+        // BEGIN android-added safety!
+        if (offset < 0 || count < 0 || offset > data.length - count) {
+            throw new IllegalArgumentException("data.length=" + data.length + " offset=" + offset +
+                    " count=" + count);
+        }
+        // END android-added
         return readSocketImpl(fd, data, offset, count, timeout);
     }
 
@@ -399,12 +405,12 @@
      * @throws IOException
      *             if an underlying socket exception occurred
      */
-    public int readDirect(FileDescriptor fd, int address, int offset, int count,
+    public int readDirect(FileDescriptor fd, int address, int count,
             int timeout) throws IOException {
-        return readSocketDirectImpl(fd, address, offset, count, timeout);
+        return readSocketDirectImpl(fd, address, count, timeout);
     }
 
-    static native int readSocketDirectImpl(FileDescriptor aFD, int address, int offset, int count,
+    static native int readSocketDirectImpl(FileDescriptor aFD, int address, int count,
             int timeout) throws IOException;
 
     /**
@@ -452,34 +458,6 @@
             DatagramPacket packet, int address, int offset, int length,
             int receiveTimeout, boolean peek) throws IOException;
 
-    /**
-     * Receive at most <code>count</code> bytes into the buffer
-     * <code>data</code> at the <code>offset</code> on the socket.
-     *
-     * @param aFD
-     *            the socket FileDescriptor
-     * @param data
-     *            the receive buffer
-     * @param offset
-     *            the offset into the buffer
-     * @param count
-     *            the max number of bytes to receive
-     * @param timeout
-     *            the max time the read operation should block waiting for data
-     * @return the actual number of bytes read
-     * @throws IOException
-     * @throws SocketException
-     *             if an error occurs while reading
-     * @deprecated use {@link #read(FileDescriptor, byte[], int, int, int)}
-     */
-    public int receiveStream(FileDescriptor aFD, byte[] data,
-            int offset, int count, int timeout) throws IOException {
-        return receiveStreamImpl(aFD, data, offset, count, timeout);
-    }
-
-    static native int receiveStreamImpl(FileDescriptor aFD, byte[] data,
-            int offset, int count, int timeout) throws IOException;
-
     // BEGIN android-added
     /**
      * Send <code>count</code> bytes from the buffer <code>data</code> at
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
index b1493f8..1d63faf 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSMemory.cpp
@@ -34,12 +34,9 @@
     jobject runtimeInstance;
 } gIDCache;
 
-#undef MMAP_READ_ONLY
-#define MMAP_READ_ONLY 1L
-#undef MMAP_READ_WRITE
-#define MMAP_READ_WRITE 2L
-#undef MMAP_WRITE_COPY
-#define MMAP_WRITE_COPY 4L
+static const int MMAP_READ_ONLY = 1;
+static const int MMAP_READ_WRITE = 2;
+static const int MMAP_WRITE_COPY = 4;
 
 /*
  * Class:     org_apache_harmony_luni_platform_OSMemory
@@ -429,36 +426,33 @@
  * Method:    mmapImpl
  * Signature: (IJJI)I
  */
-static jint harmony_nio_mmapImpl(JNIEnv *_env, jobject _this, jint fd, 
-        jlong alignment, jlong size, jint mmode) {
-    void *mapAddress = NULL;
+static jint harmony_nio_mmapImpl(JNIEnv* env, jobject, jint fd, 
+        jlong offset, jlong size, jint mapMode) {
     int prot, flags;
-          
-    // Convert from Java mapping mode to port library mapping mode.
-    switch (mmode) {
-      case MMAP_READ_ONLY:
-              prot = PROT_READ;
-              flags = MAP_SHARED;
-              break;
-      case MMAP_READ_WRITE:
-              prot = PROT_READ|PROT_WRITE;
-              flags = MAP_SHARED;
-              break;
-      case MMAP_WRITE_COPY:
-              prot = PROT_READ|PROT_WRITE;
-              flags = MAP_PRIVATE;
-              break;
-      default:
-              return -1;
-    }
-
-    mapAddress = mmap(0, (size_t)(size&0x7fffffff), prot, flags,fd,
-            (off_t)(alignment&0x7fffffff));
-    if (mapAddress == MAP_FAILED) {
+    switch (mapMode) {
+    case MMAP_READ_ONLY:
+        prot = PROT_READ;
+        flags = MAP_SHARED;
+        break;
+    case MMAP_READ_WRITE:
+        prot = PROT_READ|PROT_WRITE;
+        flags = MAP_SHARED;
+        break;
+    case MMAP_WRITE_COPY:
+        prot = PROT_READ|PROT_WRITE;
+        flags = MAP_PRIVATE;
+        break;
+    default:
+        jniThrowIOException(env, EINVAL);
+        LOGE("bad mapMode %i", mapMode);
         return -1;
     }
-    
-    return (jint) mapAddress;
+
+    void* mapAddress = mmap(0, size, prot, flags, fd, offset);
+    if (mapAddress == MAP_FAILED) {
+        jniThrowIOException(env, errno);
+    }
+    return reinterpret_cast<uintptr_t>(mapAddress);
 }
 
 /*
@@ -494,15 +488,6 @@
     return -1;
 }
 
-int getPageSize() {
-    static int page_size = 0;
-    if(page_size==0)
-    {
-        page_size=getpagesize();
-    }
-    return page_size;
-}
-
 /*
  * Class:     org_apache_harmony_luni_platform_OSMemory
  * Method:    isLoadedImpl
@@ -511,18 +496,16 @@
 static jboolean harmony_nio_isLoadedImpl(JNIEnv *_env, jobject _this, 
         jint address, jlong size) {
 
+    static int page_size = getpagesize();
     jboolean result = 0;
     jint m_addr = (jint)address;
-    int page_size = getPageSize();
-    unsigned char* vec = NULL;
-    int page_count = 0;
     
     int align_offset = m_addr%page_size;// addr should align with the boundary of a page.
     m_addr -= align_offset;
     size   += align_offset;
-    page_count = (size+page_size-1)/page_size;
+    int page_count = (size+page_size-1)/page_size;
     
-    vec = (unsigned char *) malloc(page_count*sizeof(char));
+    unsigned char* vec = (unsigned char *) malloc(page_count*sizeof(char));
     
     if (mincore((void *)m_addr, size, (MINCORE_POINTER_TYPE) vec)==0) {
         // or else there is error about the mincore and return false;
diff --git a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
index 2842fc5..904b935 100644
--- a/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
+++ b/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
@@ -1528,8 +1528,7 @@
 }
 
 static jint osNetworkSystem_readSocketDirectImpl(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jint address, jint offset, jint count,
-        jint timeout) {
+        jobject fileDescriptor, jint address, jint count, jint timeout) {
     // LOGD("ENTER readSocketDirectImpl");
 
     int fd;
@@ -1537,59 +1536,45 @@
         return 0;
     }
 
-    int result = selectWait(fd, timeout, SELECT_READ_TYPE);
-    if (result < 0) {
-        return 0;
+    if (timeout != 0) {
+        int result = selectWait(fd, timeout * 1000, SELECT_READ_TYPE);
+        if (result < 0) {
+            return 0;
+        }
     }
 
-    const int localCount = (count < 65536) ? count : 65536;
-    jbyte* message =
-            reinterpret_cast<jbyte*>(static_cast<uintptr_t>(address + offset));
+    jbyte* dst = reinterpret_cast<jbyte*>(static_cast<uintptr_t>(address));
     ssize_t bytesReceived =
-            TEMP_FAILURE_RETRY(recv(fd, message, localCount, SOCKET_NOFLAGS));
+            TEMP_FAILURE_RETRY(recv(fd, dst, count, SOCKET_NOFLAGS));
     if (bytesReceived == 0) {
         return -1;
     } else if (bytesReceived == -1) {
-        throwSocketException(env, convertError(errno));
-        return 0;
+        if (errno == EWOULDBLOCK) {
+            // We were asked to read a non-blocking socket with no data
+            // available, so report "no data".
+            return 0;
+        } else {
+            throwSocketException(env, convertError(errno));
+            return 0;
+        }
     }
     return bytesReceived;
 }
 
 static jint osNetworkSystem_readSocketImpl(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jbyteArray data, jint offset, jint count,
+        jobject fileDescriptor, jbyteArray byteArray, jint offset, jint count,
         jint timeout) {
     // LOGD("ENTER readSocketImpl");
 
-    jbyte *message;
-    int result, localCount;
-
-    jbyte internalBuffer[BUFFERSIZE];
-
-    localCount = (count < 65536) ? count : 65536;
-
-    if (localCount > BUFFERSIZE) {
-        message = (jbyte*)malloc(localCount * sizeof(jbyte));
-        if (message == NULL) {
-            jniThrowException(env, "java/lang/OutOfMemoryError",
-                    "couldn't allocate enough memory for readSocket");
-            return 0;
-        }
-    } else {
-        message = (jbyte *)internalBuffer;
+    jbyte* bytes = env->GetByteArrayElements(byteArray, NULL);
+    if (bytes == NULL) {
+        return -1;
     }
-
-    result = osNetworkSystem_readSocketDirectImpl(env, clazz, fileDescriptor,
-            (jint) message, 0, localCount, timeout);
-
-    if (result > 0) {
-        env->SetByteArrayRegion(data, offset, result, (jbyte *)message);
-    }
-
-    if (((jbyte *)message) != internalBuffer) {
-        free(( jbyte *)message);
-    }
-
+    jint address =
+            static_cast<jint>(reinterpret_cast<uintptr_t>(bytes + offset));
+    int result = osNetworkSystem_readSocketDirectImpl(env, clazz,
+            fileDescriptor, address, count, timeout);
+    env->ReleaseByteArrayElements(byteArray, bytes, 0);
     return result;
 }
 
@@ -2331,61 +2316,6 @@
     setsockopt(handle, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(int));
 }
 
-/*
- * @param timeout in milliseconds.  If zero, block until data received
- */
-// TODO(enh): this has been removed upstream; allegedly the reason we didn't
-// take that change is because it caused some tests to fail. I should
-// investigate that.
-static jint osNetworkSystem_receiveStreamImpl(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor, jbyteArray data, jint offset, jint count,
-        jint timeout) {
-    // LOGD("ENTER receiveStreamImpl");
-
-    int fd;
-    if (!jniGetFd(env, fileDescriptor, fd)) {
-        return 0;
-    }
-
-    // Cap read length to available buf size
-    int spaceAvailable = env->GetArrayLength(data) - offset;
-    int localCount = count < spaceAvailable? count : spaceAvailable;
-
-    jbyte* body = env->GetByteArrayElements(data, NULL);
-
-    // set timeout
-    timeval tv(toTimeval(timeout));
-    setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (struct timeval *)&tv,
-               sizeof(struct timeval));
-
-    int result;
-    do {
-        result = recv(fd, body + offset, localCount, SOCKET_NOFLAGS);
-    } while (result < 0 && errno == EINTR);
-
-    env->ReleaseByteArrayElements(data, body, 0);
-
-    /*
-     * If no bytes are read, return -1 to signal 'endOfFile'
-     * to the Java input stream
-     */
-    if (0 < result) {
-        return result;
-    } else if (0 == result) {
-        return -1;
-    } else {
-        // If EAGAIN or EWOULDBLOCK, read timed out
-        if (errno == EAGAIN || errno == EWOULDBLOCK) {
-            jniThrowException(env, "java/net/SocketTimeoutException",
-                              netLookupErrorString(SOCKERR_TIMEOUT));
-        } else {
-            int err = convertError(errno);
-            throwSocketException(env, err);
-        }
-        return 0;
-    }
-}
-
 static jint osNetworkSystem_sendStreamImpl(JNIEnv* env, jclass clazz,
         jobject fileDescriptor, jbyteArray data, jint offset, jint count) {
     // LOGD("ENTER sendStreamImpl");
@@ -3334,7 +3264,7 @@
     { "createStreamSocketImpl",            "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createStreamSocketImpl             },
     { "createDatagramSocketImpl",          "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createDatagramSocketImpl           },
     { "readSocketImpl",                    "(Ljava/io/FileDescriptor;[BIII)I",                                         (void*) osNetworkSystem_readSocketImpl                     },
-    { "readSocketDirectImpl",              "(Ljava/io/FileDescriptor;IIII)I",                                          (void*) osNetworkSystem_readSocketDirectImpl               },
+    { "readSocketDirectImpl",              "(Ljava/io/FileDescriptor;III)I",                                           (void*) osNetworkSystem_readSocketDirectImpl               },
     { "writeSocketImpl",                   "(Ljava/io/FileDescriptor;[BII)I",                                          (void*) osNetworkSystem_writeSocketImpl                    },
     { "writeSocketDirectImpl",             "(Ljava/io/FileDescriptor;III)I",                                           (void*) osNetworkSystem_writeSocketDirectImpl              },
     { "setNonBlockingImpl",                "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_setNonBlockingImpl                 },
@@ -3358,7 +3288,6 @@
     { "sendConnectedDatagramImpl",         "(Ljava/io/FileDescriptor;[BIIZ)I",                                         (void*) osNetworkSystem_sendConnectedDatagramImpl          },
     { "sendConnectedDatagramDirectImpl",   "(Ljava/io/FileDescriptor;IIIZ)I",                                          (void*) osNetworkSystem_sendConnectedDatagramDirectImpl    },
     { "createServerStreamSocketImpl",      "(Ljava/io/FileDescriptor;Z)V",                                             (void*) osNetworkSystem_createServerStreamSocketImpl       },
-    { "receiveStreamImpl",                 "(Ljava/io/FileDescriptor;[BIII)I",                                         (void*) osNetworkSystem_receiveStreamImpl                  },
     { "sendStreamImpl",                    "(Ljava/io/FileDescriptor;[BII)I",                                          (void*) osNetworkSystem_sendStreamImpl                     },
     { "shutdownInputImpl",                 "(Ljava/io/FileDescriptor;)V",                                              (void*) osNetworkSystem_shutdownInputImpl                  },
     { "shutdownOutputImpl",                "(Ljava/io/FileDescriptor;)V",                                              (void*) osNetworkSystem_shutdownOutputImpl                 },
diff --git a/libcore/luni/src/test/java/tests/api/java/net/AllTests.java b/libcore/luni/src/test/java/tests/api/java/net/AllTests.java
index 5bcb484..10dd9d8 100644
--- a/libcore/luni/src/test/java/tests/api/java/net/AllTests.java
+++ b/libcore/luni/src/test/java/tests/api/java/net/AllTests.java
@@ -68,6 +68,7 @@
         suite.addTestSuite(SocketPermissionTest.class);
         suite.addTestSuite(SocketTest.class);
         suite.addTestSuite(SocketTimeoutExceptionTest.class);
+        suite.addTestSuite(UnixSocketTest.class);
         suite.addTestSuite(URISyntaxExceptionTest.class);
         suite.addTestSuite(URITest.class);
         suite.addTestSuite(URLClassLoaderTest.class);
diff --git a/libcore/luni/src/test/java/tests/api/java/net/DatagramSocketTest.java b/libcore/luni/src/test/java/tests/api/java/net/DatagramSocketTest.java
index 3f35b29..853f6a6 100644
--- a/libcore/luni/src/test/java/tests/api/java/net/DatagramSocketTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/net/DatagramSocketTest.java
@@ -1584,7 +1584,7 @@
         
         try {
             new java.net.DatagramSocket(isa);
-            fail("SocketException was thrown.");
+            fail("SocketException was not thrown.");
         } catch(SocketException se) {
             //expected
         }
diff --git a/libcore/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java b/libcore/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
index 1429063..018d58a 100644
--- a/libcore/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/net/MulticastSocketTest.java
@@ -17,11 +17,6 @@
 
 package tests.api.java.net;
 
-import dalvik.annotation.KnownFailure; 
-import dalvik.annotation.TestTargetClass; 
-import dalvik.annotation.TestLevel;
-import dalvik.annotation.TestTargetNew;
-
 import java.io.IOException;
 import java.net.BindException;
 import java.net.DatagramPacket;
@@ -34,290 +29,205 @@
 import java.net.SocketAddress;
 import java.net.SocketException;
 import java.net.UnknownHostException;
-import java.security.Permission;
+import java.util.ArrayList;
 import java.util.Enumeration;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.TimeUnit;
 
 import tests.support.Support_NetworkInterface;
 import tests.support.Support_PortManager;
 
-@TestTargetClass(MulticastSocket.class) 
 public class MulticastSocketTest extends SocketTestCase {
 
-    Thread t;
+	Thread t;
 
-    MulticastSocket mss;
+	MulticastSocket mss;
 
-    MulticastServer server;
+	MulticastServer server;
 
-    // private member variables used for tests
-    boolean atLeastOneInterface = false;
+	// private member variables used for tests
+	boolean atLeastOneInterface = false;
 
-    boolean atLeastTwoInterfaces = false;
+	boolean atLeastTwoInterfaces = false;
 
-    private NetworkInterface networkInterface1 = null;
+	private NetworkInterface networkInterface1 = null;
 
-    private NetworkInterface networkInterface2 = null;
+	private NetworkInterface networkInterface2 = null;
 
-    private NetworkInterface IPV6networkInterface1 = null;
+	private NetworkInterface IPV6networkInterface1 = null;
 
-    static class MulticastServer extends Thread {
+	static class MulticastServer extends Thread {
 
-        public MulticastSocket ms;
+		public MulticastSocket ms;
 
-        volatile boolean running = true;
+		boolean running = true;
 
-        private final BlockingQueue<DatagramPacket> queue
-                = new ArrayBlockingQueue<DatagramPacket>(1);
+		volatile public byte[] rbuf = new byte[512];
+
+        volatile DatagramPacket rdp = null;
+        
+        private InetAddress groupAddr = null;
+        private SocketAddress groupSockAddr = null;
+        private NetworkInterface groupNI = null;
 
         public void run() {
-            try {
+			try {
+                byte[] tmpbuf = new byte[512];
+                DatagramPacket tmpPack =
+                        new DatagramPacket(tmpbuf, tmpbuf.length);
+                
                 while (running) {
-                    try {
-                        byte[] rbuf = new byte[512];
-                        rbuf[0] = -1;
-                        DatagramPacket rdp = new DatagramPacket(rbuf, rbuf.length);
-                        ms.receive(rdp);
-                        queue.put(rdp);
+					try {
+                        ms.receive(tmpPack);
+                        
+                        System.arraycopy(tmpPack.getData(), 0, rdp.getData(),
+                                rdp.getOffset(), tmpPack.getLength());
+                        rdp.setLength(tmpPack.getLength());
+                        rdp.setAddress(tmpPack.getAddress());
+                        rdp.setPort(tmpPack.getPort());
                     } catch (java.io.InterruptedIOException e) {
-                    } catch (InterruptedException e) {
-                    }
-                }
-            } catch (java.io.IOException e) {
-                System.out.println("Multicast server failed: " + e);
-            } finally {
-                ms.close();
-            }
-        }
+                        Thread.yield();
+					}
+				}
+			} catch (java.io.IOException e) {
+				System.out.println("Multicast server failed: " + e);
+			} finally {
+				ms.close();
+			}
+		}
 
-        public synchronized void leaveGroup(InetAddress aGroup)
-                throws java.io.IOException {
-            ms.leaveGroup(aGroup);
+		public void stopServer() {
+			running = false;
+            try {
+                if (groupAddr != null) {
+                    ms.leaveGroup(groupAddr);
+                } else if (groupSockAddr != null) {
+                    ms.leaveGroup(groupSockAddr, groupNI);
+                }
+            } catch (IOException e) {}
         }
 
         public MulticastServer(InetAddress anAddress, int aPort)
                 throws java.io.IOException {
+            rbuf = new byte[512];
+            rbuf[0] = -1;
+            rdp = new DatagramPacket(rbuf, rbuf.length);
             ms = new MulticastSocket(aPort);
             ms.setSoTimeout(2000);
-            ms.joinGroup(anAddress);
+            groupAddr = anAddress;
+            ms.joinGroup(groupAddr);
         }
-
+        
+        
         public MulticastServer(SocketAddress anAddress, int aPort,
-                NetworkInterface netInterface) throws java.io.IOException {
-            ms = new MulticastSocket(aPort);
-            ms.setSoTimeout(2000);
-            ms.joinGroup(anAddress, netInterface);
-        }
+				NetworkInterface netInterface) throws java.io.IOException {
+			rbuf = new byte[512];
+			rbuf[0] = -1;
+			rdp = new DatagramPacket(rbuf, rbuf.length);
+			ms = new MulticastSocket(aPort);
+			ms.setSoTimeout(2000);
+            groupSockAddr = anAddress;
+            groupNI = netInterface;
+            ms.joinGroup(groupSockAddr, groupNI);
+		}
+	}
 
-        public DatagramPacket receive() throws InterruptedException {
-            return queue.poll(1000, TimeUnit.MILLISECONDS);
-        }
-
-        public void stopServer() throws InterruptedException {
-            running = false;
-            interrupt();
-            join();
-        }
-    }
-
-    /**
-     * @tests java.net.MulticastSocket#MulticastSocket()
-     */
-    @TestTargetNew(
-        level = TestLevel.SUFFICIENT,
-        notes = "IOException exception checking missed.",
-        method = "MulticastSocket",
-        args = {}
-    )
-    public void test_Constructor() throws IOException {
-        // regression test for 497
+	/**
+	 * @tests java.net.MulticastSocket#MulticastSocket()
+	 */
+	public void test_Constructor() throws IOException {
+		// regression test for 497
         MulticastSocket s = new MulticastSocket();
         // regression test for Harmony-1162
         assertTrue(s.getReuseAddress());
-        
-        SecurityManager sm = new SecurityManager() {
+	}
 
-            public void checkPermission(Permission perm) {
-            }
-            
-            public void checkListen(int port) {
-                throw new SecurityException();
-            }
-        };
-
-        SecurityManager oldSm = System.getSecurityManager();
-        System.setSecurityManager(sm);
-        try {
-            new MulticastSocket();
-            fail("SecurityException should be thrown.");
-        } catch (SecurityException e) {
-            // expected
-        } catch (SocketException e) {
-            fail("SocketException was thrown.");
-        } catch (IOException e) {
-            fail("IOException was thrown.");
-            e.printStackTrace();
-        } finally {
-            System.setSecurityManager(oldSm);
-        } 
-    }
-
-    /**
-     * @tests java.net.MulticastSocket#MulticastSocket(int)
-     */
-    @TestTargetNew(
-        level = TestLevel.SUFFICIENT,
-        notes = "IOException exception checking missed.",
-        method = "MulticastSocket",
-        args = {int.class}
-    )
-    public void test_ConstructorI() {
-        // Test for method java.net.MulticastSocket(int)
-        // Used in tests
-        MulticastSocket dup = null;
-        try {
-            mss = new MulticastSocket();
-            int port = mss.getLocalPort();
-            dup = new MulticastSocket(port);
+	/**
+	 * @tests java.net.MulticastSocket#MulticastSocket(int)
+	 */
+	public void test_ConstructorI() throws IOException {
+	    MulticastSocket orig = new MulticastSocket();
+        int port = orig.getLocalPort();
+        orig.close();
+		MulticastSocket dup = null;
+		try {
+			dup = new MulticastSocket(port);
             // regression test for Harmony-1162
             assertTrue(dup.getReuseAddress());
-        } catch (IOException e) {
-            fail("duplicate binding not allowed: " + e);
-        }
-        
-        
-        
-        if (dup != null)
-            dup.close();
-        
-        SecurityManager sm = new SecurityManager() {
+		} catch (IOException e) {
+			fail("duplicate binding not allowed: " + e);
+		}
+		if (dup != null)
+			dup.close();
+	}
 
-            public void checkPermission(Permission perm) {
-            }
-            
-            public void checkListen(int port) {
-                throw new SecurityException();
-            }
-        };
+	/**
+	 * @tests java.net.MulticastSocket#getInterface()
+	 */
+	public void test_getInterface() throws Exception {
+		// Test for method java.net.InetAddress
+		// java.net.MulticastSocket.getInterface()
+		assertTrue("Used for testing.", true);
 
-        SecurityManager oldSm = System.getSecurityManager();
-        System.setSecurityManager(sm);
-        try {
-            new MulticastSocket(1);
-            fail("SecurityException should be thrown.");
-        } catch (SecurityException e) {
-            // expected
-        } catch (SocketException e) {
-            fail("SocketException was thrown.");
-        } catch (IOException e) {
-            fail("IOException was thrown.");
-            e.printStackTrace();
-        } finally {
-            System.setSecurityManager(oldSm);
-        } 
-    }
+		int groupPort = Support_PortManager.getNextPortForUDP();
 
-    /**
-     * @tests java.net.MulticastSocket#getInterface()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getInterface",
-        args = {}
-    )
-    @KnownFailure("No interfaces if there's no debugger connected")
-    public void test_getInterface() {
-        // Test for method java.net.InetAddress
-        // java.net.MulticastSocket.getInterface()
-        assertTrue("Used for testing.", true);
+                if (atLeastOneInterface) {
+                        // validate that we get the expected response when one was not
+                        // set
+                        mss = new MulticastSocket(groupPort);
+                        String preferIPv4StackValue = System
+                                        .getProperty("java.net.preferIPv4Stack");
+                        String preferIPv6AddressesValue = System
+                                        .getProperty("java.net.preferIPv6Addresses");
+                        if (((preferIPv4StackValue == null) || preferIPv4StackValue
+                                        .equalsIgnoreCase("false"))
+                                        && (preferIPv6AddressesValue != null)
+                                        && (preferIPv6AddressesValue.equals("true"))) {
+                                // we expect an IPv6 ANY in this case
+                                assertEquals("inet Address returned when not set",
+                                             InetAddress.getByName("::0"),
+                                             mss.getInterface());
+                        } else {
+                                // we expect an IPv4 ANY in this case
+                                assertEquals("inet Address returned when not set",
+                                             InetAddress.getByName("0.0.0.0"),
+                                             mss.getInterface());
+                        }
 
-        int groupPort = Support_PortManager.getNextPortForUDP();
-        try {
-            if (atLeastOneInterface) {
-                // validate that we get the expected response when one was not
-                // set
-                mss = new MulticastSocket(groupPort);
-                String preferIPv4StackValue = System
-                        .getProperty("java.net.preferIPv4Stack");
-                String preferIPv6AddressesValue = System
-                        .getProperty("java.net.preferIPv6Addresses");
-                if (((preferIPv4StackValue == null) || preferIPv4StackValue
-                        .equalsIgnoreCase("false"))
-                        && (preferIPv6AddressesValue != null)
-                        && (preferIPv6AddressesValue.equals("true"))) {
-                    // we expect an IPv6 ANY in this case
-                    assertTrue("inet Address returned when not set:"
-                            + mss.getInterface().toString(), InetAddress
-                            .getByName("::0").equals(mss.getInterface()));
-                } else {
-                    // we expect an IPv4 ANY in this case
-                    assertNotNull("inet Address returned when not set:", 
-                            mss.getInterface());
+                        // validate that we get the expected response when we set via
+                        // setInterface
+                        Enumeration addresses = networkInterface1.getInetAddresses();
+                        if (addresses.hasMoreElements()) {
+                                InetAddress firstAddress = (InetAddress) addresses
+                                                .nextElement();
+                                mss.setInterface(firstAddress);
+                                assertEquals("getNetworkInterface did not return interface set by setInterface",
+                                             firstAddress, mss.getInterface());
+
+                                groupPort = Support_PortManager.getNextPortForUDP();
+                                mss = new MulticastSocket(groupPort);
+                                mss.setNetworkInterface(networkInterface1);
+                                assertEquals("getInterface did not return interface set by setNetworkInterface",
+                                             networkInterface1,
+                                             NetworkInterface.getByInetAddress(mss.getInterface()));
+                        }
+
                 }
+	}
 
-                // validate that we get the expected response when we set via
-                // setInterface
-                Enumeration addresses = networkInterface1.getInetAddresses();
-                if (addresses != null) {
-                    InetAddress firstAddress = (InetAddress) addresses
-                            .nextElement();
-                    mss.setInterface(firstAddress);
-                    assertTrue(
-                            "getNetworkInterface did not return interface set " +
-                            "by setInterface.  Expected:"
-                                    + firstAddress + " Got:"
-                                    + mss.getInterface(), firstAddress
-                                    .equals(mss.getInterface()));
-
-                    groupPort = Support_PortManager.getNextPortForUDP();
-                    mss = new MulticastSocket(groupPort);
-                    mss.setNetworkInterface(networkInterface1);
-                    InetAddress addr = mss.getInterface();
-                    NetworkInterface if1 = NetworkInterface.getByInetAddress(addr);
-                    assertEquals(
-                            "getInterface did not return interface set by " +
-                            "setNeworkInterface Expected: " + firstAddress
-                                    + "Got:" + mss.getInterface(),
-                                    networkInterface1, if1);
-                }
-                mss.close();
-                try {
-                    mss.getInterface();
-                    fail("SocketException was not thrown.");
-                } catch(SocketException ioe) {
-                    //expected
-                }
-            }
-        } catch (Exception e) {
-            fail("Exception during getInterface test: " + e.toString());
-        }
-    }
-
-    /**
-     * @throws IOException 
-     * @tests java.net.MulticastSocket#getNetworkInterface()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getNetworkInterface",
-        args = {}
-    )
-    @KnownFailure("No interfaces if there's no debugger connected")
-    public void test_getNetworkInterface() throws IOException {
+	/**
+	 * @throws IOException
+	 * @tests java.net.MulticastSocket#getNetworkInterface()
+	 */
+	public void test_getNetworkInterface() throws IOException {
         int groupPort = Support_PortManager.getNextPortForUDP();
         if (atLeastOneInterface) {
             // validate that we get the expected response when one was not
             // set
             mss = new MulticastSocket(groupPort);
             NetworkInterface theInterface = mss.getNetworkInterface();
-            assertNotNull(
-                    "network interface returned wrong network interface when " +
-                    "not set:"
-                            + theInterface, theInterface.getInetAddresses());
+            assertTrue(
+                    "network interface returned wrong network interface when not set:"
+                            + theInterface, theInterface.getInetAddresses()
+                            .hasMoreElements());
             InetAddress firstAddress = (InetAddress) theInterface
                     .getInetAddresses().nextElement();
             // validate we the first address in the network interface is the
@@ -330,42 +240,34 @@
                     .equalsIgnoreCase("false"))
                     && (preferIPv6AddressesValue != null)
                     && (preferIPv6AddressesValue.equals("true"))) {
-                assertTrue(
-                        "network interface returned wrong network interface " +
-                        "when not set:"
-                                + theInterface, InetAddress.getByName("::0")
-                                .equals(firstAddress));
+                assertEquals("network interface returned wrong network interface when not set:"
+                             + theInterface,
+                             firstAddress, InetAddress.getByName("::0"));
 
             } else {
-                assertTrue(
-                        "network interface returned wrong network interface " +
-                        "when not set:"
-                                + theInterface, InetAddress
-                                .getByName("0.0.0.0").equals(firstAddress));
+                assertEquals("network interface returned wrong network interface when not set:"
+                             + theInterface,
+                             InetAddress.getByName("0.0.0.0"),
+                             firstAddress);
             }
 
             mss.setNetworkInterface(networkInterface1);
-            assertTrue(
-                    "getNetworkInterface did not return interface set by " +
-                    "setNeworkInterface",
-                    networkInterface1.equals(mss.getNetworkInterface()));
+            assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
+                         networkInterface1, mss.getNetworkInterface());
 
             if (atLeastTwoInterfaces) {
                 mss.setNetworkInterface(networkInterface2);
-                assertTrue(
-                        "getNetworkInterface did not return network interface " +
-                        "set by second setNetworkInterface call",
-                        networkInterface2.equals(mss.getNetworkInterface()));
+                assertEquals("getNetworkInterface did not return network interface set by second setNetworkInterface call",
+                             networkInterface2, mss.getNetworkInterface());
             }
 
             groupPort = Support_PortManager.getNextPortForUDP();
             mss = new MulticastSocket(groupPort);
             if (IPV6networkInterface1 != null) {
                 mss.setNetworkInterface(IPV6networkInterface1);
-                assertTrue(
-                        "getNetworkInterface did not return interface set " +
-                        "by setNeworkInterface",
-                        IPV6networkInterface1.equals(mss.getNetworkInterface()));
+                assertEquals("getNetworkInterface did not return interface set by setNeworkInterface",
+                             IPV6networkInterface1,
+                             mss.getNetworkInterface());
             }
 
             // validate that we get the expected response when we set via
@@ -373,191 +275,100 @@
             groupPort = Support_PortManager.getNextPortForUDP();
             mss = new MulticastSocket(groupPort);
             Enumeration addresses = networkInterface1.getInetAddresses();
-            if (addresses != null) {
+            if (addresses.hasMoreElements()) {
                 firstAddress = (InetAddress) addresses.nextElement();
                 mss.setInterface(firstAddress);
-                assertTrue(
-                        "getNetworkInterface did not return interface set " +
-                        "by setInterface",
-                        networkInterface1.equals(mss.getNetworkInterface()));
-            }
-            
-            mss.close();
-            try {
-                mss.getNetworkInterface();
-                fail("SocketException was not thrown.");
-            } catch(SocketException ioe) {
-                //expected
+                assertEquals("getNetworkInterface did not return interface set by setInterface",
+                             networkInterface1,
+                             mss.getNetworkInterface());
             }
         }
     }
 
-    /**
-     * @tests java.net.MulticastSocket#getTimeToLive()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getTimeToLive",
-        args = {}
-    )
-    public void test_getTimeToLive() {
-        try {
-            mss = new MulticastSocket();
-            mss.setTimeToLive(120);
-            assertTrue("Returned incorrect 1st TTL: " + mss.getTimeToLive(),
-                    mss.getTimeToLive() == 120);
-            mss.setTimeToLive(220);
-            assertTrue("Returned incorrect 2nd TTL: " + mss.getTimeToLive(),
-                    mss.getTimeToLive() == 220);
-            mss.close();
-            try {
-                mss.getTimeToLive();
-                fail("IOException was not thrown.");
-            } catch(IOException ioe) {
-                //expected
-            }
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (Exception e) {
-            handleException(e, SO_MULTICAST);
-        }
-    }
+	/**
+	 * @tests java.net.MulticastSocket#getTimeToLive()
+	 */
+	public void test_getTimeToLive() {
+		try {
+			mss = new MulticastSocket();
+			mss.setTimeToLive(120);
+			assertEquals("Returned incorrect 1st TTL",
+                                     120, mss.getTimeToLive());
+			mss.setTimeToLive(220);
+			assertEquals("Returned incorrect 2nd TTL",
+                                     220, mss.getTimeToLive());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST);
+		}
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#getTTL()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getTTL",
-        args = {}
-    )
-    public void test_getTTL() {
-        // Test for method byte java.net.MulticastSocket.getTTL()
+	/**
+	 * @tests java.net.MulticastSocket#getTTL()
+	 */
+	public void test_getTTL() {
+		// Test for method byte java.net.MulticastSocket.getTTL()
 
-        try {
-            mss = new MulticastSocket();
-            mss.setTTL((byte) 120);
-            assertTrue("Returned incorrect TTL: " + mss.getTTL(),
-                    mss.getTTL() == 120);
-            mss.close();
-            try {
-                mss.getTTL();
-                fail("IOException was not thrown.");
-            } catch(IOException ioe) {
-                //expected
-            }
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (Exception e) {
-            handleException(e, SO_MULTICAST);
-        }
-    }
+		try {
+			mss = new MulticastSocket();
+			mss.setTTL((byte) 120);
+			assertEquals("Returned incorrect TTL",
+                                     120, mss.getTTL());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST);
+		}
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#joinGroup(java.net.InetAddress)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "joinGroup",
-        args = {java.net.InetAddress.class}
-    )
-    public void test_joinGroupLjava_net_InetAddress() throws InterruptedException {
-        // Test for method void
-        // java.net.MulticastSocket.joinGroup(java.net.InetAddress)
-        String msg = null;
-        InetAddress group = null;
-        int[] ports = Support_PortManager.getNextPortsForUDP(2);
-        int groupPort = ports[0];
-        try {
-            group = InetAddress.getByName("224.0.0.3");
-            server = new MulticastServer(group, groupPort);
-            server.start();
-            Thread.sleep(1000);
-            msg = "Hello World";
-            mss = new MulticastSocket(ports[1]);
-            DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
-                    .length(), group, groupPort);
-            mss.joinGroup(group);
-            mss.send(sdp, (byte) 10);
+	/**
+	 * @tests java.net.MulticastSocket#joinGroup(java.net.InetAddress)
+	 */
+	public void test_joinGroupLjava_net_InetAddress() throws Exception {
+		// Test for method void
+		// java.net.MulticastSocket.joinGroup(java.net.InetAddress)
+                String msg = null;
+		InetAddress group = null;
+		int[] ports = Support_PortManager.getNextPortsForUDP(2);
+		int groupPort = ports[0];
+                group = InetAddress.getByName("224.0.0.3");
+                server = new MulticastServer(group, groupPort);
+                server.start();
+                Thread.sleep(1000);
+                msg = "Hello World";
+                mss = new MulticastSocket(ports[1]);
+                DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
+                                .length(), group, groupPort);
+                mss.send(sdp, (byte) 10);
+                Thread.sleep(1000);
 
-            SecurityManager sm = new SecurityManager() {
+                assertEquals("Group member did not recv data",
+                             msg,
+                             new String(server.rdp.getData(), 0, server.rdp.getLength()));
+	}
 
-                public void checkPermission(Permission perm) {
-                }
-                
-                public void checkMulticast(InetAddress maddr) {
-                    throw new SecurityException();
-                }
-            };
+	/**
+	 * @throws IOException 
+	 * @throws InterruptedException 
+	 * @tests java.net.MulticastSocket#joinGroup(java.net.SocketAddress,java.net.NetworkInterface)
+	 */
+	public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() throws IOException, InterruptedException {
+		// security manager that allows us to check that we only return the
+		// addresses that we should
+		class mySecurityManager extends SecurityManager {
 
-            SecurityManager oldSm = System.getSecurityManager();
-            System.setSecurityManager(sm);
-            try {
-                mss.joinGroup(group);
-                fail("SecurityException should be thrown.");
-            } catch (SecurityException e) {
-                // expected
-            } catch (SocketException e) {
-                fail("SocketException was thrown.");
-            } catch (IOException e) {
-                fail("IOException was thrown.");
-                e.printStackTrace();
-            } finally {
-                System.setSecurityManager(oldSm);
-            } 
-            
-            mss.close();
-            try {
-                mss.joinGroup(group);
-                fail("SocketException was not thrown.");
-            } catch(SocketException ioe) {
-                //expected
-            }
-        } catch (Exception e) {
-            fail("Exception during joinGroup test: " + e.toString());
-        }
-        DatagramPacket rdb = server.receive();
+			public void checkMulticast(InetAddress address) {
+				throw new SecurityException("not allowed");
+			}
+		}
 
-        assertEquals("Group member did not recv data: ", msg,
-                new String(rdb.getData(), 0, rdb.getLength()));
+		String msg = null;
+		InetAddress group = null;
+		SocketAddress groupSockAddr = null;
+		int[] ports = Support_PortManager.getNextPortsForUDP(2);
+		int groupPort = ports[0];
+		int serverPort = ports[1];
 
-    }
-
-    /**
-     * @throws IOException 
-     * @throws InterruptedException 
-     * @tests java.net.MulticastSocket#joinGroup(java.net.SocketAddress,
-     *                                              java.net.NetworkInterface)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "joinGroup",
-        args = {java.net.SocketAddress.class, java.net.NetworkInterface.class}
-    )
-    public void test_joinGroupLjava_net_SocketAddressLjava_net_NetworkInterface() 
-                                    throws IOException, InterruptedException {
-        // security manager that allows us to check that we only return the
-        // addresses that we should
-        class mySecurityManager extends SecurityManager {
-
-            public void checkPermission(Permission perm) {
-            }
-            
-            public void checkMulticast(InetAddress address) {
-                throw new SecurityException("not allowed");
-            }
-        }
-
-        String msg = null;
-        InetAddress group = null;
-        SocketAddress groupSockAddr = null;
-        int[] ports = Support_PortManager.getNextPortsForUDP(2);
-        int groupPort = ports[0];
-        int serverPort = ports[1];
-
-            Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
+        Enumeration<NetworkInterface> theInterfaces = NetworkInterface.getNetworkInterfaces();
 
         // first validate that we handle a null group ok
         mss = new MulticastSocket(groupPort);
@@ -613,11 +424,11 @@
                     .length(), group, serverPort);
             mss.setTimeToLive(2);
             mss.send(sdp);
-            DatagramPacket rdp = server.receive();
-
+            Thread.sleep(1000);
             // now vaildate that we received the data as expected
-            assertEquals("Group member did not recv data: ", msg,
-                    new String(rdp.getData(), 0, rdp.getLength()));
+            assertEquals("Group member did not recv data",
+                         msg,
+                         new String(server.rdp.getData(), 0, server.rdp.getLength()));
             server.stopServer();
 
             // now validate that we handled the case were we join a
@@ -638,9 +449,11 @@
             sdp = new DatagramPacket(msg.getBytes(), msg.length(), group2,
                     serverPort);
             mss.send(sdp);
-            rdp = server.receive();
-            assertNull("Group member received data when sent on different group",
-                    rdp);
+            Thread.sleep(1000);
+            assertFalse(
+                    "Group member received data when sent on different group: ",
+                    new String(server.rdp.getData(), 0, server.rdp.getLength())
+                            .equals(msg));
             server.stopServer();
 
             // if there is more than one network interface then check that
@@ -651,39 +464,47 @@
                 NetworkInterface loopbackInterface = NetworkInterface
                         .getByInetAddress(InetAddress.getByName("127.0.0.1"));
 
+                boolean anyLoop = networkInterface1.equals(loopbackInterface) || networkInterface2.equals(loopbackInterface);
+                
+                ArrayList<NetworkInterface> realInterfaces = new ArrayList<NetworkInterface>();
                 theInterfaces = NetworkInterface.getNetworkInterfaces();
                 while (theInterfaces.hasMoreElements()) {
-
-                    NetworkInterface thisInterface = (NetworkInterface) 
-                                                    theInterfaces.nextElement();
-                    if ((thisInterface.getInetAddresses() != null && thisInterface
-                            .getInetAddresses().hasMoreElements())
+                    NetworkInterface thisInterface = (NetworkInterface) theInterfaces.nextElement();
+                    if (thisInterface.getInetAddresses().hasMoreElements()
                             && (Support_NetworkInterface
-                                    .useInterface(thisInterface) == true)) {
+                                    .useInterface(thisInterface) == true)){
+                        realInterfaces.add(thisInterface);
+                    }
+                }
+                
+                for (int i = 0; i < realInterfaces.size(); i++) {
+                    final int SECOND = 1;
+                    NetworkInterface thisInterface = realInterfaces.get(i);
+                   
                         // get the first address on the interface
 
                         // start server which is joined to the group and has
                         // only asked for packets on this interface
-                        Enumeration addresses = thisInterface
-                                .getInetAddresses();
+                        Enumeration<InetAddress> addresses = thisInterface.getInetAddresses();
 
                         NetworkInterface sendingInterface = null;
-                        boolean isLoopback = false;
-                        if (addresses != null) {
-                            InetAddress firstAddress = (InetAddress) addresses
-                                    .nextElement();
-                            if (firstAddress.isLoopbackAddress()) {
-                                isLoopback = true;
-                            }
+                        if (addresses.hasMoreElements()) {
+                            InetAddress firstAddress = (InetAddress) addresses.nextElement();
                             if (firstAddress instanceof Inet4Address) {
                                 group = InetAddress.getByName("224.0.0.4");
-                                if (networkInterface1.equals(NetworkInterface
-                                        .getByInetAddress(InetAddress
-                                                .getByName("127.0.0.1")))) {
-                                    sendingInterface = networkInterface2;
+                                if (anyLoop) {
+                                    if (networkInterface1.equals(loopbackInterface)) {
+                                        sendingInterface = networkInterface2;
+                                    } else {
+                                        sendingInterface = networkInterface1;
+                                    }
                                 } else {
-                                    sendingInterface = networkInterface1;
+                                    if(i == SECOND){
+                                        sendingInterface = networkInterface2;
+                                    } else {
+                                        sendingInterface = networkInterface1;
                                 }
+                               }
                             } else {
                                 // if this interface only seems to support
                                 // IPV6 addresses
@@ -693,13 +514,6 @@
                             }
                         }
 
-                        InetAddress useAddress = null;
-                        addresses = sendingInterface.getInetAddresses();
-                        if ((addresses != null)
-                                && (addresses.hasMoreElements())) {
-                            useAddress = (InetAddress) addresses.nextElement();
-                        }
-
                         ports = Support_PortManager.getNextPortsForUDP(2);
                         serverPort = ports[0];
                         groupPort = ports[1];
@@ -712,33 +526,27 @@
                         // Now send out a package on interface
                         // networkInterface 1. We should
                         // only see the packet if we send it on interface 1
-                        InetSocketAddress theAddress = new InetSocketAddress(
-                                useAddress, groupPort);
                         mss = new MulticastSocket(groupPort);
                         mss.setNetworkInterface(sendingInterface);
                         msg = "Hello World - Again" + thisInterface.getName();
                         sdp = new DatagramPacket(msg.getBytes(), msg.length(),
                                 group, serverPort);
                         mss.send(sdp);
-                        rdp = server.receive();
-
+                        Thread.sleep(1000);
                         if (thisInterface.equals(sendingInterface)) {
-                            assertEquals(
-                                    "Group member did not recv data when " +
-                                    "bound on specific interface: ", msg,
-                                    new String(rdp.getData(), 0, rdp.getLength()));
+                            assertEquals("Group member did not recv data when bound on specific interface",
+                                         msg,
+                                         new String(server.rdp.getData(), 0, server.rdp.getLength()));
                         } else {
                             assertFalse(
-                                    "Group member received data on other " +
-                                    "interface when only asked for it on one " +
-                                    "interface: ",
-                                    new String(rdp.getData(), 0,
-                                            rdp.getLength()).equals(msg));
+                                    "Group member received data on other interface when only asked for it on one interface: ",
+                                    new String(server.rdp.getData(), 0,
+                                            server.rdp.getLength()).equals(msg));
                         }
 
                         server.stopServer();
                     }
-                }
+                
 
                 // validate that we can join the same address on two
                 // different interfaces but not on the same interface
@@ -748,373 +556,252 @@
                 mss.joinGroup(groupSockAddr, networkInterface2);
                 try {
                     mss.joinGroup(groupSockAddr, networkInterface1);
-                    fail("Did not get expected exception when joining for " +
-                            "second time on same interface");
+                    fail("Did not get expected exception when joining for second time on same interface");
                 } catch (IOException e) {
                 }
             }
         }
-        System.setSecurityManager(null);
-    }
+		System.setSecurityManager(null);
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#leaveGroup(java.net.InetAddress)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "leaveGroup",
-        args = {java.net.InetAddress.class}
-    )
-    public void test_leaveGroupLjava_net_InetAddress() {
-        // Test for method void
-        // java.net.MulticastSocket.leaveGroup(java.net.InetAddress)
-        String msg = null;
-        boolean except = false;
-        InetAddress group = null;
-        int[] ports = Support_PortManager.getNextPortsForUDP(2);
-        int groupPort = ports[0];
+	/**
+	 * @tests java.net.MulticastSocket#leaveGroup(java.net.InetAddress)
+	 */
+	public void test_leaveGroupLjava_net_InetAddress() {
+		// Test for method void
+		// java.net.MulticastSocket.leaveGroup(java.net.InetAddress)
+		String msg = null;
+		boolean except = false;
+		InetAddress group = null;
+		int[] ports = Support_PortManager.getNextPortsForUDP(2);
+		int groupPort = ports[0];
 
-        try {
-            group = InetAddress.getByName("224.0.0.3");
-            msg = "Hello World";
-            mss = new MulticastSocket(ports[1]);
-            DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
-                    .length(), group, groupPort);
-            mss.send(sdp, (byte) 10);
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (Exception e) {
-            handleException(e, SO_MULTICAST);
-        }
-        try {
-            // Try to leave s group that mss is not a member of
-            mss.leaveGroup(group);
-        } catch (java.io.IOException e) {
-            // Correct
-            except = true;
-        }
-        assertTrue("Failed to throw exception leaving non-member group", except);
-        
-        SecurityManager sm = new SecurityManager() {
+		try {
+			group = InetAddress.getByName("224.0.0.3");
+			msg = "Hello World";
+			mss = new MulticastSocket(ports[1]);
+			DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
+					.length(), group, groupPort);
+			mss.send(sdp, (byte) 10);
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST);
+		}
+		try {
+			// Try to leave s group that mss is not a member of
+			mss.leaveGroup(group);
+		} catch (java.io.IOException e) {
+			// Correct
+			except = true;
+		}
+		assertTrue("Failed to throw exception leaving non-member group", except);
+	}
 
-            public void checkPermission(Permission perm) {
-            }
-            
-            public void checkMulticast(InetAddress maddr) {
-                throw new SecurityException();
-            }
-        };
+	/**
+	 * @tests java.net.MulticastSocket#leaveGroup(java.net.SocketAddress,java.net.NetworkInterface)
+	 */
+	public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface() throws Exception {
+		// security manager that allows us to check that we only return the
+		// addresses that we should
+		class mySecurityManager extends SecurityManager {
 
-        SecurityManager oldSm = System.getSecurityManager();
-        System.setSecurityManager(sm);
-        try {
-            mss.leaveGroup(group);
-            fail("SecurityException should be thrown.");
-        } catch (SecurityException e) {
-            // expected
-        } catch (SocketException e) {
-            fail("SocketException was thrown.");
-        } catch (IOException e) {
-            fail("IOException was thrown.");
-            e.printStackTrace();
-        } finally {
-            System.setSecurityManager(oldSm);
-        } 
-    }
+			public void checkMulticast(InetAddress address) {
+				throw new SecurityException("not allowed");
+			}
+		}
 
-    /**
-     * @tests java.net.MulticastSocket#leaveGroup(java.net.SocketAddress,
-     * java.net.NetworkInterface)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "leaveGroup",
-        args = {java.net.SocketAddress.class, java.net.NetworkInterface.class}
-    )
-    public void test_leaveGroupLjava_net_SocketAddressLjava_net_NetworkInterface() {
-        // security manager that allows us to check that we only return the
-        // addresses that we should
-        class mySecurityManager extends SecurityManager {
-            
-            public void checkPermission(Permission p) {
-            }
+		String msg = null;
+		InetAddress group = null;
+		int groupPort = Support_PortManager.getNextPortForUDP();
+		SocketAddress groupSockAddr = null;
+		SocketAddress groupSockAddr2 = null;
 
-            public void checkMulticast(InetAddress address) {
-                throw new SecurityException("not allowed");
-            }
-        }
+                Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
 
-        String msg = null;
-        InetAddress group = null;
-        int groupPort = Support_PortManager.getNextPortForUDP();
-        SocketAddress groupSockAddr = null;
-        SocketAddress groupSockAddr2 = null;
-
-        try {
-            Enumeration theInterfaces = NetworkInterface.getNetworkInterfaces();
-
-            // first validate that we handle a null group ok
-            mss = new MulticastSocket(groupPort);
-            try {
-                mss.leaveGroup(null, null);
-                fail("Did not get exception when group was null");
-            } catch (IllegalArgumentException e) {
-            }
-
-            // now validate we get the expected error if the address specified
-            // is not a multicast group
-            try {
-                group = InetAddress.getByName("255.255.255.255");
-                groupSockAddr = new InetSocketAddress(group, groupPort);
-                mss.leaveGroup(groupSockAddr, null);
-                fail("Did not get exception when group is not a " +
-                        "multicast address");
-            } catch (IOException e) {
-            }
-
-            // now try to leave a group if we are not authorized
-            // set the security manager that will make the first address not
-            // visible
-            System.setSecurityManager(new mySecurityManager());
-            try {
-                group = InetAddress.getByName("224.0.0.3");
-                groupSockAddr = new InetSocketAddress(group, groupPort);
-                mss.leaveGroup(groupSockAddr, null);
-                fail("Did not get exception when joining group is " +
-                        "not allowed");
-            } catch (SecurityException e) {
-            }
-            System.setSecurityManager(null);
-
-            if (atLeastOneInterface) {
-
-                // now test that we can join and leave a group successfully
-                groupPort = Support_PortManager.getNextPortForUDP();
+                // first validate that we handle a null group ok
                 mss = new MulticastSocket(groupPort);
-                groupSockAddr = new InetSocketAddress(group, groupPort);
-                mss.joinGroup(groupSockAddr, null);
-                mss.leaveGroup(groupSockAddr, null);
                 try {
-                    mss.leaveGroup(groupSockAddr, null);
-                    fail(
-                            "Did not get exception when trying to leave " +
-                            "group that was allready left");
+                        mss.leaveGroup(null, null);
+                        fail("Did not get exception when group was null");
+                } catch (IllegalArgumentException e) {
+                }
+
+                // now validate we get the expected error if the address specified
+                // is not a multicast group
+                try {
+                        group = InetAddress.getByName("255.255.255.255");
+                        groupSockAddr = new InetSocketAddress(group, groupPort);
+                        mss.leaveGroup(groupSockAddr, null);
+                        fail("Did not get exception when group is not a multicast address");
                 } catch (IOException e) {
                 }
 
-                InetAddress group2 = InetAddress.getByName("224.0.0.4");
-                groupSockAddr2 = new InetSocketAddress(group2, groupPort);
-                mss.joinGroup(groupSockAddr, networkInterface1);
+                // now try to leave a group if we are not authorized
+                // set the security manager that will make the first address not
+                // visible
+                System.setSecurityManager(new mySecurityManager());
                 try {
-                    mss.leaveGroup(groupSockAddr2, networkInterface1);
-                    fail(
-                            "Did not get exception when trying to leave " +
-                            "group that was never joined");
-                } catch (IOException e) {
+                        group = InetAddress.getByName("224.0.0.3");
+                        groupSockAddr = new InetSocketAddress(group, groupPort);
+                        mss.leaveGroup(groupSockAddr, null);
+                        fail("Did not get exception when joining group is not allowed");
+                } catch (SecurityException e) {
+                }
+                System.setSecurityManager(null);
+
+                if (atLeastOneInterface) {
+
+                        // now test that we can join and leave a group successfully
+                        groupPort = Support_PortManager.getNextPortForUDP();
+                        mss = new MulticastSocket(groupPort);
+                        groupSockAddr = new InetSocketAddress(group, groupPort);
+                        mss.joinGroup(groupSockAddr, null);
+                        mss.leaveGroup(groupSockAddr, null);
+                        try {
+                                mss.leaveGroup(groupSockAddr, null);
+                                fail(
+                                                "Did not get exception when trying to leave group that was allready left");
+                        } catch (IOException e) {
+                        }
+
+                        InetAddress group2 = InetAddress.getByName("224.0.0.4");
+                        groupSockAddr2 = new InetSocketAddress(group2, groupPort);
+                        mss.joinGroup(groupSockAddr, networkInterface1);
+                        try {
+                                mss.leaveGroup(groupSockAddr2, networkInterface1);
+                                fail(
+                                                "Did not get exception when trying to leave group that was never joined");
+                        } catch (IOException e) {
+                        }
+
+                        mss.leaveGroup(groupSockAddr, networkInterface1);
+                        if (atLeastTwoInterfaces) {
+                                mss.joinGroup(groupSockAddr, networkInterface1);
+                                try {
+                                        mss.leaveGroup(groupSockAddr, networkInterface2);
+                                        fail(
+                                                        "Did not get exception when trying to leave group on wrong interface joined on ["
+                                                                        + networkInterface1
+                                                                        + "] left on ["
+                                                                        + networkInterface2 + "]");
+                                } catch (IOException e) {
+                                }
+                        }
                 }
 
-                mss.leaveGroup(groupSockAddr, networkInterface1);
-                if (atLeastTwoInterfaces) {
-                    mss.joinGroup(groupSockAddr, networkInterface1);
-                    try {
-                        mss.leaveGroup(groupSockAddr, networkInterface2);
-                        fail(
-                                "Did not get exception when trying to leave " +
-                                "group on wrong interface joined on ["
-                                        + networkInterface1
-                                        + "] left on ["
-                                        + networkInterface2 + "]");
-                    } catch (IOException e) {
-                    }
-                }
-            }
-        } catch (Exception e) {
-            fail("Exception during leaveGroup test: " + e.toString());
-        } finally {
-            System.setSecurityManager(null);
-        }
-    }
+                System.setSecurityManager(null);
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#send(java.net.DatagramPacket, byte)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "send",
-        args = {java.net.DatagramPacket.class, byte.class}
-    )
-    public void test_sendLjava_net_DatagramPacketB() throws InterruptedException {
-        // Test for method void
-        // java.net.MulticastSocket.send(java.net.DatagramPacket, byte)
+	/**
+	 * @tests java.net.MulticastSocket#send(java.net.DatagramPacket, byte)
+	 */
+	public void test_sendLjava_net_DatagramPacketB() {
+		// Test for method void
+		// java.net.MulticastSocket.send(java.net.DatagramPacket, byte)
 
-        String msg = "Hello World";
-        InetAddress group = null;
-        int[] ports = Support_PortManager.getNextPortsForUDP(2);
-        int groupPort = ports[0];
+		String msg = "Hello World";
+		InetAddress group = null;
+		int[] ports = Support_PortManager.getNextPortsForUDP(2);
+		int groupPort = ports[0];
 
-        try {
-            group = InetAddress.getByName("224.0.0.3");
-            mss = new MulticastSocket(ports[1]);
-            server = new MulticastServer(group, groupPort);
-            server.start();
-            Thread.sleep(200);
-            DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
-                    .length(), group, groupPort);
-            mss.send(sdp, (byte) 10);
-            Thread.sleep(1000);
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (Exception e) {
-            handleException(e, SO_MULTICAST);
-            try {
-                mss.close();
-            } catch (Exception ex) {
-            }
-            
-            return;
-        }
-        
-        DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
-                .length(), group, groupPort);
+		try {
+			group = InetAddress.getByName("224.0.0.3");
+			mss = new MulticastSocket(ports[1]);
+			server = new MulticastServer(group, groupPort);
+			server.start();
+			Thread.sleep(200);
+			DatagramPacket sdp = new DatagramPacket(msg.getBytes(), msg
+					.length(), group, groupPort);
+			mss.send(sdp, (byte) 10);
+			Thread.sleep(1000);
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST);
+			try {
+				mss.close();
+			} catch (Exception ex) {
+			}
+			;
+			return;
+		}
+		mss.close();
+		byte[] data = server.rdp.getData();
+		int length = server.rdp.getLength();
+		assertEquals("Failed to send data. Received " + length,
+                             msg, new String(data, 0, length));
+	}
 
-        
-        SecurityManager sm = new SecurityManager() {
+	/**
+	 * @tests java.net.MulticastSocket#setInterface(java.net.InetAddress)
+	 */
+	public void test_setInterfaceLjava_net_InetAddress() throws UnknownHostException {
+		// Test for method void
+		// java.net.MulticastSocket.setInterface(java.net.InetAddress)
+		// Note that the machine is not multi-homed
 
-            public void checkPermission(Permission perm) {
-            }
-            
-            public void checkConnect(String host,
-                    int port) {
-                throw new SecurityException();
-            }
-            
-            public void checkMulticast(InetAddress maddr) {
-                throw new SecurityException();
-            }
-        };
+		try {
+			mss = new MulticastSocket();
+			mss.setInterface(InetAddress.getLocalHost());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST_INTERFACE);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST_INTERFACE);
+			return;
+		}
+		try {
+			InetAddress theInterface = mss.getInterface();
+			// under IPV6 we are not guarrenteed to get the same address back as
+			// the address, all we should be guaranteed is that we get an
+			// address on the same interface
+			if (theInterface instanceof Inet6Address) {
+				assertTrue(
+						"Failed to return correct interface IPV6",
+						NetworkInterface
+								.getByInetAddress(mss.getInterface())
+								.equals(
+										NetworkInterface
+												.getByInetAddress(theInterface)));
+			} else {
+				assertTrue("Failed to return correct interface IPV4 got:"
+						+ mss.getInterface() + " excpeted: "
+						+ InetAddress.getLocalHost(), mss.getInterface()
+						.equals(InetAddress.getLocalHost()));
+			}
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (SocketException e) {
+			handleException(e, SO_MULTICAST);
+		}
 
-        SecurityManager oldSm = System.getSecurityManager();
-        System.setSecurityManager(sm);
-        try {
-            mss.send(sdp);
-            fail("SecurityException should be thrown.");
-        } catch (SecurityException e) {
-            // expected
-        } catch (SocketException e) {
-            fail("SocketException was thrown.");
-        } catch (IOException e) {
-            fail("IOException was thrown.");
-            e.printStackTrace();
-        } finally {
-            System.setSecurityManager(oldSm);
-        } 
-        
-        mss.close();
-        
-        try {
-            mss.send(sdp);
-            fail("IOException should be thrown.");
-        } catch(IOException ioe) {
-            //expected
-        }
+		// Regression test for Harmony-2410
+		try {
+			mss = new MulticastSocket();
+			mss.setInterface(InetAddress.getByName("224.0.0.5"));
+		} catch (SocketException se) {
+			// expected
+		} catch (IOException ioe) {
+			handleException(ioe, SO_MULTICAST_INTERFACE);
+			return;
+		}
+	}
 
-        DatagramPacket rdp = server.receive();
-        assertEquals("Failed to send data. Received " + rdp.getLength(), msg,
-                new String(rdp.getData(), 0, rdp.getLength()));
-    }
-
-    /**
-     * @tests java.net.MulticastSocket#setInterface(java.net.InetAddress)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "setInterface",
-        args = {java.net.InetAddress.class}
-    )
-    public void test_setInterfaceLjava_net_InetAddress() {
-        // Test for method void
-        // java.net.MulticastSocket.setInterface(java.net.InetAddress)
-        // Note that the machine is not multi-homed
-
-        try {
-            mss = new MulticastSocket();
-            mss.setInterface(InetAddress.getLocalHost());
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST_INTERFACE);
-        } catch (Exception e) {
-            //handleException(e, SO_MULTICAST_INTERFACE);
-            return;
-        }
-        try {
-            InetAddress theInterface = mss.getInterface();
-            // under IPV6 we are not guarrenteed to get the same address back as
-            // the address, all we should be guaranteed is that we get an
-            // address on the same interface
-            if (theInterface instanceof Inet6Address) {
-                assertTrue(
-                        "Failed to return correct interface IPV6",
-                        NetworkInterface
-                                .getByInetAddress(mss.getInterface())
-                                .equals(
-                                        NetworkInterface
-                                                .getByInetAddress(theInterface)));
-            } else {
-                assertTrue("Failed to return correct interface IPV4 got:"
-                        + mss.getInterface() + " excpeted: "
-                        + InetAddress.getLocalHost(), mss.getInterface()
-                        .equals(InetAddress.getLocalHost()));
-            }
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (SocketException e) {
-            handleException(e, SO_MULTICAST);
-        } catch (UnknownHostException e) {
-            fail("Exception during setInterface test: " + e.toString());
-        }
-
-        // Regression test for Harmony-2410
-        try {
-            mss = new MulticastSocket();
-            mss.setInterface(InetAddress.getByName("224.0.0.5"));
-        } catch (UnknownHostException uhe) {
-            fail("Unable to get InetAddress by name from '224.0.0.5' addr: " 
-                    + uhe.toString());
-        } catch (SocketException se) {
-            // expected
-        } catch (IOException ioe) {
-            handleException(ioe, SO_MULTICAST_INTERFACE);
-            return;
-        }
-    }
-
-    /**
-     * @throws IOException 
-     * @throws InterruptedException 
-     * @tests java.net.MulticastSocket#setNetworkInterface(
-     *                                              java.net.NetworkInterface)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "setNetworkInterface",
-        args = {java.net.NetworkInterface.class}
-    )
-    public void test_setNetworkInterfaceLjava_net_NetworkInterface() 
-                                    throws IOException, InterruptedException {
-        String msg = null;
-        InetAddress group = null;
-        int[] ports = Support_PortManager.getNextPortsForUDP(2);
-        int groupPort = ports[0];
-        int serverPort = ports[1];
-        if (atLeastOneInterface) {
+	/**
+	 * @throws IOException 
+	 * @throws InterruptedException 
+	 * @tests java.net.MulticastSocket#setNetworkInterface(java.net.NetworkInterface)
+	 */
+	public void test_setNetworkInterfaceLjava_net_NetworkInterface() throws IOException, InterruptedException {
+		String msg = null;
+		InetAddress group = null;
+		int[] ports = Support_PortManager.getNextPortsForUDP(2);
+		int groupPort = ports[0];
+		int serverPort = ports[1];
+		if (atLeastOneInterface) {
             // validate that null interface is handled ok
             mss = new MulticastSocket(groupPort);
 
             // this should through a socket exception to be compatible
             try {
                 mss.setNetworkInterface(null);
-                fail("No socket exception when we set then network " +
-                        "interface with NULL");
+                fail("No socket exception when we set then network interface with NULL");
             } catch (SocketException ex) {
             }
 
@@ -1122,9 +809,8 @@
             groupPort = Support_PortManager.getNextPortForUDP();
             mss = new MulticastSocket(groupPort);
             mss.setNetworkInterface(networkInterface1);
-            assertTrue(
-                    "Interface did not seem to be set by setNeworkInterface",
-                    networkInterface1.equals(mss.getNetworkInterface()));
+            assertEquals("Interface did not seem to be set by setNeworkInterface",
+                         networkInterface1, mss.getNetworkInterface());
 
             // set up the server and join the group
             group = InetAddress.getByName("224.0.0.3");
@@ -1133,8 +819,7 @@
             while (theInterfaces.hasMoreElements()) {
                 NetworkInterface thisInterface = (NetworkInterface) theInterfaces
                         .nextElement();
-                if (thisInterface.getInetAddresses() != null
-                        && thisInterface.getInetAddresses().hasMoreElements()) {
+                if (thisInterface.getInetAddresses().hasMoreElements()) {
                     if ((!((InetAddress) thisInterface.getInetAddresses()
                             .nextElement()).isLoopbackAddress())
                             &&
@@ -1163,95 +848,57 @@
                         DatagramPacket sdp = new DatagramPacket(theBytes,
                                 theBytes.length, group, serverPort);
                         mss.send(sdp);
-                        DatagramPacket rdp = server.receive();
-
-                        String receivedMessage = new String(rdp.getData(), 0, rdp.getLength());
-                        assertEquals("Group member did not recv data when send on "
-                                + "a specific interface: ", msg, receivedMessage);
-                        assertEquals("Datagram was not received as expected.",
-                                thisInterface, NetworkInterface.getByInetAddress(rdp.getAddress()));
-
+                        Thread.sleep(1000);
+                        String receivedMessage = new String(server.rdp
+                                .getData(), 0, server.rdp.getLength());
+                        assertEquals("Group member did not recv data sent on a specific interface",
+                                     msg, receivedMessage);
                         // stop the server
                         server.stopServer();
                     }
                 }
             }
         }
-    }
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#setTimeToLive(int)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "setTimeToLive",
-        args = {int.class}
-    )
-    public void test_setTimeToLiveI() {
-        try {
-            mss = new MulticastSocket();
-            mss.setTimeToLive(120);
-            assertTrue("Returned incorrect 1st TTL: " + mss.getTimeToLive(),
-                    mss.getTimeToLive() == 120);
-            mss.setTimeToLive(220);
-            assertTrue("Returned incorrect 2nd TTL: " + mss.getTimeToLive(),
-                    mss.getTimeToLive() == 220);
-            mss.close();
-            try {
-                mss.setTimeToLive(1);
-                fail("IOException was not thrown.");
-            }catch(IOException ioe) {
-                //expected
-            } 
-            
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (Exception e) {
-            handleException(e, SO_MULTICAST);
-        }
-    }
+	/**
+	 * @tests java.net.MulticastSocket#setTimeToLive(int)
+	 */
+	public void test_setTimeToLiveI() {
+		try {
+			mss = new MulticastSocket();
+			mss.setTimeToLive(120);
+			assertEquals("Returned incorrect 1st TTL",
+                                     120, mss.getTimeToLive());
+			mss.setTimeToLive(220);
+			assertEquals("Returned incorrect 2nd TTL",
+                                     220, mss.getTimeToLive());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST);
+		}
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#setTTL(byte)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "setTTL",
-        args = {byte.class}
-    )
-    public void test_setTTLB() {
-        // Test for method void java.net.MulticastSocket.setTTL(byte)
-        try {
-            mss = new MulticastSocket();
-            mss.setTTL((byte) 120);
-            assertTrue("Failed to set TTL: " + mss.getTTL(),
-                    mss.getTTL() == 120);
-            
-            mss.close();
-            try {
-                mss.setTTL((byte) 1);
-                fail("IOException was not thrown.");
-            } catch(IOException ioe) {
-                //expected
-            } 
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
-        } catch (Exception e) {
-            handleException(e, SO_MULTICAST);
-        }
-    }
+	/**
+	 * @tests java.net.MulticastSocket#setTTL(byte)
+	 */
+	public void test_setTTLB() {
+		// Test for method void java.net.MulticastSocket.setTTL(byte)
+		try {
+			mss = new MulticastSocket();
+			mss.setTTL((byte) 120);
+			assertEquals("Failed to set TTL", 120, mss.getTTL());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_MULTICAST);
+		} catch (Exception e) {
+			handleException(e, SO_MULTICAST);
+		}
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#MulticastSocket(java.net.SocketAddress)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "MulticastSocket",
-        args = {java.net.SocketAddress.class}
-    )
-    public void test_ConstructorLjava_net_SocketAddress() throws Exception {    
-        MulticastSocket ms = new MulticastSocket((SocketAddress) null);
+	/**
+	 * @tests java.net.MulticastSocket#MulticastSocket(java.net.SocketAddress)
+	 */
+	public void test_ConstructorLjava_net_SocketAddress() throws Exception {	
+		MulticastSocket ms = new MulticastSocket((SocketAddress) null);
         assertTrue("should not be bound", !ms.isBound() && !ms.isClosed()
                 && !ms.isConnected());
         ms.bind(new InetSocketAddress(InetAddress.getLocalHost(),
@@ -1285,109 +932,48 @@
         InetSocketAddress addr = new InetSocketAddress("0.0.0.0", 0);
         MulticastSocket s = new MulticastSocket(addr);
         assertTrue(s.getReuseAddress()); 
-        
-        InetSocketAddress isa = new InetSocketAddress(InetAddress
-                .getLocalHost(), Support_PortManager.getNextPortForUDP());
-        
-        SecurityManager sm = new SecurityManager() {
+	}
 
-            public void checkPermission(Permission perm) {
-            }
-            
-            public void checkListen(int port) {
-                throw new SecurityException();
-            }
-        };
-        
-        SecurityManager oldSm = System.getSecurityManager();
-        System.setSecurityManager(sm);
-        try {
-            new MulticastSocket(isa);
-            fail("SecurityException should be thrown.");
-        } catch (SecurityException e) {
-            // expected
-        } catch (SocketException e) {
-            fail("SocketException was thrown.");
-        } catch (IOException e) {
-            fail("IOException was thrown.");
-            e.printStackTrace();
-        } finally {
-            System.setSecurityManager(oldSm);
-        }  
-    }
+	/**
+	 * @tests java.net.MulticastSocket#getLoopbackMode()
+	 */
+	public void test_getLoopbackMode() {
+		try {
+			MulticastSocket ms = new MulticastSocket((SocketAddress) null);
+			assertTrue("should not be bound", !ms.isBound() && !ms.isClosed()
+					&& !ms.isConnected());
+			ms.getLoopbackMode();
+			assertTrue("should not be bound", !ms.isBound() && !ms.isClosed()
+					&& !ms.isConnected());
+			ms.close();
+			assertTrue("should be closed", ms.isClosed());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_USELOOPBACK);
+		} catch (IOException e) {
+			handleException(e, SO_USELOOPBACK);
+		}
+	}
 
-    /**
-     * @tests java.net.MulticastSocket#getLoopbackMode()
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "getLoopbackMode",
-        args = {}
-    )
-    public void test_getLoopbackMode() {
-        try {
-            MulticastSocket ms = new MulticastSocket((SocketAddress) null);
-            assertTrue("should not be bound", !ms.isBound() && !ms.isClosed()
-                    && !ms.isConnected());
-            ms.getLoopbackMode();
-            assertTrue("should not be bound", !ms.isBound() && !ms.isClosed()
-                    && !ms.isConnected());
-            ms.close();
-            assertTrue("should be closed", ms.isClosed());
-            try {
-                ms.getLoopbackMode();
-                fail("SocketException was not thrown.");
-            } catch(SocketException ioe) {
-                //expected
-            }
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_USELOOPBACK);
-        } catch (IOException e) {
-            handleException(e, SO_USELOOPBACK);
-        }
-    }
-
-    /**
-     * @tests java.net.MulticastSocket#setLoopbackMode(boolean)
-     */
-    @TestTargetNew(
-        level = TestLevel.COMPLETE,
-        notes = "",
-        method = "setLoopbackMode",
-        args = {boolean.class}
-    )
-    public void test_setLoopbackModeZ() {
-        try {
-            MulticastSocket ms = new MulticastSocket();
-            ms.setLoopbackMode(true);
-            assertTrue("loopback should be true", ms.getLoopbackMode());
-            ms.setLoopbackMode(false);
-            assertTrue("loopback should be false", !ms.getLoopbackMode());
-            ms.close();
-            assertTrue("should be closed", ms.isClosed());
-            
-            try {
-                ms.setLoopbackMode(true);
-                fail("SocketException was not thrown.");
-            } catch(SocketException se) {
-                //expected
-            }
-            
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_USELOOPBACK);
-        } catch (IOException e) {
-            handleException(e, SO_USELOOPBACK);
-        }
-    }
+	/**
+	 * @tests java.net.MulticastSocket#setLoopbackMode(boolean)
+	 */
+	public void test_setLoopbackModeZ() {
+		try {
+			MulticastSocket ms = new MulticastSocket();
+			ms.setLoopbackMode(true);
+			assertTrue("loopback should be true", ms.getLoopbackMode());
+			ms.setLoopbackMode(false);
+			assertTrue("loopback should be false", !ms.getLoopbackMode());
+			ms.close();
+			assertTrue("should be closed", ms.isClosed());
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_USELOOPBACK);
+		} catch (IOException e) {
+			handleException(e, SO_USELOOPBACK);
+		}
+	}
     
     /**
      * @tests java.net.MulticastSocket#setLoopbackMode(boolean)
      */
-    @TestTargetNew(
-        level = TestLevel.ADDITIONAL,
-        notes = "SocketException checking missed",
-        method = "setLoopbackMode",
-        args = {boolean.class}
-    )
     public void test_setLoopbackModeSendReceive() throws IOException{
         final String ADDRESS = "224.1.2.3";
         final int PORT = Support_PortManager.getNextPortForUDP();
@@ -1418,120 +1004,99 @@
             String recvMessage = new String(recvData, 0, recvDatagram
                     .getLength());
             assertEquals(message, recvMessage);
-        } finally {
+        }finally {
             if (socket != null)
                 socket.close();
         }
     }
     
     
-    /**
-     * @tests java.net.MulticastSocket#setReuseAddress(boolean)
-     */
-    @TestTargetNew(
-        level = TestLevel.PARTIAL,
-        notes = "SocketException checking missesd. Method inherited from " +
-                "class java.net.DatagramSocket",
-        method = "setReuseAddress",
-        args = {boolean.class}
-    )
-    public void test_setReuseAddressZ() {
-        try {
-            // test case were we set it to false
-            MulticastSocket theSocket1 = null;
-            MulticastSocket theSocket2 = null;
-            try {
-                InetSocketAddress theAddress = new InetSocketAddress(
-                        InetAddress.getLocalHost(), Support_PortManager
-                                .getNextPortForUDP());
-                theSocket1 = new MulticastSocket(null);
-                theSocket2 = new MulticastSocket(null);
-                theSocket1.setReuseAddress(false);
-                theSocket2.setReuseAddress(false);
-                theSocket1.bind(theAddress);
-                theSocket2.bind(theAddress);
-                fail(
-                        "No exception when trying to connect to do " +
-                        "duplicate socket bind with re-useaddr set to false");
-            } catch (BindException e) {
+	/**
+	 * @tests java.net.MulticastSocket#setReuseAddress(boolean)
+	 */
+	public void test_setReuseAddressZ() throws Exception {
+		try {
+			// test case were we set it to false
+			MulticastSocket theSocket1 = null;
+			MulticastSocket theSocket2 = null;
+			try {
+				InetSocketAddress theAddress = new InetSocketAddress(
+						InetAddress.getLocalHost(), Support_PortManager
+								.getNextPortForUDP());
+				theSocket1 = new MulticastSocket(null);
+				theSocket2 = new MulticastSocket(null);
+				theSocket1.setReuseAddress(false);
+				theSocket2.setReuseAddress(false);
+				theSocket1.bind(theAddress);
+				theSocket2.bind(theAddress);
+				fail(
+						"No exception when trying to connect to do duplicate socket bind with re-useaddr set to false");
+			} catch (BindException e) {
 
-            }
-            if (theSocket1 != null)
-                theSocket1.close();
-            if (theSocket2 != null)
-                theSocket2.close();
+			}
+			if (theSocket1 != null)
+				theSocket1.close();
+			if (theSocket2 != null)
+				theSocket2.close();
 
-            // test case were we set it to true
-            try {
-                InetSocketAddress theAddress = new InetSocketAddress(
-                        InetAddress.getLocalHost(), Support_PortManager
-                                .getNextPortForUDP());
-                theSocket1 = new MulticastSocket(null);
-                theSocket2 = new MulticastSocket(null);
-                theSocket1.setReuseAddress(true);
-                theSocket2.setReuseAddress(true);
-                theSocket1.bind(theAddress);
-                theSocket2.bind(theAddress);
-            } catch (Exception e) {
-                fail(
-                        "unexpected exception when trying to connect " +
-                        "to do duplicate socket bind with re-useaddr set " +
-                        "to true");
-            }
-            if (theSocket1 != null)
-                theSocket1.close();
-            if (theSocket2 != null)
-                theSocket2.close();
+			// test case were we set it to true
+                        InetSocketAddress theAddress = new InetSocketAddress(
+                                        InetAddress.getLocalHost(), Support_PortManager
+                                                        .getNextPortForUDP());
+                        theSocket1 = new MulticastSocket(null);
+                        theSocket2 = new MulticastSocket(null);
+                        theSocket1.setReuseAddress(true);
+                        theSocket2.setReuseAddress(true);
+                        theSocket1.bind(theAddress);
+                        theSocket2.bind(theAddress);
 
-            // test the default case which we expect to be the same on all
-            // platforms
-            try {
-                InetSocketAddress theAddress = new InetSocketAddress(
-                        InetAddress.getLocalHost(), Support_PortManager
-                                .getNextPortForUDP());
-                theSocket1 = new MulticastSocket(null);
-                theSocket2 = new MulticastSocket(null);
-                theSocket1.bind(theAddress);
-                theSocket2.bind(theAddress);
-            } catch (BindException e) {
-                fail(
-                        "unexpected exception when trying to connect to do " +
-                        "duplicate socket bind with re-useaddr left as default");
-            }
-            if (theSocket1 != null)
-                theSocket1.close();
-            if (theSocket2 != null)
-                theSocket2.close();
-            ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_REUSEADDR);
-        } catch (Exception e) {
-            handleException(e, SO_REUSEADDR);
-        }
-    }
+                        if (theSocket1 != null)
+				theSocket1.close();
+			if (theSocket2 != null)
+				theSocket2.close();
 
-    /**
-     * Sets up the fixture, for example, open a network connection. This method
-     * is called before a test is executed.
-     */
-    protected void setUp() {
+			// test the default case which we expect to be
+			// the same on all platforms
+                        theAddress =
+                            new InetSocketAddress(
+                                    InetAddress.getLocalHost(),
+                                    Support_PortManager.getNextPortForUDP());
+                        theSocket1 = new MulticastSocket(null);
+                        theSocket2 = new MulticastSocket(null);
+                        theSocket1.bind(theAddress);
+                        theSocket2.bind(theAddress);
+			if (theSocket1 != null)
+				theSocket1.close();
+			if (theSocket2 != null)
+				theSocket2.close();
+			ensureExceptionThrownIfOptionIsUnsupportedOnOS(SO_REUSEADDR);
+		} catch (Exception e) {
+			handleException(e, SO_REUSEADDR);
+		}
+	}
 
-        Enumeration theInterfaces = null;
-        try {
-            theInterfaces = NetworkInterface.getNetworkInterfaces();
-        } catch (Exception e) {
-        }
+	/**
+	 * Sets up the fixture, for example, open a network connection. This method
+	 * is called before a test is executed.
+	 */
+	protected void setUp() {
 
-        // only consider interfaces that have addresses associated with them.
-        // Otherwise tests don't work so well
-        if (theInterfaces != null) {
+		Enumeration theInterfaces = null;
+		try {
+			theInterfaces = NetworkInterface.getNetworkInterfaces();
+		} catch (Exception e) {
+		}
 
-            atLeastOneInterface = false;
-            while (theInterfaces.hasMoreElements()
+		// only consider interfaces that have addresses associated with them.
+		// Otherwise tests don't work so well
+		if (theInterfaces != null) {
+
+			atLeastOneInterface = false;
+			while (theInterfaces.hasMoreElements()
                     && (atLeastOneInterface == false)) {
                 networkInterface1 = (NetworkInterface) theInterfaces
                         .nextElement();
-                if ((networkInterface1.getInetAddresses() != null)
-                        && networkInterface1.getInetAddresses()
-                                .hasMoreElements() &&
+                if (networkInterface1.getInetAddresses().hasMoreElements() &&
                         // we only want real interfaces
                         (Support_NetworkInterface
                                 .useInterface(networkInterface1) == true)) {
@@ -1539,15 +1104,14 @@
                 }
             }
 
-            atLeastTwoInterfaces = false;
-            if (theInterfaces.hasMoreElements()) {
+			atLeastTwoInterfaces = false;
+			if (theInterfaces.hasMoreElements()) {
                 while (theInterfaces.hasMoreElements()
                         && (atLeastTwoInterfaces == false)) {
                     networkInterface2 = (NetworkInterface) theInterfaces
                             .nextElement();
-                    if ((networkInterface2.getInetAddresses() != null)
-                            && networkInterface2.getInetAddresses()
-                                    .hasMoreElements() &&
+                    if (networkInterface2.getInetAddresses().hasMoreElements()
+                            &&
                             // we only want real interfaces
                             (Support_NetworkInterface
                                     .useInterface(networkInterface2) == true)) {
@@ -1556,44 +1120,44 @@
                 }
             }
 
-            Enumeration addresses;
+			Enumeration addresses;
 
-            // first the first interface that supports IPV6 if one exists
-            try {
-                theInterfaces = NetworkInterface.getNetworkInterfaces();
-            } catch (Exception e) {
-            }
-            boolean found = false;
-            while (theInterfaces.hasMoreElements() && !found) {
-                NetworkInterface nextInterface = (NetworkInterface) theInterfaces
-                        .nextElement();
-                addresses = nextInterface.getInetAddresses();
-                if (addresses != null) {
-                    while (addresses.hasMoreElements()) {
-                        InetAddress nextAddress = (InetAddress) addresses
-                                .nextElement();
-                        if (nextAddress instanceof Inet6Address) {
-                            IPV6networkInterface1 = nextInterface;
-                            found = true;
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-    }
+			// first the first interface that supports IPV6 if one exists
+			try {
+				theInterfaces = NetworkInterface.getNetworkInterfaces();
+			} catch (Exception e) {
+			}
+			boolean found = false;
+			while (theInterfaces.hasMoreElements() && !found) {
+				NetworkInterface nextInterface = (NetworkInterface) theInterfaces
+						.nextElement();
+				addresses = nextInterface.getInetAddresses();
+				if (addresses.hasMoreElements()) {
+					while (addresses.hasMoreElements()) {
+						InetAddress nextAddress = (InetAddress) addresses
+								.nextElement();
+						if (nextAddress instanceof Inet6Address) {
+							IPV6networkInterface1 = nextInterface;
+							found = true;
+							break;
+						}
+					}
+				}
+			}
+		}
+	}
 
-    /**
-     * Tears down the fixture, for example, close a network connection. This
-     * method is called after a test is executed.
-     */
-    protected void tearDown() throws InterruptedException {
+	/**
+	 * Tears down the fixture, for example, close a network connection. This
+	 * method is called after a test is executed.
+	 */
+	protected void tearDown() {
 
-        if (t != null)
-            t.interrupt();
-        if (mss != null)
-            mss.close();
-        if (server != null)
-            server.stopServer();
-    }
+		if (t != null)
+			t.interrupt();
+		if (mss != null)
+			mss.close();
+		if (server != null)
+			server.stopServer();
+	}
 }
diff --git a/libcore/luni/src/test/java/tests/api/java/net/SocketTest.java b/libcore/luni/src/test/java/tests/api/java/net/SocketTest.java
index 7cc31a0..b8184a5 100644
--- a/libcore/luni/src/test/java/tests/api/java/net/SocketTest.java
+++ b/libcore/luni/src/test/java/tests/api/java/net/SocketTest.java
@@ -501,72 +501,14 @@
         args = {}
     )
     public void test_getInputStream() throws IOException {
-        System.setSecurityManager(null);
-        
-        // Test for method java.io.InputStream java.net.Socket.getInputStream()
-        int sport = startServer("SServer getInputStream");
-        int portNumber = Support_PortManager.getNextPort();
-        s = new Socket(InetAddress.getLocalHost(), sport, null, portNumber);
-        (t = new SServer()).start();
-        java.io.InputStream is = s.getInputStream();
+        // Simple fetch test
+        ServerSocket server = new ServerSocket(0);
+        Socket client = new Socket(InetAddress.getLocalHost(), server.getLocalPort());
+        InputStream is = client.getInputStream();
         assertNotNull("Failed to get stream", is);
-        s.setSoTimeout(6000);
-        is.read();
-        s.close();
-        assertEquals("Invalid after close", -1, is.read());
-
-        interrupted = false;
-        int portNum = Support_PortManager.getNextPort();
-        final ServerSocket ss = new ServerSocket(portNum);
-        Socket sock = new Socket(InetAddress.getLocalHost(), portNum);
-        Runnable runnable = new Runnable() {
-            public void run() {
-                try {
-                    Socket as = ss.accept();
-                    ss.close();
-                    as.setSoTimeout(12000);
-                    InputStream in = as.getInputStream();
-                    in.read();
-                    in.close();
-                } catch (InterruptedIOException e) {
-                    interrupted = true;
-                } catch (IOException e) {
-                }
-            }
-        };
-        Thread thread = new Thread(runnable, "Socket.getInputStream");
-        thread.start();
-        try {
-            do {
-                Thread.sleep(200);
-            } while (!thread.isAlive());
-        } catch (InterruptedException e) {
-        }
-        try {
-            Thread.sleep(200);
-        } catch (InterruptedException e) {
-        }
-        sock.close();
-        try {
-            sock.getInputStream();
-            fail("IOException was not thrown.");
-        } catch(IOException ioe) {
-            //expected
-        }
-        int c = 0;
-        do {
-            try {
-                Thread.sleep(200);
-            } catch (InterruptedException e) {
-            }
-            if (interrupted) {
-                fail("read interrupted");
-            }
-            if (++c > 4) {
-                fail("read call did not exit");
-            }
-        } while (thread.isAlive());
-
+        is.close();
+        client.close();
+        server.close();
     }
 
     /**
diff --git a/libcore/luni/src/test/java/tests/api/java/net/UnixSocketTest.java b/libcore/luni/src/test/java/tests/api/java/net/UnixSocketTest.java
new file mode 100644
index 0000000..4688e34
--- /dev/null
+++ b/libcore/luni/src/test/java/tests/api/java/net/UnixSocketTest.java
@@ -0,0 +1,135 @@
+/*
+ *  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.
+ */
+
+// BEGIN android-changed
+package tests.api.java.net;
+//package org.apache.harmony.luni.tests.java.net;
+// END android-changed
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.ConnectException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketException;
+
+import junit.framework.TestCase;
+
+public class UnixSocketTest extends TestCase {
+
+    /**
+     * @tests java.net.Socket#getInputStream()
+     */
+    public void test_getInputStream() throws IOException {
+        // Simple read/write test over the IO streams
+        final ServerSocket pingServer = new ServerSocket(0);
+        Runnable runnable = new Runnable() {
+            public void run() {
+                try {
+                    Socket worker = pingServer.accept();
+                    pingServer.close();
+                    InputStream in = worker.getInputStream();
+                    in.read();
+                    OutputStream out = worker.getOutputStream();
+                    out.write(new byte[42]);
+                    worker.close();
+                } catch (IOException e) {
+                    fail(e.getMessage());
+                }
+            }
+        };
+        Thread thread = new Thread(runnable, "UnixSocket.getInputStream");
+        thread.start();
+
+        Socket pingClient = new Socket(InetAddress.getLocalHost(), pingServer
+                .getLocalPort());
+
+        // Busy wait until the client is connected.
+        int c = 0;
+        while (!pingClient.isConnected()) {
+            try {
+                Thread.sleep(200);
+            } catch (InterruptedException e) {
+                // ignore
+            }
+            if (++c > 4) {
+                fail("thread is not alive");
+            }
+        }
+
+        // Write some data to the server to provoke it
+        OutputStream out = pingClient.getOutputStream();
+        out.write(new byte[256]);
+
+        InputStream in = pingClient.getInputStream();
+        in.read(new byte[42]);
+        try {
+            in.read();
+            fail("Should throw SocketException");
+        } catch (SocketException e) {
+            // expected
+        }
+        in.close();
+
+        try {
+            in.read();
+            fail("Should throw SocketException");
+        } catch (SocketException e) {
+            // expected
+        }
+        try {
+            in.read(new byte[5]);
+            fail("Should throw SocketException");
+        } catch (SocketException e) {
+            // expected
+        }
+
+        pingClient.close();
+        pingServer.close();
+    }
+
+    public void test_connectLjava_net_SocketAddressI() throws Exception {
+        // Now validate that we get a interrupted exception if we try to connect
+        // to an address on which nobody is accepting connections and the
+        // timeout expired
+        Socket theSocket = new Socket();
+        try {
+            theSocket.connect(new InetSocketAddress(InetAddress.getLocalHost(),
+                    1), 200);
+            fail("No interrupted exception when connecting to address nobody listening on with short timeout 200");
+        } catch (ConnectException e) {
+            // Expected
+        }
+        theSocket.close();
+    }
+
+    public void test_getOutputStream() throws Exception {
+        // Regression test for HARMONY-2934
+        Socket socket = new Socket("127.0.0.1", 0, false);
+        OutputStream o = socket.getOutputStream();
+        try {
+            o.write(1);
+        } catch (SocketException e) {
+            // expected
+        } finally {
+            socket.close();
+        }
+    }
+}
diff --git a/libcore/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java b/libcore/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
index 468a924..be9ab9e 100644
--- a/libcore/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
+++ b/libcore/nio/src/main/java/org/apache/harmony/nio/internal/SocketChannelImpl.java
@@ -454,9 +454,9 @@
                 int length = target.remaining();
                 if (target.isDirect()) {
                     // BEGIN android-changed
-                    // changed address from long to int; split address and offset paramters
+                    // changed address from long to int
                     int address = AddressUtil.getDirectBufferAddress(target);
-                    readCount = networkSystem.readDirect(fd, address, offset,
+                    readCount = networkSystem.readDirect(fd, address + offset,
                             length, (isBlocking() ? TIMEOUT_BLOCK
                                     : TIMEOUT_NONBLOCK));
                     // END android-changed
diff --git a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
index b474905..6489370 100644
--- a/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
+++ b/libcore/x-net/src/main/native/org_apache_harmony_xnet_provider_jsse_OpenSSLSocketImpl.cpp
@@ -1022,6 +1022,10 @@
      * and undesirable.)
      */
     mode |= SSL_MODE_ENABLE_PARTIAL_WRITE;
+    mode |= SSL_MODE_SMALL_BUFFERS;  /* lazily allocate record buffers; usually saves
+                                      * 44k over the default */
+    mode |= SSL_MODE_HANDSHAKE_CUTTHROUGH;  /* enable sending of client data as soon as
+                                             * ClientCCS and ClientFinished are sent */
     SSL_CTX_set_mode(ssl_ctx, mode);
 
     if (privatekey != NULL) {
diff --git a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java
index 46ec1d2..6eca114 100644
--- a/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java
+++ b/libcore/x-net/src/test/java/tests/api/javax/net/ssl/SSLSessionTest.java
@@ -34,6 +34,7 @@
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.security.KeyStore;
@@ -699,14 +700,15 @@
     boolean notFinished = true;
     SSLSession clientSession = null;
     SSLContext clientSslContext = null;
+    String testData = "PING";
     
     private String PASSWORD = "android";
 
     String cipherSuite = (useBKS ? cipherSuiteBKS : cipherSuiteJKS);
 
     /** 
-     * Implements a test SSL socket server. It wait for a connection on a given
-     * port, requests client authentication (if specified), and read 256 bytes
+     * Implements a test SSL socket server. It waits for a connection on a given
+     * port, requests client authentication (if specified), and reads
      * from the socket. 
      */
     class TestServer implements Runnable {
@@ -789,7 +791,7 @@
 
     /** 
      * Implements a test SSL socket client. It open a connection to localhost on
-     * a given port and writes 256 bytes to the socket. 
+     * a given port and writes to the socket. 
      */
     class TestClient implements Runnable {
         
@@ -822,6 +824,9 @@
                 SSLSocket socket = (SSLSocket)clientSslContext.getSocketFactory().createSocket();
 
                 socket.connect(new InetSocketAddress(port));
+                OutputStream ostream = socket.getOutputStream();
+                ostream.write(testData.getBytes());
+                ostream.flush();
 
                 clientSession = socket.getSession();
                 while (notFinished) {
diff --git a/tools/dmtracedump/CreateTestTrace.c b/tools/dmtracedump/CreateTestTrace.c
index 256f21a..9d72b1f 100644
--- a/tools/dmtracedump/CreateTestTrace.c
+++ b/tools/dmtracedump/CreateTestTrace.c
@@ -44,6 +44,7 @@
 
 #define VERSION 2
 int versionNumber = VERSION;
+int verbose = 0;
 
 DataHeader header = { 0x574f4c53, VERSION, sizeof(DataHeader), 0LL };
 
@@ -52,22 +53,22 @@
 
 char *keyThreads =
 "*threads\n"
-"1	main\n"
-"2	foo\n"
-"3	bar\n"
-"4	blah\n";
+"1      main\n"
+"2      foo\n"
+"3      bar\n"
+"4      blah\n";
 
 char *keyEnd = "*end\n";
 
 typedef struct dataRecord {
-    unsigned int	time;
-    int			threadId;
-    unsigned int	action;		/* 0=entry, 1=exit, 2=exception exit */
-    char		*fullName;
-    char		*className;
-    char		*methodName;
-    char		*signature;
-    unsigned int	methodId;
+    unsigned int        time;
+    int                 threadId;
+    unsigned int        action;         /* 0=entry, 1=exit, 2=exception exit */
+    char                *fullName;
+    char                *className;
+    char                *methodName;
+    char                *signature;
+    unsigned int        methodId;
 } dataRecord;
 
 dataRecord *records;
@@ -76,9 +77,8 @@
 char buf[BUF_SIZE];
 
 typedef struct stack {
-    dataRecord	**frames;
-    int		nextFrame;
-    int		indentLevel;
+    dataRecord  **frames;
+    int         indentLevel;
 } stack;
 
 /* Mac OS doesn't have strndup(), so implement it here.
@@ -124,7 +124,6 @@
     int nextRecord = 0;
     int indentLevel = 0;
     stack *callStack;
-    int nextFrame = 0;
 
     FILE *inputFp = fopen(inputFileName, "r");
     if (inputFp == NULL) {
@@ -133,13 +132,15 @@
     }
 
     /* Count the number of lines in the buffer */
-    int numLines = 0;
+    int numRecords = 0;
     int maxThreadId = 1;
+    int maxFrames = 0;
+    char *indentEnd;
     while (fgets(buf, BUF_SIZE, inputFp)) {
         char *cp = buf;
         if (*cp == '#')
             continue;
-        numLines += 1;
+        numRecords += 1;
         if (isdigit(*cp)) {
             int time = strtoul(cp, &cp, 0);
             while (isspace(*cp))
@@ -148,17 +149,22 @@
             if (maxThreadId < threadId)
                 maxThreadId = threadId;
         }
+        indentEnd = cp;
+        while (isspace(*indentEnd))
+            indentEnd += 1;
+        if (indentEnd - cp + 1 > maxFrames)
+            maxFrames = indentEnd - cp + 1;
     }
     int numThreads = maxThreadId + 1;
 
     /* Add space for a sentinel record at the end */
-    numLines += 1;
-    records = (dataRecord *) malloc(sizeof(dataRecord) * numLines);
+    numRecords += 1;
+    records = (dataRecord *) malloc(sizeof(dataRecord) * numRecords);
     callStack = (stack *) malloc(sizeof(stack) * numThreads);
     int ii;
     for (ii = 0; ii < numThreads; ++ii) {
         callStack[ii].frames = NULL;
-        callStack[ii].nextFrame = 0;
+        callStack[ii].indentLevel = 0;
     }
 
     rewind(inputFp);
@@ -169,9 +175,12 @@
 
         linenum += 1;
         char *cp = buf;
+
         /* Skip lines that start with '#' */
         if (*cp == '#')
             continue;
+
+        /* Get time and thread id */
         if (!isdigit(*cp)) {
             /* If the line does not begin with a digit, then fill in
              * default values for the time and threadId.
@@ -189,10 +198,9 @@
         // Allocate space for the thread stack, if necessary
         if (callStack[threadId].frames == NULL) {
             dataRecord **stk;
-            stk = (dataRecord **) malloc(sizeof(dataRecord *) * numLines);
+            stk = (dataRecord **) malloc(sizeof(dataRecord *) * maxFrames);
             callStack[threadId].frames = stk;
         }
-        nextFrame = callStack[threadId].nextFrame;
         indentLevel = callStack[threadId].indentLevel;
 
         save_cp = cp;
@@ -242,58 +250,66 @@
             }
         }
 
+        if (verbose) {
+            printf("Indent: %d; IndentLevel: %d; Line: %s", indent, indentLevel, buf);
+        }
+
         action = 0;
-        if (indent == indentLevel + 1) {
-            callStack[threadId].frames[nextFrame++] = &records[nextRecord];
-        } else if (indent == indentLevel) {
-            char *name = callStack[threadId].frames[nextFrame - 1]->fullName;
-            if (strcmp(name, records[nextRecord].fullName) == 0) {
-                nextFrame -= 1;
+        if (indent == indentLevel + 1) { // Entering a method
+            if (verbose)
+                printf("  Entering %s\n", records[nextRecord].fullName);
+            callStack[threadId].frames[indentLevel] = &records[nextRecord];
+        } else if (indent == indentLevel) { // Exiting a method
+            // Exiting method must be currently on top of stack (unless stack is empty)
+            if (callStack[threadId].frames[indentLevel - 1] == NULL) {
+                if (verbose)
+                    printf("  Exiting %s (past bottom of stack)\n", records[nextRecord].fullName);
+                callStack[threadId].frames[indentLevel - 1] = &records[nextRecord];
                 action = 1;
             } else {
-                if (nextFrame == indentLevel) {
+                if (indentLevel < 1) {
                     fprintf(stderr, "Error: line %d: %s", linenum, buf);
-                    fprintf(stderr, "  expected exit from %s\n",
-                            callStack[threadId].frames[nextFrame - 1]->fullName);
+                    fprintf(stderr, "  expected positive (>0) indentation, found %d\n",
+                            indent);
                     exit(1);
-                } else {
-                    callStack[threadId].frames[nextFrame++] = &records[nextRecord];
                 }
-            }
-        } else if (indent == indentLevel - 1) {
-            action = 1;
-            // Allow popping frames past the bottom of the stack.
-            if (nextFrame > 0) {
-                char *name = callStack[threadId].frames[nextFrame - 1]->fullName;
+                char *name = callStack[threadId].frames[indentLevel - 1]->fullName;
                 if (strcmp(name, records[nextRecord].fullName) == 0) {
-                    nextFrame -= 1;
-                } else {
+                    if (verbose)
+                        printf("  Exiting %s\n", name);
+                    action = 1;
+                } else { // exiting method doesn't match stack's top method
                     fprintf(stderr, "Error: line %d: %s", linenum, buf);
                     fprintf(stderr, "  expected exit from %s\n",
-                            callStack[threadId].frames[nextFrame - 1]->fullName);
+                            callStack[threadId].frames[indentLevel - 1]->fullName);
                     exit(1);
                 }
             }
         } else {
             if (nextRecord != 0) {
                 fprintf(stderr, "Error: line %d: %s", linenum, buf);
-                fprintf(stderr, "  expected indentation %d +/- 1, found %d\n",
+                fprintf(stderr, "  expected indentation %d [+1], found %d\n",
                         indentLevel, indent);
                 exit(1);
             }
 
+            if (verbose) {
+                printf("  Nonzero indent at first record\n");
+                printf("  Entering %s\n", records[nextRecord].fullName);
+            }
+
             // This is the first line of data, so we allow a larger
             // initial indent.  This allows us to test popping off more
             // frames than we entered.
-            callStack[threadId].frames[nextFrame++] = &records[nextRecord];
-            indentLevel = indent;
+            indentLevel = indent - 1;
+            callStack[threadId].frames[indentLevel] = &records[nextRecord];
         }
+
         if (action == 0)
             indentLevel += 1;
         else
             indentLevel -= 1;
         records[nextRecord].action = action;
-        callStack[threadId].nextFrame = nextFrame;
         callStack[threadId].indentLevel = indentLevel;
 
         nextRecord += 1;
@@ -383,14 +399,14 @@
                 pNext->methodId = id;
         }
         if (pRecord->className == NULL || pRecord->methodName == NULL) {
-            fprintf(keyFp, "0x%x	%s	m	()\n",
+            fprintf(keyFp, "0x%x        %s      m       ()\n",
                     pRecord->methodId, pRecord->fullName);
         } else if (pRecord->signature == NULL) {
-            fprintf(keyFp, "0x%x	%s	%s	()\n",
+            fprintf(keyFp, "0x%x        %s      %s      ()\n",
                     pRecord->methodId, pRecord->className,
                     pRecord->methodName);
         } else {
-            fprintf(keyFp, "0x%x	%s	%s	%s\n",
+            fprintf(keyFp, "0x%x        %s      %s      %s\n",
                     pRecord->methodId, pRecord->className,
                     pRecord->methodName, pRecord->signature);
         }
@@ -432,7 +448,7 @@
 {
     int err = 0;
     while (1) {
-        int opt = getopt(argc, argv, "v:");
+        int opt = getopt(argc, argv, "v:d");
         if (opt == -1)
             break;
         switch (opt) {
@@ -444,6 +460,9 @@
                     err = 1;
                 }
                 break;
+            case 'd':
+                verbose = 1;
+                break;
             default:
                 err = 1;
                 break;
@@ -459,7 +478,7 @@
     int len;
 
     if (parseOptions(argc, argv) || argc - optind != 2) {
-        fprintf(stderr, "Usage: %s [-v version] input_file trace_prefix\n",
+        fprintf(stderr, "Usage: %s [-v version] [-d] input_file trace_prefix\n",
                 argv[0]);
         exit(1);
     }
diff --git a/vm/Android.mk b/vm/Android.mk
index 353c1df..bbb5cd1 100644
--- a/vm/Android.mk
+++ b/vm/Android.mk
@@ -40,12 +40,12 @@
 
 include $(LOCAL_PATH)/Dvm.mk
 
-# liblog and libcutils are shared in this case.
+# Whether libraries are static or shared differs between host and
+# target builds, so that's mostly pulled out here and in the equivalent
+# section below.
 LOCAL_SHARED_LIBRARIES += \
-	liblog libcutils
+	liblog libcutils libnativehelper libz
 
-# libdex is static in this case. (That is, on device, we only include
-# whatever we specifically need from it directly in libdvm.)
 LOCAL_STATIC_LIBRARIES += libdex
 
 LOCAL_MODULE := libdvm
@@ -69,26 +69,24 @@
 
     include $(LOCAL_PATH)/Dvm.mk
 
-    # And we need to include all of liblog, libcutils, and libdex:
-    # The result itself is a static library, and LOCAL_STATIC_LIBRARIES
-    # doesn't actually cause any code from the specified libraries to
-    # be included. No I'm not entirely sure what LOCAL_STATIC_LIBRARIES
-    # is even supposed to mean in this context, but it is in fact
-    # meaningfully used in other parts of the build.
+    # We need to include all of these libraries. The end result of this
+    # section is a static library, but LOCAL_STATIC_LIBRARIES doesn't
+    # actually cause any code from the specified libraries to be included,
+    # whereas LOCAL_WHOLE_STATIC_LIBRARIES does. No, I (danfuzz) am not
+    # entirely sure what LOCAL_STATIC_LIBRARIES is even supposed to mean
+    # in this context, but it is in (apparently) meaningfully used in
+    # other parts of the build.
     LOCAL_WHOLE_STATIC_LIBRARIES += \
-	libdex liblog libcutils
+	libnativehelper-host libdex liblog libcutils
 
-    # libffi is called libffi-host on the host and should be staticly
-    # linked. Similarly libnativehelper.
+    # The libffi from the source tree should never be used by host builds.
+    # The recommendation is that host builds should always either
+    # have sufficient custom code so that libffi isn't needed at all,
+    # or they should use the platform's provided libffi. So, if the common
+    # build rules decided to include it, axe it back out here.
     ifneq (,$(findstring libffi,$(LOCAL_SHARED_LIBRARIES)))
         LOCAL_SHARED_LIBRARIES := \
             $(patsubst libffi, ,$(LOCAL_SHARED_LIBRARIES))
-        LOCAL_STATIC_LIBRARIES += libffi-host
-    endif
-    ifneq (,$(findstring libnativehelper,$(LOCAL_SHARED_LIBRARIES)))
-        LOCAL_SHARED_LIBRARIES := \
-            $(patsubst libnativehelper, ,$(LOCAL_SHARED_LIBRARIES))
-        LOCAL_STATIC_LIBRARIES += libnativehelper-host
     endif
 
     LOCAL_MODULE := libdvm-host
diff --git a/vm/Dvm.mk b/vm/Dvm.mk
index 9422bb6..96298f0 100644
--- a/vm/Dvm.mk
+++ b/vm/Dvm.mk
@@ -339,7 +339,3 @@
   LOCAL_CFLAGS += -DdvmAsmInstructionStart=0 -DdvmAsmInstructionEnd=0 \
 	-DdvmAsmSisterStart=0 -DdvmAsmSisterEnd=0 -DDVM_NO_ASM_INTERP=1
 endif
-
-LOCAL_SHARED_LIBRARIES += \
-	libnativehelper \
-	libz
diff --git a/vm/Jni.c b/vm/Jni.c
index 54a1f45..1dcea10 100644
--- a/vm/Jni.c
+++ b/vm/Jni.c
@@ -1123,6 +1123,27 @@
 }
 
 /*
+ * Dump the contents of the JNI reference tables to the log file.
+ *
+ * We only dump the local refs associated with the current thread.
+ */
+void dvmDumpJniReferenceTables(void)
+{
+    Thread* self = dvmThreadSelf();
+    JNIEnv* env = self->jniEnv;
+    ReferenceTable* pLocalRefs = getLocalRefTable(env);
+
+#ifdef USE_INDIRECT_REF
+    dvmDumpIndirectRefTable(pLocalRefs, "JNI local");
+    dvmDumpIndirectRefTable(&gDvm.jniGlobalRefTable, "JNI global");
+#else
+    dvmDumpReferenceTable(pLocalRefs, "JNI local");
+    dvmDumpReferenceTable(&gDvm.jniGlobalRefTable, "JNI global");
+#endif
+    dvmDumpReferenceTable(&gDvm.jniPinRefTable, "JNI pinned array");
+}
+
+/*
  * GC helper function to mark all JNI global references.
  *
  * We're currently handling the "pin" table here too.
diff --git a/vm/JniInternal.h b/vm/JniInternal.h
index 3c15ce4..302dcb0 100644
--- a/vm/JniInternal.h
+++ b/vm/JniInternal.h
@@ -201,6 +201,12 @@
  */
 void dvmReleaseJniMonitors(Thread* self);
 
+/*
+ * Dump the contents of the JNI reference tables to the log file.
+ *
+ * The local ref tables associated with other threads are not included.
+ */
+void dvmDumpJniReferenceTables(void);
 
 /*
  * This mask is applied to weak global reference values returned to
diff --git a/vm/ReferenceTable.c b/vm/ReferenceTable.c
index a8010a2..b47d775 100644
--- a/vm/ReferenceTable.c
+++ b/vm/ReferenceTable.c
@@ -213,7 +213,7 @@
     int i;
 
     if (count == 0) {
-        LOGW("Reference table has no entries\n");
+        LOGW("%s reference table has no entries\n", descr);
         return;
     }
     assert(count > 0);
diff --git a/vm/native/dalvik_system_VMDebug.c b/vm/native/dalvik_system_VMDebug.c
index 8aa371d..c2439a3 100644
--- a/vm/native/dalvik_system_VMDebug.c
+++ b/vm/native/dalvik_system_VMDebug.c
@@ -699,6 +699,23 @@
 }
 
 /*
+ * static void dumpReferenceTables()
+ */
+static void Dalvik_dalvik_system_VMDebug_dumpReferenceTables(const u4* args,
+    JValue* pResult)
+{
+    UNUSED_PARAMETER(args);
+    UNUSED_PARAMETER(pResult);
+
+    LOGI("--- reference table dump ---\n");
+    dvmDumpJniReferenceTables();
+    // could dump thread's internalLocalRefTable, probably not useful
+    // ditto for thread's jniMonitorRefTable
+    LOGI("---\n");
+    RETURN_VOID();
+}
+
+/*
  * static void crash()
  *
  * Dump the current thread's interpreted stack and abort the VM.  Useful
@@ -765,6 +782,8 @@
         Dalvik_dalvik_system_VMDebug_dumpHprofData },
     { "cacheRegisterMap",           "(Ljava/lang/String;)Z",
         Dalvik_dalvik_system_VMDebug_cacheRegisterMap },
+    { "dumpReferenceTables",        "()V",
+        Dalvik_dalvik_system_VMDebug_dumpReferenceTables },
     { "crash",                      "()V",
         Dalvik_dalvik_system_VMDebug_crash },
     { NULL, NULL, NULL },