最近收到任务,要把陀螺仪的数据对接到上层,分发应用。就赶紧看了一下Sensor服务相关的代码。本来是想熟悉之后可以在调试过程中能有的放矢。结果我们这个车载方案有些区别,看的这些东西根本没用上。这里还是整理一下Sensor服务相关的点。
我们的系统可能存在多个传感器,像陀螺仪,加速传感,接近传感,磁力传感器、方向传感等等,Sensor服务需要管理所有传感器,负责他们数据的分发和监听,还有传感融合计算,以及虚拟传感等等。
先还是通过一张图大概了接一下Sensor服务和应用之间的关系。
1 系统进程中 SensorService是一个C++的服务,他启动过程中会加载Sensor Hal层库,激活Sensor硬件。
2 在APP进程Java层可以获取SystemSensorManager对象,这个对象的初始化过程中会对应创建Native层的SensorManager对象。在SensorManager中会通过ServiceManager获取SensorService的代理对象来和SensorService交互。
3 当应用需要监听Sensor数据的时候,会通过SystemSensorManager以及他native层的SensorManager请求SensorService创建一个SensorEventConnection (binder)对象。在SensorEventConnection中还会通过BitTube创建一对Socket。一端用于SensorService从Sensor硬件读取Sensor数据后写入。另一端,用于应用来读取数据,然后分发给监听对象。
4 Receiver就是用于应用这边读取数据然后分发。
接下来就分四个部分两篇文章来对SensorService的源码做个简单的分析:
一: SensorService服务的启动以及Sensor Hal层库的加载和初始化
二: 应用层SystemSensorManager以及native层SensorManager的初始化以及和SensorService建立连接
三: 应用注册Sensor数据监听的过程
四: sensor数据分发的过程
一: SensorService服务的启动以及Sensor Hal层库的加载和初始化
1 开机启动SensorService
SystemService的startBootstrapServices()函数中会调用一个如下的Native函数:startSensorService()
static void android_server_SystemServer_startSensorService(JNIEnv* , jobject) {
char propBuf[PROPERTY_VALUE_MAX];
property_get("system_init.startsensorservice", propBuf, "1");
if (strcmp(propBuf, "1") == 0) {
SensorService::instantiate();
}
}
这个函数就是读取一个属性值,然后比较如果属性值为1,调用SensorService::instantiate()函数。
2 初始化SensorService
SensorService继承自BinderService,BinderService是个模板类,
继承自这个模板类的好处就是把创建Server对象并加入到ServerManager的代码都封装好了。
static void instantiate() { publish(); }
instantiate只是调用了BinderService的publish函数:
template
class BinderService
{
public:
static status_t publish(bool allowIsolated = false) {
spsm(defaultServiceManager());
return sm->addService(
String16(SERVICE::getServiceName()),
new SERVICE(), allowIsolated);
}
SERVICE:去看SensorService的声明你会发现他就是 SensorService
defaultServiceManager: 获取ServiceManager对象。
SERVICE::getServiceName():SensorService加入到ServiceManager的key “sensorservice”
实际上这里就是 new一个SensorService,然后 以 “sensorservice”为key把sensorservice实例加入到ServiceManaer。
3 SensorService 的构造函数并不复杂,主要初始化工作都是在onFirstRef函数中做的
这个函数涉及的东西比较多,这里对重要的部分列出来做一些分析。
void SensorService::onFirstRef(){
//3.1部分
SensorDevice& dev(SensorDevice::getInstance());
......//3.2部分
ssize_t count = dev.getSensorList(&list);
......
for (ssize_t i=0 ; i"" i++)="" {<="" span="">
registerSensor( new HardwareSensor(list[i]) );
......
}
......//3.3部分
const SensorFusion& fusion(SensorFusion::getInstance());
......//3.4部分
aSensor = registerVirtualSensor( new RotationVectorSensor() );
aSensor = registerVirtualSensor( new GravitySensor(list, count) );
aSensor = registerVirtualSensor( new LinearAccelerationSensor(list, count) );
......//3.5部分
const size_t minBufferSize = SensorEventQueue:: MAX_RECEIVE_BUFFER_EVENT_COUNT;
mSensorEventBuffer = new sensors_event_t[minBufferSize];
mSensorEventScratch = new sensors_event_t[minBufferSize];
mMapFlushEventsToConnections = new SensorEventConnection const * [minBufferSize];
mCurrentOperatingMode = NORMAL;
......//3.6部分
run("SensorService", PRIORITY_URGENT_DISPLAY);
}
这个函数做了如下几件事情:
3.1 SensorDevice初始化Sensor Hal层以及激活Sensor硬件
3.2 获取系统中的Sensor列表,调用registerSensor函数把Sensor保存起来
3.3 SensorFusion功能,传感融合。它的主要作用就是,按照一定的算法计算系统的多个传感器对某一个值的上报的数据,得到更准确的值。
3.4 registerVirtualSensor注册虚拟传感器:这些虚拟的传感器步会产生真的数据,而是通过SensorFusion功能计算得到的值,作为虚拟传感的数据。分发过程中会有分析到。
3.5 初始化一些Buffer,后面需要用到他们保存sensor硬件上报的数据。
3.6 SensorService不仅是一个服务,而且他还是一个线程,初始化工作的最后就是启动该线程执行threadLoop函数。threadLoop函数主要的工作就是,循环读取sensor硬件上传上来的数据,然后分发给应用。这个函数在Sensor数据分发的过程中详细分析。
接下来重点分析3.1 SensorDevice
4 SensorDevice的构造函数:
SensorDevice::SensorDevice() : mSensorDevice(0), mSensorModule(0)
{//4.1部分
status_t err = hw_get_module( SENSORS_HARDWARE_MODULE_ID, (hw_module_t const**) &mSensorModule);
if (mSensorModule) {//4.2部分
err = sensors_open_1(&mSensorModule->common, &mSensorDevice);
if (mSensorDevice) {
sensor_t const* list;//4.3部分
ssize_t count = mSensorModule->get_sensors_list(mSensorModule, &list);
mActivationCount.setCapacity(count);
Info model;
for (size_t i=0 ; i"" i++)="" {<="" span="">
mActivationCount.add(list[i].handle, model);
mSensorDevice->activate(//4.4部分
reinterpret_cast(mSensorDevice),
list[i].handle, 0);
}
}
}
}
该函数主要做了如下几件事情:
4.1 通过hw_get_module函数获取mSensorModule
4.2 调用sensors_open_1获取mSensorDevice
4.3 mSensorModule->get_sensors_list 获取Sensor列表。
4.4 mSensorDevice->activate激活Sensor硬件
5 hw_get_module函数获取mSensorModule的过程(hardWare.c)
这个函数的主要功能就是加载.so库文件,然后获取库文件中定义的Module结构体变量返回(sensors_module_t)
在加载的过程中需要理解如下关键点:(这里就不贴代码了)
5.1 sensor对应的.so文件的存放路径的定义:(hardWare.c)
#define HAL_LIBRARY_PATH1 "/system/lib/hw"
#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"
5.2 属性关键字的定义如下:在加载.so文件的过程中会读取这下面的属性值作为so文件的subname
static const char *variant_keys[] = {
"ro.hardware",
"ro.product.board",
"ro.board.platform",
"ro.arch"
};
5.3 #define SENSORS_HARDWARE_MODULE_ID “sensors”
//(sensors.h) sensor Module ID
在查找.so库文件中会用它和5.2中属性的值来拼接.so的名字: sensors.subname.so
5.4 handle = dlopen(path, RTLD_NOW);打开.so库文件,并加载到内存。
handle指向.so库文件的句柄
5.5 #define HAL_MODULE_INFO_SYM HMI
//表示Module的变量名,不同的硬件他们的Module的结构体不一样,但是他们的变量名都是这个,这样做的目的就是为了方便找到这个Module变量的地址。
#define HAL_MODULE_INFO_SYM_AS_STR "HMI"
//表示Module变量的符号,加载.so库文件后就可以通过这个符号获取Module变量的地址。
比如说:SensorModule定义如下:(sensors_mpl.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: "Invensense module",
author: "Invensense Inc.",
methods: &sensors_module_methods,
dso: NULL,
reserved: {0}
},
get_sensors_list: sensors__get_sensors_list,
};
5.6 const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
//5.5有说明这个宏就是”HMI”
hmi = (struct hw_module_t *)dlsym(handle, sym);
根据动态链接库操作句柄(handle)与符号 (HAL_MODULE_INFO_SYM_AS_STR),获取Module变量地址.
总结一下:hw_get_module的流程大概如下:
在5.1的这两个目录下查找由5.2和5.3拼接成的(sensors.subname.so).so库文件,然后调用5.4的dlopen打开sensor对应.so库文件,获取.so库文件的句柄handle,然后根据.so文件中定义的Module变量的符号”HMI”,调用5.6的dlsym函数,获取在5.5中定义的sensors_module_t变量的地址。
理解了上面6点,然后根据这个流程,再去阅读hw_get_module的源码就会比较轻松了。
6 sensors_open_1(&mSensorModule->common, &mSensorDevice){
//获取mSensorDevice
return module->methods->open(module, SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);
}
module: hw_module_t结构体变量,这个是Hal层通用的结构体
methods: hw_module_methods_t结构体变量,对应5.5中定义的sensors_module_t中common的methods变量(指向sensors_module_methods)定义如下:
static struct hw_module_methods_t sensors_module_methods = {
//(sensors_mpl.cpp中)
open: open_sensors
};
实际上这个函数调用的就是调用了sensors_mpl.cpp中的open_sensors函数。
static int open_sensors(const struct hw_module_t* module, const char* id, struct hw_device_t** device){
sensors_poll_context_t *dev = new sensors_poll_context_t();
memset(&dev->device, 0, sizeof(sensors_poll_device_1));
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_3;
dev->device.flush = poll__flush;
dev->device.common.module = const_cast(module);
dev->device.common.close = poll__close;
dev->device.activate = poll__activate;
dev->device.setDelay = poll__setDelay;
dev->device.poll = poll__poll;
dev->device.batch = poll__batch;
*device = &dev->device.common;
status = 0;
return status;
}
这个函数创建了一个sensors_poll_context_t的结构体变量,并初始化了一些函数指针。
并把sensors_poll_context_t的成员变量sensors_poll_device_1_t返回
Hal层就是通过返回的sensors_poll_device_1_t结构体变量,最终调用sensors_poll_context_t结构体的函数真正控制和获取Sensor数据
sensors_poll_context_t的构造函数中与Sensor驱动相关的交互这里就不做详细的分析了。
7 sensors_module_t和hw_module_t 以及 sensors_poll_device_1_t和hw_device_t 的一些疑惑。
在看源码的过程中你会发现这两对结构体可以相互转换?原因是他们的起始地址相同。
另外w_module_t,hw_device_t 是Hal层公共的定义。
8 mSensorModule->get_sensors_list(mSensorModule, &list);
//获取Sensor列表
这个函数最终获取的就是sensors_poll_context_t的成员变量:sSensorList
9 mSensorDevice->activate激活Sensor硬件
这里实际调用的就是第6步中的poll__activate,这个函数由直接调用了sensors_poll_context_t的activate函数去激活Sensor硬件。
至此SensorService的启动完成。他的启动过程中做了如下几件事情:
1 把自己加入到ServiceManger中。
2 加载了Sensor Hal层库文件。获取Hal层相关数据和接口,得到了对Sensor硬件的控制权。
3 激活Sensor硬件。
4 sensor融合+创建虚拟传感。
5 作为线程启动自己执行threadLoop函数,进入循环获取sensor数据,分发的流程。
二 应用层SystemSensorManager以及native层SensorManager的初始化以及和SensorService建立连接。
1 SystemSensorManager的创建(SystemServiceRegistry.java中)
registerService(Context.SENSOR_SERVICE, SensorManager.class, new CachedServiceFetcher() {
@Override
public SensorManager createService( ContextImpl ctx) {
return new SystemSensorManager( ctx.getOuterContext(), ctx.mMainThread. getHandler().getLooper());
}});
通过上面的初始化,应用可以通过Context.getSystemService()函数获取SystemSensorManager对象。
然后通过SystemSensorManager对象注册Sensor相关的监听。
2 SystemSensorManager 构造函数,看JNI相关的初始化。
public SystemSensorManager(Context context, Looper mainLooper) {
......
mNativeInstance = nativeCreate(context.getOpPackageName());
......
nativeClassInit();
// initialize the sensor list
for (int index = 0;;++index) {
Sensor sensor = new Sensor();
if (!nativeGetSensorAtIndex( mNativeInstance, sensor, index)) break;
mFullSensorsList.add(sensor);
mHandleToSensor.append( sensor.getHandle(), sensor);
}
}
在构造函数中主要调用了三个native的函数来完成SystemSensorManager的初始化工作:
2.1 nativeCreate 创建Native层 SensorManager 建立与SensorService的连接。
2.2 nativeClassInit 获取Sensor.java类的成员变量和成员函数保存到gSensorOffsets中。
2.3 nativeGetSensorAtIndex 获取Sensor列表保存到Java层Sensor对象中。
接下来通过源码分析这三个native的函数。
3 nativeCreate()函数(android_hardware_SensorManager.cpp)
nativeCreate(JNIEnv *env, jclass clazz, jstring opPackageName){
return (jlong) new SensorManager(String16(opPackageNameUtf.c_str()));
}
这个Native的函数只是创建了一个JNI层的SensorManager对象。然后把这个JNI层对象的地址返回保存到Jave层SystemSensorManager的成员变量mNativeInstance中。
4 SensorManager的构造函数:
SensorManager::SensorManager(const String16& opPackageName){
assertStateLocked();
}
这个函数主要是调用了 assertStateLocked 继续初始化的工作:
5 assertStateLocked()
status_t SensorManager::assertStateLocked() const {
if (mSensorServer == NULL) {
......
const String16 name("sensorservice");
err = getService(name, &mSensorServer);
......
mDeathObserver = new DeathObserver(*const_cast(this));
IInterface::asBinder(mSensorServer)->linkToDeath(mDeathObserver);
mSensors = mSensorServer->getSensorList(mOpPackageName);
size_t count = mSensors.size();
......
for (size_t i=0 ; i"" i++)="" {<="" span="">
mSensorList[i] = mSensors.array() + i;
}
}
return NO_ERROR;
}
这个函数主要做了如下几件事情:
5.1 通过getService获取SensorService的代理对象保存到mSensorServer中。
5.2 mSensorServer为这个代理对象注册BinderDead
5.3 通过mSensorServer获取SensorList
6 nativeClassInit();
这个函数比较简单,不贴源码了,就是获取java层Sensor类。
然后通过JNI的方式获取的一些成员变量和成员函数,这样就可以通过JNI的调用在Native层为Java层的Sensor对象赋值。
7 nativeGetSensorAtIndex()
nativeGetSensorAtIndex(JNIEnv *env, jclass clazz, jlong sensorManager, jobject sensor, jint index){
SensorManager* mgr = reinterpret_cast(sensorManager);
Sensor const* const* sensorList;
size_t count = mgr->getSensorList(&sensorList);
Sensor const* const list = sensorList[index];
const SensorOffsets& sensorOffsets(gSensorOffsets);
jstring name = getInternedString(env, &list->getName());
jstring vendor = getInternedString(env, &list->getVendor());
jstring requiredPermission = getInternedString(env, &list->getRequiredPermission());
env->SetObjectField(sensor, sensorOffsets.name, name);
......
return true;
}
其实这个函数主要就是把第6步获取mSensorList,赋值到Java层的Sonsor对象中并返回。
最后把这些Sensor对象保存到Java层SystemSensorManager的成员变量mFullSensorsList和mHandleToSensor中。