Android中RIL層詳細(xì)分析_第1頁
Android中RIL層詳細(xì)分析_第2頁
Android中RIL層詳細(xì)分析_第3頁
Android中RIL層詳細(xì)分析_第4頁
Android中RIL層詳細(xì)分析_第5頁
已閱讀5頁,還剩13頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、Android的電話功能介紹一一整個RIL文件夾的分析介紹本文檔對AndroidRIL部分的內(nèi)容進(jìn)行了介紹,其重點(diǎn)放在了AndroidRIL的原生代碼部分。包括四個主題:1 .AndroidRIL框架介紹2 .AndroidRIL與WindowsMobileRIL3 .AndroidRILporting4 .AndroidRIL的java框架在本文木中將Android代碼中的重要模塊列出進(jìn)行分析,并給出了相關(guān)的程序執(zhí)行流程介紹,以加深對模塊間交互方式的理解。對于java代碼部分,這里僅進(jìn)行簡單的介紹。如果需要深入了解,可以查看相關(guān)參考資料。本文檔中還對AndroidRIL的Porting部分內(nèi)

2、容進(jìn)行了描述和分析。針對對unix操作系統(tǒng)環(huán)境并不熟悉的讀者,本文檔中所涉及到的相關(guān)知識包括:UnixfilesystemUnixsocketUnixthreadUnix下I/O多路轉(zhuǎn)接以上信息可以在任意一份描述Unix系統(tǒng)調(diào)用的文檔中找到。術(shù)語:fdpipecondttyunsolicitedresponseeventloopinit.rcHAL1 .AndroidRIL框架介紹Linux文件描述符Linux管道一般是conditionvariable的縮寫通常使用tty來簡稱各種類型的終端設(shè)備被動請求命令來自basebandandroid的消息隊列機(jī)制,由Linux的系統(tǒng)調(diào)用select(

3、)實現(xiàn)init守護(hù)進(jìn)程啟動后被執(zhí)行的啟動腳本。硬件抽象層(HardwareAbstractionLayer,HAL)1.1 AndroidRIL概況RIL在AndroidAndroidRIL提供了無線硬件設(shè)備與電話服務(wù)之間的抽象層。下圖展示了體系中的位置。ApplicationsApplicationFrameworkPtioneRIL依va,androkytetepho單串mLibraries(userspace)LinuxKernelBasebandUnixJGontrpIPacketDriverPPP,kvexamplei'commands1VendorRULsysteHrMil

4、ibri-vendor.soLinuxIPSUCkandroid的ril位于應(yīng)用程序框架與內(nèi)核之間,分成了兩個部分,一個部分是rild,它負(fù)責(zé)socket與應(yīng)用程序框架進(jìn)行通信。另外一個部分是VendorRIL,這個部分負(fù)責(zé)向下是通過兩種方式與radio進(jìn)行通信,它們是直接與radio通信的AT指令通道和用于傳輸包數(shù)據(jù)的通道,數(shù)據(jù)通道用于手機(jī)的上網(wǎng)功能。對于RIL的java框架部分,也被分成了兩個部分,一個是RIL模塊,這個模塊主要用于與下層的rild進(jìn)行通信,另外一個是Phone模塊,這個模塊直接暴露電話功能接口給應(yīng)用開發(fā)用戶,供他們調(diào)用以進(jìn)行電話功能的實現(xiàn)。1.2 AndroidRIL目錄

5、結(jié)構(gòu)Android的RIL模塊位于Android/hardware/ril文件夾,有三個子模塊:rild,librilreference-ril所在目錄結(jié)構(gòu):/hardware/ril/|-ril(無線電抽象層)|-include(頭文件)|-libril(庫)|卜-reference-cdma-sms(cdma短信參考)|卜-reference-ril(ril參考)|-rild(ril后臺服務(wù)程序)hardware/ril$lsincludelibrilreference-cdma-smsreference-rilrild1 .hardware/ril/rild$lsAndroid.mkMO

6、DULE_LICENSE_APACHE2NOTICEradiooptions.crild.c2 .hardware/ril/include/telephony$lsril_cdma_sms.hril.h3 .hardware/ril/libril$lsAndroid.mkNOTICEril_event.hril.cpprilevent.cppril_commands.hril_unsol_commands.hMODULE_LICENSE_APACHE24 .hardware/ril/reference-cdma-sms$lsAndroid.mkreference-cdma-sms.crefer

7、ence-cdma-sms.h5 .hardware/ril/reference-ril$lsAndroid.mkatchannel.hat_tok.hmisc.hNOTICEatchannel.cattok.crilevent.hreference-ril.cmisc.cMODULE_LICENSE_APACHE2 include文件夾:包含RIL頭文件,最主要的是ril.h rild文件夾:RIL守護(hù)進(jìn)程,開機(jī)時被init守護(hù)進(jìn)程調(diào)用啟動,里面僅有main函數(shù)作為入口點(diǎn),負(fù)責(zé)完成RIL初始化工作。在rild.c文件中,將完成ril的加載過程,它會執(zhí)行如下操作:動態(tài)加載VendorRIL的.

8、so文件執(zhí)行RIL_startEventLoop()開啟消息隊歹U以進(jìn)行事件監(jiān)聽通過執(zhí)行VendorRIL的rilInit()方法來進(jìn)行VendorRIL與libril的關(guān)系建立。在rild文件夾中還包括一個radiooptions.c文件,它的作用是通過串口將一些radio相關(guān)的參數(shù)直接傳給rild來對radio進(jìn)行配置。 libril文件夾:在編譯時libril被鏈入rild,它為rild提供了event處理功能,還提供了在rild與VendorRIL之間傳遞請求和響應(yīng)消息的能力。Libril提供的主要功能分布在兩個主要方法內(nèi),一個是RIL_startEventLoop()方法,另一個是R

9、IL_register()方法RIL_startEventLoop()方法所提供的功能就是啟用eventLoop線程,開始執(zhí)行RIL消息隊列。RIL_register()方法的主要功能是啟動名為rild的監(jiān)聽端口,等待java端通過socket進(jìn)行連接。 reference-ril文件夾:Android自帶的VendorRIL的參考實現(xiàn)。被編譯成.so文件,由于本部分是廠商定制的重點(diǎn)所在。所以被設(shè)計為松散耦合,且可靈活配置的。在rild中通過opendl()的方式加載。librefrence.so負(fù)責(zé)直接與radio通信,這包括將來自libril的指令轉(zhuǎn)換為AT指令,并且將AT指令寫入radi

10、o中。reference-ril會接收調(diào)用者傳來的參數(shù),參數(shù)內(nèi)容為與radio的通信方式。如通過串口連接radio,那么參數(shù)為這種形式:-d/dev/ttySx1.3.AndroidRIL中的消息(event)隊列機(jī)制在AndroidRIL中,為了達(dá)到等待多路輸入并且不出現(xiàn)阻塞的目的,使用了IO多路復(fù)用機(jī)制。如果使用阻塞I/O進(jìn)行網(wǎng)絡(luò)的讀取寫入,這意味著假如需要同時從兩個網(wǎng)絡(luò)文件描述符中讀內(nèi)容,那么如果讀取操作在等待網(wǎng)絡(luò)數(shù)據(jù)到來,這將可能很長時間阻塞在一個描述符上,另一個網(wǎng)絡(luò)文件描述符不管有沒有數(shù)據(jù)到來都無法被讀取。一種解決方案是:如果使用非阻塞I/O進(jìn)行網(wǎng)絡(luò)的讀取寫入,在讀取其中一個網(wǎng)絡(luò)文件

11、描述符如果阻塞將直接返回,再讀取另外一個,這種方式的循環(huán)被稱之為輪詢。輪詢方式確實能解決進(jìn)行多路io操作時的阻塞問題,但是這種方法的不足之處是反復(fù)的執(zhí)行讀寫調(diào)用將浪費(fèi)cpu時鐘。I/O多路轉(zhuǎn)接技術(shù)在這里提供了另一種比較好的解決方案:它會先構(gòu)造一張有關(guān)I/O描述符的列表,然后調(diào)用select函數(shù),當(dāng)IO描述符列表中的一個描述符準(zhǔn)備好進(jìn)行I/O時,該函數(shù)返回,并告知可以讀或?qū)懩膫€描述符。AndroidRIL中消息隊列的核心實現(xiàn)思想就是這種I/O多路轉(zhuǎn)接技術(shù)。消息隊列機(jī)制的實現(xiàn)在ril_event.cpp中,其中被定義的ril_event結(jié)構(gòu)是消息的主體。每個ril_event結(jié)構(gòu),與一個fd句柄綁

12、定(可以是文件,socket,管道等),并且?guī)б粋€func指針,這個func指針?biāo)傅暮瘮?shù)是個回調(diào)函數(shù),它指定了當(dāng)所綁定的fd準(zhǔn)備好進(jìn)行讀取時所要進(jìn)行的操作。消息隊列的開始點(diǎn)為RIL_startEventLoop函數(shù)。RIL_startEventLoop在ril.cpp中實現(xiàn),它的主要目的是通過pthread_create(&s_tid_dispatch,&attr,eventLoop,NULL)建立一個dispatch線程,線程入口點(diǎn)在eventLoop.而在eventLoop中,會調(diào)ril_event.cpp中的ril_event_l00Po函數(shù),建立起消息隊列機(jī)制。ril

13、_event是一個帶有鏈表行為的struct,它最主要的成員一個是fd,一個是func:structril_eventstructril_event*next;structril_event*prev;intfd;intindex;boolpersist;structtimevaltimeout;ril_event_cbfunc;void*param;初始化一個新ril_event的操作是通過ril_event_set()來完成的,并通過ril_event_add()加入到消息隊列之中,add會把隊列里所有ril_event的fd,放入一個fd集合readFds中。這樣ril_event_l0

14、0P能通過一個多路復(fù)用I/O的機(jī)制(select)來等待這些fd。在進(jìn)入ril_event_loop()之前,在eventLoop中已經(jīng)創(chuàng)建和掛入了s_wakeupfd_event,它是通過pipe的機(jī)制實現(xiàn)的,這個管道fd的回調(diào)函數(shù)并沒有實現(xiàn)什么功能,它的目的只是為了讓select方法能返回一次,這樣select()方法就能重新跟蹤新加入事件隊列的fd和timeout設(shè)置。所以在添加新fd至UeventLoop時,往往不是直接調(diào)用ril_event_add,實際通常用rilEventAddWakeup來添加,這個方法除了會間接調(diào)用ril_event_add外,還會調(diào)用triggerEvLoo

15、p()函數(shù)來向s_fdWakeupWrite中寫入一個空字符,這樣select()函數(shù)會返回并重新執(zhí)行,新加入的文件描述符便得以被select()加載并跟蹤。如果在ril_event隊列中任何一個fd已經(jīng)準(zhǔn)備好,則進(jìn)入分析流程:processTimeouts(),processReadReadies(&rfds,n),firePending()其中firePending()方法執(zhí)行這個event的func,也就是回調(diào)函數(shù)。在AndroidRIL初始化完成后,將有幾個event被掛入到eventLoop中:1. s_listen_event:名為rild的socket,主要requese

16、t&response通道2. s_debug_event:名為rild-debug的socket,調(diào)試用requeset&response通道3. s_wakeupfd_event:無名管道,用于隊列主動喚醒這其中最為重要的event就是s_listen_event,它作為request與response的通道實現(xiàn)。在ril_event.cpp中還持有一個watch_table數(shù)組,一個timer_list鏈表和一個pending_list鏈表。watch_table數(shù)組的目的很單純,存放當(dāng)前被eventLoop等待的ril_event(非timerevent),供eventL

17、oop喚醒時使用。timer_list是存放timerevent的鏈表,在eventLoop喚醒時要對這些timerevent單獨(dú)進(jìn)行處理pending_list:待處理(對其回調(diào)函數(shù)進(jìn)行調(diào)用)的所有ril_event的鏈表。1.4. AndroidRIL中初始化流程分析Rild的初始化流程初始化流程從rild.c中的main函數(shù)開始,它被init守護(hù)進(jìn)行調(diào)用執(zhí)行:首先在main()函數(shù)內(nèi)會首先通過dlopen()函數(shù)力載VendorRIL(在自帶的參考實現(xiàn)中為librefrence_ril.so)。接著調(diào)用RIL_startEventLoop()函數(shù)來啟動消息隊列機(jī)制。調(diào)用librefren

18、ce_ril.so的RIL_Init()函數(shù)來進(jìn)行VendorRIL的初始化。RIL_Init()函數(shù)執(zhí)行后會返回一個RIL_RadioFunction結(jié)構(gòu)體,這個結(jié)構(gòu)體內(nèi)最重要的成員就是onRequest()方法。onRequest()方法會被dispatchFunction調(diào)用,也就是說dispatchFunction調(diào)用是程序流從rild轉(zhuǎn)入VendorRIL的分界點(diǎn)。RIL_register()函數(shù)將實現(xiàn)兩個目地,一個是將RIL_INIT中獲得的RIL_RadioFunction進(jìn)行注冊,rild通過此種方式保證自己持有一個RIL_RadioFunction實例,第二個是將s_fdLi

19、sten加入到消息隊列機(jī)制中,開啟s_fdListen的事件監(jiān)聽。VendorRIL的初始化流程:RIL_Init被調(diào)用后首先通過參數(shù)獲取硬件接口的設(shè)備文件或模擬硬件接口的socket。(參見上文中對reference-ril文件夾的介紹)接下來是創(chuàng)建mainLoop線程,并跳入到線程內(nèi)執(zhí)行。mainLoop會建立起與硬件的通信,然后通過read方法阻塞等待硬件的主動上報或響應(yīng)。mainLoop還會調(diào)用initlizeCallBack()S數(shù)來向radio發(fā)送一系列的AT命令來進(jìn)行radio的初始化設(shè)置工作。1.5. AndroidRIL中request流程分析上層應(yīng)用開始向rild通過soc

20、ket傳輸數(shù)據(jù)時,通過RIL消息隊列機(jī)制,s_listen_event的回調(diào)函數(shù)listenCallBack將會被調(diào)用,開始進(jìn)行數(shù)據(jù)流的分析與處理。接下來s_fdCommand=accept(s_fdListen,(sockaddr*)&peeraddr,&socklen),獲取傳入的socket描述符,也就是上層的javaRIL傳入的連接。然后,通過record_stream_new()建立起一個RecordStream,將這個record_stream與s_fdCommand綁定,RecordStream實際上是一個用于存放數(shù)據(jù)的結(jié)構(gòu)體,這個結(jié)構(gòu)體提供了一些操作類來保證這個

21、RecordStream所綁定的文件描述符被讀取時里面的數(shù)據(jù)會被完整讀取。一旦s_fdCommand中有數(shù)據(jù),它的回調(diào)函數(shù)processCommandsCallback()將會被調(diào)用,processCommandsCallback()通過record_stream_get_next阻塞讀取s_fdCommand上發(fā)來的數(shù)據(jù),直到收到一完整的requesto然后將其傳遞進(jìn)processCommandBuffer()函數(shù),processCommandBuffer()正式進(jìn)入了命令的解析部分。每個接收到的命令將以RequestInfo的形式存在。從socket過來的數(shù)據(jù)流,是Parcel處理過的序列

22、化字節(jié)流,在這里會通過反序列化的方法提取出來。最前面的是request號,以及token域(request的遞增序列號)。request是-"個CommandInfo,它ril_command.h中定義。接下來,這個RequestInfo會被掛入pending的request隊列,執(zhí)行具體的dispatchFunction(),進(jìn)行詳細(xì)解析。dispatchFunction方法有著多種實現(xiàn),如dispatchVoid,dispatchString,它們的調(diào)用取決于Parcel的參數(shù)傳入形式。比如說在dispatchDial方法中,Parcel對象將被解析為RIL_Dial結(jié)構(gòu)。這是d

23、isptachFunction的任務(wù)之一,它的另一個任務(wù)就是調(diào)用onRequest()方法,并將解析的內(nèi)容傳入onRequest()方法。從onRequest方法開始,程序控制流脫離了RILD,進(jìn)入到了VendorRIL中。onRequest方法會通過傳入的請求類型來調(diào)用指定的requestxxx()方法,requestxxx()方法則負(fù)責(zé)組裝AT指令并下發(fā)給at_send_command()方法集合中的一個,這個方法集合提供了針對不同類型AT指令的實現(xiàn),如單行AT指令at_send_command_singleline(),短信息指令at_send_command_sms()等。最后,執(zhí)行a

24、t_send_command_full(),再通過一個互斥的at_send_command_full_nolock()調(diào)用,完成最終的寫出操作,在writeline()中,寫出到初始化時打開的設(shè)備中。需要注意的是:at_send_command_full_nolock()在將指令寫入radio后并不會直接返回,而是通過條件變量等待響應(yīng)信息,得到響應(yīng)信息后會攜帶這些信息返回。具體流程可以參考下面的response流程分析。1.6. AndroidRIL中response流程分析AT的response有兩種,一種是unsolicitedo另一種是普通response,也就是命令的響應(yīng)。respon

25、se信息的獲取在readerLoop()中。由readline()函數(shù)讀取上來。讀取到的line將被傳入processLine()函數(shù)進(jìn)行解析,processLine()函數(shù)首先會判斷當(dāng)前的響應(yīng)是主動響應(yīng)還是普通響應(yīng),如果是主動響應(yīng),將調(diào)用handleUnsolicited()函數(shù),如果為普通響應(yīng),那么將調(diào)用handleFinalResponse()函數(shù)進(jìn)行處理對響應(yīng)串的主要的解析過程,由at_tok.c中的各種解析函數(shù)完成,提供字符串分析解析功能。對主動上報的解析handleUnsolicited()方法處理主動上報,它會調(diào)用onUnsolicited()來進(jìn)行進(jìn)一步的解析,這個函數(shù)在Ven

26、dor-RIL初始化時被傳入at_open()函數(shù),onUnsolicited只解析出頭部(一般是+XXXX的形式),然后按類型決定下一步操作,操作為RIL_onUnsolicitedResponse和RIL_requestTimedCallback兩種。在RIL_onUnsolicitedResponse()函數(shù)中,通過Parcel傳遞,將RESPONSE_UNSOLICITEDunsolResponse(request號)寫入Parcel,然后調(diào)用對應(yīng)的responseFunction完成進(jìn)一步的的解析,將解析的數(shù)據(jù)寫入Parcel中,最后通過sendResponse()fsendResp

27、onseRaw()fblockingWrite()fwriteLine()將數(shù)據(jù)寫回給與應(yīng)用層通信的socket。在RIL_requestTimedCallback()函數(shù)中。通過event機(jī)制實現(xiàn)的timer機(jī)制,回調(diào)對應(yīng)的內(nèi)部處理函數(shù)。通過internalRequestTimedCallback將回調(diào)添加到event循環(huán),最終完成callback上掛的函數(shù)的回調(diào)。比如pollSIMState,onPDPContextListChanged等回調(diào),不用返回上層,內(nèi)部處理就可以。對普通上報的解析IsFinalResponse(淤口isFinalResponseError()所處理的是一條AT指

28、令的響應(yīng)上報,它們將轉(zhuǎn)入handleFinalResponse方法。handleFinalResponse()函數(shù)會將所有響應(yīng)信息裝入sp_response,這是一個ATResponse結(jié)構(gòu),它的成員包括成功與否(success)以及一個中間結(jié)果(p_intermediates)。handleFinalResponse()在將響應(yīng)結(jié)果保存至sp_response后,設(shè)置s_commandcond這一條件變量,此條件變量由at_send_command_full_nolock等待。at_send_command_full_nolock獲得到了完整的響應(yīng)信息(在sp_response中),便開始進(jìn)

29、行響應(yīng)信息的處理,最后由RIL_onRequestComplete將響應(yīng)數(shù)據(jù)序列化并通過sendResponse傳遞至與應(yīng)用層通信的socket,這一部分與RIL_onUnsolicitedResponse()函數(shù)的功能非常相似,請參考對主動上報的解析部分。2 .AndroidRIL與WindowsMobileRILAndroidRIL與WindowsMobileRIL在設(shè)計思路上都是作為一個radio的抽象,為上層提供電話服務(wù),但在實現(xiàn)方式上兩者有著一定的差異,這種差異的產(chǎn)生主要是源自操作系統(tǒng)機(jī)制的不同。AndroidRIL被實現(xiàn)為HAL,相對于windowsmobile中被實現(xiàn)為驅(qū)動的方式

30、,AndroidRIL模塊的內(nèi)聚性更為理想,可維護(hù)性也將更強(qiáng),你也可以把AndroidRil看做一個中間件。AndroidRIL部分的開發(fā)工作,只需要拿到相應(yīng)的radio文件描述符,就可以進(jìn)行操作,無需關(guān)注radio的I/O驅(qū)動實現(xiàn)。2.1 兩者在與應(yīng)用通信上的實現(xiàn)對比WindowsMobileRIL在實現(xiàn)與應(yīng)用的通信時提供了RILProxy,在這個層面中它定義了大量的RIL_*()函數(shù)來作為電話服務(wù)請求。這一點(diǎn)與AndroidRIL的實現(xiàn)比較相似,AndroidRIL中在ril.h內(nèi)提供了一系列的宏來定義電話服務(wù)請求。在Android中的rild功能類似于windowsmobileRIL的R

31、ILproxy。它同樣也是起到一個中介的作用,為上層接口向下傳遞請求,并上傳回響應(yīng)。在windowsmobileRIL中要為每一個應(yīng)用程序客戶提供一份RilProxy實例。對于這兩種操作系統(tǒng)平臺,RIL所定義的所有請求是不可更改的。2.2 兩者在線程結(jié)構(gòu)與回調(diào)機(jī)制上的對比在windowsmobile的設(shè)計中,request與response被設(shè)計為異步執(zhí)行的,他們分別使用兩個隊列來對它們的異步行為進(jìn)行管理,執(zhí)行命令下發(fā)和上報命令處理的過程也互不影響,下發(fā)命令與命令的相應(yīng)響應(yīng)之間的依賴關(guān)系由應(yīng)用程序來捏合。在androidril中的request與response設(shè)計與windowsmobile

32、不同,它的命令與響應(yīng)之間是同步的過程。也就是說一條命令被下發(fā)后,將等待執(zhí)行結(jié)果,并進(jìn)行處理,再上向上層發(fā)。而不是直接異步的進(jìn)行處理和向上發(fā)送。3 .AndroidRILporting3.1 命名要實現(xiàn)某個無線模塊的RIL,需要創(chuàng)建一個實現(xiàn)了所有請求方法的共享庫,保證Android能夠響應(yīng)無線通信請求。所有的請求被定義ril.h中。不同的Modem使用不同的端口,這個在init.rc中設(shè)置。Android提供了一個參考VendorRIL,RIL參考源碼在reference-ril。將你自己的VendorRIL實現(xiàn)編譯為共享庫形式:libril-<companyname>-<RI

33、Lversion>.so比如:libril-techfaith-124.so其中:libril:所有vendorRIL的開頭<companyname>:公司縮寫<RILversion:RIL版本numberso:文件擴(kuò)展3.2 AndroidRIL的配置與加載在init.rc文件中,將通過這種方式來進(jìn)行AndroidRIL的加載。serviceril-daemon/system/bin/rild-l/system/lib/libreference-ril.so-d/dev/ttyS0也可以手動加載:/system/bin/rild-l/system/lib/libref

34、erence-ril.so-d/dev/ttyS0這兩種方式,都將啟動rild守護(hù)進(jìn)程,然后通過-l參數(shù)將libreference-ril.so共享庫鏈入,libreference-ril.so的參數(shù)-d是指加載一個串口設(shè)備,/dev/ttyS0則是這個串口設(shè)備的具體設(shè)備文件,除了參數(shù)-d外,還有-s代表加載類型為socket的設(shè)備,-p代表回環(huán)接口。3.3 AndroidRIL的編譯結(jié)構(gòu)rild:被編譯成可執(zhí)行文件,rild以守進(jìn)程的形式執(zhí)行。libril:將被編譯為共享庫,并被鏈入rild。VendorRIL:可以以兩種方式來運(yùn)行,如果定義了RIL_SHLIB宏,那么它將被編譯成共享庫,如

35、果沒定義RIL_SHLI眩,它將以守護(hù)進(jìn)程程序的方式被調(diào)用執(zhí)行。4 .AndroidRIL的java框架AndroidRIL的Java部分也被分為了兩個模塊,RIL模塊與Phone模塊。其中RIL模塊負(fù)責(zé)進(jìn)行請求以及相應(yīng)的處理,它將直接與RIL的原聲代碼進(jìn)行通信。而Phone模塊則向應(yīng)用程序開發(fā)者提供了一系列的電話功能接口。4.1 RIL模塊結(jié)構(gòu)在RIL.java中實現(xiàn)了幾個類來進(jìn)行與下層rild的通信。它實現(xiàn)了如下幾個類來完成操作:RILRequest:代表一個命令請求RlL.RILSender:負(fù)責(zé)AT指令的發(fā)送RlL.RILReceiver:用于處理主動和普通上報信息RlL.RILSen

36、der與RlL.RILReceiver是兩個線程。RILRequest提供了obtain()方法,用于得到具體的request操作,這些操作被定義在RILConstants.java中(RILConstants.java中定義的request命令與RIL原生代碼中ril.h中定義的request命令是相同的),然后通過send()函數(shù)發(fā)送EVENT_SEND,在RIL_Sender線程中處理這個EVENT_SEND將命令寫入到stream(socket)中去。Socket是來自常量SOCKET_NAME_RIL,socket是同一個。當(dāng)有上報信息來到時,系統(tǒng)將通過RILReciver的生命周期

37、里,它一直監(jiān)視著到來時,它將通過readRilMessage()processResponse來進(jìn)行處理。它與RIL原生代碼部分的s_fdListen所指的RILReciver來得到信息,并進(jìn)行處理。在SOCKET_NAME_RIL這個socket,當(dāng)有數(shù)據(jù)方法讀取到一個完整的響應(yīng),然后通過4.2 Phone模塊結(jié)構(gòu)Android通過暴露Phone模塊來供上層應(yīng)用程序用戶使用電話功能相關(guān)的接口。它為用戶提供了諸如電話呼叫,短信息,SIM卡管理之類的接口調(diào)用。它的核心部分是類GSMPhone,這個是Gsm的電話實現(xiàn),需要通過PhoneFactory獲取這個GSMPhone。GSMPhone并不是

38、直接提供接口給上層用戶使用,而是通過另外一個管理類TelephonyManager來供應(yīng)用程序用戶使用。類TelephonyManager實現(xiàn)了android的電話相關(guān)操作。它主要使用兩個服務(wù)來訪問telephony功能:1.ITelephony,提供給上層應(yīng)用程序用戶與telephony進(jìn)行操作,交互的接口,在packages/apps/Phone中由PhoneInterfaceManager.java實現(xiàn)。2.ItelephonyRegistry提供了一個通知機(jī)制,將底層來的上報通知給框架中需要得到通知的部分,由TelephonyRegistry.java實現(xiàn)。GSMPhone通過Phon

39、eNotifier的實現(xiàn)者DefaultPhoneNotifier將具體的事件轉(zhuǎn)化為函數(shù)調(diào)用,通知到TelephonyRegistry。TelephonyRegistry再通過兩種方式通知給用戶,其一是廣播事件,另外一種是通過服務(wù)用戶在TelephonyRegistry中注冊的IphoneStateListener接口,實現(xiàn)回調(diào)(回調(diào)方式參見android的aidl機(jī)制)。參考資料相關(guān)網(wǎng)站:5電話功能概述Android的RadioInterfaceLayer(RIL)提供了電話服務(wù)和的radio硬件之間的抽象層。RadioInterfaceLayerRIL(RadioInterfaceLaye

40、r)負(fù)責(zé)數(shù)據(jù)的可靠傳輸、AT命令的發(fā)送以及response的解析。應(yīng)用處理器通過AT命令集與帶GPR砌能的無線通訊模塊通信。ATcommand由Hayes公司發(fā)明,是一個調(diào)制解調(diào)器制造商采用的一個調(diào)制解調(diào)器命令語言,每條命令以字母"AT"開頭。JAVAFramework代碼的路徑為:frameworks/base/telephony/java/android/telephonyandroid.telephony以及android.telephony.gsmCorenative:在hardware/ril目錄中,提供了對RIL支持的本地代碼,包括4個文件夾:hardware/

41、ril/includehardware/ril/librilhardware/ril/reference-rilhardware/ril/rildkernelDriver在Linux內(nèi)核的驅(qū)動中,提供了相關(guān)的驅(qū)動程序的支持,可以建立在UART或者SDIO,USB等Wj速的串行總線上。電話功能各個部分:hardware/ril/include/telephony/目錄中的ril.h文件是ril部分的基礎(chǔ)頭文件。其中定義的結(jié)構(gòu)體RIL_RadioFunctions如下所示:typedefstructintversion;RIL_RequestFunconRequest;RIL_RadioState

42、RequestonStateRequest;RIL_Supportssupports;RIL_CancelonCancel;RIL_GetVersiongetVersion;RIL_RadioFunctions;RIL_RadioFunctions中包含了幾個函數(shù)指針的結(jié)構(gòu)體,這實際上是一個移植層的接口,下層的庫實現(xiàn)后,由rild守護(hù)進(jìn)程得到這些函數(shù)指針,執(zhí)行對應(yīng)的函數(shù)。幾個函數(shù)指針的原型為:typedefvoid(*RIL_RequestFunc)(intrequest,void*data,size_tdatalen,RIL_Tokent);typedefRIL_RadioState(*RI

43、L_RadioStateRequest)();typedefint(*RIL_Supports)(intrequestCode);typedefvoid(*RIL_Cancel)(RIL_Tokent);typedefconstchar*(*RIL_GetVersion)(void);其中最為重要的函數(shù)是onRequest(),它是一個請求執(zhí)行的函數(shù)。5.1 rild守護(hù)進(jìn)程rild守護(hù)進(jìn)程的文件包含在hardware/ril/rild目錄中,其中包含了rild.c和radiooptions.c兩個文件,這個目錄中的文件經(jīng)過編譯后生成一個可執(zhí)行程序,這個程序在系統(tǒng)的安裝路徑在:/system/

44、bin/rildrild.c是這個守護(hù)進(jìn)程的入口,它具有一個主函數(shù)的入口main,執(zhí)行的過程是將上層來的請求都由這個函數(shù)RIL_RadioFunctionsonReques()的方法進(jìn)行映射后轉(zhuǎn)換成對應(yīng)的AT命令的字符串,發(fā)給下層的硬件執(zhí)行。在運(yùn)行過程中,使用dlopen打開路徑為/system/lib/中名稱為libreference-ril.so的動態(tài)庫,然后從中取出RIL_Init符號來運(yùn)行。ril_register()注冊:RIL_Init符號是一個函數(shù)指針,執(zhí)行這個函數(shù)后,返回的是一個RIL_RadioFunctions類型的指針。得到這個指針后,調(diào)用RIL_register()函數(shù)

45、,將這個指針注冊到libril庫之中,然后進(jìn)入循環(huán)ril_event_l00P()。事實上,這個守護(hù)進(jìn)程提供了一個申請?zhí)幚淼目蚣?,而具體的功能都是在libril.so和libreference-ril.so中完成的。附:RIL守護(hù)進(jìn)程,開機(jī)時被init守護(hù)進(jìn)程調(diào)用啟動,里面僅有main函數(shù)作為入口點(diǎn),負(fù)責(zé)完成RIL初始化工作。在rild.c文件中,將完成ril的加載過程,它會執(zhí)行如下操作:動態(tài)加載VendorRIL的.so文件執(zhí)行RIL_startEventLoop()開啟消息隊列以進(jìn)行事件監(jiān)聽通過執(zhí)行VendorRIL的rilInit()方法來進(jìn)行VendorRIL與libril的關(guān)系建立。

46、在rild文件夾中還包括一個radiooptions.c文件,它的作用是通過串口將一些radio相關(guān)的參數(shù)直接傳給rild來對radio進(jìn)行配置。5.2 libreference-ril.so動態(tài)庫libreference-ril.so動態(tài)庫的路徑是:hardware/ril/reference-ril其中主要的文件是reference-ril.c和atchannel.c。這個庫必須實現(xiàn)的是一個名稱為RIL_Init的函數(shù),這個函數(shù)執(zhí)行的結(jié)果是返回一個RIL_RadioFunctions結(jié)構(gòu)體的指針,指針指向函數(shù)指針。這個庫在執(zhí)行的過程中需要創(chuàng)建一個線程來執(zhí)行實際的功能。在執(zhí)行的過程中,這個庫

47、將打開一個/dev/ttySXXX的終端(終端的名字是從上層傳入的),然后利用這個終端控制硬件執(zhí)行。附:在編譯時libril被鏈入rild,它為rild提供了event處理功能,還提供了在rild與VendorRIL之間傳遞請求和響應(yīng)消息的能力。Libril提供的主要功能分布在兩個主要方法內(nèi),一個是RIL_startEventLoop()方法,另一個是RIL_register()方法RIL_startEventLoop()方法所提供的功能就是啟用eventLoop線程,開始執(zhí)行RIL消息隊列。RIL_register()方法的主要功能是啟動名為rild的監(jiān)聽端口,等待java端通過socket

48、進(jìn)行連接。5.3 libril.so動態(tài)庫libril.so庫的目錄是:hardware/ril/libril其中主要的文件為ril.cpp,這個庫主要需要實現(xiàn)的以下幾個接口為:RIL_startEventLoop(void);voidRIL_setcallbacks(constRIL_RadioFunctions*callbacks);RIL_register(constRIL_RadioFunctions*callbacks);RIL_onRequestComplete(RIL_Tokent,RIL_Errnoe,void*response,size_tresponselen);voidR

49、IL_onUnsolicitedResponse(intunsolResponse,void*data,size_tdatalen);RIL_requestTimedCallback(RIL_TimedCallbackcallback,void*param,conststructtimeval*relativeTime);這些函數(shù)也是被rild守護(hù)進(jìn)程調(diào)用的,不同的vendor可以通過自己的方式實現(xiàn)這幾個接口,這樣可以保證RIL可以在不同系統(tǒng)的移植。其中RIL_register()函數(shù)把外部的RIL_RadioFunctions結(jié)構(gòu)體注冊到這個庫之中,在恰當(dāng)?shù)臅r候調(diào)用相應(yīng)的函數(shù)。在執(zhí)行的過程中

50、,這個庫處理了一些將請求轉(zhuǎn)換成字符串的功能。附:Android自帶的VendorRIL的參考實現(xiàn)。被編譯成.so文件,由于本部分是廠商定制的重點(diǎn)所在。所以被設(shè)計為松散耦合,且可靈活配置的。在rild中通過opendl()的方式加載。librefrence.so負(fù)責(zé)直接與radio通信,這包括將來自libril的指令轉(zhuǎn)換為AT指令,并且將AT指令寫入radio中。reference-ril會接收調(diào)用者傳來的參數(shù),參數(shù)內(nèi)容為與radio的通信方式。如通過串口連接radio,那么參數(shù)為這種形式:-d/dev/ttySx5.4 ril層的所有代碼分析5.4.1 ril/rild下的文件rild.c-&

51、gt;mian()為函數(shù)入口intmain(intargc,char*argv)/./OpenLib:#endifswitchUser();打開dlopen()加載vendorRIL獲取由RIL_register(funcs);注冊進(jìn)來的參數(shù),并解析dlHandle=dlopen(rilLibPath,RTLD_NOW);if(dlHandle=NULL)fprintf(stderr,"dlopenfailed:%sn",dlerror();exit(-1);/1:消息隊列的入口1.到select阻塞每當(dāng)看到打印信息,不按順序打下來說明阻塞RILstartEventLoop

52、();通過dlsym函數(shù)得到rilInit函數(shù)指針的引用rilInit=(constRIL_RadioFunctions*(*)(conststructRIL_Env*,int,char*)dlsym(dlHandle,"RIL_Init");if(rilInit=NULL)fprintf(stderr,"RIL_Initnotdefinedorexportedin%sn",rilLibPath);exit(-1);if(hasLibArgs)rilArgv=argv+i-1;argc=argc-i+1;elsestaticchar*newArgvMAX

53、_LIB_ARGS;staticcharargsPROPERTY_VALUE_MAX;rilArgv=newArgv;property_get(LIB_ARGS_PROPERTYirgs,"");argc=make_argv(args,rilArgv);/Makesurethere'sareasonableargv0rilArgv0=argv0;/2:利用得到的rilInit函數(shù)指針,調(diào)用真正的RIL_Initfuncs=rilInit(&srilEnv,argc,rilArgv);RILregister(funcs);done:while(1)/sleep

54、(UINT32_MAX)seemstoreturnimmediatelyonbionicsleep(OxOOffffff);5.4.2 ril/libril->ril.cpp中RIL_startEventLoop()函數(shù)分析RIL_startEventLoop(void)(intret;pthread_attr_tattr;LOGD("-2-ril.cpp-RIL_startEventLoop-");/*spinupeventLoopthreadandwaitforittogetstarted*/s_started=0;pthread_mutex_lock(&

55、s_startupMutex);pthread_attr_init(&attr);pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);LOGD("-1-ril.cpp-kai-kou-pthread_create(&s_tid_dispatch,&attr,eventLoop,NULL);");ret=pthread_create(&s_tid_dispatch,&attr,eventLoop,NULL);創(chuàng)建線程,為入口函數(shù)LOGD("-2.-ril

56、.cpp-tiao-chu-rpthread_create(&s_tid_dispatch,&attr,eventLoop,NULL);-");while(s_started=0)pthread_cond_wait(&s_startupCond,&s_startupMutex);pthread_mutex_unlock(&s_startupMutex);if(ret<0)LOGE("Failedtocreatedispatchthreaderrno:%d",errno);return;eventLoop(void*pa

57、ram)1 .-rileventinit();/初始化voidril_event_init()MUTEX_INIT();LOGD("-2.2-Ril_evnet.cpp-ril_event_init-shi-xian-han-shu-");FD_ZERO(&readFds);initlist(&timerlist);initlist(&pendinglist);memset(watchtable,0,sizeof(watchtable);2 .-ret=pipe(filedes);3 .-rileventset(&s_wakeupfd_event,s_fdWakeupRead,true,processWakeupCallback,NULL);在ril/libril/ril_event.cpp實現(xiàn)voidrileventset(structrilevent*ev,intfd,boolper

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論