Use ioctl(FIONREAD) rather than recv(MSG_PEEK) to implement Socket.available.

As well as avoiding unnecessary work, this also means we can reuse the native
code we already have for ioctl(FIONREAD), though we need to change the
interface to take FileDescriptor rather than int, and extract the int on the
native side.

Change-Id: I4c6d9e4e72e514e3e7872c7f882bda5441059915
diff --git a/luni/src/main/java/java/io/FileInputStream.java b/luni/src/main/java/java/io/FileInputStream.java
index 20f7eae..6a65395 100644
--- a/luni/src/main/java/java/io/FileInputStream.java
+++ b/luni/src/main/java/java/io/FileInputStream.java
@@ -146,33 +146,7 @@
     @Override
     public int available() throws IOException {
         openCheck();
-
-        // BEGIN android-added
-
-        // Android always uses the ioctl() method of determining bytes
-        // available. See the long discussion in
-        // org_apache_harmony_luni_platform_OSFileSystem.cpp about its
-        // use.
-
-        return fileSystem.ioctlAvailable(fd.descriptor);
-        // END android-added
-
-        // BEGIN android-deleted
-        // synchronized (repositioningLock) {
-        //     // stdin requires special handling
-        //     if (fd == FileDescriptor.in) {
-        //         return (int) fileSystem.ttyAvailable();
-        //     }
-        //
-        //     long currentPosition = fileSystem.seek(fd.descriptor, 0L,
-        //             IFileSystem.SEEK_CUR);
-        //     long endOfFilePosition = fileSystem.seek(fd.descriptor, 0L,
-        //             IFileSystem.SEEK_END);
-        //     fileSystem.seek(fd.descriptor, currentPosition,
-        //             IFileSystem.SEEK_SET);
-        //     return (int) (endOfFilePosition - currentPosition);
-        // }
-        // END android-deleted
+        return fileSystem.ioctlAvailable(fd);
     }
 
     /**
diff --git a/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java b/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
index 09b61da..91b0ed0 100644
--- a/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
+++ b/luni/src/main/java/org/apache/harmony/luni/net/PlainSocketImpl.java
@@ -176,7 +176,7 @@
         if (shutdownInput == true) {
             return 0;
         }
-        return netImpl.availableStream(fd);
+        return Platform.getFileSystem().ioctlAvailable(fd);
     }
 
     @Override
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
index bee1557..f04ea02 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/IFileSystem.java
@@ -112,7 +112,7 @@
     // END android-deleted
     
     // BEGIN android-added
-    public int ioctlAvailable(int fileDescriptor) throws IOException;
+    public int ioctlAvailable(FileDescriptor fileDescriptor) throws IOException;
     // END android-added
     
 }
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
index bc56f68..59cb7a4 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/INetworkSystem.java
@@ -142,8 +142,6 @@
 
     public void sendUrgentData(FileDescriptor fd, byte value);
 
-    public int availableStream(FileDescriptor aFD) throws SocketException;
-
     // BEGIN android-removed
     // public void acceptStreamSocket(FileDescriptor fdServer,
     //         SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
index 13ca3ab..1f8eb4a 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSFileSystem.java
@@ -182,6 +182,6 @@
     // END android-deleted
 
     // BEGIN android-added
-    public native int ioctlAvailable(int fileDescriptor) throws IOException;
+    public native int ioctlAvailable(FileDescriptor fileDescriptor) throws IOException;
     // END android-added
 }
diff --git a/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java b/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
index 7c5cf66..37bfde9 100644
--- a/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
+++ b/luni/src/main/java/org/apache/harmony/luni/platform/OSNetworkSystem.java
@@ -73,24 +73,6 @@
             SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
             throws IOException;
 
-    // BEGIN android-removed
-    // public void acceptStreamSocket(FileDescriptor fdServer,
-    //         SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
-    //         throws IOException {
-    //     acceptStreamSocketImpl(fdServer, newSocket, fdnewSocket, timeout);
-    // }
-
-    // static native void acceptStreamSocketImpl(FileDescriptor fdServer,
-    //         SocketImpl newSocket, FileDescriptor fdnewSocket, int timeout)
-    //         throws IOException;
-    // END android-removed
-
-    public int availableStream(FileDescriptor fd) throws SocketException {
-        return availableStreamImpl(fd);
-    }
-
-    static native int availableStreamImpl(FileDescriptor aFD) throws SocketException;
-
     /**
      * Associates a local address with a socket.
      *
diff --git a/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp b/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp
index 3100767..c33cbed 100644
--- a/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp
+++ b/luni/src/main/native/org_apache_harmony_luni_platform_OSFileSystem.cpp
@@ -450,7 +450,7 @@
     return rc;
 }
 
-static jint harmony_io_ioctlAvailable(JNIEnv*env, jobject, jint fd) {
+static jint harmony_io_ioctlAvailable(JNIEnv*env, jobject, jobject fileDescriptor) {
     /*
      * On underlying platforms Android cares about (read "Linux"),
      * ioctl(fd, FIONREAD, &avail) is supposed to do the following:
@@ -476,6 +476,10 @@
      * actually read some amount of data and caused the cursor to be
      * advanced.
      */
+    int fd = jniGetFDFromFileDescriptor(env, fileDescriptor);
+    if (fd == -1) {
+        return -1;
+    }
     int avail = 0;
     int rc = ioctl(fd, FIONREAD, &avail);
     if (rc >= 0) {
@@ -505,7 +509,7 @@
     { "close",              "(I)V",       (void*) harmony_io_close },
     { "fflush",             "(IZ)V",      (void*) harmony_io_fflush },
     { "getAllocGranularity","()I",        (void*) harmony_io_getAllocGranularity },
-    { "ioctlAvailable",     "(I)I",       (void*) harmony_io_ioctlAvailable },
+    { "ioctlAvailable", "(Ljava/io/FileDescriptor;)I", (void*) harmony_io_ioctlAvailable },
     { "lockImpl",           "(IJJIZ)I",   (void*) harmony_io_lockImpl },
     { "openImpl",           "([BI)I",     (void*) harmony_io_openImpl },
     { "readDirect",         "(IIII)J",    (void*) harmony_io_readDirect },
diff --git a/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp b/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
index 1a8f3a4..08bdc72 100644
--- a/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
+++ b/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.cpp
@@ -1828,40 +1828,6 @@
     }
 }
 
-static jint osNetworkSystem_availableStreamImpl(JNIEnv* env, jclass clazz,
-        jobject fileDescriptor) {
-    // LOGD("ENTER availableStreamImpl");
-
-    int handle;
-    if (!jniGetFd(env, fileDescriptor, handle)) {
-        return 0;
-    }
-
-    int result;
-    do {
-        result = selectWait(handle, 1);
-
-        if (SOCKERR_TIMEOUT == result) {
-            // The read operation timed out, so answer 0 bytes available
-            return 0;
-        } else if (SOCKERR_INTERRUPTED == result) {
-            continue;
-        } else if (0 > result) {
-            throwSocketException(env, result);
-            return 0;
-        }
-    } while (SOCKERR_INTERRUPTED == result);
-
-    char message[2048];
-    result = recv(handle, (jbyte *) message, sizeof(message), MSG_PEEK);
-
-    if (0 > result) {
-        jniThrowSocketException(env, errno);
-        return 0;
-    }
-    return result;
-}
-
 static void osNetworkSystem_acceptSocketImpl(JNIEnv* env, jclass,
         jobject serverFileDescriptor,
         jobject newSocket, jobject clientFileDescriptor, jint timeout) {
@@ -2962,7 +2928,6 @@
     { "connectStreamWithTimeoutSocketImpl","(Ljava/io/FileDescriptor;IIILjava/net/InetAddress;)V",                     (void*) osNetworkSystem_connectStreamWithTimeoutSocketImpl },
     { "socketBindImpl",                    "(Ljava/io/FileDescriptor;ILjava/net/InetAddress;)V",                       (void*) osNetworkSystem_socketBindImpl                     },
     { "listenStreamSocketImpl",            "(Ljava/io/FileDescriptor;I)V",                                             (void*) osNetworkSystem_listenStreamSocketImpl             },
-    { "availableStreamImpl",               "(Ljava/io/FileDescriptor;)I",                                              (void*) osNetworkSystem_availableStreamImpl                },
     { "acceptSocketImpl",                  "(Ljava/io/FileDescriptor;Ljava/net/SocketImpl;Ljava/io/FileDescriptor;I)V",(void*) osNetworkSystem_acceptSocketImpl                   },
     { "supportsUrgentDataImpl",            "(Ljava/io/FileDescriptor;)Z",                                              (void*) osNetworkSystem_supportsUrgentDataImpl             },
     { "sendUrgentDataImpl",                "(Ljava/io/FileDescriptor;B)V",                                             (void*) osNetworkSystem_sendUrgentDataImpl                 },