数据分发的流程你就是注册时序的一个逆过程,上一篇文章中说到了注册,[email protected]进程最后会创建一个data_msg_reader_thread线程在不断的监听数据,当收到数据后,数据会逐步往APP传递,传递的进程是[email protected]>system_server->APP,看了这篇文章你会大概了解这个sensor数据分发的流程。
数据分发流程见图上紫蓝色部分:
我们先看到qmi的data_msg_reader_thread线程,APP每注册一个新的sensor都会创建一个data_msg_reader_thread线程,一个sensor只有一个data_msg_reader_thread线程,我们在之前注册的文章中SensorDevice.cpp部分说过如果这个sensor是第一次注册,那么他会继续调用activate,否则不会继续调用activate了,说明不会在次初始化qmi 连接,当然也不会再次创建线程了。这个线程的作用是监听某个类型的sensor数据,如果我们注册了10个不同的sensor,那么就会有是个data_msg_reader_thread线程。它们在这里会分别会通过socket接收BP发送上来的sensor数据,然后往上分发
|
这里主要是poll等待bp数据到来,到来之后通过socket读取bp发送过来的数据存到buf中,然后再通过qmi_cci_xport_recv方法将buf继续向上传递
|
我们跳过一些步骤直接看到init_sensors中,qmi的层层回调最终会回到在init_sensors中的:
auto cb = [this](const auto& event, auto wakeup) { _event_queue.push(event, wakeup); };
这里最后会向_event_queue中push event
|
这里把_event_queue.push后会激活writerTask线程,writerTask线程是在sensorservice初始化的时候在addSubHwDevice方法中创建的,这个线程专门用来等待qmi传递过来的数据,当有数据之后,会调用 pthread_cond_broadcast(&data_available_cond); 激活另外一个正在等待的线程关系图如下:
调用栈流程图:
我们先看writerTask线程
|
|
我们看到system_server 通过binder call过来的线程:
|
这里是等待线程被唤醒,然后读取之前记录在queue中的mData,然后返回到system_server进程。
我们看到system_server的sensor线程对应的代码:
|
looper wake后会调用handleEvent:
|
|
最终会回调onAccuracyChanged和onSensorChanged,整个分发流程到此就结束了
看了这么多可能还是是懂非懂的话,可以亲自动手来调试一下,调试的关键点我都已经帮你准备好了,你只需要准备好gdb就可以动手调试了吗,如果gdb你不会用的话,后续我会给你更新一个gdb脚本,运行脚本就能直接attach上对应的进程了
[email protected]进程完整调用栈
①gdb断点system_server端:b vendor/qcom/proprietary/sensors-see/sensors-hal/framework/sensors_hal.cpp:190,并继续运行
②打开写好的sensor APP
③当gdb停下时,bt打印调用栈
[email protected]端push数据到event_queue中调用栈如下:
|
2.system_server进程完整调用栈
|