Android 4.0里面除了个BitTube的东西,字面意思理解就是字节管道,可以用来在进程间进行数据的传递,但是是单向的
如果要在两个进程间使用BitTube进行数据的传递,一般都是这么使用的(以SensorEventConnection和SensorEventQueue通信为例)
1、首先在SensorEventConnection的构造函数里面 new 一个BitTube,不需要参数,
SensorService::SensorEventConnection::SensorEventConnection( const sp<SensorService>& service) : mService(service), mChannel(new BitTube()) { }
我们看下BitTube的构造函数
BitTube::BitTube() : mSendFd(-1), mReceiveFd(-1) { int sockets[2]; if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) {//创造一对未命名的、相互连接的UNIX域套接字 int size = SOCKET_BUFFER_SIZE; setsockopt(sockets[0], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); setsockopt(sockets[0], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); setsockopt(sockets[1], SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); setsockopt(sockets[1], SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); fcntl(sockets[0], F_SETFL, O_NONBLOCK);//设置为非阻塞 fcntl(sockets[1], F_SETFL, O_NONBLOCK);//设置为非阻塞 mReceiveFd = sockets[0];//用于数据接收的socket mSendFd = sockets[1];//用于数据发送的socket } else { mReceiveFd = -errno; ALOGE("BitTube: pipe creation failed (%s)", strerror(-mReceiveFd)); } }
里面主要就是创建了一对未命名的互连的套接字,并设置为非阻塞的
2、然后,我们就可以使用这个BitTube了,这里这里在SensorEventQueue的onFirstRef调用时,
void SensorEventQueue::onFirstRef() { mSensorChannel = mSensorEventConnection->getSensorChannel(); }
通过getSensorChannel获取SensorEventConnection端面的BitTube我们看一下这个函数的实现,从Bp端面到Bn端
virtual sp<BitTube> getSensorChannel() const { Parcel data, reply; data.writeInterfaceToken(ISensorEventConnection::getInterfaceDescriptor()); remote()->transact(GET_SENSOR_CHANNEL, data, &reply); return new BitTube(reply); }
利用返回值new 一个新的BitTube
BitTube::BitTube(const Parcel& data) : mSendFd(-1), mReceiveFd(-1) { mReceiveFd = dup(data.readFileDescriptor()); if (mReceiveFd >= 0) { int size = SOCKET_BUFFER_SIZE; setsockopt(mReceiveFd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); setsockopt(mReceiveFd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); fcntl(mReceiveFd, F_SETFL, O_NONBLOCK); } else { mReceiveFd = -errno; ALOGE("BitTube(Parcel): can't dup filedescriptor (%s)", strerror(-mReceiveFd)); } }
利用readFileDescriptor读取描述符,然后设置mReceiveFd
3、我们看一下相应的Bn端是怎么实现的
status_t BnSensorEventConnection::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { switch(code) { case GET_SENSOR_CHANNEL: { CHECK_INTERFACE(ISensorEventConnection, data, reply); sp<BitTube> channel(getSensorChannel()); channel->writeToParcel(reply); return NO_ERROR; } break; …. }
调用getSensorChannel返回我们在第一步中new出来的BitTube,然后调用BitTube的writeToParcel
status_t BitTube::writeToParcel(Parcel* reply) const { if (mReceiveFd < 0) return -EINVAL; status_t result = reply->writeDupFileDescriptor(mReceiveFd); close(mReceiveFd); mReceiveFd = -1; return result; }
其实就是将其mReceiveFd描述符返回过去
通过这几步我们就可以在SensorEventConnection中发送数据,
ssize_tSensorEventQueue::write(const sp<BitTube>& tube,
ASensorEvent const* events, size_tnumEvents) {
return BitTube::sendObjects(tube, events,numEvents);
}
这里的tube参数就是我们第一步创建的
然后在SensorEventQueue读取数据
ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents) { return BitTube::recvObjects(mSensorChannel, events, numEvents); }
这里的mSensorChannel就是我们上面第二步创建的。