本文主要是介绍四--RIL层代码分析--整个电话来访过程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
最近公司开发一个几百万的项目,要求重写系统RIL层,看了几个招聘信息,只要你会RIL层开发的,工资上w每个月不是梦,这是几天研究的成果,希望对大家有所帮助,兄弟们加油吧!
先来一个总的流程图:
拨出电话流程:
1
contacts的androidmanifest.xmlandroid:process="android.process.acore"说明此应用程序运行在acore进程中。DialtactsActivity的intent-filter的action属性设置为main,catelog属性设置为launcher,所以此activity能出现,
2
进入TwelveKeyDialer OnClick方法,按住的按钮id为:R.id.digits,执行
placecall()
Intent intent = newIntent(Intent.ACTION_CALL_PRIVILEGED,
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
3、
intert.ACTION_CALL_PRIVILEGED实际字符串为android.intent.action.CALL_PRIVILEGED,通过查找知道了packegs/phone下面的androidmanifest.xml中PrivilegedOutgoingCallBr
onCreate()
//如果为紧急号码马上启动intent.setClass(this,InCallScreen.class); startActivity(intent);
Intent broadcastIntent = new Intent(Intent.ACTION_NEW_OUTGOING_CALL);
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);
5、请求拨号的java部分流程
onCreate(第一次)/onNewIntent(非第一次)
internalResolveIntent
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
上面步骤:为APP就是java层传下的信息(就是执行的动作:按键打电话),已经做完,下面讲RIL层如何来接受上层来的信息
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
第一、《创建轮询机制》
6.请求拨号的c/c++部分流程
/*初始化事件循环,启动串口监听,注册socket监听*/
6.1在til/rild/rild.c为入口函数
RIL_startEventLoop()
6.2在libril/ril.cpp
第一、建立事件循环线程
ret = pthread_create(&s_tid_dispatch, &attr, eventLoop, NULL);
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
######################################################################################################################
多路复用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
}
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));
...
}
这篇关于四--RIL层代码分析--整个电话来访过程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!