2012-03-24
本文介紹了AndroidRIL的總體架構(gòu),具體分析了本地庫(kù)的實(shí)現(xiàn)[c/cpp部分]
一、總體架構(gòu)
Android RIL (Radio Interface Layer)提供了Telephony服務(wù)和Radio硬件之間的抽象層。RIL負(fù)責(zé)數(shù)據(jù)的可靠傳輸、AT命令的發(fā)送以及response的解析。一般的,應(yīng)用處理器(AP)通過(guò)AT命令集與無(wú)線通訊模塊(基帶/BP)通信。把標(biāo)準(zhǔn)的GSM27.007中常用的如Dial這些主動(dòng)請(qǐng)求的操作稱之為 request ;另一類GSM主動(dòng)上報(bào)的例如信號(hào)強(qiáng)度、基站信息、來(lái)短信等,稱之為 unsolicited response 。
二、實(shí)現(xiàn)文件分布
SMS/MMS, call, …
Telephony的應(yīng)用層實(shí)現(xiàn)在具體的apps中。Call在packages/apps/Phone中;SMS/MMS在packages/apps/Mms中;網(wǎng)絡(luò)選擇等在packages/apps/Settings中。
android.telephony.*
Telephony的JavaFramework代碼,供上層使用
com.android.internal.telephony.*
Telephony的JavaFramework代碼的內(nèi)部實(shí)現(xiàn),該包是隱藏的,外面無(wú)法訪問(wèn)。
hardware/ril/include/telephony/ril.h
本地代碼的頭文件
hardware/ril/libril
ril本地庫(kù)的實(shí)現(xiàn)源代碼,生成libril.so
hardware/ril/rild
ril守護(hù)進(jìn)程rild的實(shí)現(xiàn)源代碼,生成可執(zhí)行文件rild
hardware/ril/reference-ril
ril實(shí)現(xiàn)庫(kù)的參考實(shí)現(xiàn)源代碼,生成libreference-ril.so
針對(duì)不同的硬件平臺(tái)可以仿照這個(gè)來(lái)實(shí)現(xiàn)具體的功能庫(kù)。
三、ril初始化
1.Rild解析ril的實(shí)現(xiàn)庫(kù)<rillibPath>——可以通過(guò)命令行或property來(lái)指定。
Rild在init.rc中可以通過(guò)命令行參數(shù) -l <rillibPath> 指定ril的具體實(shí)現(xiàn)庫(kù);
如果命令行中未指定實(shí)現(xiàn)庫(kù),通過(guò)property_get(“ rild.libpath ”, …)獲取實(shí)現(xiàn)庫(kù)。
而,在模擬環(huán)境下的話,就用/system/lib/libreference-ril.so,這也是上節(jié)所提到的libreference-ril.so最終被放的路徑。
2.通過(guò)dlopen(<rillibPath>, )加載ril實(shí)現(xiàn)庫(kù);
3.調(diào)用libril中的RIL_startEventLoop()開(kāi)啟并確保 eventLoop線程 已經(jīng)啟動(dòng);
4.通過(guò)dlsym()獲取<rillibPath>中定義的RIL_Init()函數(shù)。
5.獲取RIL_Init()所需的參數(shù)——可以通過(guò)命令行或property來(lái)指定。
Rild在init.rc中可以通過(guò)命令行參數(shù) -- 指定RIL_Init的參數(shù);
如果命令行中未指定實(shí)現(xiàn)庫(kù),通過(guò)property_get(“ rild.libargs ”, …)獲取參數(shù)。
6.由4&5獲取的函數(shù)以及參數(shù),執(zhí)行 RIL_Init ()開(kāi)始 mainLoop線程 ,并獲取RIL_RadioFunctions;
7.以6獲取的RIL_RadioFunctions為參數(shù),執(zhí)行l(wèi)ibril中的 RIL_Register ()保留這些callback函數(shù)到s_callbacks,開(kāi)啟命名Socket“rild”,接受上層的Socket指令。
時(shí)序圖如下圖所示:
注意:圖中的序號(hào)跟上面描述的步驟并不是一一對(duì)應(yīng)的。
在上面的時(shí)序中,有幾個(gè)重要的數(shù)據(jù): s_rilEnv : RIL_Env定義在rild中,但函數(shù)的具體實(shí)現(xiàn)是在標(biāo)準(zhǔn)庫(kù)libril.so中,注冊(cè)給實(shí)現(xiàn)庫(kù),供RIL實(shí)現(xiàn)庫(kù)調(diào)用; s_callbacks : RIL_RadioFunctions定義在reference-ril中,實(shí)現(xiàn)Request等操作。
四、Request過(guò)程
初始化過(guò)程步驟3啟動(dòng)的eventLoop會(huì)調(diào)用ril_event_loop()處理Request請(qǐng)求。
通過(guò)select()多路選擇Socket,偵聽(tīng)是否有Java層到來(lái)的Socket請(qǐng)求。執(zhí)行:
ril_event_loop() ->
-> processTimeouts()
-> processReadReadies()把ril_event從watch_table[]移到pendling_list
-> firePending() -> ev->func() [listenCallback()[ril.cpp]]
-> record_stream_new()新創(chuàng)建一個(gè)RecordStream
-> 收到完整的Request后,執(zhí)行processCommandsCallback()
-> processCommandBuffer () [ril.cpp]
具體的執(zhí)行都在processCommandBuffer()
Ril.cpp中定義了s_comamnds:CommandInfo[]
processCommandBuffer()中,通過(guò)request的索引,找到s_commands中的CommandInfo,然后通過(guò)CommandInfo的dispatchFunction,具體執(zhí)行dispatch操作。
可以打開(kāi)ril_commands.h中看具體某個(gè)Request的dispatch函數(shù)。
dispatchXYZ()是一系列對(duì)特定參數(shù)的Reqeust的封裝,看dispatchString(Parcel&p, RequestInfo *pRI)的實(shí)現(xiàn):
解析出參數(shù),通過(guò)s_callbacks.onRequest()調(diào)用reference-ril具體實(shí)現(xiàn)庫(kù)中的onRequest的實(shí)現(xiàn)。[s_callbacks是在第三節(jié)中初始化時(shí)注冊(cè)保留的]
Reference-ril中的onRequest()有一個(gè)很大的switch… case語(yǔ)句來(lái)處理各種request。
requestSendSMS()中調(diào)用at_send_command_sms()用“+CMGS”發(fā)送短信,并獲取返回值。
requestSendSMS()中調(diào)用 RIL_onRequestComplete (t,e: RIL_Errno)完成Request。
五、Response過(guò)程
Response有Solicited Response也就是上節(jié)講的Request的響應(yīng),另外還有一種就是主動(dòng)上報(bào)的unsolicitedresponse,比如來(lái)電話,來(lái)短信等信息。
5.1 solicited response
對(duì)于Solicited response,上節(jié)中最后調(diào)用的是RIL_onRequestComplete(),reference-ril中該函數(shù)調(diào)用s_rilenv->OnRequestComplete()。從第三節(jié)的初始化知道,具體的實(shí)現(xiàn)是在ril.cpp中RIL_onRequestComplete()里。
在RIL_onRequestComplete()中,
如果“ril_commsnds.h”中定義的該CommandInfo中有response函數(shù),完成對(duì)responseFunction()的調(diào)用;
轉(zhuǎn)換ril定義的響應(yīng)信息結(jié)構(gòu),調(diào)用sendResponse(),將響應(yīng)結(jié)果通過(guò)Socket反饋到上層。
5.2 unsolicited response
第三節(jié)步驟六開(kāi)始的mainLoop中會(huì)通過(guò)at_open()把onUnsolicited()傳遞給AtChannel。AtChannel的at_open()中開(kāi)啟readerLoop線程。
readerLoop()中:
readLine() -> processLine()對(duì)Unsolicited message調(diào)用handleUnsolicited()作出處理;而handleUnsolicited()中回調(diào)reference-ril中注冊(cè)的onUnsolicited()函數(shù)。
reference-ril的onUnsolicited()中對(duì)各種特殊指令作出處理之后,調(diào)用初始化時(shí)[第三節(jié)]注冊(cè)的RIL_Env中的RIL_onUnsolicitedResponse(),最終實(shí)現(xiàn)是在ril.cpp的RIL_onUnsolicitedResponse()。
同Request一樣,Ril.cpp中定義了s_comamnds:CommandInfo[]
RIL_onUnsolicitedResponse中,通過(guò)unsolResponseIndex,找到s_unsolResponses中的UnsolResponseInfo,然后通過(guò)UnsolResponseInfo的WakeType決定喚醒手機(jī)的WakeLock,再通過(guò)responseFunction,具體執(zhí)行response操作。
可以打開(kāi)ril_unsol_commands.h中看具體某個(gè)Unsolicitedresponse的定義。
最后,unsolicited response與solicited response一樣,也是通過(guò)調(diào)用sendResponse(),通過(guò)Socket反饋到Java上層。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
