ril/rild/rild.c->main()为函数入口
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1.消息队列select为非阻塞的去轮询事件
2.read的阻塞的去读取上层发下来的命令,并响应
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
int main(int argc, char **argv)
{
const char * rilLibPath = NULL;
char **rilArgv;
void *dlHandle;
const RIL_RadioFunctions *(*rilInit)(const struct RIL_Env *, int, char **);
const RIL_RadioFunctions *funcs;
char libPath[PROPERTY_VALUE_MAX];
unsigned char hasLibArgs = 0;
........
OpenLib:
#endif
switchUser();
/*打开dlopen()函数,就会动态去加载动态库vendor RIL 获取由RIL_register(funcs);注册进来的参数,并解析*/
dlHandle = dlopen(rilLibPath, RTLD_NOW);
if (dlHandle == NULL) {
fprintf(stderr, "dlopen failed: %s\n", dlerror());
exit(-1);
}
/*消息队列的入口,添加到select,用阻塞方式去读取那些ril_event_set()的数据##每当看到打印信息,不按顺序打下来说明阻塞##*/
RIL_startEventLoop();
/*通过dlsym函数得到rilInit函数指针的引用*/
rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **))dlsym(dlHandle, "RIL_Init");
if (rilInit == NULL) {
fprintf(stderr, "RIL_Init not defined or exported in %s\n", rilLibPath);
exit(-1);
}
if (hasLibArgs) {
rilArgv = argv + i - 1;
argc = argc -i + 1;
} else {
static char * newArgv[MAX_LIB_ARGS];
static char args[PROPERTY_VALUE_MAX];
rilArgv = newArgv;
property_get(LIB_ARGS_PROPERTY, args, "");
argc = make_argv(args, rilArgv);
}
// Make sure there's a reasonable argv[0]
rilArgv[0] = argv[0];
/*利用得到的rilInit函数指针,调用真正的RIL_Init ,实际是动态加载动态库去链接reference-ril.c ,由dlopen()函数加载*/
funcs = rilInit(&s_rilEnv, argc, rilArgv);
/*RIL_register作用一:把vendor RIL(即RIL_init) 注册到reference-ril库去等待,dopen()函数加载链接
附:RIL_init通过是onRequest()方法,将上层来的请求进行映射后转换成对应的AT命令发给硬件,rild通过RIL_register注册这一指针。
RIL_register作用二:创建rild socket主要是等待java层得数据通过,传到下一层,还创建debug socket*/
RIL_register(funcs);
done:
while(1) {
// sleep(UINT32_MAX) seems to return immediately on bionic
sleep(0x00ffffff);
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
所有文件:
hardware/ril/libril$ ls
Android.mk NOTICE ril_event.h ril.cpp ril_event.cpp ril_commands.h ril_unsol_commands.h
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
funcs =rilInit(&s_rilEnv, argc, rilArgv);//实际是通过动态加载动态库的方式执行reference-ril.c中的RIL_Init
由RIL_Init的返回值开始的,这是一个RIL_RadioFunctions结构的指针。
typedef struct {
int version; /* set to RIL_VERSION */
RIL_RequestFunc onRequest;
RIL_RadioStateRequest onStateRequest;
RIL_Supports supports;
RIL_Cancel onCancel;
RIL_GetVersion getVersion;
} RIL_RadioFunctions;
其中最重要的是onRequest域,上层来的请求都由这个函数进行映射后转换成对应的AT命令发给硬件。rild通过RIL_register注册这一指针。
RIL_register中要完成的另外一个任务,就是打开前面提到的跟上层通信的socket接口(s_fdListen是主接口,s_fdDebug供调试时使用)。
然后将这两个socket接口使用任务一中实现的机制进行注册(仅列出s_fdListen)
ril_event_set (&s_listen_event, s_fdListen, false,
listenCallback, NULL);
rilEventAddWakeup (&s_listen_event);
这样将两个socket加到任务一中建立起来多路复用I/O的检查句柄集合中,一旦有上层来的(调试)请求,event机制便能响应处理了。
总结:0.监听所有socket
1.RIL_register()把ril_init()初始化后的vendor RIL注册到libril.so等待dlopen()h函数加载,调用,再后到select机制中的ril_event_loop()函数轮询
2.获取连个socket(rild socket和debug socket),而rild socket 是用来和java层通信得,debug socket是用来调试的
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ril/libril/ril.cpp->RIL_register 函数
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
/*注册rild socket端口事件监听到事件循环中和bedug socket
*/
extern "C" void
RIL_register (const RIL_RadioFunctions *callbacks) {//说明已经初始化完了 ,才回调
int ret;
int flags;
LOGD("-----RIL.C-RIL_register(func)-RIL.CPP---RIL_register-");
if (callbacks == NULL
|| ! (callbacks->version == RIL_VERSION || callbacks->version == 1)
) {
LOGE(
"RIL_register: RIL_RadioFunctions * null or invalid version"
" (expected %d)", RIL_VERSION);
return;
}
if (s_registerCalled > 0) {
LOGE("RIL_register has been called more than once. "
"Subsequent call ignored");
LOGD("RIL_register has been called more than once. "
"Subsequent call ignored");
return;
}
//1:换个马甲
memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));
s_registerCalled = 1;
// Little self-check
for (int i = 0; i < (int)NUM_ELEMS(s_commands); i++) {
assert(i == s_commands[i].requestNumber);
}
for (int i = 0; i < (int)NUM_ELEMS(s_unsolResponses); i++) {
assert(i + RIL_UNSOL_RESPONSE_BASE
== s_unsolResponses[i].requestNumber);
}
// New rild impl calls RIL_startEventLoop() first
// old standalone impl wants it here.
if (s_started == 0) {
RIL_startEventLoop();
}
// start listen socket 开始侦听套接字
#if 0
ret = socket_local_server (SOCKET_NAME_RIL,ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
if (ret < 0) {
LOGE("Unable to bind socket errno:%d", errno);
exit (-1);
}
s_fdListen = ret;
#else
//2:获取init.rc定义的rild socket,,#define SOCKET_NAME_RIL "rild"
s_fdListen = android_get_control_socket(SOCKET_NAME_RIL);
if (s_fdListen < 0) {
LOGE("Failed to get socket '" SOCKET_NAME_RIL "'");
exit(-1);
}
ret = listen(s_fdListen, 4);
if (ret < 0) {
LOGE("Failed to listen on control socket '%d': %s",
s_fdListen, strerror(errno));
exit(-1);
}
#endif
/*如果ril socket 端口一有数据,就去执行listencallback函数
这个函数就建立起与客户端的监听话柄
s_fdLiten继续监听其他客户端的链接*/
/* note: non-persistent so we can accept only one connection at a time */
ril_event_set(&s_listen_event, s_fdListen, false, listenCallback, NULL); 将此处端口加入到select队列去
rilEventAddWakeup (&s_listen_event);
#if 1
// start debug interface socket 获取debug socket
s_fdDebug = android_get_control_socket(SOCKET_NAME_RIL_DEBUG);
if (s_fdDebug < 0) {
LOGE("Failed to get socket '" SOCKET_NAME_RIL_DEBUG "' errno:%d", errno);
exit(-1);
}
ret = listen(s_fdDebug, 4);
if (ret < 0) {
LOGE("Failed to listen on ril debug socket '%d': %s",
s_fdDebug, strerror(errno));
exit(-1);
}
ril_event_set (&s_debug_event, s_fdDebug, true,debugCallback, NULL);
rilEventAddWakeup (&s_debug_event);
#endif
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
// Initialize an event
void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param)
{
LOGD("----RIL_evnent.cpp-shi-xian--void ril_event_set(struct ril_event * ev, int fd, bool persist, ril_event_cb func, void * param)-");
dlog("~~~~ ril_event_set %x ~~~~", (unsigned int)ev);
memset(ev, 0, sizeof(struct ril_event));
ev->fd = fd;
ev->index = -1;
ev->persist = persist;
ev->func = func;
ev->param = param;
fcntl(fd, F_SETFL, O_NONBLOCK);
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
从传入来的参数,可知道,是注册的ril_init返回的指针RIL_RadioFunctions 参数
说明,到这步的时候,vendor RIL 初始化已经完成(就是ril_init)
若rild socket数据来,就回去执行listencallback函数,这个listencallback函数主要是执行java层通过riled socket来的数据
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
static void listenCallback (int fd, short flags, void *param) {
int ret;
int err;
int is_phone_socket;
RecordStream *p_rs;
struct sockaddr_un peeraddr;
socklen_t socklen = sizeof (peeraddr);
struct ucred creds;
socklen_t szCreds = sizeof(creds);
struct passwd *pwd = NULL;
assert (s_fdCommand < 0);
assert (fd == s_fdListen);
LOGD(" --shi-xian-ril_regiter()----- ril_event_set (&s_debug_event, s_fdDebug, true,debugCallback, NULL);");
//连接JAVA层来的sockcet
s_fdCommand = accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);
if (s_fdCommand < 0 ) {
LOGE("Error on accept() errno:%d", errno);
/* start listening for new connections again */
rilEventAddWakeup(&s_listen_event);
return;
}
/* check the credential of the other side and only accept socket from
* phone process
*/
errno = 0;
is_phone_socket = 0;
err = getsockopt(s_fdCommand, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);
if (err == 0 && szCreds > 0) {
errno = 0;
pwd = getpwuid(creds.uid);
if (pwd != NULL) {
if (strcmp(pwd->pw_name, PHONE_PROCESS) == 0) {
is_phone_socket = 1;
} else {
LOGE("RILD can't accept socket from process %s", pwd->pw_name);
}
} else {
LOGE("Error on getpwuid() errno: %d", errno);
}
} else {
LOGD("Error on getsockopt() errno: %d", errno);
}
if ( !is_phone_socket ) {
LOGE("RILD must accept socket from %s", PHONE_PROCESS);
close(s_fdCommand);
s_fdCommand = -1;
onCommandsSocketClosed();
/* start listening for new connections again */
rilEventAddWakeup(&s_listen_event);
return;
}
ret = fcntl(s_fdCommand, F_SETFL, O_NONBLOCK);
if (ret < 0) {
LOGE ("Error setting O_NONBLOCK errno:%d", errno);
}
LOGI("libril: new connection");
//有数据来的时候,把s_fdCommand绑定到record_stream_new 。目的就是保证数据的完整性
p_rs = record_stream_new(s_fdCommand, MAX_COMMAND_BYTES);
//当有数据来的时候,函数就去执行processCommandsCallback澹()函数,把数据读到p_record中
ril_event_set(&s_commands_event, s_fdCommand, 1, processCommandsCallback, p_rs);
rilEventAddWakeup(&s_commands_event);
onNewCommandConnect();
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
static void processCommandsCallback(int fd, short flags, void *param) {
RecordStream *p_rs;
void *p_record;
size_t recordlen;
int ret;
assert(fd == s_fdCommand);
p_rs = (RecordStream *)param;
LOGD("--SHI-XIAN--ril_regieter-----static void processCommandsCallback(int fd, short flags, void *param)");
for (;;) {
/* loop until EAGAIN/EINTR, end of stream, or other error */
ret = record_stream_get_next(p_rs, &p_record, &recordlen);
if (ret == 0 && p_record == NULL) {
/* end-of-stream */
break;
} else if (ret < 0) {
break;
} else if (ret == 0) { /* && p_record != NULL */
//阻塞方式获取数据 到p_record 利用RecordStream机制保证数据完整
processCommandBuffer(p_record, recordlen);
}
}
if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {
/* fatal error or end-of-stream */
if (ret != 0) {
LOGE("error on reading command socket errno:%d\n", errno);
} else {
LOGW("EOS. Closing command socket.");
}
close(s_fdCommand);
s_fdCommand = -1;
ril_event_del(&s_commands_event);//删除
record_stream_free(p_rs);//释放了上面监听到的数据,再开始新的路程
/* start listening for new connections again 开始监听新的连接*/
rilEventAddWakeup(&s_listen_event);
说明:它只是把事件添加到里面而已,添加完后,再回去ril_event_loop()去监听新的事件,反复的轮询
onCommandsSocketClosed();
}
}
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
上面数据来了,就要都得去找请求队列的序列号,就的做执行processCommandBuffer->status = p.readInt32 (&token);
假设是接收了dial指令,pRI->PCI->dispatchFunction(p,pRI),调用dispatchDial(p,pRI)
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
static int
processCommandBuffer(void *buffer, size_t buflen) {
Parcel p;
status_t status;
int32_t request;
int32_t token;
RequestInfo *pRI;
int ret;
LOGD("---shixian -processCommandBuffer---");
p.setData((uint8_t *) buffer, buflen);
// status checked at end
status = p.readInt32(&request);
status = p.readInt32 (&token);//请求队列的序列号
if (status != NO_ERROR) {
LOGE("invalid request block");
return 0;
}
if (request < 1 || request >= (int32_t)NUM_ELEMS(s_commands)) {
LOGE("unsupported request code %d token %d", request, token);
// FIXME this should perhaps return a response
return 0;
}
pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo));
pRI->token = token;
pRI->pCI = &(s_commands[request]);
ret = pthread_mutex_lock(&s_pendingRequestsMutex);
assert (ret == 0);
pRI->p_next = s_pendingRequests;
s_pendingRequests = pRI;
ret = pthread_mutex_unlock(&s_pendingRequestsMutex);
assert (ret == 0);
/* sLastDispatchedToken = token; */
pRI->pCI->dispatchFunction(p, pRI);//电话来了,就执行这个函数
return 0;