從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,並向上傳遞電話狀態改變的通知。

 

 

 

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