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;
}