ril - 3

本文深入分析AT指令响应机制,包括主动上报与命令响应处理流程。详细介绍了onUnsolicite函数处理主动上报信息,以及handleFinalResponse如何完成标准响应。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前文对request的分析, 终止在了at_send_command_full_nolock里的writeline操作,因为这里完成命令写出到硬件设备的操作,接下来就是等待硬件响应,也就是response的过程了。我们的分析也是从这里开始。
response信息的获取,是在第一篇初始化分析中,提到的readerLoop中。由readline函数以‘行’为单位接收上来。
AT的response有两种,一是主动上报的,比如网络状态,短信,来电等都不需要经过请求,有一unsolicited词语专门描述。另一种才是真正意义上的response,也就是命令的响应。

  这里我们可以看到,所有的行,首先经过sms的自动上报筛选,因为短信的AT处理通常比较麻烦,无论收发都单独列出。这里是因为要即时处理这条短信消息(两行,标志+pdu),而不能拆开处理。处理函数为onUnsolicited(由s_unsolHandler指向),我们等下介绍。

  除开sms的特例,所有的line都要经过processLine,我们来看看这个流程:

processLine
|----no cmd--->handleUnsolicited //主动上报
|----isFinalResponseSuccess--->handleFinalResponse //成功,标准响应
|----isFinalResponseError--->handleFinalResponse //失败,标准响应
|----get '>'--->send sms pdu //收到>符号,发送sms数据再继续等待响应
|----switch s_type--->具体响应 //命令有具体的响应信息需要对应分析

  我们这里主要关注handleUnsolicited自动上报(会调用到前面smsUnsolicite也调用的onUnsolicite),以及switch s_type具体响应信息,另外具体响应需要handleFinalResponse这样的标准响应来最终完成。

1. onUnsolicite(主动上报响应)
static void onUnsolicited (const char *s, const char *sms_pdu);

  短信的AT设计真是麻烦的主,以致这个函数的第二个参数完全就是为它准备的。response的主要的解析过程,由at_tok.c中的函数完成,其实就是字符串按块解析,具体的解析方式由每条命令或上报信息自行决定。这里不再详述,onUnsolicited只解析出头部(一般是+XXXX的形式),然后按类型决定下一步操作,操作为RIL_onUnsolicitedResponse和RIL_requestTimedCallback两种。

a)RIL_onUnsolicitedResponse:

  将unsolicited的信息直接返回给上层。通过Parcel传递,将RESPONSE_UNSOLICITED,unsolResponse(request号)写入Parcel先,然后通过s_unsolResponses数组,查找到对应的responseFunction完成进一步的的解析,存入Parcel中。最终通过sendResponse将其传递回原进程。流程:
sendResponse-->sendResponseRaw-->blockingWrite-->write to s_fdCommand(前面建立起来的和上层框架的socket连接)
这些步骤之后有一些唤醒系统等其他操作。不再详述。

  b)RIL_requestTimedCallback:

  通过event机制(参考文章二)实现的timer机制,回调对应的内部处理函数。通过internalRequestTimedCallback将回调添加到event循环,最终完成callback上挂的函数的回调。比如pollSIMState,onPDPContextListChanged等回调, 不用返回上层, 内部处理就可以。

  2. switch s_type(命令的具体响应)及handleFinalResponse(标准响应):

  命令的类型(s_type)在send command的时候设置(参考文章二),有NO_RESULT,NUMERIC,SINGLELINE,MULTILINE几种,供不同的AT使用。比如AT+CSQ是singleline, 返回at+csq=xx,xx,再加一行OK,比如一些设置命令,就是no_result, 只有一行OK或ERROR。

  这几个类型的解析都很相仿,通过一定的判断(比较AT头标记等),如果是对应的响应,就通过addIntermediate挂到一个临时结果sp_response->p_intermediates队列里。如果不是对应响应,那它其实应该是穿插其中的自动上报,用onUnsolicite来处理。

  具体响应,只起一个获取响应信息到临时结果,等待具体分析的作用。无论有无具体响应,最终都得以标准响应handleFinalResponse来完成,也就是接受到OK,ERROR等标准response来结束,这是大多数AT命令的规范。 

  handleFinalResponse会设置s_commandcond这一object,也就是at_send_command_full_nolock等待的对象。到这里,响应的完整信息已经完全获得,send command可以进一步处理返回的信息了(临时结果,以及标准返回的成功或失败,都在sp_response中)。

  pp_outResponse参数将sp_response返回给调用at_send_command_full_nolock的函数。
继续我们在文章二的分析的话,这个函数其实是requestDial,不过requestDial忽略了响应,所以我们另外看个例子,如requestSignalStrength,命令其实就是前面提到的at+csq:可以看到确实是通过at_send_command_singleline来进行的操作,response在p_response中。p_response如果返回失败(也就是标准响应的ERROR等造成),则通过RIL_onRequestComplete发送返回数据给上层,结束命令。

  如果成功,则进一步分析p_response->p_intermediates, 同样是通过at_tok.c里的函数进行分析。并同样将结果通过RIL_onRequestComplete返回。

RIL_onRequestComplete:
RIL_onRequestComplete和RIL_onUnsolicitedResponse很相仿,功能也一致。

  通过Parcel来传递回上层,同样是先写入RESPONSE_SOLICITED(区别于RESPONSE_UNSOLICITED),pRI->token(上层传下的request号),错误码(send command的错误,不是AT响应)。如果有AT响应,通过访问pRI->pCI->responseFunction来完成具体response的解析,并写入Parcel。

  然后通过同样的途径:
sendResponse-->sendResponseRaw-->blockingWrite-->write to s_fdCommand

完成最终的响应传递。

  到这里,我们分析了自动上报与命令响应,其实response部分,也就告一段落了,三篇分析RIL的文章也到此结束。

参考资源链接:[Android通话流程解析:RIL-Java到DriverCall](https://wenku.youkuaiyun.com/doc/4br72n9v8b?utm_source=wenku_answer2doc_content) 要通过RIL-Java实现电话呼叫的异步处理流程,首先需要理解RIL-Java在Android电话系统中的作用。RIL-Java作为中间层,负责封装与RIL的通信,并提供上层应用程序所需的接口。以下步骤将指导您实现电话呼叫的异步处理流程: 1. 使用CommandInterface定义电话呼叫的命令接口,通过这些接口可以发起拨打电话、接听电话等操作。例如,拨打电话通常使用`outgoingCall`方法。 2. RILSender负责将这些命令通过监听套接字发送给RILD。这里需要创建一个RILRequest对象,设置相应的命令和参数,然后通过套接字发送给RILD进行处理。 3. RILReceiver负责接收来自RILD的响应。在异步处理机制下,响应并不是立即返回给请求发起者的,而是通过注册的回调接口异步接收。当RILD处理完命令并产生响应时,它将通过监听套接字返回结果,RILReceiver再将这个响应转发给对应的回调接口。 4. 实际的电话呼叫处理逻辑在RILD中完成。RILD接收到命令后,会转换成硬件级别的操作,如通过AT命令与基带处理器通信。当硬件操作完成并返回结果时,RILD将结果封装成响应消息回传给RIL-Java。 5. 通过RIL-Java的异步处理机制,将RILD返回的结果通过回调接口传递给最初发起请求的应用程序或服务,应用程序可以更新UI或执行其他相关操作。 在这个过程中,您需要深入理解RIL-Java中的异步处理机制,以及如何利用RILSender发送命令和RILReceiver接收响应。要实现这一流程,推荐您阅读《Android通话流程解析:RIL-Java到DriverCall》这本书。它详细解析了Android系统的通话流程,涉及到了RIL-Java、Call、Phone、Connection、DriverCall和CallTracker等核心组件。通过这本书的学习,您可以更加深入地掌握电话呼叫的异步处理流程,并且对RIL-Java组件有一个全面的理解。 参考资源链接:[Android通话流程解析:RIL-Java到DriverCall](https://wenku.youkuaiyun.com/doc/4br72n9v8b?utm_source=wenku_answer2doc_content)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值