android sensor 框架分析---服务端
来源:互联网 发布:linux怎么用vi创建文件 编辑:程序博客网 时间:2024/05/01 09:18
前言:
相对于其他模块, Sensor的API还是非常简洁的.对Sensor的开发也很简单。Android 6.0 系统支持的传感器
多达26种,加速度传感器 (accelerometer)、磁力传感器(magnetic field)、方向传感器(orientation)、
陀螺仪(gyroscope)、环境光照传感器(light)、压力传感器(pressure)、温度传感器(temperature)和
距离传感器(proximity)等等, Sensor.java 中有相关定义。
服务端的代码路径如下,
frameworks\native\services\sensorservice
HAL对应的代码如下,
hardware\libhardware\include\hardware\ sensor.h
hardware\qcom\sensors
其他代码对应路径
frameworks\native\libs\gui
1,概述
Sensor架构图如下,
主要包括2个进程,服务端和客户端。
Sensor的整体逻辑非常清晰,一个控制流,一个数据流。
2 sensor服务端
开始一直以为sensor服务进程向很多守护进程一样通过init.rc配置文件启动,后来才发现是通过systemserver进程启动,
并且运行于systemserver进程中,就像systemserver中的各种服务一样,只是通过C/C++实现而已。
启动流程图如下,
SystemServer对应的为com_android_server_SystemServer.cpp,其实, SystemServer中只有一个native方法,
就是startSensorService,说了这么多, com_android_server_SystemServer.cpp就是为了启动sensor服务才有的。
sensorInit方法如下,
void* sensorInit(void *arg) { ALOGI("System server: starting sensor init.\n"); // Start the sensor service SensorService::instantiate();//new SensorService对象 ALOGI("System server: sensor init done.\n"); return NULL;}
SensorService的onFirstRef方法中,主要逻辑如下,
1,获取SensorDevice对象,
SensorDevice& dev(SensorDevice::getInstance());
2, 获取Sensor列表
ssize_t count = dev.getSensorList(&list);
3,sensor注册
for (ssize_t i=0 ; i<count ; i++) { registerSensor( new HardwareSensor(list[i]) );
首先为每一个sensor注册一个对应的HardwareSensor。
然后对有些sensor,注册特殊的sensor,例如,
aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );
4,启动服务
mAckReceiver = new SensorEventAckReceiver(this);mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);run("SensorService", PRIORITY_URGENT_DISPLAY);
2.1初始化
流程图如下,
SensorDevice继承于Singleton,所以整个android系统中,仅有一个SensorDevice对象,
class SensorDevice : public Singleton<SensorDevice> {friend class Singleton<SensorDevice>; sensors_poll_device_1_t* mSensorDevice; struct sensors_module_t* mSensorModule;
SensorDevice的构造方法主要逻辑如下,
1,加载sensor模块so库
status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&mSensorModule);
并且mSensorModule变量就指向sensor模块so库。通过该变量可以调用sensor模块so库中的方法。
但是mSensorDevice又是什么呢?是sensors_poll_device_1_t对象,
sensors_poll_device_1_t在sensor.h中定义,只是一个有些方法的结构体。
2, 调用sensor.h的sensors_open_1方法打开设备
err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
3,获取so库的Sensor列表
ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list); mActivationCount.setCapacity(count);
4,激活sensor
for (size_t i=0 ; i<size_t(count) ; i++) { mActivationCount.add(list[i].handle, model); mSensorDevice->activate( reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), list[i].handle, 0);}
2.1.1 sensor模块打开
sensor.h中的sensors_open_1方法如下,
static inline int sensors_open_1(const struct hw_module_t* module, sensors_poll_device_1_t** device) { return module->methods->open(module, SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);}
直接调用sensor模块的open方法,
sensors.cpp对应的open方法为open_sensors
static struct hw_module_methods_t sensors_module_methods = {open: open_sensors};
在open_sensors方法中主要进行一些初始化的操作。
1,构造NativeSensorManager对象,
NativeSensorManager& sm(NativeSensorManager::getInstance());
2,构造sensors_poll_context_t,并且初始化,
sensors_poll_context_t *dev = new sensors_poll_context_t();•••dev->device.common.module = const_cast<hw_module_t*>(module);dev->device.common.close= poll__close;dev->device.activate= poll__activate;dev->device.setDelay= poll__setDelay;dev->device.poll= poll__poll;dev->device.calibrate= poll_calibrate;
sensors_poll_context_t是sensors.cpp内部的一个结构体,类似于一个类,里面也有各种方法。
这样,sensorservice也可以通过mSensorDevice调用HAL中的方法。
在sensors_poll_context_t的构造方法中,对每个event创建从driver中读取数据的节点。
for (i = 0; i < number; i++) {context = sm.getInfoByHandle(slist[i].handle);mPollFds[i].fd = (context == NULL) ? -1 : context->data_fd;mPollFds[i].events = POLLIN;mPollFds[i].revents = 0;}ALOGI("The avaliable sensor handle number is %d",i);int wakeFds[2];int result = pipe(wakeFds);ALOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);mWritePipeFd = wakeFds[1];mPollFds[number].fd = wakeFds[0];mPollFds[number].events = POLLIN;mPollFds[number].revents = 0;
2.1.2 模块的Sensor列表
上层调用模块的get_sensors_list方法其实就是调用module__get_sensors_list方法,
get_sensors_list: sensors__get_sensors_list,
该方法直接调用NativeSensorManager的getSensorList方法,
static int sensors__get_sensors_list(struct sensors_module_t*, struct sensor_t const** list){NativeSensorManager& sm(NativeSensorManager::getInstance());return sm.getSensorList(list);}
NativeSensorManager的getSensorList方法如下,
int NativeSensorManager::getSensorList(const sensor_t **list) {*list = mSensorCount ? sensor_list:NULL;return mSensorCount;}
直接返回NativeSensorManager的mSensorCount变量。
mSensorCount变量的值是在NativeSensorManager的构造方法中调用getDataInfo方法赋值的。
sensor_list 变量保存各种sensor。
getDataInfo方法会为每个sensor保存对应的SensorContext结构体,
NativeSensorManager.h的SensorContext结构体定义如下,
struct SensorContext {char name[SYSFS_MAXLEN]; // name of the sensorchar vendor[SYSFS_MAXLEN]; // vendor of the sensorchar enable_path[PATH_MAX]; // the control path of this sensorchar data_path[PATH_MAX]; // the data path to get sensor eventsstruct sensor_t *sensor; // point to the sensor_t structure in the sensor listSensorBase *driver; // point to the sensor driver instanceint data_fd; // the file descriptor of the data device nodeint enable; // indicate if the sensor is enabledbool is_virtual; // indicate if this is a virtual sensorint64_t delay_ns; // the poll delay setting of this sensorint64_t latency_ns; // the max report latency of this sensorstruct listnode dep_list; // the background sensor type needed for this sensorstruct listnode listener; // the head of listeners of this sensor};
SensorContext保存着对应sensor驱动的各种信息,读取sensor的值时会使用该结构体的data_fd变量。
2.1.3 激活Sensor
HAL 中的activate流程图如下,
poll__activate直接调用sensors_poll_context_t的activate方法,
static int poll__activate(struct sensors_poll_device_t *dev,int handle, int enabled) {sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;return ctx->activate(handle, enabled);}
sensors_poll_context_t的activate方法首先调用NativeSensorManager.c的activate方法打开对应的驱动设备文件,
然后往里面写入值1.
int sensors_poll_context_t::activate(int handle, int enabled) {int err = -1;NativeSensorManager& sm(NativeSensorManager::getInstance());Mutex::Autolock _l(mLock);err = sm.activate(handle, enabled);if (enabled && !err) {const char wakeMessage(WAKE_MESSAGE);int result = write(mWritePipeFd, &wakeMessage, 1);ALOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));}return err;}
SensorBase.cpp的enable方法是一个虚方法,由不同的独立的sensor去实现。
例如, Accelerometer.cpp的enable方法实现如下,
strlcpy(&input_sysfs_path[input_sysfs_path_len], SYSFS_ENABLE, SYSFS_MAXLEN);fd = open(input_sysfs_path, O_RDWR);if (fd >= 0) {char buf[2];int err;buf[1] = 0;if (flags) {buf[0] = '1';mEnabledTime = getTimestamp() + IGNORE_EVENT_TIME;sysclk_sync_offset = getClkOffset();} else {buf[0] = '0';}err = write(fd, buf, sizeof(buf));close(fd);mEnabled = flags;return 0;}
实际上就是获取对应加速度sensor的驱动节点路径,然后打开该路径,往里面写入2个字符。
这样,从HAL到驱动这条路就打通了。
2.2 获取sensor列表
SensorService.cpp的onFirstRef中获取sensor列表的代码如下,
sensor_t const* list;ssize_t count = dev.getSensorList(&list);
将获取的sensor保存在list中。
SensorDevice.cpp的getSensorList方法如下,
ssize_t SensorDevice::getSensorList(sensor_t const** list) { if (!mSensorModule) return NO_INIT; ssize_t count = mSensorModule->get_sensors_list(mSensorModule, list); return count;}
上节中已经说明了,调用模块的get_sensors_list方法将获取的sensor保存在list中。
2.3 sensor注册
registerSensor方法如下,
Sensor SensorService::registerSensor(SensorInterface* s){ sensors_event_t event; memset(&event, 0, sizeof(event)); const Sensor sensor(s->getSensor()); // add to the sensor list (returned to clients) mSensorList.add(sensor); // add to our handle->SensorInterface mapping mSensorMap.add(sensor.getHandle(), s); // create an entry in the mLastEventSeen array mLastEventSeen.add(sensor.getHandle(), NULL); return sensor;}
实际上就是将从sensor模块获取的sensor 对象以及相关信息分别放在mSensorList, mSensorMap等数据结构中。
registerVirtualSensor也是调用registerSensor方法完成的。
Sensor SensorService::registerVirtualSensor(SensorInterface* s){ Sensor sensor = registerSensor(s); mVirtualSensorList.add( s ); return sensor;}
2.4 启动服务
启动服务的代码如下,
mAckReceiver = new SensorEventAckReceiver(this);mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);run("SensorService", PRIORITY_URGENT_DISPLAY);
直接调用threadLoop方法,
do { ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
调用SensorDevice的poll方法读取sensor数据并且保存在mSensorEventBuffer中。具体的获取数据的过程下面再详细论述。
小结:
1,sensor服务端首先打通HAL和driver之间的通信。
2,激活各种sensor。
3,开启子线程读取sensor数据。
- android sensor 框架分析---服务端
- android sensor 框架分析---客户端和服务端的连接
- android sensor 框架分析---sensor数据流分析
- android sensor 框架分析---sensor native分析
- android sensor 框架分析---sensor 总结
- android sensor 框架分析---客户端
- Android Sensor底层框架
- Android Sensor 框架
- Android Sensor分析
- Sensor HAL框架分析之一
- Sensor HAL框架分析之一
- Sensor HAL框架分析之一
- android-5.0 sensor框架简介
- Android Sensor HAL层分析
- Sensor HAL框架分析之二
- Sensor HAL框架分析之三 .
- Sensor HAL框架分析之四 .
- Sensor HAL框架分析之三
- Servlet简介
- JAVA_1 异常处理
- 数组和列表的区别
- B
- 机器学习笔记之代价函数
- android sensor 框架分析---服务端
- Codeforces #590D: Top Secret Task 题解
- 10个重要的算法C语言实现源代码:拉格朗日,牛顿插值,高斯,龙贝格,牛顿迭代,牛顿-科特斯,雅克比,秦九昭,幂法,高斯塞德尔
- 面向对象(内部类的使用)
- linux 下的文件搜索、可执行文件搜索
- 剑指offer | 训练题61:二叉树搜索的第K个结点
- js call()方法
- SpringSecurity学习笔记(一) 核心类与接口
- 华为机试,字符串最后一个单词的长度