Android 傳感器hal層分析

Android系統內置對傳感器有很多,它們分別是:加速度傳感器gsensor(accelerometer)、磁力傳感器(magnetic field)、方向傳感器(orientation)、陀螺儀(gyroscope)、環境光照傳感器(light)、壓力傳感器(pressure)、溫度傳感器(temperature)和距離傳感器(proximity)等。

Android實現傳感器系統代碼位置在

  framework層: frameworks\base\core\java\android\hardware\目錄下

    Sensor.java

    SensorEventListener.java 

    SensorListener.java

    SensorManager.java

jni :frameworks\base\core\jni

                         android_hardware_SensorManager.cpp

hal層,這個每個平臺的代碼位置可能不一樣,我現在分析4.4MTK的

       mediatek\hardware\sensor

Google爲Sensor提供了統一的HAL接口,不同的硬件廠商需要根據該接口來實現並完成具體的硬件抽象層,Android中Sensor的HAL接口定義在:hardware/libhardware/include/hardware/sensors.h

對傳感器類型的定義:


傳感器模塊的定義結構體如下:


該接口的定義實際上是對標準的硬件模塊hw_module_t的一個擴展,增加了一個get_sensors_list函數,用於獲取傳感器的列表。


對任意一個sensor設備 都會有一個 sensor_t 結構體,其定義如下:


struct sensor_t {
    /* name of this sensors */
    const char*     name;
    /* vendor of the hardware part */
    const char*     vendor;
    /* version of the hardware part + driver. The value of this field
     * must increase when the driver is updated in a way that changes the
     * output of this sensor. This is important for fused sensors when the
     * fusion algorithm is updated.
     */    
    int             version;
    /* handle that identifies this sensors. This handle is used to activate
     * and deactivate this sensor. The value of the handle must be 8 bits
     * in this version of the API. 
     */
    int             handle;
    /* this sensor's type. */
    int             type;
    /* maximaum range of this sensor's value in SI units */
    float           maxRange;
    /* smallest difference between two values reported by this sensor */
    float           resolution;
    /* rough estimate of this sensor's power consumption in mA */
    float           power;
    /* minimum delay allowed between events in microseconds. A value of zero
     * means that this sensor doesn't report events at a constant rate, but
     * rather only when a new data is available */
    int32_t         minDelay;

    /* reserved fields, must be zero */
    void*           reserved[8];
};

下面來分析hal流程:

 加載JNI時根據模塊會找到sensor.c

 

由上面可以看出來open_sensors是整個加載流程入口


函數操作集合賦值,看到new了一個sensors_poll_context_t類,看看到底這裏都做了什麼

struct sensors_poll_context_t {
    struct sensors_poll_device_t device; // must be first
        sensors_poll_context_t();
        ~sensors_poll_context_t();
    int activate(int handle, int enabled);
    int setDelay(int handle, int64_t ns);
    int pollEvents(sensors_event_t* data, int count);
private:
    enum {
        hwmsen        = 0, 
        accel,
        magnetic,
        //gyro,
        //light,
        //proximity,
        //pressure,
        numSensorDrivers,
        numFds,
    };
int handleToDriver(int handle) const {
        switch (handle) {
            case ID_ACCELEROMETER:
return accel;
            case ID_MAGNETIC:
            case ID_ORIENTATION:
return magnetic;
            case ID_PROXIMITY:
//return proximity;
            case ID_LIGHT:
//return light;
            case ID_GYROSCOPE:
//return gyro;
case ID_PRESSURE:
break;
//return pressure;
        }
        return -EINVAL;
    }


    static const size_t wake = numFds - 1;
    static const char WAKE_MESSAGE = 'W';
    struct pollfd mPollFds[numFds];
    int mWritePipeFd;
    SensorBase* mSensors[numSensorDrivers];
};

構造函數


重點來看pollEvents函數


poll是真正實現查詢事件

int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
{
    int nbEvents = 0;
    int n = 0;
//ALOGE("pollEvents count =%d",count );


    do {
        // see if we have some leftover from the last poll()
        for (int i=0 ; count && i<numSensorDrivers ; i++) {
            SensorBase* const sensor(mSensors[i]);
            if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {
                int nb = sensor->readEvents(data, count);
                if (nb < count) {
                    // no more data for this sensor
                    mPollFds[i].revents = 0;
                }
                //if(nb < 0||nb > count)
                // ALOGE("pollEvents count error nb:%d, count:%d, nbEvents:%d", nb, count, nbEvents);//for sensor NE debug
                count -= nb;
                nbEvents += nb;
                data += nb;
                //if(nb < 0||nb > count)
                // ALOGE("pollEvents count error nb:%d, count:%d, nbEvents:%d", nb, count, nbEvents);//for sensor NE debug
            }
        }
        if (count) {
            // we still have some room, so try to see if we can get
            // some events immediately or just wait if we don't have
            // anything to return
            
            n = poll(mPollFds, numFds, nbEvents ? 0 : -1);
            if (n<0) {
                ALOGE("poll() failed (%s)", strerror(errno));
                return -errno;
            }
            if (mPollFds[wake].revents & POLLIN) {
                char msg;
                int result = read(mPollFds[wake].fd, &msg, 1);
                ALOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));
                ALOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
                mPollFds[wake].revents = 0;
            }
        }
        // if we have events and space, go read them
    } while (n && count);
    return nbEvents;
}





發佈了15 篇原創文章 · 獲贊 5 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章