前言:
相对于其他模块, 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
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
首先为每一个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);
流程图如下,
SensorDevice继承于Singleton,所以整个android系统中,仅有一个SensorDevice对象,
class SensorDevice : public Singleton {
friend class Singleton;
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 ; iactivate(
reinterpret_cast(mSensorDevice), list[i].handle, 0);
}
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(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;
上层调用模块的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 sensor
char vendor[SYSFS_MAXLEN]; // vendor of the sensor
char enable_path[PATH_MAX]; // the control path of this sensor
char data_path[PATH_MAX]; // the data path to get sensor events
struct sensor_t *sensor; // point to the sensor_t structure in the sensor list
SensorBase *driver; // point to the sensor driver instance
int data_fd; // the file descriptor of the data device node
int enable; // indicate if the sensor is enabled
bool is_virtual; // indicate if this is a virtual sensor
int64_t delay_ns; // the poll delay setting of this sensor
int64_t latency_ns; // the max report latency of this sensor
struct listnode dep_list; // the background sensor type needed for this sensor
struct listnode listener; // the head of listeners of this sensor
};
SensorContext保存着对应sensor驱动的各种信息,读取sensor的值时会使用该结构体的data_fd变量。
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到驱动这条路就打通了。
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中。
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;
}
启动服务的代码如下,
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数据。