一.其主要框架如下圖所示:


二.sensor的JNI層:android_hardware_SensorManager.cpp (frameworks\base\core\jni)
注冊JNI:
register_android_hardware_SensorManager
jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager", gSystemSensorManagerMethods, NELEM(gSystemSensorManagerMethods));
jniRegisterNativeMethods(env, "android/hardware/SystemSensorManager$BaseEventQueue", gBaseEventQueueMethods, NELEM(gBaseEventQueueMethods));
static JNINativeMethod gSystemSensorManagerMethods[] = {
(void*)nativeClassInit },
nativeClassInit :這函數的作用
jclass sensorClass = _env->FindClass("android/hardware/Sensor"); //得到Sensor.java (frameworks\base\core\java\android\hardware)的class引用
sensorOffsets.name = _env->GetFieldID(sensorClass, "mName", "Ljava/lang/String;"); //得到sensor的的引用值,這里應該是可以直接把數據傳遞到framework
sensorOffsets.vendor = _env->GetFieldID(sensorClass, "mVendor", "Ljava/lang/String;");
sensorOffsets.version = _env->GetFieldID(sensorClass, "mVersion", "I");
(void*)nativeGetNextSensor },
size_t count = mgr.getSensorList(&sensorList); //得到sensor列表,返回sensor個數
*list = mSensorList; //在SensorManager.cpp (frameworks\native\libs\gui)中
return mSensors.size();
env->SetObjectField(sensor, sensorOffsets.name, name); //獲得sensor的信息,就是nativeClassInit 中需要得到的
env->SetObjectField(sensor, sensorOffsets.vendor, vendor);
};
static JNINativeMethod gBaseEventQueueMethods[] = {
(void*)nativeInitSensorEventQueue },
sp<SensorEventQueue> queue(mgr.createEventQueue());
queue = new SensorEventQueue(connection); //構造
SensorEventQueue
mRecBuffer = new ASensorEvent[MAX_RECEIVE_BUFFER_EVENT_COUNT]; //生成一些
ASensorEvent,用了記錄sensor的信息
android_os_MessageQueue_getMessageQueue //得到
_MessageQueue
(void*)nativeEnableSensor },
receiver->getSensorEventQueue()->enableSensor(handle, rate_us, maxBatchReportLatency,
reservedFlags); //enable sensor
enableSensor //在
SensorEventQueue.cpp (frameworks\native\libs\gui)中
mSensorEventConnection->enableDisable(handle, true, us2ns(samplingPeriodUs),
us2ns(maxBatchReportLatencyUs), reservedFlags);
(void*)nativeDisableSensor }, //關閉sensor
(void*)nativeDestroySensorEventQueue },
(void*)nativeFlushSensor },
};
實現SensorManager.java中的native函數,它主要調用SenrsorManager.cpp和SensorEventQueue.cpp中的類來完成相關的工作。
SenrsorManager.cpp與SensorService.cpp主要以binder通信
三.SensorService.cpp
SensorService作為一個輕量級的system service,它運行於SystemServer內,即在system_init<system_init.cpp>調用SensorService::instantiate();
SensorService主要功能如下:
1) SensorService::instantiate創建實例對象,並增加到ServiceManager中,且創建並啟動線程,並執行threadLoop
2) threadLoop從sensor驅動獲取原始數據,然后通過SensorEventConnection把事件發送給客戶端
3) BnSensorServer的成員函數負責讓客戶端獲取sensor列表和創建SensorEventConnection
void SensorService::onFirstRef()
SensorDevice& dev(SensorDevice::getInstance()); // 也就是調用下面的SensorDevice::SensorDevice()。
ssize_t count = dev.getSensorList(&list);
//虛擬的sensor,也就是沒有硬件,通過其他硬件計算出來的。
uint32_t virtualSensorsNeeds = (1<<SENSOR_TYPE_GRAVITY) | (1<<SENSOR_TYPE_LINEAR_ACCELERATION) | (1<<SENSOR_TYPE_ROTATION_VECTOR);
registerSensor( new HardwareSensor(list[i]) ); //根據硬件sensor_t創建HardwareSensor,然后加入mSensorList(Sensor),
mUserSensorList = mSensorList; // build the sensor list returned to users
/* 這里加入的前提是hasGyro,也就是需要陀螺儀 ,才能加入虛擬sensor*/
aSensor = registerVirtualSensor( new RotationVectorSensor() ); //
if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
mUserSensorList.add(aSensor); //加入UserSensorList,這里RotationVectorSensor,GravitySensor,LinearAccelerationSensor, OrientationSensor, CorrectedGyroSensor
}
/ *后面有一些關於batching的sensor的設置,batching sensor也就是支持批處理的sensor,有fifo */
Looper = new Looper(false); //消息循環的線程和沒有消息循環的線程,有消息循環的線程一般都會有一個Looper
mSensorEventBuffer = new sensors_event_t[minBufferSize]; //sensors_event用於藏消息
mSensorEventScratch = new sensors_event_t[minBufferSize];
run("SensorService", PRIORITY_URGENT_DISPLAY); // run("SensorService", PRIORITY_URGENT_DISPLAY);運行線程,並執行threadLoop
bool SensorService::threadLoop()
ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
fusion.process(event[i]);
activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch, mMapFlushEventsToConnections); 調用SensorService::SensorEventConnection::sendEvents,把事件發送給所有的listener
status_t SensorService::SensorEventConnection::enableDisable
err = mService->enable(this, handle, samplingPeriodNs, maxBatchReportLatencyNs, reservedFlags);
SensorService::enable
err = sensor->activate(connection.get(), true); //使能sensor
四.sensor上層調用中間層的入口
SensorDevice.cpp (frameworks\native\services\sensorservice)
SensorDevice::SensorDevice()
1.hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&mSensorModule); //這個在Sensors.c (vendor\mediatek\proprietary\hardware\sensor)
2.err = sensors_open_1(&mSensorModule->common, &mSensorDevice); 打開sensor
3.err = pressure_sensors_open(&mSensorDevicePressure); //這里我們加入的溫度氣壓傳感器
4. mSensorModule->get_sensors_list(mSensorModule, &list); //得到sensor列表,Sensors.c (vendor\mediatek\proprietary\hardware\sensor)
5.for (i=0; i<size_t(count-PRES_TEMP_SENSORS_CNT); i++) {
mActivationCount.add(list[i].handle, model); //把sensor加入到一個vector,handle是sensor唯一的標志 , Hwmsen_chip_info.c (vendor\mediatek\proprietary\hardware\sensor)
mSensorDevice->activate(reinterpret_cast<struct sensors_poll_device_t *>(mSensorDevice), list[i].handle, 0); //激活sensor
}
6.for (; i<size_t(count); i++) {
mActivationCount.add(list[i].handle, model);
mSensorDevicePressure->activate(mSensorDevicePressure, list[i].handle, 0);
sensor的重要結構體
Sensor設備結構體sensors_poll_device_t,對標准硬件設備hw_device_t結構體的擴展,主要完成讀取底層數據,並將數據存儲在struct sensors_poll_device_t結構體中,poll函數用來獲取底層數據,調用時將被阻塞定義如下:
| struct sensors_poll_device_t { struct hw_device_t common; //Activate/deactivate one sensor int (*activate)(struct sensors_poll_device_t *dev, int handle, int enabled); //Set the delay between sensor events in nanoseconds for a given sensor. int (*setDelay)(struct sensors_poll_device_t *dev, int handle, int64_t ns); //獲取數據 int (*poll)(struct sensors_poll_device_t *dev, sensors_event_t* data, int count); };
|
- typedef struct hw_device_t {
-
- uint32_t tag;
-
-
- uint32_t version;
-
-
- struct hw_module_t* module;
-
-
- uint32_t reserved[12];
-
-
- int (*close)(struct hw_device_t* device);
-
- } hw_device_t;
- typedef struct sensors_event_t {
-
- int32_t version;
-
-
- int32_t sensor;
-
-
- int32_t type;
-
-
- int32_t reserved0;
-
-
- int64_t timestamp;
-
- union {
- float data[16];
-
-
- sensors_vec_t acceleration;
-
-
- sensors_vec_t magnetic;
-
-
- sensors_vec_t orientation;
-
-
- sensors_vec_t gyro;
-
-
- float temperature;
-
-
- float distance;
-
-
- float light;
-
-
- float pressure;
-
-
- float relative_humidity;
- };
- uint32_t reserved1[4];
- } sensors_event_t;
來源:
struct pollfd {
int fd; /* 文件描述符 */
short events; /* 等待的事件 */
short revents; /* 實際發生了的事件 */
};
五.詳解四中每一步
第1步
.
hw_get_module(SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**)&mSensorModule);
根據
SENSORS_HARDWARE_MODULE_ID得到
Sensors.c (vendor\mediatek\proprietary\hardware\sensor)中的HAL層代碼
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 = "MTK SENSORS Module",
.author = "Mediatek",
.methods = &sensors_module_methods,
},
.get_sensors_list = sensors__get_sensors_list,
};
這里主要函數是:
sensors__get_sensors_list
*list = sSensorList; //得到sensorlist
struct sensor_t sSensorList[MAX_NUM_SENSOR] ={}; 在Hwmsen_chip_info.c (vendor\mediatek\proprietary\hardware\sensor)中,我推測是apk判斷是否支持某種sensor的依據
#ifdef CUSTOM_KERNEL_ACCELEROMETER //這個與ProjectConfig.mk這個相對應
{
.name = ACCELEROMETER,
.vendor = ACCELEROMETER_VENDER,
.version = 3,
.handle = ID_ACCELEROMETER+ID_OFFSET, //這個在Hwmsensor.h (kernel-3.10\include\linux)中定義,是標示各種sensor的唯一值,調用的時候使用
.type = SENSOR_TYPE_ACCELEROMETER, //這個在Hwmsensor.h (kernel-3.10\include\linux)中定義,標示sensor的類型
.maxRange = ACCELEROMETER_RANGE,//32.0f,
.resolution = ACCELEROMETER_RESOLUTION,//4.0f/1024.0f ,上報的精度在4.0f---1024f
.power = ACCELEROMETER_POWER,//130.0f/1000.0f, //估計上電用的時間
.minDelay = 10000, //最少的上報時間=10ms
.maxDelay = 1000000, //1s,最大上報時間
.reserved = {}
},
#endif
第2步:
第3步:
pressure_sensors_open(&mSensorDevicePressure); //這里我們加入的溫度氣壓傳感器
sensors__open_sensors((struct hw_device_t**)device); //打開sensor
sensors_poll_context_t *dev = new sensors_poll_context_t();
mSensors[pre] = new PresSensor();
PresSensor::PresSensor() //進入構造函數
SensorBase(NULL, "lps331ap_prs") //在PresSensor.cpp (frameworks\native\services\sensorservice)
data_fd = openInput(data_name); //data_name = lps331ap_prs
dir = opendir(dirname); //dirname=/dev/input
readdir(dir) //循環讀取dir下每一個文件,找到lps331ap_prs這個文件,pressure_presence_flag = 1
mEnabled(1),
mEnabledP(1),
mEnabledT(1),
currHzPollFreq(10.0f),
mInputReader(4)
mPendingEventP //設置mPendingEventP結構體,他一個sensors_event_t變量
property_get("ro.hardware.accsensor", buffer, INPUT_SYSFS_PATH_PRES); //得到INPUT_SYSFS_PATH_PRES "/sys/class/input/input5/device/"
getCompenseParam(); //得到補償參數
LPS331AP_InitializeLibrary(calvalues); //算法相關的
dev->device.activate = poll__activate; //填充結構體
dev->device.setDelay = poll__setDelay;
dev->device.poll = poll__poll;
第4步:
mSensorModule->get_sensors_list(mSensorModule, &list); //得到sensor列表,Sensors.c (vendor\mediatek\proprietary\hardware\sensor)
第5步:
第六步:
6.for (; i<size_t(count); i++) {
mActivationCount.add(list[i].handle, model);
//把sensor加入到一個vector,handle是sensor唯一的標志 , Hwmsen_chip_info.c
mSensorDevicePressure->activate(mSensorDevicePressure, list[i].handle, 0);
dev->device.activate = poll__activate; //在pressure_sensors_open里面賦值了這個函數指針
poll__activate //在Sensors.cpp (frameworks\native\services\sensorservice)中
ctx->activate(handle, enabled); //進行enable
sensors_poll_context_t::activate;在Sensors.cpp (frameworks\native\services\sensorservice)
index = handleToDriver(handle);
//這里返回0
err = mSensors[index]->enable(handle, enabled);
PresSensor::enable
//在
PresSensor.cpp (frameworks\native\services\sensorservice)中
fd = open(input_sysfs_path, O_RDWR); //打開/得到INPUT_SYSFS_PATH_PRES "/sys/class/input/input5/device/enable"
err = write(fd, buf, sizeof(buf)); // 寫入1,打開sensor
write(mWritePipeFd, &wakeMessage, 1);//寫一個W到pipe,pipe在open的時候創建
創建pipe:Sensors.cpp (frameworks\native\services\sensorservice)的sensors_poll_context_t::sensors_poll_context_t()
int wakeFds[2];
int result = pipe(wakeFds); //創建pipe
ALOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
fcntl(wakeFds[0], F_SETFL, O_NONBLOCK); //
設置文件的flags為O_NONBLOCK
fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
mWritePipeFd = wakeFds[1]; //寫管道
mPollFds[wake].fd = wakeFds[0]; //讀管道
mPollFds[wake].events = POLLIN;
mPollFds[wake].revents = 0;
6.sensor數據的讀取
bool SensorService::threadLoop() //
SensorService.cpp (frameworks\native\services\sensorservice)
ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
SensorDevice::poll(sensors_event_t* buffer, size_t count) //SensorDevice.cpp (frameworks\native\services\sensorservice)
c_pressure = mSensorDevicePressure->poll(mSensorDevicePressure, buffer, PRES_TEMP_SENSORS_CNT);
//ALOGE( "SensorDevice::poll, mSensorDevicePressure return = %d\n", c_pressure);
c = mSensorDevice->poll(reinterpret_cast<struct sensors_poll_device_t *> (mSensorDevice), buffer+PRES_TEMP_SENSORS_CNT, count-PRES_TEMP_SENSORS_CNT);
return ctx->pollEvents(data, count); //Nusensors.cpp (vendor\mediatek\proprietary\hardware\sensor)
int nb = sensor->readEvents(data, count); //Sensors.cpp (frameworks\native\services\sensorservice)
int Hwmsen::readEvents(sensors_event_t* data, int count) //Hwmsen.cpp (vendor\mediatek\proprietary\hardware\sensor)
n = mInputReader.fill(mdata_fd); //后面有些細節沒有深究了
n = poll(mPollFds, numFds, nbEvents ? 0 : -1); //poll,等待事件
7.虛擬sensor的讀取過程
注冊過程
SensorService::onFirstRef
ssize_t count = dev.getSensorList(&list); //得到sensorlist
if (hasGyro) { //注冊各種sensor
aSensor = registerVirtualSensor( new RotationVectorSensor() );
if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
mUserSensorList.add(aSensor);
}
aSensor = registerVirtualSensor( new GravitySensor(list, count) );
if (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) {
mUserSensorList.add(aSensor);
}
aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );
if (virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) {
mUserSensorList.add(aSensor);
}
aSensor = registerVirtualSensor( new OrientationSensor() );
if (virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) {
// if we are doing our own rotation-vector, also add
// the orientation sensor and remove the HAL provided one.
mUserSensorList.replaceAt(aSensor, orientationIndex);
}
// virtual debugging sensors are not added to mUserSensorList
registerVirtualSensor( new CorrectedGyroSensor(list, count) );
registerVirtualSensor( new GyroDriftSensor() );
}
enable過程
//SensorService.cpp (frameworks\native\services\sensorservice)
SensorService::enable
SensorInterface* sensor = mSensorMap.valueFor(handle); //得到sensor的接口,虛擬sensor的interface
mActiveVirtualSensors.add(handle, sensor); //加入到mActiveVirtualSensors鏈
err = sensor->activate(connection.get(), true); //調用active
SensorFusion::activate(void* ident, bool enabled) //調用SensorFusion.cpp (frameworks\native\services\sensorservice)
mSensorDevice.activate(ident, mAcc.getHandle(), enabled); //使能加速度傳感器
mSensorDevice.activate(ident, mMag.getHandle(), enabled); //使能磁傳感器
mSensorDevice.activate(ident, mGyro.getHandle(), enabled); //使能陀螺儀
SensorDevice::activate //SensorDevice.cpp (frameworks\native\services\sensorservice) //這里就是開始使能實體sensor
獲取數據過程
SensorService::threadLoop() //
count = device.poll(mSensorEventBuffer, numEventMax); //這里獲取實體sensor的數據
// handle virtual sensors
if (count && vcount) { //如果是虛擬sensor
SensorFusion& fusion(SensorFusion::getInstance());
fusion.isEnabled() //如果使能
fusion.process(event[i]); //調用process
SensorFusion::process //調用SensorFusion.cpp (frameworks\native\services\sensorservice),這里傳入的是實體sensor獲取來的數據
mFusion.handleGyro(vec3_t(event.data), dT); //處理各自的數據
mFusion.handleMag(mag);
mFusion.handleAcc(acc);
SensorInterface* si = mActiveVirtualSensors.valueAt(j); //得到虛擬sensor的接口
if (si->process(&out, event[i])) { //獲取計算好的值
mSensorEventBuffer[count + k] = out;}
// record the last synthesized values
recordLastValueLocked(&mSensorEventBuffer[count], k);
// sort the buffer by time-stamps
sortEventBuffer(mSensorEventBuffer, count); //給這些event排序
activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,),通過activeConnections發送到上層
注意:
如果加速度,磁傳感器,陀螺儀的數據不正常可能導致虛擬傳感器沒有數據!!