GsmCdmaCallTracker与RILJ对象的交互完成的通话控制,以及通话状态和通话基本信息的保存,更新等操作,交互方式不用说就知道有两类:
接下来讲解一下我理解的流程:
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两个对象之间的交互流程,共有两次交互过程:
代码流程:
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;
}
}
这里对应着组后一步