Home | History | Annotate | Download | only in gui
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdint.h>
     18 #include <sys/types.h>
     19 #include <sys/socket.h>
     20 
     21 #include <fcntl.h>
     22 #include <unistd.h>
     23 
     24 #include <utils/Errors.h>
     25 
     26 #include <binder/Parcel.h>
     27 
     28 #include <gui/BitTube.h>
     29 
     30 namespace android {
     31 // ----------------------------------------------------------------------------
     32 
     33 // Socket buffer size.  The default is typically about 128KB, which is much larger than
     34 // we really need.  So we make it smaller.
     35 static const size_t SOCKET_BUFFER_SIZE = 4 * 1024;
     36 
     37 
     38 BitTube::BitTube()
     39     : mSendFd(-1), mReceiveFd(-1)
     40 {
     41     int sockets[2];
     42     if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
     43         int size = SOCKET_BUFFER_SIZE;
     44         setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
     45         setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
     46         setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
     47         setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
     48         fcntl(sockets[0], F_SETFL, O_NONBLOCK);
     49         fcntl(sockets[1], F_SETFL, O_NONBLOCK);
     50         mReceiveFd = sockets[0];
     51         mSendFd = sockets[1];
     52     } else {
     53         mReceiveFd = -errno;
     54         ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
     55     }
     56 }
     57 
     58 BitTube::BitTube(const Parcel& data)
     59     : mSendFd(-1), mReceiveFd(-1)
     60 {
     61     mReceiveFd = dup(data.readFileDescriptor());
     62     if (mReceiveFd >= 0) {
     63         int size = SOCKET_BUFFER_SIZE;
     64         setsockopt(mReceiveFd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
     65         setsockopt(mReceiveFd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
     66         fcntl(mReceiveFd, F_SETFL, O_NONBLOCK);
     67     } else {
     68         mReceiveFd = -errno;
     69         ALOGE("BitTube(Parcel): can't dup filedescriptor (%s)",
     70                 strerror(-mReceiveFd));
     71     }
     72 }
     73 
     74 BitTube::~BitTube()
     75 {
     76     if (mSendFd >= 0)
     77         close(mSendFd);
     78 
     79     if (mReceiveFd >= 0)
     80         close(mReceiveFd);
     81 }
     82 
     83 status_t BitTube::initCheck() const
     84 {
     85     if (mReceiveFd < 0) {
     86         return status_t(mReceiveFd);
     87     }
     88     return NO_ERROR;
     89 }
     90 
     91 int BitTube::getFd() const
     92 {
     93     return mReceiveFd;
     94 }
     95 
     96 ssize_t BitTube::write(void const* vaddr, size_t size)
     97 {
     98     ssize_t err, len;
     99     do {
    100         len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
    101         err = len < 0 ? errno : 0;
    102     } while (err == EINTR);
    103     return err == 0 ? len : -err;
    104 
    105 }
    106 
    107 ssize_t BitTube::read(void* vaddr, size_t size)
    108 {
    109     ssize_t err, len;
    110     do {
    111         len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT);
    112         err = len < 0 ? errno : 0;
    113     } while (err == EINTR);
    114     if (err == EAGAIN || err == EWOULDBLOCK) {
    115         // EAGAIN means that we have non-blocking I/O but there was
    116         // no data to be read. Nothing the client should care about.
    117         return 0;
    118     }
    119     return err == 0 ? len : -err;
    120 }
    121 
    122 status_t BitTube::writeToParcel(Parcel* reply) const
    123 {
    124     if (mReceiveFd < 0)
    125         return -EINVAL;
    126 
    127     status_t result = reply->writeDupFileDescriptor(mReceiveFd);
    128     close(mReceiveFd);
    129     mReceiveFd = -1;
    130     return result;
    131 }
    132 
    133 
    134 ssize_t BitTube::sendObjects(const sp<BitTube>& tube,
    135         void const* events, size_t count, size_t objSize)
    136 {
    137     ssize_t numObjects = 0;
    138     for (size_t i=0 ; i<count ; i++) {
    139         const char* vaddr = reinterpret_cast<const char*>(events) + objSize * i;
    140         ssize_t size = tube->write(vaddr, objSize);
    141         if (size < 0) {
    142             // error occurred
    143             return size;
    144         } else if (size == 0) {
    145             // no more space
    146             break;
    147         }
    148         numObjects++;
    149     }
    150     return numObjects;
    151 }
    152 
    153 ssize_t BitTube::recvObjects(const sp<BitTube>& tube,
    154         void* events, size_t count, size_t objSize)
    155 {
    156     ssize_t numObjects = 0;
    157     for (size_t i=0 ; i<count ; i++) {
    158         char* vaddr = reinterpret_cast<char*>(events) + objSize * i;
    159         ssize_t size = tube->read(vaddr, objSize);
    160         if (size < 0) {
    161             // error occurred
    162             return size;
    163         } else if (size == 0) {
    164             // no more messages
    165             break;
    166         }
    167         numObjects++;
    168     }
    169     return numObjects;
    170 }
    171 
    172 // ----------------------------------------------------------------------------
    173 }; // namespace android
    174