Merge "Restart NAT port timeout measurement when keepalive fails and other fixes"
diff --git a/voip/java/com/android/server/sip/SipService.java b/voip/java/com/android/server/sip/SipService.java
index f8e5b3a..3b0f546 100644
--- a/voip/java/com/android/server/sip/SipService.java
+++ b/voip/java/com/android/server/sip/SipService.java
@@ -462,17 +462,30 @@
private void startPortMappingLifetimeMeasurement(
SipProfile localProfile) {
+ startPortMappingLifetimeMeasurement(localProfile, -1);
+ }
+
+ private void startPortMappingLifetimeMeasurement(
+ SipProfile localProfile, int maxInterval) {
if ((mIntervalMeasurementProcess == null)
&& (mKeepAliveInterval == -1)
&& isBehindNAT(mLocalIp)) {
Log.d(TAG, "start NAT port mapping timeout measurement on "
+ localProfile.getUriString());
- mIntervalMeasurementProcess = new IntervalMeasurementProcess(localProfile);
+ mIntervalMeasurementProcess =
+ new IntervalMeasurementProcess(localProfile, maxInterval);
mIntervalMeasurementProcess.start();
}
}
+ private void restartPortMappingLifetimeMeasurement(
+ SipProfile localProfile, int maxInterval) {
+ stopPortMappingMeasurement();
+ mKeepAliveInterval = -1;
+ startPortMappingLifetimeMeasurement(localProfile, maxInterval);
+ }
+
private synchronized void addPendingSession(ISipSession session) {
try {
cleanUpPendingSessions();
@@ -746,18 +759,30 @@
private class IntervalMeasurementProcess implements
SipSessionGroup.KeepAliveProcessCallback {
private static final String TAG = "SipKeepAliveInterval";
- private static final int MAX_INTERVAL = 120; // seconds
- private static final int MIN_INTERVAL = SHORT_EXPIRY_TIME;
+ private static final int MAX_INTERVAL = 120; // in seconds
+ private static final int MIN_INTERVAL = 10; // in seconds
private static final int PASS_THRESHOLD = 10;
+ private static final int MAX_RETRY_COUNT = 5;
private SipSessionGroupExt mGroup;
private SipSessionGroup.SipSessionImpl mSession;
private boolean mRunning;
private int mMinInterval = 10; // in seconds
- private int mMaxInterval = MAX_INTERVAL;
- private int mInterval = MAX_INTERVAL / 2;
- private int mPassCounter = 0;
+ private int mMaxInterval;
+ private int mInterval;
+ private int mPassCount = 0;
+ private int mErrorCount = 0;
- public IntervalMeasurementProcess(SipProfile localProfile) {
+ public IntervalMeasurementProcess(SipProfile localProfile, int maxInterval) {
+ mMaxInterval = (maxInterval < 0) ? MAX_INTERVAL : maxInterval;
+ mInterval = (mMaxInterval + mMinInterval) / 2;
+
+ // Don't start measurement if the interval is too small
+ if (mInterval < MIN_INTERVAL) {
+ Log.w(TAG, "interval is too small; measurement aborted; "
+ + "maxInterval=" + mMaxInterval);
+ return;
+ }
+
try {
mGroup = new SipSessionGroupExt(localProfile, null, null);
// TODO: remove this line once SipWakeupTimer can better handle
@@ -801,8 +826,10 @@
@Override
public void onResponse(boolean portChanged) {
synchronized (SipService.this) {
+ mErrorCount = 0;
+
if (!portChanged) {
- if (++mPassCounter != PASS_THRESHOLD) return;
+ if (++mPassCount != PASS_THRESHOLD) return;
// update the interval, since the current interval is good to
// keep the port mapping.
mKeepAliveInterval = mMinInterval = mInterval;
@@ -826,7 +853,7 @@
} else {
// calculate the new interval and continue.
mInterval = (mMaxInterval + mMinInterval) / 2;
- mPassCounter = 0;
+ mPassCount = 0;
if (DEBUG) {
Log.d(TAG, "current interval: " + mKeepAliveInterval
+ ", test new interval: " + mInterval);
@@ -841,6 +868,13 @@
public void onError(int errorCode, String description) {
synchronized (SipService.this) {
Log.w(TAG, "interval measurement error: " + description);
+ if (++mErrorCount < MAX_RETRY_COUNT) {
+ Log.w(TAG, " retry count = " + mErrorCount);
+ mPassCount = 0;
+ restart();
+ } else {
+ Log.w(TAG, " max retry count reached; measurement aborted");
+ }
}
}
}
@@ -885,9 +919,15 @@
@Override
public void onResponse(boolean portChanged) {
synchronized (SipService.this) {
- // Start keep-alive interval measurement on the first successfully
- // kept-alive SipSessionGroup
- startPortMappingLifetimeMeasurement(mSession.getLocalProfile());
+ if (portChanged) {
+ restartPortMappingLifetimeMeasurement(
+ mSession.getLocalProfile(), getKeepAliveInterval());
+ } else {
+ // Start keep-alive interval measurement on the first
+ // successfully kept-alive SipSessionGroup
+ startPortMappingLifetimeMeasurement(
+ mSession.getLocalProfile());
+ }
if (!mRunning || !portChanged) return;
@@ -907,6 +947,7 @@
@Override
public void onError(int errorCode, String description) {
Log.e(TAG, "keepalive error: " + description);
+ onResponse(true); // re-register immediately
}
public void stop() {
diff --git a/voip/java/com/android/server/sip/SipSessionGroup.java b/voip/java/com/android/server/sip/SipSessionGroup.java
index cc3e4109..2d0dd9c 100644
--- a/voip/java/com/android/server/sip/SipSessionGroup.java
+++ b/voip/java/com/android/server/sip/SipSessionGroup.java
@@ -1259,11 +1259,13 @@
private boolean mPortChanged = false;
private int mRPort = 0;
+ private int mInterval; // just for debugging
// @param interval in seconds
void start(int interval, KeepAliveProcessCallback callback) {
if (mRunning) return;
mRunning = true;
+ mInterval = interval;
mCallback = new KeepAliveProcessCallbackProxy(callback);
mWakeupTimer.set(interval * 1000, this);
if (DEBUG) {
@@ -1311,7 +1313,7 @@
if (DEBUG_PING) {
Log.d(TAG, "keepalive: " + mLocalProfile.getUriString()
- + " --> " + mPeerProfile);
+ + " --> " + mPeerProfile + ", interval=" + mInterval);
}
try {
sendKeepAlive();