现在我们结合代码以及序列图来看一下SensorService初始化的一个过程
由图可以看到涉及到的内容有SensorServer和SensorDevice和Hal层,这样我们就能知道SensorService如何和我们的Hal层对接,再看这个之前我们先在Android下看一下我们的SensorService这个服务是什么时候加到我们SeverManager中的,打开我们的frameworks/base/services/java/com/android/server/SystemServer.java这个文件。在这个文件的最后部分,也就是system这个main函数中,会有一个nativeInit,我们来看一下他的实现
他在这里就是把我们的SensorService进行实例化,下面我们来结合流程图来看一下他的实例化的过程,它定义的位置是我们的frameworks/native/services/sensorservice/SensorService.cpp。
他在初始化过程中首先会调用我们的onFirstRef(),在调用之前我们来看一下SensorService的具体定义,它继承了我们的BinderService、BnSensorServer、Thread这三个类,我们来看一下这个BinderService
他在初始化的时候就会在这里调用我们的ServiceManager,然后把自己本身添加到ServiceManager中,在这里调用了一个addService,他其实是通过binder将这个实例添加到ServiceManager中,所以说我们在初始化的时候就已经添加到我们的ServiceManager中。那么我们就再来看一下我们初始化的一个过程,现在我们再来看上边的第一幅图。
首先我们会调用onFirstRef的方法,这个方法就开始和我们的Hal层开始对接,首先在这里我们会实例化一个SensorDevice,而我们的SensorDevice在初始化的时候也会调用hw_get_module()这个方法,这个方法是一个标准的Hal层的一个接口,他通过传进一个参数,调用hw_get_module_by_class(),然后倒入sensor的库,再倒入库的时候其实就是Hal层所做的事情了,首先会去查找我们的sensor的库,然后load我们的库,得到我们的opts(),也就是操作函数集,然后就返回。然后我们来看一下这部分的具体实现
我们来看一下SensorDevice(),在初始化的时候会调用hw_get_module(),我们来看一下他的ID,他的ID就是sensors,这个sensors就是一个字符串,我们再来看一下hw_get_module的定义,他就在hardware/libhardware/hardware.c中
我们这个方法是通用的,它既可以针对于我们的sensor,也可以针对于我们的surface、camera都是调用的这个接口,我们在这里真正调用的是hw_get_module_by_class(),他的ID就是一个字符串,就是我们需要导入的库的名字和类型,而后边的module就是一个操作级的句柄,这个后便我们会给他赋值,然后返回给我们的SensorDevice。我们在来看一下hw_get_module_by_class()的具体实现
首先他在这里会做一个snprintf(),就是把这个class的ID,写到name中,然后会在后面做一个路径的处理,在variant_keys中有一些环境变量,有ro.hardware、ro.product.board、ro.board.platform、ro.arch,得到这些之后,他会把这些系统变量的值赋值到prop中,在下边会将我们整个动态库的路径添加到path中,我们HAL_LIBRARY_PATH2他的定义是在我们的/vendor/lib/hw/中,这个就是我们sensor动态库的位置,后边的name就是我们要传进来的字符串,在后边的prop是根据property_get()中的prop得到的。如果说当前的板子有ro.hardware的环境变量,而我们hw那个目录下有相关的sensor动态库,那么他就会找到这个动态库,去load这个动态库,得到这个名字之后首先会判断一下这个文件是存在的,那么就跳出当前循环,并且执行一个load操作,这个load操作就是导入我们的动态库,导入之后就会调用dlsym的方法得到我们动态库中的操作函数级的一个句柄,得到这个句柄之后,我们就会将他返回给刚才定义的hmi的一个dso,最后会返回这个状态,这样我们就能拿到我们动态函数库中的函数集,这就是我们sensor的一个初始化的过程,和Hal层对接的过程。当我们拿到这个函数集以后,他会调用sensors_open_l的方法,去打开我们的sensor设备,我们再根据第一幅图看一下
当我们得到句柄之后就会调用sensors_open_1()的方法,去打开我们底层的设备,而我们打开的时候还会返回一些实际的操作函数集,他就会返回给mSensorDevice(),然后调用get_sensors_list()的方法来拿到我们底层支持的sensor,然后返回sensorList,然后我们的SensorDevice()初始化就完成了,然后就会返回,返回之后我们的SensorServer还会调用一个SensorList_Init()的方法,拿到我们底层所支持的sensor,并且根据我们sensor的类型,来做一个registartvirtualSensor()的一个操作,这样SensorServer的一个初始化就完成了。我们再来看一下具体的代码。
我们在这里拿到一个函数操作集是我们的mSensorModule,然后会调用mSensorModule中的一个common方法去打开我们的sensor,在这里调用的是sensor_open_1(),我们来看一下这个函数的具体实现
他在这里调用的是module->methods->open()的方法,这个方法就是Hal层对sensor进行初始化的一个过程。我们接着上边衣服图来看,当我们打开之后,他就把Hal层初始化完成了。然后调用一个get_sensor_list()得到底层所支持sensor的类型,然后把sensor类型添加到我们mActivationCount中,并且把我们的sensor设备给激活,这时我们的SensorDevice初始化就完成了。然后我们再退回去,看一下我们的SensorService
他把SensorDevice实例化完成之后,就会调用我们dev.getSensorList()的方法,拿到我们sensor所有的类型,当我们拿到之后就会做一个循环,调用registerSensor(),将这些Sensor添加到我们的Sensor列表中。当我们SensorService初始化完成之后,我们来看一下他和Hal层对接的一个过程
首先我们会根据系统prop的设置,在/system/lib/hw下找到我们所需要加载的动态库,然后使用dlopen来加载我们的动态库,并且使用dlsym得到并返回我们底层的操作函数集。这样我们framework层的service层和我们的Hal层就已经挂接起来了,挂接完成之后,我们来看一下SensorServer是如何处理底层数据以及上层的SensorManager的请求的。
当上层有一个请求过来的话,这里会首先创建一个connection,我们看一下他的定义
当我们SensorManager请求SensorService的时候,首先会建立一个SensorEventConnection,而这个connection创建了一个没有连接的套接字,也就是mChannel,这时候我们的SensorManager就能够和我们的SensorService进行数据交互了,这个交互通道就是这个mChannel,数据走的是我们的套接字,而命令走的还是binder机制,当我们链接上SensorService之后,我们再来看一下SensorManager是如何来把我们的SensorService来enable的。
这个enable的方法就是将我们上层所监听的Sensor给激活,他首先会有一个句柄,而这个句柄就是Sensor在我们mSensorMap中的一个句柄,这个Sensor就是我们底层实际的Sensor,然后会将我们实际监听的Sensor给激活,我们Sensor被激活之后,SensorService继承了一个thread的类,而我们的数据接受就是在这个thread类中实现的。下面我们来看一下threadLoop()这个函数的具体实现
这个threadLoop是是SensorService继承了thread这个类,他在这里也是将我们的SensorDevice实例化了,我们SensorDevice连的是Hal层的一个操作。他在这里做了一个循环,这个过程就是调用我们的device.Poll方法来接收Sensor的一个事件,这个device.poll他挂接的是Hal层的一个Sensor,当我们没有把这个Sensor激活的话,这个Sensor是不会向上返回数据的,只有在激活的时候才会Poll到数据,当Poll到数据后,我们就会调用一系列方法,将这些数据通过connection发送出去,在这里调用了一个sendEvents,而他的内容就是我们底层发过来的消息,我们来看一下这个Sensor
他的实现过程就是将我们接收到的所有的消息,通过这个套接字发送给我们的SensorManager。这里会有一个SensorEventQueue::write,这里的mChannel就是我们的套接字,当我们写完之后,我们的SensorManager就会拿到数据,然后继续往上返,返回给我们的应用,这样我们的应用就可以拿到数据了。那么当我们的应用切到后台,或者退出应用之后,那么他会调用一个disable。这个disable的过程就是将我们的activate给他关闭掉,然后Poll的过程就不会收到消息了,这样的话我们的threadLoop这个方法就会继续在这里阻塞,如果说我们没有激活这个Sensor,那么我们的数据还是会往上抛的。这就是我们SensorService处理数据的一个过程