Android 8.0 RIL源码分析(二)
2018-02-28 16:39
381 查看
非URC消息处理
之前分析到在at_send_command_full_nolock调用后会先发送消息给modem,然后阻塞当前线程等待modem返回消息。
因此也是在readerLoop的消息处理中去唤醒阻塞的线程,而且应该把数据直接返回给阻塞的线程,如之前ndroid 8.0 RIL框架分析,非URC消息会调用processLine方法。
1.这里跟进到processLine方法
2.继续跟进handleFinalResponse
3.回到at_send_command_full_nolock
4.回到最开始的 requestDial,在获取到返回数据后会调用RIL_onRequestComplete
5.这就回到ril.c的onRequestComplete中
5.跟进到RadioResponse
6.继续跟进responseVoid
7.将消息发送回请求的地方
URC消息处理
1.之前分析过如果是底层主动上报的URC消息则是使用handleUnsolicited进行处理
可以看到s_unsolHandler是个静态变量
查找s_unsolHandler的初始化
可以看到是在at_open的时候传入的handler,继续往上追溯mainLoop
2.可以看到其实调用的是reference-ril.c中的onUnsolicited方法
可以看到其最后调用RIL_onUnsolicitedResponse进行处理
3.继续跟进RIL_onUnsolicitedResponse
查看UnsolResponseInfo结构
查找UnsolResponseInfo 的初始化
可以看到这个头文件的定义和N上已经发生了改变
4.跟进对应的callStateChangedInd响应方法
5.可以看到其又通过HIDL调用到RILJ处的方法
frameworks\opt\telephony\src\java\com\android\internal\telephony\RadioIndication.java
RILJ到RILC的HIDL调用
之前分析到在at_send_command_full_nolock调用后会先发送消息给modem,然后阻塞当前线程等待modem返回消息。
因此也是在readerLoop的消息处理中去唤醒阻塞的线程,而且应该把数据直接返回给阻塞的线程,如之前ndroid 8.0 RIL框架分析,非URC消息会调用processLine方法。
1.这里跟进到processLine方法
static void processLine(const char *line) { pthread_mutex_lock(&s_commandmutex); if (sp_response == NULL) { /* no command pending */ handleUnsolicited(line); } else if (isFinalResponseSuccess(line)) { sp_response->success = 1; //将消息发回给eventLoop 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); }
2.继续跟进handleFinalResponse
/** assumes s_commandmutex is held */ static void handleFinalResponse(const char *line) { //把回应消息返回给RIL sp_response->finalResponse = strdup(line); //唤醒阻塞线程 pthread_cond_signal(&s_commandcond); }
3.回到at_send_command_full_nolock
if (pp_outResponse == NULL) { at_response_free(sp_response); } else { /* line reader stores intermediate responses in reverse order */ reverseIntermediates(sp_response); //返回的数据 *pp_outResponse = sp_response; }
4.回到最开始的 requestDial,在获取到返回数据后会调用RIL_onRequestComplete
static void requestDial(void *data, size_t datalen __unused, RIL_Token t) { RIL_Dial *p_dial; char *cmd; const char *clir; int ret; p_dial = (RIL_Dial *)data; switch (p_dial->clir) { case 1: clir = "I"; break; /*invocation*/ case 2: clir = "i"; break; /*suppression*/ default: case 0: clir = ""; break; /*subscription default*/ } asprintf(&cmd, "ATD%s%s;", p_dial->address, clir); ret = at_send_command(cmd, NULL); free(cmd); /* success or failure is ignored by the upper layer here. it will call GET_CURRENT_CALLS and determine success that way */ RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0); }
5.这就回到ril.c的onRequestComplete中
extern "C" void RIL_onRequestComplete(RIL_Token t, RIL_Errno e, void *response, size_t responselen) { RequestInfo *pRI; int ret; RIL_SOCKET_ID socket_id = RIL_SOCKET_1; pRI = (RequestInfo *)t; if (!checkAndDequeueRequestInfoIfAck(pRI, false)) { RLOGE ("RIL_onRequestComplete: invalid RIL_Token"); return; } socket_id = pRI->socket_id; #if VDBG RLOGD("RequestComplete, %s", rilSocketIdToString(socket_id)); #endif if (pRI->local > 0) { // Locally issued command...void only! // response does not go back up the command socket RLOGD("C[locl]< %s", requestToString(pRI->pCI->requestNumber)); free(pRI); return; } appendPrintBuf("[%04d]< %s", pRI->token, requestToString(pRI->pCI->requestNumber)); if (pRI->cancelled == 0) { int responseType; if (s_callbacks.version >= 13 && pRI->wasAckSent == 1) { // If ack was already sent, then this call is an asynchronous response. So we need to // send id indicating that we expect an ack from RIL.java as we acquire wakelock here. responseType = RESPONSE_SOLICITED_ACK_EXP; grabPartialWakeLock(); } else { responseType = RESPONSE_SOLICITED; } // there is a response payload, no matter success or not. #if VDBG RLOGE ("Calling responseFunction() for token %d", pRI->token); #endif pthread_rwlock_t *radioServiceRwlockPtr = radio::getRadioServiceRwlock((int) socket_id); int rwlockRet = pthread_rwlock_rdlock(radioServiceRwlockPtr); assert(rwlockRet == 0); //调用返回的响应方法 ret = pRI->pCI->responseFunction((int) socket_id, responseType, pRI->token, e, response, responselen); rwlockRet = pthread_rwlock_unlock(radioServiceRwlockPtr); assert(rwlockRet == 0); } free(pRI); }
5.跟进到RadioResponse
public class RadioResponse extends IRadioResponse.Stub { /** * @param responseInfo Response info struct containing response type, serial no. and error */ public void dialResponse(RadioResponseInfo responseInfo) { responseVoid(responseInfo); }
6.继续跟进responseVoid
public void responseVoid(RadioResponseInfo responseInfo) { //创建rilRequest反馈对象 RILRequest rr = mRil.processResponse(responseInfo); if (rr != null) { Object ret = null; if (responseInfo.error == RadioError.NONE) { //modem处理成功 sendMessageResponse(rr.mResult, ret); } mRil.processResponseDone(rr, responseInfo, ret); } }
7.将消息发送回请求的地方
public static void sendMessageResponse(Message msg, Object ret) { if (msg != null) { AsyncResult.forMessage(msg, ret, null); msg.sendToTarget(); } }
URC消息处理
1.之前分析过如果是底层主动上报的URC消息则是使用handleUnsolicited进行处理
static void handleUnsolicited(const char *line) { if (s_unsolHandler != NULL) { s_unsolHandler(line, NULL); } }
可以看到s_unsolHandler是个静态变量
static ATUnsolHandler s_unsolHandler;
查找s_unsolHandler的初始化
int at_open(int fd, ATUnsolHandler h) { ... s_unsolHandler = h; ... }
可以看到是在at_open的时候传入的handler,继续往上追溯mainLoop
static void * mainLoop(void *param __unused) { ... ret = at_open(fd, onUnsolicited); ... }
2.可以看到其实调用的是reference-ril.c中的onUnsolicited方法
/** * Called by atchannel when an unsolicited line appears * This is called on atchannel's reader thread. AT commands may * not be issued here */ static void onUnsolicited (const char *s, const char *sms_pdu) { ... if (strStartsWith(s, "%CTZV:")) { /* TI specific -- NITZ time */ char *response; line = p = strdup(s); at_tok_start(&p); err = at_tok_nextstr(&p, &response); if (err != 0) { RLOGE("invalid NITZ line %s\n", s); } else { RIL_onUnsolicitedResponse ( RIL_UNSOL_NITZ_TIME_RECEIVED, response, strlen(response)); } free(line); } ...省略多个else if }
可以看到其最后调用RIL_onUnsolicitedResponse进行处理
#define RIL_onRequestComplete(t, e, response, responselen) s_rilenv->OnRequestComplete(t,e, response, responselen) #define RIL_onUnsolicitedResponse(a,b,c) s_rilenv->OnUnsolicitedResponse(a,b,c)
3.继续跟进RIL_onUnsolicitedResponse
extern "C" void RIL_onUnsolicitedResponse(int unsolResponse, const void *data, size_t datalen) { ... ret = s_unsolResponses[unsolResponseIndex].responseFunction( (int) soc_id, responseType, 0, RIL_E_SUCCESS, const_cast<void*>(data), datalen); ... }
查看UnsolResponseInfo结构
typedef struct { int requestNumber; int (*responseFunction) (int slotId, int responseType, int token, RIL_Errno e, void *response, size_t responselen); WakeType wakeType; } UnsolResponseInfo;
查找UnsolResponseInfo 的初始化
static UnsolResponseInfo s_unsolResponses[] = { #include "ril_unsol_commands.h" };
可以看到这个头文件的定义和N上已经发生了改变
{RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, radio::callStateChangedInd, WAKE_PARTIAL},
4.跟进对应的callStateChangedInd响应方法
ril-service.cp int radio::callStateChangedInd(int slotId, int indicationType, int token, RIL_Errno e, void *response, size_t responseLen) { if (radioService[slotId] != NULL && radioService[slotId]->mRadioIndication != NULL) { #if VDBG RLOGD("callStateChangedInd"); #endif Return<void> retStatus = radioService[slotId]->mRadioIndication->callStateChanged( convertIntToRadioIndicationType(indicationType)); radioService[slotId]->checkReturnStatus(retStatus); } else { RLOGE("callStateChangedInd: radioService[%d]->mRadioIndication == NULL", slotId); } return 0; }
5.可以看到其又通过HIDL调用到RILJ处的方法
frameworks\opt\telephony\src\java\com\android\internal\telephony\RadioIndication.java
public void callStateChanged(int indicationType) { mRil.processIndication(indicationType); if (RIL.RILJ_LOGD) mRil.unsljLog(RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED); //继续通知消息 mRil.mCallStateRegistrants.notifyRegistrants(); }
RILJ到RILC的HIDL调用
相关文章推荐
- Android 8.0 RIL源码分析(一)
- Android 8.0系统源码分析--Binder进程间通信(三)
- Android RIL源码分析(2)
- Android 8.0系统源码分析--相机createCaptureSession创建过程源码分析
- < Android 源码分析(0)> Android 8.0 源码下载编译
- Android RIL源码分析(3)
- Android BroadcastReceiver的工作流程源码分析(8.0)
- Android RIL源码分析
- Android 8.0系统源码分析--Message发送、处理过程源码分析
- Android Service的绑定流程源码分析(8.0)
- Android 8.0系统源码分析--Looper、MessageQueue创建过程分析
- Android 8.0系统源码分析--Activity的窗口Window对象添加过程源码分析
- Android 8.0系统源码分析--开篇
- Android 8.0系统源码分析--openCamera启动过程源码分析
- Android源码分析:RIL代码分析
- Android——RIL 机制源码分析
- Android 8.0系统源码分析--应用进程启动过程分析
- Android Service的启动流程源码分析(8.0)
- Android 8.0系统源码分析--Binder进程间通信(二)
- Android 8.0系统源码分析--Binder进程间通信(一)