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了。

你可能感兴趣的:(Android移动开发)