其中涉及到3个变量的处理:
protected int pendingOperations;
protected boolean needsPoll;
protected Message lastRelevantPoll;
pendingOperations:顾名思义,这个变量是在发生请求的时候会++,在处理应答的时候会--。
needsPoll:该变量是用来配合pendingOperations处理是否需要从RIL获取当前calls列表,并更新connections列表。
lastRelevantPoll:在发送RIL_REQUEST_GET_CURRENT_CALLS的时候记录最近一次请求的message,在response的时候只对最近一次请求的response做出响应,更新connections列表。
上面的3个变量主要是用来判断是否需要发送RIL_REQUEST_GET_CURRENT_CALLS请
求来从RIL获取当前的calls列表,并更新connections列表。
候,用户有可能会继续的发送对应的请求,然后会有多个response同时上报过来,上
GsmCallTracker事件处理的核心是一个异步事件的处理,在发送请求后等待回应的时
面的3个变量主要是为了更好的处理这种情况,不管用户发送了多少次请求,
pendingOperations都会记录下来;而且只要用户发送了一次请求,needsPoll就为true,即就需要从RIL获取最新的call列表。所以只有当pendingOperations==0 并且 needsPoll == true的时候才发送RIL_REQUEST_GET_CURRENT_CALLS请求
去获取Calls列表。
if (pendingOperations == 0 && needsPoll) {
lastRelevantPoll= obtainMessage(EVENT_POLL_CALLS_RESULT); cm.getCurrentCalls(lastRelevantPoll); }
由于中间可能发送了多次RIL_REQUEST_GET_CURRENT_CALLS请求,在多次发送此请
求的过程中却没有一次response回来,最后的结果是到最后肯定会有多个response上来,而此时我们只需要更新一次就够了,lastRelevantPoll就是用来处理这个事情的:lastRelevantPoll记录了最近一次发送
RIL_REQUEST_GET_CURRENT_CALLS请求时的response message,当返回的response message是最后一个时就更新Connections列表。
4) GsmCallTracker的核心处理方法----更新connections列表处理方法
protected void handlePollCalls(AsyncResult ar)的处理分析
handlePollCalls(AsyncResult ar) { List polledCalls;
if(DBG_POLL) log(\);
if (ar.exception == null) { //没有异常,取得calllists列表
polledCalls = (List)ar.result;
} else if (isCommandExceptionRadioNotAvailable(ar.exception)) {
//如果radio是RADIO_NOT_AVAILABLE,则挂断所有的calls,这里的意思是所有的
DriverCall是null。
polledCalls = new ArrayList();
} else {
//其他的异常的话,推迟POLL_DELAY_MSEC = 250后再发送//RIL_REQUEST_GET_CURRENT_CALLS去获取DriverCall列表。
pollCallsAfterDelay(); return; }
Connection newRinging = null; //or waiting
boolean hasNonHangupStateChanged = false; // Any change besides // a dropped connection boolean needsPollDelay = false;
boolean unknownConnectionAppeared = false;
//遍历DriverCall和Connections,根据不同情况做相应处理。
for (int i = 0, curDC = 0, dcSize = polledCalls.size()
; i < connections.length; i++) { GsmConnection conn = connections[i]; DriverCall dc = null;
// polledCall list is sparse if (curDC < dcSize) {
dc = (DriverCall) polledCalls.get(curDC);
//此处说明connections数组的index+1就是callId,也即dc.index。 if (dc.index == i+1) { curDC++; } else { dc = null; } }
if (conn == null && dc != null) {
//conn为null,说明CallTracker中是没有对应的call的,这只有两种情况可以
//发生:MO的dialing状态和MT的incoming/waiting状态。打电话和来电的时候
//会执行到此处。
} else if (conn != null && dc == null) {
//说明在底层已经挂掉了,CallTracker需要drop该connection。对方挂断电话//的时候就会执行到此处。
} else if (conn != null && dc != null && !conn.compareTo(dc)) { //此处说明对应的connection和dc并不是同一个call,这种情况下就需要drop //当前的connection并根据dc重新构建一个。此处应该是一个异常的处理情况。
} else if (conn != null && dc != null) {
//此处表明connection和dc是同一个call,随后根据dc来更新connection。 }
if (REPEAT_POLLING) {} }
if (pendingMO != null) {
//此时dial请求已经发送给ril但是对应的response还没有上来的情况。正常情况
//下,到此时pengdingMO应该为null了,但是假如在dial后的response还没有上
//来的时候做了其他动作,如hangup call,则此时很可能就执行到此处。
droppedDuringPoll.add(pendingMO); pendingMO = null;
hangupPendingMO = false; }
if (newRinging != null) {
//表示是一个MT call,需要通知用户。
phone.notifyNewRingingConnection(newRinging); }
// clear the \ // cases from the \ // These cases need no \
for (int i = droppedDuringPoll.size() - 1; i >= 0 ; i--) { GsmConnection conn = droppedDuringPoll.get(i);
if (conn.isIncoming() && conn.getConnectTime() == 0) { // Missed or rejected call
Connection.DisconnectCause cause;
if (conn.cause == Connection.DisconnectCause.LOCAL) { cause = Connection.DisconnectCause.INCOMING_REJECTED; } else {
cause = Connection.DisconnectCause.INCOMING_MISSED; }
droppedDuringPoll.remove(i); conn.onDisconnect(cause);
} else if (conn.cause == Connection.DisconnectCause.LOCAL) { // Local hangup
droppedDuringPoll.remove(i);
conn.onDisconnect(Connection.DisconnectCause.LOCAL); } else if (conn.cause ==
Connection.DisconnectCause.INVALID_NUMBER) { droppedDuringPoll.remove(i);
conn.onDisconnect(Connection.DisconnectCause.INVALID_NUMBER);
} }
// Any non-local disconnects: determine cause
if (droppedDuringPoll.size() > 0) {
//本地挂断都是DisconnectCause.LOCAL,此处表明是对方或网络端的挂断,具体//挂断原因需要从RIL处获得。
cm.getLastCallFailCause(
obtainNoPollCompleteMessage(EVENT_GET_LAST_CALL_FAIL_CAUSE));
}
if (needsPollDelay) { pollCallsAfterDelay(); }
// Cases when we can no longer keep disconnected Connection's // with their previous calls
// 1) the phone has started to ring
// 2) A Call/Connection object has changed state...
// we may have switched or held or answered (but not hung up) if (newRinging != null || hasNonHangupStateChanged) { internalClearDisconnected(); }
更新Phone的状态。
updatePhoneState();
if (unknownConnectionAppeared) { phone.notifyUnknownConnection(); }
if (hasNonHangupStateChanged || newRinging != null) { //通知用户callstatechange。
phone.notifyPreciseCallStateChanged(); }
if(DBG_POLL) log(\); //dumpState(); }
Call处理中的内部接口就是PhoneUtils,它提供的主要接口如下: setAudioControlState(int) answerCall(Phone) hangup(Phone)
hangupRingingCall(Phone) hangupActiveCall(Phone) hangupHoldingCall(Phone)
hangupRingingAndActive(Phone) hangupAllCalls(Phone) hangup(Call)
hangupAllConnections(Call) hangup(Connection)
answerAndEndHolding(Phone) answerAndEndActive(Phone) placeCall(Phone, String, Uri)
placeCallVia(Context, Phone, String, Uri, Uri) switchHoldingAndActive(Phone) mergeCalls(Phone)
isConferenceCall(Call) showIncomingCallUi(int)
turnOnSpeaker(Context, boolean, boolean) restoreSpeakerMode(Context) isSpeakerOn(Context)
turnOnNoiseSuppression(Context, boolean, boolean) restoreNoiseSuppression(Context) setMute(Phone, boolean) getMute(Phone)
setAudioMode(Context, int) okToSwapCalls(Phone) okToMergeCalls(Phone) okToAddCall(Phone)
外部进程或应用需要使用call时,如hardware键接听和挂断电话等,此时的接口是PhoneInterfaceManager类所提供,此类继承自ITelephony.Stub,是aidl接口。
PhoneUtils中有一个static子类:ConnectionHandler,其主要是用来处理Mute设置相关的,其中主要是更新sConnectionMuteTable并根据当前phone的状态来控制mute设置。