我们在android中经常会注册sensor然后监听sensor的数据来做一些特殊的功能,但是之前一直没有关注过整个注册的流程,本文将会告诉你高通855平台中sensor的整个完整的注册流程是什么样子的,先大概总结一下:
APP进程创建一个SensorEventQueue,等待接收system_server发送过来的数据
system_server进程会保存app端的SensorEventQueue,有一个线程会循环的读取[email protected]进程发送过来的消息,当有消息来到时会往APP端的SensorEventQueue中发送sensor 数据,
[email protected]进程会初始化一个socket和子系统通信,并且创建一个线程一直等待BP发送上来的数据,当接收到数据时会发给system_server。
注册流程图参考绿色部分
|
首先我们先写一个SensorEventListener,之后sensor有数据之后会回调onSensorChanged/onAccuracyChanged,先不管怎么回调的,先看看注册过程
NO.1获取对应type的sensor
|
NO.1.1 这里是从所有的sensor中获得对应type的sensor.
|
// NO.1.2 一般sensor有一个wakeup sensor,一个non wakeup sensor,我们返回wakeup sensor。
若是注册Non-Wakeup的sensor的话,在系统suspend时,不会有任何数据上报.若是注册Wakeup的sensor的话,系统会被wakelock住,根本睡不下去,这时系统功耗非常高
NO.2注册sensor
|
sensor的模式类型有:
REPORTING_MODE_CONTINUOUS 常用的都是CONTINUOUS类型,例如light,acc,gryo等等
REPORTING_MODE_ON_CHANGE
REPORTING_MODE_ONE_SHOT 例如:计步
REPORTING_MODE_SPECIAL_TRIGGER
NO2.2 新建一个SensorEventQueue
|
接下来我们看看是怎么回调的
NO2.2.1调用父类方法
|
NO2.2.1.1初始化nativeInitBaseEventQueue
|
NO2.2.1.1.2创建natvive层对应的queue
|
创建sensorEventConnection
|
这里思创建一个SensorEventConnection,并把它添加到mActiveConnections中,当SensorService的主线程中收到sensor事件后会遍历所有的mActiveConnections,调用它们的sendEvents方法,然后在receiver中的handleEvent会响应该事件,你可以用JAVA层的Handler来理解这个sendEvents,和handleEvent,但是它的实现和Handler不一样,这里不深入讨论了,继续receiver的代码
NO2.2.1.1.2 新建一个receiver,后边会收到消息后会通过eventQWeak回调java层的dispatchSensorEvent,eventQWeak是java层的mNativeSensorEventQueue,后边回调会用到
|
这里当handleEvent被调用的时候会通过前边传入的参数eventQWeak回调java层对应的BaseEventQueue,eventQWeak实际上就是java层的BaseEventQueue对象。
|
这里enable sensor后会把connection添加到mActiveConnections中
|
NO2.2 新建SensorEventQueue就说完了,这里主要是创建一个SensorEvent消息队列,SensorService的主线程当收到sensor事件后会通过遍历activeConnections调用sendEvents将事件发给所有的receiver,然后会通过JNI回调对应对象的dispatchSensorEvent,最后回调onSensorChanged。接下去我们继续说NO2.3 添加sennsor
NO2.3 添加sennsor
|
这一步主要是往下调用,使能sensor,接下去将进入native层的nativeEnableSensor
|
然后一步步传递会走到
|
我们跳过一些步骤直接看到SensorDevice.cpp
|
system_server进程的代码到这里就结束了,往下就是[email protected]进程的了
我们跟着时序图再跳过一些传递的步骤来到sensors_hal.cpp中的activate
|
我们继续看到NO.3调用的activate
|
NO.3.1 创建一个和bp通信的连接,省略一些步骤直接看到qmi通信的核心文件qmi_cci_xport_qrtr.c
|
NO.3.2 创建一个data_msg_reader_thread去接收BP发上来的数据
|
当这里读到数据之后就要开始分发了,将在下一文章中说
看了这么多可能还是是懂非懂的话,可以亲自动手来调试一下,调试的关键点我都已经帮你准备好了,你只需要准备好gdb就可以动手调试了吗,如果gdb你不会用的话,后续我会给你更新一个gdb脚本,运行脚本就能直接attach上对应的进程了
1.APP进程完整调用栈
①gdb断点system_server端:b frameworks/native/libs/sensor/ISensorEventConnection.cpp:138,并继续运行
②打开写好的sensor APP
③当gdb停下时,打印APP的调用栈(kill -3)
app端调用栈如下:
|
2.system_server进程完整调用栈
①gdb断点[email protected]进程:b vendor/qcom/proprietary/commonsys-intf/qmi-framework/qcci/src/qmi_cci_xport_qrtr.c:621,并继续运行
②打开写好的sensor APP
③当gdb停下时,打印system_server的调用栈(kill -3)
调用栈如下:
|
[email protected]进程完整调用栈
①gdb断点[email protected]进程:b vendor/qcom/proprietary/commonsys-intf/qmi-framework/qcci/src/qmi_cci_xport_qrtr.c:621,并继续运行
②打开写好的sensor APP
③当gdb停下时,bt打印调用栈
|