BitTube.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. #include <stdint.h>
  17. #include <sys/types.h>
  18. #include <sys/socket.h>
  19. #include <fcntl.h>
  20. #include <unistd.h>
  21. #include <utils/Errors.h>
  22. #include <binder/Parcel.h>
  23. #include <gui/BitTube.h>
  24. namespace android {
  25. // ----------------------------------------------------------------------------
  26. // Socket buffer size. The default is typically about 128KB, which is much larger than
  27. // we really need. So we make it smaller.
  28. static const size_t DEFAULT_SOCKET_BUFFER_SIZE = 4 * 1024;
  29. BitTube::BitTube()
  30. : mSendFd(-1), mReceiveFd(-1)
  31. {
  32. init(DEFAULT_SOCKET_BUFFER_SIZE, DEFAULT_SOCKET_BUFFER_SIZE);
  33. }
  34. BitTube::BitTube(size_t bufsize)
  35. : mSendFd(-1), mReceiveFd(-1)
  36. {
  37. init(bufsize, bufsize);
  38. }
  39. BitTube::BitTube(const Parcel& data)
  40. : mSendFd(-1), mReceiveFd(-1)
  41. {
  42. mReceiveFd = dup(data.readFileDescriptor());
  43. if (mReceiveFd < 0) {
  44. mReceiveFd = -errno;
  45. ALOGE("BitTube(Parcel): can't dup filedescriptor (%s)",
  46. strerror(-mReceiveFd));
  47. }
  48. }
  49. BitTube::~BitTube()
  50. {
  51. if (mSendFd >= 0)
  52. close(mSendFd);
  53. if (mReceiveFd >= 0)
  54. close(mReceiveFd);
  55. }
  56. void BitTube::init(size_t rcvbuf, size_t sndbuf) {
  57. int sockets[2];
  58. if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {
  59. size_t size = DEFAULT_SOCKET_BUFFER_SIZE;
  60. setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(rcvbuf));
  61. setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
  62. // sine we don't use the "return channel", we keep it small...
  63. setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
  64. setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
  65. fcntl(sockets[0], F_SETFL, O_NONBLOCK);
  66. fcntl(sockets[1], F_SETFL, O_NONBLOCK);
  67. mReceiveFd = sockets[0];
  68. mSendFd = sockets[1];
  69. } else {
  70. mReceiveFd = -errno;
  71. ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
  72. }
  73. }
  74. status_t BitTube::initCheck() const
  75. {
  76. if (mReceiveFd < 0) {
  77. return status_t(mReceiveFd);
  78. }
  79. return NO_ERROR;
  80. }
  81. int BitTube::getFd() const
  82. {
  83. return mReceiveFd;
  84. }
  85. int BitTube::getSendFd() const
  86. {
  87. return mSendFd;
  88. }
  89. ssize_t BitTube::write(void const* vaddr, size_t size)
  90. {
  91. ssize_t err, len;
  92. do {
  93. len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
  94. // cannot return less than size, since we're using SOCK_SEQPACKET
  95. err = len < 0 ? errno : 0;
  96. } while (err == EINTR);
  97. return err == 0 ? len : -err;
  98. }
  99. ssize_t BitTube::read(void* vaddr, size_t size)
  100. {
  101. ssize_t err, len;
  102. do {
  103. len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT);
  104. err = len < 0 ? errno : 0;
  105. } while (err == EINTR);
  106. if (err == EAGAIN || err == EWOULDBLOCK) {
  107. // EAGAIN means that we have non-blocking I/O but there was
  108. // no data to be read. Nothing the client should care about.
  109. return 0;
  110. }
  111. return err == 0 ? len : -err;
  112. }
  113. status_t BitTube::writeToParcel(Parcel* reply) const
  114. {
  115. if (mReceiveFd < 0)
  116. return -EINVAL;
  117. status_t result = reply->writeDupFileDescriptor(mReceiveFd);
  118. close(mReceiveFd);
  119. mReceiveFd = -1;
  120. return result;
  121. }
  122. ssize_t BitTube::sendObjects(const sp<BitTube>& tube,
  123. void const* events, size_t count, size_t objSize)
  124. {
  125. const char* vaddr = reinterpret_cast<const char*>(events);
  126. ssize_t size = tube->write(vaddr, count*objSize);
  127. // should never happen because of SOCK_SEQPACKET
  128. LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
  129. "BitTube::sendObjects(count=%zu, size=%zu), res=%zd (partial events were sent!)",
  130. count, objSize, size);
  131. //ALOGE_IF(size<0, "error %d sending %d events", size, count);
  132. return size < 0 ? size : size / static_cast<ssize_t>(objSize);
  133. }
  134. ssize_t BitTube::recvObjects(const sp<BitTube>& tube,
  135. void* events, size_t count, size_t objSize)
  136. {
  137. char* vaddr = reinterpret_cast<char*>(events);
  138. ssize_t size = tube->read(vaddr, count*objSize);
  139. // should never happen because of SOCK_SEQPACKET
  140. LOG_ALWAYS_FATAL_IF((size >= 0) && (size % static_cast<ssize_t>(objSize)),
  141. "BitTube::recvObjects(count=%zu, size=%zu), res=%zd (partial events were received!)",
  142. count, objSize, size);
  143. //ALOGE_IF(size<0, "error %d receiving %d events", size, count);
  144. return size < 0 ? size : size / static_cast<ssize_t>(objSize);
  145. }
  146. // ----------------------------------------------------------------------------
  147. }; // namespace android