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 17801ea093b0e923a61b832f2adba698a273479880Mathias Agopian#include <private/gui/BitTube.h> 18801ea093b0e923a61b832f2adba698a273479880Mathias Agopian 19589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian#include <stdint.h> 207b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian#include <sys/socket.h> 2127c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza#include <sys/types.h> 22589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 23589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian#include <fcntl.h> 2499fe3c6d3dcb6fb26bf283343f946d031b052dffMathias Agopian#include <unistd.h> 25589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 26589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian#include <utils/Errors.h> 27589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 28589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian#include <binder/Parcel.h> 29589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 30589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopiannamespace android { 3127c8115510cebda13cbe24fd4caa946ea9c5003cDan Stozanamespace gui { 32589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 3327c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza// Socket buffer size. The default is typically about 128KB, which is much larger than we really 3427c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza// need. So we make it smaller. 3590ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopianstatic const size_t DEFAULT_SOCKET_BUFFER_SIZE = 4 * 1024; 367b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian 377d290174b08a56ae6bc6719bec58805ca38b348bDan StozaBitTube::BitTube(size_t bufsize) { 3890ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian init(bufsize, bufsize); 39589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 40589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 417d290174b08a56ae6bc6719bec58805ca38b348bDan StozaBitTube::BitTube(DefaultSizeType) : BitTube(DEFAULT_SOCKET_BUFFER_SIZE) {} 42589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 437d290174b08a56ae6bc6719bec58805ca38b348bDan StozaBitTube::BitTube(const Parcel& data) { 447d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza readFromParcel(&data); 45589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 46589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 4790ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopianvoid BitTube::init(size_t rcvbuf, size_t sndbuf) { 4890ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian int sockets[2]; 4990ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) { 5090ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian size_t size = DEFAULT_SOCKET_BUFFER_SIZE; 5190ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf)); 5290ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf)); 5327c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza // since we don't use the "return channel", we keep it small... 5490ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); 5590ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); 5690ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian fcntl(sockets[0], F_SETFL, O_NONBLOCK); 5790ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian fcntl(sockets[1], F_SETFL, O_NONBLOCK); 587d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza mReceiveFd.reset(sockets[0]); 597d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza mSendFd.reset(sockets[1]); 6090ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian } else { 617d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza mReceiveFd.reset(); 627d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza ALOGE("BitTube: pipe creation failed (%s)", strerror(errno)); 6390ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian } 6490ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian} 6590ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian 6627c8115510cebda13cbe24fd4caa946ea9c5003cDan Stozastatus_t BitTube::initCheck() const { 675cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian if (mReceiveFd < 0) { 685cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian return status_t(mReceiveFd); 695cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian } 705cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian return NO_ERROR; 715cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian} 725cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian 7327c8115510cebda13cbe24fd4caa946ea9c5003cDan Stozaint BitTube::getFd() const { 74589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian return mReceiveFd; 75589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 76589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 7727c8115510cebda13cbe24fd4caa946ea9c5003cDan Stozaint BitTube::getSendFd() const { 7856ae42613c91f6a6fb0dc3f626daa24666fd18c2Aravind Akella return mSendFd; 7956ae42613c91f6a6fb0dc3f626daa24666fd18c2Aravind Akella} 8056ae42613c91f6a6fb0dc3f626daa24666fd18c2Aravind Akella 816b698e4fe4ff50dcef818452283637f9870ae770Dan Stozabase::unique_fd BitTube::moveReceiveFd() { 826b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza return std::move(mReceiveFd); 836b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza} 846b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza 856b698e4fe4ff50dcef818452283637f9870ae770Dan Stozavoid BitTube::setReceiveFd(base::unique_fd&& receiveFd) { 866b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza mReceiveFd = std::move(receiveFd); 876b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza} 886b698e4fe4ff50dcef818452283637f9870ae770Dan Stoza 8927c8115510cebda13cbe24fd4caa946ea9c5003cDan Stozassize_t BitTube::write(void const* vaddr, size_t size) { 905cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian ssize_t err, len; 915cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian do { 927b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL); 9390ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian // cannot return less than size, since we're using SOCK_SEQPACKET 945cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian err = len < 0 ? errno : 0; 955cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian } while (err == EINTR); 965cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian return err == 0 ? len : -err; 97589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 98589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 9927c8115510cebda13cbe24fd4caa946ea9c5003cDan Stozassize_t BitTube::read(void* vaddr, size_t size) { 1005cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian ssize_t err, len; 1015cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian do { 1027b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT); 1035cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian err = len < 0 ? errno : 0; 1045cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian } while (err == EINTR); 1053ad3807a5c4039618175c042a1121c926c2c62e9Mathias Agopian if (err == EAGAIN || err == EWOULDBLOCK) { 10627c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza // EAGAIN means that we have non-blocking I/O but there was no data to be read. Nothing the 10727c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza // client should care about. 1083ad3807a5c4039618175c042a1121c926c2c62e9Mathias Agopian return 0; 1093ad3807a5c4039618175c042a1121c926c2c62e9Mathias Agopian } 1105cae0d0699a169e468fff3e21165f35db12f2cdeMathias Agopian return err == 0 ? len : -err; 111589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 112589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 11327c8115510cebda13cbe24fd4caa946ea9c5003cDan Stozastatus_t BitTube::writeToParcel(Parcel* reply) const { 11427c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza if (mReceiveFd < 0) return -EINVAL; 115589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 116589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian status_t result = reply->writeDupFileDescriptor(mReceiveFd); 1177d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza mReceiveFd.reset(); 118589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian return result; 119589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian} 120589ce85ee4174829cfedce91b6b2509d2a4002ebMathias Agopian 1217d290174b08a56ae6bc6719bec58805ca38b348bDan Stozastatus_t BitTube::readFromParcel(const Parcel* parcel) { 1227d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza mReceiveFd.reset(dup(parcel->readFileDescriptor())); 1237d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza if (mReceiveFd < 0) { 1247d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza mReceiveFd.reset(); 1257d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza int error = errno; 1267d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza ALOGE("BitTube::readFromParcel: can't dup file descriptor (%s)", strerror(error)); 1277d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza return -error; 1287d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza } 1297d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza return NO_ERROR; 1307d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza} 1317d290174b08a56ae6bc6719bec58805ca38b348bDan Stoza 1326b698e4fe4ff50dcef818452283637f9870ae770Dan Stozassize_t BitTube::sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize) { 13390ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian const char* vaddr = reinterpret_cast<const char*>(events); 13427c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza ssize_t size = tube->write(vaddr, count * objSize); 13590ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian 13690ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian // should never happen because of SOCK_SEQPACKET 137d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)), 13827c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were " 13927c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza "sent!)", 14027c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza count, objSize, size); 14190ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian 14227c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza // ALOGE_IF(size<0, "error %d sending %d events", size, count); 143d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza return size < 0 ? size : size / static_cast<ssize_t>(objSize); 1447b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian} 1457b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian 1466b698e4fe4ff50dcef818452283637f9870ae770Dan Stozassize_t BitTube::recvObjects(BitTube* tube, void* events, size_t count, size_t objSize) { 14790ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian char* vaddr = reinterpret_cast<char*>(events); 14827c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza ssize_t size = tube->read(vaddr, count * objSize); 14990ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian 15090ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian // should never happen because of SOCK_SEQPACKET 151d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)), 15227c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza "BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were " 15327c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza "received!)", 15427c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza count, objSize, size); 15590ed3e8d7883d9c80fb8bf11b1c593bd8b2b39d0Mathias Agopian 15627c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza // ALOGE_IF(size<0, "error %d receiving %d events", size, count); 157d723bd7669b4fc88dc282d8bf8ba5ecb2849d22fDan Stoza return size < 0 ? size : size / static_cast<ssize_t>(objSize); 1587b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian} 1597b5be95cb3903087742f1079fe89cddd8abe3696Mathias Agopian 16027c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza} // namespace gui 16127c8115510cebda13cbe24fd4caa946ea9c5003cDan Stoza} // namespace android 162