sp
sp
while (assertStateLocked() == NO_ERROR) { //创建连接接口
sp
mSensorServer->createSensorEventConnection(); if (connection == NULL) {
// SensorService just died.
LOGE(\SensorService died.\
continue; }
//创建消息队列
queue = new SensorEventQueue(connection); break; }
return queue; }
View Code
客户端与服务器创建一个SensorEventConnection连接接口,而一个消息队列中包含一个连接接口。
创建连接接口:
sp
SensorService::createSensorEventConnection()
{
sp
return result; }
SensorService::SensorEventConnection::SensorEventConnection( const sp
: mService(service), mChannel(new BitTube ()) { }
View Code
关键在于BitTube,在构造函数中创建了管道:
BitTube::BitTube()
: mSendFd(-1), mReceiveFd(-1) {
int sockets[2];
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, sockets) == 0) { 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]; mSendFd = sockets[1]; } else {
mReceiveFd = -errno;
ALOGE(\strerror(-mReceiveFd));
} }
View Code
其中:fds[0]就是对应的mReceiveFd,是管道的读端,sensor数据的读取端,对应的是客户端进程访问的。
fds[1]就是对应mSendFd,是管道的写端,sensor数据写入端,是sensor的服务进程访问的一端。 通过pipe(fds)创建管道,通过fcntl来设置操作管道的方式,设置通道两端的操作方式为O_NONBLOCK ,非阻塞IO方式,read或write调用返回-1和EAGAIN错误。
总结下消息队列
客户端第一次注册监听器的时候,就需要创建一个消息队列,客户端创了SensorThread线程从消息队列里面读取数据。
SensorEventQueue中有一个SensorEventConnection实例的引用,SensorEventConnection中有一个BitTube实例的引用。
使能Sensor
客户端创建了连接接口SensorEventConnection后,可以调用其方法使能Sensor传感器:
status_t SensorService::SensorEventConnection::enableDisable( int handle, bool enabled) {
status_t err; if (enabled) {
err = mService->enable(this, handle); } else {
err = mService->disable(this, handle); }
return err; }
View Code
handle对应着Sensor传感器的句柄
服务端往管道写数据
bool SensorService::threadLoop() {
…… do {
count = device.poll(buffer, numEventMax);
recordLastValue(buffer, count); ……
// send our events to clients...
const SortedVector< wp
getActiveConnections());
size_t numConnections = activeConnections.size(); for (size_t i=0 ; i
connection->sendEvents(buffer, count, scratch); } }
} while (count >= 0 || Thread::exitPending()); return false; }
View Code
前面介绍过,在SensorService中,创建了一个线程不断从HAL层读取Sensor数据,就是在threadLoop方法中。
关键在与下面了一个for循环,其实是扫描有多少个客户端连接接口,然后就往没每个连接的管道中写数据。
status_t SensorService::SensorEventConnection::sendEvents( sensors_event_t const* buffer, size_t numEvents, sensors_event_t* scratch) {
// filter out events not for this connection size_t count = 0; if (scratch) { …… } ……
if (count == 0) return 0;
ssize_t size = mChannel->write(scratch, count*sizeof(sensors_event_t));
…… }
View Code
调用该连接接口的BitTube::write():
ssize_t BitTube::write(void const* vaddr, size_t size) {
ssize_t err, len; do {
len = ::send(mSendFd, vaddr, size, MSG_DONTWAIT | MSG_NOSIGNAL);
err = len < 0 ? errno : 0; } while (err == EINTR);
return err == 0 ? len : -err; } }
View Code
到此,服务端就完成了往管道的写端写入数据。
客户端读管道数据
时序图
ssize_t SensorEventQueue::read(ASensorEvent* events, size_t numEvents)
{
return BitTube::recvObjects(mSensorChannel, events, numEvents); }
View Code
调用到了BitTube::read():
static ssize_t recvObjects(const sp
return recvObjects(tube, events, count, sizeof(T)); }
ssize_t BitTube::recvObjects(const sp
ssize_t numObjects = 0;
for (size_t i=0 ; i char* vaddr = reinterpret_cast // error occurred return size; } else if (size == 0) { // no more messages break; } numObjects++; } return numObjects; } ssize_t BitTube::read(void* vaddr, size_t size) { ssize_t err, len; do { len = ::recv(mReceiveFd, vaddr, size, MSG_DONTWAIT); err = len < 0 ? errno : 0; } while (err == EINTR); if (err == EAGAIN || err == EWOULDBLOCK) { return 0; } return err == 0 ? len : -err; } View Code