根据sensor的使用一文中,介绍了应用如何使用sensor。
按照我的style怎么可能只研究怎么用呢,关键是这些功能都是如何实现的,还是很想要知道源码中的实现原理呀。不妨来探究一下。
研究源码一定要从功能出发,从上文中sensor的使用可以看出,提供给应用的有两个功能
-
获取到对应type的sensor对象
-
获取到sensor的数据
所以,本文从这两个方面出发,来瞻仰一下google大佬们的code.
估计有人会好奇了,为什么你总是倒追代码?
给你形容一下,源码像一棵树,正追的话你要从树根到树枝,起点是树根,终点是所有树枝,也就是越分析岔路口越多
你究竟该往哪个树枝走?走着走着可能就迷路了。
而倒追像什么?起点是树枝,终点是树根,那么从树枝到树根的路是唯一的,你只要掌握了有哪些树枝,越分析越清晰,是不是这个道理?
当然,每个人有每个人的学习方法,看个人的习惯和喜好
来,咱们开启一个树枝的分析
应用层怎么获取到sensor对象的?
通过SensorManager来getDefaultSensor(int type)。
这么简单的咧?还等什么,瞬间定位到SensorManager.java文件(文件路径:/frameworks/base/core/java/android/hardware/SensorManager.java)
方法如下
1 public Sensor getDefaultSensor(int type) {
2 //获取到所有sensor列表
3 List<Sensor> l = getSensorList(type);
4 boolean wakeUpSensor = false;
5 //以下几种type只能返回wake-up的sensor
6 if (type == Sensor.TYPE_PROXIMITY || type == Sensor.TYPE_SIGNIFICANT_MOTION ||
7 type == Sensor.TYPE_TILT_DETECTOR || type == Sensor.TYPE_WAKE_GESTURE ||
8 type == Sensor.TYPE_GLANCE_GESTURE || type == Sensor.TYPE_PICK_UP_GESTURE ||
9 type == Sensor.TYPE_WRIST_TILT_GESTURE || type == Sensor.TYPE_DYNAMIC_SENSOR_META) {
10 wakeUpSensor = true;
11 }
12
13 for (Sensor sensor : l) {
14 if (sensor.isWakeUpSensor() == wakeUpSensor) return sensor;
15 }
16 return null;
17 }
这个方法刚开始把我搞蒙了,也没看明白,所以在此记录下。在看我的分析之前不妨仔细看一下代码,看看自己分析的对不对。
其实代码很简单,就围绕一个思想:从sensor列表中选出某个类型为type的sensor
但是,每个type可能会对应两个sensor
比如加速度传感器,会有一个wake-up类型的加速度传感器,也会有一个non-wake类型的加速度传感器。至于wake-up的概念参见上文
也就是说同一个type的传感器根据wake-up的模式不同,会注册两种,那么系统会返回哪一种呢?就是这个代码决定了。
如果是指定的这几种type,那么就返回wake-up类型的传感器,否则返回non-wake的传感器
那么又有人说了,我就想要wake-up的传感器,怎么办?
别急,google大佬说了,你想要的都给你。
sensorManager还提供了一个同名方法,可以传入一个bool值,来决定是否是wake-up
1public Sensor getDefaultSensor(int type, boolean wakeUp) {
欧了,你可以获取到指定type和指定wakeUp参数的sensor了
如果你觉得仅仅追到这儿就可以了,那我多问一句,sensor列表哪儿来的?
有疑问,怎么办? 继续追,这才是故事的开头啊。
break一点点儿的追下去,你会发现,java层的代码流程是这样滴
1//获取sensor列表的java层的流程
2-->getSensorList(SensorManager)
3-->getFullSensorList(SensorManager中的抽象方法)
4-->getFullSensorList(SystemSensorManager继承自sensorManager)
5-->nativeGetSensorAtIndex(SystemSensorManager)
6-->nativeGetSensorAtIndex(android_hardware_SensorManager.cpp)
上边儿有很重要的一句话SystemSensorManager继承自SensorManager。
如果你看源码就会发现SensorManager是一个abstract抽象类,根本就没办法创建对象
1@SystemService(Context.SENSOR_SERVICE)
2public abstract class SensorManager
那我们在使用时getSystemService获取到的是谁?当然SystemSensorManager的对象了。不信??可以验证下
就按照getSystemService的逻辑,看看获取到的是什么对象
1//出自/frameworks/base/core/java/android/app/SystemServiceRegistry.java
2registerService(Context.SENSOR_SERVICE, SensorManager.class,
3 new CachedServiceFetcher<SensorManager>() {
4 @Override
5 public SensorManager createService(ContextImpl ctx) {
6 return new SystemSensorManager(ctx.getOuterContext(),
7 ctx.mMainThread.getHandler().getLooper());
8}});
很明显了,系统在注册时使用的就是SystemSensorManager了。
ok,以上都是题外话,来继续分析刚才的流程
怎么办?搞来搞去到了jni,而jni只能算是一个native和java之前的相互调用的接口工具而已,这没啥具体实现。
还得往下走,很久之前我一般看到jni层就不再往下研究了,想想错过了多少风景,哎
继续下去,可以看到最终获取到的是SensorService中的sensorList对象的数据
1//native层代码流程
2-->getSensorList(/frameworks/native/libs/sensor/SensorManager.cpp)
3-->getSensorList(/frameworks/native/services/sensorservice/SensorService.cpp)
4-->getUserSensors(/frameworks/native/services/sensorservice/SensorList.cpp)
但是,这个sensorlist哪儿来的呢?是在sensorService中注册sensor时添加的,也就是registerSensor方法中给sensorList添加的值。
由此,也可以看到,registerSensor的作用是什么?就是填充sensor列表,提供给app使用
那么registerSensor何时触发的呢?在sensorService的onFirstRef方法中出发
也就是创建sensorService的强引用即创建sensorService对象时会触发onFirstRef方法,进而去注册sensor,进而填充sensor列表供应用使用
ok,稍歇一下
总结一下目前的分析
从app层-->framework的java层-->framework的native层的传感器列表加载基本已经完事儿了。
正向总结一下就是:
在创建sensorservice的强引用对象时,会获取到本机设备所有的sensor,通过registerSensor方法将sensor添加到sensorList中。
到这儿,sensorService的sensorlist工作就完成了
在创建SystemSensorManager对象时,会触发nativeCreate创建native层的sensorManager引用
并通过sensorManager以binder跨进程通信的方式获取到sensorService(位于systemserver进程)中的sensorList列表中对于app可用的sensor.并保存在mFullSensorList中。
至此,SystemSensorManager的sensor列表工作完成
最后,是app通过framework的java层的SensorManager引用来获取到所需要的sensor,整个从framework(native,jni和java)到app的流程就是这样。
基本上是sensorService加载list,sensorManager使用list.符合server/client的设计
如果你对hal层不感兴趣,到这儿就可以了,基本上你也看到了binder通信机制,以及sensor的framework代码结构了。
但,我的选择是继续前进,冲鸭!!!
break
一个传感器列表为什么为那么深入?其实很好理解
传感器是有硬件实体接入的,当然也有虚拟出来的,但虚拟的也是靠硬件传感器融合出来的,所以咧?
你不追到hal层,安能知道sensor列表究竟是怎么从硬件变为软件列表的呢?
SensorService在注册sensor时也是需要遍历一个sensor列表,来一一注册的
那么这个sensor列表哪儿来的呢?
1void SensorService::onFirstRef() {
2//代码省略......
3 SensorDevice& dev(SensorDevice::getInstance());
4//代码省略.......
5 ssize_t count = dev.getSensorList(&list);
6//代码省略......
7}
可以看到从SensorDevice中过来的。SensorDevice代码路径:
/frameworks/native/services/sensorservice/SensorDevice.cpp
这个是framework层的最后一道防线,也就是在sensordevice中就直接和hal层代码交互
其实就是和hal层的Sensors服务交互,利用的也是跨进程通信的方式,叫做hidl,和aidl类似,叫做hal层接口描述语言。
所以sensorDevice相当于hal层sensors服务的client端,SensorDevice的作用就是跨进程调用sensors服务的方法。
sensors服务代码路径:/hardware/interfaces/sensors/1.0/default/Sensors.cpp
来看看具体sensors服务怎么做的
1Return<void> Sensors::getSensorsList(getSensorsList_cb _hidl_cb) {
2 //代码省略...
3 mSensorModule->get_sensors_list(mSensorModule, &list)
4 //代码省略...
5}
恩?看起来还是很好理解的,从module中获取到sensor列表。
如果对hal层稍微了解的话,应该大致能明白,hal层属于硬件抽象层,作用就是把硬件模块抽象成一个模块hw_module_t和hw_device_t
之后framework就可以借助hal层抽象出来的模块来操作硬件层了。
hal层其实也不是直接和驱动交互,而是去加载驱动生成的so包,从so包中读取数据
这个hal层存在的好处我就不废话了。
当然继续再往下追,你就可以看到hal层是如何把硬件驱动抽象成module的,这个实现在multihal.cpp中,代码路径为:/hardware/libhardware/modules/sensors/multihal.cpp。感兴趣的可以看下
static int module__get_sensors_list(__unused struct sensors_module_t* module,
struct sensor_t const** list) {
ALOGV("module__get_sensors_list start");
//加载sensor列表
lazy_init_sensors_list();
*list = global_sensors_list;
ALOGV("global_sensors_count: %d", global_sensors_count);
for (int i = 0; i < global_sensors_count; i++) {
ALOGV("sensor type: %d", global_sensors_list[i].type);
}
return global_sensors_count;
}
总结来看,整个sensor的架构涉及到了app层->framework层->hal层->驱动层
其中关键文件有四个
-
SensorManager:提供三方应用api,也就是app使用sensor的能力。当然很多具体实现在systemSensorManager中
-
SensorService:为sensorManager提供framework层native的sensor服务
-
SensorDevice:framework层的最后一道屏障,作为hal层sensors服务的client端,获取到hal层的相关信息
-
Sensors:hal层的服务,加载sensor硬件模块,对framework层提供接口
其他 比如sensor.cpp等辅助类型的文件就不再描述了。说一下我研究过程中遇到的问题
按照以上分析,有两次跨进程通信(排除掉servicemanager的那一次),那么就应该涉及到三个进程:app进程、systemServer进程、sensors服务进程。
到这儿我有一个题外话的问题了。
至于区分是不是位于app进程我可以理解,但是究竟怎么规定这个服务是不是在systemserver进程的呢?
属于systemserver的就不说了,怎么判断不属于?也即是说为什么sensorService就是systemServer进程,sensors就是另一个进程?
当然会有人说,从systemServer开启的服务就是systemserver进程的,不是的话就不是sytemserver进程,那么不是的话是属于什么进程?怎么规定的?
看当前目录下Android.mk(若没有则看Android.bp)的文件,看local_init_rc(init_rc)字段是否有定义。
比如hal层的sensors服务,它的编译脚本有这么一句话
1init_rc: ["android.hardware.sensors@1.0-service.rc"],
那就表示,文件android.hardware.sensors@1.0-service.rc中指定了进程相关的信息。而且该进程会在init进程中启动
1service vendor.sensors-hal-1-0 /vendor/bin/hw/android.hardware.sensors@1.0-service
2 class hal
3 user system
4 group system wakelock
5 capabilities BLOCK_SUSPEND
6 rlimit rtprio 10 10
基本上能看懂一些,进程的user是system,属于的进程组为system和wakelock.capabilitied表示能力rlimit是当前文件规定的程序可以打开的最大文件数和系统规定的可以打开的最大文件数
最终呈现出来的进程名如下
1$adb shell ps |grep sensor
2system .. android.hardware.sensors@1.0-service
ok,暂时到这儿吧sensorList基本流程搞清楚了,也顺便学习了一下如何区分进程
近期也解决了很多传感器的问题,才发现总结这件事儿真是帮了我的大忙。
源码那么多,我们不能寄希望于自己的脑子能够记住所有流程,有了笔记记录的流程,解决问题时会省去很多时间
原创声明
本文为作者原创文章,未经本人同意,禁止转载和挪作他用
https://mp.weixin.qq.com/s/1qYYn_9x6a1FOeKgNt2pBg