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
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index a6790ad..9973e8d 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -85,22 +85,13 @@
ssize_t DisplayEventReceiver::getEvents(const sp<BitTube>& dataChannel,
Event* events, size_t count)
{
- ssize_t size = dataChannel->read(events, sizeof(events[0])*count);
- ALOGE_IF(size<0,
- "DisplayEventReceiver::getEvents error (%s)",
- strerror(-size));
- if (size >= 0) {
- // Note: if (size % sizeof(events[0])) != 0, we've got a
- // partial read. This can happen if the queue filed up (ie: if we
- // didn't pull from it fast enough).
- // We discard the partial event and rely on the sender to
- // re-send the event if appropriate (some events, like VSYNC
- // can be lost forever).
+ return BitTube::recvObjects(dataChannel, events, count);
+}
- // returns number of events read
- size /= sizeof(events[0]);
- }
- return size;
+ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,
+ Event const* events, size_t count)
+{
+ return BitTube::sendObjects(dataChannel, events, count);
}
// ---------------------------------------------------------------------------
diff --git a/libs/gui/SensorEventQueue.cpp b/libs/gui/SensorEventQueue.cpp
index b95dd90..04ba640 100644
--- a/libs/gui/SensorEventQueue.cpp
+++ b/libs/gui/SensorEventQueue.cpp
@@ -53,36 +53,15 @@
return mSensorChannel->getFd();
}
-ssize_t SensorEventQueue::write(ASensorEvent const* events, size_t numEvents)
-{
- ssize_t size = mSensorChannel->write(events, numEvents * sizeof(events[0]));
- if (size >= 0) {
- if (size % sizeof(events[0])) {
- // partial write!!! should never happen.
- return -EINVAL;
- }
- // returns number of events written
- size /= sizeof(events[0]);
- }
- return size;
+
+ssize_t SensorEventQueue::write(const sp<BitTube>& tube,
+ ASensorEvent const* events, size_t numEvents) {
+ return BitTube::sendObjects(tube, events, numEvents);
}
ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents)
{
- ssize_t size = mSensorChannel->read(events, numEvents*sizeof(events[0]));
- ALOGE_IF(size<0 && size!=-EAGAIN,
- "SensorChannel::read error (%s)", strerror(-size));
- if (size >= 0) {
- if (size % sizeof(events[0])) {
- // partial read!!! should never happen.
- ALOGE("SensorEventQueue partial read (event-size=%u, read=%d)",
- sizeof(events[0]), int(size));
- return -EINVAL;
- }
- // returns number of events read
- size /= sizeof(events[0]);
- }
- return size;
+ return BitTube::recvObjects(mSensorChannel, events, numEvents);
}
sp<Looper> SensorEventQueue::getLooper() const