RILJ對象的交互機制

RILJ交互機制:

GsmCdmaCallTracker與RILJ對象的交互完成的通話控制,以及通話狀態和通話基本信息的保存,更新等操作,交互方式不用說就知道有兩類:

  • CallTracker對象主動發起
  • CallTracker對象被動接收

接下來講解一下我理解的流程:

GsmCdmaPhone作爲一個Facade(門面)模式控制這三個Tracker類分別是:GsmCdmaCallTracker(語音通話模型)和ServiceStateTracker(網絡服務)和DcTracker(移動數據業務)處理,也是 數據下發的入口比如:dial (請求撥號),acceptCall(接聽電話),rejectCall(拒接電話)等等..

 

主動發起

主動發起我們用rejectCall()(掛斷方法)方法作爲講解:

先看一下流程圖:

 

 

講解:

首先電話發起一個掛斷請求從Dialer->Telecom-TeleService->GsmCdmaPhone.java中調用rejectCall()這個方法表示掛斷

GsmCdmaPhone.java

  @Override
    public void rejectCall() throws CallStateException {
        mCT.rejectCall();
    }

這裏的mCT(GsmCdmaCallTracker.java類)。

 

GmsCdmaCallTracker.java

 //拒接電話
    public void rejectCall() throws CallStateException {
        // AT指令,通話保持或掛斷電話
        // 非響領狀態時,將掛斷通話保持的電話
        if (mRingingCall.getState().isRinging()) {
            mCi.rejectCall(obtainCompleteMessage());//調用RIL對象的拒接來電請求方法
        } else {
            throw new CallStateException("phone not ringing");
        }
    }

這個方法我們重點講解一下obtainCompleteMessage()方法他內部是創建一個Message消息進行返回

private Message obtainCompleteMessage() {
        return obtainCompleteMessage(EVENT_OPERATION_COMPLETE);
}
private Message obtainCompleteMessage(int what) {
        mPendingOperations++;
        mLastRelevantPoll = null;
        mNeedsPoll = true;

        if (DBG_POLL) log("obtainCompleteMessage: pendingOperations=" +
                mPendingOperations + ", needsPoll=" + mNeedsPoll);

        return obtainMessage(what);
    }

這裏創建了一個Message對象

          GsmCdmaCallTracker對象首先調用obtainCompleteMessage創建Message消息對象接着調用RILJ對象中對應的通話控制方法,同時傳遞剛創建的Message消息對象作爲回調參數。

在RIL中完成通話管理和通話控制後,RILJ對象發起ENEVT_OPERATION_COMPLETE類型的Handler Callback(回調)

@Override
    public void handleMessage(Message msg) {//接收並且處理RILJ發出的Handle消息 。handleMessge方法接收並響應RILJ對象發出的Handler消息。
     
        AsyncResult ar;
        switch (msg.what) {
            .......
            .....
            case EVENT_OPERATION_COMPLETE://有四個方法全是EVENT_OPERATION_COMPLETE  (dial,acceptCall,rejectCall,hangup)
                //最終還是獲取了EVENT_POLL_CALLS_RESULT調用 handlePoolCalls()
                operationComplete();
            break;
        ....
        .......
}

      GsmCdmaCallTracker對象響應ENEVT_OPERATION_COMPLETE類型的Handler消息,將調用operationComplete()方法。那麼我們來看看這個方法:

//與RILJ交互的回調處理
    private void operationComplete() {
        mPendingOperations--;

        if (DBG_POLL) log("operationComplete: pendingOperations=" +
                mPendingOperations + ", needsPoll=" + mNeedsPoll);

        if (mPendingOperations == 0 && mNeedsPoll) {
            //攜帶EVENT_POOL_CALLS_RESULT查詢當前的CallList列表
            mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);//EVENT_POLL_CALLS_RESULT
            //獲取最新狀態  往底層發送消息連接成功了  攜帶  EVENT_POLL_CALLS_RESULT消息
            mCi.getCurrentCalls(mLastRelevantPoll);
        } else if (mPendingOperations < 0) {
            // this should never happen
            Rlog.e(LOG_TAG,"GsmCdmaCallTracker.pendingOperations < 0");
            mPendingOperations = 0;
        }
    }

這裏很重要可以看到obtainMessage(EVENT_POLL_CALLS_RESULT)獲取了Message消息對象,調用mCi.getCurrentCalls(mLastRelevantPoll)開始查詢Call List列表

RIL.java

@Override
    public void getCurrentCalls(Message result) {
        IRadio radioProxy = getRadioProxy(result);//區別與7.0的代碼,獲取一個Radio代理進行通信
        if (radioProxy != null) {
            RILRequest rr = obtainRequest(RIL_REQUEST_GET_CURRENT_CALLS, result,
                    mRILDefaultWorkSource);//創建一個請求消息
            if (RILJ_LOGD) {
                riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
            }
            try {
                radioProxy.getCurrentCalls(rr.mSerial);//向底層發起請求
            } catch (RemoteException | RuntimeException e) {
                handleRadioProxyExceptionForRR(rr, "getCurrentCalls", e);
            }
        }
    }

    在RIL完成查詢Call List列表後,發起EVENT_POLL_CALL_RESULT類型的Handler消息,最終調用handlePollCalls()方法.

由於handlePollCalls()方法邏輯太多所以不展示於此

 

主動發起請求:

GsmCdmaCallTracker對象向RILJ對象發起兩次請求第一次發起管理或者控制通話請求,第二次發起查詢當前通話列表請求(就是獲取Call Lit)。  RILJ對象處理的兩次請求並且發起兩次處理的結果的Callback消息回調,兩次消息回調的Handler類型分別是EVENT_OPENACTION_COMPLETE 和 ENENT_POLL_CALLS_RESULT

 

 

被動接收

我們被動接收或者主動下發,首先我們先看一下GsmCdmaCallTracker裏面的構造方法,他內部註冊了三個消息:

public GsmCdmaCallTracker (GsmCdmaPhone phone) {
        this.mPhone = phone;
        mCi = phone.mCi;
        mCi.registerForCallStateChanged(this, EVENT_CALL_STATE_CHANGE, null);//註冊EVENT_CALL_STATE_CHANGE 狀態 通話狀態變化
        mCi.registerForOn(this, EVENT_RADIO_AVAILABLE, null);                //EVENT_RADIO_AVAILABLE無線通信模塊可用狀態
        mCi.registerForNotAvailable(this, EVENT_RADIO_NOT_AVAILABLE, null);  //EVENT_RADIO_NOT_AVAILABLE 無線通信模塊不可用狀態
        .......
    }

這裏向RILJ註冊了三種類型的Handler消息,我們這裏只看EVENT_CALL_STATE_CHANGE狀態

先來看一下初始化註冊流程圖:

 

這一塊開機啓動TeleService的過程就會註冊這些Hanler就拿EVENT_CALL_STATE_CHANGE變化狀態。

 

接下來我們來看一下被動接收Handle消息
首先來看一下流程圖:

 

 

被動接收通話狀態變化的消息處理流程,僅僅只表現在RILJ與GsmCdmaCallTracker兩個對象之間的交互流程,共有兩次交互過程:

  • 第一次交互過程
    RILJ對象向GsmCdmaCallTracker對象發起了EVENT_CALL_STATE_CHANGE類型的Handler Callback消息通知。
  • 第二次交互過程
    GsmCdmaCallTracker對象調用mCi.getCurrentCalls方法,採用Handler消息回調的處理方式查詢當前最新的Call List列表
  1. 步驟一,Radio的回調
  2. 步驟二,通知GsmCdmaCallTracker中的Handler,他註冊的位置可以查看上面從初始化流程。
  3. 步驟三,進入Handler Message攜帶這一個EVENT_CALL_STATE_CHANGE消息進行匹配選擇 Handle內部會調用pollCallsWhenSafe()方法
  4. 步驟四,調用父類的CallTracker 裏面的pollCallWhenSafe()方法首先會生成EVENT_POLL_CALLS_RESULT類型的Handler消息消息對象,接着使用此對象作爲參數發起mCi.getCurrentCalls調用,向RILJ對象發出查詢最新的Call List列表消息
  5. 步驟五,mCi.getCurrentCalls調用,向RILJ對象發出查詢最新的Call List列表消息
  6. 步驟六,在RIL中完成查詢Call List列表後,發起EVENT_POLL_CALLS_RESULT類型的HandlerCallback消息回調
  7. 步驟七,GsmCdmaCallTracker對象最終調用handlerPollCalls方法響應EVENT_POLL_CALLS_RESULT類型的Handler消息

 

代碼流程:

GsmCdmaCallTracker.java
內部的Handler

 public void handleMessage(Message msg) {//接收並且處理RILJ發出的Handle消息 。handleMessge方法接收並響應RILJ對象發出的Handler消息。
        AsyncResult ar;
           switch (msg.what) {  
                ......
                case EVENT_CALL_STATE_CHANGE: //來電入口 通話狀態改變 等等....
                    pollCallsWhenSafe();
                break;
                .......
                .........
}

這裏對應着步驟三     進入pollCallsWhenSafe()方法

CallTracker.java

/**
     * 當Voice Call狀態和Radio狀態發生改變是,RILJ對象會向GsmCdmaCallTracker對象發出三個( EVENT_CALL_STATE_CHANGE , EVENT_RADIO_AVAILABLE ,EVENT_RADIO_NOT_AVAILABLE)
     * 對應的Handle消息;GsmCdmaCallTracker對象接收到這三個類型的Handler消息後,最後創建一個Message消息對象,在調用mCi.getCurrentCalls()方法,
     * 向RILJ對象查詢當前Call List(通話列表)。
     */
    protected void pollCallsWhenSafe() { //向RIL發起getCurrentCalls查詢CallList調用
        mNeedsPoll = true;
        if (checkNoOperationsPending()) {
            mLastRelevantPoll = obtainMessage(EVENT_POLL_CALLS_RESULT);//創建Message消息對象
            //去查詢當前的Call情況,此方法會調用到RIL中對應的方法去(Phone 創建的時候對mCi進行初始化,使得具有RIL通信功能,其mCi就調用的是RIL.java)
            mCi.getCurrentCalls(mLastRelevantPoll); //這裏攜帶這一個消息 EVENT_POLL_CALLS_RESULT 獲取Call List
        }
    }

調用父類的CallTracker 裏面的pollCallWhenSafe()方法首先會生成EVENT_POLL_CALLS_RESULT類型的Handler消息消息對象,接着使用此對象作爲參數發起mCi.getCurrentCalls調用,向RILJ對象發出查詢最新的Call List列表消息

 

 public void handleMessage(Message msg) {//接收並且處理RILJ發出的Handle消息 。handleMessge方法接收並響應RILJ對象發出的Handler消息。
        AsyncResult ar;
        switch (msg.what) {
            case EVENT_POLL_CALLS_RESULT:
                Rlog.d(LOG_TAG, "Event EVENT_POLL_CALLS_RESULT Received");
                Log.v("TelephonyFlowsendAck","GsmCdmaCallTracker  handleMessage EVENT_POLL_CALLS_RESULT 處理4種狀態後,通知 phone 更新狀態。");
                if (msg == mLastRelevantPoll) {
                    if (DBG_POLL) log(
                            "handle EVENT_POLL_CALL_RESULT: set needsPoll=F");
                    mNeedsPoll = false;
                    mLastRelevantPoll = null;
                    handlePollCalls((AsyncResult)msg.obj);//handlePollCalls 處理4種狀態後,通知 phone 更新狀態。
                }
            break;
        }
}

這裏對應着組後一步

 

 

結語:
這篇文章爲了提高TelephonyFramework的流程收悉度,特此做筆記記下來,如果有問題請提出做修改,也可以討論噢,謝謝!

發佈了245 篇原創文章 · 獲贊 645 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章