BitTube.cpp revision 7b5be95cb3903087742f1079fe89cddd8abe3696
1589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian/* 2589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * Copyright (C) 2010 The Android Open Source Project 3589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * 4589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * Licensed under the Apache License, Version 2.0 (the "License"); 5589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * you may not use this file except in compliance with the License. 6589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * You may obtain a copy of the License at 7589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * 8589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * http://www.apache.org/licenses/LICENSE-2.0 9589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * 10589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * Unless required by applicable law or agreed to in writing, software 11589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * distributed under the License is distributed on an "AS IS" BASIS, 12589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * See the License for the specific language governing permissions and 14589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian * limitations under the License. 15589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian */ 16589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 17589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian#include <stdint.h> 18589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian#include <sys/types.h> 197b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian#include <sys/socket.h> 20589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 21589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian#include <fcntl.h> 2299fe3c6d3dcb6fb26bf283343f946d031b052dffMathias Agopian#include <unistd.h> 23589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 24589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian#include <utils/Errors.h> 25589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 26589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian#include <binder/Parcel.h> 27589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 285cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian#include <gui/BitTube.h> 29589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 30589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopiannamespace android { 31589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian// ---------------------------------------------------------------------------- 32589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 337b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian// Socket buffer size. The default is typically about 128KB, which is much larger than 347b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian// we really need. So we make it smaller. 357b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopianstatic const size_t SOCKET_BUFFER_SIZE = 4 * 1024; 367b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian 377b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian 385cae0d0699a169e468fff3e21165f35db12f2cdeMathias AgopianBitTube::BitTube() 39589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian : mSendFd(-1), mReceiveFd(-1) 40589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian{ 417b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian int sockets[2]; 427b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) { 437b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian int size = SOCKET_BUFFER_SIZE; 447b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); 457b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); 467b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); 477b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); 487b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian fcntl(sockets[0], F_SETFL, O_NONBLOCK); 497b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian fcntl(sockets[1], F_SETFL, O_NONBLOCK); 507b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian mReceiveFd = sockets[0]; 517b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian mSendFd = sockets[1]; 525cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian } else { 535cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian mReceiveFd = -errno; 54e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd)); 55589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian } 56589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 57589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 585cae0d0699a169e468fff3e21165f35db12f2cdeMathias AgopianBitTube::BitTube(const Parcel& data) 59589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian : mSendFd(-1), mReceiveFd(-1) 60589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian{ 61589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian mReceiveFd = dup(data.readFileDescriptor()); 625cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian if (mReceiveFd >= 0) { 637b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian int size = SOCKET_BUFFER_SIZE; 647b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian setsockopt(mReceiveFd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); 657b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian setsockopt(mReceiveFd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); 665cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian fcntl(mReceiveFd, F_SETFL, O_NONBLOCK); 675cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian } else { 685cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian mReceiveFd = -errno; 69e6f43ddce78d6846af12550ff9193c5c6fe5844bSteve Block ALOGE("BitTube(Parcel): can't dup filedescriptor (%s)", 705cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian strerror(-mReceiveFd)); 715cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian } 72589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 73589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 745cae0d0699a169e468fff3e21165f35db12f2cdeMathias AgopianBitTube::~BitTube() 75589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian{ 76589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian if (mSendFd >= 0) 77589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian close(mSendFd); 78589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 79589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian if (mReceiveFd >= 0) 80589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian close(mReceiveFd); 81589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 82589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 835cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopianstatus_t BitTube::initCheck() const 845cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian{ 855cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian if (mReceiveFd < 0) { 865cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian return status_t(mReceiveFd); 875cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian } 885cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian return NO_ERROR; 895cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian} 905cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian 915cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopianint BitTube::getFd() const 92589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian{ 93589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian return mReceiveFd; 94589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 95589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 965cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopianssize_t BitTube::write(void const* vaddr, size_t size) 97589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian{ 985cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian ssize_t err, len; 995cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian do { 1007b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL); 1015cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian err = len < 0 ? errno : 0; 1025cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian } while (err == EINTR); 1035cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian return err == 0 ? len : -err; 1045cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian 105589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 106589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 1075cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopianssize_t BitTube::read(void* vaddr, size_t size) 108589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian{ 1095cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian ssize_t err, len; 1105cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian do { 1117b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT); 1125cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian err = len < 0 ? errno : 0; 1135cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian } while (err == EINTR); 1143ad3807a5c4039618175c042a1121c926c2c62e9Mathias Agopian if (err == EAGAIN || err == EWOULDBLOCK) { 1153ad3807a5c4039618175c042a1121c926c2c62e9Mathias Agopian // EAGAIN means that we have non-blocking I/O but there was 1163ad3807a5c4039618175c042a1121c926c2c62e9Mathias Agopian // no data to be read. Nothing the client should care about. 1173ad3807a5c4039618175c042a1121c926c2c62e9Mathias Agopian return 0; 1183ad3807a5c4039618175c042a1121c926c2c62e9Mathias Agopian } 1195cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian return err == 0 ? len : -err; 120589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 121589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 1225cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopianstatus_t BitTube::writeToParcel(Parcel* reply) const 123589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian{ 124589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian if (mReceiveFd < 0) 125589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian return -EINVAL; 126589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 127589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian status_t result = reply->writeDupFileDescriptor(mReceiveFd); 128589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian close(mReceiveFd); 129589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian mReceiveFd = -1; 130589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian return result; 131589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 132589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 1337b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian 1347b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopianssize_t BitTube::sendObjects(const sp<BitTube>& tube, 1357b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian void const* events, size_t count, size_t objSize) 1367b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian{ 1377b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian ssize_t numObjects = 0; 1387b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian for (size_t i=0 ; i<count ; i++) { 1397b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian const char* vaddr = reinterpret_cast<const char*>(events) + objSize * i; 1407b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian ssize_t size = tube->write(vaddr, objSize); 1417b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian if (size < 0) { 1427b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian // error occurred 1437b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian numObjects = -size; 1447b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian break; 1457b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian } else if (size == 0) { 1467b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian // no more space 1477b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian break; 1487b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian } 1497b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian numObjects++; 1507b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian } 1517b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian return numObjects; 1527b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian} 1537b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian 1547b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopianssize_t BitTube::recvObjects(const sp<BitTube>& tube, 1557b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian void* events, size_t count, size_t objSize) 1567b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian{ 1577b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian ssize_t numObjects = 0; 1587b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian for (size_t i=0 ; i<count ; i++) { 1597b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian char* vaddr = reinterpret_cast<char*>(events) + objSize * i; 1607b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian ssize_t size = tube->read(vaddr, objSize); 1617b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian if (size < 0) { 1627b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian // error occurred 1637b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian numObjects = -size; 1647b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian break; 1657b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian } else if (size == 0) { 1667b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian // no more messages 1677b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian break; 1687b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian } 1697b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian numObjects++; 1707b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian } 1717b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian return numObjects; 1727b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian} 1737b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian 174589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian// ---------------------------------------------------------------------------- 175589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian}; // namespace android 176