Loading services/java/com/android/server/sip/SipSessionGroup.java +96 −23 Original line number Diff line number Diff line Loading @@ -84,7 +84,8 @@ class SipSessionGroup implements SipListener { private static final boolean DEBUG_PING = DEBUG && false; private static final String ANONYMOUS = "anonymous"; 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 END_CALL = new EventObject("End call"); Loading Loading @@ -363,6 +364,40 @@ class SipSessionGroup implements SipListener { String mPeerSessionDescription; boolean mInCall; 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) { setListener(listener); Loading @@ -382,6 +417,8 @@ class SipSessionGroup implements SipListener { mServerTransaction = null; mClientTransaction = null; mPeerSessionDescription = null; cancelSessionTimer(); } public boolean isInCall() { Loading Loading @@ -434,16 +471,16 @@ class SipSessionGroup implements SipListener { }).start(); } public void makeCall(SipProfile peerProfile, String sessionDescription) { doCommandAsync( new MakeCallCommand(peerProfile, sessionDescription)); public void makeCall(SipProfile peerProfile, String sessionDescription, int timeout) { doCommandAsync(new MakeCallCommand(peerProfile, sessionDescription, timeout)); } public void answerCall(String sessionDescription) { public void answerCall(String sessionDescription, int timeout) { try { processCommand( new MakeCallCommand(mPeerProfile, sessionDescription)); processCommand(new MakeCallCommand(mPeerProfile, sessionDescription, timeout)); } catch (SipException e) { onError(e); } Loading @@ -453,9 +490,15 @@ class SipSessionGroup implements SipListener { doCommandAsync(END_CALL); } public void changeCall(String sessionDescription) { doCommandAsync( new MakeCallCommand(mPeerProfile, sessionDescription)); public void changeCall(String sessionDescription, int timeout) { doCommandAsync(new MakeCallCommand(mPeerProfile, sessionDescription, timeout)); } public void changeCallWithTimeout( String sessionDescription, int timeout) { doCommandAsync(new MakeCallCommand(mPeerProfile, sessionDescription, timeout)); } public void register(int duration) { Loading Loading @@ -800,6 +843,7 @@ class SipSessionGroup implements SipListener { addSipSession(this); mState = SipSessionState.OUTGOING_CALL; mProxy.onCalling(this); startSessionTimer(cmd.getTimeout()); return true; } else if (evt instanceof RegisterCommand) { int duration = ((RegisterCommand) evt).getDuration(); Loading Loading @@ -831,6 +875,7 @@ class SipSessionGroup implements SipListener { ((MakeCallCommand) evt).getSessionDescription(), mServerTransaction); mState = SipSessionState.INCOMING_CALL_ANSWERING; startSessionTimer(((MakeCallCommand) evt).getTimeout()); return true; } else if (END_CALL == evt) { mSipHelper.sendInviteBusyHere(mInviteReceived, Loading Loading @@ -873,6 +918,7 @@ class SipSessionGroup implements SipListener { if (mState == SipSessionState.OUTGOING_CALL) { mState = SipSessionState.OUTGOING_CALL_RING_BACK; mProxy.onRingingBack(this); cancelSessionTimer(); } return true; case Response.OK: Loading @@ -885,10 +931,10 @@ class SipSessionGroup implements SipListener { if (handleAuthentication(event)) { addSipSession(this); } else if (mLastNonce == null) { endCallOnError(SipErrorCode.SERVER_ERROR, onError(SipErrorCode.SERVER_ERROR, "server does not provide challenge"); } else { endCallOnError(SipErrorCode.INVALID_CREDENTIALS, onError(SipErrorCode.INVALID_CREDENTIALS, "incorrect username or password"); } return true; Loading @@ -914,6 +960,7 @@ class SipSessionGroup implements SipListener { // response. mSipHelper.sendCancel(mClientTransaction); mState = SipSessionState.OUTGOING_CALL_CANCELING; startSessionTimer(CANCEL_CALL_TIMER); return true; } return false; Loading @@ -926,9 +973,13 @@ class SipSessionGroup implements SipListener { Response response = event.getResponse(); int statusCode = response.getStatusCode(); if (expectResponse(Request.CANCEL, evt)) { if (statusCode == Response.OK) { switch (statusCode) { case Response.OK: // do nothing; wait for REQUEST_TERMINATED return true; case Response.REQUEST_TERMINATED: endCallNormally(); return true; } } else if (expectResponse(Request.INVITE, evt)) { if (statusCode == Response.OK) { Loading Loading @@ -978,11 +1029,27 @@ class SipSessionGroup implements SipListener { mClientTransaction = mSipHelper.sendReinvite(mDialog, ((MakeCallCommand) evt).getSessionDescription()); mState = SipSessionState.OUTGOING_CALL; startSessionTimer(((MakeCallCommand) evt).getTimeout()); return true; } 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) { return String.format(SERVER_ERROR_PREFIX + "%s (%d)", response.getReasonPhrase(), response.getStatusCode()); Loading @@ -991,15 +1058,10 @@ class SipSessionGroup implements SipListener { private void establishCall() { mState = SipSessionState.IN_CALL; mInCall = true; cancelSessionTimer(); mProxy.onCallEstablished(this, mPeerSessionDescription); } private void fallbackToPreviousInCall(Throwable exception) { exception = getRootCause(exception); fallbackToPreviousInCall(getErrorCode(exception), exception.toString()); } private void fallbackToPreviousInCall(SipErrorCode errorCode, String message) { mState = SipSessionState.IN_CALL; Loading @@ -1022,6 +1084,7 @@ class SipSessionGroup implements SipListener { } private void onError(SipErrorCode errorCode, String message) { cancelSessionTimer(); switch (mState) { case REGISTERING: case DEREGISTERING: Loading Loading @@ -1255,11 +1318,18 @@ class SipSessionGroup implements SipListener { private class MakeCallCommand extends EventObject { private String mSessionDescription; private int mTimeout; // in seconds public MakeCallCommand(SipProfile peerProfile, String sessionDescription) { this(peerProfile, sessionDescription, -1); } public MakeCallCommand(SipProfile peerProfile, String sessionDescription, int timeout) { super(peerProfile); mSessionDescription = sessionDescription; mTimeout = timeout; } public SipProfile getPeerProfile() { Loading @@ -1269,6 +1339,9 @@ class SipSessionGroup implements SipListener { public String getSessionDescription() { return mSessionDescription; } } public int getTimeout() { return mTimeout; } } } telephony/java/com/android/internal/telephony/sip/SipPhone.java +5 −4 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ import java.util.List; public class SipPhone extends SipPhoneBase { private static final String LOG_TAG = "SipPhone"; private static final boolean LOCAL_DEBUG = true; private static final int SESSION_TIMEOUT = 8; // in seconds // A call that is ringing or (call) waiting private SipCall ringingCall = new SipCall(); Loading Loading @@ -675,7 +676,7 @@ public class SipPhone extends SipPhoneBase { void acceptCall() throws CallStateException { try { mSipAudioCall.answerCall(); mSipAudioCall.answerCall(SESSION_TIMEOUT); } catch (SipException e) { throw new CallStateException("acceptCall(): " + e); } Loading @@ -693,7 +694,7 @@ public class SipPhone extends SipPhoneBase { void dial() throws SipException { setState(Call.State.DIALING); mSipAudioCall = mSipManager.makeAudioCall(mContext, mProfile, mPeer, null); mPeer, null, SESSION_TIMEOUT); mSipAudioCall.setRingbackToneEnabled(false); mSipAudioCall.setListener(mAdapter); } Loading @@ -701,7 +702,7 @@ public class SipPhone extends SipPhoneBase { void hold() throws CallStateException { setState(Call.State.HOLDING); try { mSipAudioCall.holdCall(); mSipAudioCall.holdCall(SESSION_TIMEOUT); } catch (SipException e) { throw new CallStateException("hold(): " + e); } Loading @@ -711,7 +712,7 @@ public class SipPhone extends SipPhoneBase { mSipAudioCall.setAudioGroup(audioGroup); setState(Call.State.ACTIVE); try { mSipAudioCall.continueCall(); mSipAudioCall.continueCall(SESSION_TIMEOUT); } catch (SipException e) { throw new CallStateException("unhold(): " + e); } Loading voip/java/android/net/sip/ISipSession.aidl +9 −3 Original line number Diff line number Diff line Loading @@ -112,9 +112,11 @@ interface ISipSession { * * @param callee the SIP profile to make the call to * @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 */ 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 Loading @@ -122,8 +124,10 @@ interface ISipSession { * {@link SipSessionState#INCOMING_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 Loading @@ -140,6 +144,8 @@ interface ISipSession { * to call when the session state is in {@link SipSessionState#IN_CALL}. * * @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); } voip/java/android/net/sip/SipAudioCall.java +34 −8 Original line number Diff line number Diff line Loading @@ -158,12 +158,18 @@ public interface SipAudioCall { 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 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. Loading @@ -179,18 +185,38 @@ public interface SipAudioCall { /** * 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, * {@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. */ void setSpeakerMode(boolean speakerMode); Loading voip/java/android/net/sip/SipAudioCallImpl.java +21 −10 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ public class SipAudioCallImpl extends SipSessionAdapter private static final boolean DONT_RELEASE_SOCKET = false; private static final String AUDIO = "audio"; private static final int DTMF = 101; private static final int SESSION_TIMEOUT = 5; // in seconds private Context mContext; private SipProfile mLocalProfile; Loading Loading @@ -144,12 +145,21 @@ public class SipAudioCallImpl extends SipSessionAdapter if (closeRtp) stopCall(RELEASE_SOCKET); stopRingbackTone(); stopRinging(); mSipSession = null; mInCall = false; mHold = false; mSessionId = -1L; mErrorCode = null; mErrorMessage = null; if (mSipSession != null) { try { mSipSession.setListener(null); } catch (RemoteException e) { // don't care } mSipSession = null; } } public synchronized SipProfile getLocalProfile() { Loading Loading @@ -219,7 +229,7 @@ public class SipAudioCallImpl extends SipSessionAdapter // session changing request try { mPeerSd = new SdpSessionDescription(sessionDescription); answerCall(); answerCall(SESSION_TIMEOUT); } catch (Throwable e) { Log.e(TAG, "onRinging()", e); session.endCall(); Loading Loading @@ -346,14 +356,15 @@ public class SipAudioCallImpl extends SipSessionAdapter } public synchronized void makeCall(SipProfile peerProfile, SipManager sipManager) throws SipException { SipManager sipManager, int timeout) throws SipException { try { mSipSession = sipManager.createSipSession(mLocalProfile, this); if (mSipSession == null) { throw new SipException( "Failed to create SipSession; network available?"); } mSipSession.makeCall(peerProfile, createOfferSessionDescription()); mSipSession.makeCall(peerProfile, createOfferSessionDescription(), timeout); } catch (Throwable e) { if (e instanceof SipException) { throw (SipException) e; Loading @@ -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; try { mSipSession.changeCall(createHoldSessionDescription()); mSipSession.changeCall(createHoldSessionDescription(), timeout); mHold = true; } catch (Throwable e) { throwSipException(e); Loading @@ -389,21 +400,21 @@ public class SipAudioCallImpl extends SipSessionAdapter if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_ON_HOLD); } public synchronized void answerCall() throws SipException { public synchronized void answerCall(int timeout) throws SipException { try { stopRinging(); mSipSession.answerCall(createAnswerSessionDescription()); mSipSession.answerCall(createAnswerSessionDescription(), timeout); } catch (Throwable e) { Log.e(TAG, "answerCall()", e); throwSipException(e); } } public synchronized void continueCall() throws SipException { public synchronized void continueCall(int timeout) throws SipException { if (!mHold) return; try { mHold = false; mSipSession.changeCall(createContinueSessionDescription()); mSipSession.changeCall(createContinueSessionDescription(), timeout); } catch (Throwable e) { throwSipException(e); } Loading Loading
services/java/com/android/server/sip/SipSessionGroup.java +96 −23 Original line number Diff line number Diff line Loading @@ -84,7 +84,8 @@ class SipSessionGroup implements SipListener { private static final boolean DEBUG_PING = DEBUG && false; private static final String ANONYMOUS = "anonymous"; 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 END_CALL = new EventObject("End call"); Loading Loading @@ -363,6 +364,40 @@ class SipSessionGroup implements SipListener { String mPeerSessionDescription; boolean mInCall; 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) { setListener(listener); Loading @@ -382,6 +417,8 @@ class SipSessionGroup implements SipListener { mServerTransaction = null; mClientTransaction = null; mPeerSessionDescription = null; cancelSessionTimer(); } public boolean isInCall() { Loading Loading @@ -434,16 +471,16 @@ class SipSessionGroup implements SipListener { }).start(); } public void makeCall(SipProfile peerProfile, String sessionDescription) { doCommandAsync( new MakeCallCommand(peerProfile, sessionDescription)); public void makeCall(SipProfile peerProfile, String sessionDescription, int timeout) { doCommandAsync(new MakeCallCommand(peerProfile, sessionDescription, timeout)); } public void answerCall(String sessionDescription) { public void answerCall(String sessionDescription, int timeout) { try { processCommand( new MakeCallCommand(mPeerProfile, sessionDescription)); processCommand(new MakeCallCommand(mPeerProfile, sessionDescription, timeout)); } catch (SipException e) { onError(e); } Loading @@ -453,9 +490,15 @@ class SipSessionGroup implements SipListener { doCommandAsync(END_CALL); } public void changeCall(String sessionDescription) { doCommandAsync( new MakeCallCommand(mPeerProfile, sessionDescription)); public void changeCall(String sessionDescription, int timeout) { doCommandAsync(new MakeCallCommand(mPeerProfile, sessionDescription, timeout)); } public void changeCallWithTimeout( String sessionDescription, int timeout) { doCommandAsync(new MakeCallCommand(mPeerProfile, sessionDescription, timeout)); } public void register(int duration) { Loading Loading @@ -800,6 +843,7 @@ class SipSessionGroup implements SipListener { addSipSession(this); mState = SipSessionState.OUTGOING_CALL; mProxy.onCalling(this); startSessionTimer(cmd.getTimeout()); return true; } else if (evt instanceof RegisterCommand) { int duration = ((RegisterCommand) evt).getDuration(); Loading Loading @@ -831,6 +875,7 @@ class SipSessionGroup implements SipListener { ((MakeCallCommand) evt).getSessionDescription(), mServerTransaction); mState = SipSessionState.INCOMING_CALL_ANSWERING; startSessionTimer(((MakeCallCommand) evt).getTimeout()); return true; } else if (END_CALL == evt) { mSipHelper.sendInviteBusyHere(mInviteReceived, Loading Loading @@ -873,6 +918,7 @@ class SipSessionGroup implements SipListener { if (mState == SipSessionState.OUTGOING_CALL) { mState = SipSessionState.OUTGOING_CALL_RING_BACK; mProxy.onRingingBack(this); cancelSessionTimer(); } return true; case Response.OK: Loading @@ -885,10 +931,10 @@ class SipSessionGroup implements SipListener { if (handleAuthentication(event)) { addSipSession(this); } else if (mLastNonce == null) { endCallOnError(SipErrorCode.SERVER_ERROR, onError(SipErrorCode.SERVER_ERROR, "server does not provide challenge"); } else { endCallOnError(SipErrorCode.INVALID_CREDENTIALS, onError(SipErrorCode.INVALID_CREDENTIALS, "incorrect username or password"); } return true; Loading @@ -914,6 +960,7 @@ class SipSessionGroup implements SipListener { // response. mSipHelper.sendCancel(mClientTransaction); mState = SipSessionState.OUTGOING_CALL_CANCELING; startSessionTimer(CANCEL_CALL_TIMER); return true; } return false; Loading @@ -926,9 +973,13 @@ class SipSessionGroup implements SipListener { Response response = event.getResponse(); int statusCode = response.getStatusCode(); if (expectResponse(Request.CANCEL, evt)) { if (statusCode == Response.OK) { switch (statusCode) { case Response.OK: // do nothing; wait for REQUEST_TERMINATED return true; case Response.REQUEST_TERMINATED: endCallNormally(); return true; } } else if (expectResponse(Request.INVITE, evt)) { if (statusCode == Response.OK) { Loading Loading @@ -978,11 +1029,27 @@ class SipSessionGroup implements SipListener { mClientTransaction = mSipHelper.sendReinvite(mDialog, ((MakeCallCommand) evt).getSessionDescription()); mState = SipSessionState.OUTGOING_CALL; startSessionTimer(((MakeCallCommand) evt).getTimeout()); return true; } 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) { return String.format(SERVER_ERROR_PREFIX + "%s (%d)", response.getReasonPhrase(), response.getStatusCode()); Loading @@ -991,15 +1058,10 @@ class SipSessionGroup implements SipListener { private void establishCall() { mState = SipSessionState.IN_CALL; mInCall = true; cancelSessionTimer(); mProxy.onCallEstablished(this, mPeerSessionDescription); } private void fallbackToPreviousInCall(Throwable exception) { exception = getRootCause(exception); fallbackToPreviousInCall(getErrorCode(exception), exception.toString()); } private void fallbackToPreviousInCall(SipErrorCode errorCode, String message) { mState = SipSessionState.IN_CALL; Loading @@ -1022,6 +1084,7 @@ class SipSessionGroup implements SipListener { } private void onError(SipErrorCode errorCode, String message) { cancelSessionTimer(); switch (mState) { case REGISTERING: case DEREGISTERING: Loading Loading @@ -1255,11 +1318,18 @@ class SipSessionGroup implements SipListener { private class MakeCallCommand extends EventObject { private String mSessionDescription; private int mTimeout; // in seconds public MakeCallCommand(SipProfile peerProfile, String sessionDescription) { this(peerProfile, sessionDescription, -1); } public MakeCallCommand(SipProfile peerProfile, String sessionDescription, int timeout) { super(peerProfile); mSessionDescription = sessionDescription; mTimeout = timeout; } public SipProfile getPeerProfile() { Loading @@ -1269,6 +1339,9 @@ class SipSessionGroup implements SipListener { public String getSessionDescription() { return mSessionDescription; } } public int getTimeout() { return mTimeout; } } }
telephony/java/com/android/internal/telephony/sip/SipPhone.java +5 −4 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ import java.util.List; public class SipPhone extends SipPhoneBase { private static final String LOG_TAG = "SipPhone"; private static final boolean LOCAL_DEBUG = true; private static final int SESSION_TIMEOUT = 8; // in seconds // A call that is ringing or (call) waiting private SipCall ringingCall = new SipCall(); Loading Loading @@ -675,7 +676,7 @@ public class SipPhone extends SipPhoneBase { void acceptCall() throws CallStateException { try { mSipAudioCall.answerCall(); mSipAudioCall.answerCall(SESSION_TIMEOUT); } catch (SipException e) { throw new CallStateException("acceptCall(): " + e); } Loading @@ -693,7 +694,7 @@ public class SipPhone extends SipPhoneBase { void dial() throws SipException { setState(Call.State.DIALING); mSipAudioCall = mSipManager.makeAudioCall(mContext, mProfile, mPeer, null); mPeer, null, SESSION_TIMEOUT); mSipAudioCall.setRingbackToneEnabled(false); mSipAudioCall.setListener(mAdapter); } Loading @@ -701,7 +702,7 @@ public class SipPhone extends SipPhoneBase { void hold() throws CallStateException { setState(Call.State.HOLDING); try { mSipAudioCall.holdCall(); mSipAudioCall.holdCall(SESSION_TIMEOUT); } catch (SipException e) { throw new CallStateException("hold(): " + e); } Loading @@ -711,7 +712,7 @@ public class SipPhone extends SipPhoneBase { mSipAudioCall.setAudioGroup(audioGroup); setState(Call.State.ACTIVE); try { mSipAudioCall.continueCall(); mSipAudioCall.continueCall(SESSION_TIMEOUT); } catch (SipException e) { throw new CallStateException("unhold(): " + e); } Loading
voip/java/android/net/sip/ISipSession.aidl +9 −3 Original line number Diff line number Diff line Loading @@ -112,9 +112,11 @@ interface ISipSession { * * @param callee the SIP profile to make the call to * @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 */ 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 Loading @@ -122,8 +124,10 @@ interface ISipSession { * {@link SipSessionState#INCOMING_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 Loading @@ -140,6 +144,8 @@ interface ISipSession { * to call when the session state is in {@link SipSessionState#IN_CALL}. * * @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); }
voip/java/android/net/sip/SipAudioCall.java +34 −8 Original line number Diff line number Diff line Loading @@ -158,12 +158,18 @@ public interface SipAudioCall { 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 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. Loading @@ -179,18 +185,38 @@ public interface SipAudioCall { /** * 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, * {@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. */ void setSpeakerMode(boolean speakerMode); Loading
voip/java/android/net/sip/SipAudioCallImpl.java +21 −10 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ public class SipAudioCallImpl extends SipSessionAdapter private static final boolean DONT_RELEASE_SOCKET = false; private static final String AUDIO = "audio"; private static final int DTMF = 101; private static final int SESSION_TIMEOUT = 5; // in seconds private Context mContext; private SipProfile mLocalProfile; Loading Loading @@ -144,12 +145,21 @@ public class SipAudioCallImpl extends SipSessionAdapter if (closeRtp) stopCall(RELEASE_SOCKET); stopRingbackTone(); stopRinging(); mSipSession = null; mInCall = false; mHold = false; mSessionId = -1L; mErrorCode = null; mErrorMessage = null; if (mSipSession != null) { try { mSipSession.setListener(null); } catch (RemoteException e) { // don't care } mSipSession = null; } } public synchronized SipProfile getLocalProfile() { Loading Loading @@ -219,7 +229,7 @@ public class SipAudioCallImpl extends SipSessionAdapter // session changing request try { mPeerSd = new SdpSessionDescription(sessionDescription); answerCall(); answerCall(SESSION_TIMEOUT); } catch (Throwable e) { Log.e(TAG, "onRinging()", e); session.endCall(); Loading Loading @@ -346,14 +356,15 @@ public class SipAudioCallImpl extends SipSessionAdapter } public synchronized void makeCall(SipProfile peerProfile, SipManager sipManager) throws SipException { SipManager sipManager, int timeout) throws SipException { try { mSipSession = sipManager.createSipSession(mLocalProfile, this); if (mSipSession == null) { throw new SipException( "Failed to create SipSession; network available?"); } mSipSession.makeCall(peerProfile, createOfferSessionDescription()); mSipSession.makeCall(peerProfile, createOfferSessionDescription(), timeout); } catch (Throwable e) { if (e instanceof SipException) { throw (SipException) e; Loading @@ -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; try { mSipSession.changeCall(createHoldSessionDescription()); mSipSession.changeCall(createHoldSessionDescription(), timeout); mHold = true; } catch (Throwable e) { throwSipException(e); Loading @@ -389,21 +400,21 @@ public class SipAudioCallImpl extends SipSessionAdapter if (audioGroup != null) audioGroup.setMode(AudioGroup.MODE_ON_HOLD); } public synchronized void answerCall() throws SipException { public synchronized void answerCall(int timeout) throws SipException { try { stopRinging(); mSipSession.answerCall(createAnswerSessionDescription()); mSipSession.answerCall(createAnswerSessionDescription(), timeout); } catch (Throwable e) { Log.e(TAG, "answerCall()", e); throwSipException(e); } } public synchronized void continueCall() throws SipException { public synchronized void continueCall(int timeout) throws SipException { if (!mHold) return; try { mHold = false; mSipSession.changeCall(createContinueSessionDescription()); mSipSession.changeCall(createContinueSessionDescription(), timeout); } catch (Throwable e) { throwSipException(e); } Loading