Merge "Add timer to SIP session creation process." into gingerbread
This commit is contained in:
committed by
Android (Google) Code Review
commit
9404e633a5
@@ -84,7 +84,8 @@ class SipSessionGroup implements SipListener {
|
|||||||
private static final boolean DEBUG_PING = DEBUG && false;
|
private static final boolean DEBUG_PING = DEBUG && false;
|
||||||
private static final String ANONYMOUS = "anonymous";
|
private static final String ANONYMOUS = "anonymous";
|
||||||
private static final String SERVER_ERROR_PREFIX = "Response: ";
|
private static final String SERVER_ERROR_PREFIX = "Response: ";
|
||||||
private static final int EXPIRY_TIME = 3600;
|
private static final int EXPIRY_TIME = 3600; // in seconds
|
||||||
|
private static final int CANCEL_CALL_TIMER = 5; // in seconds
|
||||||
|
|
||||||
private static final EventObject DEREGISTER = new EventObject("Deregister");
|
private static final EventObject DEREGISTER = new EventObject("Deregister");
|
||||||
private static final EventObject END_CALL = new EventObject("End call");
|
private static final EventObject END_CALL = new EventObject("End call");
|
||||||
@@ -363,6 +364,40 @@ class SipSessionGroup implements SipListener {
|
|||||||
String mPeerSessionDescription;
|
String mPeerSessionDescription;
|
||||||
boolean mInCall;
|
boolean mInCall;
|
||||||
boolean mReRegisterFlag = false;
|
boolean mReRegisterFlag = false;
|
||||||
|
SessionTimer mTimer;
|
||||||
|
|
||||||
|
// lightweight timer
|
||||||
|
class SessionTimer {
|
||||||
|
private boolean mRunning = true;
|
||||||
|
|
||||||
|
void start(final int timeout) {
|
||||||
|
new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
sleep(timeout);
|
||||||
|
if (mRunning) timeout();
|
||||||
|
}
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized void cancel() {
|
||||||
|
mRunning = false;
|
||||||
|
this.notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void timeout() {
|
||||||
|
synchronized (SipSessionGroup.this) {
|
||||||
|
onError(SipErrorCode.TIME_OUT, "Session timed out!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void sleep(int timeout) {
|
||||||
|
try {
|
||||||
|
this.wait(timeout * 1000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Log.e(TAG, "session timer interrupted!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public SipSessionImpl(ISipSessionListener listener) {
|
public SipSessionImpl(ISipSessionListener listener) {
|
||||||
setListener(listener);
|
setListener(listener);
|
||||||
@@ -382,6 +417,8 @@ class SipSessionGroup implements SipListener {
|
|||||||
mServerTransaction = null;
|
mServerTransaction = null;
|
||||||
mClientTransaction = null;
|
mClientTransaction = null;
|
||||||
mPeerSessionDescription = null;
|
mPeerSessionDescription = null;
|
||||||
|
|
||||||
|
cancelSessionTimer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isInCall() {
|
public boolean isInCall() {
|
||||||
@@ -434,16 +471,16 @@ class SipSessionGroup implements SipListener {
|
|||||||
}).start();
|
}).start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void makeCall(SipProfile peerProfile,
|
public void makeCall(SipProfile peerProfile, String sessionDescription,
|
||||||
String sessionDescription) {
|
int timeout) {
|
||||||
doCommandAsync(
|
doCommandAsync(new MakeCallCommand(peerProfile, sessionDescription,
|
||||||
new MakeCallCommand(peerProfile, sessionDescription));
|
timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void answerCall(String sessionDescription) {
|
public void answerCall(String sessionDescription, int timeout) {
|
||||||
try {
|
try {
|
||||||
processCommand(
|
processCommand(new MakeCallCommand(mPeerProfile,
|
||||||
new MakeCallCommand(mPeerProfile, sessionDescription));
|
sessionDescription, timeout));
|
||||||
} catch (SipException e) {
|
} catch (SipException e) {
|
||||||
onError(e);
|
onError(e);
|
||||||
}
|
}
|
||||||
@@ -453,9 +490,15 @@ class SipSessionGroup implements SipListener {
|
|||||||
doCommandAsync(END_CALL);
|
doCommandAsync(END_CALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void changeCall(String sessionDescription) {
|
public void changeCall(String sessionDescription, int timeout) {
|
||||||
doCommandAsync(
|
doCommandAsync(new MakeCallCommand(mPeerProfile, sessionDescription,
|
||||||
new MakeCallCommand(mPeerProfile, sessionDescription));
|
timeout));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changeCallWithTimeout(
|
||||||
|
String sessionDescription, int timeout) {
|
||||||
|
doCommandAsync(new MakeCallCommand(mPeerProfile, sessionDescription,
|
||||||
|
timeout));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void register(int duration) {
|
public void register(int duration) {
|
||||||
@@ -800,6 +843,7 @@ class SipSessionGroup implements SipListener {
|
|||||||
addSipSession(this);
|
addSipSession(this);
|
||||||
mState = SipSessionState.OUTGOING_CALL;
|
mState = SipSessionState.OUTGOING_CALL;
|
||||||
mProxy.onCalling(this);
|
mProxy.onCalling(this);
|
||||||
|
startSessionTimer(cmd.getTimeout());
|
||||||
return true;
|
return true;
|
||||||
} else if (evt instanceof RegisterCommand) {
|
} else if (evt instanceof RegisterCommand) {
|
||||||
int duration = ((RegisterCommand) evt).getDuration();
|
int duration = ((RegisterCommand) evt).getDuration();
|
||||||
@@ -831,6 +875,7 @@ class SipSessionGroup implements SipListener {
|
|||||||
((MakeCallCommand) evt).getSessionDescription(),
|
((MakeCallCommand) evt).getSessionDescription(),
|
||||||
mServerTransaction);
|
mServerTransaction);
|
||||||
mState = SipSessionState.INCOMING_CALL_ANSWERING;
|
mState = SipSessionState.INCOMING_CALL_ANSWERING;
|
||||||
|
startSessionTimer(((MakeCallCommand) evt).getTimeout());
|
||||||
return true;
|
return true;
|
||||||
} else if (END_CALL == evt) {
|
} else if (END_CALL == evt) {
|
||||||
mSipHelper.sendInviteBusyHere(mInviteReceived,
|
mSipHelper.sendInviteBusyHere(mInviteReceived,
|
||||||
@@ -873,6 +918,7 @@ class SipSessionGroup implements SipListener {
|
|||||||
if (mState == SipSessionState.OUTGOING_CALL) {
|
if (mState == SipSessionState.OUTGOING_CALL) {
|
||||||
mState = SipSessionState.OUTGOING_CALL_RING_BACK;
|
mState = SipSessionState.OUTGOING_CALL_RING_BACK;
|
||||||
mProxy.onRingingBack(this);
|
mProxy.onRingingBack(this);
|
||||||
|
cancelSessionTimer();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
case Response.OK:
|
case Response.OK:
|
||||||
@@ -885,10 +931,10 @@ class SipSessionGroup implements SipListener {
|
|||||||
if (handleAuthentication(event)) {
|
if (handleAuthentication(event)) {
|
||||||
addSipSession(this);
|
addSipSession(this);
|
||||||
} else if (mLastNonce == null) {
|
} else if (mLastNonce == null) {
|
||||||
endCallOnError(SipErrorCode.SERVER_ERROR,
|
onError(SipErrorCode.SERVER_ERROR,
|
||||||
"server does not provide challenge");
|
"server does not provide challenge");
|
||||||
} else {
|
} else {
|
||||||
endCallOnError(SipErrorCode.INVALID_CREDENTIALS,
|
onError(SipErrorCode.INVALID_CREDENTIALS,
|
||||||
"incorrect username or password");
|
"incorrect username or password");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -914,6 +960,7 @@ class SipSessionGroup implements SipListener {
|
|||||||
// response.
|
// response.
|
||||||
mSipHelper.sendCancel(mClientTransaction);
|
mSipHelper.sendCancel(mClientTransaction);
|
||||||
mState = SipSessionState.OUTGOING_CALL_CANCELING;
|
mState = SipSessionState.OUTGOING_CALL_CANCELING;
|
||||||
|
startSessionTimer(CANCEL_CALL_TIMER);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -926,9 +973,13 @@ class SipSessionGroup implements SipListener {
|
|||||||
Response response = event.getResponse();
|
Response response = event.getResponse();
|
||||||
int statusCode = response.getStatusCode();
|
int statusCode = response.getStatusCode();
|
||||||
if (expectResponse(Request.CANCEL, evt)) {
|
if (expectResponse(Request.CANCEL, evt)) {
|
||||||
if (statusCode == Response.OK) {
|
switch (statusCode) {
|
||||||
// do nothing; wait for REQUEST_TERMINATED
|
case Response.OK:
|
||||||
return true;
|
// do nothing; wait for REQUEST_TERMINATED
|
||||||
|
return true;
|
||||||
|
case Response.REQUEST_TERMINATED:
|
||||||
|
endCallNormally();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
} else if (expectResponse(Request.INVITE, evt)) {
|
} else if (expectResponse(Request.INVITE, evt)) {
|
||||||
if (statusCode == Response.OK) {
|
if (statusCode == Response.OK) {
|
||||||
@@ -978,11 +1029,27 @@ class SipSessionGroup implements SipListener {
|
|||||||
mClientTransaction = mSipHelper.sendReinvite(mDialog,
|
mClientTransaction = mSipHelper.sendReinvite(mDialog,
|
||||||
((MakeCallCommand) evt).getSessionDescription());
|
((MakeCallCommand) evt).getSessionDescription());
|
||||||
mState = SipSessionState.OUTGOING_CALL;
|
mState = SipSessionState.OUTGOING_CALL;
|
||||||
|
startSessionTimer(((MakeCallCommand) evt).getTimeout());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// timeout in seconds
|
||||||
|
private void startSessionTimer(int timeout) {
|
||||||
|
if (timeout > 0) {
|
||||||
|
mTimer = new SessionTimer();
|
||||||
|
mTimer.start(timeout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void cancelSessionTimer() {
|
||||||
|
if (mTimer != null) {
|
||||||
|
mTimer.cancel();
|
||||||
|
mTimer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String createErrorMessage(Response response) {
|
private String createErrorMessage(Response response) {
|
||||||
return String.format(SERVER_ERROR_PREFIX + "%s (%d)",
|
return String.format(SERVER_ERROR_PREFIX + "%s (%d)",
|
||||||
response.getReasonPhrase(), response.getStatusCode());
|
response.getReasonPhrase(), response.getStatusCode());
|
||||||
@@ -991,15 +1058,10 @@ class SipSessionGroup implements SipListener {
|
|||||||
private void establishCall() {
|
private void establishCall() {
|
||||||
mState = SipSessionState.IN_CALL;
|
mState = SipSessionState.IN_CALL;
|
||||||
mInCall = true;
|
mInCall = true;
|
||||||
|
cancelSessionTimer();
|
||||||
mProxy.onCallEstablished(this, mPeerSessionDescription);
|
mProxy.onCallEstablished(this, mPeerSessionDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fallbackToPreviousInCall(Throwable exception) {
|
|
||||||
exception = getRootCause(exception);
|
|
||||||
fallbackToPreviousInCall(getErrorCode(exception),
|
|
||||||
exception.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void fallbackToPreviousInCall(SipErrorCode errorCode,
|
private void fallbackToPreviousInCall(SipErrorCode errorCode,
|
||||||
String message) {
|
String message) {
|
||||||
mState = SipSessionState.IN_CALL;
|
mState = SipSessionState.IN_CALL;
|
||||||
@@ -1022,6 +1084,7 @@ class SipSessionGroup implements SipListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onError(SipErrorCode errorCode, String message) {
|
private void onError(SipErrorCode errorCode, String message) {
|
||||||
|
cancelSessionTimer();
|
||||||
switch (mState) {
|
switch (mState) {
|
||||||
case REGISTERING:
|
case REGISTERING:
|
||||||
case DEREGISTERING:
|
case DEREGISTERING:
|
||||||
@@ -1255,11 +1318,18 @@ class SipSessionGroup implements SipListener {
|
|||||||
|
|
||||||
private class MakeCallCommand extends EventObject {
|
private class MakeCallCommand extends EventObject {
|
||||||
private String mSessionDescription;
|
private String mSessionDescription;
|
||||||
|
private int mTimeout; // in seconds
|
||||||
|
|
||||||
public MakeCallCommand(SipProfile peerProfile,
|
public MakeCallCommand(SipProfile peerProfile,
|
||||||
String sessionDescription) {
|
String sessionDescription) {
|
||||||
|
this(peerProfile, sessionDescription, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MakeCallCommand(SipProfile peerProfile,
|
||||||
|
String sessionDescription, int timeout) {
|
||||||
super(peerProfile);
|
super(peerProfile);
|
||||||
mSessionDescription = sessionDescription;
|
mSessionDescription = sessionDescription;
|
||||||
|
mTimeout = timeout;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SipProfile getPeerProfile() {
|
public SipProfile getPeerProfile() {
|
||||||
@@ -1269,6 +1339,9 @@ class SipSessionGroup implements SipListener {
|
|||||||
public String getSessionDescription() {
|
public String getSessionDescription() {
|
||||||
return mSessionDescription;
|
return mSessionDescription;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
public int getTimeout() {
|
||||||
|
return mTimeout;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ import java.util.List;
|
|||||||
public class SipPhone extends SipPhoneBase {
|
public class SipPhone extends SipPhoneBase {
|
||||||
private static final String LOG_TAG = "SipPhone";
|
private static final String LOG_TAG = "SipPhone";
|
||||||
private static final boolean LOCAL_DEBUG = true;
|
private static final boolean LOCAL_DEBUG = true;
|
||||||
|
private static final int SESSION_TIMEOUT = 8; // in seconds
|
||||||
|
|
||||||
// A call that is ringing or (call) waiting
|
// A call that is ringing or (call) waiting
|
||||||
private SipCall ringingCall = new SipCall();
|
private SipCall ringingCall = new SipCall();
|
||||||
@@ -675,7 +676,7 @@ public class SipPhone extends SipPhoneBase {
|
|||||||
|
|
||||||
void acceptCall() throws CallStateException {
|
void acceptCall() throws CallStateException {
|
||||||
try {
|
try {
|
||||||
mSipAudioCall.answerCall();
|
mSipAudioCall.answerCall(SESSION_TIMEOUT);
|
||||||
} catch (SipException e) {
|
} catch (SipException e) {
|
||||||
throw new CallStateException("acceptCall(): " + e);
|
throw new CallStateException("acceptCall(): " + e);
|
||||||
}
|
}
|
||||||
@@ -693,7 +694,7 @@ public class SipPhone extends SipPhoneBase {
|
|||||||
void dial() throws SipException {
|
void dial() throws SipException {
|
||||||
setState(Call.State.DIALING);
|
setState(Call.State.DIALING);
|
||||||
mSipAudioCall = mSipManager.makeAudioCall(mContext, mProfile,
|
mSipAudioCall = mSipManager.makeAudioCall(mContext, mProfile,
|
||||||
mPeer, null);
|
mPeer, null, SESSION_TIMEOUT);
|
||||||
mSipAudioCall.setRingbackToneEnabled(false);
|
mSipAudioCall.setRingbackToneEnabled(false);
|
||||||
mSipAudioCall.setListener(mAdapter);
|
mSipAudioCall.setListener(mAdapter);
|
||||||
}
|
}
|
||||||
@@ -701,7 +702,7 @@ public class SipPhone extends SipPhoneBase {
|
|||||||
void hold() throws CallStateException {
|
void hold() throws CallStateException {
|
||||||
setState(Call.State.HOLDING);
|
setState(Call.State.HOLDING);
|
||||||
try {
|
try {
|
||||||
mSipAudioCall.holdCall();
|
mSipAudioCall.holdCall(SESSION_TIMEOUT);
|
||||||
} catch (SipException e) {
|
} catch (SipException e) {
|
||||||
throw new CallStateException("hold(): " + e);
|
throw new CallStateException("hold(): " + e);
|
||||||
}
|
}
|
||||||
@@ -711,7 +712,7 @@ public class SipPhone extends SipPhoneBase {
|
|||||||
mSipAudioCall.setAudioGroup(audioGroup);
|
mSipAudioCall.setAudioGroup(audioGroup);
|
||||||
setState(Call.State.ACTIVE);
|
setState(Call.State.ACTIVE);
|
||||||
try {
|
try {
|
||||||
mSipAudioCall.continueCall();
|
mSipAudioCall.continueCall(SESSION_TIMEOUT);
|
||||||
} catch (SipException e) {
|
} catch (SipException e) {
|
||||||
throw new CallStateException("unhold(): " + e);
|
throw new CallStateException("unhold(): " + e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -112,9 +112,11 @@ interface ISipSession {
|
|||||||
*
|
*
|
||||||
* @param callee the SIP profile to make the call to
|
* @param callee the SIP profile to make the call to
|
||||||
* @param sessionDescription the session description of this call
|
* @param sessionDescription the session description of this call
|
||||||
|
* @param timeout the session will be timed out if the call is not
|
||||||
|
* established within {@code timeout} seconds
|
||||||
* @see ISipSessionListener
|
* @see ISipSessionListener
|
||||||
*/
|
*/
|
||||||
void makeCall(in SipProfile callee, String sessionDescription);
|
void makeCall(in SipProfile callee, String sessionDescription, int timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Answers an incoming call with the specified session description. The
|
* Answers an incoming call with the specified session description. The
|
||||||
@@ -122,8 +124,10 @@ interface ISipSession {
|
|||||||
* {@link SipSessionState#INCOMING_CALL}.
|
* {@link SipSessionState#INCOMING_CALL}.
|
||||||
*
|
*
|
||||||
* @param sessionDescription the session description to answer this call
|
* @param sessionDescription the session description to answer this call
|
||||||
|
* @param timeout the session will be timed out if the call is not
|
||||||
|
* established within {@code timeout} seconds
|
||||||
*/
|
*/
|
||||||
void answerCall(String sessionDescription);
|
void answerCall(String sessionDescription, int timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ends an established call, terminates an outgoing call or rejects an
|
* Ends an established call, terminates an outgoing call or rejects an
|
||||||
@@ -140,6 +144,8 @@ interface ISipSession {
|
|||||||
* to call when the session state is in {@link SipSessionState#IN_CALL}.
|
* to call when the session state is in {@link SipSessionState#IN_CALL}.
|
||||||
*
|
*
|
||||||
* @param sessionDescription the new session description
|
* @param sessionDescription the new session description
|
||||||
|
* @param timeout the session will be timed out if the call is not
|
||||||
|
* established within {@code timeout} seconds
|
||||||
*/
|
*/
|
||||||
void changeCall(String sessionDescription);
|
void changeCall(String sessionDescription, int timeout);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,12 +158,18 @@ public interface SipAudioCall {
|
|||||||
void close();
|
void close();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiates an audio call to the specified profile.
|
* Initiates an audio call to the specified profile. The attempt will be
|
||||||
|
* timed out if the call is not established within {@code timeout} seconds
|
||||||
|
* and {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
|
||||||
|
* will be called.
|
||||||
*
|
*
|
||||||
* @param callee the SIP profile to make the call to
|
* @param callee the SIP profile to make the call to
|
||||||
* @param sipManager the {@link SipManager} object to help make call with
|
* @param sipManager the {@link SipManager} object to help make call with
|
||||||
|
* @param timeout the timeout value in seconds
|
||||||
|
* @see Listener.onError
|
||||||
*/
|
*/
|
||||||
void makeCall(SipProfile callee, SipManager sipManager) throws SipException;
|
void makeCall(SipProfile callee, SipManager sipManager, int timeout)
|
||||||
|
throws SipException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches an incoming call to this call object.
|
* Attaches an incoming call to this call object.
|
||||||
@@ -179,18 +185,38 @@ public interface SipAudioCall {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Puts a call on hold. When succeeds, {@link Listener#onCallHeld} is
|
* Puts a call on hold. When succeeds, {@link Listener#onCallHeld} is
|
||||||
* called.
|
* called. The attempt will be timed out if the call is not established
|
||||||
|
* within {@code timeout} seconds and
|
||||||
|
* {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
|
||||||
|
* will be called.
|
||||||
|
*
|
||||||
|
* @param timeout the timeout value in seconds
|
||||||
|
* @see Listener.onError
|
||||||
*/
|
*/
|
||||||
void holdCall() throws SipException;
|
void holdCall(int timeout) throws SipException;
|
||||||
|
|
||||||
/** Answers a call. */
|
/**
|
||||||
void answerCall() throws SipException;
|
* Answers a call. The attempt will be timed out if the call is not
|
||||||
|
* established within {@code timeout} seconds and
|
||||||
|
* {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
|
||||||
|
* will be called.
|
||||||
|
*
|
||||||
|
* @param timeout the timeout value in seconds
|
||||||
|
* @see Listener.onError
|
||||||
|
*/
|
||||||
|
void answerCall(int timeout) throws SipException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Continues a call that's on hold. When succeeds,
|
* Continues a call that's on hold. When succeeds,
|
||||||
* {@link Listener#onCallEstablished} is called.
|
* {@link Listener#onCallEstablished} is called. The attempt will be timed
|
||||||
|
* out if the call is not established within {@code timeout} seconds and
|
||||||
|
* {@code Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
|
||||||
|
* will be called.
|
||||||
|
*
|
||||||
|
* @param timeout the timeout value in seconds
|
||||||
|
* @see Listener.onError
|
||||||
*/
|
*/
|
||||||
void continueCall() throws SipException;
|
void continueCall(int timeout) throws SipException;
|
||||||
|
|
||||||
/** Puts the device to speaker mode. */
|
/** Puts the device to speaker mode. */
|
||||||
void setSpeakerMode(boolean speakerMode);
|
void setSpeakerMode(boolean speakerMode);
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public class SipAudioCallImpl extends SipSessionAdapter
|
|||||||
private static final boolean DONT_RELEASE_SOCKET = false;
|
private static final boolean DONT_RELEASE_SOCKET = false;
|
||||||
private static final String AUDIO = "audio";
|
private static final String AUDIO = "audio";
|
||||||
private static final int DTMF = 101;
|
private static final int DTMF = 101;
|
||||||
|
private static final int SESSION_TIMEOUT = 5; // in seconds
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private SipProfile mLocalProfile;
|
private SipProfile mLocalProfile;
|
||||||
@@ -144,12 +145,21 @@ public class SipAudioCallImpl extends SipSessionAdapter
|
|||||||
if (closeRtp) stopCall(RELEASE_SOCKET);
|
if (closeRtp) stopCall(RELEASE_SOCKET);
|
||||||
stopRingbackTone();
|
stopRingbackTone();
|
||||||
stopRinging();
|
stopRinging();
|
||||||
mSipSession = null;
|
|
||||||
mInCall = false;
|
mInCall = false;
|
||||||
mHold = false;
|
mHold = false;
|
||||||
mSessionId = -1L;
|
mSessionId = -1L;
|
||||||
mErrorCode = null;
|
mErrorCode = null;
|
||||||
mErrorMessage = null;
|
mErrorMessage = null;
|
||||||
|
|
||||||
|
if (mSipSession != null) {
|
||||||
|
try {
|
||||||
|
mSipSession.setListener(null);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
// don't care
|
||||||
|
}
|
||||||
|
mSipSession = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized SipProfile getLocalProfile() {
|
public synchronized SipProfile getLocalProfile() {
|
||||||
@@ -219,7 +229,7 @@ public class SipAudioCallImpl extends SipSessionAdapter
|
|||||||
// session changing request
|
// session changing request
|
||||||
try {
|
try {
|
||||||
mPeerSd = new SdpSessionDescription(sessionDescription);
|
mPeerSd = new SdpSessionDescription(sessionDescription);
|
||||||
answerCall();
|
answerCall(SESSION_TIMEOUT);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e(TAG, "onRinging()", e);
|
Log.e(TAG, "onRinging()", e);
|
||||||
session.endCall();
|
session.endCall();
|
||||||
@@ -346,14 +356,15 @@ public class SipAudioCallImpl extends SipSessionAdapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void makeCall(SipProfile peerProfile,
|
public synchronized void makeCall(SipProfile peerProfile,
|
||||||
SipManager sipManager) throws SipException {
|
SipManager sipManager, int timeout) throws SipException {
|
||||||
try {
|
try {
|
||||||
mSipSession = sipManager.createSipSession(mLocalProfile, this);
|
mSipSession = sipManager.createSipSession(mLocalProfile, this);
|
||||||
if (mSipSession == null) {
|
if (mSipSession == null) {
|
||||||
throw new SipException(
|
throw new SipException(
|
||||||
"Failed to create SipSession; network available?");
|
"Failed to create SipSession; network available?");
|
||||||
}
|
}
|
||||||
mSipSession.makeCall(peerProfile, createOfferSessionDescription());
|
mSipSession.makeCall(peerProfile, createOfferSessionDescription(),
|
||||||
|
timeout);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
if (e instanceof SipException) {
|
if (e instanceof SipException) {
|
||||||
throw (SipException) e;
|
throw (SipException) e;
|
||||||
@@ -376,10 +387,10 @@ public class SipAudioCallImpl extends SipSessionAdapter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void holdCall() throws SipException {
|
public synchronized void holdCall(int timeout) throws SipException {
|
||||||
if (mHold) return;
|
if (mHold) return;
|
||||||
try {
|
try {
|
||||||
mSipSession.changeCall(createHoldSessionDescription());
|
mSipSession.changeCall(createHoldSessionDescription(), timeout);
|
||||||
mHold = true;
|
mHold = true;
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throwSipException(e);
|
throwSipException(e);
|
||||||
@@ -389,21 +400,21 @@ public class SipAudioCallImpl extends SipSessionAdapter
|
|||||||
if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
|
if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_ON_HOLD);
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void answerCall() throws SipException {
|
public synchronized void answerCall(int timeout) throws SipException {
|
||||||
try {
|
try {
|
||||||
stopRinging();
|
stopRinging();
|
||||||
mSipSession.answerCall(createAnswerSessionDescription());
|
mSipSession.answerCall(createAnswerSessionDescription(), timeout);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
Log.e(TAG, "answerCall()", e);
|
Log.e(TAG, "answerCall()", e);
|
||||||
throwSipException(e);
|
throwSipException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void continueCall() throws SipException {
|
public synchronized void continueCall(int timeout) throws SipException {
|
||||||
if (!mHold) return;
|
if (!mHold) return;
|
||||||
try {
|
try {
|
||||||
mHold = false;
|
mHold = false;
|
||||||
mSipSession.changeCall(createContinueSessionDescription());
|
mSipSession.changeCall(createContinueSessionDescription(), timeout);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throwSipException(e);
|
throwSipException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,44 +218,55 @@ public class SipManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link SipAudioCall} to make a call.
|
* Creates a {@link SipAudioCall} to make a call. The attempt will be timed
|
||||||
|
* out if the call is not established within {@code timeout} seconds and
|
||||||
|
* {@code SipAudioCall.Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
|
||||||
|
* will be called.
|
||||||
*
|
*
|
||||||
* @param context context to create a {@link SipAudioCall} object
|
* @param context context to create a {@link SipAudioCall} object
|
||||||
* @param localProfile the SIP profile to make the call from
|
* @param localProfile the SIP profile to make the call from
|
||||||
* @param peerProfile the SIP profile to make the call to
|
* @param peerProfile the SIP profile to make the call to
|
||||||
* @param listener to listen to the call events from {@link SipAudioCall};
|
* @param listener to listen to the call events from {@link SipAudioCall};
|
||||||
* can be null
|
* can be null
|
||||||
|
* @param timeout the timeout value in seconds
|
||||||
* @return a {@link SipAudioCall} object
|
* @return a {@link SipAudioCall} object
|
||||||
* @throws SipException if calling the SIP service results in an error
|
* @throws SipException if calling the SIP service results in an error
|
||||||
|
* @see SipAudioCall.Listener.onError
|
||||||
*/
|
*/
|
||||||
public SipAudioCall makeAudioCall(Context context, SipProfile localProfile,
|
public SipAudioCall makeAudioCall(Context context, SipProfile localProfile,
|
||||||
SipProfile peerProfile, SipAudioCall.Listener listener)
|
SipProfile peerProfile, SipAudioCall.Listener listener, int timeout)
|
||||||
throws SipException {
|
throws SipException {
|
||||||
SipAudioCall call = new SipAudioCallImpl(context, localProfile);
|
SipAudioCall call = new SipAudioCallImpl(context, localProfile);
|
||||||
call.setListener(listener);
|
call.setListener(listener);
|
||||||
call.makeCall(peerProfile, this);
|
call.makeCall(peerProfile, this, timeout);
|
||||||
return call;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link SipAudioCall} to make a call. To use this method, one
|
* Creates a {@link SipAudioCall} to make a call. To use this method, one
|
||||||
* must call {@link #open(SipProfile)} first.
|
* must call {@link #open(SipProfile)} first. The attempt will be timed out
|
||||||
|
* if the call is not established within {@code timeout} seconds and
|
||||||
|
* {@code SipAudioCall.Listener.onError(SipAudioCall, SipErrorCode.TIME_OUT, String)}
|
||||||
|
* will be called.
|
||||||
*
|
*
|
||||||
* @param context context to create a {@link SipAudioCall} object
|
* @param context context to create a {@link SipAudioCall} object
|
||||||
* @param localProfileUri URI of the SIP profile to make the call from
|
* @param localProfileUri URI of the SIP profile to make the call from
|
||||||
* @param peerProfileUri URI of the SIP profile to make the call to
|
* @param peerProfileUri URI of the SIP profile to make the call to
|
||||||
* @param listener to listen to the call events from {@link SipAudioCall};
|
* @param listener to listen to the call events from {@link SipAudioCall};
|
||||||
* can be null
|
* can be null
|
||||||
|
* @param timeout the timeout value in seconds
|
||||||
* @return a {@link SipAudioCall} object
|
* @return a {@link SipAudioCall} object
|
||||||
* @throws SipException if calling the SIP service results in an error
|
* @throws SipException if calling the SIP service results in an error
|
||||||
|
* @see SipAudioCall.Listener.onError
|
||||||
*/
|
*/
|
||||||
public SipAudioCall makeAudioCall(Context context, String localProfileUri,
|
public SipAudioCall makeAudioCall(Context context, String localProfileUri,
|
||||||
String peerProfileUri, SipAudioCall.Listener listener)
|
String peerProfileUri, SipAudioCall.Listener listener, int timeout)
|
||||||
throws SipException {
|
throws SipException {
|
||||||
try {
|
try {
|
||||||
return makeAudioCall(context,
|
return makeAudioCall(context,
|
||||||
new SipProfile.Builder(localProfileUri).build(),
|
new SipProfile.Builder(localProfileUri).build(),
|
||||||
new SipProfile.Builder(peerProfileUri).build(), listener);
|
new SipProfile.Builder(peerProfileUri).build(), listener,
|
||||||
|
timeout);
|
||||||
} catch (ParseException e) {
|
} catch (ParseException e) {
|
||||||
throw new SipException("build SipProfile", e);
|
throw new SipException("build SipProfile", e);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user