androoid framework学习之 - RILd启动过程和如何接收framwork层的消息流程(二)
2017-01-11 14:48
731 查看
response 分析---从moderm主动发消息给RIL-JAVA
上一篇分析了RIL启动和request的分析,今天来看下response:
1.还记得在reference_ril.c里面:
2.下面会调用Achannel.c里面的at_open函数:
调用readerloop函数:
readloop解决的问题是解析从moderm发过来的回应,如果遇到URC则通过handleUnsolicited上报给RIL.JAVA;
如果是命令的应答,则通过handleFinalResponse通知handleFinalResponse有应答结果
看到了吧,这个s_unsolHandler就是在at_open函数里面赋值的,它指向onUnsolicited函数,所以接下来就调用onUnsolicited函数:
这边会通过strStartsWith去判断是什么事件,然后再调用 RIL_onUnsolicitedResponse 将相应的事件发送给RIL-JAVA,
在ril.cpp里面:
3.下面讲一下 新事件或者 send事件response在RIL.C的体现:
在RIL.C里面:
以上代码是一只在循环跑的,当有Response时,receiver就会呗唤醒去读取response信息,并且用processResponse函数来处理RIL response的信息:
上面code很明显了,当时新事件如来电、短信时,会跑 processUnsolicited (p)函数,然后根据相应的事件
上一篇分析了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)函数,然后根据相应的事件
相关文章推荐
- androoid framework学习之 - RILd启动过程和如何接收framwork层的消息流程
- socket数据传输过程中如何准确的接收消息
- Framework启动流程(1) - init进程启动过程
- Android的启动过程分析(从进程和Framework的角度)-android学习之旅(98)
- Android Framework学习(五)之应用进程启动流程
- Framework学习(六)应用程序进程启动过程
- Android的启动过程分析(从进程和Framework的角度)-android学习之旅(98)
- Android的启动过程分析(从进程和Framework的角度)-android学习之旅(98)
- androoid framework学习之 - Telephony 来电流程
- Android Framework学习——Launcher启动应用程序过程源码分析
- Android的启动过程分析(从进程和Framework的角度)-android学习之旅(98)
- srs代码学习(7)--消息接收过程
- Framework学习(九)Broadcast的注册、发送和接收过程
- Framework学习(五)应用程序启动过程
- androoid framework学习之 - Telephony 流程
- Android的启动过程分析(从进程和Framework的角度)-android学习之旅(98)
- POX学习笔记:POX接收OpenFlow消息的处理流程分析
- Framework学习(八)Service的启动/绑定过程
- SpringMvc如何学习框架技术? 就像如上的图示一样,先掌握新技术的体系流程图。在快速弄明白程序执行流程后,在使用过程中 了解细节。