use a socketpair instead of a pipe in BitTube
Bug: 6252830 Change-Id: Ia7a7b08409517214136261c05569dc5959a597ab
This commit is contained in:
parent
0e1080f887
commit
7b5be95cb3
@ -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);
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
@ -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.
|
||||
@ -98,6 +98,13 @@ public:
|
||||
static ssize_t getEvents(const sp<BitTube>& dataChannel,
|
||||
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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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).
|
||||
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);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user