summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHung-ying Tyan <tyanh@google.com>2010-09-13 02:48:22 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2010-09-13 02:48:22 -0700
commita5dce0c15ac05724b4595d62d521a481c7e1f86a (patch)
treea047413cf22bd0fd14ac5db76809b157b8d2b6c7
parent38dc67f49ec77d34c858777144323960c37d045e (diff)
parent3d7606aa607b24817e37c264f2141ed7b2d50be0 (diff)
downloadframeworks_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.
-rw-r--r--services/java/com/android/server/sip/SipService.java103
-rw-r--r--services/java/com/android/server/sip/SipSessionGroup.java146
-rw-r--r--telephony/java/com/android/internal/telephony/Connection.java1
-rwxr-xr-xtelephony/java/com/android/internal/telephony/sip/SipPhone.java3
-rw-r--r--voip/java/android/net/sip/SipErrorCode.java8
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;
}