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

     

    谢谢!

  • 相关阅读:
    信息和熵
    【算法】欧几里得算法与青蛙约会oj
    【算法】并查集模板与练习
    Kaggle-房价预测
    【pytorch】pytorch-backward()的理解
    【pytorch】pytorch-LSTM
    【计算机网络】数据链路层总结
    【Code】numpy、pytorch实现全连接神经网络
    【MT】牛津的MT教程
    【计算机网络】物理层基础知识
  • 原文地址:https://www.cnblogs.com/hackfun/p/11693444.html
Copyright © 2020-2023  润新知