欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android4.4 RIL软件框架

程序员文章站 2023-11-09 18:00:40
本文主要对android4.4 RIL的telephony与modem的命令交互流程进行分析,当然本文不是重点介绍telephony。telephony涉及具体业务逻辑内容比较多,包括sim、dail、sms、network等等,以后会针对这些内容学习分析。 RIL在Android体系中的位置: ( ......

    文主要对android4.4 ril的telephony与modem的命令交互流程进行分析,当然本文不是重点介绍telephony。
telephony涉及具体业务逻辑内容比较多,包括sim、dail、sms、network等等,以后会针对这些内容学习分析。

ril在android体系中的位置:

Android4.4 RIL软件框架

 

(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的方式控制,实现通话、短信、上网等功能。

 

谢谢!