Android源碼目錄hardware/ril/libril中總共包含5個C/CPP檔案,它們分別是ril_commands.h、ril_unsol_commands.h、ril_event.h、ril_event.cpp和ril.cpp。這篇文章主要分析ril.cpp檔案。
我們可以將該檔案劃分為定義部分和實現部分,先來看定義部分:
#define LOG_TAG "RILC"</p><p>#include <hardware_legacy/power.h></p><p>#include <telephony/ril.h><br />#include <telephony/ril_cdma_sms.h><br />#include <cutils/sockets.h><br />#include <cutils/jstring.h><br />#include <cutils/record_stream.h><br />#include <utils/Log.h><br />#include <utils/SystemClock.h><br />#include <pthread.h><br />#include <binder/Parcel.h><br />#include <cutils/jstring.h></p><p>#include <sys/types.h><br />#include <pwd.h></p><p>#include <stdio.h><br />#include <stdlib.h><br />#include <stdarg.h><br />#include <string.h><br />#include <unistd.h><br />#include <fcntl.h><br />#include <time.h><br />#include <errno.h><br />#include <assert.h><br />#include <ctype.h><br />#include <alloca.h><br />#include <sys/un.h><br />#include <assert.h><br />#include <netinet/in.h><br />#include <cutils/properties.h></p><p>#include <ril_event.h></p><p>namespace android {</p><p>#define PHONE_PROCESS "radio"</p><p>#define SOCKET_NAME_RIL "rild"<br />#define SOCKET_NAME_RIL_DEBUG "rild-debug"</p><p>#define ANDROID_WAKE_LOCK_NAME "radio-interface"</p><p>#define PROPERTY_RIL_IMPL "gsm.version.ril-impl"</p><p>// match with constant in RIL.java<br />#define MAX_COMMAND_BYTES (8 * 1024)</p><p>// Basically: memset buffers that the client library<br />// shouldn't be using anymore in an attempt to find<br />// memory usage issues sooner.<br />#define MEMSET_FREED 1</p><p>// 常見的擷取數組元素個數的方法<br />#define NUM_ELEMS(a) (sizeof (a) / sizeof (a)[0])</p><p>// 返回兩數中較小者<br />#define MIN(a,b) ((a)<(b) ? (a) : (b))</p><p>/* 回複類型:經過請求的回複和未經請求的回複*/<br />#define RESPONSE_SOLICITED 0<br />#define RESPONSE_UNSOLICITED 1</p><p>/* Negative values for private RIL errno's */<br />#define RIL_ERRNO_INVALID_RESPONSE -1</p><p>// request, response, and unsolicited msg print macro<br />// 即列印緩衝區printBuf的大小<br />#define PRINTBUF_SIZE 8096</p><p>// Enable RILC log<br />#define RILC_LOG 0</p><p>#if RILC_LOG<br /> // 三個宏的調用順序是startRequest - printRequest - closeRequest<br />// 這樣列印出來的請求命令將包含在()中<br /> #define startRequest sprintf(printBuf, "(")<br /> #define closeRequest sprintf(printBuf, "%s)", printBuf)<br /> #define printRequest(token, req) \<br /> LOGD("[%04d]> %s %s", token, requestToString(req), printBuf)<br />// 三個宏的調用順序是startResponse - printResponse - closeResponse<br />// 這樣列印出來的回複資訊將包含在{}中<br /> #define startResponse sprintf(printBuf, "%s {", printBuf)<br /> #define closeResponse sprintf(printBuf, "%s}", printBuf)<br /> #define printResponse LOGD("%s", printBuf)</p><p> #define clearPrintBuf printBuf[0] = 0<br /> #define removeLastChar printBuf[strlen(printBuf)-1] = 0<br /> #define appendPrintBuf(x...) sprintf(printBuf, x)<br />#else<br /> #define startRequest<br /> #define closeRequest<br /> #define printRequest(token, req)<br /> #define startResponse<br /> #define closeResponse<br /> #define printResponse<br /> #define clearPrintBuf<br /> #define removeLastChar<br /> #define appendPrintBuf(x...)<br />#endif</p><p>// 喚醒類型:不喚醒,部分喚醒<br />enum WakeType {DONT_WAKE, WAKE_PARTIAL};</p><p>// "經過請求的回複"結構體定義:請求號,命令分發處理函數,返回結果響應函數<br />// 該結構體的取值見ril_commands.h檔案<br />typedef struct {<br /> int requestNumber;<br /> void (*dispatchFunction) (Parcel &p, struct RequestInfo *pRI);<br /> int(*responseFunction) (Parcel &p, void *response, size_t responselen);<br />} CommandInfo;</p><p>//"未經請求的回複"結構體定義:請求號,事件響應函數,喚醒類型<br />// 該結構體的取值見ril_unsol_commands.h檔案<br />typedef struct {<br /> int requestNumber;<br /> int (*responseFunction) (Parcel &p, void *response, size_t responselen);<br /> WakeType wakeType;<br />} UnsolResponseInfo;</p><p>// 請求資訊結構體,封裝CommandInfo,串成鏈表<br />typedef struct RequestInfo {<br /> int32_t token; //this is not RIL_Token<br /> CommandInfo *pCI;<br /> struct RequestInfo *p_next;<br /> char cancelled;<br /> char local; // responses to local commands do not go back to command process<br />} RequestInfo;</p><p>// 使用者回調資訊結構體<br />typedef struct UserCallbackInfo {<br /> RIL_TimedCallback p_callback; // 回呼函數<br /> void *userParam; // 回呼函數的參數<br /> struct ril_event event; // ril event<br /> struct UserCallbackInfo *p_next; // 指向下一個回調資訊結構(鏈表形式)<br />} UserCallbackInfo;</p><p>/*******************************************************************/<br />// 初始化回調結構<br />RIL_RadioFunctions s_callbacks = {0, NULL, NULL, NULL, NULL, NULL};<br />static int s_registerCalled = 0;</p><p>static pthread_t s_tid_dispatch; // 分發處理線程ID<br />static pthread_t s_tid_reader; // 讀者線程ID<br />static int s_started = 0; </p><p>// 檔案描述符初始化<br />static int s_fdListen = -1;<br />static int s_fdCommand = -1;<br />static int s_fdDebug = -1;</p><p>static int s_fdWakeupRead;<br />static int s_fdWakeupWrite;</p><p>// 5個相關的事件<br />static struct ril_event s_commands_event;<br />static struct ril_event s_wakeupfd_event;<br />static struct ril_event s_listen_event;<br />static struct ril_event s_wake_timeout_event;<br />static struct ril_event s_debug_event;</p><p>static const struct timeval TIMEVAL_WAKE_TIMEOUT = {1,0};</p><p>// 初始化互斥量和條件變數<br />static pthread_mutex_t s_pendingRequestsMutex = PTHREAD_MUTEX_INITIALIZER;<br />static pthread_mutex_t s_writeMutex = PTHREAD_MUTEX_INITIALIZER;<br />static pthread_mutex_t s_startupMutex = PTHREAD_MUTEX_INITIALIZER;<br />static pthread_cond_t s_startupCond = PTHREAD_COND_INITIALIZER;</p><p>static pthread_mutex_t s_dispatchMutex = PTHREAD_MUTEX_INITIALIZER;<br />static pthread_cond_t s_dispatchCond = PTHREAD_COND_INITIALIZER;</p><p>static RequestInfo *s_pendingRequests = NULL;</p><p>static RequestInfo *s_toDispatchHead = NULL;<br />static RequestInfo *s_toDispatchTail = NULL;</p><p>static UserCallbackInfo *s_last_wake_timeout_info = NULL;</p><p>static void *s_lastNITZTimeData = NULL;<br />static size_t s_lastNITZTimeDataSize;</p><p>#if RILC_LOG<br /> static char printBuf[PRINTBUF_SIZE]; // 緩衝列印資訊的數組<br />#endif</p><p>/*******************************************************************/<br />// dispatch*系列函數是基帶處理器對應用處理器請求的處理函數<br />static void dispatchVoid (Parcel& p, RequestInfo *pRI);<br />static void dispatchString (Parcel& p, RequestInfo *pRI);<br />static void dispatchStrings (Parcel& p, RequestInfo *pRI);<br />static void dispatchInts (Parcel& p, RequestInfo *pRI);<br />static void dispatchDial (Parcel& p, RequestInfo *pRI);<br />static void dispatchSIM_IO (Parcel& p, RequestInfo *pRI);<br />static void dispatchCallForward(Parcel& p, RequestInfo *pRI);<br />static void dispatchRaw(Parcel& p, RequestInfo *pRI);<br />static void dispatchSmsWrite (Parcel &p, RequestInfo *pRI);</p><p>static void dispatchCdmaSms(Parcel &p, RequestInfo *pRI);<br />static void dispatchCdmaSmsAck(Parcel &p, RequestInfo *pRI);<br />static void dispatchGsmBrSmsCnf(Parcel &p, RequestInfo *pRI);<br />static void dispatchCdmaBrSmsCnf(Parcel &p, RequestInfo *pRI);<br />static void dispatchRilCdmaSmsWriteArgs(Parcel &p, RequestInfo *pRI);</p><p>// response*系列函數是應用處理器對基帶處理器訊息的響應函數<br />// 包括請求回複響應函數和事件響應函數<br />static int responseInts(Parcel &p, void *response, size_t responselen);<br />static int responseStrings(Parcel &p, void *response, size_t responselen);<br />static int responseString(Parcel &p, void *response, size_t responselen);<br />static int responseVoid(Parcel &p, void *response, size_t responselen);<br />static int responseCallList(Parcel &p, void *response, size_t responselen);<br />static int responseSMS(Parcel &p, void *response, size_t responselen);<br />static int responseSIM_IO(Parcel &p, void *response, size_t responselen);<br />static int responseCallForwards(Parcel &p, void *response, size_t responselen);<br />static int responseDataCallList(Parcel &p, void *response, size_t responselen);<br />static int responseRaw(Parcel &p, void *response, size_t responselen);<br />static int responseSsn(Parcel &p, void *response, size_t responselen);<br />static int responseSimStatus(Parcel &p, void *response, size_t responselen);<br />static int responseGsmBrSmsCnf(Parcel &p, void *response, size_t responselen);<br />static int responseCdmaBrSmsCnf(Parcel &p, void *response, size_t responselen);<br />static int responseCdmaSms(Parcel &p, void *response, size_t responselen);<br />static int responseCellList(Parcel &p, void *response, size_t responselen);<br />static int responseCdmaInformationRecords(Parcel &p,void *response, size_t responselen);<br />static int responseRilSignalStrength(Parcel &p,void *response, size_t responselen);<br />static int responseCallRing(Parcel &p, void *response, size_t responselen);<br />static int responseCdmaSignalInfoRecord(Parcel &p,void *response, size_t responselen);<br />static int responseCdmaCallWaiting(Parcel &p,void *response, size_t responselen);</p><p>// 將資料結構資訊轉換成字串輸出<br />extern "C" const char * requestToString(int request);<br />extern "C" const char * failCauseToString(RIL_Errno);<br />extern "C" const char * callStateToString(RIL_CallState);<br />extern "C" const char * radioStateToString(RIL_RadioState);</p><p>#ifdef RIL_SHLIB<br />extern "C" void RIL_onUnsolicitedResponse(int unsolResponse, void *data,<br /> size_t datalen);<br />#endif</p><p>static UserCallbackInfo * internalRequestTimedCallback<br /> (RIL_TimedCallback callback, void *param,<br /> const struct timeval *relativeTime);</p><p>/** Index == requestNumber */<br />// 很不錯的一個用法,由於數組元素太多,為了代碼的整潔清晰,<br />// 將數組元素的定義放在一個單獨的標頭檔中,並用#include進來即可<br />static CommandInfo s_commands[] = {<br />#include "ril_commands.h"<br />};</p><p>static UnsolResponseInfo s_unsolResponses[] = {<br />#include "ril_unsol_commands.h"<br />};
To Be Continued