非URC消息处理
之前分析到在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(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调用