summaryrefslogtreecommitdiffstats
path: root/voip/java
diff options
context:
space:
mode:
authorrepo sync <cywang@google.com>2011-06-23 19:40:36 +0800
committerrepo sync <cywang@google.com>2011-06-27 16:20:28 +0800
commit1aceda35cc607856ec2e960e0c6cfc6aea87ab8e (patch)
treedf58a646008282041c3f1e1b959a888e01f0f6fe /voip/java
parent14f14863c508ff38fb2fe925c89e2bb2228fcffe (diff)
downloadframeworks_base-1aceda35cc607856ec2e960e0c6cfc6aea87ab8e.zip
frameworks_base-1aceda35cc607856ec2e960e0c6cfc6aea87ab8e.tar.gz
frameworks_base-1aceda35cc607856ec2e960e0c6cfc6aea87ab8e.tar.bz2
Support Invite w/ Replaces request.
bug:3326870 Change-Id: Idbfbe7e3cc6ba83874d42bfb7d149866f454e70a
Diffstat (limited to 'voip/java')
-rw-r--r--voip/java/android/net/sip/ISipSessionListener.aidl8
-rw-r--r--voip/java/android/net/sip/SipAudioCall.java57
-rw-r--r--voip/java/android/net/sip/SipSession.java21
-rw-r--r--voip/java/android/net/sip/SipSessionAdapter.java4
-rw-r--r--voip/java/com/android/server/sip/SipHelper.java2
-rw-r--r--voip/java/com/android/server/sip/SipSessionGroup.java89
-rw-r--r--voip/java/com/android/server/sip/SipSessionListenerProxy.java14
7 files changed, 180 insertions, 15 deletions
diff --git a/voip/java/android/net/sip/ISipSessionListener.aidl b/voip/java/android/net/sip/ISipSessionListener.aidl
index 5920bca..690700c 100644
--- a/voip/java/android/net/sip/ISipSessionListener.aidl
+++ b/voip/java/android/net/sip/ISipSessionListener.aidl
@@ -72,6 +72,14 @@ interface ISipSessionListener {
void onCallBusy(in ISipSession session);
/**
+ * Called when the call is being transferred to a new one.
+ *
+ * @param newSession the new session that the call will be transferred to
+ * @param sessionDescription the new peer's session description
+ */
+ void onCallTransferring(in ISipSession newSession, String sessionDescription);
+
+ /**
* Called when an error occurs during session initialization and
* termination.
*
diff --git a/voip/java/android/net/sip/SipAudioCall.java b/voip/java/android/net/sip/SipAudioCall.java
index b46f826..2666b69 100644
--- a/voip/java/android/net/sip/SipAudioCall.java
+++ b/voip/java/android/net/sip/SipAudioCall.java
@@ -170,6 +170,7 @@ public class SipAudioCall {
private SipProfile mLocalProfile;
private SipAudioCall.Listener mListener;
private SipSession mSipSession;
+ private SipSession mTransferringSession;
private long mSessionId = System.currentTimeMillis();
private String mPeerSd;
@@ -347,6 +348,27 @@ public class SipAudioCall {
}
}
+ private synchronized void transferToNewSession() {
+ if (mTransferringSession == null) return;
+ SipSession origin = mSipSession;
+ mSipSession = mTransferringSession;
+ mTransferringSession = null;
+
+ // stop the replaced call.
+ if (mAudioStream != null) {
+ mAudioStream.join(null);
+ } else {
+ try {
+ mAudioStream = new AudioStream(InetAddress.getByName(
+ getLocalIp()));
+ } catch (Throwable t) {
+ Log.i(TAG, "transferToNewSession(): " + t);
+ }
+ }
+ if (origin != null) origin.endCall();
+ startAudio();
+ }
+
private SipSession.Listener createListener() {
return new SipSession.Listener() {
@Override
@@ -404,6 +426,13 @@ public class SipAudioCall {
mPeerSd = sessionDescription;
Log.v(TAG, "onCallEstablished()" + mPeerSd);
+ // TODO: how to notify the UI that the remote party is changed
+ if ((mTransferringSession != null)
+ && (session == mTransferringSession)) {
+ transferToNewSession();
+ return;
+ }
+
Listener listener = mListener;
if (listener != null) {
try {
@@ -420,7 +449,17 @@ public class SipAudioCall {
@Override
public void onCallEnded(SipSession session) {
- Log.d(TAG, "sip call ended: " + session);
+ Log.d(TAG, "sip call ended: " + session + " mSipSession:" + mSipSession);
+ // reset the trasnferring session if it is the one.
+ if (session == mTransferringSession) {
+ mTransferringSession = null;
+ return;
+ }
+ // or ignore the event if the original session is being
+ // transferred to the new one.
+ if ((mTransferringSession != null) ||
+ (session != mSipSession)) return;
+
Listener listener = mListener;
if (listener != null) {
try {
@@ -489,6 +528,22 @@ public class SipAudioCall {
public void onRegistrationDone(SipSession session, int duration) {
// irrelevant
}
+
+ @Override
+ public void onCallTransferring(SipSession newSession,
+ String sessionDescription) {
+ Log.v(TAG, "onCallTransferring mSipSession:"
+ + mSipSession + " newSession:" + newSession);
+ mTransferringSession = newSession;
+ // session changing request
+ try {
+ String answer = createAnswer(sessionDescription).encode();
+ newSession.answerCall(answer, SESSION_TIMEOUT);
+ } catch (Throwable e) {
+ Log.e(TAG, "onCallTransferring()", e);
+ newSession.endCall();
+ }
+ }
};
}
diff --git a/voip/java/android/net/sip/SipSession.java b/voip/java/android/net/sip/SipSession.java
index 5629b3c..5ba1626 100644
--- a/voip/java/android/net/sip/SipSession.java
+++ b/voip/java/android/net/sip/SipSession.java
@@ -160,6 +160,17 @@ public final class SipSession {
}
/**
+ * Called when the call is being transferred to a new one.
+ *
+ * @hide
+ * @param newSession the new session that the call will be transferred to
+ * @param sessionDescription the new peer's session description
+ */
+ public void onCallTransferring(SipSession newSession,
+ String sessionDescription) {
+ }
+
+ /**
* Called when an error occurs during session initialization and
* termination.
*
@@ -489,6 +500,16 @@ public final class SipSession {
}
}
+ public void onCallTransferring(ISipSession session,
+ String sessionDescription) {
+ if (mListener != null) {
+ mListener.onCallTransferring(
+ new SipSession(session, SipSession.this.mListener),
+ sessionDescription);
+
+ }
+ }
+
public void onCallChangeFailed(ISipSession session, int errorCode,
String message) {
if (mListener != null) {
diff --git a/voip/java/android/net/sip/SipSessionAdapter.java b/voip/java/android/net/sip/SipSessionAdapter.java
index 86aca37..f538983 100644
--- a/voip/java/android/net/sip/SipSessionAdapter.java
+++ b/voip/java/android/net/sip/SipSessionAdapter.java
@@ -42,6 +42,10 @@ public class SipSessionAdapter extends ISipSessionListener.Stub {
public void onCallBusy(ISipSession session) {
}
+ public void onCallTransferring(ISipSession session,
+ String sessionDescription) {
+ }
+
public void onCallChangeFailed(ISipSession session, int errorCode,
String message) {
}
diff --git a/voip/java/com/android/server/sip/SipHelper.java b/voip/java/com/android/server/sip/SipHelper.java
index 018e6de..47950e3 100644
--- a/voip/java/com/android/server/sip/SipHelper.java
+++ b/voip/java/com/android/server/sip/SipHelper.java
@@ -314,7 +314,7 @@ class SipHelper {
}
}
- private ServerTransaction getServerTransaction(RequestEvent event)
+ public ServerTransaction getServerTransaction(RequestEvent event)
throws SipException {
ServerTransaction transaction = event.getServerTransaction();
if (transaction == null) {
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index 2d0dd9c..481e306 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -21,6 +21,8 @@ import gov.nist.javax.sip.clientauthutils.UserCredentials;
import gov.nist.javax.sip.header.SIPHeaderNames;
import gov.nist.javax.sip.header.ProxyAuthenticate;
import gov.nist.javax.sip.header.WWWAuthenticate;
+import gov.nist.javax.sip.header.extensions.ReferredByHeader;
+import gov.nist.javax.sip.header.extensions.ReplacesHeader;
import gov.nist.javax.sip.message.SIPMessage;
import android.net.sip.ISipSession;
@@ -365,24 +367,85 @@ class SipSessionGroup implements SipListener {
super(listener);
}
+ private SipSessionImpl createNewSession(RequestEvent event,
+ ISipSessionListener listener, ServerTransaction transaction)
+ throws SipException {
+ SipSessionImpl newSession = new SipSessionImpl(listener);
+ newSession.mServerTransaction = transaction;
+ newSession.mState = SipSession.State.INCOMING_CALL;
+ newSession.mDialog = newSession.mServerTransaction.getDialog();
+ newSession.mInviteReceived = event;
+ newSession.mPeerProfile = createPeerProfile(event.getRequest());
+ newSession.mPeerSessionDescription =
+ extractContent(event.getRequest());
+ return newSession;
+ }
+
+ private int processInviteWithReplaces(RequestEvent event,
+ ReplacesHeader replaces) {
+ String callId = replaces.getCallId();
+ SipSessionImpl session = mSessionMap.get(callId);
+ if (session == null) {
+ return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
+ }
+
+ Dialog dialog = session.mDialog;
+ if (dialog == null) return Response.DECLINE;
+
+ if (!dialog.getLocalTag().equals(replaces.getToTag()) ||
+ !dialog.getRemoteTag().equals(replaces.getFromTag())) {
+ // No match is found, returns 481.
+ return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
+ }
+
+ ReferredByHeader referredBy = (ReferredByHeader) event.getRequest()
+ .getHeader(ReferredByHeader.NAME);
+ if ((referredBy == null) ||
+ !dialog.getRemoteParty().equals(referredBy.getAddress())) {
+ return Response.CALL_OR_TRANSACTION_DOES_NOT_EXIST;
+ }
+ return Response.OK;
+ }
+
+ private void processNewInviteRequest(RequestEvent event)
+ throws SipException {
+ ReplacesHeader replaces = (ReplacesHeader) event.getRequest()
+ .getHeader(ReplacesHeader.NAME);
+ SipSessionImpl newSession = null;
+ if (replaces != null) {
+ int response = processInviteWithReplaces(event, replaces);
+ if (DEBUG) {
+ Log.v(TAG, "ReplacesHeader: " + replaces
+ + " response=" + response);
+ }
+ if (response == Response.OK) {
+ SipSessionImpl replacedSession =
+ mSessionMap.get(replaces.getCallId());
+ // got INVITE w/ replaces request.
+ newSession = createNewSession(event,
+ replacedSession.mProxy.getListener(),
+ mSipHelper.getServerTransaction(event));
+ newSession.mProxy.onCallTransferring(newSession,
+ newSession.mPeerSessionDescription);
+ } else {
+ mSipHelper.sendResponse(event, response);
+ }
+ } else {
+ // New Incoming call.
+ newSession = createNewSession(event, mProxy,
+ mSipHelper.sendRinging(event, generateTag()));
+ mProxy.onRinging(newSession, newSession.mPeerProfile,
+ newSession.mPeerSessionDescription);
+ }
+ if (newSession != null) addSipSession(newSession);
+ }
+
public boolean process(EventObject evt) throws SipException {
if (isLoggable(this, evt)) Log.d(TAG, " ~~~~~ " + this + ": "
+ SipSession.State.toString(mState) + ": processing "
+ log(evt));
if (isRequestEvent(Request.INVITE, evt)) {
- RequestEvent event = (RequestEvent) evt;
- SipSessionImpl newSession = new SipSessionImpl(mProxy);
- newSession.mState = SipSession.State.INCOMING_CALL;
- newSession.mServerTransaction = mSipHelper.sendRinging(event,
- generateTag());
- newSession.mDialog = newSession.mServerTransaction.getDialog();
- newSession.mInviteReceived = event;
- newSession.mPeerProfile = createPeerProfile(event.getRequest());
- newSession.mPeerSessionDescription =
- extractContent(event.getRequest());
- addSipSession(newSession);
- mProxy.onRinging(newSession, newSession.mPeerProfile,
- newSession.mPeerSessionDescription);
+ processNewInviteRequest((RequestEvent) evt);
return true;
} else if (isRequestEvent(Request.OPTIONS, evt)) {
mSipHelper.sendResponse((RequestEvent) evt, Response.OK);
diff --git a/voip/java/com/android/server/sip/SipSessionListenerProxy.java b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
index f8be0a8..8655a3a 100644
--- a/voip/java/com/android/server/sip/SipSessionListenerProxy.java
+++ b/voip/java/com/android/server/sip/SipSessionListenerProxy.java
@@ -110,6 +110,20 @@ class SipSessionListenerProxy extends ISipSessionListener.Stub {
});
}
+ public void onCallTransferring(final ISipSession newSession,
+ final String sessionDescription) {
+ if (mListener == null) return;
+ proxy(new Runnable() {
+ public void run() {
+ try {
+ mListener.onCallTransferring(newSession, sessionDescription);
+ } catch (Throwable t) {
+ handle(t, "onCallTransferring()");
+ }
+ }
+ });
+ }
+
public void onCallBusy(final ISipSession session) {
if (mListener == null) return;
proxy(new Runnable() {