4.2.1. 5.0 SIP呼叫MO流程
SIP MO呼叫流程如下图所示(为了便于看清,分两段截图):
3.6.2.1. SIP呼叫App层处理流程
SIP呼叫在App层的处理流程和普通呼叫流程一样,只是号码uri的参数scheme不一样。
3.6.2.2. SIP呼叫telecom层处理流程
在telecom层,SIP呼叫和普通呼叫不同的地方开始于ConnectionService。
在ConnectionService服务端,onCreateOutgoingConnection会被调用到,这个方法被SipConnectionService重写,TelephonyConnectionService是ConnectionService的子类和最终要实例化的类,所以ConnectionService实例的onCreateOutgoingConnection方法在TelephonyConnectionService执行,这个方法代码较多,最终它会调用 placeOutgoingConnection(),需要注意的是其中的phone实例的获取,对于普通的呼叫,其实例是GSMPhone或CDMAPhone,对于IMS呼叫,其实例是IMSPhone,这会决定到后面的调用流程,关于Phone实例的获取,有兴趣可以自行研究。
public Connection onCreateOutgoingConnection( PhoneAccountHandle connectionManagerPhoneAccount, final ConnectionRequest request) { … final Phone phone = getPhoneForAccount(request.getAccountHandle(), isEmergencyNumber); … final TelephonyConnection connection = createConnectionFor(phone, null, true /* isOutgoing */); … placeOutgoingConnection(connection, phone, request); } |
在ConnectionService端,onCreateOutgoingConnection会被调用到,这个方法被SipConnectionService重写,SipConnectionService是ConnectionService的子类和最终要实例化的类,所以ConnectionService实例的onCreateOutgoingConnection方法在SipConnectionService执行,这个方法里会创建一个SipConnection实例,再调用 createConnectionForProfile(),
createConnectionForProfile则获取到SipPhone实例,然后调用startCallWithPhone,startCallWithPhone代码如下,它通过Phone.dial进行拨号,并返回一个com.android.internal.telephony.Connection类型的连接,
private void placeOutgoingConnection(
TelephonyConnection connection, Phone phone, ConnectionRequest request) {…
originalConnection = phone.dial(number, request.getVideoState());
…
if (originalConnection == null) {…
} else {
connection.setOriginalConnection(originalConnection);
}
}
3.6.2.3. SIP呼叫流程SipPhone层
SipPhone.dail设置当前状态为DIALING,调用SipManager.makeAudioCall进行呼叫,并设置监听器,
void dial() throws SipException { setState(Call.State.DIALING); mSipAudioCall = mSipManager.makeAudioCall(mProfile, mPeer, null, TIMEOUT_MAKE_CALL); mSipAudioCall.setListener(mAdapter); } |
SipManager的makeAudioCall则新建一个SipAudioCall实例,同时创建一个SipSession实例,并使用SipAudioCall.makeCall进行呼叫,
public SipAudioCall makeAudioCall(SipProfile localProfile, SipProfile peerProfile, SipAudioCall.Listener listener, int timeout) throws SipException { if (!isVoipSupported(mContext)) { throw new SipException("VOIP API is not supported"); } SipAudioCall call = new SipAudioCall(mContext, localProfile); call.setListener(listener); SipSession s = createSipSession(localProfile, null); call.makeCall(peerProfile, s, timeout); return call; } |
后者会调用sipSession.makeCall,这里的处理方式和IMS呼叫比较相似。
3.6.2.4. SIP呼叫流程Sip接口层
SipSession.makeCall则使用了一个AIDL接口ISipSession,ISipSession接口的实现是在SipSessionGroup.java,(frameworks\opt\net\voip\src\java \com\android\server\sip),
class SipSessionGroup implements SipListener { … class SipSessionImpl extends ISipSession.Stub { … public void makeCall(SipProfile peerProfile, String sessionDescription, int timeout) { doCommandAsync(new MakeCallCommand(peerProfile, sessionDescription, timeout)); } …} } |
这里调用doCommandAsync,进而启动一个线程,执行processCommand,再到process,根据SipSession.State,我们选择READY_TO_CALL,
public boolean process(EventObject evt) throws SipException { … switch (mState) { case SipSession.State.REGISTERING: case SipSession.State.DEREGISTERING: processed = registeringToReady(evt); break; case SipSession.State.READY_TO_CALL: processed = readyForCall(evt); break; case SipSession.State.INCOMING_CALL: processed = incomingCall(evt); break; case SipSession.State.INCOMING_CALL_ANSWERING: processed = incomingCallToInCall(evt); break; case SipSession.State.OUTGOING_CALL: case SipSession.State.OUTGOING_CALL_RING_BACK: processed = outgoingCall(evt); break; case SipSession.State.OUTGOING_CALL_CANCELING: processed = outgoingCallToReady(evt); break; case SipSession.State.IN_CALL: processed = inCall(evt); break; case SipSession.State.ENDING_CALL: processed = endingCall(evt); break; default: processed = false; } return (processed || processExceptions(evt)); } } } |
在readyForCall()方法里面,根据事件类型是MakeCallCommand,我们判断执行的代码如下,主要是使用mSipHelper.sendInvite向SIP协议栈发起呼叫请求,再进行本地会话管理,最后通过监听器通知状态变化。
private boolean readyForCall(EventObject evt) throws SipException { // expect MakeCallCommand, RegisterCommand, DEREGISTER if (evt instanceof MakeCallCommand) { mState = SipSession.State.OUTGOING_CALL; MakeCallCommand cmd = (MakeCallCommand) evt; mPeerProfile = cmd.getPeerProfile(); if (mReferSession != null) { mSipHelper.sendReferNotify(mReferSession.mDialog, getResponseString(Response.TRYING)); } mClientTransaction = mSipHelper.sendInvite( mLocalProfile, mPeerProfile, cmd.getSessionDescription(), generateTag(), mReferredBy, mReplaces); mDialog = mClientTransaction.getDialog(); addSipSession(this); startSessionTimer(cmd.getTimeout()); mProxy.onCalling(this); return true; } … |
后续就是sip协议栈的响应处理,有兴趣可以研究sip协议栈的流程和内容。