打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
探秘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"。
[cpp]  
/** 
 * 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  //距离传感器  
[cpp]  
#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  //环境温度传感器  
    支持的传感器还很多,但是 一般设备并不会用到这么多传感器,也就是加速度传感器、重力传感器、方向传感器、距离传感器、光线传感器这些,陀螺仪都很少见。
[cpp]  
/**  
 * 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)  
还用有趣的符号图形形象的描述了“轴”的概念。然后就是一坨坨的传感器知识,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函数用来打开/关闭一个传感器。
[cpp] 
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);  
}  
2. 服务开启之路(1)
sensor服务由system_server开启:
frameworks/base/cmds/system_server/system_init.cpp
[cpp]  
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();  
    }  
...  
}  
调用到frameworks/base/services/sensorservice/SensorService.cpp
[cpp]  
void SensorService::onFirstRef()  
{  
    ALOGD("nuSensorService starting...");  
    SensorDevice& dev(SensorDevice::getInstance());  
之后又调用到了SensorDevice.cpp(同目录下)
[cpp]  
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[i].handle, model);  
                mSensorDevice->activate(mSensorDevice, list[i].handle, 0);  
            }  
        }  
    }  
}  
这段负责打开HAL,取得需要的数据及handle,对应的部分在HAL的代码中,见DASH/sensors_module.c
[cpp] 
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  
};  
ID对上了,即可以成功打开,mSensorModule变得有效了。
然后SensorDevice.cpp调用API sensors_open,这个函数在接口头文件中有定义:
[cpp]  
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);  
}  
是开调用HAL的open方法:
[cpp] 
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  
};  
实际调用到了sensors_module_open,此函数返回0代表成功,-1代表打开失败,主要工作是组装device,最终将句柄交给mSensorDevice,即:
[cpp]  
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;  
之前在说明接口头文件时,说明了,对于传感器的数据操作有三个重要函数就是avtivate, setDelay, poll。记住这几个函数,稍后做分析。
在mSensorDevice成功被组装后,调用sensors_module_t自创的另一重要接口:get_sensors_list。瞧一瞧此函数在本实例中的具体实现(DASH/sensors_list.c):
[cpp]  
static struct sensor_t sensors[DASH_MAX_SENSORS];  
static struct sensor_api_t* sensor_apis[DASH_MAX_SENSORS];  
static int number_of_sensors = 0;  
[cpp] view plaincopyprint?
int sensors_list_get(struct sensors_module_t* module, struct sensor_t const** plist)  
{  
    *plist = sensors;  
    return number_of_sensors;  
}  
此函数完成两个工作,一将传感器列表赋给指针plist,二返回传感器数量。这里sensors列表和number_of_sensors是如何运作的:
[cpp]  
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;  
}  
每个传感器都会调用sensors_list_register将自己注册进sensors列表中,并且会将自己的API也注册进sensors_apis列表中,来一个例子吧(DASH/sensors/bma150_input.c):
[cpp]  
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  
};  
以上是BMA150注册了属于自己的初始化、激活、延迟、关闭等操作。
每次注册完成后自会对number_of_sensors进行+1操作。这样所有的传感器注册完成后,就会形成两个列表和一个传感器总数。sensors_list_get也就理解了。
在获取到总数后,会根据总数进行循环遍历,挨个激活传感器。
[cpp] 
for (size_t i=0 ; i<size_t(count) ; i++) {  
                mActivationCount.add(list[i].handle, model);  
                mSensorDevice->activate(mSensorDevice, list[i].handle, 0);  
            }  
OK,这下,引出了三大数据处理函数之一:activate。
sensors_module.c
[cpp]  
/* 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;  
}  
sensors_list.c
[cpp]  
struct sensor_api_t* sensors_list_get_api_from_handle(int handle)  
{  
    int i;  
    for (i = 0; i < number_of_sensors; i++)  
        if (sensors[i].handle == handle)  
            return sensor_apis[i];  
    return NULL;  
}  
比如BMA150的handle就是SENSOR_ACCELEROMETER_HANDLE,通过简单的匹配后,就能找到对应的sensors_api[x],然后执行active也就是bma150_input_activate函数,有兴趣就简单看一下代码,大体意思就是打开驱动获取句柄,然后组装给相关参数。
至此SensorDevice的大体工作也就完成了,总结就是成功获取HAL后,对每个传感器执行activate操作。
3.服务开启之路(2)
之所分(1)(2)是觉得SensorDevice部分可以单独成一部分,毕竟多数是在跟HAL在交互,这部分将分析完服务部分。
回头看SensorService::onFirstRef()
[cpp]  
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[i]) );  
                switch (list[i].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[i].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;  
        }  
    }  
}  
从上面可以看出,如果传感器中有SENSOR_TYPE_GYROSCOPE类型的话,也就是陀螺仪(高端传感器),会定义hasGyro,从而注册多个虚拟传感器,blablabla……
最后会触发一个重要动作:run。
回头查看SensorService类的定义:
[cpp]  
class SensorService :  
        public BinderService<SensorService>,  
        public BnSensorServer,  
        protected Thread  
发现SensorService是继承了Thread的。
那么run的工作实际是启动了线程,threadLoop:
[cpp]  
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;  
        }  
...  
}  
发现这个线程会一直执行poll操作,这个操作是什么呢?还记得“服务开启之路(1)”中提到的吗?
[cpp]  
mSensorDevice->poll = sensors_module_poll;  
是在HAL中的函数,最终指向sensors_module_poll ( DASH/sensors_module.c )
[cpp] 
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;  
}  
( DASH/sensors_fifo.c )
[cpp] 
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[i] = sensors_fifo.fifo[i];  
    sensors_fifo.fifo_i = 0;  
    pthread_mutex_unlock(&sensors_fifo.mutex);  
    return i;  
}  
上边的函数用到了线程等待,有兴趣的可以去百度,很好理解,就是两个线程等待一个变量data_cond,sensors_fifo_put在放置完data后会释放掉data_cond,而sensors_fifo_get_all在data_cond释放之前会一直进行等待。
继续向前跟踪sensors_fifo_put ( DASH/sensors/bma150_input.c ):
[cpp]  
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;  
}  
上述函数很好理解,首先取得此传感器的内核驱动句柄,然后等待此句柄输出信息,当取得信息后,对信息进行解析与再封装,最终写入到data中。那么bma150_input_read又是谁来调用呢?答案在此传感器的初始化过程中:
[cpp]  
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;  
}  
可能现在会有迷惑,这个bma150_input_init是什么时候启动的呢?这是问题1,问题2是sensors_select_init是怎么吧bma150_input_read启动起来的?
下面一次解决,问题1:
[cpp]  
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  
    },  
...  
};  
bma150_input_init被注册到api->init.
( DASH/sensors_module.c )
[cpp]  
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);  
}  
( DASH/sensors_list.c )
[cpp] 
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[i], arg) != SENSOR_OK) {  
            sensors_list_deregister(sensor_apis[i]);  
            /* need to revisit this position after deregister */  
            --i;  
        }  
}  
遍历所有注册过的传感器,执行其api->init. 问题1解决完毕。
问题2:
( DASH/sensors_select.c )
[cpp] 
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);  
}  
bma150_init_read为该函数的第二个参数,即select_func, 组装给了s->select_callback。送去sensors_worker_init函数( DASH/sensors_worker.c ):
[cpp]  
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);  
}  
该函数第二个参数为sensors_select_init所送入的sensors_select_callback, 暂放此处,稍后分析,只记得他化身work_func组装给了worker->poll_callback, 最终被当作参数送入新开启的线程sensors_worker_internal_worker中:
[cpp]  
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;  
}  
这是一个工作线程,用来处理不同模式的不同动作,这些不同的模式由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:
[cpp]  
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);  
}  
两者不同之处在于,resume会让传感器的状态切换到RUNNING,而destroy会使其切换至DESTROY状态,从而导致线程sensors_worker_internal_worker退出,传感器工作停止。问题又来了,初始化的状态是SLEEP,什么时候?谁?来激活这个工作线程呢?问题的答案在bma150_input.c ( DASH/bma150_input.c ):
[cpp]  
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;  
}  
前面只是一代而过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 )
[cpp]  
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;  
}  
一层层的设置执行,最终执行到s->select_callback,参数为s->arg。
select_callback = (select_func);www.2cto.com
(select_func) = bma150_input_read;
终于执行到了这一步,问题2解决。
总结: 一切的一切始于SensorService的threadLoop,他执行了一个poll操作,从而层层调用到SensorHAL,HAL经过初始化及激活后,开启了一个工作线程。当工作线程处于RUNNING(default)状态时,会无限循环来读取硬件驱动句柄所发出的数据,然后经过解析重构发回到SensorService中。至此,服务成功开启,从驱动中源源不断的获取数据。这个SensorService的threadLoop工作还有很多,大体概括就是对获取到的驱动数据进行分类,处理,最后发送……blablabla,这里边涉及到很多专业知识,也就不便再进行分析。总之SensorHAL的运作流程即使如此。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Android 传感器 HAL 头文件 sensors.h 详细注释
重力感应器BMA250源代码执行分析
生产者和消费者
linux内核数据结构之kfifo
C语言环形缓冲fifo实现
HAL硬件抽象层的实现及架构、Android API 与硬件平台的衔接、NDK的一些看法
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服