Android Telephony RIL Request Message執行流程

Android Telephony包含了打電話,發短信,電話本,注網等,telephony framework各個module非常依賴於RILD和modem,framework的設置,設置的結果,網絡的變化,打電話等都需要framework通過HIDL結果向底層請求,請求的結果通過message傳回來。發送請求的時候,將message傳入,等RILD返回結果後,再通過message將結果反饋出來,framework解析message的結果。那Message在這個過程中是如何流動的呢?request的response返回後,是如何找到request的message,將結果傳入Message的呢?我們拿sendCdmaSms作爲例子(會精簡一些無關的code)。
在Android P 版本上看一下RIL.java中sendCdmaSms,精簡之後的code如下:

@Override
public void sendCdmaSms(byte[] pdu, Message result) { //我們跟蹤的message就是參數result
    IRadio radioProxy = getRadioProxy(result); // getRadioProxy中沒有存儲result,傳入result的目的是getRadioProxy可能有異常, 直接將message result send回Handler。例如proxy 還沒有創建好,還是null
    if (radioProxy != null) {
        RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_SEND_SMS, result, mRILDefaultWorkSource);//mRILDefaultWorkSource這個參數我們可以忽略掉,現在result被傳入了RILRequest rr,rr的成員已經指向了result。
        CdmaSmsMessage msg = new CdmaSmsMessage();
        constructCdmaSendSmsRilRequest(msg, pdu); // 這部分和Message Result無關,這部分在組裝pdu到結構體,通過HIDL接口傳給RILD
        try {
            radioProxy.sendCdmaSms(rr.mSerial, msg); // 這就會通過binder call到了rild,只使用了RILRequest rr的mSerial,從這裏可以推測出我們的Message result已經存儲到rr,並且rr也以某種方式存儲起來。等request的response的回來後,通過某種方式取出對應的rr,之後找到rr中存儲的message result。
        } catch (RemoteException | RuntimeException e) {
            handleRadioProxyExceptionForRR(rr, "sendCdmaSms", e);
        }
    }
}

我們先看一下RIL.java中obtainRequest的實現

protected RILRequest obtainRequest(int request, Message result, WorkSource workSource) {
    RILRequest rr = RILRequest.obtain(request, result, workSource);
    addRequest(rr);
    return rr;
    // obtainRequest做了兩件事情,通過RILRequest的obtain方法獲取一個RILRequest rr,並將rr加入到某個鏈表中。
}

private void addRequest() {
    acqureWakeLock(rr, FOR_WAKELOCK);
    synchronized (mRequestList) {
        mRequestList.append(rr.mSerial, rr); //從這裏就開看出mRequestList想要找到某個rr,需要使用mSerial來尋找,也就是mSerial是mRequestList的key。我們在這裏可以有理由猜測request的response回來的時候,一定會攜帶merial,因爲HIDL接口調用的時候傳入的mSerial(radioProxy.sendCdmaSms(rr.mSerial, msg))。之後通過response的mSerial找到mRequestList對應的rr,之後從rr取出message,發送傳出去即可。
    }
}

我們繼續分析RILRequest和obtainRequest。
我們簡化一下RILRequest(可以參考RILRequest.java),不影響解釋Message的傳播

public class RILRequest { //已經簡化了
    public int mSerial; // 這個值就是HIDL傳入的值
    public Message mResult; // 這個就是傳入的Message result存儲的位置。
    static AtomicInterger sNextSerial = new AtomicInterger(0); // 用來生成mSerial的值,不斷增加
    private static RILRequest obtain(int request, Message result) {
        RILRequest rr = null;
        rr = new RILRequest();
        rr.mResult = result; //存儲message
        rr.mSerial = sNextSerial.getAndIncrement(); 
        return rr;
    }
}

現在我們就只剩下對request的response的分析了,主要是驗證我們的猜測是否正確。request的response都在RadioResponse.java中
我們看一下RadioResponse.java中sendCdmaSmsResponse(sendCdmaSms的返回結果通過這個函數返回到framework);

// 這個函數沒有貨,這樣做只是統一GSM和CDMA的response到一個函數中

public void sendCdmaSmsResponse(RadioResponseInfo responseInfo, SendSmsResult sms) {
    responseSms(responseInfo, sms);
}

繼續看responseSms

private void responseSms(RadioResponseInfo responseInfo, SendSmsResult sms) {
    RILRequest rr = mRil.processResponse(reesponseInfo); // processResponse通過reesponseInfo的成員serial找到mRequestList中的rr,並且將rr從mRequestList中移除掉. mRil.processResponse的實現請參考RIL.java中processResponse的實現。
    // 下面就是取出rr的mResult並且將SendSmsResult sms添加到message裏面,之後發送出去。
    if (rr != null) {
        SmsResponse ret = new SmsResponse(sms.messageRef, sms.ackPDU, sms.errorCode); //重新組裝SendSmsResult
        if(responseInfo.error == RadioError.NONE) {
            sendMessageResponse(rr.mResult, ret); //已經取出rr中的message,也就是rr.mResult,request的response的結果變成了ret
        }
        mRil.processResponseDone(rr, responseInfo, ret); // 這個是做一些收尾的動作
    }
}

最後一步sendMessageResponse

public static void sendMessageResponse(Message msg, object ret) {
    if(msg != null) {
        AsyncResult.forMessage(msg, ret, null); //封裝ret到msg的成員obj
        msg.sendTotarget(); // 發送msg到handler進行處理。
    }
}

// 關於AsyncResult.forMessage討論就不講了,具體可以參考AsyncResult中的code和Message的code。

public class AsyncResult {
    public static AsyncResult forMessage(Message m, Object r, Throwable ex) {
        AsyncResult ret;
        ret = new AsyncResult(m.obj, r, ex);
        m.obj = ret;
    }
}

framework的request帶的message一直在framework中維護着,爲了能夠response能夠取到正確的message,request下發的時候,將key帶到rild,response回來的時候還繼續將key帶回來,這樣通過這個key就能找到request對應的message了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章