从Phone源码中分析来电话流程(部分)

首先,通过ddms拨打模拟器的电话,这样
在RIL.java的RILReceiver线程(run()函数中)当中接收到rild发来的incoming消息,接收线程将消息转给processResponse(p)进行处理,processResponse(p)又将消息转给processUnsolicited (p)处理,然后又转到          

         case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED:
                if (RILJ_LOGD) unsljLog(response);
                mCallStateRegistrants
                    .notifyRegistrants(new AsyncResult(null, null, null));
            break;
进行处理。这样消息就转到了mCallStateRegistrants(RegistrantList.java类中)的notifyRegistrants()函数进行处理了,接着转到internalNotifyRegistrants(ar.result, ar.exception);
消息继续上传到
            Registrant  r = (Registrant) registrants.get(i);
            r.internalNotifyRegistrant(result, exception);

    internalNotifyRegistrant的函数如下所示:

    internalNotifyRegistrant (Object result, Throwable exception)
    {
        Handler h = getHandler();

        if (h == null) {
            clear();
        } else {
            Message msg = Message.obtain();

            msg.what = what;
           
            msg.obj = new AsyncResult(userObj, result, exception);
           
            h.sendMessage(msg);
        }
    }

注意到消息是由Handler类型的h发出的。好了

我们来看Handler
在Handler中含有如下函数(只是没有什么实现而已)
handleMessage(Message msg)
这就好说了,接着我们看消息怎么上传的吧:
我们以GSM类型的Phone为例
找到CallTracker类,我们发现这个类是由Handler继承而来的,于是我们查看下其handleMessage(Message msg)函数,发现该函数还是没有什么实现(刚看了下原来该这是个抽象类,汗。。。)
不用着急,继续往下找,我们发现GsmCallTracker类是继承自CallTracker类的,看GsmCallTracker的名字,我们应该知道这个类是做什么用的了吧。
找到handleMessage(Message msg)函数,其中有如下语句:
            case EVENT_REPOLL_AFTER_DELAY:
            case EVENT_CALL_STATE_CHANGE:
                pollCallsWhenSafe();
            break;
注意第二个case语句,有电话来了,那么call的状态自然是要改变的,呵呵。
于是,转到 pollCallsWhenSafe()进行处理。

在CallTracker类中,pollCallsWhenSafe()函数是的实现如下

    protected void pollCallsWhenSafe() {
        needsPoll = true;

        if (checkNoOperationsPending()) {
            lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);
            cm.getCurrentCalls(lastRelevantPoll);
        }
    }

其中 public CommandsInterface cm;
于是,转到RIL.java的

    public void
    getCurrentCalls (Message result) {
        RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result);

        if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));

        send(rr);
    }
执行

这样,消息就往底层下发了,详细过程,我不解释,当消息处理完后,RIL.java的接收线程又会收到相应的消息

进入processSolicited (Parcel p)处理,然后消息进入GsmCallTracker类的
case:EVENT_POLL_CALLS_RESULT进行处理---->handlePollCalls(AsyncResult ar)---->消息经过发送和接收后进入
            case EVENT_REPOLL_AFTER_DELAY:
            case EVENT_CALL_STATE_CHANGE:
                pollCallsWhenSafe();
------>................消息太多,自己去跟踪吧
------>handlePollCalls((AsyncResult)msg.obj);
------>pollCallsWhenSafe();
接通电话,则进入下面的函数执行
------>operationComplete();
进入App层处理,找下CallNotifier.java的handleMessage()函数,在接下来的过程当中,就比较好跟踪了,

 

==================================================================================================================================

 

Android电话系统之GSMCallTracker

通话连接管理

GSMCallTracker在本质上是一个Handler。

wps_clip_image-65

GSMCallTracker是Android的通话管理层。GSMCallTracker建立了ConnectionList来管理现行的通话连接,并向上层提供电话调用接口。

wps_clip_image-1

在GSMCallTracker中维护着通话列表:connections。顺序记录了正连接上的通话,这些通话包括:ACTIVE,DIALING,ALERTING,HOLDING,INCOMING,WAITING等状态的连接。GSMCallTracker将这些连接分为了三类别进行管理:

RingingCall: INCOMING ,WAITING

ForegourndCall: ACTIVE, DIALING ,ALERTING

BackgroundCall: HOLDING

上层函数通过getRingCall(),getForegrouandCall()等来获得电话系统中特定通话连接。

为了管理电话状态,GSMCallTracker在构造时就将自己登记到了电话状态变化通知表中。RIL-Java一收到电话状态变化的通知,就会使用EVENT_CALL_STATE_CHANGE通知到GSMCallTacker

    在一般的实现中,我们的通话Call Table是通过AT+CLCC查询到的,CPI可以通知到电话的改变,但是CPI在各个Modem的实现中差别比较大,所以参考设计都没有用到CPI这样的电话连接改变通知,而是使用最为传统的CLCC查询CALL TABLE。在GSMTracker中使用connections来管理Android电话系统中的通话连接。每次电话状态发生变化是GSMTracker就会使用CLCC查询来更新connections内容,如果内容有发生变化,则向上层发起电话状态改变的通知。

1 RIL-JAVA中发起电话连接列表操作

在RIL-JAVA中涉及到CurrentCallList查询的有以下几个操作:

(1)hangup

(2)dial

(3)acceptCall

(4)rejectCall

在GSMcallTracker在发起这些调用的时候都有一个共同的ResultMessage构造函数:obtainCompleteMessage()。obtainCompleteMessage()实际上是调用:

obtainCompleteMessage(EVENT_OPERATION_COMPLETE)

这就意味着在这些电话操作后,GSMCallTracker会收到EVENT_OPERATION_COMPLETE消息,于是我们将目光转移到handleMessage()@GSMCallTracker的EVENT_OPERATION_COMPLETE事件处理:operationComplete@GSMCallTracker。

operationComplete()操作会使用cm.getCurrentCalls(lastRelevantPoll)调用,向RILD发起RIL_REQUEST_GET_CURRENT_CALLS调用,这个最终就是向Modem发起AT+CLCC,获取到真正的电话列表。

2 在RILD中,引起getCurrentCalls调用

(1)在RILD中,收到URC消息:

+CRING

RING

NO CARRIER

+CCWA

将会使用RIL_onUnsolicitedResponse( RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED),主动向ril-java上报RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED消息。

(2) 在处理requestCurrentCalls时,使用CLCC查询通话连接(CALL TABLE)后,如何发现有call Table不为空则开启一个定时器,主动上报RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED消息,直到没有电话连接为止。

在RIL-Java层收到RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED这个URC,并利用mCallStateRegistrants.notifyRegistrants(new AsyncResult(null, null, null))来通知电话状态的变化,此时GSMTracker会接收到EVENT_CALL_STATE_CHANGE消息,并使用

                pollCallsWhenSafe()->  cm.getCurrentCalls(lastRelevantPoll);

来发起查询,并更新JAVA层的电话列表。

3 handlePollCalls电话列表刷新

      首先我们来看看是什么引起了handlePollCalls的调用。

     上面的1,2分析了,Android电话系统中所有引起电话连接列表更新的条件及其处理。他们共同的调用了cm.getCurrentCalls(lastRelevantPoll) 来完成电话列表的获取。

lastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT)

我们这里就从可以看到获取到的电话列表Result使用handlePollCalls进行了处理。Result实际上是一个DriverCall列表,handlePollCalls的工作就是将当前电话列表与RIL-Java的电话列表对比,使用DriverCall列表更新CallTracker的电话列表connections,并向上传递电话状态改变的通知。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章