qcril接口函数
来源:互联网 发布:数据架构师是做什么的 编辑:程序博客网 时间:2024/05/30 12:29
qcril中包括两个部分,一个funsion 一个qmi
每个对应一个事件表qcril_event_table。所谓事件表是指rild进程给下面发某一条命令或者modem给qcril返回一个事件都代表一个事件,由qcril_dispatch_event调用。表中的每个成员包括了请求号和相应的处理函数如语音呼叫RIL命令:
在qmi中RIL_REQUEST_DIAL-->qcril_qmi_voice_request_dial在fusion中RIL_REQUEST_DIAL---qcril_cm_callsvc_request_dial
qcril_cm_api_callbacks:
一个请求在qcril处理完传给modem后要调用qcril_send_request_response来回复上层
qcril_response_api:将回复传给上层qcril_response_api[ param_ptr->instance_id ]->OnRequestComplete,在代码里被赋予为s_rilEnv=s_rilEnv
从qcril给cm发命令是通过初始化时,注册一个静态的数组qcril_cm_api_funcs[],这个数组保存在sharememory里面,这就保证了这个数组里面的函数能被cm和qcril共享调用。他里面包含了对应不同cm事件的处理函数
qcril_process_event:用来处理event如cm处理发来的始呼回调事件,注意不是处理ril发来的请求
qcril_event_main:是一个循环,用来等待amss发给qcril的事件,并给予相应的处理调用的是qcril_process_event
qcril里面等待从modem来的事件也采用sock通信调用select监听端口:
n = select(qcril_event.fdWakeupRead + 1, &rfds, NULL, NULL, NULL);
一旦modem有命令给qicril则会调用qcril_process_event,这个函数是用来处理event如:cm处理完主动命令发回来的始呼回调事件,注意这个函数不是处理从rild进程发来的请求.。而这个函数又会调用qcril_dispatch_event会调用前面红字显示的qcril_event_table数组里面的函数来处理事件
CM_CALL_EVENT_ORIG 的处理函数qcril_cm_callsvc_event_orig
qcril_send_unsol_response:给上层发底层被动事件的回复
qcril_send_request_response:对上层请求的回复调用这个函数
/*下面这个是ril和qcril的接口*/
static const RIL_RadioFunctions qcril_request_api[ QCRIL_MAX_INSTANCE_ID ] = { { RIL_VERSION, onRequest_rid0, currentState_rid0, onSupports_rid0, onCancel_rid0, getVersion_rid0 } #ifdef FEATURE_QCRIL_DSDS , { RIL_VERSION, onRequest_rid1, currentState_rid1, onSupports_rid1, onCancel_rid1, getVersion_rid1 } #endif /* FEATURE_QCRIL_DSDS */};
2、rild
rild进程的main函数在rild.c里面。下面只写了主要的3个步骤
main()>1、RIL_startEventLoop(); 它的主要目的是通过pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL)建立一个dispatch线程,入口点在eventLoop. 而eventLoop中,会调ril_event.cpp中的ril_event_loop()函数,建立起消息(event)队列机制。funcs_inst = rilInit(s_rilEnv, argc, s_argv);/*调用的是qcril.c里的RIL_Init函数"s_rilEnv是定义时就初始化了的函数,会赋值给qcril里的一个成员,(qcril_response_api)用来给上层发回复或者发消息其有两个很重要的步骤:1、qcril_response_api[ instance_id ] = (struct RIL_Env *) env;其中env就是输入的s_rilEnv2、return &qcril_request_api[ instance_id ];这个是返回给RILD的数组,赋值给了funcs_inst被rild用来给qcril的发请求的函数3、RIL_register(funcs_inst[i], i);注册调用ril_init返回的数组中函数,同时打开跟上层通信的socket接口(s_fdListen是主接口,s_fdDebug供调试时使用)。仅列出s_fdListen的设置,其中listenCallback是当有连接请求时要调用的函数, ril_event_set (&s_listen_event, s_fdListen, false,listenCallback, NULL);<span style="font-family:宋体;font-size:14px;color:#333333;line-height:28px; text-indent:28px"><strong></strong></span><pre name="code" class="cpp">
下面写rild线程的事件机制
ril_event_loop()函数,所有的事件都由他来处理。他有三个事件队列 watch_list,timer_list,pending_list,并使用了一个设备句柄池readFDS。
readFDS:是Linux的fd_set,readFDS保存了Rild中所有的设备文件句柄,以便利用select函数统一的完成事件的侦听。
watch_list:监测队列。需要检测的事件都放入到该队列中(包括请求连接事件)。
timer_list:timer队列
pending_list:待处理事件队列
当watch_list队列上检测到事件时,将其放入到pending_list里等待处理。下面通过请求的流程来写事件机制。
当有请求连接信号到来时,select发现rild socket有了请求链接的信号,导致s_listen_event从watch_list中取下并被挂入pending_list,执行event->func。这个回调函数是listenCallback,之后通过这个句柄过来的命令都由processCommandBuffer函数处理。
这个函数里面有这样两句
pRI->pCI = &(s_commands[request]); //ril_commands.h里面获得request号对应的函数pRI->pCI->dispatchFunction(p, pRI);就是调用上面得到的分派函数
举例如下,语音呼叫在ril_commands.h对应的成员是{RIL_REQUEST_DIAL,dispatchDial, responseVoid},其中dispatchDial在ril.cpp文件中。而这个函数里面有这样一句:s_callbacks[pRI->client_id].onRequest(pRI->pCI->requestNumber, &dial, sizeOfDial, pRI);
他这里调用的onRequest,就是qcril.c里面的onRequest_rid0/1(...)-->onRequest
{
qcril_request_params_type param;
param.event_id = request;
param.data = data;
param.datalen = datalen;
param.t = t;
param.instance_id = instance_id;
param.modem_id = QCRIL_DEFAULT_MODEM_ID;
...;
qcril_dispatch_event( entry_ptr, ¶m ) == E_NOT_ALLOWED
} 在这个之后调用qcril_dispatch_event分派函数,这个分派函数是在数组qcril_event_table里面找处理函数.responseVoid:这个是response函数,当命令处理完后,会返回一个回复结构体,回复结构体的序列化操作在这个里面处理。每个命令的回复函数是可以自己定义的,因为回复结构体比较复杂,不是单一的同一个类型。
static int responseInts(Parcel &p, void *response, size_t responselen) {
int numInts;
if (response == NULL && responselen != 0) {
ALOGE("invalid response: NULL");
return RIL_ERRNO_INVALID_RESPONSE;
}
if (responselen % sizeof(int) != 0) {
ALOGE("invalid response length %d expected multiple of %d\n", (int)responselen, (int)sizeof(int));
return RIL_ERRNO_INVALID_RESPONSE;
}
int *p_int = (int *) response;
numInts = responselen / sizeof(int *);
p.writeInt32 (numInts); /* each int*/
startResponse;
for (int i = 0 ; i < numInts ; i++) {
appendPrintBuf("%s%d,", printBuf, p_int[i]); p.writeInt32(p_int[i]);
}
removeLastChar;
closeResponse;
return 0;}
ril_commands.h包含了主动请求的每个事件对应的分派处理函数和参数
ril_unsol_commands.h包含了被动上报的每个事件对应的分派处理函数和参数
RIL_Init:在qcril里
主动上报的事件
RIL_onUnsolicitedSendResponse是将从qcril传上来的主动上报信息传给上层的函数,处理流程如下:
qcril_send_unsol_response-->qcril_response_api[ instance_id ]->OnUnsolicitedResponse这里实际调用RIL_onUnsolicitedResponse-->
RIL_onUnsolicitedSendResponse(int unsolResponse, void *data,size_t datalen, int client_id)
{
Parcel p;
p.writeInt32 (RESPONSE_UNSOLICITED);
p.writeInt32 (unsolResponse);
ret = s_unsolResponses[unsolResponseIndex].responseFunction(p, data, datalen);
}
其中
static UnsolResponseInfo s_unsolResponses[] = {
#include "ril_unsol_commands.h"
};
首先调用rild里的s_unsolResponses[unsolResponseIndex].responseFunction(p, data, datalen)来处理unsolicited命令(只是序列化response结构体)。
与命令对应的回复流程:
qcril_send_request_response
{
qcril_response_api[ param_ptr->instance_id ]->OnRequestComplete( param_ptr->t, param_ptr->ril_err_no,
param_ptr->resp_pkt, param_ptr->resp_len );
}
这里的OnRequestComplete就是ril.cpp里面的RIL_onRequestComplete
RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen) {
RequestInfo *pRI;
pRI = (RequestInfo *)t;
if (pRI->cancelled == 0) {
Parcel p;
p.writeInt32 (RESPONSE_SOLICITED);//表示是针对请求的回复事件
p.writeInt32 (pRI->token); //令牌号
errorOffset = p.dataPosition();
p.writeInt32 (e); //处理是否成功
if (response != NULL) {
//调用每个命令对应的回复函数在ril_commands.h里,如responseInts 在ril.cpp文件里头
ret = pRI->pCI->responseFunction(p, response, responselen);
if (ret != 0) {
p.setDataPosition(errorOffset);
p.writeInt32 (ret);
}
}
sendResponse(p,pRI->client_id);
}
之后再调用sendresponse,这个函数是真正用来上报给ril java层的。
ril java
public class GSMPhone extends PhoneBase
public abstract class PhoneBase extends Handler implements Phone
GSMPhone和CDMAPhone继承了PhoneBase,PhoneBase(实现了Phone接口中定义的函数)-->Phone 这是一个接口
PhoneProxy是GSMPhone和CDMAPhone的代理-->Phone 这是一个接口,初始化如下(代码位于phoneapp.java):
PhoneFactory.makeDefaultPhones(this);在这个函数里真正的初始化了phone对象
phone = PhoneFactory.getDefaultPhone(); //获取这个sProxyPhone对象。
PhoneFactory.makeDefaultPhones{
sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);//初始化ril实例
/*这里会把gsmphone实例保存在sProxyPhone的mActivePhone成员里面*/
sProxyPhone = new PhoneProxy(new GSMPhone(context,sCommandsInterface, sPhoneNotifier));
}
GSMPhone并不是直接提供接口给上层用户使用。而是通过另外一个管理类TelephonyManager来使用。
而TelephonyManager又主要调用系统的两个服务:
1.ITelephony:提供给上层应用程序用户与telephony进行操作与交互的接口,这个服务实现在packages/apps/Phone中。PhoneInterfaceManager.java实现。
TelephonyManager类里面通过 ITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE))来获得一个PhoneInterfaceManager的代理。PhoneInterfaceManager里面有一个phone的interface对象,其实他就是初始化为GSMPhone。PhoneInterfaceManager通过调用phone里面的函数来交给底层处理。
2.ItelephonyRegistry提供了一个通知机制,将底层来的事件通知给框架中需要得到通知的部分,服务端由TelephonyRegistry.java实现。TelephonyManager里面有一成员
private static ITelephonyRegistry sRegistry;
在TelephonyManager初始化时
sRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService("telephony.registry"));
TelephonyManager将通过这个sRegistry 成员告诉 telephonyRegistry 服务,他对哪类事件感情趣。之后gsmphone里的mNotifier对象会把发生的事件通过同样的原理告诉telephonyRegistry。然后telephonyRegistry 依次检查哪些线程对当前发生的事件感兴趣,并给其发一个msg
TelephonyManager里面有个listen函数如下:
public void listen(PhoneStateListener listener, int events) { String pkgForDebug = sContext != null ? sContext.getPackageName() : "<unknown>"; try { Boolean notifyNow = (getITelephony() != null); sRegistry.listen(pkgForDebug, listener.callback, events, notifyNow); } catch (RemoteException ex) { // system process dead } catch (NullPointerException ex) { // system process dead } }
这个函数会传进来一个PhoneStateListener对象,一般实际的对象类是继承了PhoneStateListener的,且里面重载了PhoneStateListener的一些成员函数。如:
PhoneStateListener mMSimPhoneStateListener = new PhoneStateListener() { //在定义的同时重载函数 @Override public void <u><span style="color:#cc0000;">onServiceStateChanged</span></u>(ServiceState serviceState) { int currentState = serviceState.getState(); if (currentState == ServiceState.STATE_POWER_OFF) { currentState = RADIO_OFF; } else { currentState = RADIO_ON; } Log.d(LOG_TAG, "PhoneStateListener : onServiceStateChanged-->currentState = " + currentState); if (mLastServiceState != currentState) { mLastServiceState = currentState; if (mAirplaneModeState != null) { ((AirplaneModeStateTracker)mAirplaneModeState).onActualStateChange(); } } } }; return mMSimPhoneStateListener;
底层发生了这个监听的事件时,调用这个对象的callback成员的处理函数来处理。
PhoneStateListener里的callback定义如下:
IPhoneStateListener callback = new IPhoneStateListener.Stub() { public void <u><span style="color:#cc0000;">onServiceStateChanged</span></u>(ServiceState serviceState) { Message.obtain(mHandler, LISTEN_SERVICE_STATE, 0, 0, serviceState).sendToTarget(); //这个消息会在下面讲到的mhandle里处理 } public void onSignalStrengthChanged(int asu) { Message.obtain(mHandler, LISTEN_SIGNAL_STRENGTH, asu, 0, null).sendToTarget(); } public void onMessageWaitingIndicatorChanged(boolean mwi) { Message.obtain(mHandler, LISTEN_MESSAGE_WAITING_INDICATOR, mwi ? 1 : 0, 0, null) .sendToTarget(); } public void onCallForwardingIndicatorChanged(boolean cfi) { Message.obtain(mHandler, LISTEN_CALL_FORWARDING_INDICATOR, cfi ? 1 : 0, 0, null) .sendToTarget(); }}
注意这里的mhandle是PhoneStateListener的另一个成员,定义如下:
Handler mHandler = new Handler() { public void handleMessage(Message msg) { //Log.d("TelephonyRegistry", "what=0x" + Integer.toHexString(msg.what) + " msg=" + msg); switch (msg.what) { case LISTEN_SERVICE_STATE: PhoneStateListener.this.<span style="color:#cc0000;"><u>onServiceStateChanged</u></span>((ServiceState)msg.obj); break; case LISTEN_SIGNAL_STRENGTH: PhoneStateListener.this.onSignalStrengthChanged(msg.arg1); break; case LISTEN_MESSAGE_WAITING_INDICATOR: PhoneStateListener.this.onMessageWaitingIndicatorChanged(msg.arg1 != 0); break;......}
所以处理还是在PhoneStateListener里。
当TelephonyRegistry要通知某一事件时,如下:
public void notifyCallState(int state, String incomingNumber) { synchronized (mRecords) { mCallState = state; mCallIncomingNumber = incomingNumber; for (Record r : mRecords) { if ((r.events & PhoneStateListener.LISTEN_CALL_STATE) != 0) { try { r.callback.onCallStateChanged(state, incomingNumber); //这里调用的就是new IPhoneStateListener.Stub() 定义时的重载函数 } catch (RemoteException ex) { mRemoveList.add(r.binder); } } } handleRemoveListLocked(); } broadcastCallStateChanged(state, incomingNumber);
GSMPhone通过PhoneNotifier的实现者DefaultPhoneNotifier将事件通知到 TelephonyRegistry。TelephonyRegistry再通过两种方式通知给用户,其一是广播事件,另外一种是通过服务用户在 TelephonyRegistry中注册的IphoneStateListener接口,实现回调(回调方式参见android的aidl机制)
GSMPhone的父类PhoneBase里面有一个
protected PhoneNotifier mNotifier; 成员
GSMPhone初始化的时候会传进来一个PhoneNotifier 的类对象,具体的初始化调用在PhoneFactory类的
makeDefaultPhone(Context context) 函数里:
sPhoneNotifier = new DefaultPhoneNotifier();
sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);... int phoneType = TelephonyManager.getPhoneType(networkMode); if (phoneType == PhoneConstants.PHONE_TYPE_GSM) { Log.i(LOG_TAG, "Creating GSMPhone"); sProxyPhone = new PhoneProxy(new GSMPhone(context, sCommandsInterface, sPhoneNotifier));
GSMPhone接收到一个需要通知给上层的事件时
/*package*/ void notifyPhoneStateChanged() {
mNotifier.notifyPhoneState(this);
}
DefaultPhoneNotifier里的notifyPhoneStateChanged函数如下
public void notifyPhoneState(Phone sender) { 。。。 mRegistry.notifyCallState(convertCallState(sender.getState()), incomingNumber); 。。。 }
mRegistry 是在创建DefaultPhoneNotifier对象时获得的,
protected DefaultPhoneNotifier() { mRegistry = ITelephonyRegistry.Stub.asInterface(ServiceManager.getService( "telephony.registry")); }
所以接下来会调用上面TelephonyRegistry服务类对应的notifyPhoneState函数。
GSMCallTracker
GSMCallTracker在构造时就将自己登记到了电话状态变化通知表中。RIL-Java一收到电话状态变化的通知,就会使用EVENT_CALL_STATE_CHANGE通知到GSMCallTacker
GSMPhone里有个GsmCallTracker的成员变量,在GSMPhone初始化的时候初始
mCT = new GsmCallTracker(this);
再看GsmCallTracker的构造函数
GsmCallTracker (GSMPhone phone) {
this.phone = phone;
cm = phone.mCM;
cm.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null); //当ril.java接到电话状态变化时,就会给GsmCallTracker抛出一个msg.what=EVENT_CALL_STATE_CHANGE 的消息
cm.registerForOn(this, EVENT_RADIO_AVAILABLE, null);
cm.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);
}
其中public CommandsInterface cm;
sCommandsInterface = new RIL(context, networkMode, cdmaSubscription);在PhoneFactory类的makeDefaultPhone函数里,很GSMPhone一起初始化,这里就是个RIL实例了。在GSMPhone和GsmCallTracker两个类里面都保存有这个实例,当然这是同一个实例。
public final class RIL extends BaseCommands implements CommandsInterface
public abstract class BaseCommands implements CommandsInterface {
public void registerForCallStateChanged(Handler h, int what, Object obj) {
Registrant r = new Registrant (h, what, obj);
mCallStateRegistrants.add(r);
}
protected RegistrantList mCallStateRegistrants = new RegistrantList();
}
发ril命令
GSMPhone.java里
mCM.getIMEI(obtainMessage(EVENT_GET_IMEI_DONE));
ril.java里
public void
getIMEI(Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMEI, result);
send(rr);
}
static RILRequest obtain(int request, Message result) {
RILRequest rr = null;
rr.mRequest = request;
rr.mResult = result;
}
所以rr.mRequest里面保存了一个发出这个请求的类的message,供回复时调用
在class RILReceiver里面
processSolicited{
RILRequest rr;
rr = findAndRemoveRequestFromList(serial);
...
case RIL_REQUEST_GET_IMEI: ret = responseString(p); break;
...
AsyncResult.forMessage(rr.mResult, ret, null);
rr.mResult.sendToTarget();
}
OEM定制的ril命令
public class QcrilMsgTunnelIfaceManager extends IQcrilMsgTunnel.Stub {
QcrilMsgTunnelService mService;
QcrilMsgTunnelSocket mQcrilMsgTunnelSocket //相当于ril.java
public int sendOemRilRequestRaw(byte[] request,byte[] response)
{
/*暴露给外面调用用来发送的接口函数,进来的请求和回复结构体都是Byte类型的数组*/
requestId已经保存在了request里面
}
//打包消息
public AsyncResult sendQcRilHookMsg(intrequestId, byte[] payload) {
byte[] request = new byte[mHeaderSize +payload.length];
ByteBufferreqBuffer = createBufferWithNativeByteOrder(request);
addQcRilHookHeader(reqBuffer, requestId, payload.length);
reqBuffer.put(payload);
returnsendRilOemHookMsg(requestId, request);
}
}
public classQcrilMsgTunnelService extends Service {
QcrilMsgTunnelIfaceManagermTunnelIface;
}
QcRilHook里的IQcrilMsgTunnelmService成员就是QcrilMsgTunnelIfaceManager。这个类里面的成员函数是暴露给用户使用的。
QcrilMsgTunnelSocket和ril.java是一样的,里面也同时有一个QcRilSender和QcRilReceiver分别用来处理发送和接受请求。QcRilSender在这个里面也有一个socket来连接rild name = qmux_radio/rild_oem0。只是有一点不同的是从这里发下去的ril命令对应的命令号
mRequest = RIL_REQUEST_OEM_HOOK_RAW。所以就不用再ril.cpp里为新加的每个ril命令添加dispatch函数(序列化)。
http://www.redwolf-blog.com/?p=1100
- qcril接口函数
- qcril接口函数
- qcril
- qcril
- Qcril
- Android Qcril
- QCRIL层qcril.c部分解析
- qcril voice call flow
- Android 学习之QCRIL QMI
- RILD及qcril初始化流程
- 函数接口
- 函数接口
- 函数接口
- 在 qcril 中打 log(内部bbs)
- android QMI机制---Qcril初始化流程
- android QMI机制---QCRIL消息发送
- UCOSIIIAPI函数接口OSTaskCreate();函数
- libpcap主要接口函数
- jquery UI datepicker 增加 时间的选择。
- Makefile 简明手册
- onCreate中获取view实际大小
- Servlet.service() for servlet jsp threw exception java.lang.NullPointerException
- JDK环境变量配置
- qcril接口函数
- 十年学会编程
- Oracle “CONNECT BY” 使用
- VI/VIM进行字符替换
- 网页加载速度优化的一些技巧
- mysql 实现行号的方法
- Android面试题整理
- BIT 1054 Largest prime factor
- 李嘉诚理财三秘诀