您的位置:首页 > 移动开发 > Android开发

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方法

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调用

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  RIL Android 8.0