第一部分 c代碼
Android源碼中,hardware/ril目錄中包含著Android的telephony底層源碼。這個(gè)目錄下包含著三個(gè)子目錄,下面是對(duì)三個(gè)子目錄的具體分析。
一、目錄hardware/ril/include分析:
只有一個(gè)頭文件ril.h包含在此目錄下。ril.h中定義了76個(gè)如下類型的宏:
RIL_REQUEST_XXX ,
這些宏代表著客戶進(jìn)程可以向Android telephony發(fā)送的命令,包括SIM卡相關(guān)的功能,打電話,發(fā)短信,網(wǎng)絡(luò)信號(hào)查詢等。好像沒有操作地址本的功能?
二、目錄hardware/ril/libril分析。本目錄下代碼負(fù)責(zé)與客戶進(jìn)程進(jìn)行交互。在接收客戶進(jìn)程命令后,調(diào)用相應(yīng)函數(shù)進(jìn)行處理,然后將命令響應(yīng)結(jié)果傳回客戶進(jìn)程。在收到來自網(wǎng)絡(luò)端的事件后,也傳給客戶進(jìn)程。
- 文件ril_commands.h:列出了telephony可以接收的命令;每個(gè)命令對(duì)應(yīng)的處理函數(shù);以及命令響應(yīng)的處理函數(shù)。
- 文件ril_unsol_commands.h:列出了telephony可以接收的事件類型;對(duì)每個(gè)事件的處理函數(shù);以及WAKE Type???
- 文件ril_event.h/cpp:處理與事件源(端口,modem等)相關(guān)的功能。ril_event_loop監(jiān)視所有注冊(cè)的事件源,當(dāng)某事件源有數(shù)據(jù)到來時(shí),相應(yīng)事件源的回調(diào)函數(shù)被觸發(fā)(firePending -> ev->func())
- 文件ril.cpp:
RIL_register函數(shù):打開監(jiān)聽端口,接收來自客戶進(jìn)程的命令請(qǐng)求 (s_fdListen = android_get_control_socket(SOCKET_NAME_RIL);),當(dāng)與某客戶進(jìn)程連接建立時(shí),調(diào)用listenCallback函數(shù);創(chuàng)建一單獨(dú)線程監(jiān)視并處理所有事件源 (通過ril_event_loop)
listenCallback函數(shù):當(dāng)與客戶進(jìn)程連接建立時(shí),此函數(shù)被調(diào)用。此函數(shù)接著調(diào)用processCommandsCallback處理來自客戶進(jìn)程的命令請(qǐng)求
processCommandsCallback函數(shù):具體處理來自客戶進(jìn)程的命令請(qǐng)求。對(duì)每一個(gè)命令,ril_commands.h中都規(guī)定了對(duì)應(yīng)的命 令處理函數(shù)(dispatchXXX),processCommandsCallback會(huì)調(diào)用這個(gè)命令處理函數(shù)進(jìn)行處理。
dispatch系列函數(shù):此函數(shù)接收來自客戶進(jìn)程的命令己相應(yīng)參數(shù),并調(diào)用onRequest進(jìn)行處理。
RIL_onUnsolicitedResponse函數(shù):將來自網(wǎng)絡(luò)端的事件封裝(通過調(diào)用responseXXX)后傳給客戶進(jìn)程。
RIL_onRequestComplete函數(shù):將命令的最終響應(yīng)結(jié)構(gòu)封裝(通過調(diào)用responseXXX)后傳給客戶進(jìn)程。
response系列函數(shù):對(duì)每一個(gè)命令,都規(guī)定了一個(gè)對(duì)應(yīng)的response函數(shù)來處理命令的最終響應(yīng);對(duì)每一個(gè)網(wǎng)絡(luò)端的事件,也規(guī)定了一個(gè)對(duì)應(yīng)的 response函數(shù)來處理此事件。response函數(shù)可被onUnsolicitedResponse或者onRequestComplete調(diào)用。
三、目錄hardware/ril/reference-ril分析。本目錄下代碼主要負(fù)責(zé)與modem進(jìn)行交互。
- 文件reference-ril.c:此文件核心是兩個(gè)函數(shù):onRequest和onUnsolicited
onRequest 函數(shù):在這個(gè)函數(shù)里,對(duì)每一個(gè)RIL_REQUEST_XXX請(qǐng)求,都轉(zhuǎn)化成相應(yīng)的AT command,發(fā)送給modem,然后睡眠等待。當(dāng)收到此AT command的最終響應(yīng)后,線程被喚醒,將響應(yīng)傳給客戶進(jìn)程(RIL_onRequestComplete -> sendResponse)。
onUnsolicited函數(shù):這個(gè)函數(shù)處理modem從網(wǎng)絡(luò)端收到的各種事件,如網(wǎng)絡(luò)信號(hào)變化,撥入的電話,收到短信等。然后將時(shí)間傳給客戶進(jìn)程 (RIL_onUnsolicitedResponse -> sendResponse)
- 文件atchannel.c:負(fù)責(zé)向modem讀寫數(shù)據(jù)。其中,寫數(shù)據(jù)(主要是AT command)功能運(yùn)行在主線程中,讀數(shù)據(jù)功能運(yùn)行在一個(gè)單獨(dú)的讀線程中。
函數(shù)at_send_command_full_nolock:運(yùn)行在主線程里面。將一個(gè)AT command命令寫入modem后進(jìn)入睡眠狀態(tài)(使用 pthread_cond_wait或類似函數(shù)),直到modem讀線程將其喚醒。喚醒后此函數(shù)獲得了AT command的最終響應(yīng)并返回。
函數(shù)readerLoop運(yùn)行在一個(gè)單獨(dú)的讀線程里面,負(fù)責(zé)從modem中讀取數(shù)據(jù)。讀到的數(shù)據(jù)可分為三種類型:網(wǎng)絡(luò)端傳入的事件;modem對(duì)當(dāng)前AT command的部分響應(yīng);modem對(duì)當(dāng)前AT command的全部響應(yīng)。對(duì)第三種類型的數(shù)據(jù)(AT command的全部響應(yīng)),讀線程喚醒(pthread_cond_signal)睡眠狀態(tài)的主線程。
第二部分 Java代碼
Android中,telephony相關(guān)的java代碼主要在下列目錄中:
1. frameworks/base/telephony/java/android/telephony
2. frameworks/base/telephony/java/com/android/internal/telephony
3. frameworks/base/services/java/com/android/server/TelephonyRegistry.java
4. packages/apps/Phone
其中,目錄1中的代碼提供Android telephony的公開接口,任何具有權(quán)限的第三方應(yīng)用都可使用,如接口類TelephonyManager。
目錄2/3中的代碼提供一系列內(nèi)部接口,目前第三方應(yīng)用還不能使用。當(dāng)前似乎只有packages/apps/Phone能夠使用
目錄4是一個(gè)特殊應(yīng)用,或者理解為一個(gè)平臺(tái)內(nèi)部進(jìn)程。其他應(yīng)用通過intent方式調(diào)用這個(gè)進(jìn)程的服務(wù)。
TelephonyManager主要使用兩個(gè)服務(wù)來訪問telephony功能:
1. ITelephony, 提供與telephony 進(jìn)行操作,交互的接口,在packages/apps/Phone中由PhoneInterfaceManager.java實(shí)現(xiàn)。
2. ITelephonyRegistry, 提供登記telephony事件的接口。由frameworks/base/services/java/com/android/server/TelephonyRegistry.java實(shí)現(xiàn)。
interface CommandsInterface 描述了對(duì)電話的所有操作接口,如命令, 查詢狀態(tài),以及電話事件監(jiān)聽等
class BaseCommands是CommandsInterface的直接派生類,實(shí)現(xiàn)了電話事件的處理(發(fā)送message給對(duì)應(yīng)的handler)。
而class RIL又派生自BaseCommands。RIL負(fù)責(zé)實(shí)際實(shí)現(xiàn)CommandsInterface中的接口方法。RIL通過Socket和rild守護(hù)進(jìn) 程進(jìn)行通訊。對(duì)于每一個(gè)命令接口方法,如acceptCall,或者狀態(tài)查詢,將它轉(zhuǎn)換成對(duì)應(yīng)的RIL_REQUEST_XXX,發(fā)送給rild。線程 RILReceiver監(jiān)聽socket,當(dāng)有數(shù)據(jù)上報(bào)時(shí),讀取該數(shù)據(jù)并處理。讀取的數(shù)據(jù)有兩種,
1. 電話事件,RIL_UNSOL_xxx, RIL讀取相應(yīng)數(shù)據(jù)后,發(fā)送message給對(duì)應(yīng)的handler (詳見函數(shù)processUnsolicited)
2. 命令的異步響應(yīng)。(詳見函數(shù)processSolicited)
interface Phone描述了對(duì)電話的所有操作接口。 PhoneBase直接從Phone 派生而來。而另外兩個(gè)類,CDMAPhone和GSMPhone,又從PhoneBase派生而來,分別代表對(duì)CDMA 和GSM的操作。
PhoneProxy也從Phone直接派生而來。當(dāng)當(dāng)前不需要區(qū)分具體是CDMA Phone還是GSM Phone時(shí),可使用PhoneProxy。
抽象類Call代表一個(gè)call,有兩個(gè)派生類CdmaCall和GsmCall。
interface PhoneNotifier定義電話事件的通知方法
DefaultPhoneNotifier從PhoneNotifier派生而來。在其方法實(shí)現(xiàn)中,通過調(diào)用service ITelephonyRegistry來發(fā)布電話事件。
service ITelephonyRegistey由frameworks/base/services/java/com/android/server/TelephonyRegistry.java實(shí)現(xiàn)。這個(gè)類通過廣播intent,從而觸發(fā)對(duì)應(yīng)的broadcast receiver。
在PhoneApp創(chuàng)建時(shí),
sPhoneNotifier = new DefaultPhoneNotifier();
...
sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);
然后根據(jù)當(dāng)前phone是cdma還是gsm,創(chuàng)建對(duì)應(yīng)的phone,如
sProxyPhone = new PhoneProxy(new GSMPhone(context,
sCommandsInterface, sPhoneNotifier));
下面我們來研究一個(gè)電話打出去的流程。
1. TwelveKeyDialer.java, onKeyUp()
2. TwelveKeyDialer.java, placeCall()
3. OutgoingCallBroadcaster.java, onCreate()
sendOrderedBroadcast(broadcastIntent, PERMISSION,
new OutgoingCallReceiver(), null, Activity.RESULT_OK, number, null);
4. OutgoingCallBroadcaster.java, OutgoingCallReceiver
doReceive -> context.startActivity(newIntent);
5. InCallScreen.java, onCreate/onNewIntent
6. InCallScreen.java, placeCall
7. PhoneUtils.java, placeCall
8. GSMPhone.java, dial
9. GsmCallTracker.java, dial
10. RIL.java, dial
RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);
...
send(rr);
下面來研究一個(gè)incoming call的流程:
1. 創(chuàng)建GsmPhone時(shí),mCT = new GsmCallTracker(this);
2. 創(chuàng)建GsmCallTracker時(shí):
cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null); -->
mCallStateRegistrants.add(r);
3. RIL中的RILReceiver線程首先讀取從rild中傳來的數(shù)據(jù):processResponse -> processUnsolicited
4. 對(duì)應(yīng)于incoming call,RIL收到RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED 消息,觸發(fā)mCallStateRegistrants中的所有記錄。
5. GsmCallTracker處理EVENT_CALL_STATE_CHANGE,調(diào)用pollCallsWhenSafe
6. 函數(shù)pllCallsWhenSafe 處理:
lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
cm.getCurrentCalls(lastRelevantPoll);
7. RIL::getCurrentCalls
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result);
...
send(rr);
8. 接著RIL調(diào)用processSolicited處理RIL_REQUEST_GET_CURRENT_CALLS的返回結(jié)果
9. GsmCallTracker的handleMessage被觸發(fā),處理事件EVENT_POLL_CALLS_RESULT,調(diào)用函數(shù)
handlePollCalls
10. handlPollCalls 調(diào)用
phone.notifyNewRingingConnection(newRinging);
11. PhoneApp中創(chuàng)建CallNotifier
12. CallNotifier注冊(cè):
registerForNewRingingConnection -> mNewRingingConnectionRegistrants.addUnique(h, what, obj);