android 8.0 ril.java,Android 8.0 RIL源码分析(一)

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;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值