您的位置:首页 > 编程语言

<四>--RIL层代码分析--整个电话来访过程

2012-09-28 19:58 579 查看

最近公司开发一个几百万的项目,要求重写系统RIL层,看了几个招聘信息,只要你会RIL层开发的,工资上w每个月不是梦,这是几天研究的成果,希望对大家有所帮助,兄弟们加油吧!

先来一个总的流程图:



拨出电话流程:

1 在系统源码这个路径下/packages/apps/Phone/src/com/android/phone/DialtactsActivity.java

contacts的androidmanifest.xmlandroid:process="android.process.acore"说明此应用程序运行在acore进程中。DialtactsActivity的intent-filter的action属性设置为main,catelog属性设置为launcher,所以此activity能出现, 首先启动的就是这个activity在主菜单中,并且是点击此应用程序的第一个界面。dialtactsactivity包含四个tab,分别由TwelveKeyDialer、RecentCallsListActivity,两个activity-aliasDialtactsContactsEntryActivity和DialtactsFavoritesEntryActivity分别表示联系人和收藏tab,但是正真的联系人列表和收藏是由ContactsListActivity负责。

2

进入TwelveKeyDialer OnClick方法,按住的按钮id为:R.id.digits,执行

placecall()

Intent intent = newIntent(Intent.ACTION_CALL_PRIVILEGED,

Uri.fromParts("tel", number, null));

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

startActivity(intent);

3、

intert.ACTION_CALL_PRIVILEGED实际字符串为android.intent.action.CALL_PRIVILEGED,通过查找知道了packegs/phone下面的androidmanifest.xml中PrivilegedOutgoingCallBroadcasteractivity-alias设置了intent-filter,所以需要找到其targetactivity为OutgoingCallBroadcaster。所以进入OutgoingCallBroadcaster的

onCreate()

//如果为紧急号码马上启动intent.setClass(this,InCallScreen.class); startActivity(intent);

Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);

if (number != null) broadcastIntent.putExtra(Intent.EXTRA_PHONE_NUMBER,number);

broadcastIntent.putExtra(EXTRA_ALREADY_CALLED, callNow);

broadcastIntent.putExtra(EXTRA_ORIGINAL_URI,intent.getData().toString());

if (LOGV) Log.v(TAG, "Broadcasting intent " + broadcastIntent+ ".");

sendOrderedBroadcast(broadcastIntent, PERMISSION, null, null,

Activity.RESULT_OK, number, null);

4、Intent.ACTION_NEW_OUTGOING_CALL实际字符串为android.intent.action.NEW_OUTGOING_CALL,通过查找知道了packegs/phone

下面的androidmanifest.xml中OutgoingCallReceiver Receiver接收此intent消息。找到OutgoingCallReceiver,执行

onReceive()函数

Intent newIntent = new Intent(Intent.ACTION_CALL, uri);

newIntent.putExtra(Intent.EXTRA_PHONE_NUMBER, number);

newIntent.setClass(context, InCallScreen.class);

newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

5、请求拨号的java部分流程

onCreate(第一次)/onNewIntent(非第一次)

internalResolveIntent

placeCall(intent);

PhoneUtils.placeCall(mPhone, number, intent.getData());

phone.dial(number);

mCT.dial(newDialString);

dial(dialString, CommandsInterface.CLIR_DEFAULT);

cm.dial(pendingMO.address,clirMode,obtainCompleteMessage());//obtainCompleteMessage(EVENT_OPERATION_COMPLETE);

send(rr);

msg =mSender.obtainMessage(EVENT_SEND, rr);

acquireWakeLock();

msg.sendToTarget();

RILSender.handleMessage()

case EVENT_SEND:

...

s.getOutputStream().write(dataLength);

s.getOutputStream().write(data);//从这里流程跑到下面ril.cpp中监听部份

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

上面步骤:为APP就是java层传下的信息(就是执行的动作:按键打电话),已经做完,下面讲RIL层如何来接受上层来的信息

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

第一、《创建轮询机制》

6.请求拨号的c/c++部分流程

/*初始化事件循环,启动串口监听,注册socket监听*/

6.1在til/rild/rild.c为入口函数

RIL_startEventLoop()



6.2在libril/ril.cpp

第一、建立事件循环线程

[b]ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);[/b]

RIL_startEventLoop(void){

..........

ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);//创建线程,为入口函数,去实现它的功能



}

--------------------------------------------------------------------

eventLoop入口函数->跳到/ril/libril/ril.cpp 实现

----------------------------------------------------------------------

eventLoop(void *param)

{

ril_event_init();/*初始化*/

void ril_event_init()

{

MUTEX_INIT();

LOGD("-2.2-Ril_evnet.cpp-ril_event_init-shi-xian-han-shu-");

FD_ZERO(&readFds);

init_list(&timer_list);

init_list(&pending_list);

memset(watch_table, 0, sizeof(watch_table));

}

ret = pipe(filedes);

s_fdWakeupRead = filedes[0];/
* 消息循环中侦听*/

s_fdWakeupWrite = filedes[1];/* 用于通知消息循环定义消息已发送*/

第二、注册进程唤醒事件回调

ril_event_set(&s_wakeupfd_event, s_fdWakeupRead, true, processWakeupCallback, NULL);/*注册进程唤醒事件回调*/

static void processWakeupCallback(int fd, short flags, void *param) {

char buff[16];

int ret;

LOGD("--2.5-ril_event_set--processWakeupCallback- read(s_fdWakeupRead, &buff, sizeof(buff));---");

LOGV("processWakeupCallback");

/* empty our wakeup socket out */

do {

ret = read(s_fdWakeupRead, &buff, sizeof(buff));

} while (ret > 0 || (ret < 0 && errno == EINTR));

}

rilEventAddWakeup (&s_wakeupfd_event);

->static void rilEventAddWakeup(struct ril_event *ev)

{

ril_event_add(ev);

triggerEvLoop();

}

// Add event to watch list

void ril_event_add(struct ril_event * ev)

{

LOGD("---RIL_evnent.cpp--shi--xian--void ril_event_add(struct ril_event * ev)----");

dlog("~~~~ +ril_event_add ~~~~");

MUTEX_ACQUIRE();

for (int i = 0; i < MAX_FD_EVLL) {

//1:

watch_table[i] = ev;//把上面ril_event_add函数添加的事件_wakeupfd_event结构体添加到这个数组来

ev->index = i;

dlog("~~~~ added at %d ~~~~", i);

dump_event(ev);

//2:

FD_SET(ev->fd, &readFds);

if (ev->fd >= nfds) nfds = ev->fd+1;

dlog("~~~~ nfds = %d ~~~~", nfds);

break;ENTS; i++) {

if (watch_table[i] == NU

}

}

MUTEX_RELEASE();

dlog("~~~~ -ril_event_add ~~~~");

}

static void triggerEvLoop(){

int ret;

LOGD("--- ret = write (s_fdWakeupWrite, " ", 1);---");

if (!pthread_equal(pthread_self(), s_tid_dispatch)) {

/* trigger event loop to wakeup. No reason to do this,

* if we're in the event loop thread */

do {

ret = write (s_fdWakeupWrite, " ", 1);

} while (ret < 0 && errno == EINTR);

}

}

第三、建立事件循环

ril_event_loop();/
*建立事件循环*/

}

4.

当调用ril_event_loop()时,就去跳到->reference-ril/reference-ril.c去实现

/* 我们知道对于Linux 设备来讲,我们可以使用select 函数等待在FDS 上,只要FDS 中记录的设备有数据到来,

select 就会设置相应的标志位并返回。readFDS 记录了所有的事件相关设备句柄。readFDS 中句柄是在在AddEvent

加入的。所有的事件侦听都是建立在linux 的select readFDS 基础上。

ril_event_loop 利用select 等待在readFDS (fd_set)上,当select 设备有数据时,ril_event_loop 会从select 返回,

在watch_list 中相应的Event 放置到pend_list,如果Event 是持久性的则不从watch_list 中删除。然后ril_event_loop

遍历pengding_list 处理Event 事件,发起事件回调函数。

*/

void ril_event_loop()

{

int n;

fd_set rfds;

struct timeval tv;

struct timeval * ptv


for (;;) {



...}
n =select(nfds, &rfds,NULL, NULL, ptv);//等待唤醒fd

// Check for timeouts

processTimeouts();// 处理定时消息 ,处理ril_event_init ->pending_list

// Check for read-ready
processReadReadies(&rfds, n);// 处理侦听消息 ,处理ril_event_init ->watch_list

// Fire away

firePending(); // 处理挂起消息



}

######################################################################################################################

多路复用I/O机制的运转

上文说到request是接收,是通过ril_event_loop中的多路复用I/O,也对初始化做了分析.现在我们来仔细看看这个机制如何运转.

ril_event_set负责配置一个event,主要有两种event:

ril_event_add添加使用多路I/O的event,它负责将其挂到队列,同时将event的通道句柄fd加入到watch_table,然后通过select等待.

ril_timer_add添加timer event,它将其挂在队列,同时重新计算最短超时时间.

无论哪种add,最后都会调用triggerEvLoop来刷新队列,更新超时值或等待对象.

刷新之后, ril_event_loop从阻塞的位置,select返回,只有两种可能,一是超时,二是等待到了某I/O操作.

超时的处理在processTimeouts中,摘下超时的event,加入pending_list.

检查有I/O操作的通道的处理在processReadReadies中,将超时的event加入pending_list.

最后在firePending中,检索pending_list的event并依次执行event->func.

这些操作完之后,计算新超时时间,并重新select阻塞于多路I/O.

前面的初始化流程已分析得知,初始化完成以后,队列上挂了3个event对象,分别是:

s_listen_event: 名为rild的socket,主要requeset & response通道

s_debug_event: 名为rild-debug的socket,调试用requeset & response通道(流程与s_listen_event基本相同,后面仅分析s_listen_event)

s_wakeupfd_event: 无名管道,用于队列主动唤醒(前面提到的队列刷新,就用它来实现,请参考使用它的相关地方)
######################################################################################################################

一上电,就开始执行上面程序,不断的轮询是否有事件(主要是通过pipe作用,再通select机制来处理三态信息:监听,超时,挂起)

当有事件来了,就执行下面函数,对它初始化,和线程mainloop->readloop读取信息和->readline()响应,而

RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);中的initializeCallback发送AT>
ATE0Q0V1命令


######################################################################################################################

第二、读取并判断modem发的信息(URC,还是响应)
6.3reference-ril/reference-ril.c->RIL_init()

/*初始化Vendor RIL 并进行注册*/

1.入口:funcs =rilInit(&s_rilEnv, argc, rilArgv);//实际是通过动态加载动态库的方式执行reference-ril.c中的RIL_Init

const RIL_RadioFunctions *RIL_Init(const struct RIL_Env *env, int argc, char **argv)

{

while ( -1 != (opt = getopt(argc, argv, "p:d:s:"))) {

switch (opt) {

//获取dev/ttyUSB,只是打开而已,是否获取,由线程mainLoop执行完才知道

case 'd':

s_device_path = optarg;

LOGI("Opening tty device %s\n", s_device_path);

break;


case 's':

s_device_path = optarg;

s_device_socket = 1;

LOGI("Opening socket %s\n", s


_device_path);

break;


return NULL;

}

第四、单独启动一个线程读取串口数据

ret = pthread_create(&s_tid_mainloop, &attr,mainLoop, NULL);//
创建一个线程mainLoop

return &s_callbacks;//返回一个ril_init,给 RIL_register(&s_callbacks);回调,进行初始化

}

6.4实现mainloop()函数

static void *

mainLoop(void *param)

{

at_set_on_reader_closed(onATReaderClosed);

at_set_on_timeout(onATTimeout);


for (;;) {

fd = -1;

while (fd < 0) {

if (s_port > 0) {

fd = socket_loopback_client(s_port, SOCK_STREAM);

} else if (s_device_socket) {

if (!strcmp(s_device_path, "/dev/socket/qemud")) {

/* Qemu-specific control socket */

fd = socket_local_client( "qemud", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM );

if (fd >= 0 ) {

char answer[2];


if ( write(fd, "gsm", 3) != 3 ||

read(fd, answer, 2) != 2 ||

memcmp(answer, "OK", 2) != 0)

{

close(fd);

fd = -1;

}

}

}

else

/* 获取rild socket*/


fd = socket_local_client( s_device_path, ANDROID_SOCKET_NAMESPACE_FILESYSTEM,SOCK_STREAM );

} else if (s_device_path != NULL) {

fd = open (s_device_path, O_RDWR);


}

ret =
at_open(fd, onUnsolicited);


附:在atchannel.c

int at_open(int fd, ATUnsolHandler h)

{

#ifdef HUAWEI_EM770W /*新增的modulse*/

{ fd2 = open ("/dev/ttyUSB2", O_RDWR);

ret = pthread_create(&s_tid_reader_urc, &attr, urc_readerLoop, &attr);

}

ret = pthread_create(&s_tid_reader, &attr,
readerLoop, &attr);

#endif

return 0;

}

第五、通过readloop()函数判断为AT:等待回应还是URC请求

/*下面read的阻塞式的读取modoem(是initializeCallback()函数发送的AT命令,)发来信息,还判断是URC还是AT回应请求,并等待回应是否OK,*/

static void
*readerLoop(void *arg)

{

for (;;) {

const char * line;

line =readline();

if (line == NULL) {

break;

}

if(isSMSUnsolicited(line)) {

char *line1;

const char *line2;

line1 = strdup(line);

line2 = readline();

if (line2 == NULL) {

break;

}

if (s_unsolHandler != NULL) {

s_unsolHandler (line1, line2);

}

free(line1);

} else {

processLine(line);/*对上面读取信息进行解析判断*/

}

#ifdef HAVE_ANDROID_OS

if (s_ackPowerIoctl > 0) {

ioctl(s_fd, OMAP_CSMI_TTY_ACK, &s_readCount);

s_readCount = 0;

}

#endif /*HAVE_ANDROID_OS*/

}

onReaderClosed();

return NULL;

}

/*AT的response有两种,一种是unsolicited。另一种是普通response,也就是命令的响应。

response信息的获取在readerLoop()中。由readline()函数读取上来。

读取到的line将被传入processLine()函数进行解析,processLine()函数首先会判断当前的响应是主动响应还是普通响应,

如果是主动响应,将调用handleUnsolicited()函数,如果为普通响应,那么将调用handleFinalResponse()函数进行处理

对响应串的主要的解析过程,由at_tok.c中的各种解析函数完成,提供字符串分析解析功能。

*/

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;

handleFinalResponse(line);

} else if (isFinalResponseError(line)) {

sp_response->success = 0;

handleFinalResponse(line);//1.用来处理UCR请求,上报RIL.java层

} 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);//2.用来处理send_at_command()发过的回应

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 */

LOGE("Unsupported AT command type %d\n", s_type);

handleUnsolicited(line);

break;

}

pthread_mutex_unlock(&s_commandmutex);

}

static const char *readline()

{

//在这打印Modem回应的OK/err信息,还有是否是URC还是AT命令请求信???

LOGD("AT< %s\n", ret);

return ret;//返回,读取好的上面信息

}

RIL_requestTimedCallback(initializeCallback, NULL, &TIMEVAL_0);//打印AT> ATE0Q0V1

/*发生AT命令*/

static void initializeCallback(void *param)

{

at_handshake

at_send_command("ATE0Q0V1", NULL);//同步机制,send_at_command 是同步的,命令发送后,send_at_command 将等待在s_commandcond ,直到有 sp_response->finalResponse。

setRadioState (RADIO_STATE_SIM_NOT_READY);

}

}

}

}



######################################################################################################################

上面函数执行完了,说明在ril_evnet_loop()轮询中有事件,再去把信息向下层的模块发生AT命令,等知道,模块的生效

接下来就要去注册到reference-ril.so动态库去,等待dlopen调用

######################################################################################################################

第三、处理两个socket
6.5libril/ril.cpp-

/*注册rild socket端口事件监听到事件循环中和bedug socket*/

第六、注册rild socket端口事件监听到事件循环中

RIL_register(funcs);



RIL_register (const RIL_RadioFunctions *callbacks){//说明已经初始化完了 ,才回调

if (callbacks == NULL|| ! (callbacks->version == RIL_VERSION || callbacks->version == 1)) {

LOGE("RIL_register: RIL_RadioFunctions * null or invalid version"," (expected %d)", RIL_VERSION);

return;

}


if (s_registerCalled > 0) {

LOGE("RIL_register has been called more than once. ""Subsequent call ignored");

LOGD("RIL_register has been called more than once. ""Subsequent call ignored");

return;

}

//1:换个马甲

memcpy(&s_callbacks, callbacks, sizeof (RIL_RadioFunctions));

s_registerCalled = 1;

for (int i = 0; i < (int)NUM_ELEMS(s_commands); i++) {

assert(i == s_commands[i].requestNumber);

}


for (int i = 0; i < (int)NUM_ELEMS(s_unsolResponses); i++) {

assert(i + RIL_UNSOL_RESPONSE_BASE

== s_unsolResponses[i].requestNumber);

}


if (s_started == 0) {

RIL_startEventLoop();

}


// start listen socket 开始侦听套接字

#if 0

ret = socket_local_server (SOCKET_NAME_RIL,ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);


s_fdListen = ret;

#else

2:获取init.rc定义的rild socket


s_fdListen= android_get_control_socket(SOCKET_NAME_RIL);

ret = listen(s_fdListen, 4);


#endif

/*如果ril socket 端口一有数据,就去执行listencallback函数

这个函数就建立起与客户端的监听话柄

s_fdLiten继续监听其他客户端的链接*/

第六、将此端口加入事件select队列

ril_event_set (&s_listen_event, s_fdListen, false,listenCallback, NULL);


rilEventAddWakeup (&s_listen_event);

#if 1

3.获取debug socket

s_fdDebug= android_get_control_socket(SOCKET_NAME_RIL_DEBUG);

ret = listen(s_fdDebug, 4);

//将此处端口加入到select队列去

ril_event_set (&s_debug_event, s_fdDebug, true,debugCallback, NULL);

rilEventAddWakeup (&s_debug_event);

#endif


}

第七、 如果rild socket端口有数据来了将执行listencallback函数

ril_event_set (&s_listen_event, s_fdListen, false,listenCallback, NULL);

static void listenCallback(int fd, short flags, void *param) {

int ret;

int err;

int is_phone_socket;

RecordStream *p_rs;

struct sockaddr_un peeraddr;

socklen_t socklen = sizeof (peeraddr);

struct ucred creds;

socklen_t szCreds = sizeof(creds);

struct passwd *pwd = NULL;

assert (s_fdCommand < 0);

assert (fd == s_fdListen);

//连接JAVA层来的sockcet

s_fdCommand =
accept(s_fdListen, (sockaddr *) &peeraddr, &socklen);


if (s_fdCommand < 0 ) {

LOGE("Error on accept() errno:%d", errno);

rilEventAddWakeup(&s_listen_event);

return;

}

errno = 0;

is_phone_socket = 0;

err = getsockopt(s_fdCommand, SOL_SOCKET, SO_PEERCRED, &creds, &szCreds);

if (err == 0 && szCreds > 0) {

errno = 0;

pwd = getpwuid(creds.uid);

if (pwd != NULL) {if (strcmp(pwd->pw_name, PHONE_PROCESS) == 0) { is_phone_socket = 1;}

else {

LOGE("RILD can't accept socket from process %s", pwd->pw_name);

}

} else { LOGE("Error on getpwuid() errno: %d", errno); }

} else {

LOGD("Error on getsockopt() errno: %d", errno);

}

if ( !is_phone_socket ) {

LOGE("RILD must accept socket from %s", PHONE_PROCESS);

close(s_fdCommand);

s_fdCommand = -1;

onCommandsSocketClosed();

/* start listening for new connections again */

rilEventAddWakeup(&s_listen_event);

return;

}

ret = fcntl(s_fdCommand, F_SETFL, O_NONBLOCK);

if (ret < 0) {

LOGE ("Error setting O_NONBLOCK errno:%d", errno);

}

LOGI("libril: new connection");

//有数据来的时候,把s_fdCommand绑定到record_stream_new 。目的就是保证数据的完整性

p_rs = record_stream_new(s_fdCommand, MAX_COMMAND_BYTES);

//当有数据来的时候,函数就去执行processCommandsCallback()函数,把数据读到p_record中

ril_event_set (&s_commands_event, s_fdCommand, 1, processCommandsCallback, p_rs);

static void processCommandsCallback(int fd, short flags, void *param) {

RecordStream *p_rs;

void *p_record;

size_t recordlen;

int ret;

assert(fd == s_fdCommand);

p_rs = (RecordStream *)param;

LOGD("--SHI-XIAN--ril_regieter-----static void processCommandsCallback(int fd, short flags, void *param)");

for (;;) {

/* loop until EAGAIN/EINTR, end of stream, or other error */

ret = record_stream_get_next(p_rs, &p_record, &recordlen);

if (ret == 0 && p_record == NULL) {

/* end-of-stream */

break;

} else if (ret < 0) {

break;

} else if (ret == 0) { /* && p_record != NULL */

//阻塞方式获取数据 到p_record 利用RecordStream机制保证数据完整

processCommandBuffer(p_record, recordlen);

}

}

if (ret == 0 || !(errno == EAGAIN || errno == EINTR)) {

/* fatal error or end-of-stream */

if (ret != 0) {

LOGE("error on reading command socket errno:%d\n", errno);

} else {

LOGW("EOS. Closing command socket.");

}

close(s_fdCommand);

s_fdCommand = -1;

ril_event_del(&s_commands_event);

record_stream_free(p_rs);

/* start listening for new connections again 开始监听新的连接*/

rilEventAddWakeup(&s_listen_event);

onCommandsSocketClosed();

}

}

把accpet接受到rild socket 来的信息先绑定,后读到p_record,说明向下动作全部结束,等待onRequest发请求

第八,状态结束,等待onRequest发请求

static int

processCommandBuffer(void *buffer, size_t buflen) {

Parcel p;

status_t status;

int32_t request;

int32_t token;

RequestInfo *pRI;

int ret;

LOGD("---shixian -processCommandBuffer---");

p.setData((uint8_t *) buffer, buflen);

上面实现状态检查全部结束结束,下面为java来的请求,响应onRequest()方法

// status checked at end

status = p.readInt32(&request);

status = p.readInt32 (&token);//请求队列的序列号

if (status != NO_ERROR) {

LOGE("invalid request block");

return 0;

}

if (request < 1 || request >= (int32_t)NUM_ELEMS(s_commands)) {

LOGE("unsupported request code %d token %d", request, token);

// FIXME this should perhaps return a response

return 0;

}

pRI = (RequestInfo *)calloc(1, sizeof(RequestInfo));

pRI->token = token;

pRI->pCI = &(s_commands[request]);

ret = pthread_mutex_lock(&s_pendingRequestsMutex);

assert (ret == 0);

pRI->p_next = s_pendingRequests;

s_pendingRequests = pRI;

ret = pthread_mutex_unlock(&s_pendingRequestsMutex);

assert (ret == 0);

/* sLastDispatchedToken = token; */

pRI->pCI->dispatchFunction(p, pRI);

//假设是接收了dial指令,pRI->PCI->dispatchFunction(p,pRI),调用dispatchDial(p,pRI)

return 0;

}

s_callbacks.onRequest(pRI->pCI->requestNumber, &dial,sizeof(dial), pRI);

in reference-ril.c onRequest()

/*** Callback methods from the RIL library to us ***/

/**

* 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.

*

* Will always be called from the same thread, so returning here implies

* that the radio is ready to process another command (whether or not

* the previous command has completed).

*/

static void

onRequest (int request, void *data, size_t datalen, RIL_Token t)

{

ATResponse *p_response;

int err;

LOGD("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 (request) {

case RIL_REQUEST_GET_SIM_STATUS: {

RIL_CardStatus *p_card_status;

char *p_buffer;

int buffer_size;

int result = getCardStatus(&p_card_status);

if (result == RIL_E_SUCCESS) {

p_buffer = (char *)p_card_status;

buffer_size = sizeof(*p_card_status);

} else {

p_buffer = NULL;

buffer_size = 0;

}

RIL_onRequestComplete(t, result, p_buffer, buffer_size);

freeCardStatus(p_card_status);

break;

}

case RIL_REQUEST_GET_CURRENT_CALLS:

requestGetCurrentCalls(data, datalen, t);

break;

case RIL_REQUEST_DIAL:

requestDial(data, datalen, t);

break;

case RIL_REQUEST_HANGUP:

requestHangup(data, datalen, t);

break;

case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND:

// 3GPP 22.030 6.5.5

// "Releases all held calls or sets User Determined User Busy

// (UDUB) for a waiting call."

at_send_command("AT+CHLD=0", NULL);

/* 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);

break;

case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND:

// 3GPP 22.030 6.5.5

// "Releases all active calls (if any exist) and accepts

// the other (held or waiting) call."

at_send_command("AT+CHLD=1", NULL);

/* 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);

break;

case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE:

// 3GPP 22.030 6.5.5

// "Places all active calls (if any exist) on hold and accepts

// the other (held or waiting) call."

at_send_command("AT+CHLD=2", NULL);

#ifdef WORKAROUND_ERRONEOUS_ANSWER

s_expectAnswer = 1;

#endif /* WORKAROUND_ERRONEOUS_ANSWER */

/* 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);

break;

case RIL_REQUEST_ANSWER:

at_send_command("ATA", NULL);

#ifdef WORKAROUND_ERRONEOUS_ANSWER

s_expectAnswer = 1;

#endif /* WORKAROUND_ERRONEOUS_ANSWER */

/* 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);

break;

case RIL_REQUEST_CONFERENCE:

// 3GPP 22.030 6.5.5

// "Adds a held call to the conversation"

at_send_command("AT+CHLD=3", NULL);

/* 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);

break;

case RIL_REQUEST_UDUB:

/* user determined user busy */

/* sometimes used: ATH */

at_send_command("ATH", NULL);

/* 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);

break;

case RIL_REQUEST_SEPARATE_CONNECTION:

{

char cmd[12];

int party = ((int*)data)[0];

// Make sure that party is in a valid range.

// (Note: The Telephony middle layer imposes a range of 1 to 7.

// It's sufficient for us to just make sure it's single digit.)

if (party > 0 && party < 10) {

sprintf(cmd, "AT+CHLD=2%d", party);

at_send_command(cmd, NULL);

RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);

} else {

RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);

}

}

break;

case RIL_REQUEST_SIGNAL_STRENGTH:

requestSignalStrength(data, datalen, t);

break;

case RIL_REQUEST_REGISTRATION_STATE:

case RIL_REQUEST_GPRS_REGISTRATION_STATE:

requestRegistrationState(request, data, datalen, t);

break;

case RIL_REQUEST_OPERATOR:

requestOperator(data, datalen, t);

break;

case RIL_REQUEST_RADIO_POWER:

requestRadioPower(data, datalen, t);

break;

case RIL_REQUEST_DTMF: {

char c = ((char *)data)[0];

char *cmd;

asprintf(&cmd, "AT+VTS=%c", (int)c);

at_send_command(cmd, NULL);

free(cmd);

RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);

break;

}

case RIL_REQUEST_SEND_SMS:

requestSendSMS(data, datalen, t);

break;

case RIL_REQUEST_SETUP_DATA_CALL:

requestSetupDataCall(data, datalen, t);

break;

case RIL_REQUEST_SMS_ACKNOWLEDGE:

requestSMSAcknowledge(data, datalen, t);

break;

case RIL_REQUEST_GET_IMSI:

p_response = NULL;

err = at_send_command_numeric("AT+CIMI", &p_response);

if (err < 0 || p_response->success == 0) {

RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);

} else {

RIL_onRequestComplete(t, RIL_E_SUCCESS,

p_response->p_intermediates->line, sizeof(char *));

}

at_response_free(p_response);

break;

case RIL_REQUEST_GET_IMEI:

p_response = NULL;

err = at_send_command_numeric("AT+CGSN", &p_response);

if (err < 0 || p_response->success == 0) {

RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);

} else {

RIL_onRequestComplete(t, RIL_E_SUCCESS,

p_response->p_intermediates->line, sizeof(char *));

}

at_response_free(p_response);

break;

case RIL_REQUEST_SIM_IO:

requestSIM_IO(data,datalen,t);

break;

case RIL_REQUEST_SEND_USSD:

requestSendUSSD(data, datalen, t);

break;

case RIL_REQUEST_CANCEL_USSD:

p_response = NULL;

err = at_send_command_numeric("AT+CUSD=2", &p_response);

if (err < 0 || p_response->success == 0) {

RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);

} else {

RIL_onRequestComplete(t, RIL_E_SUCCESS,

p_response->p_intermediates->line, sizeof(char *));

}

at_response_free(p_response);

break;

case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC:

at_send_command("AT+COPS=0", NULL);

break;

case RIL_REQUEST_DATA_CALL_LIST:

requestDataCallList(data, datalen, t);

break;

case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE:

requestQueryNetworkSelectionMode(data, datalen, t);

break;

case RIL_REQUEST_OEM_HOOK_RAW:

// echo back data

RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);

break;

case RIL_REQUEST_OEM_HOOK_STRINGS: {

int i;

const char ** cur;

LOGD("got OEM_HOOK_STRINGS: 0x%8p %lu", data, (long)datalen);

for (i = (datalen / sizeof (char *)), cur = (const char **)data ;

i > 0 ; cur++, i --) {

LOGD("> '%s'", *cur);

}

// echo back strings

RIL_onRequestComplete(t, RIL_E_SUCCESS, data, datalen);

break;

}

case RIL_REQUEST_WRITE_SMS_TO_SIM:

requestWriteSmsToSim(data, datalen, t);

break;

case RIL_REQUEST_DELETE_SMS_ON_SIM: {

char * cmd;

p_response = NULL;

asprintf(&cmd, "AT+CMGD=%d", ((int *)data)[0]);

err = at_send_command(cmd, &p_response);

free(cmd);

if (err < 0 || p_response->success == 0) {

RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);

} else {

RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);

}

at_response_free(p_response);

break;

}

case RIL_REQUEST_ENTER_SIM_PIN:

case RIL_REQUEST_ENTER_SIM_PUK:

case RIL_REQUEST_ENTER_SIM_PIN2:

case RIL_REQUEST_ENTER_SIM_PUK2:

case RIL_REQUEST_CHANGE_SIM_PIN:

case RIL_REQUEST_CHANGE_SIM_PIN2:

requestEnterSimPin(data, datalen, t);

break;

default:

RIL_onRequestComplete(t, RIL_E_REQUEST_NOT_SUPPORTED, NULL, 0);

break;

}

}

rilEventAddWakeup(&s_commands_event);

onNewCommandConnect();

}



最后,就进入

frameworks/base/telephony/java/com/android/internal/telephony/gsm/RIL.java

6.4、串口监听收到atd命令的应答"OK"或"nocarrier"等

readerLoop()

line = readline();

processLine(line);

handleFinalResponse(line);

pthread_cond_signal(&s_commandcond);//至此,前面的等待结束,接着执行RIL_onRequestComplete函数

6.5、java层收到应答后的处理,以dial为例子.

ril.java->RILReceiver.run()

for(;;)

{

...

length = readRilMessage(is, buffer);

p = Parcel.obtain();

p.unmarshall(buffer, 0, length);

p.setDataPosition(0);

processResponse(p);

type = p.readInt();

if (type == RESPONSE_SOLICITED) {

processSolicited (p);

serial = p.readInt();

rr = findAndRemoveRequestFromList(serial);

rr.mResult.sendToTarget();

......

}

CallTracker.java->handleMessage (Message msg)

switch (msg.what) {

case EVENT_OPERATION_COMPLETE:

ar = (AsyncResult)msg.obj;

operationComplete();

cm.getCurrentCalls(lastRelevantPoll);

第二部分:unsolicited 消息从modem上报到java的流程。

c++部份

readerLoop()

line = readline();

processLine(line);

handleUnsolicited(line);

if (s_unsolHandler != NULL) {

s_unsolHandler (line1, line2);//实际执行的是voidonUnsolicited (const char *s, const char *sms_pdu)

if (strStartsWith(s,"+CRING:")

||strStartsWith(s,"RING")

|| strStartsWith(s,"NOCARRIER")

||strStartsWith(s,"+CCWA")

)

RIL_onUnsolicitedResponse (RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED, NULL,0);

p.writeInt32(RESPONSE_UNSOLICITED);

p.writeInt32 (unsolResponse);

ret =s_unsolResponses[unsolResponseIndex].responseFunction(p, data, datalen);

ret = sendResponse(p);

sendResponseRaw(p.data(),p.dataSize());

ret = blockingWrite(fd, (void*)&header, sizeof(header));

blockingWrite(fd, data,dataSize);

java部份

ril.java->RILReceiver.run()

for(;;)

{

...

length = readRilMessage(is, buffer);

p = Parcel.obtain();

p.unmarshall(buffer, 0, length);

p.setDataPosition(0);

processResponse(p);

processUnsolicited (p);

response = p.readInt();

switch(response) {

...

case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret = responseVoid(p); break;

...

}

switch(response) {

caseRIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:

if (RILJ_LOGD)unsljLog(response);

mCallStateRegistrants

.notifyRegistrants(newAsyncResult(null, null, null));

...

}

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