Android4.4 RIL軟件框架

1
回復
583
查看
打印 上一主題 下一主題
[復制鏈接]

262

主題

285

帖子

1萬

安幣

管理員

Rank: 9Rank: 9Rank: 9

樓主
發表于 2019-12-9 16:00:01 | 只看該作者 |只看大圖 回帖獎勵 |倒序瀏覽 |閱讀模式
如果對本篇文章感興趣,請前往,原文地址:http://www.1574304.live/blog-986390-82729.html

文主要對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 d                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 == NULL) {                    watch_table = 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;                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??梢詤⒖糝IL_onUnsolicitedResponse()函數。

        到此,RILJ與RILD之間的通信流程已經分析完,后續分析libreference-ril。libreference-ril中先關接口的實現方式,每個modem廠商都不一樣。
BC72是通過串口/USB發送AT的方式控制,實現通話、短信、上網等功能。


謝謝!
  繼續閱讀全文



想在安卓巴士找到更多優質博文,可移步博客區

如果對本篇文章感興趣,請前往,
原文地址:
http://www.1574304.live/blog-986390-82729.html
分享到:  QQ好友和群 QQ空間 微信
收藏
收藏0
支持
支持0
反對
反對0

0

主題

1

帖子

12

安幣

初級碼農

Rank: 1

沙發
發表于 2019-12-20 17:57:41 | 只看該作者







您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

領先的中文移動開發者社區
18620764416
7*24全天服務
意見反饋:[email protected]

掃一掃關注我們

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粵ICP備15117877號 )

在柳州学什么小吃赚钱