use a socketpair instead of a pipe in BitTube

Bug: 6252830
Change-Id: Ia7a7b08409517214136261c05569dc5959a597ab
diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp
index 55f4178..355a319 100644
--- a/libs/gui/BitTube.cpp
+++ b/libs/gui/BitTube.cpp
@@ -16,9 +16,9 @@
 
 #include <stdint.h>
 #include <sys/types.h>
+#include <sys/socket.h>
 
 #include <fcntl.h>
-#include <signal.h>
 #include <unistd.h>
 
 #include <utils/Errors.h>
@@ -30,17 +30,25 @@
 namespace android {
 // ----------------------------------------------------------------------------
 
+// Socket buffer size.  The default is typically about 128KB, which is much larger than
+// we really need.  So we make it smaller.
+static const size_t SOCKET_BUFFER_SIZE = 4 * 1024;
+
+
 BitTube::BitTube()
     : mSendFd(-1), mReceiveFd(-1)
 {
-    int fds[2];
-    if (pipe(fds) == 0) {
-        mReceiveFd = fds[0];
-        mSendFd = fds[1];
-        fcntl(mReceiveFd, F_SETFL, O_NONBLOCK);
-        fcntl(mSendFd, F_SETFL, O_NONBLOCK);
-        // ignore SIGPIPE, we handle write errors through EPIPE instead
-        signal(SIGPIPE, SIG_IGN);
+    int sockets[2];
+    if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
+        int size = SOCKET_BUFFER_SIZE;
+        setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
+        setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
+        setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
+        setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
+        fcntl(sockets[0], F_SETFL, O_NONBLOCK);
+        fcntl(sockets[1], F_SETFL, O_NONBLOCK);
+        mReceiveFd = sockets[0];
+        mSendFd = sockets[1];
     } else {
         mReceiveFd = -errno;
         ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
@@ -52,6 +60,9 @@
 {
     mReceiveFd = dup(data.readFileDescriptor());
     if (mReceiveFd >= 0) {
+        int size = SOCKET_BUFFER_SIZE;
+        setsockopt(mReceiveFd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
+        setsockopt(mReceiveFd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
         fcntl(mReceiveFd, F_SETFL, O_NONBLOCK);
     } else {
         mReceiveFd = -errno;
@@ -86,7 +97,7 @@
 {
     ssize_t err, len;
     do {
-        len = ::write(mSendFd, vaddr, size);
+        len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
         err = len < 0 ? errno : 0;
     } while (err == EINTR);
     return err == 0 ? len : -err;
@@ -97,7 +108,7 @@
 {
     ssize_t err, len;
     do {
-        len = ::read(mReceiveFd, vaddr, size);
+        len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT);
         err = len < 0 ? errno : 0;
     } while (err == EINTR);
     if (err == EAGAIN || err == EWOULDBLOCK) {
@@ -119,5 +130,46 @@
     return result;
 }
 
+
+ssize_t BitTube::sendObjects(const sp<BitTube>& tube,
+        void const* events, size_t count, size_t objSize)
+{
+    ssize_t numObjects = 0;
+    for (size_t i=0 ; i<count ; i++) {
+        const char* vaddr = reinterpret_cast<const char*>(events) + objSize * i;
+        ssize_t size = tube->write(vaddr, objSize);
+        if (size < 0) {
+            // error occurred
+            numObjects = -size;
+            break;
+        } else if (size == 0) {
+            // no more space
+            break;
+        }
+        numObjects++;
+    }
+    return numObjects;
+}
+
+ssize_t BitTube::recvObjects(const sp<BitTube>& tube,
+        void* events, size_t count, size_t objSize)
+{
+    ssize_t numObjects = 0;
+    for (size_t i=0 ; i<count ; i++) {
+        char* vaddr = reinterpret_cast<char*>(events) + objSize * i;
+        ssize_t size = tube->read(vaddr, objSize);
+        if (size < 0) {
+            // error occurred
+            numObjects = -size;
+            break;
+        } else if (size == 0) {
+            // no more messages
+            break;
+        }
+        numObjects++;
+    }
+    return numObjects;
+}
+
 // ----------------------------------------------------------------------------
 }; // namespace android