




已閱讀5頁(yè),還剩80頁(yè)未讀, 繼續(xù)免費(fèi)閱讀
版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Android的電話(huà)功能介紹整個(gè)RIL文件夾的分析介紹本文檔對(duì)Android RIL部分的內(nèi)容進(jìn)行了介紹,其重點(diǎn)放在了Android RIL的原生代碼部分。包括四個(gè)主題:1.Android RIL框架介紹2.Android RIL與WindowsMobile RIL3.Android RIL porting4.Android RIL的java框架在本文檔中將Android代碼中的重要模塊列出進(jìn)行分析,并給出了相關(guān)的程序執(zhí)行流程介紹,以加深對(duì)模塊間交互方式的理解。對(duì)于java代碼部分,這里僅進(jìn)行簡(jiǎn)單的介紹。如果需要深入了解,可以查看相關(guān)參考資料。本文檔中還對(duì)Android RIL的Porting部分內(nèi)容進(jìn)行了描述和分析。針對(duì)對(duì)unix操作系統(tǒng)環(huán)境并不熟悉的讀者,本文檔中所涉及到的相關(guān)知識(shí)包括: Unix file system Unix socket Unix thread Unix下I/O多路轉(zhuǎn)接以上信息可以在任意一份描述Unix系統(tǒng)調(diào)用的文檔中找到。1.Android RIL框架介紹術(shù)語(yǔ):fd Linux文件描述符pipe Linux管道cond 一般是condition variable的縮寫(xiě)tty 通常使用tty來(lái)簡(jiǎn)稱(chēng)各種類(lèi)型的終端設(shè)備unsolicited response 被動(dòng)請(qǐng)求命令來(lái)自basebandevent loop android的消息隊(duì)列機(jī)制,由Linux的系統(tǒng)調(diào)用select()實(shí)現(xiàn)init.rc init守護(hù)進(jìn)程啟動(dòng)后被執(zhí)行的啟動(dòng)腳本。HAL 硬件抽象層(Hardware Abstraction Layer,HAL)1.1 Android RIL概況Android RIL提供了無(wú)線(xiàn)硬件設(shè)備與電話(huà)服務(wù)之間的抽象層。下圖展示了RIL在Android體系中的位置。android的ril位于應(yīng)用程序框架與內(nèi)核之間,分成了兩個(gè)部分,一個(gè)部分是rild,它負(fù)責(zé)socket與應(yīng)用程序框架進(jìn)行通信。另外一個(gè)部分是Vendor RIL,這個(gè)部分負(fù)責(zé)向下是通過(guò)兩種方式與radio進(jìn)行通信,它們是直接與radio通信的AT指令通道和用于傳輸包數(shù)據(jù)的通道,數(shù)據(jù)通道用于手機(jī)的上網(wǎng)功能。對(duì)于RIL的java框架部分,也被分成了兩個(gè)部分,一個(gè)是RIL模塊,這個(gè)模塊主要用于與下層的rild進(jìn)行通信,另外一個(gè)是Phone模塊,這個(gè)模塊直接暴露電話(huà)功能接口給應(yīng)用開(kāi)發(fā)用戶(hù),供他們調(diào)用以進(jìn)行電話(huà)功能的實(shí)現(xiàn)。1.2 Android RIL目錄結(jié)構(gòu)Android的RIL模塊位于Android/hardware/ril文件夾,有三個(gè)子模塊:rild , libril , reference-ril所在目錄結(jié)構(gòu):/hardware/ril/|- ril (無(wú)線(xiàn)電抽象層)| |- include (頭文件)| |- libril (庫(kù))| |- reference-cdma-sms (cdma短信參考)| |- reference-ril (ril參考)| |- rild (ril后臺(tái)服務(wù)程序)hardware/ril$ lsincludelibrilreference-cdma-smsreference-rilrild1.hardware/ril/rild$ lsAndroid.mk MODULE_LICENSE_APACHE2 NOTICEradiooptions.crild.c2.hardware/ril/include/telephony$ lsril_cdma_sms.hril.h3.hardware/ril/libril$ lsAndroid.mk NOTICEril_event.hril.cppril_event.cpp ril_commands.hril_unsol_commands.hMODULE_LICENSE_APACHE24.hardware/ril/reference-cdma-sms$ lsAndroid.mk reference-cdma-sms.c reference-cdma-sms.h5.hardware/ril/reference-ril$ lsAndroid.mk atchannel.h at_tok.h misc.h NOTICEatchannel.cat_tok.cril_event.hreference-ril.c misc.c MODULE_LICENSE_APACHE2include文件夾:包含RIL頭文件,最主要的是ril.hrild文件夾:RIL守護(hù)進(jìn)程,開(kāi)機(jī)時(shí)被init守護(hù)進(jìn)程調(diào)用啟動(dòng),里面僅有main函數(shù)作為入口點(diǎn),負(fù)責(zé)完成RIL初始化工作。在rild.c文件中,將完成ril的加載過(guò)程,它會(huì)執(zhí)行如下操作:動(dòng)態(tài)加載Vendor RIL的.so文件執(zhí)行RIL_startEventLoop()開(kāi)啟消息隊(duì)列以進(jìn)行事件監(jiān)聽(tīng)通過(guò)執(zhí)行Vendor RIL的rilInit()方法來(lái)進(jìn)行Vendor RIL與libril的關(guān)系建立。在rild文件夾中還包括一個(gè)radiooptions.c文件,它的作用是通過(guò)串口將一些radio相關(guān)的參數(shù)直接傳給rild來(lái)對(duì)radio進(jìn)行配置。libril文件夾:在編譯時(shí)libril被鏈入rild,它為rild提供了event處理功能,還提供了在rild與Vendor RIL之間傳遞請(qǐng)求和響應(yīng)消息的能力。Libril提供的主要功能分布在兩個(gè)主要方法內(nèi),一個(gè)是RIL_startEventLoop()方法,另一個(gè)是RIL_register()方法RIL_startEventLoop()方法所提供的功能就是啟用eventLoop線(xiàn)程,開(kāi)始執(zhí)行RIL消息隊(duì)列。RIL_register()方法的主要功能是啟動(dòng)名為 rild 的監(jiān)聽(tīng)端口,等待java 端通過(guò)socket進(jìn)行連接。reference-ril文件夾:Android自帶的Vendor RIL的參考實(shí)現(xiàn)。被編譯成.so文件,由于本部分是廠商定制的重點(diǎn)所在。所以被設(shè)計(jì)為松散耦合,且可靈活配置的。在rild中通過(guò)opendl()的方式加載。librefrence.so負(fù)責(zé)直接與radio通信,這包括將來(lái)自libril的指令轉(zhuǎn)換為AT指令,并且將AT指令寫(xiě)入radio中。reference-ril會(huì)接收調(diào)用者傳來(lái)的參數(shù),參數(shù)內(nèi)容為與radio的通信方式。如通過(guò)串口連接radio,那么參數(shù)為這種形式:-d /dev/ttySx1.3.Android RIL中的消息(event)隊(duì)列機(jī)制 在Android RIL中,為了達(dá)到等待多路輸入并且不出現(xiàn)阻塞的目的,使用了IO多路復(fù)用機(jī)制。 如果使用阻塞I/O進(jìn)行網(wǎng)絡(luò)的讀取寫(xiě)入,這意味著假如需要同時(shí)從兩個(gè)網(wǎng)絡(luò)文件描述符中讀內(nèi)容,那么如果讀取操作在等待網(wǎng)絡(luò)數(shù)據(jù)到來(lái),這將可能很長(zhǎng)時(shí)間阻塞在一個(gè)描述符上,另一個(gè)網(wǎng)絡(luò)文件描述符不管有沒(méi)有數(shù)據(jù)到來(lái)都無(wú)法被讀取。一種解決方案是: 如果使用非阻塞I/O進(jìn)行網(wǎng)絡(luò)的讀取寫(xiě)入,在讀取其中一個(gè)網(wǎng)絡(luò)文件描述符如果阻塞將直接返回,再讀取另外一個(gè),這種方式的循環(huán)被稱(chēng)之為輪詢(xún)。輪詢(xún)方式確實(shí)能解決進(jìn)行多路io操作時(shí)的阻塞問(wèn)題,但是這種方法的不足之處是反復(fù)的執(zhí)行讀寫(xiě)調(diào)用將浪費(fèi)cpu時(shí)鐘。I/O多路轉(zhuǎn)接技術(shù)在這里提供了另一種比較好的解決方案: 它會(huì)先構(gòu)造一張有關(guān)I/O描述符的列表,然后調(diào)用select函數(shù),當(dāng)IO描述符列表中的一個(gè)描述符準(zhǔn)備好進(jìn)行I/O時(shí),該函數(shù)返回,并告知可以讀或?qū)懩膫€(gè)描述符。 Android RIL中消息隊(duì)列的核心實(shí)現(xiàn)思想就是這種I/O多路轉(zhuǎn)接技術(shù)。消息隊(duì)列機(jī)制的實(shí)現(xiàn)在ril_event.cpp中,其中被定義的ril_event結(jié)構(gòu)是消息的主體。 每個(gè)ril_event結(jié)構(gòu),與一個(gè)fd句柄綁定(可以是文件,socket,管道等),并且?guī)б粋€(gè)func指針,這個(gè)func指針?biāo)傅暮瘮?shù)是個(gè)回調(diào)函數(shù),它指定了當(dāng)所綁定的fd準(zhǔn)備好進(jìn)行讀取時(shí)所要進(jìn)行的操作。 消息隊(duì)列的開(kāi)始點(diǎn)為RIL_startEventLoop函數(shù)。RIL_startEventLoop在ril.cpp中實(shí)現(xiàn),它的主要目的是通過(guò)pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL)建立一個(gè)dispatch線(xiàn)程,線(xiàn)程入口點(diǎn)在eventLoop. 而在eventLoop中,會(huì)調(diào)ril_event.cpp中的ril_event_loop()函數(shù),建立起消息隊(duì)列機(jī)制。 ril_event是一個(gè)帶有鏈表行為的struct,它最主要的成員一個(gè)是fd,一個(gè)是func:struct ril_event struct ril_event *next;struct ril_event *prev;int fd;int index;bool persist;struct timeval timeout;ril_event_cb func;void *param; 初始化一個(gè)新ril_event的操作是通過(guò)ril_event_set()來(lái)完成的,并通過(guò)ril_event_add()加入到消息隊(duì)列之中,add會(huì)把隊(duì)列里所有ril_event的fd,放入一個(gè)fd集合readFds中。這樣 ril_event_loop能通過(guò)一個(gè)多路復(fù)用I/O的機(jī)制(select)來(lái)等待這些fd。在進(jìn)入ril_event_loop()之前,在eventLoop中已經(jīng)創(chuàng)建和掛入了s_wakeupfd_event,它是通過(guò)pipe的機(jī)制實(shí)現(xiàn)的,這個(gè)管道fd的回調(diào)函數(shù)并沒(méi)有實(shí)現(xiàn)什么功能,它的目的只是為了讓select方法能返回一次,這樣select()方法就能重新跟蹤新加入事件隊(duì)列的fd和timeout設(shè)置。所以在添加新fd到eventLoop時(shí),往往不是直接調(diào)用ril_event_add,實(shí)際通常用rilEventAddWakeup來(lái)添加,這個(gè)方法除了會(huì)間接調(diào)用ril_event_add外,還會(huì)調(diào)用triggerEvLoop()函數(shù)來(lái)向s_fdWakeupWrite中寫(xiě)入一個(gè)空字符,這樣select()函數(shù)會(huì)返回并重新執(zhí)行,新加入的文件描述符便得以被select()加載并跟蹤。如果在ril_event隊(duì)列中任何一個(gè)fd已經(jīng)準(zhǔn)備好,則進(jìn)入分析流程:processTimeouts(),processReadReadies(&rfds, n),firePending()其中firePending()方法執(zhí)行這個(gè)event的func,也就是回調(diào)函數(shù)。 在Android RIL初始化完成后,將有幾個(gè)event被掛入到eventLoop中:1.s_listen_event:名為rild的socket,主要requeset & response通道2.s_debug_event:名為rild-debug的socket,調(diào)試用requeset & response通道3.s_wakeupfd_event:無(wú)名管道,用于隊(duì)列主動(dòng)喚醒 這其中最為重要的event就是s_listen_event,它作為request與response的通道實(shí)現(xiàn)。在ril_event.cpp中還持有一個(gè)watch_table數(shù)組,一個(gè)timer_list鏈表和一個(gè)pending_list鏈表。watch_table數(shù)組的目的很單純,存放當(dāng)前被eventLoop等待的ril_event(非timer event),供eventLoop喚醒時(shí)使用。timer_list是存放timer event的鏈表,在eventLoop喚醒時(shí)要對(duì)這些timer event單獨(dú)進(jìn)行處理pending_list:待處理(對(duì)其回調(diào)函數(shù)進(jìn)行調(diào)用)的所有ril_event的鏈表。1.4.Android RIL中初始化流程分析Rild的初始化流程初始化流程從rild.c中的main函數(shù)開(kāi)始,它被init守護(hù)進(jìn)行調(diào)用執(zhí)行:首先在main()函數(shù)內(nèi)會(huì)首先通過(guò)dlopen()函數(shù)加載Vendor RIL(在自帶的參考實(shí)現(xiàn)中為librefrence_ril.so)。接著調(diào)用RIL_startEventLoop()函數(shù)來(lái)啟動(dòng)消息隊(duì)列機(jī)制。調(diào)用librefrence_ril.so的RIL_Init()函數(shù)來(lái)進(jìn)行Vendor RIL的初始化。RIL_Init()函數(shù)執(zhí)行后會(huì)返回一個(gè)RIL_RadioFunction結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體內(nèi)最重要的成員就是onRequest()方法。onRequest()方法會(huì)被dispatchFunction調(diào)用,也就是說(shuō)dispatchFunction調(diào)用是程序流從rild轉(zhuǎn)入Vendor RIL的分界點(diǎn)。RIL_register()函數(shù)將實(shí)現(xiàn)兩個(gè)目地,一個(gè)是將RIL_INIT中獲得的RIL_RadioFunction進(jìn)行注冊(cè),rild通過(guò)此種方式保證自己持有一個(gè)RIL_RadioFunction實(shí)例,第二個(gè)是將s_fdListen加入到消息隊(duì)列機(jī)制中,開(kāi)啟s_fdListen的事件監(jiān)聽(tīng)。Vendor RIL的初始化流程:RIL_Init被調(diào)用后首先通過(guò)參數(shù)獲取硬件接口的設(shè)備文件或模擬硬件接口的socket。(參見(jiàn)上文中對(duì)reference-ril文件夾的介紹)接下來(lái)是創(chuàng)建mainLoop線(xiàn)程,并跳入到線(xiàn)程內(nèi)執(zhí)行。mainLoop會(huì)建立起與硬件的通信,然后通過(guò)read方法阻塞等待硬件的主動(dòng)上報(bào)或響應(yīng)。mainLoop還會(huì)調(diào)用initlizeCallBack()函數(shù)來(lái)向radio發(fā)送一系列的AT命令來(lái)進(jìn)行radio的初始化設(shè)置工作。1.5.Android RIL中request流程分析 上層應(yīng)用開(kāi)始向rild通過(guò)socket傳輸數(shù)據(jù)時(shí),通過(guò)RIL消息隊(duì)列機(jī)制,s_listen_event的回調(diào)函數(shù)listenCallBack將會(huì)被調(diào)用,開(kāi)始進(jìn)行數(shù)據(jù)流的分析與處理。接下來(lái)s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen),獲取傳入的socket描述符,也就是上層的java RIL傳入的連接。然后,通過(guò)record_stream_new()建立起一個(gè)RecordStream, 將這個(gè)record_stream與s_fdCommand綁定, RecordStream實(shí)際上是一個(gè)用于存放數(shù)據(jù)的結(jié)構(gòu)體,這個(gè)結(jié)構(gòu)體提供了一些操作類(lèi)來(lái)保證這個(gè)RecordStream所綁定的文件描述符被讀取時(shí)里面的數(shù)據(jù)會(huì)被完整讀取。一旦s_fdCommand中有數(shù)據(jù),它的回調(diào)函數(shù)processCommandsCallback()將會(huì)被調(diào)用,processCommandsCallback()通過(guò)record_stream_get_next阻塞讀取s_fdCommand上發(fā)來(lái)的 數(shù)據(jù), 直到收到一完整的request。然后將其傳遞進(jìn)processCommandBuffer()函數(shù),processCommandBuffer()正式進(jìn)入了命令的解析部分。每個(gè)接收到的命令將以RequestInfo的形式存在。從socket過(guò)來(lái)的數(shù)據(jù)流,是Parcel處理過(guò)的序列化字節(jié)流, 在這里會(huì)通過(guò)反序列化的方法提取出來(lái)。最前面的是request號(hào), 以及token域(request的遞增序列號(hào))。request號(hào)是一個(gè)CommandInfo,它在ril_command.h中定義。接下來(lái), 這個(gè)RequestInfo會(huì)被掛入pending的request隊(duì)列, 執(zhí)行具體的dispatchFunction(), 進(jìn)行詳細(xì)解析。dispatchFunction方法有著多種實(shí)現(xiàn),如dispatchVoid, dispatchString, 它們的調(diào)用取決于Parcel的參數(shù)傳入形式。比如說(shuō)在dispatchDial方法中,Parcel對(duì)象將被解析為RIL_Dial結(jié)構(gòu)。這是disptachFunction的任務(wù)之一,它的另一個(gè)任務(wù)就是調(diào)用onRequest()方法,并將解析的內(nèi)容傳入onRequest()方法。從onRequest方法開(kāi)始,程序控制流脫離了RILD,進(jìn)入到了Vendor RIL中。onRequest方法會(huì)通過(guò)傳入的請(qǐng)求類(lèi)型來(lái)調(diào)用指定的request()方法,request()方法則負(fù)責(zé)組裝AT指令并下發(fā)給at_send_command()方法集合中的一個(gè),這個(gè)方法集合提供了針對(duì)不同類(lèi)型AT指令的實(shí)現(xiàn),如單行AT指令at_send_command_singleline(),短信息指令at_send_command_sms()等。最后,執(zhí)行at_send_command_full(),再通過(guò)一個(gè)互斥的at_send_command_full_nolock()調(diào)用,完成最終的寫(xiě)出操作,在writeline()中,寫(xiě)出到初始化時(shí)打開(kāi)的設(shè)備中。需要注意的是:at_send_command_full_nolock()在將指令寫(xiě)入radio后并不會(huì)直接返回,而是通過(guò)條件變量等待響應(yīng)信息,得到響應(yīng)信息后會(huì)攜帶這些信息返回。具體流程可以參考下面的response流程分析。1.6.Android RIL中response流程分析AT的response有兩種,一種是unsolicited。另一種是普通response,也就是命令的響應(yīng)。response信息的獲取在readerLoop()中。由readline()函數(shù)讀取上來(lái)。讀取到的line將被傳入processLine()函數(shù)進(jìn)行解析,processLine()函數(shù)首先會(huì)判斷當(dāng)前的響應(yīng)是主動(dòng)響應(yīng)還是普通響應(yīng),如果是主動(dòng)響應(yīng),將調(diào)用handleUnsolicited()函數(shù),如果為普通響應(yīng),那么將調(diào)用handleFinalResponse()函數(shù)進(jìn)行處理對(duì)響應(yīng)串的主要的解析過(guò)程,由at_tok.c中的各種解析函數(shù)完成,提供字符串分析解析功能。對(duì)主動(dòng)上報(bào)的解析 handleUnsolicited ()方法處理主動(dòng)上報(bào),它會(huì)調(diào)用onUnsolicited()來(lái)進(jìn)行進(jìn)一步的解析,這個(gè)函數(shù)在Vendor-RIL初始化時(shí)被傳入at_open()函數(shù),onUnsolicited只解析出頭部(一般是+XXXX的形式),然后按類(lèi)型決定下一步操作,操作為 RIL_onUnsolicitedResponse和RIL_requestTimedCallback兩種。在RIL_onUnsolicitedResponse()函數(shù)中,通過(guò)Parcel傳遞,將 RESPONSE_UNSOLICITED,unsolResponse(request號(hào))寫(xiě)入Parcel,然后調(diào)用對(duì)應(yīng)的responseFunction完成進(jìn)一步的的解析,將解析的數(shù)據(jù)寫(xiě)入Parcel中,最后通過(guò)sendResponse()sendResponseRaw()blockingWrite()writeLine()將數(shù)據(jù)寫(xiě)回給與應(yīng)用層通信的socket。在RIL_requestTimedCallback()函數(shù)中。通過(guò)event機(jī)制實(shí)現(xiàn)的timer機(jī)制,回調(diào)對(duì)應(yīng)的內(nèi)部處理函數(shù)。通過(guò)internalRequestTimedCallback將回調(diào)添加到event循環(huán),最終完成callback上掛的函數(shù)的回調(diào)。比如 pollSIMState,onPDPContextListChanged等回調(diào), 不用返回上層,內(nèi)部處理就可以。對(duì)普通上報(bào)的解析 IsFinalResponse()和isFinalResponseError()所處理的是一條AT指令的響應(yīng)上報(bào),它們將轉(zhuǎn)入handleFinalResponse方法。 handleFinalResponse()函數(shù)會(huì)將所有響應(yīng)信息裝入sp_response,這是一個(gè)ATResponse結(jié)構(gòu),它的成員包括成功與否(success)以及一個(gè)中間結(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中),便開(kāi)始進(jìn)行響應(yīng)信息的處理,最后由RIL_onRequestComplete將響應(yīng)數(shù)據(jù)序列化并通過(guò)sendResponse傳遞至與應(yīng)用層通信的socket,這一部分與RIL_onUnsolicitedResponse()函數(shù)的功能非常相似,請(qǐng)參考對(duì)主動(dòng)上報(bào)的解析部分。2.Android RIL與WindowsMobile RIL Android RIL與WindowsMobile RIL 在設(shè)計(jì)思路上都是作為一個(gè)radio的抽象,為上層提供電話(huà)服務(wù),但在實(shí)現(xiàn)方式上兩者有著一定的差異,這種差異的產(chǎn)生主要是源自操作系統(tǒng)機(jī)制的不同。Android RIL被實(shí)現(xiàn)為HAL,相對(duì)于windows mobile中被實(shí)現(xiàn)為驅(qū)動(dòng)的方式,Android RIL模塊的內(nèi)聚性更為理想,可維護(hù)性也將更強(qiáng),你也可以把Android Ril 看做一個(gè)中間件。Android RIL部分的開(kāi)發(fā)工作,只需要拿到相應(yīng)的radio文件描述符,就可以進(jìn)行操作,無(wú)需關(guān)注radio的I/O驅(qū)動(dòng)實(shí)現(xiàn)。2.1兩者在與應(yīng)用通信上的實(shí)現(xiàn)對(duì)比 WindowsMobile RIL在實(shí)現(xiàn)與應(yīng)用的通信時(shí)提供了RIL Proxy,在這個(gè)層面中它定義了大量的RIL_*()函數(shù)來(lái)作為電話(huà)服務(wù)請(qǐng)求。這一點(diǎn)與Android RIL的實(shí)現(xiàn)比較相似,Android RIL中在ril.h內(nèi)提供了一系列的宏來(lái)定義電話(huà)服務(wù)請(qǐng)求。在Android中的rild功能類(lèi)似于windows mobile RIL的RIL proxy。它同樣也是起到一個(gè)中介的作用,為上層接口向下傳遞請(qǐng)求,并上傳回響應(yīng)。在windows mobile RIL中要為每一個(gè)應(yīng)用程序客戶(hù)提供一份Ril Proxy實(shí)例。對(duì)于這兩種操作系統(tǒng)平臺(tái),RIL所定義的所有請(qǐng)求是不可更改的。2.2兩者在線(xiàn)程結(jié)構(gòu)與回調(diào)機(jī)制上的對(duì)比 在windows mobile的設(shè)計(jì)中,request與response被設(shè)計(jì)為異步執(zhí)行的,他們分別使用兩個(gè)隊(duì)列來(lái)對(duì)它們的異步行為進(jìn)行管理,執(zhí)行命令下發(fā)和上報(bào)命令處理的過(guò)程也互不影響,下發(fā)命令與命令的相應(yīng)響應(yīng)之間的依賴(lài)關(guān)系由應(yīng)用程序來(lái)捏合。 在android ril中的request與response設(shè)計(jì)與windows mobile不同,它的命令與響應(yīng)之間是同步的過(guò)程。也就是說(shuō)一條命令被下發(fā)后,將等待執(zhí)行結(jié)果,并進(jìn)行處理,再上向上層發(fā)。而不是直接異步的進(jìn)行處理和向上發(fā)送。3.Android RIL porting3.1.命名 要實(shí)現(xiàn)某個(gè)無(wú)線(xiàn)模塊的RIL,需要?jiǎng)?chuàng)建一個(gè)實(shí)現(xiàn)了所有請(qǐng)求方法的共享庫(kù),保證Android能夠響應(yīng)無(wú)線(xiàn)通信請(qǐng)求。所有的請(qǐng)求被定義ril.h中。不同的Modem使用不同的端口,這個(gè)在init.rc中設(shè)置。Android提供了一個(gè)參考Vendor RIL,RIL參考源碼在reference-ril。將你自己的Vendor RIL實(shí)現(xiàn)編譯為共享庫(kù)形式: libril-.so比如:libril-techfaith-124.so其中: libril:所有vendor RIL的開(kāi)頭 :公司縮寫(xiě):RIL版本number so:文件擴(kuò)展3.2.Android RIL的配置與加載 在init.rc文件中,將通過(guò)這種方式來(lái)進(jìn)行Android RIL的加載。service ril-daemon /system/bin/rild -l /system/lib/libreference-ril.so - -d /dev/ttyS0也可以手動(dòng)加載:/system/bin/rild -l /system/lib/libreference-ril.so - -d /dev/ttyS0這兩種方式,都將啟動(dòng)rild守護(hù)進(jìn)程,然后通過(guò)-l參數(shù)將libreference-ril.so共享庫(kù)鏈入,libreference-ril.so的參數(shù)-d是指加載一個(gè)串口設(shè)備,/dev/ttyS0則是這個(gè)串口設(shè)備的具體設(shè)備文件,除了參數(shù)-d外,還有-s代表加載類(lèi)型為socket的設(shè)備,-p代表回環(huán)接口。3.3.Android RIL的編譯結(jié)構(gòu) rild:被編譯成可執(zhí)行文件,rild以守進(jìn)程的形式執(zhí)行。libril:將被編譯為共享庫(kù),并被鏈入rild。Vendor RIL:可以以?xún)煞N方式來(lái)運(yùn)行,如果定義了RIL_SHLIB宏,那么它將被編譯成共享庫(kù),如果沒(méi)定義RIL_SHLIB宏,它將以守護(hù)進(jìn)程程序的方式被調(diào)用執(zhí)行。4.Android RIL的java框架 Android RIL的Java部分也被分為了兩個(gè)模塊,RIL模塊與Phone模塊。其中RIL模塊負(fù)責(zé)進(jìn)行請(qǐng)求以及相應(yīng)的處理,它將直接與RIL的原聲代碼進(jìn)行通信。而Phone模塊則向應(yīng)用程序開(kāi)發(fā)者提供了一系列的電話(huà)功能接口。4.1.RIL模塊結(jié)構(gòu) 在RIL.java中實(shí)現(xiàn)了幾個(gè)類(lèi)來(lái)進(jìn)行與下層rild的通信。它實(shí)現(xiàn)了如下幾個(gè)類(lèi)來(lái)完成操作:RILRequest:代表一個(gè)命令請(qǐng)求RIL.RILSender:負(fù)責(zé)AT指令的發(fā)送RIL.RILReceiver:用于處理主動(dòng)和普通上報(bào)信息RIL.RILSender與RIL.RILReceiver是兩個(gè)線(xiàn)程。RILRequest提供了obtain()方法,用于得到具體的request操作,這些操作被定義在RILConstants.java中(RILConstants.java中定義的request命令與RIL原生代碼中ril.h中定義的request命令是相同的),然后通過(guò)send()函數(shù)發(fā)送EVENT_SEND,在RIL_Sender線(xiàn)程中處理這個(gè)EVENT_SEND將命令寫(xiě)入到stream(socket)中去。Socket是來(lái)自常量SOCKET_NAME_RIL,它與RIL原生代碼部分的s_fdListen所指的socket是同一個(gè)。 當(dāng)有上報(bào)信息來(lái)到時(shí),系統(tǒng)將通過(guò)RILReciver來(lái)得到信息,并進(jìn)行處理。在RILReciver的生命周期里,它一直監(jiān)視著SOCKET_NAME_RIL這個(gè)socket,當(dāng)有數(shù)據(jù)到來(lái)時(shí),它將通過(guò)readRilMessage()方法讀取到一個(gè)完整的響應(yīng),然后通過(guò)processResponse來(lái)進(jìn)行處理。4.2.Phone模塊結(jié)構(gòu)Android通過(guò)暴露Phone模塊來(lái)供上層應(yīng)用程序用戶(hù)使用電話(huà)功能相關(guān)的接口。它為用戶(hù)提供了諸如電話(huà)呼叫,短信息,SIM卡管理之類(lèi)的接口調(diào)用。它的核心部分是類(lèi)GSMPhone,這個(gè)是Gsm的電話(huà)實(shí)現(xiàn),需要通過(guò)PhoneFactory獲取這個(gè)GSMPhone。GSMPhone并不是直接提供接口給上層用戶(hù)使用,而是通過(guò)另外一個(gè)管理類(lèi)TelephonyManager來(lái)供應(yīng)用程序用戶(hù)使用。類(lèi)TelephonyManager實(shí)現(xiàn)了android的電話(huà)相關(guān)操作。它主要使用兩個(gè)服務(wù)來(lái)訪(fǎng)問(wèn)telephony功能:1.ITelephony,提供給上層應(yīng)用程序用戶(hù)與telephony進(jìn)行操作,交互的接口,在packages/apps/Phone中由PhoneInterfaceManager.java實(shí)現(xiàn)。2.ItelephonyRegistry提供了一個(gè)通知機(jī)制,將底層來(lái)的上報(bào)通知給框架中需要得到通知的部分,由TelephonyRegistry.java實(shí)現(xiàn)。 GSMPhone通過(guò)PhoneNotifier的實(shí)現(xiàn)者DefaultPhoneNotifier將具體的事件轉(zhuǎn)化為函數(shù)調(diào)用,通知到TelephonyRegistry。TelephonyRegistry再通過(guò)兩種方式通知給用戶(hù),其一是廣播事件,另外一種是通過(guò)服務(wù)用戶(hù)在TelephonyRegistry中注冊(cè)的IphoneStateListener接口,實(shí)現(xiàn)回調(diào)(回調(diào)方式參見(jiàn)android的aidl機(jī)制)。參考資料 相關(guān)網(wǎng)站:/android//developerworks/cn/opensource/theme/android//wiki/Android_%28operating_system%295 電話(huà)功能概述Android的Radio Interface Layer (RIL)提供了電話(huà)服務(wù)和的radio硬件之間的抽象層。Radio Interface Layer RIL(Radio Interface Layer)負(fù)責(zé)數(shù)據(jù)的可靠傳輸、AT命令的發(fā)送以及response的解析。應(yīng)用處理器通過(guò)AT命令集與帶GPRS功能的無(wú)線(xiàn)通訊模塊通信。AT command由Hayes公司發(fā)明,是一個(gè)調(diào)制解調(diào)器制造商采用的一個(gè)調(diào)制解調(diào)器命令語(yǔ)言,每條命令以字母AT開(kāi)頭。JAVA Framework代碼的路徑為:frameworks/base/telephony/java/android/telephonyandroid.telephony以及android.telephony.gsmCorenative:在hardware/ril目錄中,提供了對(duì)RIL支持的本地代碼,包括4個(gè)文件夾:hardware/ril/includehardware/ril/librilhardware/ril/reference-rilhardware/ril/rildkernel Driver 在Linux內(nèi)核的驅(qū)動(dòng)中,提供了相關(guān)的驅(qū)動(dòng)程序的支持,可以建立在UART或者SDIO,USB等高速的串行總線(xiàn)上。電話(huà)功能各個(gè)部分: hardware/ril/include/telephony/目錄中的ril.h文件是ril部分的基礎(chǔ)頭文件。其中定義的結(jié)構(gòu)體RIL_RadioFunctions如下所示:typedef struct int version; RIL_RequestFunc onRequest; RIL_RadioStateRequest onStateRequest; RIL_Supports supports; RIL_Cancel onCancel; RIL_GetVersion getVersion; RIL_RadioFunctions; RIL_RadioFunctions中包含了幾個(gè)函數(shù)指針的結(jié)構(gòu)體,這實(shí)際上是一個(gè)移植層的接口,下層的庫(kù)實(shí)現(xiàn)后,由rild守護(hù)進(jìn)程得到這些函數(shù)指針,執(zhí)行對(duì)應(yīng)的函數(shù)。幾個(gè)函數(shù)指針的原型為:typedef void (*RIL_RequestFunc) (int request, void *data, size_t datalen, RIL_Token t);typedef RIL_RadioState (*RIL_RadioStateRequest)();typedef int (*RIL_Supports)(int requestCode);typedef void (*RIL_Cancel)(RIL_Token t);typedef const char * (*RIL_GetVersion) (void);其中最為重要的函數(shù)是onRequest(),它是一個(gè)請(qǐng)求執(zhí)行的函數(shù)。5.1 rild守護(hù)進(jìn)程rild 守護(hù)進(jìn)程的文件包含在hardware/ril/rild目錄中,其中包含了rild.c和radiooptions.c兩個(gè)文件,這個(gè)目錄中的文件經(jīng)過(guò)編譯后生成一個(gè)可執(zhí)行程序,這個(gè)程序在系統(tǒng)的安裝路徑在:/system/bin/rildrild.c是這個(gè)守護(hù)進(jìn)程的入口,它具有一個(gè)主函數(shù)的入口main,執(zhí)行的過(guò)程是將上層來(lái)的請(qǐng)求都由這個(gè)函數(shù)RIL_RadioFunctionsonReques()的方法進(jìn)行映射后轉(zhuǎn)換成對(duì)應(yīng)的AT命令的字符串,發(fā)給下層的硬件執(zhí)行。在運(yùn)行過(guò)程中,使用dlopen 打開(kāi)路徑為/system/lib/中名稱(chēng)為libreference-ril.so的動(dòng)態(tài)庫(kù),然后從中取出 RIL_Init符號(hào)來(lái)運(yùn)行。ril_register()注冊(cè):RIL_Init符號(hào)是一個(gè)函數(shù)指針,執(zhí)行這個(gè)函數(shù)后,返回的是一個(gè)RIL_RadioFunctions類(lèi)型的指針。得到這個(gè)指針后,調(diào)用RIL_register()函數(shù),將這個(gè)指針注冊(cè)到libril庫(kù)之中,然后進(jìn)入循環(huán)ril_event_loop()。 事實(shí)上,這個(gè)守護(hù)進(jìn)程提供了一個(gè)申請(qǐng)?zhí)幚淼目蚣?,而具體的功能都是在libril.so和libreference-ril.so中完成的。附:RIL守護(hù)進(jìn)程,開(kāi)機(jī)時(shí)被init守護(hù)進(jìn)程調(diào)用啟動(dòng),里面僅有main函數(shù)作為入口點(diǎn),負(fù)責(zé)完成RIL初始化工作。在rild.c文件中,將完成ril的加載過(guò)程,它會(huì)執(zhí)行如下操作:動(dòng)態(tài)加載Vendor RIL的.so文件執(zhí)行RIL_startEventLoop()開(kāi)啟消息隊(duì)列以進(jìn)行事件監(jiān)聽(tīng)通過(guò)執(zhí)行Vendor RIL的rilInit()方法來(lái)進(jìn)行Vendor RIL與libril的關(guān)系建立。在rild文件夾中還包括一個(gè)radiooptions.c文件,它的作用是通過(guò)串口將一些radio相關(guān)的參數(shù)直接傳給rild來(lái)對(duì)radio進(jìn)行配置。5.2 libreference-ril.so動(dòng)態(tài)庫(kù)libreference-ril.so動(dòng)態(tài)庫(kù)的路徑是:hardware/ril/reference-ril其中主要的文件是reference-ril.c和atchannel.c。這個(gè)庫(kù)必須實(shí)現(xiàn)的是一個(gè)名稱(chēng)為RIL_Init的函數(shù),這個(gè)函數(shù)執(zhí)行的結(jié)果是返回一個(gè)RIL_RadioFunctions結(jié)構(gòu)體的指針,指針指向函數(shù)指針。這個(gè)庫(kù)在執(zhí)行的過(guò)程中需要?jiǎng)?chuàng)建一個(gè)線(xiàn)程來(lái)執(zhí)行實(shí)際的功能。在執(zhí)行的過(guò)程中,這個(gè)庫(kù)將打開(kāi)一個(gè)/dev/ttySXXX的終端(終端的名字是從上層傳入的),然后利用這個(gè)終端控制硬件執(zhí)行。附:在編譯時(shí)libril被鏈入rild,它為rild提供了event處理功能,還提供了在rild與Vendor RIL之間傳遞請(qǐng)求和響應(yīng)消息的能力。Libril提供的主要功能分布在兩個(gè)主要方法內(nèi),一個(gè)是RIL_startEventLoop()方法,另一個(gè)是RIL_register()方法RIL_startEventLoop()方法所提供的功能就是啟用eventLoop線(xiàn)程,開(kāi)始執(zhí)行RIL消息隊(duì)列。RIL_register()方法的主要功能是啟動(dòng)名為rild的監(jiān)聽(tīng)端口,等待java端通過(guò)socket進(jìn)行連接。5.3 libril.so動(dòng)態(tài)庫(kù) libril.so庫(kù)的目錄是:hardware/ril/libril 其中主要的文件為ril.cpp,這個(gè)庫(kù)主要需要實(shí)現(xiàn)的以下幾個(gè)接口為:RIL_startEventLoop(void);void RIL_setcallbacks (const RIL_RadioFunctions *callbacks);RIL_register (const RIL_RadioFunctions *callbacks);RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen);void RIL_onUnsolicitedResponse(int unsolResponse, void *data, size_t datalen);RIL_requestTimedCallback (RIL_TimedCallback callback, void *param, const struct timeval *relativeTime); 這些函數(shù)也是被rild守護(hù)進(jìn)程調(diào)用的,不同的vendor可以通過(guò)自己的方式實(shí)現(xiàn)這幾個(gè)接口,這樣可以保證RIL可以在不同系統(tǒng)的移植。其中 RIL_register()函數(shù)把外部的RIL_RadioFunctions結(jié)構(gòu)體注冊(cè)到這個(gè)庫(kù)之中,在恰當(dāng)?shù)臅r(shí)候調(diào)用相應(yīng)的函數(shù)。在執(zhí)行的過(guò)程中,這個(gè)庫(kù)處理了一些將請(qǐng)求轉(zhuǎn)換成字符串的功能。附:Android自帶的VendorRIL的參考實(shí)現(xiàn)。被編譯成.so文件,由于本部分是廠商定制的重點(diǎn)所在。所以被設(shè)計(jì)為松散耦合,且可靈活配置的。在rild中通過(guò)opendl()的方式加載。librefrence.so負(fù)責(zé)直接與radio通信,這包括將來(lái)自libril的指令轉(zhuǎn)換為AT指令,并且將AT指令寫(xiě)入radio中。reference-ril會(huì)接收調(diào)用者傳來(lái)的參數(shù),參數(shù)內(nèi)容為與radio的通信方式。如通過(guò)串口連接radio,那么參數(shù)為這種形式:-d /dev/ttySx5.4 ril層的所有代碼分析5.4.1 ril/rild下的文件 rild.c-mian()為函數(shù)入口int main(int argc, char *argv)/./OpenLib:#endif switchUser();/打開(kāi)dlopen()加載vendor RIL 獲取由RIL_register(funcs);注冊(cè)進(jìn)來(lái)的參數(shù),并解析dlHandle = dlopen(rilLibPath, RTLD_NOW); if (dlHandle = NULL) fprintf(stderr, dlopen failed: %sn, dlerror(); exit(-1);/1:消息隊(duì)列的入口1.到select阻塞/每當(dāng)看到打印信息,不按順序打下來(lái)說(shuō)明阻塞RIL_startEventLoop();/通過(guò)dlsym函數(shù)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025煙臺(tái)中考數(shù)學(xué)真題試卷
- 企業(yè)并購(gòu)重組資金支持合同
- 2025年環(huán)境影響評(píng)價(jià)公眾參與與環(huán)境保護(hù)公眾參與機(jī)制實(shí)施路徑報(bào)告
- 教育精準(zhǔn)扶貧政策實(shí)施與農(nóng)村教育質(zhì)量監(jiān)控體系構(gòu)建報(bào)告001
- 2025年文化產(chǎn)業(yè)園產(chǎn)業(yè)集聚與服務(wù)體系構(gòu)建中的風(fēng)險(xiǎn)與對(duì)策報(bào)告
- 電動(dòng)汽車(chē)電池?zé)峁芾砑夹g(shù)在安全性能提升中的應(yīng)用研究報(bào)告
- 2025年直播電商主播影響力評(píng)估與營(yíng)銷(xiāo)策略?xún)?yōu)化指南實(shí)戰(zhàn)報(bào)告
- 能源與資源行業(yè):石油化工產(chǎn)業(yè)投資機(jī)會(huì)與風(fēng)險(xiǎn)預(yù)警報(bào)告
- 2025年中國(guó)塑料捆扎繩行業(yè)投資前景及策略咨詢(xún)研究報(bào)告
- 游戲化商業(yè)模式的創(chuàng)新與實(shí)踐
- 機(jī)房接地方案
- 鋼筋焊接接頭平行檢驗(yàn)記錄
- 醫(yī)用電子儀器原理與實(shí)驗(yàn):第七章 心臟起博器與除顫器
- 食堂從業(yè)人員知識(shí)培訓(xùn)考核試題與答案
- 合同能源管理協(xié)議書(shū)范本
- 壓力容器使用年度檢查報(bào)告(范本)
- 壓力管道安裝質(zhì)量證明書(shū)新
- 轉(zhuǎn)預(yù)備、預(yù)備轉(zhuǎn)正各種無(wú)記名投票表格匯總(20201230021242)
- 腰椎間盤(pán)突出癥的診斷、鑒別診斷與分型
- 閥體零件機(jī)械加工工藝及裝備設(shè)計(jì)
- LD型單梁起重機(jī)使用說(shuō)明書(shū)
評(píng)論
0/150
提交評(píng)論