writeStringToParcel(p, (const char*)(appStatus[i].app_label_ptr)); p.writeInt32(appStatus[i].pin1_replaced); p.writeInt32(appStatus[i].pin1); p.writeInt32(appStatus[i].pin2); }
closeResponse; }
其实这里所谓的打包处理,不过是根据不同的命令,把相应的回应写入到给RILJ的返回数据包中。 然后在RIL_onRequestComplete中调用sendResponse把数据发送到RILJ层。 以上就是RIL数据传输的整个过程。
现在,我们再来回顾一下在本文开始处展示的RIL层数据流向图,希望这次看到他时不会那么的陌生:
四、一些重要概念
4.1、s_commandcond
我们知道,RIL是一个框架,并不会在意每个命令之间的差异,但是每个命令所发送的数据不同,要求的回应更是不同。而这个数组就是完成了从标准化到差异化的转换过程。 先来看一下定义:
static CommandInfo s_commands[] = { #include \ };
以上这个变量定义在是一个数组,类型如下: typedef struct { int requestNumber;
void (*dispatchFunction) (Parcel &p, struct RequestInfo *pRI); int(*responseFunction) (Parcel &p, void *response, size_t responselen); } CommandInfo;
这个结构体中有3个数据:requestNumber表示一个命令的请求码;dispatchFunction表示当前命令发送给reference库时的入口函数;而responseFunction表示reference给出应答后需要用这个函数对应答数据进行封装,然后传递给RILJ; 主要内容如下:
{RIL_REQUEST_GET_SIM_STATUS, dispatchVoid, responseSimStatus}, {RIL_REQUEST_ENTER_SIM_PIN, dispatchStrings, responseInts}, {RIL_REQUEST_ENTER_SIM_PUK, dispatchStrings, responseInts},
结合到流程来说,当我们从Eventloop中读取一条RILJ发送的请求后,在Eventloop的发送最后
(processCommandBuffer函数)根据当前命令去s_commands中查找相应的dispatchFunction和responseFunction,组成一个RequestInfo的数据。然后调用当前命令的dispatchFunction函数将RequestInfo数据发送给reference库。 而当reference接收到Modem数据后,根据当前命令的RequestInfo信息,查找当前命令的应答回调(responseFunction)对回应数据进行封装,封装后调用统一的reference到Event侧的接口函数(RIL_onRequestComplete)把数据发送给Event侧,再由Event侧发送到RILJ。
4.2、s_unsolResponses
对比上面的s_commands来看,这个变量就显得比较简单了。我们先来看一下他的定义:
static UnsolResponseInfo s_unsolResponses[] = { #include \ };
然后列出几个重要的数组内容
{RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, responseVoid, WAKE_PARTIAL}, {RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, responseVoid, WAKE_PARTIAL},
{RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED, responseVoid, WAKE_PARTIAL}, 再来看数据类型: typedef struct { int requestNumber;
int (*responseFunction) (Parcel &p, void *response, size_t responselen); WakeType wakeType; } UnsolResponseInfo;
这里我们看到,他和s_commands的区别就在于他的里面只有responseFunction而没有dispatchFunction。为什么会这样呢?原因就在于URC消息与非URC消息的区别上。
上面我们讲到,非URC消息是由RILJ主动发起的并且需要接受Modem的数据;而URC消息是Modem主动上报的(比如网络状态改变的消息),因此没有发送的过程,只有接受消息的过程。因此不需要dispatchFunction。 再次结合流程来看一下,当我们在reference的ReaderLoop中检测到Modem消息时,如果是URC消息,就在reference中根据AT命令头的不同转换为相应的命令号(onUnsolicited中完成),然后把数据发送给Event侧(RIL_onUnsolicitedResponse接收),在Event侧根据命令号的不同找到s_unsolResponses中对应的responseFunction,对数据进行不同的封装,然后发送给RILJ(仍在RIL_onUnsolicitedResponse中处理)。
4.3、RequestInfo
这个数据类型是Event侧与reference侧协定的统一命令格式。所有的命令,当从Event侧发送到reference侧时,都要把他标准化为RequestInfo结构。 数据结构:
typedef struct RequestInfo { int32_t token; CommandInfo *pCI; struct RequestInfo *p_next;
char cancelled; char local; } RequestInfo;
其中token是当前命令的令牌,相当于命令的ID。pCI的数据结构: typedef struct { int requestNumber;
void (*dispatchFunction) (Parcel &p, struct RequestInfo *pRI); int(*responseFunction) (Parcel &p, void *response, size_t responselen); } CommandInfo;
这个数据表明了当前命令的3个很重要属性:1、当前命令的请求码;2、当前命令发送到reference侧的入口;3、当前命令从reference返回给Event侧时要调用responseFunction进行数据封装。