Android 5.0 呼叫流程--SIP呼出
来源:互联网 发布:php sae环境 编辑:程序博客网 时间:2024/06/01 19:33
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协议栈的流程和内容。
- Android 5.0 呼叫流程--SIP呼出
- Android 5.0 呼叫流程--呼出
- Android 5.0 呼叫流程--呼出
- Android 5.0 呼叫流程--呼出
- SIP基本呼叫流程
- SIP呼叫流程
- SIP基本呼叫流程
- Android 5.0 呼叫流程
- SIP呼叫种类及流程
- SIP用户呼叫流程分析
- sip协议呼叫流程详解
- 【SIP基础】SIP协议基本呼叫流程
- Android 5.0 呼叫流程--呼入
- Android Sip学习—SIP 协议完整的呼叫流程(准备知识)
- Android Sip学习(准备知识)SIP 协议完整的呼叫流程
- SIP呼叫流程典型流程图解
- 一个简单的SIP呼叫建立流程
- SIP协议呼叫流程及协议分析
- 常用awk命令(转)
- (转载)Android Fragment 真正的完全解析(上)
- sgu 187
- linux 命令系列之 useradd(24)
- 玩命牛的成长记录(十二)——sql注入和session
- Android 5.0 呼叫流程--SIP呼出
- Sublime下python 报错[Decode error - output not utf-8]解决办法
- ubuntu修改用户名、计算机名、主目录名
- linux 命令系列之 passwd(25)
- MFC 中ComboBox的 Data属性设置多行选项
- 开课第一天
- DFS深度优先搜索之lake counting
- Jpeg 库的解码OpenCL优化
- Android Studio安装时的注意点