3,远程挂断电话流程分析
3.1 services Telephony
当远程挂断/拒接电话时,GsmCallTracker的handlePollCalls 方法有关代码如下,
if (mDroppedDuringPoll.size() > 0) {
mCi.getLastCallFailCause(
obtainNoPollCompleteMessage(EVENT_GET_LAST_CALL_FAIL_CAUSE));
}
由于不是主动发起的挂断流程,因此会向RIL发送消息获取通话断开的cause,
RIL的getLastCallFailCause方法如下,
public void getLastCallFailCause (Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_LAST_CALL_FAIL_CAUSE, result);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
注意,此时封装了EVENT_GET_LAST_CALL_FAIL_CAUSE消息。
向ril库发送RIL_REQUEST_LAST_CALL_FAIL_CAUSE消息,ril处理查询完成之后,返回上报结果, processSolicited方法中
对该消息处理如下,
1,读取消息处理结果,
case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: ret = responseFailCause(p); break;
responseFailCause方法如下,
private Object responseFailCause(Parcel p) {
LastCallFailCause failCause = new LastCallFailCause();
failCause.causeCode = p.readInt();
if (p.dataAvail() > 0) {
failCause.vendorCause = p.readString();
}
return failCause;
}
返回的是LastCallFailCause对象。
2,分发消息给对应的注册类处理,
if (rr.mResult != null) {
AsyncResult.forMessage(rr.mResult, ret, null);
rr.mResult.sendToTarget();
}
GsmCallTracker的handleMessage方法中对EVENT_GET_LAST_CALL_FAIL_CAUSE消息处理如下,
1,首先获取结果,也就是断开的原因,
LastCallFailCause failCause = (LastCallFailCause)ar.result;
causeCode = failCause.causeCode;
vendorCause = failCause.vendorCause;
2,调用GsmConnection的onRemoteDisconnect继续处理,
for (int i = 0, s = mDroppedDuringPoll.size(); i < s ; i++ ) {
GsmConnection conn = mDroppedDuringPoll.get(i);
conn.onRemoteDisconnect(causeCode, vendorCause);
}
updatePhoneState();//更新phone状态
mPhone.notifyPreciseCallStateChanged();
mDroppedDuringPoll.clear();
GsmConnection的onRemoteDisconnect方法调用流程图如下,
onRemoteDisconnect方法如下,
void onRemoteDisconnect(int causeCode, String vendorCause) {
this.mPreciseCause = causeCode;
this.mVendorCause = vendorCause;
onDisconnect(disconnectCauseFromCode(causeCode));
}
在onDisconnect方法中,又会调用GSMPhone的notifyDisconnect方法,该方法如下,
void notifyDisconnect(Connection cn) {
mDisconnectRegistrants.notifyResult(cn);
mNotifier.notifyDisconnectCause(cn.getDisconnectCause(), cn.getPreciseDisconnectCause());
}
在父类PhoneBase中注册mDisconnectRegistrants的方法为registerForDisconnect,
public void registerForDisconnect(Handler h, int what, Object obj) {
checkCorrectThread(h);
mDisconnectRegistrants.addUnique(h, what, obj);
}
同样的, TelephonyConnection的setOriginalConnection方法中调用了PhoneBase的registerForDisconnect方法,
getPhone().registerForDisconnect(mHandler, MSG_DISCONNECT, null);
TelephonyConnection的内部变量mHandler的handleMessage方法对该消息处理如下,
case MSG_DISCONNECT:
updateState();
break;
调用带参数的updateState方法,
void updateState() {
updateState(false);
}
updateState方法如下,
1,获取当前的Call状态,
Call.State newState = mOriginalConnection.getState();
2,根据状态分别进行处理,
switch (newState) {
case IDLE:
break;
case ACTIVE:
•••
如果是断开状态,调用setDisconnected方法进一步处理,
setDisconnected(DisconnectCauseUtil.toTelecomDisconnectCause(
mOriginalConnection.getDisconnectCause(),
mOriginalConnection.getVendorDisconnectCause()));
3,更新信息已经相关状态,
updateStatusHints();
updateConnectionCapabilities();
updateAddress();
updateMultiparty();
setDisconnected方法在父类Connection中实现,如下,
public final void setDisconnected(DisconnectCause disconnectCause) {
checkImmutable();
mDisconnectCause = disconnectCause;
setState(STATE_DISCONNECTED);
Log.d(this, "Disconnected with cause %s", disconnectCause);
for (Listener l : mListeners) {
l.onDisconnected(this, disconnectCause);
}
}
mListeners变量中保存了所有注册的监听器,
private final Set<Listener> mListeners = Collections.newSetFromMap(
new ConcurrentHashMap<Listener, Boolean>(8, 0.9f, 1));
并且是在addConnectionListener方法中添加监听器的,
public final Connection addConnectionListener(Listener l) {
mListeners.add(l);
return this;
}
再看ConnectionService的addConnection方法,
private void addConnection(String callId, Connection connection) {
mConnectionById.put(callId, connection);
mIdByConnection.put(connection, callId);
connection.addConnectionListener(mConnectionListener);
connection.setConnectionService(this);
}
调用了Connection的addConnectionListener方法注册mConnectionListener变量,
因此当Connection中的setDisconnected调用监听器的onDisconnected方法时,会调用ConnectionService的
mConnectionListener的onDisconnected方法。
在此注意的是, ConnectionService只是一个抽象类,其实运行的是子类TelephonyConnectionService。还是在
services Telephony进程中,并没有跨进程调用。
ConnectionService的mConnectionListener变量是一个匿名内部类,
private final Connection.Listener mConnectionListener = new Connection.Listener() {
其onDisconnected方法如下,
public void onDisconnected(Connection c, DisconnectCause disconnectCause) {
String id = mIdByConnection.get(c);
Log.d(this, "Adapter set disconnected %s", disconnectCause);
mAdapter.setDisconnected(id, disconnectCause);
}
ConnectionServiceAdapter的setDisconnected方法如下,
void setDisconnected(String callId, DisconnectCause disconnectCause) {
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
adapter.setDisconnected(callId, disconnectCause);
} catch (RemoteException e) {
}
}
}
Adapter其实是一个跨进程调用, adapter 指services telecom进程中的ConnectionServiceWrapper的内部类Adapter。
3.2 services telecom
ConnectionServiceWrapper的内部类Adapter定义如下,
private final class Adapter extends IConnectionServiceAdapter.Stub {
调用流程图如下,
Adapter的setDisconnected方法如下,
if (call != null) {
mCallsManager.markCallAsDisconnected(call, disconnectCause);
}
CallsManager的setCallState方法如下,
if (mCalls.contains(call)) {
for (CallsManagerListener listener : mListeners) {
if (Log.SYSTRACE_DEBUG) {
Trace.beginSection(listener.getClass().toString() + " onCallStateChanged");
}
listener.onCallStateChanged(call, oldState, newState);
if (Log.SYSTRACE_DEBUG) {
Trace.endSection();
}
}
updateCallsManagerState();
}
调用监听器的onCallStateChanged方法更新界面。