Merge changes from topic "ka05" am: 908eb08326 am: 9a4614f4b0

am: ee5162e5b5

Change-Id: Ie56c431a6d934c752d1de30fc4bf98a7e557e5b2
This commit is contained in:
Junyu Lai
2019-01-23 22:24:41 -08:00
committed by android-build-merger
7 changed files with 692 additions and 21 deletions

View File

@@ -107,6 +107,8 @@ import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
import android.net.IpSecManager;
import android.net.IpSecManager.UdpEncapsulationSocket;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.MatchAllNetworkSpecifier;
@@ -122,6 +124,7 @@ import android.net.NetworkSpecifier;
import android.net.NetworkStack;
import android.net.NetworkUtils;
import android.net.RouteInfo;
import android.net.SocketKeepalive;
import android.net.UidRange;
import android.net.metrics.IpConnectivityLog;
import android.net.shared.NetworkMonitorUtils;
@@ -186,6 +189,8 @@ import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -402,8 +407,8 @@ public class ConnectivityServiceTest {
private final ConditionVariable mPreventReconnectReceived = new ConditionVariable();
private int mScore;
private NetworkAgent mNetworkAgent;
private int mStartKeepaliveError = PacketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
private int mStopKeepaliveError = PacketKeepalive.NO_KEEPALIVE;
private int mStartKeepaliveError = SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED;
private int mStopKeepaliveError = SocketKeepalive.NO_KEEPALIVE;
private Integer mExpectedKeepaliveSlot = null;
// Contains the redirectUrl from networkStatus(). Before reading, wait for
// mNetworkStatusReceived.
@@ -3548,6 +3553,80 @@ public class ConnectivityServiceTest {
}
}
private static class TestSocketKeepaliveCallback extends SocketKeepalive.Callback {
public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
private class CallbackValue {
public CallbackType callbackType;
public int error;
CallbackValue(CallbackType type) {
this.callbackType = type;
this.error = SocketKeepalive.SUCCESS;
assertTrue("onError callback must have error", type != CallbackType.ON_ERROR);
}
CallbackValue(CallbackType type, int error) {
this.callbackType = type;
this.error = error;
assertEquals("error can only be set for onError", type, CallbackType.ON_ERROR);
}
@Override
public boolean equals(Object o) {
return o instanceof CallbackValue
&& this.callbackType == ((CallbackValue) o).callbackType
&& this.error == ((CallbackValue) o).error;
}
@Override
public String toString() {
return String.format("%s(%s, %d)", getClass().getSimpleName(), callbackType,
error);
}
}
private LinkedBlockingQueue<CallbackValue> mCallbacks = new LinkedBlockingQueue<>();
@Override
public void onStarted() {
mCallbacks.add(new CallbackValue(CallbackType.ON_STARTED));
}
@Override
public void onStopped() {
mCallbacks.add(new CallbackValue(CallbackType.ON_STOPPED));
}
@Override
public void onError(int error) {
mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
}
private void expectCallback(CallbackValue callbackValue) {
try {
assertEquals(
callbackValue,
mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
}
}
public void expectStarted() {
expectCallback(new CallbackValue(CallbackType.ON_STARTED));
}
public void expectStopped() {
expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
}
public void expectError(int error) {
expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
}
}
private Network connectKeepaliveNetwork(LinkProperties lp) {
// Ensure the network is disconnected before we do anything.
if (mWiFiNetworkAgent != null) {
@@ -3694,6 +3773,145 @@ public class ConnectivityServiceTest {
callback3.expectStopped();
}
@Test
public void testNattSocketKeepalives() throws Exception {
// TODO: 1. Move this outside of ConnectivityServiceTest.
// 2. Add helper function to test against newSingleThreadExecutor as well as inline
// executor.
// 3. Make test to verify that Nat-T keepalive socket is created by IpSecService.
final int srcPort = 12345;
final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
final InetAddress dstIPv6 = InetAddress.getByName("2001:4860:4860::8888");
final int validKaInterval = 15;
final int invalidKaInterval = 9;
final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(srcPort);
final Executor executor = Executors.newSingleThreadExecutor();
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("wlan12");
lp.addLinkAddress(new LinkAddress(myIPv6, 64));
lp.addLinkAddress(new LinkAddress(myIPv4, 25));
lp.addRoute(new RouteInfo(InetAddress.getByName("fe80::1234")));
lp.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254")));
Network notMyNet = new Network(61234);
Network myNet = connectKeepaliveNetwork(lp);
TestSocketKeepaliveCallback callback = new TestSocketKeepaliveCallback();
SocketKeepalive ka;
// Attempt to start keepalives with invalid parameters and check for errors.
// Invalid network.
ka = mCm.createSocketKeepalive(notMyNet, testSocket, myIPv4, dstIPv4, executor, callback);
ka.start(validKaInterval);
callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
// Invalid interval.
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
ka.start(invalidKaInterval);
callback.expectError(SocketKeepalive.ERROR_INVALID_INTERVAL);
// Invalid destination.
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv6, executor, callback);
ka.start(validKaInterval);
callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
// Invalid source;
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv6, dstIPv4, executor, callback);
ka.start(validKaInterval);
callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
// NAT-T is only supported for IPv4.
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv6, dstIPv6, executor, callback);
ka.start(validKaInterval);
callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
// Sanity check before testing started keepalive.
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
ka.start(validKaInterval);
callback.expectError(SocketKeepalive.ERROR_HARDWARE_UNSUPPORTED);
// Check that a started keepalive can be stopped.
mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
ka.start(validKaInterval);
callback.expectStarted();
mWiFiNetworkAgent.setStopKeepaliveError(SocketKeepalive.SUCCESS);
ka.stop();
callback.expectStopped();
// Check that deleting the IP address stops the keepalive.
LinkProperties bogusLp = new LinkProperties(lp);
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
ka.start(validKaInterval);
callback.expectStarted();
bogusLp.removeLinkAddress(new LinkAddress(myIPv4, 25));
bogusLp.addLinkAddress(new LinkAddress(notMyIPv4, 25));
mWiFiNetworkAgent.sendLinkProperties(bogusLp);
callback.expectError(SocketKeepalive.ERROR_INVALID_IP_ADDRESS);
mWiFiNetworkAgent.sendLinkProperties(lp);
// Check that a started keepalive is stopped correctly when the network disconnects.
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
ka.start(validKaInterval);
callback.expectStarted();
mWiFiNetworkAgent.disconnect();
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
callback.expectError(SocketKeepalive.ERROR_INVALID_NETWORK);
// ... and that stopping it after that has no adverse effects.
waitForIdle();
final Network myNetAlias = myNet;
assertNull(mCm.getNetworkCapabilities(myNetAlias));
ka.stop();
// Reconnect.
myNet = connectKeepaliveNetwork(lp);
mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
// Check things work as expected when the keepalive is stopped and the network disconnects.
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
ka.start(validKaInterval);
callback.expectStarted();
ka.stop();
mWiFiNetworkAgent.disconnect();
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
waitForIdle();
callback.expectStopped();
// Reconnect.
myNet = connectKeepaliveNetwork(lp);
mWiFiNetworkAgent.setStartKeepaliveError(SocketKeepalive.SUCCESS);
// Check that keepalive slots start from 1 and increment. The first one gets slot 1.
mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
ka = mCm.createSocketKeepalive(myNet, testSocket, myIPv4, dstIPv4, executor, callback);
ka.start(validKaInterval);
callback.expectStarted();
// The second one gets slot 2.
mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(6789);
TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback();
SocketKeepalive ka2 =
mCm.createSocketKeepalive(myNet, testSocket2, myIPv4, dstIPv4, executor, callback2);
ka2.start(validKaInterval);
callback2.expectStarted();
ka.stop();
callback.expectStopped();
ka2.stop();
callback2.expectStopped();
}
@Test
public void testGetCaptivePortalServerUrl() throws Exception {
String url = mCm.getCaptivePortalServerUrl();