




已閱讀5頁(yè),還剩13頁(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)介
Framework中的Ril源碼分析目錄(?)- 一概述 二RILRequest 三發(fā)送子線(xiàn)程 如何把數(shù)據(jù)發(fā)送到mSenderThread mSenderThread子線(xiàn)程把請(qǐng)求發(fā)送給RILC 四接收子線(xiàn)程 接收數(shù)據(jù)的過(guò)程 數(shù)據(jù)的處理流程 URC消息處理流程 非URC消息處理流程 為了區(qū)別RIL層中的RIL.cpp,我們約定framework中的RIL.java文件描述為RILJ,而hardware中的RIL.cpp描述為RILC。一、概述 所有上層對(duì)RIL層的請(qǐng)求,最終都需要在RILJ中轉(zhuǎn)換為RIL層可識(shí)別的命令,然后通過(guò)Socket通道傳輸下去;同時(shí),RIL層數(shù)據(jù)的上報(bào),也要通過(guò) RILJ進(jìn)行解碼,還原為上層容易識(shí)別的格式。因此,RILJ是framework與RIL層交互的通道。 RILJ有兩個(gè)主要特點(diǎn): 1、開(kāi)啟了兩個(gè)獨(dú)立線(xiàn)程分別負(fù)責(zé)發(fā)送數(shù)據(jù)和接收數(shù)據(jù) 2、數(shù)據(jù)的發(fā)送和接收是異步的 第一個(gè)特點(diǎn)很容易理解,而對(duì)于第二個(gè)特點(diǎn)有衍生出來(lái)了另一個(gè)問(wèn)題:既然是異步的消息機(jī)制,也就是說(shuō)發(fā)送者在發(fā)送完數(shù)據(jù)后就可以返回,那么當(dāng)?shù)玫交貞?yīng)后,就要有一種方法去找到當(dāng)初的請(qǐng)求者,并把結(jié)果返回給他。那么這個(gè)方法是什么呢? 這個(gè)方法就是令牌系統(tǒng),我們將在第二節(jié)介紹。 有了以上簡(jiǎn)要的認(rèn)識(shí),我們從RILJ的入口開(kāi)始展開(kāi)我們的分析,也就是RILJ的構(gòu)造函數(shù): javaview plaincopy RIL.java public RIL(Context context, int preferredNetworkType, int cdmaSubscription) super(context); /發(fā)送子線(xiàn)程 mSenderThread = new HandlerThread(RILSender); mSenderThread.start(); Looper looper = mSenderThread.getLooper(); /mSender是發(fā)送子線(xiàn)程的Handler,通過(guò)他可以發(fā)送數(shù)據(jù) mSender = new RILSender(looper); /接收子線(xiàn)程 mReceiver = new RILReceiver(); mReceiverThread = new Thread(mReceiver, RILReceiver); mReceiverThread.start(); 可以看到,在構(gòu)造函數(shù)中開(kāi)啟了兩個(gè)獨(dú)立的子線(xiàn)程:mSenderThread用于給RILC發(fā)送數(shù)據(jù),而mReceiverThread用于接收RILC上報(bào)的數(shù)據(jù)。 下面我們分析兩個(gè)子線(xiàn)程的處理流程。而在介紹他們之前,我們先來(lái)介紹以下在RIL層中傳遞的消息的格式:RILRequest。二、RILRequest 我們單獨(dú)拿出一小節(jié)來(lái)介紹RILRequest對(duì)象,是因?yàn)槔锩姘宋覀冊(cè)谖恼麻_(kāi)始地方介紹的“消息異步傳輸”的秘密。 首先來(lái)看他的屬性:class RILRequest ,說(shuō)明這是一個(gè)獨(dú)立的類(lèi),沒(méi)有繼承任何的父類(lèi)或接口。他也在RIL.java中,同時(shí)也是RIL.java中除了RIL外唯一的類(lèi)。 我們?cè)賮?lái)看一下RILRequest的構(gòu)成: javaview plaincopy class RILRequest /令牌 int mSerial; int mRequest; Message mResult; Parcel mp; RILRequest mNext; /生成一個(gè)RILRequest的消息對(duì)象 static RILRequest obtain(int request, Message result) /釋放資源 void release() /構(gòu)造函數(shù),內(nèi)容為空 private RILRequest() /重置令牌 static void resetSerial() sNextSerial.set(sRandom.nextInt(); /用于調(diào)試 String serialString() /異常處理 void onError(int error, Object ret) 這個(gè)類(lèi)并不復(fù)雜,主要的包括一些成員變量和兩個(gè)重要的成員函數(shù):用于生成消息對(duì)象的obtain方法和用于釋放對(duì)象的release方法。我們先來(lái)介紹他的成員變量: mSerial:這個(gè)變量就是一個(gè)令牌,每生成(obtain)一個(gè)新的請(qǐng)求,都將產(chǎn)生一個(gè)遞增的、唯一的mSerial,當(dāng)從RILC得到一個(gè)數(shù)據(jù)后, 我們將通過(guò)mSerial找到當(dāng)初發(fā)送這個(gè)請(qǐng)求的對(duì)象。這也就是異步通信最關(guān)鍵的聯(lián)系點(diǎn)。我們?cè)赗IL層談到的令牌(token)就是這個(gè)東西。 mRequest:請(qǐng)求碼,需要和RIL層中的ril_commands.h文件內(nèi)定義的請(qǐng)求碼一致。 mResult:生成當(dāng)前請(qǐng)求的請(qǐng)求者。從RILC中得到數(shù)據(jù)后,需要把數(shù)據(jù)處理后返回給mResult指向的對(duì)象。 mp:附加數(shù)據(jù)。 mNext:鏈表結(jié)構(gòu),代表下一個(gè)RILRequest。 然后我們介紹RILRequest中主要的方法,先來(lái)看看obtain: javaview plaincopy static RILRequest obtain(int request, Message result) RILRequest rr = null; synchronized(sPoolSync) /釋放的RILRequest可以循環(huán)利用 if (sPool != null) rr = sPool; sPool = rr.mNext; rr.mNext = null; sPoolSize-; if (rr = null) rr = new RILRequest(); rr.mSerial = sNextSerial.getAndIncrement(); rr.mRequest = request; rr.mResult = result; rr.mp = Parcel.obtain(); rr.mp.writeInt(request); rr.mp.writeInt(rr.mSerial); return rr; 在obtain過(guò)程中,涉及到了sPool的用法,這個(gè)對(duì)象代表了一個(gè)RILRequest對(duì)象的鏈表,作用就是對(duì)RILRequest的循環(huán)利用, 具體原理就是:當(dāng)一個(gè)RILRequest被銷(xiāo)毀(release)的時(shí)候,可以把當(dāng)前的RILRequest保存在sPool中,等下次需要申請(qǐng) RILRequest時(shí)就去sPool中取出用即可,而無(wú)需重復(fù)的申請(qǐng)(new)RILRequest。同時(shí)sPool的最大個(gè)數(shù)為 4(MAX_POOL_SIZE)。 然后在obtain中對(duì)RILRequest對(duì)象的mSerial進(jìn)行初始化,前面說(shuō)過(guò),這個(gè)值是當(dāng)前請(qǐng)求的令牌,是唯一的。他是通過(guò) getAndIncrement的方式生成的。這里補(bǔ)充以下AtomicInteger的知識(shí):AtomicInteger是一個(gè)提供原子操作的 Integer的類(lèi)。在Java語(yǔ)言中,+i和i+操作并不是線(xiàn)程安全的,在使用的時(shí)候,不可避免的會(huì)用到synchronized關(guān)鍵字。而 AtomicInteger則通過(guò)一種線(xiàn)程安全的加減操作接口??梢院?jiǎn)單的理解為,getAndIncrement的方法可以得到一個(gè)絕對(duì)遞增的整數(shù)。 接下來(lái)就是mResult的初始化,他的初始化過(guò)程很簡(jiǎn)單,就是簡(jiǎn)單的賦值。 然后是mp,他的初始化過(guò)程中把上面的request和mSerial都寫(xiě)了進(jìn)去。 這就是生成RILRequest的過(guò)程。 接下來(lái)看看release方法: javaview plaincopy void release() synchronized (sPoolSync) if (sPoolSize 8) & 0xff); dataLength3 = (byte)(data.length) & 0xff); /通過(guò)Socket通道發(fā)送數(shù)據(jù) s.getOutputStream().write(dataLength); s.getOutputStream().write(data); catch (IOException ex) catch (RuntimeException exc) break; case EVENT_WAKE_LOCK_TIMEOUT: break; 發(fā)送的過(guò)程比較直觀,就是通過(guò)Socket通道把數(shù)據(jù)長(zhǎng)度(dataLength)和數(shù)據(jù)(data)發(fā)送出去。四、接收子線(xiàn)程 接收子線(xiàn)程要完成的就是對(duì)接收數(shù)據(jù)的處理操作。我們還分為兩步去分析:1、如何接收的消息;2、消息的處理流程。4.1、接收數(shù)據(jù)的過(guò)程 我們直接來(lái)看接收子線(xiàn)程的run方法: javaview plaincopy public void run() for (;) /開(kāi)啟Socket通道 s = new LocalSocket(); l = new LocalSocketAddress(SOCKET_NAME_RIL, LocalSocketAddress.Namespace.RESERVED); s.connect(l); mSocket = s; InputStream is = mSocket.getInputStream(); /接收數(shù)據(jù)過(guò)程 for (;) Parcel p; /從通道讀取數(shù)據(jù) length = readRilMessage(is, buffer); if (length 0) break; p = Parcel.obtain(); p.unmarshall(buffer, 0, length); p.setDataPosition(0); /處理數(shù)據(jù) processResponse(p); p.recycle(); /關(guān)閉Socket,然后重新打開(kāi) mSocket.close(); mSocket = null; /清除令牌 RILRequest.resetSerial(); /清除所有請(qǐng)求 clearRequestList(RADIO_NOT_AVAILABLE, false); /通知ril連接狀態(tài)改變 notifyRegistrantsRilConnectionChanged(-1); 從上面的過(guò)程中我們看到,我們是在接收的子線(xiàn)程中打開(kāi)了Socket的通道,并且在通道內(nèi)通過(guò)for死循環(huán)不斷檢測(cè)(readRilMessage)數(shù)據(jù),然后通過(guò)processResponse去處理。如果讀取的過(guò)程出現(xiàn)異常,將會(huì)關(guān)閉Socket通道,并且清除令牌和請(qǐng)求列表,重新打開(kāi)Socket。 我們現(xiàn)在看一下readRilMessage的過(guò)程,至于處理的流程放到下一節(jié)介紹。javaview plaincopy private static int readRilMessage(InputStream is, byte buffer) throws IOException /先讀取數(shù)據(jù)的長(zhǎng)度 do /從InputStream中讀取數(shù)據(jù) countRead = is.read(buffer, offset, remaining); if (countRead 0); /計(jì)算數(shù)據(jù)長(zhǎng)度 messageLength = (buffer0 & 0xff) 24) | (buffer1 & 0xff) 16) | (buffer2 & 0xff) 8) | (buffer3 & 0xff); remaining = messageLength; /再讀取有效數(shù)據(jù) do countRead = is.read(buffer, offset, remaining); if (countRead 0); return messageLength; 可以看出,返回的數(shù)據(jù)分為兩部分,數(shù)據(jù)長(zhǎng)度+數(shù)據(jù)內(nèi)容,我們通過(guò)對(duì)InputStream的連續(xù)讀取得到了完整的數(shù)據(jù),并把數(shù)據(jù)的長(zhǎng)度返回出來(lái),而數(shù)據(jù)的內(nèi)容通過(guò)buffer帶出來(lái)。 下面介紹數(shù)據(jù)的處理流程(processResponse)。4.2、數(shù)據(jù)的處理流程 在RIL層源碼分析文檔中我們介紹過(guò),RIL層收到的消息分為兩部分: 一部分是Modem主動(dòng)上報(bào)的消息,比如新短信的提醒、Modem狀態(tài)的改變等,這類(lèi)消息稱(chēng)為URC消息; 另一部分是由終端發(fā)送給Modem后,Modem給出的回應(yīng),屬于非URC消息; 對(duì)于URC消息來(lái)說(shuō),只需要調(diào)用相應(yīng)的通知機(jī)制即可;而對(duì)于非URC消息,我們還需要把相應(yīng)的數(shù)據(jù)返回給當(dāng)初發(fā)送請(qǐng)求的單位。 既然RIL層對(duì)消息的處理方式不同,那么對(duì)應(yīng)的在RILJ中也要分開(kāi)處理: javaview plaincopy private void processResponse (Parcel p) int type; /得到數(shù)據(jù)的類(lèi)型,是URC消息還是非URC消息 type = p.readInt(); if (type = RESPONSE_UNSOLICITED) /URC消息的處理 processUnsolicited (p); else if (type = RESPONSE_SOLICITED) /非URC消息的處理 RILRequest rr = processSolicited (p); if (rr != null) rr.release(); decrementWakeLock(); 上面看到,URC消息是通過(guò)processUnsolicited處理的,而非URC消息是由processSolicited處理的,我們分別介紹兩種處理流程。4.2.1、URC消息處理流程 URC消息是由processUnsolicited處理的: javaview plaincopy private void processUnsolicited (Parcel p) int response; Object ret; /讀取當(dāng)前消息的消息碼 response = p.readInt(); /先處理 switch(response) case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret = responseVoid(p); break; case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret = responseVoid(p); break; case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: ret = responseVoid(p); break; case RIL_UNSOL_RESPONSE_NEW_SMS: ret = responseString(p); break; . /再次處理 switch(response) case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: /Radio狀態(tài)改變 switchToRadioState(newState); break; case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: /通知call狀態(tài)改變 mCallStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null); break; case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: /通知網(wǎng)絡(luò)狀態(tài)改變 mVoiceNetworkStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null); break; case RIL_UNSOL_RESPONSE_NEW_SMS: /新短信 SmsMessage sms; sms = SmsMessage.newFromCMT(a); if (mGsmSmsRegistrant != null) /發(fā)送短信通知 mGsmSmsRegistrant.notifyRegistrant(new AsyncResult(null, sms, null); break; case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: /短信報(bào)告 mSmsStatusRegistrant.notifyRegistrant( new AsyncResult(null, ret, null); break; 上面代碼只挑出部分消息的處理代碼,從中可以看到,URC消息的處理要經(jīng)過(guò)兩個(gè)switch語(yǔ)句的處理: A、第一個(gè)switch: 根據(jù)不同的消息碼對(duì)數(shù)據(jù)進(jìn)行初步解析,得到上報(bào)的有效數(shù)據(jù)。 responseVoid:當(dāng)前消息的附帶數(shù)據(jù)為空。 responseString:當(dāng)前消息的附帶數(shù)據(jù)為String型,需要得到String。 responseInts:當(dāng)前消息的附帶數(shù)據(jù)為int型的數(shù)組,需要得到這個(gè)數(shù)組。 B、第二個(gè)switch 在這個(gè)switch語(yǔ)句中針對(duì)不同的消息碼用剛剛得到的有效數(shù)據(jù)進(jìn)行不同的處理,主要就是調(diào)用相應(yīng)的管理者去做相應(yīng)的通知。4.2.2、非URC消息處理流程 非URC消息是在processSolicited中處理的: javaview plaincopy private RILRequest processSolicited (Parcel p) RILRequest rr; /得到當(dāng)前的RILRequest對(duì)象,然后從mRequestList中將其刪除 rr = findAndRemoveRequestFromList(serial); /得到RIL上報(bào)的數(shù)據(jù) switch (rr.mRequest) case RIL_REQUEST_GET_SIM_STATUS: ret = responseIccCardStatus(p); break; case RIL_REQUEST_ENTER_SIM_PIN: ret = responseInts(p); break; case RIL_REQUEST_ENTER_SIM_PUK: ret = responseInts(p); break; case RIL_REQUEST_ENTER_SIM_PIN2: ret = responseInts(p); break; case RIL_REQUEST_ENTER_SIM_PUK2: ret = responseInts(p); break; case RIL_REQUEST_CHANGE_SIM_PIN: ret = responseInts(p); break; case RIL_REQUEST_CHANGE_SIM_PIN2: ret = responseInts(p); break; case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION: ret = responseInts(p); break; case RIL_REQUEST_G
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 農(nóng)田受災(zāi)賠償協(xié)議書(shū)
- 內(nèi)部共同采購(gòu)協(xié)議書(shū)
- 人力期刊轉(zhuǎn)讓協(xié)議書(shū)
- 山東省文登市大水泊中學(xué)2025年生物高二第二學(xué)期期末達(dá)標(biāo)檢測(cè)模擬試題含解析
- 太湖創(chuàng)意職業(yè)技術(shù)學(xué)院《工程制圖實(shí)訓(xùn)》2023-2024學(xué)年第二學(xué)期期末試卷
- 南開(kāi)大學(xué)濱海學(xué)院《材料分析測(cè)試與表征》2023-2024學(xué)年第二學(xué)期期末試卷
- 東北四市一模試題2025屆高二下化學(xué)期末學(xué)業(yè)質(zhì)量監(jiān)測(cè)試題含解析
- 2025年湖北省仙桃市漢江高級(jí)中學(xué)化學(xué)高二第二學(xué)期期末質(zhì)量檢測(cè)試題含解析
- 浙江大學(xué)《網(wǎng)絡(luò)仿真與虛擬化(實(shí)驗(yàn))》2023-2024學(xué)年第二學(xué)期期末試卷
- 山東省萊陽(yáng)市一中2025年化學(xué)高二第二學(xué)期期末監(jiān)測(cè)模擬試題含解析
- 行政案例分析-終結(jié)性考核-國(guó)開(kāi)(SC)-參考資料
- 04S519小型排水構(gòu)筑物(含隔油池)圖集
- 小學(xué)語(yǔ)文作文:五感法描寫(xiě)課件
- 《康復(fù)醫(yī)學(xué)》PPT課件(PPT 105頁(yè))
- 心理學(xué)在船舶安全管理中的應(yīng)用
- 實(shí)驗(yàn)室生物安全委員會(huì)及其工作職責(zé)
- 光學(xué)零件工藝學(xué)
- 三一重工SCC2000履帶吊履帶式起重機(jī)技術(shù)參數(shù)
- 浙工大 《大學(xué)英語(yǔ)》專(zhuān)升本 復(fù)習(xí)試卷 及答案
- [精品]GA38-2004《銀行營(yíng)業(yè)場(chǎng)所風(fēng)險(xiǎn)等級(jí)和防護(hù)級(jí)別的規(guī)定》
- 千斤頂詳細(xì)設(shè)計(jì)
評(píng)論
0/150
提交評(píng)論