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, &param ) == 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

原创粉丝点击