diff options
author | Hung-ying Tyan <tyanh@google.com> | 2010-09-13 02:48:22 -0700 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2010-09-13 02:48:22 -0700 |
commit | a5dce0c15ac05724b4595d62d521a481c7e1f86a (patch) | |
tree | a047413cf22bd0fd14ac5db76809b157b8d2b6c7 | |
parent | 38dc67f49ec77d34c858777144323960c37d045e (diff) | |
parent | 3d7606aa607b24817e37c264f2141ed7b2d50be0 (diff) | |
download | frameworks_base-a5dce0c15ac05724b4595d62d521a481c7e1f86a.zip frameworks_base-a5dce0c15ac05724b4595d62d521a481c7e1f86a.tar.gz frameworks_base-a5dce0c15ac05724b4595d62d521a481c7e1f86a.tar.bz2 |
am 3d7606aa: SIP: enhance timeout and registration status feedback.
Merge commit '3d7606aa607b24817e37c264f2141ed7b2d50be0' into gingerbread-plus-aosp
* commit '3d7606aa607b24817e37c264f2141ed7b2d50be0':
SIP: enhance timeout and registration status feedback.
5 files changed, 156 insertions, 105 deletions
diff --git a/services/java/com/android/server/sip/SipService.java b/services/java/com/android/server/sip/SipService.java index eee97c3..c3786f5 100644 --- a/services/java/com/android/server/sip/SipService.java +++ b/services/java/com/android/server/sip/SipService.java @@ -27,6 +27,7 @@ import android.net.NetworkInfo; import android.net.sip.ISipService; import android.net.sip.ISipSession; import android.net.sip.ISipSessionListener; +import android.net.sip.SipErrorCode; import android.net.sip.SipManager; import android.net.sip.SipProfile; import android.net.sip.SipSessionAdapter; @@ -528,6 +529,8 @@ public final class SipService extends ISipService.Stub { private int mBackoff = 1; private boolean mRegistered; private long mExpiryTime; + private SipErrorCode mErrorCode; + private String mErrorMessage; private String getAction() { return toString(); @@ -551,15 +554,25 @@ public final class SipService extends ISipService.Stub { } public void stop() { + stop(false); + } + + private void stopButKeepStates() { + stop(true); + } + + private void stop(boolean keepStates) { if (mSession == null) return; - if (mConnected) mSession.unregister(); + if (mConnected && mRegistered) mSession.unregister(); mTimer.cancel(this); if (mKeepAliveProcess != null) { mKeepAliveProcess.stop(); mKeepAliveProcess = null; } - mSession = null; - mRegistered = false; + if (!keepStates) { + mSession = null; + mRegistered = false; + } } private boolean isStopped() { @@ -568,20 +581,33 @@ public final class SipService extends ISipService.Stub { public void setListener(ISipSessionListener listener) { Log.v(TAG, "setListener(): " + listener); - mProxy.setListener(listener); - if (mSession == null) return; + synchronized (SipService.this) { + mProxy.setListener(listener); + if (mSession == null) return; - try { - if ((mSession != null) && SipSessionState.REGISTERING.equals( - mSession.getState())) { - mProxy.onRegistering(mSession); - } else if (mRegistered) { - int duration = (int) - (mExpiryTime - SystemClock.elapsedRealtime()); - mProxy.onRegistrationDone(mSession, duration); + try { + SipSessionState state = (mSession == null) + ? SipSessionState.READY_TO_CALL + : Enum.valueOf( + SipSessionState.class, mSession.getState()); + if ((state == SipSessionState.REGISTERING) + || (state == SipSessionState.DEREGISTERING)) { + mProxy.onRegistering(mSession); + } else if (mRegistered) { + int duration = (int) + (mExpiryTime - SystemClock.elapsedRealtime()); + mProxy.onRegistrationDone(mSession, duration); + } else if (mErrorCode != null) { + if (mErrorCode == SipErrorCode.TIME_OUT) { + mProxy.onRegistrationTimeout(mSession); + } else { + mProxy.onRegistrationFailed(mSession, + mErrorCode.toString(), mErrorMessage); + } + } + } catch (Throwable t) { + Log.w(TAG, "setListener(): " + t); } - } catch (Throwable t) { - Log.w(TAG, "setListener(): " + t); } } @@ -590,6 +616,8 @@ public final class SipService extends ISipService.Stub { } public void run() { + mErrorCode = null; + mErrorMessage = null; Log.v(TAG, " ~~~ registering"); synchronized (SipService.this) { if (mConnected && !isStopped()) mSession.register(EXPIRY_TIME); @@ -634,11 +662,7 @@ public final class SipService extends ISipService.Stub { synchronized (SipService.this) { if (!isStopped() && (session != mSession)) return; mRegistered = false; - try { - mProxy.onRegistering(session); - } catch (Throwable t) { - Log.w(TAG, "onRegistering()", t); - } + mProxy.onRegistering(session); } } @@ -647,11 +671,9 @@ public final class SipService extends ISipService.Stub { Log.v(TAG, "onRegistrationDone(): " + session + ": " + mSession); synchronized (SipService.this) { if (!isStopped() && (session != mSession)) return; - try { - mProxy.onRegistrationDone(session, duration); - } catch (Throwable t) { - Log.w(TAG, "onRegistrationDone()", t); - } + + mProxy.onRegistrationDone(session, duration); + if (isStopped()) return; if (duration > 0) { @@ -687,19 +709,25 @@ public final class SipService extends ISipService.Stub { } @Override - public void onRegistrationFailed(ISipSession session, String className, - String message) { + public void onRegistrationFailed(ISipSession session, + String errorCodeString, String message) { + SipErrorCode errorCode = + Enum.valueOf(SipErrorCode.class, errorCodeString); Log.v(TAG, "onRegistrationFailed(): " + session + ": " + mSession - + ": " + className + ": " + message); + + ": " + errorCode + ": " + message); synchronized (SipService.this) { if (!isStopped() && (session != mSession)) return; - try { - mProxy.onRegistrationFailed(session, className, message); - } catch (Throwable t) { - Log.w(TAG, "onRegistrationFailed(): " + t); + mErrorCode = errorCode; + mErrorMessage = message; + mProxy.onRegistrationFailed(session, errorCode.toString(), + message); + + if (errorCode == SipErrorCode.INVALID_CREDENTIALS) { + Log.d(TAG, " pause auto-registration"); + stopButKeepStates(); + } else if (!isStopped()) { + onError(); } - - if (!isStopped()) onError(); } } @@ -708,11 +736,8 @@ public final class SipService extends ISipService.Stub { Log.v(TAG, "onRegistrationTimeout(): " + session + ": " + mSession); synchronized (SipService.this) { if (!isStopped() && (session != mSession)) return; - try { - mProxy.onRegistrationTimeout(session); - } catch (Throwable t) { - Log.w(TAG, "onRegistrationTimeout(): " + t); - } + mErrorCode = SipErrorCode.TIME_OUT; + mProxy.onRegistrationTimeout(session); if (!isStopped()) { mRegistered = false; diff --git a/services/java/com/android/server/sip/SipSessionGroup.java b/services/java/com/android/server/sip/SipSessionGroup.java index 2f7ddc4..da8e9b8 100644 --- a/services/java/com/android/server/sip/SipSessionGroup.java +++ b/services/java/com/android/server/sip/SipSessionGroup.java @@ -412,13 +412,7 @@ class SipSessionGroup implements SipListener { processCommand(command); } catch (SipException e) { Log.w(TAG, "command error: " + command, e); - // TODO: find a better way to do this - if ((command instanceof RegisterCommand) - || (command == DEREGISTER)) { - onRegistrationFailed(e); - } else { - onError(e); - } + onError(e); } } }).start(); @@ -480,7 +474,9 @@ class SipSessionGroup implements SipListener { private void processCommand(EventObject command) throws SipException { if (!process(command)) { - throw new SipException("wrong state to execute: " + command); + onError(SipErrorCode.IN_PROGRESS, + "cannot initiate a new transaction to execute: " + + command); } } @@ -562,11 +558,8 @@ class SipSessionGroup implements SipListener { if (evt instanceof TimeoutEvent) { processTimeout((TimeoutEvent) evt); } else { - Log.d(TAG, "Transaction terminated:" + this); - if (!SipSessionState.IN_CALL.equals(mState)) { - removeSipSession(this); - } - return true; + processTransactionTerminated( + (TransactionTerminatedEvent) evt); } return true; } else if (evt instanceof DialogTerminatedEvent) { @@ -585,6 +578,20 @@ class SipSessionGroup implements SipListener { } } + private void processTransactionTerminated( + TransactionTerminatedEvent event) { + switch (mState) { + case IN_CALL: + case READY_TO_CALL: + Log.d(TAG, "Transaction terminated; do nothing"); + break; + default: + Log.d(TAG, "Transaction terminated early: " + this); + onError(SipErrorCode.TRANSACTION_TERMINTED, + "transaction terminated"); + } + } + private void processTimeout(TimeoutEvent event) { Log.d(TAG, "processing Timeout..." + event); Transaction current = event.isServerTransaction() @@ -600,25 +607,26 @@ class SipSessionGroup implements SipListener { return; } switch (mState) { - case REGISTERING: - case DEREGISTERING: - reset(); - mProxy.onRegistrationTimeout(this); - break; - case INCOMING_CALL: - case INCOMING_CALL_ANSWERING: - case OUTGOING_CALL_CANCELING: - endCallOnError(SipErrorCode.TIME_OUT, event.toString()); - break; - case PINGING: - reset(); - mReRegisterFlag = true; - mState = SipSessionState.READY_TO_CALL; - break; + case REGISTERING: + case DEREGISTERING: + reset(); + mProxy.onRegistrationTimeout(this); + break; + case INCOMING_CALL: + case INCOMING_CALL_ANSWERING: + case OUTGOING_CALL: + case OUTGOING_CALL_CANCELING: + onError(SipErrorCode.TIME_OUT, event.toString()); + break; + case PINGING: + reset(); + mReRegisterFlag = true; + mState = SipSessionState.READY_TO_CALL; + break; - default: - // do nothing - break; + default: + Log.d(TAG, " do nothing"); + break; } } @@ -665,7 +673,7 @@ class SipSessionGroup implements SipListener { } else { Log.w(TAG, "peer did not respect our rport request"); } - mState = SipSessionState.READY_TO_CALL; + reset(); return true; } return false; @@ -687,7 +695,6 @@ class SipSessionGroup implements SipListener { switch (statusCode) { case Response.OK: SipSessionState state = mState; - reset(); onRegistrationDone((state == SipSessionState.REGISTERING) ? getExpiryTime(((ResponseEvent) evt).getResponse()) : -1); @@ -698,15 +705,13 @@ class SipSessionGroup implements SipListener { case Response.PROXY_AUTHENTICATION_REQUIRED: if (!handleAuthentication(event)) { Log.v(TAG, "Incorrect username/password"); - reset(); onRegistrationFailed(SipErrorCode.INVALID_CREDENTIALS, "incorrect username or password"); } return true; default: if (statusCode >= 500) { - reset(); - onRegistrationFailed(createCallbackException(response)); + onRegistrationFailed(response); return true; } } @@ -720,7 +725,6 @@ class SipSessionGroup implements SipListener { String nonce = getNonceFromResponse(response); if (((nonce != null) && nonce.equals(mLastNonce)) || (nonce == mLastNonce)) { - Log.v(TAG, "Incorrect username/password"); return false; } else { mClientTransaction = mSipHelper.handleChallenge( @@ -906,7 +910,7 @@ class SipSessionGroup implements SipListener { } if (statusCode >= 400) { - onError(createCallbackException(response)); + onError(response); return true; } } else if (evt instanceof TransactionTerminatedEvent) { @@ -954,10 +958,6 @@ class SipSessionGroup implements SipListener { response.getReasonPhrase(), response.getStatusCode()); } - private Exception createCallbackException(Response response) { - return new SipException(createErrorMessage(response)); - } - private void establishCall() { mState = SipSessionState.IN_CALL; mInCall = true; @@ -965,22 +965,22 @@ class SipSessionGroup implements SipListener { } private void fallbackToPreviousInCall(Throwable exception) { - mState = SipSessionState.IN_CALL; exception = getRootCause(exception); - mProxy.onCallChangeFailed(this, getErrorCode(exception).toString(), + fallbackToPreviousInCall(getErrorCode(exception), exception.toString()); } + private void fallbackToPreviousInCall(SipErrorCode errorCode, + String message) { + mState = SipSessionState.IN_CALL; + mProxy.onCallChangeFailed(this, errorCode.toString(), message); + } + private void endCallNormally() { reset(); mProxy.onCallEnded(this); } - private void endCallOnError(Throwable exception) { - exception = getRootCause(exception); - endCallOnError(getErrorCode(exception), exception.toString()); - } - private void endCallOnError(SipErrorCode errorCode, String message) { reset(); mProxy.onError(this, errorCode.toString(), message); @@ -991,26 +991,34 @@ class SipSessionGroup implements SipListener { mProxy.onCallBusy(this); } - private void onError(Throwable exception) { - if (mInCall) { - fallbackToPreviousInCall(exception); - } else { - endCallOnError(exception); + private void onError(SipErrorCode errorCode, String message) { + switch (mState) { + case REGISTERING: + case DEREGISTERING: + onRegistrationFailed(errorCode, message); + break; + default: + if (mInCall) { + fallbackToPreviousInCall(errorCode, message); + } else { + endCallOnError(errorCode, message); + } } } + + private void onError(Throwable exception) { + exception = getRootCause(exception); + onError(getErrorCode(exception), exception.toString()); + } + private void onError(Response response) { - if (mInCall) { - fallbackToPreviousInCall(createCallbackException(response)); + int statusCode = response.getStatusCode(); + if (!mInCall && ((statusCode == Response.TEMPORARILY_UNAVAILABLE) + || (statusCode == Response.BUSY_HERE))) { + endCallOnBusy(); } else { - int statusCode = response.getStatusCode(); - if ((statusCode == Response.TEMPORARILY_UNAVAILABLE) - || (statusCode == Response.BUSY_HERE)) { - endCallOnBusy(); - } else { - endCallOnError(getErrorCode(statusCode), - createErrorMessage(response)); - } + onError(getErrorCode(statusCode), createErrorMessage(response)); } } @@ -1053,19 +1061,29 @@ class SipSessionGroup implements SipListener { } private void onRegistrationDone(int duration) { + reset(); mProxy.onRegistrationDone(this, duration); } private void onRegistrationFailed(SipErrorCode errorCode, String message) { + reset(); mProxy.onRegistrationFailed(this, errorCode.toString(), message); } private void onRegistrationFailed(Throwable exception) { + reset(); exception = getRootCause(exception); onRegistrationFailed(getErrorCode(exception), exception.toString()); } + + private void onRegistrationFailed(Response response) { + reset(); + int statusCode = response.getStatusCode(); + onRegistrationFailed(getErrorCode(statusCode), + createErrorMessage(response)); + } } /** diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java index e5456e4..c20c200 100644 --- a/telephony/java/com/android/internal/telephony/Connection.java +++ b/telephony/java/com/android/internal/telephony/Connection.java @@ -40,6 +40,7 @@ public abstract class Connection { MMI, /* not presently used; dial() returns null */ INVALID_NUMBER, /* invalid dial string */ INVALID_CREDENTIALS, /* invalid credentials */ + TIMED_OUT, /* client timed out */ LOST_SIGNAL, LIMIT_EXCEEDED, /* eg GSM ACM limit exceeded */ INCOMING_REJECTED, /* an incoming call that was rejected */ diff --git a/telephony/java/com/android/internal/telephony/sip/SipPhone.java b/telephony/java/com/android/internal/telephony/sip/SipPhone.java index fd90610..2c99145 100755 --- a/telephony/java/com/android/internal/telephony/sip/SipPhone.java +++ b/telephony/java/com/android/internal/telephony/sip/SipPhone.java @@ -826,7 +826,8 @@ public class SipPhone extends SipPhoneBase { onError(Connection.DisconnectCause.INVALID_NUMBER); break; case TIME_OUT: - onError(Connection.DisconnectCause.CONGESTION); + case TRANSACTION_TERMINTED: + onError(Connection.DisconnectCause.TIMED_OUT); break; case INVALID_CREDENTIALS: onError(Connection.DisconnectCause.INVALID_CREDENTIALS); diff --git a/voip/java/android/net/sip/SipErrorCode.java b/voip/java/android/net/sip/SipErrorCode.java index 2eb67e8..8624811 100644 --- a/voip/java/android/net/sip/SipErrorCode.java +++ b/voip/java/android/net/sip/SipErrorCode.java @@ -31,6 +31,9 @@ public enum SipErrorCode { /** When server responds with an error. */ SERVER_ERROR, + /** When transaction is terminated unexpectedly. */ + TRANSACTION_TERMINTED, + /** When some error occurs on the device, possibly due to a bug. */ CLIENT_ERROR, @@ -41,5 +44,8 @@ public enum SipErrorCode { INVALID_REMOTE_URI, /** When invalid credentials are provided. */ - INVALID_CREDENTIALS; + INVALID_CREDENTIALS, + + /** The client is in a transaction and cannot initiate a new one. */ + IN_PROGRESS; } |