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列表
- 步驟一,Radio的回調
- 步驟二,通知GsmCdmaCallTracker中的Handler,他註冊的位置可以查看上面從初始化流程。
- 步驟三,進入Handler Message攜帶這一個EVENT_CALL_STATE_CHANGE消息進行匹配選擇 Handle內部會調用pollCallsWhenSafe()方法
- 步驟四,調用父類的CallTracker 裏面的pollCallWhenSafe()方法首先會生成EVENT_POLL_CALLS_RESULT類型的Handler消息消息對象,接着使用此對象作爲參數發起mCi.getCurrentCalls調用,向RILJ對象發出查詢最新的Call List列表消息
- 步驟五,mCi.getCurrentCalls調用,向RILJ對象發出查詢最新的Call List列表消息
- 步驟六,在RIL中完成查詢Call List列表後,發起EVENT_POLL_CALLS_RESULT類型的HandlerCallback消息回調
- 步驟七,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;
}
}
這裏對應着組後一步