diff options
author | Mathias Agopian <mathias@google.com> | 2012-04-02 17:02:19 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2012-04-02 18:41:10 -0700 |
commit | 7b5be95cb3903087742f1079fe89cddd8abe3696 (patch) | |
tree | fb45ed1d40465a1283e9a416b90433bc9b66ffe0 | |
parent | 0e1080f887bcd80c75910cabe7b2eca224bf739c (diff) | |
download | frameworks_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.h | 19 | ||||
-rw-r--r-- | include/gui/DisplayEventReceiver.h | 9 | ||||
-rw-r--r-- | include/gui/SensorEventQueue.h | 5 | ||||
-rw-r--r-- | libs/gui/BitTube.cpp | 74 | ||||
-rw-r--r-- | libs/gui/DisplayEventReceiver.cpp | 23 | ||||
-rw-r--r-- | libs/gui/SensorEventQueue.cpp | 31 | ||||
-rw-r--r-- | services/surfaceflinger/DisplayEventConnection.cpp | 6 |
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); } |