分析背景:
Android4.1.2(Based on CyanogenMod 10)
DASH(
https://github.com/sonyxperiadev/DASH)
1.接口头文件
sensors.h(hardware/libhardware/include/sensors.h)
刚一打开就看到SENSOR HAL的ID 为"SENSORS_HARDWARE_MODULE_ID"。
[mw_shl_code=java,true]/**
* Handles must be higher than SENSORS_HANDLE_BASE and must be unique.
* A Handle identifies a given sensors. The handle is used to activate
* and/or deactivate sensors.
* In this version of the API there can only be 256 handles.
*/
#define SENSORS_HANDLE_BASE 0
#define SENSORS_HANDLE_BITS 8
#define SENSORS_HANDLE_COUNT (1<<SENSORS_HANDLE_BITS)
/* 8位能够支持256个handle */
/**
* Sensor types
*/
#define SENSOR_TYPE_ACCELEROMETER 1 //加速度传感器
#define SENSOR_TYPE_MAGNETIC_FIELD 2 //磁力传感器
#define SENSOR_TYPE_ORIENTATION 3 //方向传感器
#define SENSOR_TYPE_GYROSCOPE 4 //陀螺仪
#define SENSOR_TYPE_LIGHT 5 //亮度传感器
#define SENSOR_TYPE_PRESSURE 6 //压力传感器
#define SENSOR_TYPE_TEMPERATURE 7 // deprecated 温度传感器,以后的版本中将看不到任何身影
#define SENSOR_TYPE_PROXIMITY 8 //距离传感器[/mw_shl_code]
[mw_shl_code=java,true]#define SENSOR_TYPE_GRAVITY 9 //重力传感器
#define SENSOR_TYPE_LINEAR_ACCELERATION 10 //速度传感器
#define SENSOR_TYPE_ROTATION_VECTOR 11 //旋转矢量传感器
#define SENSOR_TYPE_RELATIVE_HUMIDITY 12 //相对湿度传感器
#define SENSOR_TYPE_AMBIENT_TEMPERATURE 13 //环境温度传感器[/mw_shl_code]
支持的传感器还很多,但是 一般设备并不会用到这么多传感器,也就是加速度传感器、重力传感器、方向传感器、距离传感器、光线传感器这些,陀螺仪都很少见。
[mw_shl_code=java,true]/**
* Definition of the axis
* ----------------------
*
* This API is relative to the screen of the device in its default orientation,
* that is, if the device can be used in portrait or landscape, this API
* is only relative to the NATURAL orientation of the screen. In other words,
* the axis are not swapped when the device's screen orientation changes.
* Higher level services /may/ perform this transformation.
*
* x<0 x>0
* ^
* |
* +-----------+--> y>0
* | |
* | |
* | 设备 |
* | | / z<0
* | 面朝天空 | /
* | | /
* O-----------+/
* |[] [ ] []/
* +----------/+ y<0
* /
* /
* |/ z>0 (toward the sky)
*
* O: Origin (x=0,y=0,z=0)[/mw_shl_code]
还用有趣的符号图形形象的描述了“轴”的概念。然后就是一坨坨的传感器知识,blablabla......
定义了几个结构体:
1) sensors_vec_t 对单个传感器的泛用性封装,包含坐标、角度、状态等信息;
2) sensors_event_t 对传感器细致的数据再封装,包含版本号、传感器类型、数据、加速度、磁力、角度、重力等等等等的信息;
3) sensor_t 对应每个传感器,是都会有的数据,包括传感器名称、版本、handle句柄、类型、最大范围、解析度、耗能、最小延迟等信息;
4) sensors_module_t 对hw_module_t的扩展,不仅有common为hw_module_t,还定义了一个函数get_sensors_list用来获取所支持的传感器,返回值为传感器总数;
5) sensors_poll_device_t 每个传感器所私有的数据操作,包括(反)激活、设置延时、提取数据等动作。
最后定义了两个API函数用来打开/关闭一个传感器。
[mw_shl_code=java,true]static inline int sensors_open(const struct hw_module_t* module,
struct sensors_poll_device_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);
}
static inline int sensors_close(struct sensors_poll_device_t* device) {
return device->common.close(&device->common);
}[/mw_shl_code]
2. 服务开启之路(1)
sensor服务由system_server开启:
frameworks/base/cmds/system_server/system_init.cpp
[mw_shl_code=java,true]extern "C" status_t system_init()
{
ALOGI("Entered system_init()");
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
ALOGI("ServiceManager: %p\n", sm.get());
...
}
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the sensor service
SensorService::instantiate();
}
...
}[/mw_shl_code]
调用到frameworks/base/services/sensorservice/SensorService.cpp
[mw_shl_code=java,true]void SensorService::onFirstRef()
{
ALOGD("nuSensorService starting...");
SensorDevice& dev(SensorDevice::getInstance());
[/mw_shl_code]
之后又调用到了SensorDevice.cpp(同目录下)
[mw_shl_code=java,true]SensorDevice::SensorDevice()
: mSensorDevice(0),
mSensorModule(0)
{
status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,
(hw_module_t const**)&mSensorModule);
ALOGE_IF(err, "couldn't load %s module (%s)",
SENSORS_HARDWARE_MODULE_ID, strerror(-err));
if (mSensorModule) {
err = sensors_open(&mSensorModule->common, &mSensorDevice);
ALOGE_IF(err, "couldn't open device for module %s (%s)",
SENSORS_HARDWARE_MODULE_ID, strerror(-err));
if (mSensorDevice) {
sensor_t const* list;
ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
mActivationCount.setCapacity(count);
Info model;
for (size_t i=0 ; i<size_t(count) ; i++) {
mActivationCount.add(list
.handle, model);
mSensorDevice->activate(mSensorDevice, list.handle, 0);
}
}
}
}
[/mw_shl_code]
这段负责打开HAL,取得需要的数据及handle,对应的部分在HAL的代码中,见DASH/sensors_module.c
[mw_shl_code=java,true]struct sensors_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 0,
id: SENSORS_HARDWARE_MODULE_ID,
name : "dash",
author : "oskar.andero@sonymobile.com",
methods: &sensors_module_methods,
},
get_sensors_list: sensors_list_get
};[/mw_shl_code]
ID对上了,即可以成功打开,mSensorModule变得有效了。
然后SensorDevice.cpp调用API sensors_open,这个函数在接口头文件中有定义:
[mw_shl_code=java,true]static inline int sensors_open(const struct hw_module_t* module,
struct sensors_poll_device_t** device) {
return module->methods->open(module,
SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);
}[/mw_shl_code]
是开调用HAL的open方法:
[mw_shl_code=java,true]static int sensors_module_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device)
{
struct sensors_poll_device_t *dev;
if (strcmp(id, SENSORS_HARDWARE_POLL))
return 0;
dev = malloc(sizeof(*dev));
if (!dev)
return -1;
memset(dev, 0, sizeof(*dev));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (struct hw_module_t*)module;
dev->common.close = sensors_module_close;
dev->activate = sensors_module_activate;
dev->setDelay = sensors_module_set_delay;
dev->poll = sensors_module_poll;
*device = (struct hw_device_t*) dev;
sensors_config_read(NULL);
sensors_fifo_init();
sensors_list_foreach_api(sensors_init_iterator, NULL);
return 0;
}
struct hw_module_methods_t sensors_module_methods = {
open: sensors_module_open
};[/mw_shl_code]
实际调用到了sensors_module_open,此函数返回0代表成功,-1代表打开失败,主要工作是组装device,最终将句柄交给mSensorDevice,即:
[mw_shl_code=java,true] mSensorDevice->common.tag = HARDWARE_DEVICE_TAG;
mSensorDevice->common.version = 0;
mSensorDevice->common.module = (struct hw_module_t*)module;
mSensorDevice->common.close = sensors_module_close;
mSensorDevice->activate = sensors_module_activate;
mSensorDevice->setDelay = sensors_module_set_delay;
mSensorDevice->poll = sensors_module_poll;
[/mw_shl_code]
之前在说明接口头文件时,说明了,对于传感器的数据操作有三个重要函数就是avtivate, setDelay, poll。记住这几个函数,稍后做分析。
在mSensorDevice成功被组装后,调用sensors_module_t自创的另一重要接口:get_sensors_list。瞧一瞧此函数在本实例中的具体实现(DASH/sensors_list.c):
[mw_shl_code=java,true]static struct sensor_t sensors[DASH_MAX_SENSORS];
static struct sensor_api_t* sensor_apis[DASH_MAX_SENSORS];
static int number_of_sensors = 0;
[/mw_shl_code]
[mw_shl_code=java,true]int sensors_list_get(struct sensors_module_t* module, struct sensor_t const** plist)
{
*plist = sensors;
return number_of_sensors;
}[/mw_shl_code]
此函数完成两个工作,一将传感器列表赋给指针plist,二返回传感器数量。这里sensors列表和number_of_sensors是如何运作的:
[mw_shl_code=java,true]int sensors_list_register(struct sensor_t* sensor, struct sensor_api_t* api)
{
if (!sensor || !api)
return -1;
if (number_of_sensors > DASH_MAX_SENSORS-1)
return -1;
sensor_apis[number_of_sensors] = api;
/* We have to copy due to sensor API */
memcpy(&sensors[number_of_sensors++], sensor, sizeof(*sensor));
return 0;
}[/mw_shl_code]
每个传感器都会调用sensors_list_register将自己注册进sensors列表中,并且会将自己的API也注册进sensors_apis列表中,来一个例子吧(DASH/sensors/bma150_input.c):
[mw_shl_code=java,true]struct sensor_desc {
struct sensors_select_t select_worker;
struct sensor_t sensor;
struct sensor_api_t api;
int input_fd;
float current_data[3];
char *rate_path;
/* config options */
int axis_x;
int axis_y;
int axis_z;
int neg_x;
int neg_y;
int neg_z;
int64_t delay_requests[MAX_CLIENTS];
};
static struct sensor_desc bma150_input = {
.sensor = {
name: "BMA150 accelerometer",
vendor: "Bosch Sensortec GmbH",
version: sizeof(sensors_event_t),
handle: SENSOR_ACCELEROMETER_HANDLE,
type: SENSOR_TYPE_ACCELEROMETER,
maxRange: 9.81,
resolution: 20,
power: 0.13,
minDelay: 5000
},
.api = {
init: bma150_input_init,
activate: bma150_input_activate,
set_delay: bma150_input_fw_delay,
close: bma150_input_close
},
.input_fd = -1,
.axis_x = 0,
.axis_y = 1,
.axis_z = 2,
.neg_x = 0,
.neg_y = 0,
.neg_z = 0
};[/mw_shl_code]
以上是BMA150注册了属于自己的初始化、激活、延迟、关闭等操作。
每次注册完成后自会对number_of_sensors进行+1操作。这样所有的传感器注册完成后,就会形成两个列表和一个传感器总数。sensors_list_get也就理解了。
在获取到总数后,会根据总数进行循环遍历,挨个激活传感器。
[mw_shl_code=java,true]for (size_t i=0 ; i<size_t(count) ; i++) {
mActivationCount.add(list.handle, model);
mSensorDevice->activate(mSensorDevice, list.handle, 0);
}[/mw_shl_code]
OK,这下,引出了三大数据处理函数之一:activate。
sensors_module.c
[mw_shl_code=java,true]/* mSensorDevice->activate = sensors_module_activate; */
static int sensors_module_activate(struct sensors_poll_device_t *dev,
int handle, int enabled)
{
struct sensor_api_t* api = sensors_list_get_api_from_handle(handle);
if (!api) {
ALOGE("%s: unable to find handle!", __func__);
return -1;
}
if (api->activate(api, enabled) < 0)
return -1;
return 0;
}
[/mw_shl_code]
sensors_list.c
[mw_shl_code=java,true]struct sensor_api_t* sensors_list_get_api_from_handle(int handle)
{
int i;
for (i = 0; i < number_of_sensors; i++)
if (sensors.handle == handle)
return sensor_apis;
return NULL;
}[/mw_shl_code]
比如BMA150的handle就是SENSOR_ACCELEROMETER_HANDLE,通过简单的匹配后,就能找到对应的sensors_api[x],然后执行active也就是bma150_input_activate函数,有兴趣就简单看一下代码,大体意思就是打开驱动获取句柄,然后组装给相关参数。
至此SensorDevice的大体工作也就完成了,总结就是成功获取HAL后,对每个传感器执行activate操作。
3.服务开启之路(2)
之所分(1)(2)是觉得SensorDevice部分可以单独成一部分,毕竟多数是在跟HAL在交互,这部分将分析完服务部分。
回头看SensorService::onFirstRef()
[mw_shl_code=java,true]void SensorService::onFirstRef()
{
ALOGD("nuSensorService starting...");
SensorDevice& dev(SensorDevice::getInstance());
if (dev.initCheck() == NO_ERROR) {
/**********************************
检测SensorDevice执行是否成功,所获取的数据是否有效。
>status_t SensorDevice::initCheck() const {
return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT;
}
**********************************/
sensor_t const* list;
ssize_t count = dev.getSensorList(&list);
/* 执行与(1)中sensors_list_get一样的工作 */
if (count > 0) {
ssize_t orientationIndex = -1;
bool hasGyro = false;
uint32_t virtualSensorsNeeds =
(1<<SENSOR_TYPE_GRAVITY) |
(1<<SENSOR_TYPE_LINEAR_ACCELERATION) |
(1<<SENSOR_TYPE_ROTATION_VECTOR);
mLastEventSeen.setCapacity(count);
for (ssize_t i=0 ; i<count ; i++) {
registerSensor( new HardwareSensor(list) );
switch (list.type) {
case SENSOR_TYPE_ORIENTATION:
orientationIndex = i;
break;
case SENSOR_TYPE_GYROSCOPE:
hasGyro = true;
break;
case SENSOR_TYPE_GRAVITY:
case SENSOR_TYPE_LINEAR_ACCELERATION:
case SENSOR_TYPE_ROTATION_VECTOR:
virtualSensorsNeeds &= ~(1<<list.type);
break;
}
}
/* 遍历查看SENSOR HAL都支持哪些类型的传感器 */
// it's safe to instantiate the SensorFusion object here
// (it wants to be instantiated after h/w sensors have been
// registered)
const SensorFusion& fusion(SensorFusion::getInstance());
if (hasGyro) {
// Always instantiate Android's virtual sensors. Since they are
// instantiated behind sensors from the HAL, they won't
// interfere with applications, unless they looks specifically
// for them (by name).
registerVirtualSensor( new RotationVectorSensor() );
registerVirtualSensor( new GravitySensor(list, count) );
registerVirtualSensor( new LinearAccelerationSensor(list, count) );
// these are optional
registerVirtualSensor( new OrientationSensor() );
registerVirtualSensor( new CorrectedGyroSensor(list, count) );
// virtual debugging sensors...
char value[PROPERTY_VALUE_MAX];
property_get("debug.sensors", value, "0");
if (atoi(value)) {
registerVirtualSensor( new GyroDriftSensor() );
}
} else if (orientationIndex != -1) {
// If we don't have a gyro but have a orientation sensor from
// elsewhere, we can compute rotation vector from that.
// (Google Maps expects rotation vector sensor to exist.)
registerVirtualSensor( &RotationVectorSensor2::getInstance() );
}
// build the sensor list returned to users
mUserSensorList = mSensorList;
if (hasGyro &&
(virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) {
// if we have the fancy sensor fusion, and it's not provided by the
// HAL, use our own (fused) orientation sensor by removing the
// HAL supplied one form the user list.
if (orientationIndex >= 0) {
mUserSensorList.removeItemsAt(orientationIndex);
}
}
run("SensorService", PRIORITY_URGENT_DISPLAY);
mInitCheck = NO_ERROR;
}
}
}
[/mw_shl_code]
从上面可以看出,如果传感器中有SENSOR_TYPE_GYROSCOPE类型的话,也就是陀螺仪(高端传感器),会定义hasGyro,从而注册多个虚拟传感器,blablabla……
最后会触发一个重要动作:run。
回头查看SensorService类的定义:
[mw_shl_code=java,true]从上面可以看出,如果传感器中有SENSOR_TYPE_GYROSCOPE类型的话,也就是陀螺仪(高端传感器),会定义hasGyro,从而注册多个虚拟传感器,blablabla……
最后会触发一个重要动作:run。
回头查看SensorService类的定义:
[/mw_shl_code]
发现SensorService是继承了Thread的。
那么run的工作实际是启动了线程,threadLoop:
[mw_shl_code=java,true]bool SensorService::threadLoop()
{
ALOGD("nuSensorService thread starting...");
const size_t numEventMax = 16;
const size_t minBufferSize = numEventMax + numEventMax * mVirtualSensorList.size();
sensors_event_t buffer[minBufferSize];
sensors_event_t scratch[minBufferSize];
SensorDevice& device(SensorDevice::getInstance());
const size_t vcount = mVirtualSensorList.size();
ssize_t count;
do {
count = device.poll(buffer, numEventMax);
if (count<0) {
ALOGE("sensor poll failed (%s)", strerror(-count));
break;
}
...
}[/mw_shl_code]
发现这个线程会一直执行poll操作,这个操作是什么呢?还记得“服务开启之路(1)”中提到的吗?
[mw_shl_code=java,true]mSensorDevice->poll = sensors_module_poll;[/mw_shl_code]
是在HAL中的函数,最终指向sensors_module_poll ( DASH/sensors_module.c )
[mw_shl_code=java,true]static int sensors_module_poll(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count)
{
int ret;
while ((ret = sensors_fifo_get_all(data, count)) == 0)
;
return ret;
}[/mw_shl_code]
( DASH/sensors_fifo.c )
[mw_shl_code=java,true]void sensors_fifo_put(sensors_event_t *data)
{
pthread_mutex_lock(&sensors_fifo.mutex);
if (sensors_fifo.fifo_i < FIFO_LEN)
sensors_fifo.fifo[sensors_fifo.fifo_i++] = *data;
pthread_cond_broadcast(&sensors_fifo.data_cond);
pthread_mutex_unlock(&sensors_fifo.mutex);
}
int sensors_fifo_get_all(sensors_event_t *data, int len)
{
int i;
/* This function deliberately drops all packets above len. */
pthread_mutex_lock(&sensors_fifo.mutex);
pthread_cond_wait(&sensors_fifo.data_cond, &sensors_fifo.mutex);
for (i = 0; (i < sensors_fifo.fifo_i) && (i < len); i++)
data = sensors_fifo.fifo;
sensors_fifo.fifo_i = 0;
pthread_mutex_unlock(&sensors_fifo.mutex);
return i;
}[/mw_shl_code]
上边的函数用到了线程等待,有兴趣的可以去百度,很好理解,就是两个线程等待一个变量data_cond,sensors_fifo_put在放置完data后会释放掉data_cond,而sensors_fifo_get_all在data_cond释放之前会一直进行等待。
继续向前跟踪sensors_fifo_put ( DASH/sensors/bma150_input.c ):
[mw_shl_code=java,true]static void *bma150_input_read(void *arg)
{
struct sensor_api_t *s = arg;
struct sensor_desc *d = container_of(s, struct sensor_desc, api);
struct input_event event;
int fd = d->select_worker.get_fd(&d->select_worker);
sensors_event_t data;
memset(&data, 0, sizeof(data));
while (read(fd, &event, sizeof(event)) > 0) {
switch (event.type) {
case EV_ABS:
switch (event.code) {
case ABS_X:
d->current_data[0] = ev2grav(event.value);
break;
case ABS_Y:
d->current_data[1] = ev2grav(event.value);
break;
case ABS_Z:
d->current_data[2] = ev2grav(event.value);
break;
case ABS_MISC:
default:
break;
}
break;
case EV_SYN:
data.acceleration.x = (d->neg_x ? -d->current_data[d->axis_x] :
d->current_data[d->axis_x]);
data.acceleration.y = (d->neg_y ? -d->current_data[d->axis_y] :
d->current_data[d->axis_y]);
data.acceleration.z = (d->neg_z ? -d->current_data[d->axis_z] :
d->current_data[d->axis_z]);
data.acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
data.sensor = bma150_input.sensor.handle;
data.type = bma150_input.sensor.type;
data.version = bma150_input.sensor.version;
data.timestamp = get_current_nano_time();
sensors_fifo_put(&data);
goto exit;
default:
goto exit;
}
}
exit:
return NULL;
}[/mw_shl_code]
上述函数很好理解,首先取得此传感器的内核驱动句柄,然后等待此句柄输出信息,当取得信息后,对信息进行解析与再封装,最终写入到data中。那么bma150_input_read又是谁来调用呢?答案在此传感器的初始化过程中:
[mw_shl_code=java,true]static int bma150_input_init(struct sensor_api_t *s)
{
struct sensor_desc *d = container_of(s, struct sensor_desc, api);
int fd;
bma150_input_read_config(d);
/* check for availablity */
fd = open_input_dev_by_name(BMA150_INPUT_NAME, O_RDONLY | O_NONBLOCK);
if (fd < 0) {
ALOGE("%s: unable to find %s input device!\n", __func__,
BMA150_INPUT_NAME);
return -1;
}
d->rate_path = bma150_get_rate_path(fd);
close(fd);
sensors_select_init(&d->select_worker, bma150_input_read, s, -1);
return 0;
}[/mw_shl_code]
可能现在会有迷惑,这个bma150_input_init是什么时候启动的呢?这是问题1,问题2是sensors_select_init是怎么吧bma150_input_read启动起来的?
下面一次解决,问题1:
[mw_shl_code=java,true]static struct sensor_desc bma150_input = {
...
.api = {
init: bma150_input_init,
activate: bma150_input_activate,
set_delay: bma150_input_fw_delay,
close: bma150_input_close
},
...
};[/mw_shl_code]
bma150_input_init被注册到api->init.
( DASH/sensors_module.c )
[mw_shl_code=java,true]static int sensors_module_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device)
{
...
sensors_list_foreach_api(sensors_init_iterator, NULL);
return 0;
}
static int sensors_init_iterator(struct sensor_api_t* api, void *arg)
{
return api->init(api);
}
[/mw_shl_code]
( DASH/sensors_list.c )
[mw_shl_code=java,true]void sensors_list_foreach_api(int (*f)(struct sensor_api_t* api, void* arg),
void *arg)
{
int i;
for (i = 0; i < number_of_sensors; i++)
if (f(sensor_apis, arg) != SENSOR_OK) {
sensors_list_deregister(sensor_apis);
/* need to revisit this position after deregister */
--i;
}
}[/mw_shl_code]
遍历所有注册过的传感器,执行其api->init. 问题1解决完毕。
问题2:
( DASH/sensors_select.c )
[mw_shl_code=java,true]void sensors_select_init(struct sensors_select_t* s,
void* (*select_func)(void *arg), void* arg, int fd)
{
s->suspend = sensors_select_suspend;
s->resume = sensors_select_resume;
s->destroy = sensors_select_destroy;
s->set_delay = sensors_select_set_delay;
s->set_fd = sensors_select_set_fd;
s->get_fd = sensors_select_get_fd;
s->select_callback = select_func;
s->arg = arg;
s->fd = fd;
s->delay = 0;
if (pipe(s->ctl_fds) < 0)
ALOGE("%s: pipe failed: %s", __func__, strerror(errno));
sensors_worker_init(&s->worker, sensors_select_callback, s);
s->worker.set_delay(&s->worker, 0);
pthread_mutex_init(&s->fd_mutex, NULL);
}[/mw_shl_code]
bma150_init_read为该函数的第二个参数,即select_func, 组装给了s->select_callback。送去sensors_worker_init函数( DASH/sensors_worker.c ):
[mw_shl_code=java,true]void sensors_worker_init(struct sensors_worker_t* worker,
void* (*work_func)(void *arg), void* arg)
{
worker->mode = SENSOR_SLEEP;
worker->poll_callback = work_func;
worker->suspend = sensors_worker_suspend;
worker->resume = sensors_worker_resume;
worker->destroy = sensors_worker_destroy;
worker->set_delay = sensors_worker_set_delay;
worker->delay_ns = 200000000L;
worker->arg = arg;
pthread_mutex_init (&worker->mode_mutex, NULL);
pthread_cond_init (&worker->suspend_cond, NULL);
pthread_create(&worker->worker_thread_id, NULL,
sensors_worker_internal_worker, (void*) worker);
}[/mw_shl_code]
该函数第二个参数为sensors_select_init所送入的sensors_select_callback, 暂放此处,稍后分析,只记得他化身work_func组装给了worker->poll_callback, 最终被当作参数送入新开启的线程sensors_worker_internal_worker中:
[mw_shl_code=java,true]static void *sensors_worker_internal_worker(void *arg)
{
struct sensors_worker_t* worker = (struct sensors_worker_t*) arg;
enum sensors_worker_mode mode;
while (1) {
pthread_mutex_lock(&worker->mode_mutex);
mode = worker->mode;
pthread_mutex_unlock(&worker->mode_mutex);
switch (mode) {
case SENSOR_DESTROY:
goto exit;
case SENSOR_SLEEP:
pthread_mutex_lock(&worker->mode_mutex);
pthread_cond_wait(&worker->suspend_cond, &worker->mode_mutex);
pthread_mutex_unlock(&worker->mode_mutex);
break;
default:
worker->poll_callback(worker->arg);
break;
}
if (worker->delay_ns)
sensor_nano_sleep(worker->delay_ns);
}
exit:
return NULL;
}[/mw_shl_code]
这是一个工作线程,用来处理不同模式的不同动作,这些不同的模式由worker->mode来进行控制,同时worker->mode又由互斥锁worker->mode_mutex进行保护来防止读写冲突。此mode实际有三种:
SENSOR_SLEEP
SENSOR_RUNNING
SENSOR_DESTROY
分别对应三个工作函数:
sensors_worker_suspend
sensors_worker_resume
sensors_worker_destroy
这三个工作函数又在sensors_worker_init初始化时分别分配给了:
worker->suspend
worker->resume
worker->destroy
综上, sensors_worker_internal_worker中default即为SENSOR_RUNNING,其他状态暂不说明,先解决了这个RUNNING。在第一次初始化的时候默认给出的是SLEEP状态,则会等待suspend_cond变量,试看谁在使用这个变量。在sensors_worker.c中不难发现,在resume和destroy函数中,当前一状态为SLEEP时,会释放suspend_cond:
[mw_shl_code=java,true]static void sensors_worker_resume(struct sensors_worker_t* worker)
{
enum sensors_worker_mode prev_mode;
pthread_mutex_lock(&worker->mode_mutex);
prev_mode = worker->mode;
worker->mode = SENSOR_RUNNING;
if (prev_mode == SENSOR_SLEEP)
pthread_cond_broadcast(&worker->suspend_cond);
pthread_mutex_unlock(&worker->mode_mutex);
}
static void sensors_worker_destroy(struct sensors_worker_t* worker)
{
enum sensors_worker_mode prev_mode;
pthread_mutex_lock(&worker->mode_mutex);
prev_mode = worker->mode;
worker->mode = SENSOR_DESTROY;
if (prev_mode == SENSOR_SLEEP)
pthread_cond_broadcast(&worker->suspend_cond);
pthread_mutex_unlock(&worker->mode_mutex);
pthread_join(worker->worker_thread_id, NULL);
}[/mw_shl_code]
两者不同之处在于,resume会让传感器的状态切换到RUNNING,而destroy会使其切换至DESTROY状态,从而导致线程sensors_worker_internal_worker退出,传感器工作停止。问题又来了,初始化的状态是SLEEP,什么时候?谁?来激活这个工作线程呢?问题的答案在bma150_input.c ( DASH/bma150_input.c ):
[mw_shl_code=java,true]static int bma150_input_activate(struct sensor_api_t *s, int enable)
{
struct sensor_desc *d = container_of(s, struct sensor_desc, api);
int fd = d->select_worker.get_fd(&d->select_worker);
/* suspend/resume will be handled in kernel-space */
if (enable && (fd < 0)) {
fd = open_input_dev_by_name(BMA150_INPUT_NAME,
O_RDONLY | O_NONBLOCK);
if (fd < 0) {
ALOGE("%s: failed to open input dev %s\n", __func__,
BMA150_INPUT_NAME);
return -1;
}
d->select_worker.set_fd(&d->select_worker, fd);
d->select_worker.resume(&d->select_worker);
} else if (!enable && (fd > 0)) {
d->select_worker.set_fd(&d->select_worker, -1);
d->select_worker.suspend(&d->select_worker);
}
return 0;
}[/mw_shl_code]
前面只是一代而过activate函数,没有进行分析,回头来看,原来resume与suspend操作就在这里,当未初始化且要求开启时,寻找驱动句柄,并设置句柄,然后执行resume操作,从而使sensors_worker_internal_worker工作线程开启,执行worker->poll_callback函数。在回去之前还是把avtivate看完,除了上边说的开启的情况,就是关闭的情况。当驱动句柄有效,且要求关闭时,设置句柄为-1(无效),并执行suspend操作,使传感器进入SLEEP状态,继续等待suspend_cond变量。
在执行poll_callback时候一层层向回摸吧,worker->arg就等于sensors_worker_init所带入的arg。
worker->poll_back = (work_func);
(work_func) = sensors_select_callback;
( DASH/sensors_select.c )
[mw_shl_code=java,true]static void *sensors_select_callback(void *arg)
{
fd_set readfds;
int ret;
struct sensors_select_t *s = arg;
int maxfd;
LOCK(&s->fd_mutex);
maxfd = s->ctl_fds[0] > s->fd ? s->ctl_fds[0] : s->fd;
FD_ZERO(&readfds);
FD_SET(s->ctl_fds[0], &readfds);
FD_SET(s->fd, &readfds);
UNLOCK(&s->fd_mutex);
ret = select(maxfd + 1, &readfds, NULL, NULL, NULL);
if (ret < 0) {
ALOGE("%s: select failed!\n", __func__);
} else if (ret) {
if (FD_ISSET(s->ctl_fds[0], &readfds)) {
read(s->ctl_fds[0], &ret, sizeof(ret));
} else if (FD_ISSET(s->fd, &readfds)) {
LOCK(&wrapper_mutex);
LOCK(&s->fd_mutex);
if (s->fd >= 0)
s->select_callback(s->arg);
UNLOCK(&s->fd_mutex);
UNLOCK(&wrapper_mutex);
}
}
return NULL;
}[/mw_shl_code]
一层层的设置执行,最终执行到s->select_callback,参数为s->arg。
select_callback = (select_func);
(select_func) = bma150_input_read;
终于执行到了这一步,问题2解决。
总结: 一切的一切始于SensorService的threadLoop,他执行了一个poll操作,从而层层调用到SensorHAL,HAL经过初始化及激活后,开启了一个工作线程。当工作线程处于RUNNING(default)状态时,会无限循环来读取硬件驱动句柄所发出的数据,然后经过解析重构发回到SensorService中。至此,服务成功开启,从驱动中源源不断的获取数据。这个SensorService的threadLoop工作还有很多,大体概括就是对获取到的驱动数据进行分类,处理,最后发送……blablabla,这里边涉及到很多专业知识,也就不便再进行分析。总之SensorHAL的运作流程即使如此。
转帖呦