拨出电话流程:

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

第一、建立事件循环线程

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

   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));
              ...
         }

RIL层代码分析--拨号整个流程相关推荐

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

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

  2. 一--RIL层代码分析-RIL_RadioFunctions *RIL_Init(funcs =rilInit()-mainloop()

     ril/rild/rild.c->main()为函数入口 ------------------------------------------------------------------- ...

  3. 三:Sensor SLPI层代码分析---

    三:Sensor SLPI层代码分析 在学习SLPI侧代码前我们先了解下SEE的registry&config. registry 放在/persist/sensors/registry/re ...

  4. BLOCK层代码分析(9)IO下发之IO下发

    看着题目是不是很奇怪,想不出好的名字,就这样将就吧. 前面bio bounce过程,bio的切分和合并,request的获取是为IO请求下发做准备工作.当这些准备工作完成后,才进入到真正的IO下发过程 ...

  5. BLOCK层代码分析(10)IO下发之IO下发函数总结

    BLOCK层IO下发涉及直接下发,调度器,没有设置调度类型以及plug/unplug等,因此下发函数纷繁复杂,这里做介绍几个主要的函数. 前面介绍了函数blk_mq_try_issue_directl ...

  6. perf-perf stat用户层代码分析

    perf_event 源码分析 前言 简单来说,perf是一种性能监测工具,它首先对通用处理器提供的performance counter进行编程,设定计数器阈值和事件,然后性能计数器就会在设定事件发 ...

  7. 美颜sdk人脸美妆代码分析、算法流程

    美颜sdk人像美妆是非常重要的一个功能,目前深受广大用户喜爱,本篇文章小编将为大家讲解一下美颜sdk人像美妆功能的代码以及算法实现流程. 1.人像美妆算法流程 首先进行妆容模板制作,主要由Photos ...

  8. 微型项目实践(6):Business层代码分析——实体类的生成策略

    上一篇中,我们分析了实体类的基类Entity,这一篇中,我们就分析一下基于该类的实体类. 每一个实体类都会有两个文件组成,我们以BlogClass为例,该类包含两个文件:BlogClass.cs和Bl ...

  9. AndroidStudio_百度人脸识别离线SDK_代码分析_使用流程_随时更新---Android原生开发工作笔记217

    打开百度的人脸识别的离线识别SDK 的案例,可以看到有个闸机模式, 可以看到上面这个类就是,识别人脸用的.闸机模式下识别人脸的类. 识别流程是这样的: 这里调用 FaceSDKManager 进行摄像 ...

最新文章

  1. 第十六届智能车竞赛赛道设计第一版本
  2. Java 面向对象细节
  3. WordPress-基础设置之固定链接设置
  4. 【JavaSE04】Java中循环语句for,while,do···while-练习2
  5. object-c 随机数总结
  6. ftp获取远程Pdf文件
  7. 『对比Excel,轻松学习Python数据分析』新书发布
  8. python京东注册账号_Python爬虫模拟登录京东获取个人信息
  9. C++ 学习之旅(12)——static用法小结
  10. 玩转oracle 11g(19):ora-00020和64位数据库安装32为plsql
  11. 大数据翻页_大数据量下的分页解决方法
  12. Silverlight 入门
  13. 【Android】Android Studio打包生成正式签名的APK
  14. 黑马博客——详细步骤(九)项目功能的实现之mongoDB数据库添加账号
  15. CenOS6 nginx+pxe+tftpd+samba/nfs+dhcpd 无盘安装windows  linux
  16. pyqt5 加载gif_PyQt5:在Qmovi中重新加载gif
  17. 【嵌入式】学习心路历程与总结
  18. 深度学习推荐系统_深度推荐系统
  19. 妙用自定义注解,一行代码搞定大功能(文末赠书)
  20. 红米4android版本怎么升级,红米4MIUI稳定版安卓9.0刷机包(完整固件升级包MIUI11 稳定版)...

热门文章

  1. 2019年北京画室排名前十位(考央美比较好的画)
  2. pythondistinct教程_【python】用asq实现count(distinct cln)
  3. Swagger 入门
  4. 华创资本“细+慢活儿”的企业服务SaaS
  5. java pdf转word,没页数限制,去除水印
  6. MATLAB+Simulink实现赛车(含多种赛车相关场景)建模(含源码)
  7. 适合圣诞送礼的蓝牙耳机有哪些?这几款音质好的蓝牙耳机值得入手
  8. CGB2009-京淘项目day02
  9. OpenCV-Python小应用(六):车道线检测
  10. 程序员:我们为什么要熬夜