您的位置:首页 > 其它

androoid framework学习之 - RILd启动过程和如何接收framwork层的消息流程(二)

2017-01-11 14:48 731 查看
response 分析---从moderm主动发消息给RIL-JAVA

上一篇分析了RIL启动和request的分析,今天来看下response:

1.还记得在reference_ril.c里面:
const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)
{
......................
pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&s_tid_mainloop, &attr, mainLoop, NULL);//创建mainloop线程,用于从moderm主动到RIL-JAVA
..................................
}

static void *
mainLoop(void *param __unused)
{
...................
ret = at_open(fd, onUnsolicited);

...........................
}


2.下面会调用Achannel.c里面的at_open函数:
int at_open(int fd, ATUnsolHandler h)
{
int ret;
pthread_t tid;
pthread_attr_t attr;

s_fd = fd;
 s_unsolHandler = h;//将onUnsolicited赋给s_unsolHandler全局指针
s_readerClosed = 0;

s_responsePrefix = NULL;
s_smsPDU = NULL;
sp_response = NULL;

pthread_attr_init (&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

ret = pthread_create(&s_tid_reader, &attr, readerLoop, &attr);//创建线程用于读取moderm的消息

if (ret < 0) {
perror ("pthread_create");
return -1;
}

return 0;
}


调用readerloop函数:
static void *readerLoop(void *arg)
{
for (;;) {
const char * line;

line = readline();

if (line == NULL) {
break;
}

if(isSMSUnsolicited(line)) {
char *line1;
const char *line2;

// The scope of string returned by 'readline()' is valid only
// till next call to 'readline()' hence making a copy of line
// before calling readline again.
line1 = strdup(line);
line2 = readline();//读取消息

if (line2 == NULL) {
break;
}

if (s_unsolHandler != NULL) {
s_unsolHandler (line1, line2);
}
free(line1);
} else {
processLine(line);//处理消息
}
}

onReaderClosed();

return NULL;
}


readloop解决的问题是解析从moderm发过来的回应,如果遇到URC则通过handleUnsolicited上报给RIL.JAVA;
如果是命令的应答,则通过handleFinalResponse通知handleFinalResponse有应答结果
static void processLine(const char *line)
{
pthread_mutex_lock(&s_commandmutex);

if (sp_response == NULL) {
/* no command pending */
handleUnsolicited(line);
} else if (isFinalResponseSuccess(line)) {//判断是否是unsolicited消息
sp_response->success = 1;
handleFinalResponse(line);
} else if (isFinalResponseError(line)) {
sp_response->success = 0;
handleFinalResponse(line);
} else if (s_smsPDU != NULL && 0 == strcmp(line, "> ")) {
// See eg. TS 27.005 4.3
// Commands like AT+CMGS have a "> " prompt
writeCtrlZ(s_smsPDU);
s_smsPDU = NULL;
} else switch (s_type) {
case NO_RESULT:
handleUnsolicited(line);
break;
case NUMERIC:
if (sp_response->p_intermediates == NULL
&& isdigit(line[0])
) {
addIntermediate(line);
} else {
/* either we already have an intermediate response or
the line doesn't begin with a digit */
handleUnsolicited(line);//处理消息
}
break;
case SINGLELINE:
if (sp_response->p_intermediates == NULL
&& strStartsWith (line, s_responsePrefix)
) {
addIntermediate(line);
} else {
/* we already have an intermediate response */
handleUnsolicited(line);
}
break;
case MULTILINE:
if (strStartsWith (line, s_responsePrefix)) {
addIntermediate(line);
} else {
handleUnsolicited(line);
}
break;

default: /* this should never be reached */
RLOGE("Unsupported AT command type %d\n", s_type);
handleUnsolicited(line);
break;
}

pthread_mutex_unlock(&s_commandmutex);
}

static void handleUnsolicited(const char *line)
{
if (s_unsolHandler != NULL) {
s_unsolHandler(line, NULL);
}
}


看到了吧,这个s_unsolHandler就是在at_open函数里面赋值的,它指向onUnsolicited函数,所以接下来就调用onUnsolicited函数:
static void onUnsolicited (const char *s, const char *sms_pdu)
{
char *line = NULL, *p;
int err;

/* Ignore unsolicited responses until we're initialized.
* This is OK because the RIL library will poll for initial state
*/
if (sState == RADIO_STATE_UNAVAILABLE) {
return;
}

if (strStartsWith(s, "%CTZV:")) {
/* TI specific -- NITZ time */
char *response;

line = p = strdup(s);
at_tok_start(&p);

err = at_tok_nextstr(&p, &response);

free(line);
if (err != 0) {
RLOGE("invalid NITZ line %s\n", s);
} else {
RIL_onUnsolicitedResponse (
RIL_UNSOL_NITZ_TIME_RECEIVED,
response, strlen(response));
}
} else if (strStartsWith(s,"+CRING:")
|| strStartsWith(s,"RING")
|| strStartsWith(s,"NO CARRIER")
|| strStartsWith(s,"+CCWA")
) {
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED,
NULL, 0);
#ifdef WORKAROUND_FAKE_CGEV
RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL); //TODO use new function
#endif /* WORKAROUND_FAKE_CGEV */
} else if (strStartsWith(s,"+CREG:")
|| strStartsWith(s,"+CGREG:")
) {
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED,
NULL, 0);
#ifdef WORKAROUND_FAKE_CGEV
RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
#endif /* WORKAROUND_FAKE_CGEV */
} else if (strStartsWith(s, "+CMT:")) {
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_NEW_SMS,
sms_pdu, strlen(sms_pdu));
} else if (strStartsWith(s, "+CDS:")) {
RIL_onUnsolicitedResponse (
RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT,
sms_pdu, strlen(sms_pdu));
} else if (strStartsWith(s, "+CGEV:")) {
/* Really, we can ignore NW CLASS and ME CLASS events here,
* but right now we don't since extranous
* RIL_UNSOL_DATA_CALL_LIST_CHANGED calls are tolerated
*/
/* can't issue AT commands here -- call on main thread */
RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
#ifdef WORKAROUND_FAKE_CGEV
} else if (strStartsWith(s, "+CME ERROR: 150")) {
RIL_requestTimedCallback (onDataCallListChanged, NULL, NULL);
#endif /* WORKAROUND_FAKE_CGEV */
} else if (strStartsWith(s, "+CTEC: ")) {
int tech, mask;
switch (parse_technology_response(s, &tech, NULL))
{
case
4000
-1: // no argument could be parsed.
RLOGE("invalid CTEC line %s\n", s);
break;
case 1: // current mode correctly parsed
case 0: // preferred mode correctly parsed
mask = 1 << tech;
if (mask != MDM_GSM && mask != MDM_CDMA &&
mask != MDM_WCDMA && mask != MDM_LTE) {
RLOGE("Unknown technology %d\n", tech);
} else {
setRadioTechnology(sMdmInfo, tech);
}
break;
}
} else if (strStartsWith(s, "+CCSS: "))


这边会通过strStartsWith去判断是什么事件,然后再调用            RIL_onUnsolicitedResponse 将相应的事件发送给RIL-JAVA,

在ril.cpp里面:
void RIL_onUnsolicitedResponse(int unsolResponse, void *data,
{
........................
ret = sendResponse(p, soc_id);//将打包好的数据写入socket,发送给上层ril-Java
.................................

}
最后就是blockingWrite函数了,到这里就完成了response的流程了

3.下面讲一下  新事件或者 send事件response在RIL.C的体现:

在RIL.C里面:
class RILReceiver implements Runnable {
byte[] buffer;

RILReceiver() {
buffer = new byte[RIL_MAX_COMMAND_BYTES];
}

@Override
public void
run() {
int retryCount = 0;
String rilSocket = "rild";

//循环处理rild传递来的事件
try {for (;;) {
LocalSocket s = null;
LocalSocketAddress l;

if (mInstanceId == null || mInstanceId == 0 ) {
rilSocket = SOCKET_NAME_RIL[0];
} else {
rilSocket = SOCKET_NAME_RIL[mInstanceId];
}

try {
//创建于rild通信的socket 建立连接
s = new LocalSocket();
l = new LocalSocketAddress(rilSocket,
LocalSocketAddress.Namespace.RESERVED);
s.connect(l);
} catch (IOException ex){
try {
if (s != null) {
s.close();
}
} catch (IOException ex2) {
//ignore failure to close after failure to connect
}

// don't print an error message after the the first time
// or after the 8th time

if (retryCount == 8) {
Rlog.e (RILJ_LOG_TAG,
"Couldn't find '" + rilSocket
+ "' socket after " + retryCount
+ " times, continuing to retry silently");
} else if (retryCount >= 0 && retryCount < 8) {
Rlog.i (RILJ_LOG_TAG,
"Couldn't find '" + rilSocket
+ "' socket; retrying after timeout");
}

try {
Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);
} catch (InterruptedException er) {
}

retryCount++;
continue;
}

retryCount = 0;

mSocket = s;
Rlog.i(RILJ_LOG_TAG, "(" + mInstanceId + ") Connected to '"
+ rilSocket + "' socket");

int length = 0;
try {
//读取socket数据
InputStream is = mSocket.getInputStream();

for (;;) {
//解析数据
Parcel p;

length = readRilMessage(is, buffer);

if (length < 0) {
// End-of-stream reached
break;
}

p = Parcel.obtain();
p.unmarshall(buffer, 0, length);
p.setDataPosition(0);

//Rlog.v(RILJ_LOG_TAG, "Read packet: " + length + " bytes");

//处理rild传递来的消息
processResponse(p);
p.recycle();
}
} catch (java.io.IOException ex) {
Rlog.i(RILJ_LOG_TAG, "'" + rilSocket + "' socket closed",
ex);
} catch (Throwable tr) {
Rlog.e(RILJ_LOG_TAG, "Uncaught exception read length=" + length +
"Exception:" + tr.toString());
}

Rlog.i(RILJ_LOG_TAG, "(" + mInstanceId + ") Disconnected from '" + rilSocket
+ "' socket");

//无法读取数据,将CP状态设置为不可用
setRadioState (RadioState.RADIO_UNAVAILABLE);

try {
mSocket.close();
} catch (IOException ex) {
}

mSocket = null;
RILRequest.resetSerial();

// Clear request list on close
clearRequestList(RADIO_NOT_AVAILABLE, false);
}} catch (Throwable tr) {
Rlog.e(RILJ_LOG_TAG,"Uncaught exception", tr);
}

/* We're disconnected so we don't know the ril version */
notifyRegistrantsRilConnectionChanged(-1);
}
}


以上代码是一只在循环跑的,当有Response时,receiver就会呗唤醒去读取response信息,并且用processResponse函数来处理RIL response的信息:
    private void
    processResponse (Parcel p) {
        int type;

        type = p.readInt();

//新事件Or send事件response
        if (type == RESPONSE_UNSOLICITED) {
            processUnsolicited (p);//新事件
        } else if (type == RESPONSE_SOLICITED) {
            RILRequest rr = processSolicited (p);//send事件的response
            if (rr != null) {
                rr.release();
                decrementWakeLock();
            }
        }
    }


上面code很明显了,当时新事件如来电、短信时,会跑 processUnsolicited (p)函数,然后根据相应的事件
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: