Android4.4 RIL软件框架
本文主要对android4.4 ril的telephony与modem的命令交互流程进行分析,当然本文不是重点介绍telephony。
telephony涉及具体业务逻辑内容比较多,包括sim、dail、sms、network等等,以后会针对这些内容学习分析。
ril在android体系中的位置:
(a) 应用层发起访问modem的请求
(b) rild进程
(a) 应用层发起访问modem的请求
frameworks/opt/telephony/src/java/com/android/internal/telephony/ril.java中的类ril,提供了一系
列的接口给上层应用调用,以访问modem。当然这些接口并不是直接给app使用,而是由framework中sim、dail、
sms、network等相关服务调用。
如: 以查询sim卡状态geticccardstatus()为例,该api为uicccontroller模块所调用:
完整的sim卡请求log:
10-11 12:21:43.630 d/rilj ( 1833): [3653]> get_sim_status
10-11 12:21:43.630 d/rilc ( 1286): [0005]> get_sim_status
10-11 12:21:43.630 d/rilc ( 1286): onrequest: get_sim_status
10-11 12:21:43.630 d/atc ( 1286): at> at+cpin?
10-11 12:21:43.640 d/atc ( 1286): at< +cpin: ready
10-11 12:21:43.640 d/atc ( 1286): at< ok
10-11 12:21:43.640 d/rilc ( 1286): [0005]< get_sim_status {[app_type=1,app_state=5,perso_substate=2,aid_ptr=(null),app_label_ptr=(null),pin1_replaced=0,pin1=0,pin2=0],}
10-11 12:21:43.640 d/rilj ( 1833): [3653]< get_sim_status icccardstate {cardstate_present,pinstate_unknown,num_apps=1,gsm_id=0{apptype_sim,appstate_ready},cdma_id=8,ims_id=8}
发起请求:
frameworks/opt/telephony/src/java/com/android/internal/telephony/ril.java
@override public void geticccardstatus(message result) { //note: this ril request has not been renamed to icc, // but this request is also valid for sim and ruim rilrequest rr = rilrequest.obtain(ril_request_get_sim_status, result); /* 获取一个rilrequest */ if (rilj_logd) riljlog(rr.serialstring() + "> " + requesttostring(rr.mrequest)); /* 参考log:[3653]> get_sim_status */ send(rr); /* 发送请求 */ }
rilrequest.obtain是从内存池获取一个rilrequest实例,并初始化:
frameworks/opt/telephony/src/java/com/android/internal/telephony/ril.java
class rilrequest { static final string log_tag = "rilrequest"; ... ... static rilrequest obtain(int request, message result) { rilrequest rr = null; synchronized(spoolsync) { /* 从内存池中取出一个rilrequest对象*/ if (spool != null) { rr = spool; spool = rr.mnext; rr.mnext = null; spoolsize--; } } if (rr == null) { /* 如果内存池中没有,则实例化一个 */ rr = new rilrequest(); } rr.mserial = snextserial.getandincrement(); /* 获取串号,并且+1 */ rr.mrequest = request; /* 对应ril_request_*请求 */ rr.mresult = result; rr.mparcel = parcel.obtain(); /* 初始化一个parcel,用于封包以发送给底层rild */ if (result != null && result.gettarget() == null) { throw new nullpointerexception("message target must not be null"); } // first elements in any ril parcel rr.mparcel.writeint(request); /* 每个ril parcel最开始也最基本的两个元素 */ rr.mparcel.writeint(rr.mserial); return rr; /* 返回这个从内存池中获取的实例 */ } ... ... string serialstring() { //cheesy way to do %04d stringbuilder sb = new stringbuilder(8); /* 创建一个stringbuilder实例用于操作字符串 */ string sn; long adjustedserial = (((long)mserial) - integer.min_value)%10000; sn = long.tostring(adjustedserial); /* 把数值转换成字符串 */ //sb.append("j["); sb.append('['); for (int i = 0, s = sn.length() ; i < 4 - s; i++) { sb.append('0'); } sb.append(sn); sb.append(']'); return sb.tostring(); /* 转换出来的字符串格式: [xxxx] */ } ... ... }
send(rr)发送请求到服务端:
frameworks/opt/telephony/src/java/com/android/internal/telephony/ril.java
private void send(rilrequest rr) { message msg; ... ... msg = msender.obtainmessage(event_send, rr); /* 发送event_send时间,时间参数为rilrequest */ acquirewakelock(); /* 获取wakelock,禁止进入休眠 */ msg.sendtotarget(); /* message从handler类获取,从而可以直接向该handler对象发送消息。target就是创建message的handler */ }
实际上telephony无法直接与modem通讯,由于每个厂商的modem都不一样,modem存在于系统中的方式
也不一样,如:有的cpu芯片厂商的modem是以一个cp核的方式集成在基带上(高通、展讯等),有的cpu芯
片(exynos 4412等)需要通过串口/usb外接modem模块,如:bc72 lte模块等。
send(rr)向rild发送请求,这里涉及一个进程间通信问题,而且java侧与c++侧的进程通讯,当然这里并没
有用android开发的朋友都熟悉的bind,而是socket。
telephony/java侧ril命令交互的处理,暂且称为rilj。
rilj作为socket的客户端,rild(rild进程)作为服务端,后面会分析rild进程。
socket客户端的创建:
frameworks/opt/telephony/src/java/com/android/internal/telephony/ril.java
public ril(context context, int preferrednetworktype, int cdmasubscription) { ... ... msenderthread = new handlerthread("rilsender"); /* 创建rilsender线程 */ msenderthread.start(); looper looper = msenderthread.getlooper(); msender = new rilsender(looper); connectivitymanager cm = (connectivitymanager)context.getsystemservice( context.connectivity_service); if (cm.isnetworksupported(connectivitymanager.type_mobile) == false) { riljlog("not starting rilreceiver: wifi-only"); } else { riljlog("starting rilreceiver"); mreceiver = new rilreceiver(); mreceiverthread = new thread(mreceiver, "rilreceiver"); /* 创建rilreceiver线程 */ mreceiverthread.start(); ... ... } ... ... } class rilreceiver implements runnable { byte[] buffer; rilreceiver() { /* 构造时,分配一个数组 */ buffer = new byte[ril_max_command_bytes]; } @override public void run() { /* 循环读取从rild返回或主动上报的数据 */ int retrycount = 0; try {for (;;) { localsocket s = null; localsocketaddress l; try { s = new localsocket(); /* 创建一个socket客户端 */ l = new localsocketaddress(socket_name_ril, localsocketaddress.namespace.reserved); s.connect(l); /* 连接服务器 */ } ... ... } ... ... try { inputstream is = msocket.getinputstream(); /* 循环读取socket的数据 */ for (;;) { parcel p; length = readrilmessage(is, buffer); /* 解析socket数据 */ if (length < 0) { // end-of-stream reached break; } p = parcel.obtain(); /* 获取一个parcel */ p.unmarshall(buffer, 0, length); /* 读取出来的就是之前序列化的byte数组,所以要进行一个反序列化操作 */ p.setdataposition(0); /* 从buffer转换到parcel之后,需要将指针手动指向到最初的位置 */ //rlog.v(rilj_log_tag, "read packet: " + length + " bytes"); processresponse(p); p.recycle(); /* 数据处理完后,需要回收parcel的内存 */ } } ... ... }
rilreceiver线程创建socket客户端,连接服务端,然后进入等待服务端的processresponse消息处理循环,rilj
接收到rild回复的response返回ril请求的发起者,以geticccardstatus(message result)为例,processresponse(p)
会把drild的response返回给uicccontroller
frameworks/opt/telephony/src/java/com/android/internal/telephony/ril.java
private static int readrilmessage(inputstream is, byte[] buffer) throws ioexception { int countread; int offset; int remaining; int messagelength; // first, read in the length of the message offset = 0; remaining = 4; do { countread = is.read(buffer, offset, remaining); /* 读出消息的4字节长度 */ if (countread < 0 ) { rlog.e(rilj_log_tag, "hit eos reading message length"); return -1; } offset += countread; remaining -= countread; } while (remaining > 0); messagelength = ((buffer[0] & 0xff) << 24) /* 获取长度 */ | ((buffer[1] & 0xff) << 16) | ((buffer[2] & 0xff) << 8) | (buffer[3] & 0xff); // then, re-use the buffer and read in the message itself offset = 0; remaining = messagelength; do { countread = is.read(buffer, offset, remaining); /* 读取剩余的数据 */ if (countread < 0 ) { rlog.e(rilj_log_tag, "hit eos reading message. messagelength=" + messagelength + " remaining=" + remaining); return -1; } offset += countread; remaining -= countread; } while (remaining > 0); return messagelength; } private void processresponse (parcel p) { int type; type = p.readint(); /* 从rild返回的数据第一个字节,表示请求的返回类型:response_unsolicited/response_solicited */ if (type == response_unsolicited) { processunsolicited (p); /* 主动上报 */ } else if (type == response_solicited) { rilrequest rr = processsolicited (p); /* 普通请求对应的同步上报 */ if (rr != null) { rr.release(); /* 释放对应的rilrequest内存和wakelock */ decrementwakelock(); } } }
rild的response一般有两种,一种是rilj普通请求,rild对rilj请求的response (response_solicited),另一种是rild主动上报的
response (response_unsolicited), processresponse (parcel p)分别对这两种情况的response进行处理。
frameworks/opt/telephony/src/java/com/android/internal/telephony/ril.java
private rilrequest processsolicited (parcel p) { int serial, error; boolean found = false; serial = p.readint(); /* 串号,也就是token */ error = p.readint(); /* 错误码 */ rilrequest rr; rr = findandremoverequestfromlist(serial); /* 根据taken取出对应的rilrequest */ ... ... */ case ril_request_get_sim_status: ret = responseicccardstatus(p); break; ... ... if (rr.mresult != null) { asyncresult.formessage(rr.mresult, ret, null); /* 把rr.mresult存到asyncresult.userobj,并把rr.mresult.obj转换为asyncresult */ rr.mresult.sendtotarget(); /* msg发送到对应的target(handler) */ } ... ... } private object responseicccardstatus(parcel p) { icccardapplicationstatus appstatus; ... ... appstatus = new icccardapplicationstatus(); ... ... return cardstatus; }
回到刚才send(rr),send(rr)并不是直接发送到socket服务端rild,而是通过一个message发送到rilsender线程,
在handlemessage中,把请求发到socket服务端rild。
frameworks/opt/telephony/src/java/com/android/internal/telephony/ril.java
class rilsender extends handler implements runnable { /* 继承handler,实现runnable */ public rilsender(looper looper) { super(looper); } ... ... //***** handler implementation @override public void handlemessage(message msg) { /* 继承handler的handlemessage */ rilrequest rr = (rilrequest)(msg.obj); /* maessage中携带的rilrequest对象 */ rilrequest req = null; switch (msg.what) { case event_send: /* 发送ril请求事件 */ try { localsocket s; s = msocket; /* rilreceiver中创建的用于与rild通讯的socket */ ... ... synchronized (mrequestlist) { /* 多线程保护操作mrequestlist */ mrequestlist.append(rr.mserial, rr); /* 把接受到的rilrequest和对应的串号,存到mrequestlist数据 */ } byte[] data; data = rr.mparcel.marshall(); /* 把parcel中的数据转换为byte数据 */ rr.mparcel.recycle(); /* parcel的内存回收 */ rr.mparcel = null; ... ... // parcel length in big endian datalength[0] = datalength[1] = 0; /* ril请求包的大小为4个字节 */ datalength[2] = (byte)((data.length >> 8) & 0xff); datalength[3] = (byte)((data.length) & 0xff); //rlog.v(rilj_log_tag, "writing packet: " + data.length + " bytes"); s.getoutputstream().write(datalength); /* 把包大小和包数据发送出去 */ s.getoutputstream().write(data); } catch (ioexception ex) { rlog.e(rilj_log_tag, "ioexception", ex); req = findandremoverequestfromlist(rr.mserial); /* 如果出现异常,则把串号对应的rilrequest从mrequestlist中删除 */ // make sure this request has not already been handled, // eg, if rilreceiver cleared the list. if (req != null) { rr.onerror(radio_not_available, null); rr.release(); decrementwakelock(); } } ... ... } } }
(b) rild进程
rild作为一个独立的进程,telephony与modem之间的通讯通道。抽象出一些接口以适配不同的modem厂商,无需关心具体的
硬件操作,或者以哪种形式存存在于系统(modem作为cp集成于cpu或cpu通过串口/usb连接,如: bc72 lte模块)。因为这些接口
由厂商去实现具体的硬件操作细节,这些接口都在libreference-ril中,在android中使用bc72 lte模块,只要移植
libreference-ril就行。
1. rild的启动
rild有init进程直接启动,启动后就监听rilj客户端,等待rilj连接请求。
device/samsung/smdk4x12/conf/init.smdk4x12.rc
service ril-daemon /system/bin/rild -l /system/lib/libreference-ril.so class main socket rild stream 660 root radio socket rild-debug stream 660 radio system user root
hardware/ril/rild/rild.c为rild进程入口:
hardware/ril/rild/rild.c
int main(int argc, char **argv) { ... ... dlhandle = dlopen(rillibpath, rtld_now); /* 打开/system/lib/libreference-ril.so */ if (dlhandle == null) { rloge("dlopen failed: %s", dlerror()); exit(-1); } ril_starteventloop(); /* 创建eventloop线程, 在ril_event_loop()中监听多路io的事件,如主动唤醒事件(pipe)、rilj的请求等 */ /* 获取/system/lib/libreference-ril.so中ril_init函数指针 */ rilinit = (const ril_radiofunctions *(*)(const struct ril_env *, int, char **))dlsym(dlhandle, "ril_init"); if (rilinit == null) { rloge("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]; funcs = rilinit(&s_rilenv, argc, rilargv); /* 初始化vender ril */ ril_register(funcs); /* 注册ril */ ... ... }
hardware/ril/libril/ril.cpp
extern "c" void ril_starteventloop(void) { ... ... ret = pthread_create(&s_tid_dispatch, &attr, eventloop, null); /* 创建eventloop线程 */ ... ... } static void * eventloop(void *param) { int ret; int filedes[2]; ril_event_init(); /* 初始化事件链表,timer_list,pending_list, watch_table */ pthread_mutex_lock(&s_startupmutex); s_started = 1; pthread_cond_broadcast(&s_startupcond); pthread_mutex_unlock(&s_startupmutex); ret = pipe(filedes); /* 创建一个pipe,用于每次添加一个新事件时,唤醒selet()返回,更新fd_set使select监听新的事件 */ if (ret < 0) { rloge("error in pipe() errno:%d", errno); return null; } s_fdwakeupread = filedes[0]; /* filedes[0]用于读pipe, filedes[1]用于写pipe */ s_fdwakeupwrite = filedes[1]; fcntl(s_fdwakeupread, f_setfl, o_nonblock); /* 以非阻塞的方式读pipe */ ril_event_set (&s_wakeupfd_event, s_fdwakeupread, true, /* 读pipe描述符绑定到s_wakeupfd_event事件,指定回调processwakeupcallback */ processwakeupcallback, null); rileventaddwakeup (&s_wakeupfd_event); /* 添加s_wakeupfd_event事件到watch_table,更新readfds集合,使select监听该事件,并触发该事件 */ // only returns on error ril_event_loop(); /* 进入多路io事件监听循环 */ rloge ("error in event_loop_base errno:%d", errno); // kill self to restart on error kill(0, sigkill); return null; }
main函数主要启动eventloop线程,在ril_event_loop()中监听多路io的事件,如主动唤醒事件(pipe)、rilj的请求等,
注册vendor ril接口(libreference-ril)
注意这里pipe的主要作用是唤醒select返回,因为每次动态的添加一个事件,都要更新readfds集合,方便select监听
集合中新的io。
rileventaddwakeup()添加新事件后,都会触发select返回
hardware/ril/libril/ril.cpp
static void rileventaddwakeup(struct ril_event *ev) { ril_event_add(ev); /* 添加事件 */ triggerevloop(); /* 触发事件, 每添加一个事件,都通过写pipe唤醒select,以更新多路io集合,使能够监听该事件 */ }
hardware/ril/libril/ril_event.cpp
void ril_event_add(struct ril_event * ev) { dlog("~~~~ +ril_event_add ~~~~"); mutex_acquire(); for (int i = 0; i < max_fd_events; i++) { if (watch_table[i] == null) { watch_table[i] = ev; /* 将新事件添加到watch_table */ ev->index = i; dlog("~~~~ added at %d ~~~~", i); dump_event(ev); fd_set(ev->fd, &readfds); /* 更新readfds集合 */ if (ev->fd >= nfds) nfds = ev->fd+1; /* 更新nfds */ dlog("~~~~ nfds = %d ~~~~", nfds); break; } } mutex_release(); dlog("~~~~ -ril_event_add ~~~~"); }
hardware/ril/libril/ril.cpp
static void triggerevloop() { int ret; if (!pthread_equal(pthread_self(), s_tid_dispatch)) { /* trigger event loop to wakeup. no reason to do this, * if we're in the event loop thread */ do { ret = write (s_fdwakeupwrite, " ", 1); /* 向pipe写入一个" ",以唤醒select */ } while (ret < 0 && errno == eintr); } }
在ril_event_loop()接收到事件或socket客户端rilj发过来的请求后,firepending()根据事件请求,调用相应的处理函数
hardware/ril/libril/ril_event.cpp
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)) { /* 计算timer_list链表中每个事件对应的超时时间 */ // 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); n = select(nfds, &rfds, null, null, ptv); /* 等待readfds集合中的事件唤醒 */ printreadies(&rfds); dlog("~~~~ %d events fired ~~~~", n); if (n < 0) { if (errno == eintr) continue; rloge("ril_event: select error (%d)", errno); // bail? return; } // check for timeouts processtimeouts(); /* 检查timer_list链表中是否有事件已经超时 */ // check for read-ready processreadreadies(&rfds, n); /* 从watch_table中取出监听到的事件, 并添加到pending_list链表 */ // fire away firepending(); /* 从pending_list依次取出事件,并执行该事件的回调 */ } } static void processtimeouts() { dlog("~~~~ +processtimeouts ~~~~"); mutex_acquire(); struct timeval now; struct ril_event * tev = timer_list.next; struct ril_event * next; getnow(&now); // walk list, see if now >= ev->timeout for any events /* 检查timer_list链表中是否有事件已经超时 */ dlog("~~~~ looking for timers <= %ds + %dus ~~~~", (int)now.tv_sec, (int)now.tv_usec); while ((tev != &timer_list) && (timercmp(&now, &tev->timeout, >))) { // timer expired dlog("~~~~ firing timer ~~~~"); next = tev->next; removefromlist(tev); /* 将该超时移出链表 */ addtolist(tev, &pending_list); /* 并且将该超时添加到pending链表 */ tev = next; /* 指针指向下一个超时 */ } mutex_release(); dlog("~~~~ -processtimeouts ~~~~"); } static void processreadreadies(fd_set * rfds, int n) { dlog("~~~~ +processreadreadies (%d) ~~~~", n); mutex_acquire(); for (int i = 0; (i < max_fd_events) && (n > 0); i++) { struct ril_event * rev = watch_table[i]; if (rev != null && fd_isset(rev->fd, rfds)) { /* 从watch_table中取出监听到的事件 */ addtolist(rev, &pending_list); /* 并把该事件加入pending_list链表 */ if (rev->persist == false) { /* 如果该事件不需要处理,则移出removewatch */ removewatch(rev, i); } n--; } } mutex_release(); dlog("~~~~ -processreadreadies (%d) ~~~~", n); } static void firepending() { dlog("~~~~ +firepending ~~~~"); struct ril_event * ev = pending_list.next; while (ev != &pending_list) { /* 从pending_list依次取出事件 */ struct ril_event * next = ev->next; removefromlist(ev); ev->func(ev->fd, 0, ev->param); /* 并执行该事件的回调 */ ev = next; } dlog("~~~~ -firepending ~~~~"); }
上面分析了ril_starteventloop()的事件流程,简单总结就是根据事件调用该事件的处理函数。
到这里还没说到怎样创建socket服务端的,回到mian(),funcs = rilinit(&s_rilenv, argc, rilargv);
初始化了libreference-ril,ril_register(funcs);注册了厂商须实现的相关接口,创建socket服务端的,
并监听客户端连接,一旦连接,则开始等待读取客户端发过来的请求。
hardware/ril/libril/ril.cpp
extern "c" void ril_register (const ril_radiofunctions *callbacks) { ... ... s_fdlisten = android_get_control_socket(socket_name_ril); /* 创建socket服务端,用于与rilj通信 */ if (s_fdlisten < 0) { rloge("failed to get socket '" socket_name_ril "'"); exit(-1); } ret = listen(s_fdlisten, 4); /* 监听rilj */ if (ret < 0) { rloge("failed to listen on control socket '%d': %s", s_fdlisten, strerror(errno)); exit(-1); } /* note: non-persistent so we can accept only one connection at a time */ ril_event_set (&s_listen_event, s_fdlisten, false, /* 设置一个监听事件s_listen_event,一旦与rilj建立连 */ listencallback, null); /* 则进入listencallback,等待读取rilj发送数据 */ rileventaddwakeup (&s_listen_event); /* 添加s_listen_event到watch_table, 唤醒select */ ... ... } static void listencallback (int fd, short flags, void *param) { ... ... s_fdcommand = accept(s_fdlisten, (sockaddr *) &peeraddr, &socklen); /* 接受rilj客户端的连接 */ ... ... err = getsockopt(s_fdcommand, sol_socket, so_peercred, &creds, &szcreds); ret = fcntl(s_fdcommand, f_setfl, o_nonblock); /* 非阻塞方式读写socket */ if (ret < 0) { rloge ("error setting o_nonblock errno:%d", errno); } rlogi("libril: new connection"); p_rs = record_stream_new(s_fdcommand, max_command_bytes); /* 创建一个stream用于缓存读socket的数据 */ ril_event_set (&s_commands_event, s_fdcommand, 1, /* 设置s_commands_event,processcommandscallback循环读取socket的数据 */ processcommandscallback, p_rs); rileventaddwakeup (&s_commands_event); /* 添加s_commands_event事件,唤醒select */ onnewcommandconnect(); /* 通知rilj已建立连接 */ } 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); /* 循环从数据流中读取socket数据 */ if (ret == 0 && p_record == null) { /* end-of-stream */ break; } else if (ret < 0) { break; } else if (ret == 0) { /* && p_record != null */ processcommandbuffer(p_record, recordlen); /* 对接受到的数据进行组包,下发给vender ril,即libreference-ril.so */ } } }
processcommandbuffer(p_record, recordlen)对接收到的数据进行组包,下发给vender ril,即libreference-ril.so,
然后就脱离了rild的控制了,libreference-ril.so主要是厂商对rild控制modem接口的实现。
hardware/ril/libril/ril.cpp
static int processcommandbuffer(void *buffer, size_t buflen) { ... ... p.setdata((uint8_t *) buffer, buflen); /* 把接受到的数据填装到parcel */ // status checked at end status = p.readint32(&request); /* 解析request */ status = p.readint32 (&token); /* 解析token,rilj中的serial */ ... ... pri = (requestinfo *)calloc(1, sizeof(requestinfo)); /* 分配一个requestinfo,用于发送请求给vendor ril */ pri->token = token; /* 设置token */ pri->pci = &(s_commands[request]); /* 设置请求 */ ret = pthread_mutex_lock(&s_pendingrequestsmutex); assert (ret == 0); pri->p_next = s_pendingrequests; /* 添加到s_pendingrequests请求链表中 */ s_pendingrequests = pri; ret = pthread_mutex_unlock(&s_pendingrequestsmutex); assert (ret == 0); /* slastdispatchedtoken = token; */ pri->pci->dispatchfunction(p, pri); /* 执行事件回调,到这里开始进入vender ril了 */ return 0; }
我们仍然以获取sim卡状态为例,pri->pci->dispatchfunction(p, pri)对应调用了dispatchvoid()
hardware/ril/libril/ril.cpp
static void dispatchvoid (parcel& p, requestinfo *pri) { clearprintbuf; printrequest(pri->token, pri->pci->requestnumber); s_callbacks.onrequest(pri->pci->requestnumber, null, 0, pri); }
s_callbacks.onrequest(pri->pci->requestnumber, null, 0, pri); 调用的就是libreference-ril.c中的onrequest()函数。
以上分析了rild对rilj下发的请求处理流程,下面接着分析rild返回response给rilj的流程。分两种情况,一种对请求的响应,
另一种是主动上报。
libreference-ril对请求处理完毕后,调用ril_onrequestcomplete回复rilj该请求的处理结果。
hardware/ril/libril/ril.cpp
ril_onrequestcomplete(ril_token t, ril_errno e, void *response, size_t responselen) { ... ... p.writeint32 (response_solicited); p.writeint32 (pri->token); erroroffset = p.dataposition(); p.writeint32 (e); if (response != null) { // there is a response payload, no matter success or not. ret = pri->pci->responsefunction(p, response, responselen); ... ... } ... ... sendresponse(p); ... ... } static int sendresponse (parcel &p) { printresponse; return sendresponseraw(p.data(), p.datasize()); } static int sendresponseraw (const void *data, size_t datasize) { ... ... ret = blockingwrite(fd, (void *)&header, sizeof(header)); /* 先写4字节数据长度 */ if (ret < 0) { pthread_mutex_unlock(&s_writemutex); return ret; } ret = blockingwrite(fd, data, datasize); /* 再写数据 */ ... ... }
最终是通过sendresponseraw()直接通过写socket回复rilj。对于主动上报的处理是类似的,也是通过sendresponseraw()
上报给rilj。可以参考ril_onunsolicitedresponse()函数。
到此,rilj与rild之间的通信流程已经分析完,后续分析libreference-ril。libreference-ril中先关接口的实现方式,每个modem厂商都不一样。
bc72是通过串口/usb发送at的方式控制,实现通话、短信、上网等功能。
谢谢!