(1)RIL简析(高通)——RIL如何启动及初始化
来源:互联网 发布:退伍军人召回通知软件 编辑:程序博客网 时间:2024/05/01 18:29
Android设置了RIL层,是上层framework与Modem沟通的桥梁。高通使用qcril作为其vendor-RIL,与modem之间使用QMI机制通讯。
分3篇分析下面的问题:
- RIL如何启动及初始化?
- RILJ和RILD如何关联?
- RILJ的消息如何传递和被处理?
- event table的定义
- event如何管理
- event的处理、返回结果和主动上报(UNSOL)
- 如何正确地添加一个RIL消息和对应的处理函数?
RILD进程启动
RIL、QCRIL运行在RILD进程,在开机后启动,Rild.c的main函数为入口:
/system/core/rootdir/init.rc
service netd /system/bin/netd class main socket netd stream 0660 root system socket dnsproxyd stream 0660 root inet socket mdns stream 0660 root system socket fwmarkd stream 0660 root inet
RILD2
/device/qcom/common/rootdir/etc/init.qcom.rc
service ril-daemon2 /system/bin/rild -c 2 class main socket rild2 stream 660 root radio socket rild-debug2 stream 660 radio system user root disabled group radio cache inet misc audio sdcard_r sdcard_rw qcom_diag diag log
rild主函数入口:
#define LIB_PATH_PROPERTY "rild.libpath"int main(int argc, char **argv) { const char * rilLibPath = NULL; if (rilLibPath == NULL) { //这里的property值为:vendor/lib64/libril-qc-qmi-1.so if ( 0 == property_get(LIB_PATH_PROPERTY, libPath, NULL)) { // No lib sepcified on the command line, and nothing set in props. // Assume "no-ril" case. goto done; } else { rilLibPath = libPath; } } //获取libril-qc-qmi-1.so库的句柄 dlHandle = dlopen(rilLibPath, RTLD_NOW); if (dlHandle == NULL) { RLOGE("dlopen failed: %s", dlerror()); exit(EXIT_FAILURE); } RIL_startEventLoop(); //获取RIL_Init函数指针 rilInit = (const RIL_RadioFunctions *(*)(const struct RIL_Env *, int, char **)) dlsym(dlHandle, "RIL_Init"); //调用RIL_Init函数,s_rilEnv定义见后面 funcs = rilInit(&s_rilEnv, argc, rilArgv); RLOGD("RIL_Init rilInit completed"); RIL_register(funcs);}//提供给qcril的回调函数,消息处理完成后调用这些callback函数返回static struct RIL_Env s_rilEnv = { RIL_onRequestComplete, RIL_onUnsolicitedResponse, RIL_requestTimedCallback};
RILD入口主要关注这3个函数:
RIL_startEventLoop() —— ril.cpp,线程中开启一个消息循环来监听消息并触发事件处理。
RIL_Init() —— qcril.c初始化工作
RIL_register() —— 注册qcril.c消息函数入口(ril与qcril的关联)
RIL_startEventLoop()
int main(int argc, char **argv) {
RIL_startEventLoop();
}
ril.cppextern "C" voidRIL_startEventLoop(void) { /* spin up eventLoop thread and wait for it to get started */ s_started = 0; pthread_mutex_lock(&s_startupMutex); pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); //创建线程,负责执行eventLoop函数 int result = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL); if (result != 0) { RLOGE("Failed to create dispatch thread: %s", strerror(result)); goto done; } while (s_started == 0) { pthread_cond_wait(&s_startupCond, &s_startupMutex); }done: pthread_mutex_unlock(&s_startupMutex);}
RIL_startEventLoop(void) {
int result = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
}
eventloop函数开始在线程中执行,初始化并开始一个消息循环:
static fd_set readFds;static int nfds = 0;static struct ril_event * watch_table[MAX_FD_EVENTS];static struct ril_event timer_list;static struct ril_event pending_list;static void *eventLoop(void *param) { int ret; int filedes[2]; //初始化watch_table、timer_list、pending_list、readFds ril_event_init(); pthread_mutex_lock(&s_startupMutex); s_started = 1; pthread_cond_broadcast(&s_startupCond); pthread_mutex_unlock(&s_startupMutex); //管道 ret = pipe(filedes); if (ret < 0) { RLOGE("Error in pipe() errno:%d", errno); return NULL; } s_fdWakeupRead = filedes[0]; s_fdWakeupWrite = filedes[1]; fcntl(s_fdWakeupRead, F_SETFL, O_NONBLOCK); //创建一个event,回调函数为processWakeupCallback ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true, processWakeupCallback, NULL); //将event加入watchtable,唤醒eventloop rilEventAddWakeup (&s_wakeupfd_event); // Only returns on error //开始event循环 ril_event_loop(); RLOGE ("error in event_loop_base errno:%d", errno); // kill self to restart on error kill(0, SIGKILL); return NULL;}static fd_set readFds;static int nfds = 0;static struct ril_event * watch_table[MAX_FD_EVENTS];static struct ril_event timer_list;static struct ril_event pending_list;// 初始化消息列表、计时器消息列表、待处理消息列表void ril_event_init(){ MUTEX_INIT(); FD_ZERO(&readFds); init_list(&timer_list); init_list(&pending_list); memset(watch_table, 0, sizeof(watch_table));}//唤醒event loopstatic void rilEventAddWakeup(struct ril_event *ev) { //将event加入到watch_table ril_event_add(ev); //向s_fdWakeupWrite写入空值,唤醒select triggerEvLoop();}
ril_event.cpp::ril_event_set
初始化一个event,fd是监听的设备文件描述,persist指定event是否一直存在于watchtable,以上面代码为例:
ril_event_set (&s_wakeupfd_event, s_fdWakeupRead, true,
processWakeupCallback, NULL);
s_fdWakeupRead会一直存在于readFds,因此起到长期监听的作用。
//初始化一个event,persist值若为true则此event会一直存在于watchtablevoid 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);}
static void *eventLoop(void *param) {
ril_event_loop();
}
ril_event_loop函数是循环的主体,在获取到消息后触发3个处理函数:
void ril_event_loop(){ int n; fd_set rfds; struct timeval tv; struct timeval * ptv; for (;;) { // make local copy of read fd_set memcpy(&rfds, &readFds, sizeof(fd_set)); if (-1 == calcNextTimeout(&tv)) { // no pending timers; block indefinitely dlog("~~~~ no timers; blocking indefinitely ~~~~"); ptv = NULL; } else { dlog("~~~~ blocking for %ds + %dus ~~~~", (int)tv.tv_sec, (int)tv.tv_usec); ptv = &tv; } printReadies(&rfds); //select,等待被唤醒 n = select(nfds, &rfds, NULL, NULL, ptv); printReadies(&rfds); dlog("~~~~ %d events fired ~~~~", n); if (n < 0) { if (errno == EINTR) continue; RLOGE("ril_event: select error (%d)", errno); // bail? return; } //处理timer_list中超时的event,加入到pending_list processTimeouts(); //从watch_table获取event加入到pending_list processReadReadies(&rfds, n); //分发pending_list中的事件给对应的处理函数 firePending(); }}
RIL_INIT
回到rild.c的main函数,继续分析Ril_Init。
int main(int argc, char **argv) {
funcs = rilInit(&s_rilEnv, argc, rilArgv);
}
RIL_startEventLoop()执行过后,RIL的消息循环已经开始进入工作,接下来RIL_Init负责Qcril的初始化及消息循环的创建。
qcril.c/*=========================================================================== FUNCTION: RIL_Init===========================================================================*//*! @brief Returns the current state of the RIL @return The current state of the RIL*//*=========================================================================*/const RIL_RadioFunctions *RIL_Init( const struct RIL_Env *env, int argc, char **argv){ //response函数(ril.cpp) // o maintain compatibility with data and UIM code which use instance_id and may respond on "second instance" context qcril_response_api[ QCRIL_DEFAULT_INSTANCE_ID ] = (struct RIL_Env *) env; qcril_response_api[ QCRIL_SECOND_INSTANCE_ID ] = (struct RIL_Env *) env;---------- //初始化unsol消息列表 qmi_ril_android_pending_unsol_resp qmi_ril_init_android_unsol_resp_pending_list(); //在新线程中执行event loop(qcril_event_main()) qcril_event_init(); // 初始化QCRIL(初始化消息函数的table等) qcril_init(c_argc, c_argv); //qcril_event_main开始进入循环,等待被唤醒并处理event。 qcril_event_start();---------- // start bootup if applicable qmi_ril_initiate_bootup(); //返回RIL_RadioFunctions函数数组给rild.c return &qcril_request_api[ QCRIL_DEFAULT_INSTANCE_ID ];}//qcril的request相关函数接口static const RIL_RadioFunctions qcril_request_api[] = { { RIL_VERSION, onRequest_rid, currentState_rid, onSupports_rid, onCancel_rid, getVersion_rid }};
RIL_Init(){
qcril_event_init()
}
qcril_event.cvoid qcril_event_init(void){ qcril_event.started = 0; //开启线程来执行qcril_event_main ret = pthread_create(&qcril_event.tid, &attr, qcril_event_main, NULL); //等待qcril_event_main执行 while (qcril_event.started == 0){ pthread_cond_wait(&qcril_event_startupCond, &qcril_event.startup_mutex); }}
qcril_event_init(){
ret = pthread_create(&qcril_event.tid, &attr, qcril_event_main, NULL);
}
qcril_event_main开始一个循环,被唤醒后将event list中的消息分发给qcril_process_event处理。
qcril_event.cstatic void *qcril_event_main(void *param){ qcril_event.started = 1; pthread_cond_broadcast(&qcril_event_startupCond); while (qcril_event.started < 2) { // pthread_cond_wait(&qcril_event_startupCond, &qcril_event.startup_mutex); } for (;;) { n = select(qcril_event.fdWakeupRead + 1, &rfds, NULL, NULL, NULL); do { ret = read(qcril_event.fdWakeupRead, &buff, sizeof(buff)); if (ret > 0) { QCRIL_LOG_DEBUG("%d items on queue", ret); } } while (ret > 0 || (ret < 0 && errno == EINTR)); do { if ( ( NULL != ( ev = qcril_event.list.next ) && ( ev != &qcril_event.list ) ) ) { qcril_event_remove_from_list( ev ); //处理消息——qcril_process_event err_no = qcril_process_event( ev->instance_id, ev->modem_id, ev->event_id, ev->data, ev->datalen, ev->t ); } } }}
RIL_Init(){
qcril_init ()
}
qcril.c//定义了所有消息和处理函数的对应数组static qcril_dispatch_table_entry_type qcril_event_table[] = {{ QCRIL_REG_ALL_STATES( QCRIL_EVT_UIM_QMI_COMMAND_CALLBACK, qcril_uim_process_qmi_callback ) },}//使用hash值来存储qcril_event_table的数据(是实际操作所用的数组)static qcril_dispatch_table_entry_type *qcril_hash_table[ QCRIL_HT_ENTRIES_MAX ];void qcril_init( int argc, char **argv){ //qcril_setup_timed_callback 设置timed callback等初始化动作。 qcril_init_state(); //qcril_event_table存储到qcril_hash_table,使用hash id为索引 qcril_init_hash_table(); //初始化qcril_reqlist(qcril_reqlist.c专门用于管理request info,提供添加、查询、删除等函数) qcril_reqlist_init();}
RIL_Init(){
qcril_event_start()
开始qcril_event_main中的循环
void qcril_event_start( void ){ QCRIL_MUTEX_LOCK( &qcril_event.startup_mutex, "[Main Thread] qcril_event.startup_mutex" ); qcril_event.started = 2; pthread_cond_broadcast(&qcril_event_startupCond); QCRIL_MUTEX_UNLOCK( &qcril_event.startup_mutex, "[Main Thread] qcril_event.startup_mutex" );} /* qcril_event_start() */
RIL_Init完成了qcril 初始化,开始eventloop循环,最后返回了qcril_request_api[]
RIL_register
int main(int argc, char **argv) {
funcs = rilInit(&s_rilEnv, argc, rilArgv);
RIL_register(funcs);
}
监听socket并设置event callback等。
ril.cppRIL_RadioFunctions s_callbacks = {0, NULL, NULL, NULL, NULL, NULL};extern "C" voidRIL_register (const RIL_RadioFunctions *callbacks) { memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions)); //定义socket,双卡项目需要定义2个 /* Initialize socket1 parameters */ s_ril_param_socket = { RIL_SOCKET_1, /* socket_id */ -1, /* fdListen */ -1, /* fdCommand */ PHONE_PROCESS, /* processName */ &s_commands_event, /* commands_event */ &s_listen_event, /* listen_event */ processCommandsCallback, /* 回调函数 */ NULL /* p_rs */ }; #if (SIM_COUNT >= 2) s_ril_param_socket2 = { RIL_SOCKET_2, /* socket_id */ -1, /* fdListen */ -1, /* fdCommand */ PHONE_PROCESS, /* processName */ &s_commands_event_socket2, /* commands_event */ &s_listen_event_socket2, /* listen_event */ processCommandsCallback, NULL /* p_rs */ }; #endif //开始监听socket1 startListen(RIL_SOCKET_1, &s_ril_param_socket); #if (SIM_COUNT >= 2) //开始监听socket2 startListen(RIL_SOCKET_2, &s_ril_param_socket2);}//开始监听static void startListen(RIL_SOCKET_ID socket_id, SocketListenParam* socket_listen_p) { fdListen = android_get_control_socket(socket_name); if (fdListen < 0) { RLOGE("Failed to get socket %s", socket_name); exit(-1); } //监听rild(2) ret = listen(fdListen, 4); if (ret < 0) { RLOGE("Failed to listen on control socket '%d': %s", fdListen, strerror(errno)); exit(-1); } socket_listen_p->fdListen = fdListen; //唤醒eventloop,回调方法为listenCallback(persist为false) ril_event_set (socket_listen_p->listen_event, fdListen, false, listenCallback, socket_listen_p); rilEventAddWakeup (socket_listen_p->listen_event);}//eventloop执行回调,设置对socket的监听static void listenCallback (int fd, short flags, void *param) { if(NULL == sapSocket) { p_info->fdCommand = fdCommand; p_rs = record_stream_new(p_info->fdCommand, MAX_COMMAND_BYTES); p_info->p_rs = p_rs; //event persist属性为true,回调为processCommandsCallback ril_event_set (p_info->commands_event, p_info->fdCommand, 1, p_info->processCommandsCallback, p_info); rilEventAddWakeup (p_info->commands_event); onNewCommandConnect(p_info->socket_id); }}
ril和qcril的event loop及消息函数入口完成了初始化并开始监听消息。
后面的来分析下消息处理和上报。
- (1)RIL简析(高通)——RIL如何启动及初始化
- (2)RIL简析(高通)——消息处理
- 高通的ril
- 阅读深入解析Android RIL笔记1 —Android RIL框架结构及RILJ运行机制
- Android RIL源码梳理(1) ——rild启动流程
- Android RIL源码梳理(1) ——rild启动流程 .
- RIL
- RIL
- RIL
- ril
- RIL
- RIL
- RIL
- RIL
- RIL
- Android RIL源码分析(1)
- ril - 1
- Android RIL模块非启动界面联网实战(一)
- 麻将 (Standard IO)
- adapter.notifyDataSetChanged()不起着用
- SQL执行XML编码问题
- 使用matplotlib实现画图
- Android控件visible,invisible和gone
- (1)RIL简析(高通)——RIL如何启动及初始化
- hdu 1203- I NEED A OFFER!
- 观察者模式
- 项目间的循环依赖
- python 画雷达图
- HDU 4445 Crazy Tank
- ssh连接提示 "Connection closed by remote host"
- Android 各层调用的方式
- 【zzuliOJ】1916 - 树(dfs序 & 树状数组)