探秘SensorHAL

分析背景:

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"。

  1. /** 
  2.  * Handles must be higher than SENSORS_HANDLE_BASE and must be unique. 
  3.  * A Handle identifies a given sensors. The handle is used to activate 
  4.  * and/or deactivate sensors. 
  5.  * In this version of the API there can only be 256 handles. 
  6.  */  
  7. #define SENSORS_HANDLE_BASE             0  
  8. #define SENSORS_HANDLE_BITS             8  
  9. #define SENSORS_HANDLE_COUNT            (1<<SENSORS_HANDLE_BITS)  
  10. /* 8位能够支持256个handle */  
  11.   
  12. /** 
  13.  * Sensor types 
  14.  */  
  15. #define SENSOR_TYPE_ACCELEROMETER       1  //加速度传感器  
  16. #define SENSOR_TYPE_MAGNETIC_FIELD      2  //磁力传感器  
  17. #define SENSOR_TYPE_ORIENTATION         3  //方向传感器  
  18. #define SENSOR_TYPE_GYROSCOPE           4  //陀螺仪  
  19. #define SENSOR_TYPE_LIGHT               5  //亮度传感器  
  20. #define SENSOR_TYPE_PRESSURE            6  //压力传感器  
  21. #define SENSOR_TYPE_TEMPERATURE         7   // deprecated  温度传感器,以后的版本中将看不到任何身影  
  22. #define SENSOR_TYPE_PROXIMITY           8  //距离传感器  
  1. #define SENSOR_TYPE_GRAVITY             9  //重力传感器  
  2. #define SENSOR_TYPE_LINEAR_ACCELERATION 10  //速度传感器  
  3. #define SENSOR_TYPE_ROTATION_VECTOR     11  //旋转矢量传感器  
  4. #define SENSOR_TYPE_RELATIVE_HUMIDITY   12  //相对湿度传感器  
  5. #define SENSOR_TYPE_AMBIENT_TEMPERATURE 13  //环境温度传感器  

    支持的传感器还很多,但是 一般设备并不会用到这么多传感器,也就是加速度传感器、重力传感器、方向传感器、距离传感器、光线传感器这些,陀螺仪都很少见。
  1. /**  
  2.  * Definition of the axis  
  3.  * ----------------------  
  4.  *  
  5.  * This API is relative to the screen of the device in its default orientation,  
  6.  * that is, if the device can be used in portrait or landscape, this API  
  7.  * is only relative to the NATURAL orientation of the screen. In other words,  
  8.  * the axis are not swapped when the device's screen orientation changes.  
  9.  * Higher level services /may/ perform this transformation.  
  10.  *  
  11.  *   x<0         x>0  
  12.  *                ^  
  13.  *                |  
  14.  *    +-----------+-->  y>0  
  15.  *    |           |  
  16.  *    |           |  
  17.  *    |    设备    |  
  18.  *    |           |   / z<0  
  19.  *    |  面朝天空  |  /  
  20.  *    |           | /  
  21.  *    O-----------+/  
  22.  *    |[]  [ ]  []/  
  23.  *    +----------/+     y<0  
  24.  *              /  
  25.  *             /  
  26.  *           |/ z>0 (toward the sky)  
  27.  *  
  28.  *    O: Origin (x=0,y=0,z=0)  

还用有趣的符号图形形象的描述了“轴”的概念。然后就是一坨坨的传感器知识,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函数用来打开/关闭一个传感器。

  1. static inline int sensors_open(const struct hw_module_t* module,  
  2.         struct sensors_poll_device_t** device) {  
  3.     return module->methods->open(module,  
  4.             SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);  
  5. }  
  6.   
  7. static inline int sensors_close(struct sensors_poll_device_t* device) {  
  8.     return device->common.close(&device->common);  
  9. }  

2. 服务开启之路(1)

sensor服务由system_server开启:

frameworks/base/cmds/system_server/system_init.cpp

  1. extern "C" status_t system_init()  
  2. {  
  3.     ALOGI("Entered system_init()");  
  4.   
  5.     sp<ProcessState> proc(ProcessState::self());  
  6.   
  7.     sp<IServiceManager> sm = defaultServiceManager();  
  8.     ALOGI("ServiceManager: %p\n", sm.get());  
  9.   
  10.  ...  
  11.     }  
  12.   
  13.     property_get("system_init.startsensorservice", propBuf, "1");  
  14.     if (strcmp(propBuf, "1") == 0) {  
  15.         // Start the sensor service  
  16.         SensorService::instantiate();  
  17.     }  
  18. ...  
  19. }  
调用到frameworks/base/services/sensorservice/SensorService.cpp
  1. void SensorService::onFirstRef()  
  2. {  
  3.     ALOGD("nuSensorService starting...");  
  4.   
  5.     SensorDevice& dev(SensorDevice::getInstance());  
之后又调用到了SensorDevice.cpp(同目录下)
  1. SensorDevice::SensorDevice()  
  2.     :  mSensorDevice(0),  
  3.        mSensorModule(0)  
  4. {  
  5.     status_t err = hw_get_module(SENSORS_HARDWARE_MODULE_ID,  
  6.             (hw_module_t const**)&mSensorModule);  
  7.   
  8.     ALOGE_IF(err, "couldn't load %s module (%s)",  
  9.             SENSORS_HARDWARE_MODULE_ID, strerror(-err));  
  10.   
  11.     if (mSensorModule) {  
  12.         err = sensors_open(&mSensorModule->common, &mSensorDevice);  
  13.   
  14.         ALOGE_IF(err, "couldn't open device for module %s (%s)",  
  15.                 SENSORS_HARDWARE_MODULE_ID, strerror(-err));  
  16.   
  17.         if (mSensorDevice) {  
  18.             sensor_t const* list;  
  19.             ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);  
  20.   
  21.             mActivationCount.setCapacity(count);  
  22.             Info model;  
  23.             for (size_t i=0 ; i<size_t(count) ; i++) {  
  24.                 mActivationCount.add(list[i].handle, model);  
  25.                 mSensorDevice->activate(mSensorDevice, list[i].handle, 0);  
  26.             }  
  27.         }  
  28.     }  
  29. }  

这段负责打开HAL,取得需要的数据及handle,对应的部分在HAL的代码中,见DASH/sensors_module.c
  1. struct sensors_module_t HAL_MODULE_INFO_SYM = {  
  2.     common: {  
  3.         tag: HARDWARE_MODULE_TAG,  
  4.         version_major: 1,  
  5.         version_minor: 0,  
  6.         id: SENSORS_HARDWARE_MODULE_ID,  
  7.         name : "dash",  
  8.         author : "oskar.andero@sonymobile.com",  
  9.         methods: &sensors_module_methods,  
  10.     },  
  11.     get_sensors_list: sensors_list_get  
  12. };  

ID对上了,即可以成功打开,mSensorModule变得有效了。

然后SensorDevice.cpp调用API sensors_open,这个函数在接口头文件中有定义:

  1. static inline int sensors_open(const struct hw_module_t* module,  
  2.         struct sensors_poll_device_t** device) {  
  3.     return module->methods->open(module,  
  4.             SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);  
  5. }  

是开调用HAL的open方法:

  1. static int sensors_module_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device)  
  2. {  
  3.     struct sensors_poll_device_t *dev;  
  4.   
  5.   
  6.     if (strcmp(id, SENSORS_HARDWARE_POLL))  
  7.         return 0;  
  8.   
  9.   
  10.     dev = malloc(sizeof(*dev));  
  11.     if (!dev)  
  12.         return -1;  
  13.   
  14.   
  15.     memset(dev, 0, sizeof(*dev));  
  16.     dev->common.tag = HARDWARE_DEVICE_TAG;  
  17.     dev->common.version = 0;  
  18.     dev->common.module = (struct hw_module_t*)module;  
  19.     dev->common.close = sensors_module_close;  
  20.     dev->activate = sensors_module_activate;  
  21.     dev->setDelay = sensors_module_set_delay;  
  22.     dev->poll = sensors_module_poll;  
  23.   
  24.   
  25.     *device = (struct hw_device_t*) dev;  
  26.   
  27.   
  28.     sensors_config_read(NULL);  
  29.     sensors_fifo_init();  
  30.     sensors_list_foreach_api(sensors_init_iterator, NULL);  
  31.   
  32.   
  33.     return 0;  
  34. }  
  35.   
  36.   
  37. struct hw_module_methods_t sensors_module_methods = {  
  38.     open: sensors_module_open  
  39. };  

实际调用到了sensors_module_open,此函数返回0代表成功,-1代表打开失败,主要工作是组装device,最终将句柄交给mSensorDevice,即:
  1. mSensorDevice->common.tag = HARDWARE_DEVICE_TAG;  
  2. mSensorDevice->common.version = 0;  
  3. mSensorDevice->common.module = (struct hw_module_t*)module;  
  4. mSensorDevice->common.close = sensors_module_close;  
  5. mSensorDevice->activate = sensors_module_activate;  
  6. mSensorDevice->setDelay = sensors_module_set_delay;  
  7. mSensorDevice->poll = sensors_module_poll;  

之前在说明接口头文件时,说明了,对于传感器的数据操作有三个重要函数就是avtivate, setDelay, poll。记住这几个函数,稍后做分析。

在mSensorDevice成功被组装后,调用sensors_module_t自创的另一重要接口:get_sensors_list。瞧一瞧此函数在本实例中的具体实现(DASH/sensors_list.c):

  1. static struct sensor_t sensors[DASH_MAX_SENSORS];  
  2. static struct sensor_api_t* sensor_apis[DASH_MAX_SENSORS];  
  3. static int number_of_sensors = 0;  
  1. int sensors_list_get(struct sensors_module_t* module, struct sensor_t const** plist)  
  2. {  
  3.     *plist = sensors;  
  4.     return number_of_sensors;  
  5. }  

此函数完成两个工作,一将传感器列表赋给指针plist,二返回传感器数量。这里sensors列表和number_of_sensors是如何运作的:
  1. int sensors_list_register(struct sensor_t* sensor, struct sensor_api_t* api)  
  2. {  
  3.     if (!sensor || !api)  
  4.         return -1;  
  5.   
  6.   
  7.     if (number_of_sensors > DASH_MAX_SENSORS-1)  
  8.         return -1;  
  9.   
  10.   
  11.     sensor_apis[number_of_sensors] = api;  
  12.     /* We have to copy due to sensor API */  
  13.     memcpy(&sensors[number_of_sensors++], sensor, sizeof(*sensor));  
  14.   
  15.   
  16.     return 0;  
  17. }  

每个传感器都会调用sensors_list_register将自己注册进sensors列表中,并且会将自己的API也注册进sensors_apis列表中,来一个例子吧(DASH/sensors/bma150_input.c):
  1. struct sensor_desc {  
  2.     struct sensors_select_t select_worker;  
  3.     struct sensor_t sensor;  
  4.     struct sensor_api_t api;  
  5.   
  6.     int input_fd;  
  7.     float current_data[3];  
  8.   
  9.     char *rate_path;  
  10.   
  11.     /* config options */  
  12.     int axis_x;  
  13.     int axis_y;  
  14.     int axis_z;  
  15.   
  16.     int neg_x;  
  17.     int neg_y;  
  18.     int neg_z;  
  19.     int64_t  delay_requests[MAX_CLIENTS];  
  20. };  
  21.   
  22. static struct sensor_desc bma150_input = {  
  23.     .sensor = {  
  24.         name: "BMA150 accelerometer",  
  25.         vendor: "Bosch Sensortec GmbH",  
  26.         version: sizeof(sensors_event_t),  
  27.         handle: SENSOR_ACCELEROMETER_HANDLE,  
  28.         type: SENSOR_TYPE_ACCELEROMETER,  
  29.         maxRange: 9.81,  
  30.         resolution: 20,  
  31.         power: 0.13,  
  32.         minDelay: 5000  
  33.     },  
  34.     .api = {  
  35.         init: bma150_input_init,  
  36.         activate: bma150_input_activate,  
  37.         set_delay: bma150_input_fw_delay,  
  38.         close: bma150_input_close  
  39.     },  
  40.     .input_fd = -1,  
  41.     .axis_x = 0,  
  42.     .axis_y = 1,  
  43.     .axis_z = 2,  
  44.     .neg_x = 0,  
  45.     .neg_y = 0,  
  46.     .neg_z = 0  
  47. };  

以上是BMA150注册了属于自己的初始化、激活、延迟、关闭等操作。

每次注册完成后自会对number_of_sensors进行+1操作。这样所有的传感器注册完成后,就会形成两个列表和一个传感器总数。sensors_list_get也就理解了。

在获取到总数后,会根据总数进行循环遍历,挨个激活传感器。

  1. for (size_t i=0 ; i<size_t(count) ; i++) {  
  2.                 mActivationCount.add(list[i].handle, model);  
  3.                 mSensorDevice->activate(mSensorDevice, list[i].handle, 0);  
  4.             }  

OK,这下,引出了三大数据处理函数之一:activate。

sensors_module.c

  1. /* mSensorDevice->activate = sensors_module_activate; */  
  2. static int sensors_module_activate(struct sensors_poll_device_t *dev,  
  3.                    int handle, int enabled)  
  4. {  
  5.     struct sensor_api_t* api = sensors_list_get_api_from_handle(handle);  
  6.   
  7.   
  8.     if (!api) {  
  9.         ALOGE("%s: unable to find handle!", __func__);  
  10.                 return -1;  
  11.         }  
  12.   
  13.   
  14.     if (api->activate(api, enabled) < 0)  
  15.         return -1;  
  16.   
  17.   
  18.     return 0;  
  19. }  

sensors_list.c
  1. struct sensor_api_t* sensors_list_get_api_from_handle(int handle)  
  2. {  
  3.     int i;  
  4.     for (i = 0; i < number_of_sensors; i++)  
  5.         if (sensors[i].handle == handle)  
  6.             return sensor_apis[i];  
  7.     return NULL;  
  8. }  

比如BMA150的handle就是SENSOR_ACCELEROMETER_HANDLE,通过简单的匹配后,就能找到对应的sensors_api[x],然后执行active也就是bma150_input_activate函数,有兴趣就简单看一下代码,大体意思就是打开驱动获取句柄,然后组装给相关参数。


至此SensorDevice的大体工作也就完成了,总结就是成功获取HAL后,对每个传感器执行activate操作。


3.服务开启之路(2)

之所分(1)(2)是觉得SensorDevice部分可以单独成一部分,毕竟多数是在跟HAL在交互,这部分将分析完服务部分。

回头看SensorService::onFirstRef()

  1. void SensorService::onFirstRef()  
  2. {  
  3.     ALOGD("nuSensorService starting...");  
  4.   
  5.     SensorDevice& dev(SensorDevice::getInstance());  
  6.   
  7.     if (dev.initCheck() == NO_ERROR) {  
  8.   
  9. /********************************** 
  10. 检测SensorDevice执行是否成功,所获取的数据是否有效。 
  11. >status_t SensorDevice::initCheck() const { 
  12.     return mSensorDevice && mSensorModule ? NO_ERROR : NO_INIT; 
  13. } 
  14. **********************************/  
  15.         sensor_t const* list;  
  16.         ssize_t count = dev.getSensorList(&list);  
  17. /* 执行与(1)中sensors_list_get一样的工作 */  
  18.         if (count > 0) {  
  19.             ssize_t orientationIndex = -1;  
  20.             bool hasGyro = false;  
  21.             uint32_t virtualSensorsNeeds =  
  22.                     (1<<SENSOR_TYPE_GRAVITY) |  
  23.                     (1<<SENSOR_TYPE_LINEAR_ACCELERATION) |  
  24.                     (1<<SENSOR_TYPE_ROTATION_VECTOR);  
  25.   
  26.             mLastEventSeen.setCapacity(count);  
  27.             for (ssize_t i=0 ; i<count ; i++) {  
  28.                 registerSensor( new HardwareSensor(list[i]) );  
  29.                 switch (list[i].type) {  
  30.                     case SENSOR_TYPE_ORIENTATION:  
  31.                         orientationIndex = i;  
  32.                         break;  
  33.                     case SENSOR_TYPE_GYROSCOPE:  
  34.                         hasGyro = true;  
  35.                         break;  
  36.                     case SENSOR_TYPE_GRAVITY:  
  37.                     case SENSOR_TYPE_LINEAR_ACCELERATION:  
  38.                     case SENSOR_TYPE_ROTATION_VECTOR:  
  39.                         virtualSensorsNeeds &= ~(1<<list[i].type);  
  40.                         break;  
  41.                 }  
  42.             }  
  43. /* 遍历查看SENSOR HAL都支持哪些类型的传感器 */  
  44.   
  45.             // it's safe to instantiate the SensorFusion object here  
  46.             // (it wants to be instantiated after h/w sensors have been  
  47.             // registered)  
  48.             const SensorFusion& fusion(SensorFusion::getInstance());  
  49.   
  50.             if (hasGyro) {  
  51.                 // Always instantiate Android's virtual sensors. Since they are  
  52.                 // instantiated behind sensors from the HAL, they won't  
  53.                 // interfere with applications, unless they looks specifically  
  54.                 // for them (by name).  
  55.   
  56.                 registerVirtualSensor( new RotationVectorSensor() );  
  57.                 registerVirtualSensor( new GravitySensor(list, count) );  
  58.                 registerVirtualSensor( new LinearAccelerationSensor(list, count) );  
  59.   
  60.                 // these are optional  
  61.                 registerVirtualSensor( new OrientationSensor() );  
  62.                 registerVirtualSensor( new CorrectedGyroSensor(list, count) );  
  63.   
  64.                 // virtual debugging sensors...  
  65.                 char value[PROPERTY_VALUE_MAX];  
  66.                 property_get("debug.sensors", value, "0");  
  67.                 if (atoi(value)) {  
  68.                     registerVirtualSensor( new GyroDriftSensor() );  
  69.                 }  
  70.             } else if (orientationIndex != -1) {  
  71.                 // If we don't have a gyro but have a orientation sensor from  
  72.                 // elsewhere, we can compute rotation vector from that.  
  73.                 // (Google Maps expects rotation vector sensor to exist.)  
  74.   
  75.                 registerVirtualSensor( &RotationVectorSensor2::getInstance() );  
  76.             }  
  77.   
  78.             // build the sensor list returned to users  
  79.             mUserSensorList = mSensorList;  
  80.             if (hasGyro &&  
  81.                     (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR))) {  
  82.                 // if we have the fancy sensor fusion, and it's not provided by the  
  83.                 // HAL, use our own (fused) orientation sensor by removing the  
  84.                 // HAL supplied one form the user list.  
  85.                 if (orientationIndex >= 0) {  
  86.                     mUserSensorList.removeItemsAt(orientationIndex);  
  87.                 }  
  88.             }  
  89.   
  90.             run("SensorService", PRIORITY_URGENT_DISPLAY);  
  91.             mInitCheck = NO_ERROR;  
  92.         }  
  93.     }  
  94. }  

从上面可以看出,如果传感器中有SENSOR_TYPE_GYROSCOPE类型的话,也就是陀螺仪(高端传感器),会定义hasGyro,从而注册多个虚拟传感器,blablabla……

最后会触发一个重要动作:run。

回头查看SensorService类的定义:

  1. class SensorService :  
  2.         public BinderService<SensorService>,  
  3.         public BnSensorServer,  
  4.         protected Thread  

发现SensorService是继承了Thread的。

那么run的工作实际是启动了线程,threadLoop:

  1. bool SensorService::threadLoop()  
  2. {  
  3.     ALOGD("nuSensorService thread starting...");  
  4.   
  5.     const size_t numEventMax = 16;  
  6.     const size_t minBufferSize = numEventMax + numEventMax * mVirtualSensorList.size();  
  7.     sensors_event_t buffer[minBufferSize];  
  8.     sensors_event_t scratch[minBufferSize];  
  9.     SensorDevice& device(SensorDevice::getInstance());  
  10.     const size_t vcount = mVirtualSensorList.size();  
  11.   
  12.     ssize_t count;  
  13.     do {  
  14.         count = device.poll(buffer, numEventMax);  
  15.         if (count<0) {  
  16.             ALOGE("sensor poll failed (%s)", strerror(-count));  
  17.             break;  
  18.         }  
  19.   
  20. ...  
  21. }  

发现这个线程会一直执行poll操作,这个操作是什么呢?还记得“服务开启之路(1)”中提到的吗?
  1. mSensorDevice->poll = sensors_module_poll;  

是在HAL中的函数,最终指向sensors_module_poll ( DASH/sensors_module.c )

  1. static int sensors_module_poll(struct sensors_poll_device_t *dev,  
  2.                    sensors_event_t* data, int count)  
  3. {  
  4.     int ret;  
  5.   
  6.     while ((ret = sensors_fifo_get_all(data, count)) == 0)  
  7.         ;  
  8.   
  9.     return ret;  
  10. }  

( DASH/sensors_fifo.c )

  1. void sensors_fifo_put(sensors_event_t *data)  
  2. {  
  3.     pthread_mutex_lock(&sensors_fifo.mutex);  
  4.   
  5.     if (sensors_fifo.fifo_i < FIFO_LEN)  
  6.         sensors_fifo.fifo[sensors_fifo.fifo_i++] = *data;  
  7.   
  8.     pthread_cond_broadcast(&sensors_fifo.data_cond);  
  9.     pthread_mutex_unlock(&sensors_fifo.mutex);  
  10. }  
  11.   
  12. int sensors_fifo_get_all(sensors_event_t *data, int len)  
  13. {  
  14.     int i;  
  15.   
  16.     /* This function deliberately drops all packets above len. */  
  17.     pthread_mutex_lock(&sensors_fifo.mutex);  
  18.     pthread_cond_wait(&sensors_fifo.data_cond, &sensors_fifo.mutex);  
  19.   
  20.     for (i = 0; (i < sensors_fifo.fifo_i) && (i < len); i++)  
  21.         data[i] = sensors_fifo.fifo[i];  
  22.     sensors_fifo.fifo_i = 0;  
  23.     pthread_mutex_unlock(&sensors_fifo.mutex);  
  24.   
  25.     return i;  
  26. }  

上边的函数用到了线程等待,有兴趣的可以去百度,很好理解,就是两个线程等待一个变量data_cond,sensors_fifo_put在放置完data后会释放掉data_cond,而sensors_fifo_get_all在data_cond释放之前会一直进行等待。

继续向前跟踪sensors_fifo_put ( DASH/sensors/bma150_input.c ):

  1. static void *bma150_input_read(void *arg)  
  2. {  
  3.     struct sensor_api_t *s = arg;  
  4.     struct sensor_desc *d = container_of(s, struct sensor_desc, api);  
  5.     struct input_event event;  
  6.     int fd = d->select_worker.get_fd(&d->select_worker);  
  7.     sensors_event_t data;  
  8.   
  9.     memset(&data, 0, sizeof(data));  
  10.     while (read(fd, &event, sizeof(event)) > 0) {  
  11.         switch (event.type) {  
  12.         case EV_ABS:  
  13.             switch (event.code) {  
  14.             case ABS_X:  
  15.                 d->current_data[0] = ev2grav(event.value);  
  16.                 break;  
  17.   
  18.             case ABS_Y:  
  19.                 d->current_data[1] = ev2grav(event.value);  
  20.                 break;  
  21.   
  22.             case ABS_Z:  
  23.                 d->current_data[2] = ev2grav(event.value);  
  24.                 break;  
  25.   
  26.             case ABS_MISC:  
  27.             default:  
  28.                 break;  
  29.             }  
  30.             break;  
  31.   
  32.         case EV_SYN:  
  33.   
  34.             data.acceleration.x = (d->neg_x ? -d->current_data[d->axis_x] :  
  35.                                d->current_data[d->axis_x]);  
  36.             data.acceleration.y = (d->neg_y ? -d->current_data[d->axis_y] :  
  37.                                d->current_data[d->axis_y]);  
  38.             data.acceleration.z = (d->neg_z ? -d->current_data[d->axis_z] :  
  39.                                d->current_data[d->axis_z]);  
  40.             data.acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;  
  41.   
  42.             data.sensor = bma150_input.sensor.handle;  
  43.             data.type = bma150_input.sensor.type;  
  44.             data.version = bma150_input.sensor.version;  
  45.             data.timestamp = get_current_nano_time();  
  46.   
  47.             sensors_fifo_put(&data);  
  48.   
  49.             goto exit;  
  50.   
  51.         default:  
  52.             goto exit;  
  53.         }  
  54.     }  
  55.   
  56. exit:  
  57.     return NULL;  
  58. }  

上述函数很好理解,首先取得此传感器的内核驱动句柄,然后等待此句柄输出信息,当取得信息后,对信息进行解析与再封装,最终写入到data中。那么bma150_input_read又是谁来调用呢?答案在此传感器的初始化过程中:
  1. static int bma150_input_init(struct sensor_api_t *s)  
  2. {  
  3.     struct sensor_desc *d = container_of(s, struct sensor_desc, api);  
  4.     int fd;  
  5.     bma150_input_read_config(d);  
  6.   
  7.     /* check for availablity */  
  8.     fd = open_input_dev_by_name(BMA150_INPUT_NAME, O_RDONLY | O_NONBLOCK);  
  9.     if (fd < 0) {  
  10.         ALOGE("%s: unable to find %s input device!\n", __func__,  
  11.             BMA150_INPUT_NAME);  
  12.         return -1;  
  13.     }  
  14.     d->rate_path = bma150_get_rate_path(fd);  
  15.     close(fd);  
  16.   
  17.     sensors_select_init(&d->select_worker, bma150_input_read, s, -1);  
  18.     return 0;  
  19. }  
可能现在会有迷惑,这个bma150_input_init是什么时候启动的呢?这是问题1,问题2是sensors_select_init是怎么吧bma150_input_read启动起来的?


下面一次解决,问题1:

  1. static struct sensor_desc bma150_input = {  
  2. ...  
  3.     .api = {  
  4.         init: bma150_input_init,  
  5.         activate: bma150_input_activate,  
  6.         set_delay: bma150_input_fw_delay,  
  7.         close: bma150_input_close  
  8.     },  
  9. ...  
  10. };  
bma150_input_init被注册到api->init.

( DASH/sensors_module.c )

  1. static int sensors_module_open(const struct hw_module_t* module, const char* id, struct hw_device_t** device)  
  2. {  
  3.     ...  
  4.     sensors_list_foreach_api(sensors_init_iterator, NULL);  
  5.   
  6.     return 0;  
  7. }  
  8.   
  9. static int sensors_init_iterator(struct sensor_api_t* api, void *arg)  
  10. {  
  11.     return api->init(api);  
  12. }  

( DASH/sensors_list.c )
  1. void sensors_list_foreach_api(int (*f)(struct sensor_api_t* api, void* arg),  
  2.                   void *arg)  
  3. {  
  4.     int i;  
  5.     for (i = 0; i < number_of_sensors; i++)  
  6.         if (f(sensor_apis[i], arg) != SENSOR_OK) {  
  7.             sensors_list_deregister(sensor_apis[i]);  
  8.             /* need to revisit this position after deregister */  
  9.             --i;  
  10.         }  
  11. }  
遍历所有注册过的传感器,执行其api->init. 问题1解决完毕。


问题2:

( DASH/sensors_select.c )

  1. void sensors_select_init(struct sensors_select_t* s,  
  2.             void* (*select_func)(void *arg), void* arg, int fd)  
  3. {  
  4.     s->suspend = sensors_select_suspend;  
  5.     s->resume = sensors_select_resume;  
  6.     s->destroy = sensors_select_destroy;  
  7.     s->set_delay = sensors_select_set_delay;  
  8.     s->set_fd = sensors_select_set_fd;  
  9.     s->get_fd = sensors_select_get_fd;  
  10.     s->select_callback = select_func;  
  11.     s->arg = arg;  
  12.     s->fd = fd;  
  13.     s->delay = 0;  
  14.   
  15.         if (pipe(s->ctl_fds) < 0)  
  16.         ALOGE("%s: pipe failed: %s", __func__, strerror(errno));  
  17.   
  18.     sensors_worker_init(&s->worker, sensors_select_callback, s);  
  19.     s->worker.set_delay(&s->worker, 0);  
  20.     pthread_mutex_init(&s->fd_mutex, NULL);  
  21. }  

bma150_init_read为该函数的第二个参数,即select_func, 组装给了s->select_callback。送去sensors_worker_init函数( DASH/sensors_worker.c ):
  1. void sensors_worker_init(struct sensors_worker_t* worker,  
  2.             void* (*work_func)(void *arg), void* arg)  
  3. {  
  4.     worker->mode = SENSOR_SLEEP;  
  5.   
  6.     worker->poll_callback = work_func;  
  7.     worker->suspend = sensors_worker_suspend;  
  8.     worker->resume = sensors_worker_resume;  
  9.     worker->destroy = sensors_worker_destroy;  
  10.     worker->set_delay = sensors_worker_set_delay;  
  11.     worker->delay_ns = 200000000L;  
  12.     worker->arg = arg;  
  13.   
  14.     pthread_mutex_init (&worker->mode_mutex, NULL);  
  15.     pthread_cond_init (&worker->suspend_cond, NULL);  
  16.     pthread_create(&worker->worker_thread_id, NULL,  
  17.                sensors_worker_internal_worker, (void*) worker);  
  18. }  

该函数第二个参数为sensors_select_init所送入的sensors_select_callback, 暂放此处,稍后分析,只记得他化身work_func组装给了worker->poll_callback, 最终被当作参数送入新开启的线程sensors_worker_internal_worker中:
  1. static void *sensors_worker_internal_worker(void *arg)  
  2. {  
  3.     struct sensors_worker_t* worker = (struct sensors_worker_t*) arg;  
  4.     enum sensors_worker_mode mode;  
  5.   
  6.     while (1) {  
  7.         pthread_mutex_lock(&worker->mode_mutex);  
  8.         mode = worker->mode;  
  9.         pthread_mutex_unlock(&worker->mode_mutex);  
  10.   
  11.         switch (mode) {  
  12.         case SENSOR_DESTROY:  
  13.             goto exit;  
  14.   
  15.         case SENSOR_SLEEP:  
  16.             pthread_mutex_lock(&worker->mode_mutex);  
  17.             pthread_cond_wait(&worker->suspend_cond, &worker->mode_mutex);  
  18.             pthread_mutex_unlock(&worker->mode_mutex);  
  19.             break;  
  20.   
  21.         default:  
  22.             worker->poll_callback(worker->arg);  
  23.             break;  
  24.         }  
  25.         if (worker->delay_ns)  
  26.             sensor_nano_sleep(worker->delay_ns);  
  27.     }  
  28. exit:  
  29.     return NULL;  
  30. }  

这是一个工作线程,用来处理不同模式的不同动作,这些不同的模式由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:

  1. static void sensors_worker_resume(struct sensors_worker_t* worker)  
  2. {  
  3.     enum sensors_worker_mode prev_mode;  
  4.   
  5.     pthread_mutex_lock(&worker->mode_mutex);  
  6.     prev_mode = worker->mode;  
  7.     worker->mode = SENSOR_RUNNING;  
  8.   
  9.     if (prev_mode == SENSOR_SLEEP)  
  10.         pthread_cond_broadcast(&worker->suspend_cond);  
  11.   
  12.     pthread_mutex_unlock(&worker->mode_mutex);  
  13. }  
  14.   
  15. static void sensors_worker_destroy(struct sensors_worker_t* worker)  
  16. {  
  17.     enum sensors_worker_mode prev_mode;  
  18.   
  19.     pthread_mutex_lock(&worker->mode_mutex);  
  20.     prev_mode = worker->mode;  
  21.     worker->mode = SENSOR_DESTROY;  
  22.   
  23.     if (prev_mode == SENSOR_SLEEP)  
  24.         pthread_cond_broadcast(&worker->suspend_cond);  
  25.   
  26.     pthread_mutex_unlock(&worker->mode_mutex);  
  27.     pthread_join(worker->worker_thread_id, NULL);  
  28. }  

两者不同之处在于,resume会让传感器的状态切换到RUNNING,而destroy会使其切换至DESTROY状态,从而导致线程sensors_worker_internal_worker退出,传感器工作停止。问题又来了,初始化的状态是SLEEP,什么时候?谁?来激活这个工作线程呢?问题的答案在bma150_input.c ( DASH/bma150_input.c ):
  1. static int bma150_input_activate(struct sensor_api_t *s, int enable)  
  2. {  
  3.     struct sensor_desc *d = container_of(s, struct sensor_desc, api);  
  4.     int fd = d->select_worker.get_fd(&d->select_worker);  
  5.   
  6.     /* suspend/resume will be handled in kernel-space */  
  7.     if (enable && (fd < 0)) {  
  8.         fd = open_input_dev_by_name(BMA150_INPUT_NAME,  
  9.             O_RDONLY | O_NONBLOCK);  
  10.         if (fd < 0) {  
  11.             ALOGE("%s: failed to open input dev %s\n", __func__,  
  12.                 BMA150_INPUT_NAME);  
  13.             return -1;  
  14.         }  
  15.         d->select_worker.set_fd(&d->select_worker, fd);  
  16.         d->select_worker.resume(&d->select_worker);  
  17.     } else if (!enable && (fd > 0)) {  
  18.         d->select_worker.set_fd(&d->select_worker, -1);  
  19.         d->select_worker.suspend(&d->select_worker);  
  20.     }  
  21.   
  22.     return 0;  
  23. }  

前面只是一代而过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 )

  1. static void *sensors_select_callback(void *arg)  
  2. {  
  3.     fd_set readfds;  
  4.     int ret;  
  5.     struct sensors_select_t *s = arg;  
  6.     int maxfd;  
  7.   
  8.     LOCK(&s->fd_mutex);  
  9.     maxfd = s->ctl_fds[0] > s->fd ? s->ctl_fds[0] : s->fd;  
  10.     FD_ZERO(&readfds);  
  11.     FD_SET(s->ctl_fds[0], &readfds);  
  12.     FD_SET(s->fd, &readfds);  
  13.     UNLOCK(&s->fd_mutex);  
  14.     ret = select(maxfd + 1, &readfds, NULL, NULL, NULL);  
  15.   
  16.     if (ret < 0) {  
  17.         ALOGE("%s: select failed!\n", __func__);  
  18.     } else if (ret) {  
  19.         if (FD_ISSET(s->ctl_fds[0], &readfds)) {  
  20.             read(s->ctl_fds[0], &ret, sizeof(ret));  
  21.         } else if (FD_ISSET(s->fd, &readfds)) {  
  22.             LOCK(&wrapper_mutex);  
  23.             LOCK(&s->fd_mutex);  
  24.             if (s->fd >= 0)  
  25.                 s->select_callback(s->arg);  
  26.             UNLOCK(&s->fd_mutex);  
  27.             UNLOCK(&wrapper_mutex);  
  28.         }  
  29.     }  
  30.     return NULL;  
  31. }  

一层层的设置执行,最终执行到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的运作流程即使如此。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值