android sensor 框架分析---sensor数据流分析
来源:互联网 发布:尚学堂大数据视频下载 编辑:程序博客网 时间:2024/09/21 08:57
5,sensor数据流分析
前面几章做了很多准备和铺垫,这章终于可以分析sensor数据的传输流程了。主要步骤如下,
1,服务端通过HAL从驱动文件节点中获取sensor数据。
2,服务端通过管道发送数据。
3,客户端通过管道读取数据。
4,客户端吐出数据。
5.1服务端获取数据
启动sensor服务之后,就会调用SensorService.cpp的threadLoop方法,该方法首先不断调用SensorDevice.cpp的poll方法获取sensor数据,
do { ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
然后遍历activeConnections变量,向每一个客户端发送一份sensor数据。
for (size_t i=0 ; i < numConnections; ++i) { if (activeConnections[i] != 0) { activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch, mMapFlushEventsToConnections);
poll方法调用流程图如下,
这些方法都很简单,没什么可论述的。加速度sensor的readEvents调用流程图如下,
1,fill方法
Accelerometer.cpp 的readEvents中调用fill方法如下,
ssize_t n = mInputReader.fill(data_fd);
传入的data_fd是NativeSensorManager.h的SensorContext结构体的变量。见第二章2.1.2 小节。
fill方法如下,
ssize_t InputEventCircularReader::fill(int fd){ size_t numEventsRead = 0; if (mFreeSpace) { const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event)); if (nread<0 || nread % sizeof(input_event)) { // we got a partial event!! return nread<0 ? -errno : -EINVAL; } numEventsRead = nread / sizeof(input_event); if (numEventsRead) { mHead += numEventsRead; mFreeSpace -= numEventsRead; if (mHead > mBufferEnd) { size_t s = mHead - mBufferEnd; memcpy(mBuffer, mBufferEnd, s * sizeof(input_event)); mHead = mBuffer + s; } } } return numEventsRead;}
struct input_event* const mBuffer;struct input_event* const mBufferEnd;struct input_event* mHead;struct input_event* mCurr;ssize_t mFreeSpace;
mBuffer表示未读事件;
mHead表示未读事件的第一个,初始为缓冲区首部.
mBufferEnd表示未读事件的最后一个,初始为缓冲区尾部.
mCurr表示当前未读事件
struct input_event结构体定义在kernel/include/uapi/linux/input.h中,
struct input_event {struct timeval time;__u16 type;//类型,比如sensor,按键事件等__u16 code;__s32 value;//具体的数值};
2,获取sensor值,
while (count && mInputReader.readEvent(&event)) {int type = event->type;if (type == EV_ABS) {float value = event->value;if (event->code == EVENT_TYPE_ACCEL_X) {mPendingEvent.data[0] = value * CONVERT_ACCEL_X;} else if (event->code == EVENT_TYPE_ACCEL_Y) {mPendingEvent.data[1] = value * CONVERT_ACCEL_Y;} else if (event->code == EVENT_TYPE_ACCEL_Z) {mPendingEvent.data[2] = value * CONVERT_ACCEL_Z;}} else if (type == EV_SYN) {switch (event->code){case SYN_TIME_SEC:{mUseAbsTimeStamp = true;report_time = event->value*1000000000LL;}break;case SYN_TIME_NSEC:{mUseAbsTimeStamp = true;mPendingEvent.timestamp = report_time+event->value;}break;•••mInputReader.next();
首先获取加速度sensor三个方向上的值,然后获取对应的时间。
当然,时间有2部分组成,最后转化为ns相加。
InputEventReader.cpp的readEvent方法如下,
ssize_t InputEventCircularReader::readEvent(input_event const** events){ *events = mCurr; ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace; return available ? 1 : 0;}
3,读取下一个sensor的值
InputEventReader.cpp的next方法如下,
void InputEventCircularReader::next(){ mCurr++; mFreeSpace++; if (mCurr >= mBufferEnd) { mCurr = mBuffer; }}
这样,通过InputEventReader.cpp读取sensor设备节点的值。
5.2服务端发送数据
Sensor服务端每次读取数据之后,当然,一次读取一组sensor数据,这一组sensor数据可能有几个sensor值,也可能一个都没有。
for (size_t i=0 ; i < numConnections; ++i) { if (activeConnections[i] != 0) { activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch, mMapFlushEventsToConnections);
调用SensorEventConnection对象的sendEvents方法将数据发送给客户端。发送流程图如下,
最后的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); // cannot return less than size, since we're using SOCK_SEQPACKET err = len < 0 ? errno : 0; } while (err == EINTR); return err == 0 ? len : -err;}
利用mSendFd将数据写入管道。
注意, mSensorChannel就是指BitTube.cpp对象,在服务端和客户端共用一个。
5.3客服端读取数据
android_hardware_SensorManager.cpp内部类Receiver的handleEvent首先会读取服务端写入管道的数据,然后发送给Java上层。
读取代码如下,
while ((n = q->read(buffer, 16)) > 0) {
read方法的调用流程图如下,
BitTube.cpp的read方法如下,
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) { // EAGAIN means that we have non-blocking I/O but there was // no data to be read. Nothing the client should care about. return 0; } return err == 0 ? len : -err;}
使用mReceiveFd从管道中读取服务端发送过来的数据。
5.4客户端发送数据
handleEvent方法获取数据之后, 回调Java层SystemSensorManager的内部类SensorEventQueue的dispatchSensorEvent方法。
env->CallVoidMethod(receiverObj.get(),gBaseEventQueueClassInfo.dispatchSensorEvent, buffer[i].sensor, mScratch, status, buffer[i].timestamp);
最后调用注册的onSensorChanged吐出数据。
小结:
经过了前面那么多的铺垫,终于论述了数据从服务端到客户端客户端的过程。- android sensor 框架分析---sensor数据流分析
- android sensor 框架分析---sensor native分析
- android sensor 框架分析---sensor 总结
- android sensor 框架分析---服务端
- android sensor 框架分析---客户端
- Android Sensor分析
- Sensor HAL框架分析之一
- Sensor HAL框架分析之一
- Sensor HAL框架分析之一
- Android Sensor HAL层分析
- android sensor 框架分析---客户端和服务端的连接
- Sensor HAL框架分析之二
- Sensor HAL框架分析之三 .
- Sensor HAL框架分析之四 .
- Sensor HAL框架分析之三
- Sensor HAL框架分析之二
- Sensor HAL框架分析之四
- android2.3 G-sensor实现框架分析
- LinkedList
- react开发环境搭建
- ubuntu14.04上网问题
- Makefile
- Android 应用程序框架
- android sensor 框架分析---sensor数据流分析
- 深入理解Java类加载器(ClassLoader)
- Weak references & Soft references
- python2.6 升级到python2.7
- docker基本命令
- Java for Web学习笔记(六八):Service和Repository(3)异步Async和调度Schedule
- C#中主窗体Panel中加载其他多个窗体Panel控件
- 494Target Sum
- ray marching shader