Merge "SIP: misc fixes." into gingerbread

This commit is contained in:
Hung-ying Tyan
2010-09-29 18:12:12 -07:00
committed by Android (Google) Code Review
3 changed files with 94 additions and 58 deletions

View File

@ -520,7 +520,9 @@ public class SipManager {
private String getUri(ISipSession session) { private String getUri(ISipSession session) {
try { try {
return session.getLocalProfile().getUriString(); return ((session == null)
? "no session"
: session.getLocalProfile().getUriString());
} catch (RemoteException e) { } catch (RemoteException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View File

@ -510,31 +510,43 @@ public final class SipService extends ISipService.Stub {
} }
} }
// KeepAliveProcess is controlled by AutoRegistrationProcess.
// All methods will be invoked in sync with SipService.this except realRun()
private class KeepAliveProcess implements Runnable { private class KeepAliveProcess implements Runnable {
private static final String TAG = "\\KEEPALIVE/"; private static final String TAG = "\\KEEPALIVE/";
private static final int INTERVAL = 10; private static final int INTERVAL = 10;
private SipSessionGroup.SipSessionImpl mSession; private SipSessionGroup.SipSessionImpl mSession;
private boolean mRunning = false;
public KeepAliveProcess(SipSessionGroup.SipSessionImpl session) { public KeepAliveProcess(SipSessionGroup.SipSessionImpl session) {
mSession = session; mSession = session;
} }
public void start() { public void start() {
if (mRunning) return;
mRunning = true;
mTimer.set(INTERVAL * 1000, this); mTimer.set(INTERVAL * 1000, this);
} }
// timeout handler
public void run() { public void run() {
if (!mRunning) return;
final SipSessionGroup.SipSessionImpl session = mSession;
// delegate to mExecutor // delegate to mExecutor
getExecutor().addTask(new Runnable() { getExecutor().addTask(new Runnable() {
public void run() { public void run() {
realRun(); realRun(session);
} }
}); });
} }
private void realRun() { // real timeout handler
private void realRun(SipSessionGroup.SipSessionImpl session) {
synchronized (SipService.this) { synchronized (SipService.this) {
SipSessionGroup.SipSessionImpl session = mSession.duplicate(); if (notCurrentSession(session)) return;
session = session.duplicate();
if (DEBUG) Log.d(TAG, "~~~ keepalive"); if (DEBUG) Log.d(TAG, "~~~ keepalive");
mTimer.cancel(this); mTimer.cancel(this);
session.sendKeepAlive(); session.sendKeepAlive();
@ -547,8 +559,14 @@ public final class SipService extends ISipService.Stub {
} }
public void stop() { public void stop() {
mRunning = false;
mSession = null;
mTimer.cancel(this); mTimer.cancel(this);
} }
private boolean notCurrentSession(ISipSession session) {
return (session != mSession) || !mRunning;
}
} }
private class AutoRegistrationProcess extends SipSessionAdapter private class AutoRegistrationProcess extends SipSessionAdapter
@ -561,13 +579,15 @@ public final class SipService extends ISipService.Stub {
private long mExpiryTime; private long mExpiryTime;
private int mErrorCode; private int mErrorCode;
private String mErrorMessage; private String mErrorMessage;
private boolean mRunning = false;
private String getAction() { private String getAction() {
return toString(); return toString();
} }
public void start(SipSessionGroup group) { public void start(SipSessionGroup group) {
if (mSession == null) { if (!mRunning) {
mRunning = true;
mBackoff = 1; mBackoff = 1;
mSession = (SipSessionGroup.SipSessionImpl) mSession = (SipSessionGroup.SipSessionImpl)
group.createSession(this); group.createSession(this);
@ -584,35 +604,24 @@ public final class SipService extends ISipService.Stub {
} }
public void stop() { public void stop() {
stop(false); if (!mRunning) return;
} mRunning = false;
mSession.setListener(null);
private void stopButKeepStates() {
stop(true);
}
private void stop(boolean keepStates) {
if (mSession == null) return;
if (mConnected && mRegistered) mSession.unregister(); if (mConnected && mRegistered) mSession.unregister();
mTimer.cancel(this); mTimer.cancel(this);
if (mKeepAliveProcess != null) { if (mKeepAliveProcess != null) {
mKeepAliveProcess.stop(); mKeepAliveProcess.stop();
mKeepAliveProcess = null; mKeepAliveProcess = null;
} }
if (!keepStates) {
mSession = null;
mRegistered = false;
}
}
private boolean isStopped() { mRegistered = false;
return (mSession == null); setListener(mProxy.getListener());
} }
public void setListener(ISipSessionListener listener) { public void setListener(ISipSessionListener listener) {
synchronized (SipService.this) { synchronized (SipService.this) {
mProxy.setListener(listener); mProxy.setListener(listener);
if (mSession == null) return;
try { try {
int state = (mSession == null) int state = (mSession == null)
@ -632,6 +641,18 @@ public final class SipService extends ISipService.Stub {
mProxy.onRegistrationFailed(mSession, mErrorCode, mProxy.onRegistrationFailed(mSession, mErrorCode,
mErrorMessage); mErrorMessage);
} }
} else if (!mConnected) {
mProxy.onRegistrationFailed(mSession,
SipErrorCode.DATA_CONNECTION_LOST,
"no data connection");
} else if (!mRunning) {
mProxy.onRegistrationFailed(mSession,
SipErrorCode.CLIENT_ERROR,
"registration not running");
} else {
mProxy.onRegistrationFailed(mSession,
SipErrorCode.IN_PROGRESS,
String.valueOf(state));
} }
} catch (Throwable t) { } catch (Throwable t) {
Log.w(TAG, "setListener(): " + t); Log.w(TAG, "setListener(): " + t);
@ -643,21 +664,29 @@ public final class SipService extends ISipService.Stub {
return mRegistered; return mRegistered;
} }
// timeout handler
public void run() { public void run() {
// delegate to mExecutor synchronized (SipService.this) {
getExecutor().addTask(new Runnable() { if (!mRunning) return;
public void run() { final SipSessionGroup.SipSessionImpl session = mSession;
realRun();
} // delegate to mExecutor
}); getExecutor().addTask(new Runnable() {
public void run() {
realRun(session);
}
});
}
} }
private void realRun() { // real timeout handler
mErrorCode = SipErrorCode.NO_ERROR; private void realRun(SipSessionGroup.SipSessionImpl session) {
mErrorMessage = null;
if (DEBUG) Log.d(TAG, "~~~ registering");
synchronized (SipService.this) { synchronized (SipService.this) {
if (mConnected && !isStopped()) mSession.register(EXPIRY_TIME); if (notCurrentSession(session)) return;
mErrorCode = SipErrorCode.NO_ERROR;
mErrorMessage = null;
if (DEBUG) Log.d(TAG, "~~~ registering");
if (mConnected) session.register(EXPIRY_TIME);
} }
} }
@ -697,22 +726,29 @@ public final class SipService extends ISipService.Stub {
public void onRegistering(ISipSession session) { public void onRegistering(ISipSession session) {
if (DEBUG) Log.d(TAG, "onRegistering(): " + session); if (DEBUG) Log.d(TAG, "onRegistering(): " + session);
synchronized (SipService.this) { synchronized (SipService.this) {
if (!isStopped() && (session != mSession)) return; if (notCurrentSession(session)) return;
mRegistered = false; mRegistered = false;
mProxy.onRegistering(session); mProxy.onRegistering(session);
} }
} }
private boolean notCurrentSession(ISipSession session) {
if (session != mSession) {
((SipSessionGroup.SipSessionImpl) session).setListener(null);
return true;
}
return !mRunning;
}
@Override @Override
public void onRegistrationDone(ISipSession session, int duration) { public void onRegistrationDone(ISipSession session, int duration) {
if (DEBUG) Log.d(TAG, "onRegistrationDone(): " + session); if (DEBUG) Log.d(TAG, "onRegistrationDone(): " + session);
synchronized (SipService.this) { synchronized (SipService.this) {
if (!isStopped() && (session != mSession)) return; if (notCurrentSession(session)) return;
mProxy.onRegistrationDone(session, duration); mProxy.onRegistrationDone(session, duration);
if (isStopped()) return;
if (duration > 0) { if (duration > 0) {
mSession.clearReRegisterRequired(); mSession.clearReRegisterRequired();
mExpiryTime = SystemClock.elapsedRealtime() mExpiryTime = SystemClock.elapsedRealtime()
@ -751,17 +787,18 @@ public final class SipService extends ISipService.Stub {
if (DEBUG) Log.d(TAG, "onRegistrationFailed(): " + session + ": " if (DEBUG) Log.d(TAG, "onRegistrationFailed(): " + session + ": "
+ SipErrorCode.toString(errorCode) + ": " + message); + SipErrorCode.toString(errorCode) + ": " + message);
synchronized (SipService.this) { synchronized (SipService.this) {
if (!isStopped() && (session != mSession)) return; if (notCurrentSession(session)) return;
mErrorCode = errorCode;
mErrorMessage = message;
mProxy.onRegistrationFailed(session, errorCode, message);
if (errorCode == SipErrorCode.INVALID_CREDENTIALS) { if (errorCode == SipErrorCode.INVALID_CREDENTIALS) {
if (DEBUG) Log.d(TAG, " pause auto-registration"); if (DEBUG) Log.d(TAG, " pause auto-registration");
stopButKeepStates(); stop();
} else if (!isStopped()) { } else {
onError(); onError();
} }
mErrorCode = errorCode;
mErrorMessage = message;
mProxy.onRegistrationFailed(session, errorCode, message);
} }
} }
@ -769,14 +806,11 @@ public final class SipService extends ISipService.Stub {
public void onRegistrationTimeout(ISipSession session) { public void onRegistrationTimeout(ISipSession session) {
if (DEBUG) Log.d(TAG, "onRegistrationTimeout(): " + session); if (DEBUG) Log.d(TAG, "onRegistrationTimeout(): " + session);
synchronized (SipService.this) { synchronized (SipService.this) {
if (!isStopped() && (session != mSession)) return; if (notCurrentSession(session)) return;
mErrorCode = SipErrorCode.TIME_OUT; mErrorCode = SipErrorCode.TIME_OUT;
mProxy.onRegistrationTimeout(session); mProxy.onRegistrationTimeout(session);
onError();
if (!isStopped()) {
mRegistered = false;
onError();
}
} }
} }
@ -883,6 +917,7 @@ public final class SipService extends ISipService.Stub {
mConnected = connected; mConnected = connected;
} }
// timeout handler
@Override @Override
public void run() { public void run() {
// delegate to mExecutor // delegate to mExecutor

View File

@ -334,12 +334,12 @@ class SipSessionGroup implements SipListener {
if (isRequestEvent(Request.INVITE, evt)) { if (isRequestEvent(Request.INVITE, evt)) {
RequestEvent event = (RequestEvent) evt; RequestEvent event = (RequestEvent) evt;
SipSessionImpl newSession = new SipSessionImpl(mProxy); SipSessionImpl newSession = new SipSessionImpl(mProxy);
newSession.mState = SipSession.State.INCOMING_CALL;
newSession.mServerTransaction = mSipHelper.sendRinging(event, newSession.mServerTransaction = mSipHelper.sendRinging(event,
generateTag()); generateTag());
newSession.mDialog = newSession.mServerTransaction.getDialog(); newSession.mDialog = newSession.mServerTransaction.getDialog();
newSession.mInviteReceived = event; newSession.mInviteReceived = event;
newSession.mPeerProfile = createPeerProfile(event.getRequest()); newSession.mPeerProfile = createPeerProfile(event.getRequest());
newSession.mState = SipSession.State.INCOMING_CALL;
newSession.mPeerSessionDescription = newSession.mPeerSessionDescription =
extractContent(event.getRequest()); extractContent(event.getRequest());
addSipSession(newSession); addSipSession(newSession);
@ -708,7 +708,6 @@ class SipSessionGroup implements SipListener {
case SipSession.State.PINGING: case SipSession.State.PINGING:
reset(); reset();
mReRegisterFlag = true; mReRegisterFlag = true;
mState = SipSession.State.READY_TO_CALL;
break; break;
default: default:
@ -877,6 +876,7 @@ class SipSessionGroup implements SipListener {
private boolean readyForCall(EventObject evt) throws SipException { private boolean readyForCall(EventObject evt) throws SipException {
// expect MakeCallCommand, RegisterCommand, DEREGISTER // expect MakeCallCommand, RegisterCommand, DEREGISTER
if (evt instanceof MakeCallCommand) { if (evt instanceof MakeCallCommand) {
mState = SipSession.State.OUTGOING_CALL;
MakeCallCommand cmd = (MakeCallCommand) evt; MakeCallCommand cmd = (MakeCallCommand) evt;
mPeerProfile = cmd.getPeerProfile(); mPeerProfile = cmd.getPeerProfile();
mClientTransaction = mSipHelper.sendInvite(mLocalProfile, mClientTransaction = mSipHelper.sendInvite(mLocalProfile,
@ -884,25 +884,24 @@ class SipSessionGroup implements SipListener {
generateTag()); generateTag());
mDialog = mClientTransaction.getDialog(); mDialog = mClientTransaction.getDialog();
addSipSession(this); addSipSession(this);
mState = SipSession.State.OUTGOING_CALL;
mProxy.onCalling(this); mProxy.onCalling(this);
startSessionTimer(cmd.getTimeout()); startSessionTimer(cmd.getTimeout());
return true; return true;
} else if (evt instanceof RegisterCommand) { } else if (evt instanceof RegisterCommand) {
mState = SipSession.State.REGISTERING;
int duration = ((RegisterCommand) evt).getDuration(); int duration = ((RegisterCommand) evt).getDuration();
mClientTransaction = mSipHelper.sendRegister(mLocalProfile, mClientTransaction = mSipHelper.sendRegister(mLocalProfile,
generateTag(), duration); generateTag(), duration);
mDialog = mClientTransaction.getDialog(); mDialog = mClientTransaction.getDialog();
addSipSession(this); addSipSession(this);
mState = SipSession.State.REGISTERING;
mProxy.onRegistering(this); mProxy.onRegistering(this);
return true; return true;
} else if (DEREGISTER == evt) { } else if (DEREGISTER == evt) {
mState = SipSession.State.DEREGISTERING;
mClientTransaction = mSipHelper.sendRegister(mLocalProfile, mClientTransaction = mSipHelper.sendRegister(mLocalProfile,
generateTag(), 0); generateTag(), 0);
mDialog = mClientTransaction.getDialog(); mDialog = mClientTransaction.getDialog();
addSipSession(this); addSipSession(this);
mState = SipSession.State.DEREGISTERING;
mProxy.onRegistering(this); mProxy.onRegistering(this);
return true; return true;
} }
@ -913,11 +912,11 @@ class SipSessionGroup implements SipListener {
// expect MakeCallCommand(answering) , END_CALL cmd , Cancel // expect MakeCallCommand(answering) , END_CALL cmd , Cancel
if (evt instanceof MakeCallCommand) { if (evt instanceof MakeCallCommand) {
// answer call // answer call
mState = SipSession.State.INCOMING_CALL_ANSWERING;
mServerTransaction = mSipHelper.sendInviteOk(mInviteReceived, mServerTransaction = mSipHelper.sendInviteOk(mInviteReceived,
mLocalProfile, mLocalProfile,
((MakeCallCommand) evt).getSessionDescription(), ((MakeCallCommand) evt).getSessionDescription(),
mServerTransaction); mServerTransaction);
mState = SipSession.State.INCOMING_CALL_ANSWERING;
startSessionTimer(((MakeCallCommand) evt).getTimeout()); startSessionTimer(((MakeCallCommand) evt).getTimeout());
return true; return true;
} else if (END_CALL == evt) { } else if (END_CALL == evt) {
@ -1009,8 +1008,8 @@ class SipSessionGroup implements SipListener {
// RFC says that UA should not send out cancel when no // RFC says that UA should not send out cancel when no
// response comes back yet. We are cheating for not checking // response comes back yet. We are cheating for not checking
// response. // response.
mSipHelper.sendCancel(mClientTransaction);
mState = SipSession.State.OUTGOING_CALL_CANCELING; mState = SipSession.State.OUTGOING_CALL_CANCELING;
mSipHelper.sendCancel(mClientTransaction);
startSessionTimer(CANCEL_CALL_TIMER); startSessionTimer(CANCEL_CALL_TIMER);
return true; return true;
} }
@ -1065,8 +1064,8 @@ class SipSessionGroup implements SipListener {
return true; return true;
} else if (isRequestEvent(Request.INVITE, evt)) { } else if (isRequestEvent(Request.INVITE, evt)) {
// got Re-INVITE // got Re-INVITE
RequestEvent event = mInviteReceived = (RequestEvent) evt;
mState = SipSession.State.INCOMING_CALL; mState = SipSession.State.INCOMING_CALL;
RequestEvent event = mInviteReceived = (RequestEvent) evt;
mPeerSessionDescription = extractContent(event.getRequest()); mPeerSessionDescription = extractContent(event.getRequest());
mServerTransaction = null; mServerTransaction = null;
mProxy.onRinging(this, mPeerProfile, mPeerSessionDescription); mProxy.onRinging(this, mPeerProfile, mPeerSessionDescription);
@ -1077,9 +1076,9 @@ class SipSessionGroup implements SipListener {
return true; return true;
} else if (evt instanceof MakeCallCommand) { } else if (evt instanceof MakeCallCommand) {
// to change call // to change call
mState = SipSession.State.OUTGOING_CALL;
mClientTransaction = mSipHelper.sendReinvite(mDialog, mClientTransaction = mSipHelper.sendReinvite(mDialog,
((MakeCallCommand) evt).getSessionDescription()); ((MakeCallCommand) evt).getSessionDescription());
mState = SipSession.State.OUTGOING_CALL;
startSessionTimer(((MakeCallCommand) evt).getTimeout()); startSessionTimer(((MakeCallCommand) evt).getTimeout());
return true; return true;
} }