BitTube.cpp revision 3ad3807a5c4039618175c042a1121c926c2c62e9
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
20#include <unistd.h>
21#include <fcntl.h>
22
23#include <utils/Errors.h>
24
25#include <binder/Parcel.h>
26
27#include <gui/BitTube.h>
28
29namespace android {
30// ----------------------------------------------------------------------------
31
32BitTube::BitTube()
33    : mSendFd(-1), mReceiveFd(-1)
34{
35    int fds[2];
36    if (pipe(fds) == 0) {
37        mReceiveFd = fds[0];
38        mSendFd = fds[1];
39        fcntl(mReceiveFd, F_SETFL, O_NONBLOCK);
40        fcntl(mSendFd, F_SETFL, O_NONBLOCK);
41    } else {
42        mReceiveFd = -errno;
43        LOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd));
44    }
45}
46
47BitTube::BitTube(const Parcel& data)
48    : mSendFd(-1), mReceiveFd(-1)
49{
50    mReceiveFd = dup(data.readFileDescriptor());
51    if (mReceiveFd >= 0) {
52        fcntl(mReceiveFd, F_SETFL, O_NONBLOCK);
53    } else {
54        mReceiveFd = -errno;
55        LOGE("BitTube(Parcel): can't dup filedescriptor (%s)",
56                strerror(-mReceiveFd));
57    }
58}
59
60BitTube::~BitTube()
61{
62    if (mSendFd >= 0)
63        close(mSendFd);
64
65    if (mReceiveFd >= 0)
66        close(mReceiveFd);
67}
68
69status_t BitTube::initCheck() const
70{
71    if (mReceiveFd < 0) {
72        return status_t(mReceiveFd);
73    }
74    return NO_ERROR;
75}
76
77int BitTube::getFd() const
78{
79    return mReceiveFd;
80}
81
82ssize_t BitTube::write(void const* vaddr, size_t size)
83{
84    ssize_t err, len;
85    do {
86        len = ::write(mSendFd, vaddr, size);
87        err = len < 0 ? errno : 0;
88    } while (err == EINTR);
89    return err == 0 ? len : -err;
90
91}
92
93ssize_t BitTube::read(void* vaddr, size_t size)
94{
95    ssize_t err, len;
96    do {
97        len = ::read(mReceiveFd, vaddr, size);
98        err = len < 0 ? errno : 0;
99    } while (err == EINTR);
100    if (err == EAGAIN || err == EWOULDBLOCK) {
101        // EAGAIN means that we have non-blocking I/O but there was
102        // no data to be read. Nothing the client should care about.
103        return 0;
104    }
105    return err == 0 ? len : -err;
106}
107
108status_t BitTube::writeToParcel(Parcel* reply) const
109{
110    if (mReceiveFd < 0)
111        return -EINVAL;
112
113    status_t result = reply->writeDupFileDescriptor(mReceiveFd);
114    close(mReceiveFd);
115    mReceiveFd = -1;
116    return result;
117}
118
119// ----------------------------------------------------------------------------
120}; // namespace android
121