1.去电流程三中跟踪到最后的时候可以看到其调用了RIL的dail方法
这里继续以此分析其从RIL到Modem的流程
@Override
public void dial(String address, int clirMode, UUSInfo uusInfo, Message result) {
//获取radio对象
IRadio radioProxy = getRadioProxy(result);
if (radioProxy != null) {
//构建RIL请求消息
RILRequest rr = obtainRequest(RIL_REQUEST_DIAL, result,
mRILDefaultWorkSource);
Dial dialInfo = new Dial();
dialInfo.address = convertNullToEmptyString(address);
dialInfo.clir = clirMode;
if (uusInfo != null) {
UusInfo info = new UusInfo();
info.uusType = uusInfo.getType();
info.uusDcs = uusInfo.getDcs();
info.uusData = new String(uusInfo.getUserData());
dialInfo.uusInfo.add(info);
}
if (RILJ_LOGD) {
// Do not log function arg for privacy
riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
}
try {
//调用dial方法
radioProxy.dial(rr.mSerial, dialInfo);
} catch (RemoteException | RuntimeException e) {
handleRadioProxyExceptionForRR(rr, "dial", e);
}
}
}
1.1使用单例模式通过获取Radio对象,可以看到其获取的是HIDL的对象,并且设置的回复方法mRadioResponse,可以参见RIL架构分析。
protected IRadio getRadioProxy(Message result) {
...
try {
//获取HIDL的服务并设置setResponseFunctions
mRadioProxy = IRadio.getService(HIDL_SERVICE_NAME[mPhoneId == null ? 0 : mPhoneId]);
if (mRadioProxy != null) {
mRadioProxy.linkToDeath(mRadioProxyDeathRecipient,
mRadioProxyCookie.incrementAndGet());
//设置mRadioResponse和mRadioIndication
mRadioProxy.setResponseFunctions(mRadioResponse, mRadioIndication);
} else {
riljLoge("getRadioProxy: mRadioProxy == null");
}
} catch (RemoteException | RuntimeException e) {
mRadioProxy = null;
riljLoge("RadioProxy getService/setResponseFunctions: " + e);
}
...
}
可以看到其通过HIDL方式获取到Radio对象后,进一步调用此对象的dial方法
继续查找远端的Radio类
发现RadioImpl继承了IRadio
struct RadioImpl : public V1_1::IRadio
2.在 ril_service 中实现了dial方法,继续跟进此方法
Return RadioImpl::dial(int32_t serial, const Dial& dialInfo) {
#if VDBG
RLOGD("dial: serial %d", serial);
#endif
//构建请求对象,Event侧和reference测协定的统一格式,当从event测发送到reference测时需要标准化为此对象
RequestInfo *pRI = android::addRequestToList(serial, mSlotId, RIL_REQUEST_DIAL);
if (pRI == NULL) {
return Void();
}
RIL_Dial dial = {};
RIL_UUS_Info uusInfo = {};
int32_t sizeOfDial = sizeof(dial);
if (!copyHidlStringToRil(&dial.address, dialInfo.address, pRI)) {
return Void();
}
dial.clir = (int) dialInfo.clir;
if (dialInfo.uusInfo.size() != 0) {
uusInfo.uusType = (RIL_UUS_Type) dialInfo.uusInfo[0].uusType;
uusInfo.uusDcs = (RIL_UUS_DCS) dialInfo.uusInfo[0].uusDcs;
if (dialInfo.uusInfo[0].uusData.size() == 0) {
uusInfo.uusData = NULL;
uusInfo.uusLength = 0;
} else {
if (!copyHidlStringToRil(&uusInfo.uusData, dialInfo.uusInfo[0].uusData, pRI)) {
memsetAndFreeStrings(1, dial.address);
return Void();
}
uusInfo.uusLength = dialInfo.uusInfo[0].uusData.size();
}
dial.uusInfo = &uusInfo;
}
//
CALL_ONREQUEST(RIL_REQUEST_DIAL, &dial, sizeOfDial, pRI, mSlotId);
memsetAndFreeStrings(2, dial.address, uusInfo.uusData);
return Void();
}
疑问点:为何没有进入EventLoop循环????
在Android7.0上是通过Select获取Socke发送过来的消息,然后通过EventLoop进行处理,最后调用到processCommandsCallback之后进行处理。和同事沟通后HIDL发送消息也会被Select获取到,之后一路调用到ev->func(ev->fd, 0, ev->param); ,但在8.0上没有processCommandsCallback处理,这里笔者也未追溯到其如何进一步处理,后续会进一步进行分析。但从现有源码来看其是调用到了RadioImpl的dial方法进行处理。
3.继续跟踪CALL_ONREQUEST
搜索CALL_ONREQUEST,可以看到其实际调用的是s_vendorFunctions->onRequest
#define CALL_ONREQUEST(a, b, c, d, e) s_vendorFunctions->onRequest((a), (b), (c), (d))
在registerService方法中看到s_vendorFunctions其实是传进来的callbacks实例,即RIL_RadioFunctions对象,这里具体分析可以见Android 8.0RIL框架分析。
在ril.c中继续跟踪OnRequest方法,回到之前rild.c的main中,我们看到其先调用rilInit进行初始化,之后返回了funcs,在传如RIL_register进行注册
跟进到reference-ril.c的 onRequest 方法
/**
* Call from RIL to us to make a RIL_REQUEST
*
* Must be completed with a call to RIL_onRequestComplete()
*
* RIL_onRequestComplete() may be called from any thread, before or after
* this function returns.
*
* Because onRequest function could be called from multiple different thread,
* we must ensure that the underlying at_send_command_* function
* is atomic.
*/
static void
onRequest (int request, void *data, size_t datalen, RIL_Token t)
{
ATResponse *p_response;
int err;
RLOGD("onRequest: %s", requestToString(request));
/* Ignore all requests except RIL_REQUEST_GET_SIM_STATUS
* when RADIO_STATE_UNAVAILABLE.
*/
if (sState == RADIO_STATE_UNAVAILABLE
&& request != RIL_REQUEST_GET_SIM_STATUS
) {
RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
return;
}
/* Ignore all non-power requests when RADIO_STATE_OFF
* (except RIL_REQUEST_GET_SIM_STATUS)
*/
if (sState == RADIO_STATE_OFF
&& !(request == RIL_REQUEST_RADIO_POWER
|| request == RIL_REQUEST_GET_SIM_STATUS)
) {
RIL_onRequestComplete(t, RIL_E_RADIO_NOT_AVAILABLE, NULL, 0);
return;
}
//可以看到只有两种情况是单独处理的,其他的在switch中处理
switch (request) {
...
case RIL_REQUEST_DIAL:
requestDial(data, datalen, t);
break;
...
}
}
4.继续跟进requestDial方法
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);
//发送AT命令
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.继续跟踪at_send_command
int at_send_command (const char *command, ATResponse **pp_outResponse)
{
int err;
err = at_send_command_full (command, NO_RESULT, NULL,
NULL, 0, pp_outResponse);
return err;
}
6.继续跟进at_send_command_full
/**
* Internal send_command implementation
*
* timeoutMsec == 0 means infinite timeout
*/
static int at_send_command_full (const char *command, ATCommandType type,
const char *responsePrefix, const char *smspdu,
long long timeoutMsec, ATResponse **pp_outResponse)
{
int err;
bool inEmulator;
if (0 != pthread_equal(s_tid_reader, pthread_self())) {
/* cannot be called from reader thread */
return AT_ERROR_INVALID_THREAD;
}
inEmulator = isInEmulator();
if (inEmulator) {
pthread_mutex_lock(&s_writeMutex);
}
pthread_mutex_lock(&s_commandmutex);
//继续发送
err = at_send_command_full_nolock(command, type,
responsePrefix, smspdu,
timeoutMsec, pp_outResponse);
pthread_mutex_unlock(&s_commandmutex);
if (inEmulator) {
pthread_mutex_unlock(&s_writeMutex);
}
if (err == AT_ERROR_TIMEOUT && s_onTimeout != NULL) {
s_onTimeout();
}
return err;
}
7.继续跟进at_send_command_full_nolock
/**
* Internal send_command implementation
* Doesn't lock or call the timeout callback
*
* timeoutMsec == 0 means infinite timeout
*/
static int at_send_command_full_nolock (const char *command, ATCommandType type,
const char *responsePrefix, const char *smspdu,
long long timeoutMsec, ATResponse **pp_outResponse)
{
int err = 0;
struct timespec ts;
if(sp_response != NULL) {
err = AT_ERROR_COMMAND_PENDING;
goto error;
}
//给modem发送AT消息
err = writeline (command);
if (err < 0) {
goto error;
}
s_type = type;
s_responsePrefix = responsePrefix;
s_smsPDU = smspdu;
//创建sp_respose作为回应
sp_response = at_response_new();
if (timeoutMsec != 0) {
setTimespecRelative(&ts, timeoutMsec);
}
//发送完后阻塞线程
while (sp_response->finalResponse == NULL && s_readerClosed == 0) {
if (timeoutMsec != 0) {
//进入阻塞状态,待另一个线程满足s_commandcond后解除
err = pthread_cond_timedwait(&s_commandcond, &s_commandmutex, &ts);
} else {
err = pthread_cond_wait(&s_commandcond, &s_commandmutex);
}
//超时结束
if (err == ETIMEDOUT) {
err = AT_ERROR_TIMEOUT;
goto error;
}
}
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;
}
sp_response = NULL;
if(s_readerClosed > 0) {
err = AT_ERROR_CHANNEL_CLOSED;
goto error;
}
err = 0;
error:
clearPendingCommand();
return err;
}
可以看到这里做了两个重要的操作:
1.通过writeLine发送数据给modem
2.阻塞当前线程等待modem回应
8.这样数据就发送到了modem了
/**
* Sends string s to the radio with a \r appended.
* Returns AT_ERROR_* on error, 0 on success
*
* This function exists because as of writing, android libc does not
* have buffered stdio.
*/
static int writeline (const char *s)
{
size_t cur = 0;
size_t len = strlen(s);
ssize_t written;
if (s_fd < 0 || s_readerClosed > 0) {
return AT_ERROR_CHANNEL_CLOSED;
}
//AT命令的打印
RLOGD("AT> %s\n", s);
AT_DUMP( ">> ", s, strlen(s) );
/* the main string */
while (cur < len) {
do {
s_fd是modem和rilc的串口
written = write (s_fd, s + cur, len - cur);
} while (written < 0 && errno == EINTR);
if (written < 0) {
return AT_ERROR_GENERIC;
}
cur += written;
}
/* the \r */
//以r结尾
do {
written = write (s_fd, "\r" , 1);
} while ((written < 0 && errno == EINTR) || (written == 0));
if (written < 0) {
return AT_ERROR_GENERIC;
}
return 0;
}
本文参考了以下博客
http://blog.csdn.net/u010961631/article/details/9446377