Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9b712211 authored by Mathias Agopian's avatar Mathias Agopian Committed by Android (Google) Code Review
Browse files

Merge "use a socketpair instead of a pipe in BitTube"

parents cf0db31c 7b5be95c
Loading
Loading
Loading
Loading
+19 −0
Original line number Diff line number Diff line
@@ -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);
};

// ----------------------------------------------------------------------------
+8 −1
Original line number Diff line number Diff line
@@ -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,
+4 −1
Original line number Diff line number Diff line
@@ -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;
+63 −11
Original line number Diff line number Diff line
@@ -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
+7 −16
Original line number Diff line number Diff line
@@ -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 BitTube::recvObjects(dataChannel, events, count);
}
    return size;

ssize_t DisplayEventReceiver::sendEvents(const sp<BitTube>& dataChannel,
        Event const* events, size_t count)
{
    return BitTube::sendObjects(dataChannel, events, count);
}

// ---------------------------------------------------------------------------
Loading