qcril:第4章 RILC运行机制

第4章 RILC运行机制

4.1 RILC运行机制

RILC代码重点在于:hardware/ril/libril(Runtime运行环境的源文件)、hardware/ril/reference-ril.so、hardware/ril/rild这三个目录下的C/C++代码文件。

Rilc运行在UserLibraries系统运行库中的HAL层,它使用HAL Stub运行结构。最关键的为Runtime对外提供Proxy代理接口,Stub向Runtime提供Operations操作函数,Runtime向Stub提供Callback函数。

RILC运行机制主要围绕libRIL与Reference-RIL相互调用,从而完成solicited和unsolicited消息处理机制,包括两个过程:启动和运行

启动过程:rild完成;

运行核心:LibRIL和Reference-RIL消息交互。

RILC运行机制

LibRIL为Reference-RIL实现了RIL请求转换成AT命令,并执行AT命令逻辑。

LibRIL提供了Reference-RIL的proxy代理接口。RILJ基于Socket网络连接完成solicited和unsolicited消息和LibRIL进行交互,最终交给Reference-RIL进行处理。

Reference-RIL和modem之间通过串口进行通信,主要用于AT命令执行。

4.1.1 rild.c的main函数

         第一章所说的main函数,它整体负责启动rilc。关键职责是建立LibRIL和Reference-RIL的一种相互协调的能力。

LibRIL中有指向Reference-RIL中funcs结构体的指针。

Reference-RIL中有指向LibRIL中s_rilEnv结构体(Runtime)的指针。

4.1.2 LibRIL目录结构

hardware/ril/libril

    Android.mk

    Ril_commands.h //定义了LibRIL接收到RILJ发出的solicited请求消息所对应的调用函数和返回调用函数。

    Ril.cpp //建立Runtime框架;

    Ril_event.cpp //实现基于ril_event双向链表操作函数;

    Ril_event.h //定义ril_event事件的结构定义;

    Ril_ex.h

    Ril_unsol_commands.h //定义了unsolicited消息返回函数的调用。

……

1)LibRIL以ril.cpp代码为核心,其他代码协助他完成LibRIL Runtime的启动和运行,LibRIl Runtime的两个作用:

1、与RILJ基于socket交互;

2、与Reference-RIL基于函数调用的交互。

2)结构体RIL_env定义了三个指向函数的指针。

3)结构体RIL_RadioFunctions:当LibRIL接收到RILJ发起的solicited请求后,其他5个指向函数的指针会调用Reference-RIL提供给funcs中对应请求函数。

4.1.3 LibRIL Runtime的加载

LibRIl Runtime的加载体现在RIL_startEventLoop和RIL_register两个函数。

1)RILC启动该过程中,先调用LibRIL中的RIL_startEventLoop函数完成LibRIl运行环境的准备,然后开始循环监听socket相关RIL事件。RIL_startEventLoop调用以下相关函数:

eventLoop函数:

s_wakeupfd_event的事件处理分为三大块:

a. 创建管道获取其输入输出文件描述符s_fdWakeupRead、    s_fdWakeupWrite;  

b使用s_fdWakeupRead和processWakeupCallback创建s_wakeupfd_event事件;

c增加并激活s_wakeupfd_event事件。

2)RIL_register函数引入三方RIL_RadioFunctions

3)ril_event事件处理机制

Ril_event_init:双向链表初始化;

Ril_event_set:设置新创建ril_event事件参数;

Ril_event_add:增加event;

Ril_event_loop:开始监听ril事件,分两步:

a.增加pending_list双向链表中的RIL事件节点。processTimeouts和processReadReadies两个函数都是将对应RIL时间增加到pending_list双向链表;

b. 调用firePending函数遍历pending_list双向链表获取ril_event,调用其他func回调函数,完成对应ril事件的回应。

4.1.3 LibRIL 运行机制

分为两个部分:

1)RIJ建立与RIL的socket连接;

2) RILJ向RIL发起solicited消息的交互流程和处理机制。

4.2 AP侧主动请求,以dial为例

RIL.java  dail()àril_service.cpp  dial()àril_service.cpp   CALL_ONREQUESTàreference-ril.c  onRequest()

在这里根据发送的请求类型到requestXXX(),àrequestDial()  “    ret = at_send_command(cmd, NULL);”  à发送AT指令 atchannel.c  at_send_command()    at_send_command_full()  at_send_command_full_nolock()   writeLine()

最后都会到RIL_onRequestComplete

而这里的RIL_onRequestComplete都是调用ril.cppàril.cpp  responseFunction()

 

RIL.dial()

//获取service proxy           IRadio radioProxy = getRadioProxy(result);            

//构造request消息

//调用dial方法

àril_serivce.dial()

RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_DIAL);

//为RequestInfo类型分配了一块内存,并将地址给pRI,这个是response时用的

//解析参数,并保存在RIL_Dial类型的变量内

CALL_ONREQUEST(RIL_REQUEST_DIAL, &dial, sizeOfDial, pRI, mSlotId);

CALL_ONREQUESTs_vendorFunctions->onRequest((a), (b), (c), (d), ((RIL_SOCKET_ID)(e)))    

s_vendorFunctions是vendor lib返回的函数指针,所以到这里也就调用了lib里面相应的函数

lib处理完之后会调用RIL_onRequestCompletedialResponse函数会被调用

àril_service.dialResponse()

radioService[slotId]->mRadioResponse != NULL

//radioService[slotId]中的mRadioResponse是RILJ在启动时放的回调,在RILJ对应的类是RadioResponse

4.3 modem主动上报消息

Modem主动上报:

前面提到过的qcril初始化流程中,调用了Ril_init函数,其中传递的参数”s_rilEnv”是rild.c的全局变量

static struct RIL_Env s_rilEnv = {

    RIL_onRequestComplete,

    RIL_onUnsolicitedResponse,

    RIL_requestTimedCallback,

    RIL_onRequestAck

};

将s_rilEnv的地址传进Ril_Init函数是为了给modem上报消息提供调用接口,当modem有消息上报时,RIL_onUnsolicitedResponse函数会被调用

ril. RIL_onUnsolicitedResponse()

    ret = s_unsolResponses[unsolResponseIndex].responseFunction(

            (int) soc_id, responseType, 0, RIL_E_SUCCESS, const_cast<void*>(data),

            datalen);

s_unsolResponses是ril.cpp的全局变量,使用头文件ril_unsol_commands.h初始化。该文件定义了每个unsolicited消息对应的函数;RIL_onUnsolicitedResponse通过s_unsolResponses找到对应函数,并调用。

ril_unsol_commands.h:

{RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED, radio::radioStateChangedInd, WAKE_PARTIAL},

{RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, radio::callStateChangedInd, WAKE_PARTIAL},

以RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED为例,RIL_onUnsolicitedResponse会调用callStateChangedInd函数:

callStateChangedInd通过radioService[slotId]的mRadioIndication将消息传到Java层,Java层对应的类是RadioIndication.java。RadioIndication.callStateChanged会调用ril.java将消息进一步上传。

 

 

 

RIL.java

public class RIL extends BaseCommands implements CommandsInterface

RadioIndication                              RadioResponse

从名字就可以看出,RadioIndication用于处理modem主动上报的消息,RadioResponse用于处理AP侧request的response

public class RadioIndication extends IRadioIndication.Stub

public class RadioResponse extends IRadioResponse.Stub

根据上面的定义,RadioIndication和RadioResponse都继承于Stub,明显是为了进程间的通信

Ril.java对象是在开机时PhoneApp应用启动的过程中创建的,Ril.java的构造函数完成了初始化工作,包括RadioIndication、RadioResponse对象的创建以及HIDL service的获取。

getRadioProxy方法获取了HIDL service,并将RadioResponse和RadioIndication对象传递给service,经过binder传递后,这两个对象的引用分别被保存在RadioImpl::mRadioResponse和RadioImpl::mRadioIndication中,后续用于modem给AP侧上报消息。

**************************************************************************************************************************************************************************

术语:

fd:unix文件描述符

pipe:unix管道

cond:一般是condition variable的缩写

tty:通常使用tty来简称各种类型的终端设备

unsolicited response:被动请求命令来自baseband

eventLoop:Android的消息队列机制,有Unix的系统调用select()实现

init.rc:init守护进程启动后被执行的启动脚本

HAL:硬件抽象层

4.4 solicited消息处理机制

 

Solicited消息的交互流程和处理机制

  1. RILJ与LibRIL建立socket连接后,LibRIL的watch_table数组增加了一个事件监听:s_commands_event;
  2. RILJ基于rild端口的socket向LibRIL发起Solicited Request消息请求时,s_commands_event通过func发起RILJ事件callback函数调用
  3. 即调用processCommandsCallback函数处理RILJ发起的request请求,在ril_commands.h头文件中定义了107个RIL请求的处理函数和回调函数
  4. RILJ在发起RIL请求后,在这里通过RIL请求类型获取请求处理和返回处理的函数(比如:发起拨号请求,LibRIL匹配CommandInfo的请求调用函数为dispatchDial,返回调用函数responseVoid;当LibRIL发起pRI->pCI->dispatchFunction函数调用时,实际调用的是dispatchDial函数)
  5. LibRIL请求调用函数,最终通过Reference_RIL提供的s_callbacks发起onRequest函数调用
  6. Reference-RIL接收到LibRIL的请求,根据请求类型转换成对应的AT命令,向modem发起AT指令;接着便会调用LinRIL提供的RIL_onRequestComplete函数,完成RIL请求处理完成后的回调
  7. RIL_onRequestComplete函数处理逻辑:responseFunction函数调用,完成不用返回的Parcel数据设置;sendResponse函数调用,通过socket连接发生Parcel数据,即RILJ接收此数据;同样发起拨号请求后,pRI->pCI->responseFunction函数调用,实际是responseCallList函数调用

 

 

 

 

 

Reference-ril.c主要负责:

  1. 将Solicited Request请求转化为AT命令交给Modem执行,并将AT命令执行的结果以Solicited Response消息的方式反馈给LibRIL;
  2. 同时负责接收modem主动上报的消息,以UnSolicited Response消息的方式反馈给LibRIL处理,逻辑可分为两部分:与LibRIL的交互完成RIL消息的处理、与modem通信模块的交互完成AT命令的执行

Reference-ril.c运行机制:

  1. Reference-ril的初始化函数RIL_Init
  2. onRequest函数接收LibRIL的请求调用
  3. 接收modem发出的UnSolicited Response消息处理逻辑

RIL_Init函数初始化Reference-ril:

  1. 记录LibRIL提供的RIL_Env指针,通过他调用LibRIL提供相应函数
  2. 启动mainLoop子进程,负责监听和接受modem主动上报的UnSolicited消息
  3. 返回Reference-ril提供的指向RIL_RadioFunctions指针s_callbacks

onRequest接收LinRIL的请求调用:LibRIL接收到RILJ发起的ril请求后,通过onRequest函数调用,向Reference-ril发起对应的RIL请求

  1. 将RIL请求转化为对应的AT命令,并向modem发出AT命令
  2. 调用LibRIL的RIL_onRequestComplete函数,完成RIL请求处理结果的返回

UnSolicited消息处理逻辑:mainLoop函数主要负责监听和处理modem上报的UnSolicited消息

  1. 与modem建立基于串口的通信连接,同时获取连接的文件扫描符fd
  2. 调用at_open函数开启AT命令通道:保存与modem建立连接的文件描述符fd,以及接收到modem发出的AT命令后的回调函数onUnsolicited、启动readerLoop子进程,readerLoop函数会for循环监听并接受modem发出的AT命令
  3. onUnsolicited函数:提供LibRIL提供的RIL_onUnsolicitedResponse函数发出不同类型的UnSolicited Response消息通知
  4. RIL_onUnsolicitedResponse函数:根据UnSolicited Response消息类型获取s_unsolResponses数组中对应的UnSolicited ResponseInfo结构体对象,其中包括此消息电源唤醒策略和Parcel数据处理函数、应用UnsolResponseInfo中的电源管理唤醒策略,进行电源唤醒操作、调用UnsolResponseInfo中的Parcel数据处理函数,完成Parcel数据的组织和设置、调用sendResponse函数,通过socket连接发送Parcel给RILJ                                                                                            

现在都是用的都是qcril-hal, 但是流程和我讲的qcril流程差不多。

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值