此文纯属个人笔记,没什么章法,请看官见谅!
来源:Android 2.3 Source Code Ril Driver 分析 + 前辈总结
看官最好是完整的看过源代码,还有就是稍微熟悉Modem AT command才行哦,不然就云里雾里了!
OK,开始了!
R:采用AT_CMD代号,及相应AT参数组合成struct通过socket 发送
R:RILd 为守护进程,调用libRIL.so 和reference-ril.so库
一、结构图
Andrid Ril 结构图(有点丑,个人理解code画的,请指教)
FROM network(不太看得清楚,不过感觉这个图很有用的)
二、ril_event datastructure
不得不提这个她。当我第一眼见到她就亢奋了,真的。对于我这刚走出校园,没见过什么大世面的菜鸟来说,这个结构既熟悉又陌生。能在真正的Code里见到callback func&双向链表&……(有点冲动,不多说了)。让我想起了正在做的windows Mobile 6.5的RIL项目,WMRIL Driver采用的是简单队列来存储UI和Modem发来的各种command,而且二者顺序不能打乱,乱了就不得了了。(回想起来,之前有个BUG就因为顺序原因,照成Modem 睡眠后,很难被唤醒,唤醒了又注册不上网络,这个BUG我们几个解了N天才找到原因,然后五分钟就解了。哎!Microsoft的Code太烂,怪不得不敢公开)。
继续,Ril Event struct是个双链表结构。在整个Android Ril Driver 运行中发挥了非常重要的作用,RIL的整个架构也是根据其来建立的,一定要贴出来大家欣赏一番。
structril_event {
structril_event*next;
intfd;
int index;
bool persist;
structtimevaltimeout;
ril_event_cbfunc; //callback func
void *param;
};
很简单,不解释这个struct了。
三、RIL Driver文件功能安排(重前辈的总结中二次开发的)
Ø 文件ril_commands.h:列出了telephony可以接收的solicited命令;每个命令对应的处理函数;以及命令响应的处理函数。
Ø 文件ril_unsol_commands.h:列出了telephony可以接收的unsolicited事件类型;对每个事件的处理函数;以及WAKEType:定义是否占用唤醒锁
Ø 文件ril_event.h/cpp:定义事件数据结构,及事件处理函数,ril_event_loop ril_event_set函数建立新的evnet,设置其callbackfunction
listenCallback监视客户端commandprocessCommandsCallback
eventLoopprocessWakeupCallback
RIL_register监视客户端连接请求debugCallback
internalRequestTimedCallbackuserTimerCallback
没有发现readerloop中的event
Ø 文件ril.cpp:
RIL_register函数:打开监听端口,接收来自客户进程的命令请求(s_fdListen=android_get_control_socket(SOCKET_NAME_RIL);),当与某客户进程连接建立时,调用listenCallback函数;创建一单独线程监视并处理所有事件源(通过ril_event_loop)
下面几个函数太重要了,包含了UI
listenCallback函数:当与客户进程连接建立时,此函数被调用。此函数接着调用processCommandsCallback处理来自客户进程的命令请求
processCommandsCallback函数:具体处理来自客户进程的命令请求。对每一个命令,ril_commands.h中都规定了对应的命令处理函数(dispatchXXX)
processCommandsCallback会调用这个命令处理函数进行处理。
dispatch系列函数:此函数接收来自客户进程的命令己相应参数,并调用onRequest进行处理。
RIL_onUnsolicitedResponse函数:将readerloopUnsolicited事件响应数据封装(通过调用responseXXX)后传给客户进程。这个函数当然就是处理Modem
自行发来的AT啦!比如 “RING” 之类的了,这个函数是要根据对应的Modem做相应修改的。
RIL_onRequestComplete函数:将命令的最终solicited响应结构封装(通过调用responseXXX)后传给客户进程。
responseXXX系列函数:对每一个命令,都规定了一个对应的response函数来处理命令的最终响应, 处理modem运行AT后返回的数据。这个也是要根据实际Modem自己定制的哦。
Ø 文件reference-ril.c:此文件核心是两个函数:onRequest和onUnsolicited
onRequest 函数:在这个函数里,对每一个RIL_REQUEST_XXX请求,都转化成相应的ATcommand,发送给modem,然后睡眠等待。当收到此ATcommand的最终响应后,线程被唤醒,将响应传给客户进程(RIL_onRequestComplete->sendResponse)。
onUnsolicited函数:这个函数处理modem的各种自发事件,如网络信号变化,拨入的电话,收到短信等。然后将时间传给客户进程(RIL_onUnsolicitedResponse ->sendResponse)
Ø 文件atchannel.c:负责向modem读写数据。其中,写数据(主要是ATcommand)功能运行在主线程中,读数据功能运行在一个单独的读线程中。
at_send_command_full_nolock函数:运行在主线程里面。将一个ATcommand命令写入modem后进入睡眠状态(使用pthread_cond_wait或类似函数),直到modem读线程将其唤醒。唤醒后此函数获得了ATcommand的最终响应并返回。
readerLoop函数: 运行在一个单独的读线程里面,负责从modem中读取全部数据,然后调用isSMSUnsolicited函数&processLine函数处理数据,分析响应类型Unsolicited / solicited,然后唤醒(pthread_cond_signal)睡眠
差不多了,没写太多,笔记嘛,记重点就行。
因为没做过Android RIL相关项目,错误肯定是有的,大家多多指正!