Merge "Adjust polling interval for auto on/off keepalives"
This commit is contained in:
@@ -18,6 +18,7 @@ package com.android.server.connectivity;
|
|||||||
|
|
||||||
import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE;
|
import static android.net.NetworkAgent.CMD_START_SOCKET_KEEPALIVE;
|
||||||
import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET;
|
import static android.net.SocketKeepalive.ERROR_INVALID_SOCKET;
|
||||||
|
import static android.net.SocketKeepalive.MIN_INTERVAL_SEC;
|
||||||
import static android.net.SocketKeepalive.SUCCESS_PAUSED;
|
import static android.net.SocketKeepalive.SUCCESS_PAUSED;
|
||||||
import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
|
import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
|
||||||
import static android.system.OsConstants.AF_INET;
|
import static android.system.OsConstants.AF_INET;
|
||||||
@@ -88,8 +89,8 @@ import java.util.Objects;
|
|||||||
public class AutomaticOnOffKeepaliveTracker {
|
public class AutomaticOnOffKeepaliveTracker {
|
||||||
private static final String TAG = "AutomaticOnOffKeepaliveTracker";
|
private static final String TAG = "AutomaticOnOffKeepaliveTracker";
|
||||||
private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET6, AF_INET};
|
private static final int[] ADDRESS_FAMILIES = new int[] {AF_INET6, AF_INET};
|
||||||
private static final long DEFAULT_TCP_POLLING_INTERVAL_MS = 120_000L;
|
|
||||||
private static final long LOW_TCP_POLLING_INTERVAL_MS = 1_000L;
|
private static final long LOW_TCP_POLLING_INTERVAL_MS = 1_000L;
|
||||||
|
private static final int ADJUST_TCP_POLLING_DELAY_MS = 2000;
|
||||||
private static final String AUTOMATIC_ON_OFF_KEEPALIVE_VERSION =
|
private static final String AUTOMATIC_ON_OFF_KEEPALIVE_VERSION =
|
||||||
"automatic_on_off_keepalive_version";
|
"automatic_on_off_keepalive_version";
|
||||||
/**
|
/**
|
||||||
@@ -280,12 +281,14 @@ public class AutomaticOnOffKeepaliveTracker {
|
|||||||
mAlarmManager = mDependencies.getAlarmManager(context);
|
mAlarmManager = mDependencies.getAlarmManager(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startTcpPollingAlarm(@NonNull final AlarmManager.OnAlarmListener listener) {
|
private void startTcpPollingAlarm(@NonNull AutomaticOnOffKeepalive ki) {
|
||||||
|
if (ki.mAlarmListener == null) return;
|
||||||
|
|
||||||
final long triggerAtMillis =
|
final long triggerAtMillis =
|
||||||
SystemClock.elapsedRealtime() + getTcpPollingInterval();
|
mDependencies.getElapsedRealtime() + getTcpPollingIntervalMs(ki);
|
||||||
// Setup a non-wake up alarm.
|
// Setup a non-wake up alarm.
|
||||||
mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, triggerAtMillis, null /* tag */,
|
mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME, triggerAtMillis, null /* tag */,
|
||||||
listener, mConnectivityServiceHandler);
|
ki.mAlarmListener, mConnectivityServiceHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -322,7 +325,7 @@ public class AutomaticOnOffKeepaliveTracker {
|
|||||||
handleMaybeResumeKeepalive(ki);
|
handleMaybeResumeKeepalive(ki);
|
||||||
}
|
}
|
||||||
// TODO: listen to socket status instead of periodically check.
|
// TODO: listen to socket status instead of periodically check.
|
||||||
startTcpPollingAlarm(ki.mAlarmListener);
|
startTcpPollingAlarm(ki);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -402,7 +405,7 @@ public class AutomaticOnOffKeepaliveTracker {
|
|||||||
}
|
}
|
||||||
mAutomaticOnOffKeepalives.add(autoKi);
|
mAutomaticOnOffKeepalives.add(autoKi);
|
||||||
if (STATE_ALWAYS_ON != autoKi.mAutomaticOnOffState) {
|
if (STATE_ALWAYS_ON != autoKi.mAutomaticOnOffState) {
|
||||||
startTcpPollingAlarm(autoKi.mAlarmListener);
|
startTcpPollingAlarm(autoKi);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,9 +680,15 @@ public class AutomaticOnOffKeepaliveTracker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private long getTcpPollingInterval() {
|
private long getTcpPollingIntervalMs(@NonNull AutomaticOnOffKeepalive ki) {
|
||||||
final boolean useLowTimer = mTestLowTcpPollingTimerUntilMs > System.currentTimeMillis();
|
final boolean useLowTimer = mTestLowTcpPollingTimerUntilMs > System.currentTimeMillis();
|
||||||
return useLowTimer ? LOW_TCP_POLLING_INTERVAL_MS : DEFAULT_TCP_POLLING_INTERVAL_MS;
|
// Adjust the polling interval to be smaller than the keepalive delay to preserve
|
||||||
|
// some time for the system to restart the keepalive.
|
||||||
|
final int timer = ki.mKi.getKeepaliveIntervalSec() * 1000 - ADJUST_TCP_POLLING_DELAY_MS;
|
||||||
|
if (timer < MIN_INTERVAL_SEC) {
|
||||||
|
Log.wtf(TAG, "Unreasonably low keepalive delay: " + ki.mKi.getKeepaliveIntervalSec());
|
||||||
|
}
|
||||||
|
return useLowTimer ? LOW_TCP_POLLING_INTERVAL_MS : Math.max(timer, MIN_INTERVAL_SEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -786,5 +795,14 @@ public class AutomaticOnOffKeepaliveTracker {
|
|||||||
return DeviceConfigUtils.isFeatureEnabled(mContext, NAMESPACE_TETHERING, name,
|
return DeviceConfigUtils.isFeatureEnabled(mContext, NAMESPACE_TETHERING, name,
|
||||||
defaultEnabled);
|
defaultEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns milliseconds since boot, including time spent in sleep.
|
||||||
|
*
|
||||||
|
* @return elapsed milliseconds since boot.
|
||||||
|
*/
|
||||||
|
public long getElapsedRealtime() {
|
||||||
|
return SystemClock.elapsedRealtime();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,6 +264,10 @@ public class KeepaliveTracker {
|
|||||||
return mSlot;
|
return mSlot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getKeepaliveIntervalSec() {
|
||||||
|
return mInterval;
|
||||||
|
}
|
||||||
|
|
||||||
private int checkNetworkConnected() {
|
private int checkNetworkConnected() {
|
||||||
if (!mNai.networkInfo.isConnectedOrConnecting()) {
|
if (!mNai.networkInfo.isConnectedOrConnecting()) {
|
||||||
return ERROR_INVALID_NETWORK;
|
return ERROR_INVALID_NETWORK;
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ import static org.junit.Assert.assertTrue;
|
|||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||||
import static org.mockito.ArgumentMatchers.anyInt;
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
import static org.mockito.ArgumentMatchers.anyLong;
|
|
||||||
import static org.mockito.ArgumentMatchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
|
import static org.mockito.ArgumentMatchers.longThat;
|
||||||
import static org.mockito.Mockito.doNothing;
|
import static org.mockito.Mockito.doNothing;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
@@ -57,6 +57,7 @@ import android.os.HandlerThread;
|
|||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
|
import android.os.SystemClock;
|
||||||
import android.test.suitebuilder.annotation.SmallTest;
|
import android.test.suitebuilder.annotation.SmallTest;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
@@ -94,6 +95,7 @@ public class AutomaticOnOffKeepaliveTrackerTest {
|
|||||||
private static final int NETID_MASK = 0xffff;
|
private static final int NETID_MASK = 0xffff;
|
||||||
private static final int TIMEOUT_MS = 30_000;
|
private static final int TIMEOUT_MS = 30_000;
|
||||||
private static final int MOCK_RESOURCE_ID = 5;
|
private static final int MOCK_RESOURCE_ID = 5;
|
||||||
|
private static final int TEST_KEEPALIVE_INTERVAL_SEC = 10;
|
||||||
private AutomaticOnOffKeepaliveTracker mAOOKeepaliveTracker;
|
private AutomaticOnOffKeepaliveTracker mAOOKeepaliveTracker;
|
||||||
private HandlerThread mHandlerThread;
|
private HandlerThread mHandlerThread;
|
||||||
|
|
||||||
@@ -334,9 +336,13 @@ public class AutomaticOnOffKeepaliveTrackerTest {
|
|||||||
final KeepalivePacketData kpd = new NattKeepalivePacketData(srcAddress, srcPort,
|
final KeepalivePacketData kpd = new NattKeepalivePacketData(srcAddress, srcPort,
|
||||||
dstAddress, dstPort, new byte[] {1});
|
dstAddress, dstPort, new byte[] {1});
|
||||||
final KeepaliveInfo ki = mKeepaliveTracker.new KeepaliveInfo(cb, nai, kpd,
|
final KeepaliveInfo ki = mKeepaliveTracker.new KeepaliveInfo(cb, nai, kpd,
|
||||||
10 /* interval */, KeepaliveInfo.TYPE_NATT, fd);
|
TEST_KEEPALIVE_INTERVAL_SEC, KeepaliveInfo.TYPE_NATT, fd);
|
||||||
mKeepaliveTracker.setReturnedKeepaliveInfo(ki);
|
mKeepaliveTracker.setReturnedKeepaliveInfo(ki);
|
||||||
|
|
||||||
|
// Mock elapsed real time to verify the alarm timer.
|
||||||
|
final long time = SystemClock.elapsedRealtime();
|
||||||
|
doReturn(time).when(mDependencies).getElapsedRealtime();
|
||||||
|
|
||||||
mAOOKeepaliveTracker.startNattKeepalive(nai, fd, 10 /* intervalSeconds */, cb,
|
mAOOKeepaliveTracker.startNattKeepalive(nai, fd, 10 /* intervalSeconds */, cb,
|
||||||
srcAddress.toString(), srcPort, dstAddress.toString(), dstPort,
|
srcAddress.toString(), srcPort, dstAddress.toString(), dstPort,
|
||||||
true /* automaticOnOffKeepalives */, underpinnedNetwork);
|
true /* automaticOnOffKeepalives */, underpinnedNetwork);
|
||||||
@@ -344,8 +350,11 @@ public class AutomaticOnOffKeepaliveTrackerTest {
|
|||||||
|
|
||||||
final ArgumentCaptor<AlarmManager.OnAlarmListener> listenerCaptor =
|
final ArgumentCaptor<AlarmManager.OnAlarmListener> listenerCaptor =
|
||||||
ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
|
ArgumentCaptor.forClass(AlarmManager.OnAlarmListener.class);
|
||||||
verify(mAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME), anyLong(),
|
// The alarm timer should be smaller than the keepalive delay. Verify the alarm trigger time
|
||||||
any(), listenerCaptor.capture(), eq(mTestHandler));
|
// is higher than base time but smaller than the keepalive delay.
|
||||||
|
verify(mAlarmManager).setExact(eq(AlarmManager.ELAPSED_REALTIME),
|
||||||
|
longThat(t -> t > time + 1000L && t < time + TEST_KEEPALIVE_INTERVAL_SEC * 1000L),
|
||||||
|
any() /* tag */, listenerCaptor.capture(), eq(mTestHandler));
|
||||||
final AlarmManager.OnAlarmListener listener = listenerCaptor.getValue();
|
final AlarmManager.OnAlarmListener listener = listenerCaptor.getValue();
|
||||||
|
|
||||||
// For realism, the listener should be posted on the handler
|
// For realism, the listener should be posted on the handler
|
||||||
|
|||||||
Reference in New Issue
Block a user