summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Agopian <mathias@google.com>2012-04-02 17:02:19 -0700
committerMathias Agopian <mathias@google.com>2012-04-02 18:41:10 -0700
commit7b5be95cb3903087742f1079fe89cddd8abe3696 (patch)
treefb45ed1d40465a1283e9a416b90433bc9b66ffe0
parent0e1080f887bcd80c75910cabe7b2eca224bf739c (diff)
downloadframeworks_native-7b5be95cb3903087742f1079fe89cddd8abe3696.zip
frameworks_native-7b5be95cb3903087742f1079fe89cddd8abe3696.tar.gz
frameworks_native-7b5be95cb3903087742f1079fe89cddd8abe3696.tar.bz2
use a socketpair instead of a pipe in BitTube
Bug: 6252830 Change-Id: Ia7a7b08409517214136261c05569dc5959a597ab
-rw-r--r--include/gui/BitTube.h19
-rw-r--r--include/gui/DisplayEventReceiver.h9
-rw-r--r--include/gui/SensorEventQueue.h5
-rw-r--r--libs/gui/BitTube.cpp74
-rw-r--r--libs/gui/DisplayEventReceiver.cpp23
-rw-r--r--libs/gui/SensorEventQueue.cpp31
-rw-r--r--services/surfaceflinger/DisplayEventConnection.cpp6
7 files changed, 109 insertions, 58 deletions
diff --git a/include/gui/BitTube.h b/include/gui/BitTube.h
index 76389a0..3022d05 100644
--- a/include/gui/BitTube.h
+++ b/include/gui/BitTube.h
@@ -22,6 +22,7 @@
#include <utils/Errors.h>
#include <utils/RefBase.h>
+#include <cutils/log.h>
namespace android {
@@ -43,9 +44,27 @@ public:
status_t writeToParcel(Parcel* reply) const;
+ template <typename T>
+ static ssize_t sendObjects(const sp<BitTube>& tube,
+ T const* events, size_t count) {
+ return sendObjects(tube, events, count, sizeof(T));
+ }
+
+ template <typename T>
+ static ssize_t recvObjects(const sp<BitTube>& tube,
+ T* events, size_t count) {
+ return recvObjects(tube, events, count, sizeof(T));
+ }
+
private:
int mSendFd;
mutable int mReceiveFd;
+
+ static ssize_t sendObjects(const sp<BitTube>& tube,
+ void const* events, size_t count, size_t objSize);
+
+ static ssize_t recvObjects(const sp<BitTube>& tube,
+ void* events, size_t count, size_t objSize);
};
// ----------------------------------------------------------------------------
diff --git a/include/gui/DisplayEventReceiver.h b/include/gui/DisplayEventReceiver.h
index 7bca8d6..e631cca 100644
--- a/include/gui/DisplayEventReceiver.h
+++ b/include/gui/DisplayEventReceiver.h
@@ -89,7 +89,7 @@ public:
int getFd() const;
/*
- * getEvents reads event from the queue and returns how many events were
+ * getEvents reads events from the queue and returns how many events were
* read. Returns 0 if there are no more events or a negative error code.
* If NOT_ENOUGH_DATA is returned, the object has become invalid forever, it
* should be destroyed and getEvents() shouldn't be called again.
@@ -99,6 +99,13 @@ public:
Event* events, size_t count);
/*
+ * sendEvents write events to the queue and returns how many events were
+ * written.
+ */
+ static ssize_t sendEvents(const sp<BitTube>& dataChannel,
+ Event const* events, size_t count);
+
+ /*
* setVsyncRate() sets the Event::VSync delivery rate. A value of
* 1 returns every Event::VSync. A value of 2 returns every other event,
* etc... a value of 0 returns no event unless requestNextVsync() has
diff --git a/include/gui/SensorEventQueue.h b/include/gui/SensorEventQueue.h
index ef7c6e3..759b5cb 100644
--- a/include/gui/SensorEventQueue.h
+++ b/include/gui/SensorEventQueue.h
@@ -54,7 +54,10 @@ public:
virtual void onFirstRef();
int getFd() const;
- ssize_t write(ASensorEvent const* events, size_t numEvents);
+
+ static ssize_t write(const sp<BitTube>& tube,
+ ASensorEvent const* events, size_t numEvents);
+
ssize_t read(ASensorEvent* events, size_t numEvents);
status_t waitForEvent() const;
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 @@ BitTube::BitTube(const Parcel& data)
{
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 BitTube::write(void const* vaddr, size_t size)
{
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 BitTube::read(void* vaddr, size_t size)
{
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 @@ status_t BitTube::writeToParcel(Parcel* reply) const
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(DisplayEventReceiver::Event* events,
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).
-
- // returns number of events read
- size /= sizeof(events[0]);
- }
- return size;
+ return BitTube::recvObjects(dataChannel, events, count);
+}
+
+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 @@ int SensorEventQueue::getFd() const
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
diff --git a/services/surfaceflinger/DisplayEventConnection.cpp b/services/surfaceflinger/DisplayEventConnection.cpp
index 77ecbd2..67381ef 100644
--- a/services/surfaceflinger/DisplayEventConnection.cpp
+++ b/services/surfaceflinger/DisplayEventConnection.cpp
@@ -60,9 +60,9 @@ void DisplayEventConnection::requestNextVsync() {
mEventThread->requestNextVsync(this);
}
-status_t DisplayEventConnection::postEvent(const DisplayEventReceiver::Event& event)
-{
- ssize_t size = mChannel->write(&event, sizeof(DisplayEventReceiver::Event));
+status_t DisplayEventConnection::postEvent(
+ const DisplayEventReceiver::Event& event) {
+ ssize_t size = DisplayEventReceiver::sendEvents(mChannel, &event, 1);
return size < 0 ? status_t(size) : status_t(NO_ERROR);
}