Android SensorService源码分析(一)

最近收到任务,要把陀螺仪的数据对接到上层,分发应用。就赶紧看了一下Sensor服务相关的代码。本来是想熟悉之后可以在调试过程中能有的放矢。结果我们这个车载方案有些区别,看的这些东西根本没用上。这里还是整理一下Sensor服务相关的点。
我们的系统可能存在多个传感器,像陀螺仪,加速传感,接近传感,磁力传感器、方向传感等等,Sensor服务需要管理所有传感器,负责他们数据的分发和监听,还有传感融合计算,以及虚拟传感等等。
先还是通过一张图大概了接一下Sensor服务和应用之间的关系。
Android SensorService源码分析(一)_第1张图片
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中。

欢迎关注个人微信公众号,定期更新个人工作心得
Android SensorService源码分析(一)_第2张图片

你可能感兴趣的:(android)