对于sensor的工作已经有一段时间了,在此将了解的知识记录下
Android sensor 框架
首先介绍下 Android 下 sensor的基本框架,对于 mtk 或者 Qcom sensor hub 架构,会与这个稍微有些不同
对上图部分进行基本的概括:
- App中传感器注册,获取系统服务,数据上报给app(onSensorChange)都是通过SystemSensorManager.java完成的,SensorManager.java仅仅是类似于接口类,功能是由SystemSensorManager.java实现
- SystemSensorManager.java 中函数会调用 jni 的android_hardware_SensorManager.cpp实现
- android_hardware_SensorManager.cpp调用SensorManager.cpp实现
- SensorManager.cpp 与sensorService.cpp 间进行通信,其中命令传输通过binder实现,数据传输通过管道实现;其中binder做主要贡献的是ISensorEventConnection.cpp,完成binder的服务端和客户端
- sensorService.cpp通过中通过 threadloop 不断的从hardware 层获取sensor数据,其中对sensor 的操作主要有sensordevice 类完成
- hardware (sensor hal)层则通过read / write sensor驱动设备节点去操作sensor 设备,读取sensor上报的数据(一般是input子系统,但是目前mtk有所不同,mtk为sensor_event)
- kenel中sensor将数据放入到input子系统中(Qcom) 或者 sensor_event 中(mtk);如果是sensor hub 将不是linux驱动模型,在此先不讨论
sensor service 的启动过程
当按下power键后,首先会启动BOOT ROM,然后是 lk ,后面会启动kernel,然后进行init进程,启动虚拟机,后面进入到 systemServer,在该进程启动过程如下:
SensorService 服务
Frameworks/base/services/java/com/android/server/SystemServer.java
Main函数
public static void main(String[] args) {
new SystemServer().run();
}
Run函数
private void run() {
......
// Start services.
try {
Trace.traceBegin(Trace.TRACE_TAG_SYSTEM_SERVER, "StartServices");
startBootstrapServices();
startCoreServices();
startOtherServices();
} catch (Throwable ex) {
throw ex;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
}
// Loop forever.
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
startBootstrapServices函数
private void startBootstrapServices() {
......
traceLog.traceBegin(START_SENSOR_SERVICE);
startSensorService();
traceLog.traceEnd();
......
}
startSensorService函数
private static native void startSensorService();
android_server_SystemServer_startSensorService函数
Framework/base/services/core/jni/com_android_server_SystemServer.cpp
static void android_server_SystemServer_startSensorService(JNIEnv* /* env */, jobject /* clazz */) {
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
// Start the sensor service
SensorService::instantiate();
}
}
onFirstRef 函数
此函数中启动 sensor 线程 threadloop
void SensorService::onFirstRef() {
//判断是否有 陀螺仪 加速度 和地磁
if (hasGyro && hasAccel && hasMag) {
// Add Android virtual sensors if they're not already
// available in the HAL
bool needRotationVector =
(virtualSensorsNeeds & (1<<SENSOR_TYPE_ROTATION_VECTOR)) != 0;
registerSensor(new RotationVectorSensor(), !needRotationVector, true);
registerSensor(new OrientationSensor(), !needRotationVector, true);
bool needLinearAcceleration =
(virtualSensorsNeeds & (1<<SENSOR_TYPE_LINEAR_ACCELERATION)) != 0;
registerSensor(new LinearAccelerationSensor(list, count),
!needLinearAcceleration, true);
// virtual debugging sensors are not for user
registerSensor( new CorrectedGyroSensor(list, count), true, true);
registerSensor( new GyroDriftSensor(), true, true);
}
if (hasAccel && hasGyro) {
bool needGravitySensor = (virtualSensorsNeeds & (1<<SENSOR_TYPE_GRAVITY)) != 0;
registerSensor(new GravitySensor(list, count), !needGravitySensor, true);
bool needGameRotationVector =
(virtualSensorsNeeds & (1<<SENSOR_TYPE_GAME_ROTATION_VECTOR)) != 0;
registerSensor(new GameRotationVectorSensor(), !needGameRotationVector, true);
}
if (hasAccel && hasMag) {
bool needGeoMagRotationVector =
(virtualSensorsNeeds & (1<<SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR)) != 0;
registerSensor(new GeoMagRotationVectorSensor(), !needGeoMagRotationVector, true);
}
// Check if the device really supports batching by looking at the FIFO event
// counts for each sensor.
bool batchingSupported = false;
mSensors.forEachSensor(
[&batchingSupported] (const Sensor& s) -> bool {
if (s.getFifoMaxEventCount() > 0) {
batchingSupported = true;
}
return !batchingSupported;
});
if (batchingSupported) {
// Increase socket buffer size to a max of 100 KB for batching capabilities.
mSocketBufferSize = MAX_SOCKET_BUFFER_SIZE_BATCHED;
} else {
mSocketBufferSize = SOCKET_BUFFER_SIZE_NON_BATCHED;
}
// Compare the socketBufferSize value against the system limits and limit
// it to maxSystemSocketBufferSize if necessary.
FILE *fp = fopen("/proc/sys/net/core/wmem_max", "r");
char line[128];
if (fp != NULL && fgets(line, sizeof(line), fp) != NULL) {
line[sizeof(line) - 1] = '\0';
size_t maxSystemSocketBufferSize;
sscanf(line, "%zu", &maxSystemSocketBufferSize);
if (mSocketBufferSize > maxSystemSocketBufferSize) {
mSocketBufferSize = maxSystemSocketBufferSize;
}
}
if (fp) {
fclose(fp);
}
mInitCheck = NO_ERROR;
mAckReceiver = new SensorEventAckReceiver(this);
mAckReceiver->run("SensorEventAckReceiver", PRIORITY_URGENT_DISPLAY);
// 运行threadLoop函数
run("SensorService", PRIORITY_URGENT_DISPLAY);
// priority can only be changed after run
enableSchedFifoMode();
}
}
}
threadLoop 函数
bool SensorService::threadLoop() {
......
SensorDevice& device(SensorDevice::getInstance());
const int halVersion = device.getHalDeviceVersion();
do {
ssize_t count = device.poll(mSensorEventBuffer, numEventMax);
if (count < 0) {
ALOGE("sensor poll failed (%s)", strerror(-count));
break;
}
for (int i = 0; i < count; i++) {
mSensorEventBuffer[i].flags = 0;
}
SortedVector< sp<SensorEventConnection> > activeConnections;
populateActiveConnections(&activeConnections);
Mutex::Autolock _l(mLock);
bool bufferHasWakeUpEvent = false;
for (int i = 0; i < count; i++) {
if (isWakeUpSensorEvent(mSensorEventBuffer[i])) {
bufferHasWakeUpEvent = true;
break;
}
}
if (bufferHasWakeUpEvent && !mWakeLockAcquired) {
setWakeLockAcquiredLocked(true);
}
recordLastValueLocked(mSensorEventBuffer, count);
// handle virtual sensors
if (count && vcount) {
sensors_event_t const * const event = mSensorEventBuffer;
if (!mActiveVirtualSensors.empty()) {
size_t k = 0;
SensorFusion& fusion(SensorFusion::getInstance());
if (fusion.isEnabled()) {
for (size_t i=0 ; i<size_t(count) ; i++) {
fusion.process(event[i]);
}
}
for (size_t i=0 ; i<size_t(count) && k<minBufferSize ; i++) {
for (int handle : mActiveVirtualSensors) {
if (count + k >= minBufferSize) {
ALOGE("buffer too small to hold all events: "
"count=%zd, k=%zu, size=%zu",
count, k, minBufferSize);
break;
}
sensors_event_t out;
sp<SensorInterface> si = mSensors.getInterface(handle);
if (si == nullptr) {
ALOGE("handle %d is not an valid virtual sensor", handle);
continue;
}
if (si->process(&out, event[i])) {
mSensorEventBuffer[count + k] = out;
k++;
}
}
}
if (k) {
// record the last synthesized values
recordLastValueLocked(&mSensorEventBuffer[count], k);
count += k;
// sort the buffer by time-stamps
sortEventBuffer(mSensorEventBuffer, count);
}
}
}
for (int i = 0; i < count; ++i) {
mMapFlushEventsToConnections[i] = NULL;
if (mSensorEventBuffer[i].type == SENSOR_TYPE_META_DATA) {
const int sensor_handle = mSensorEventBuffer[i].meta_data.sensor;
SensorRecord* rec = mActiveSensors.valueFor(sensor_handle);
if (rec != NULL) {
mMapFlushEventsToConnections[i] = rec->getFirstPendingFlushConnection();
rec->removeFirstPendingFlushConnection();
}
}
if (mSensorEventBuffer[i].type == SENSOR_TYPE_DYNAMIC_SENSOR_META) {
if (mSensorEventBuffer[i].dynamic_sensor_meta.connected) {
int handle = mSensorEventBuffer[i].dynamic_sensor_meta.handle;
const sensor_t& dynamicSensor =
*(mSensorEventBuffer[i].dynamic_sensor_meta.sensor);
ALOGI("Dynamic sensor handle 0x%x connected, type %d, name %s",
handle, dynamicSensor.type, dynamicSensor.name);
if (mSensors.isNewHandle(handle)) {
const auto& uuid = mSensorEventBuffer[i].dynamic_sensor_meta.uuid;
sensor_t s = dynamicSensor;
// make sure the dynamic sensor flag is set
s.flags |= DYNAMIC_SENSOR_MASK;
// force the handle to be consistent
s.handle = handle;
SensorInterface *si = new HardwareSensor(s, uuid);
// This will release hold on dynamic sensor meta, so it should be called
// after Sensor object is created.
device.handleDynamicSensorConnection(handle, true /*connected*/);
registerDynamicSensorLocked(si);
} else {
ALOGE("Handle %d has been used, cannot use again before reboot.", handle);
}
} else {
int handle = mSensorEventBuffer[i].dynamic_sensor_meta.handle;
ALOGI("Dynamic sensor handle 0x%x disconnected", handle);
device.handleDynamicSensorConnection(handle, false /*connected*/);
if (!unregisterDynamicSensorLocked(handle)) {
ALOGE("Dynamic sensor release error.");
}
size_t numConnections = activeConnections.size();
for (size_t i=0 ; i < numConnections; ++i) {
if (activeConnections[i] != NULL) {
activeConnections[i]->removeSensor(handle);
}
}
}
}
}
bool needsWakeLock = false;
size_t numConnections = activeConnections.size();
for (size_t i=0 ; i < numConnections; ++i) {
if (activeConnections[i] != 0) {
activeConnections[i]->sendEvents(mSensorEventBuffer, count, mSensorEventScratch,mMapFlushEventsToConnections);
needsWakeLock |= activeConnections[i]->needsWakeLock();
if (activeConnections[i]->hasOneShotSensors()) {
cleanupAutoDisabledSensorLocked(activeConnections[i], mSensorEventBuffer,
count);
}
}
}
if (mWakeLockAcquired && !needsWakeLock) {
setWakeLockAcquiredLocked(false);
}
} while (!Thread::exitPending());
ALOGW("Exiting SensorService::threadLoop => aborting...");
abort();
return false;
}