Add HostsideVpnTests for testing setVpnDefaultForUids()

The test will check if the VPN will be the only default network
for the app after ConnectivityManager#setVpnDefaultForUids() is
called.

Bug: 231749077
Test: atest CtsHostsideNetworkTests:HostsideVpnTests
Change-Id: I02758ad7d948342797b6a4b00dfec3acdf44775d
This commit is contained in:
lucaslin
2022-12-20 09:02:15 +00:00
parent 220332b9c5
commit cf52cee443
3 changed files with 68 additions and 6 deletions

View File

@@ -97,6 +97,7 @@ import android.system.StructPollfd;
import android.telephony.TelephonyManager; import android.telephony.TelephonyManager;
import android.test.MoreAsserts; import android.test.MoreAsserts;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log; import android.util.Log;
import android.util.Range; import android.util.Range;
@@ -108,6 +109,7 @@ import com.android.net.module.util.PacketBuilder;
import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.RecorderCallback; import com.android.testutils.RecorderCallback;
import com.android.testutils.RecorderCallback.CallbackEntry;
import com.android.testutils.TestableNetworkCallback; import com.android.testutils.TestableNetworkCallback;
import org.junit.After; import org.junit.After;
@@ -136,6 +138,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Random; import java.util.Random;
import java.util.UUID;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -839,8 +842,13 @@ public class VpnTest {
callback.eventuallyExpect(RecorderCallback.CallbackEntry.NETWORK_CAPS_UPDATED, callback.eventuallyExpect(RecorderCallback.CallbackEntry.NETWORK_CAPS_UPDATED,
NETWORK_CALLBACK_TIMEOUT_MS, NETWORK_CALLBACK_TIMEOUT_MS,
entry -> (Objects.equals(expectUnderlyingNetworks, entry -> (Objects.equals(expectUnderlyingNetworks,
((RecorderCallback.CallbackEntry.CapabilitiesChanged) entry) entry.getCaps().getUnderlyingNetworks())));
.getCaps().getUnderlyingNetworks()))); }
private void expectVpnNetwork(TestableNetworkCallback callback) {
callback.eventuallyExpect(RecorderCallback.CallbackEntry.NETWORK_CAPS_UPDATED,
NETWORK_CALLBACK_TIMEOUT_MS,
entry -> entry.getCaps().hasTransport(TRANSPORT_VPN));
} }
@Test @IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available @Test @IgnoreUpTo(SC_V2) // TODO: Use to Build.VERSION_CODES.SC_V2 when available
@@ -1622,7 +1630,7 @@ public class VpnTest {
mCM.registerDefaultNetworkCallbackForUid(remoteUid, remoteUidCallback, mCM.registerDefaultNetworkCallbackForUid(remoteUid, remoteUidCallback,
new Handler(Looper.getMainLooper())); new Handler(Looper.getMainLooper()));
}, NETWORK_SETTINGS); }, NETWORK_SETTINGS);
remoteUidCallback.expectAvailableCallbacks(network); remoteUidCallback.expectAvailableCallbacksWithBlockedReasonNone(network);
// The remote UDP socket can receive packets coming from the TUN interface // The remote UDP socket can receive packets coming from the TUN interface
checkBlockIncomingPacket(tunFd, remoteUdpFd, EXPECT_PASS); checkBlockIncomingPacket(tunFd, remoteUdpFd, EXPECT_PASS);
@@ -1666,6 +1674,56 @@ public class VpnTest {
}); });
} }
@Test
public void testSetVpnDefaultForUids() throws Exception {
assumeTrue(supportedHardware());
assumeTrue(SdkLevel.isAtLeastU());
final Network defaultNetwork = mCM.getActiveNetwork();
assertNotNull("There must be a default network", defaultNetwork);
final TestableNetworkCallback defaultNetworkCallback = new TestableNetworkCallback();
final String session = UUID.randomUUID().toString();
final int myUid = Process.myUid();
testAndCleanup(() -> {
mCM.registerDefaultNetworkCallback(defaultNetworkCallback);
defaultNetworkCallback.expectAvailableCallbacks(defaultNetwork);
final Range<Integer> myUidRange = new Range<>(myUid, myUid);
runWithShellPermissionIdentity(() -> {
mCM.setVpnDefaultForUids(session, List.of(myUidRange));
}, NETWORK_SETTINGS);
// The VPN will be the only default network for the app, so it's expected to receive
// onLost() callback.
defaultNetworkCallback.eventuallyExpect(CallbackEntry.LOST);
final ArrayList<Network> underlyingNetworks = new ArrayList<>();
underlyingNetworks.add(defaultNetwork);
startVpn(new String[] {"192.0.2.2/32", "2001:db8:1:2::ffe/128"} /* addresses */,
new String[] {"0.0.0.0/0", "::/0"} /* routes */,
"" /* allowedApplications */, "" /* disallowedApplications */,
null /* proxyInfo */, underlyingNetworks, false /* isAlwaysMetered */);
expectVpnNetwork(defaultNetworkCallback);
}, /* cleanup */ () -> {
stopVpn();
defaultNetworkCallback.eventuallyExpect(CallbackEntry.LOST);
}, /* cleanup */ () -> {
runWithShellPermissionIdentity(() -> {
mCM.setVpnDefaultForUids(session, new ArraySet<>());
}, NETWORK_SETTINGS);
// The default network of the app will be changed back to wifi when the VPN network
// preference feature is disabled.
defaultNetworkCallback.eventuallyExpect(CallbackEntry.AVAILABLE,
NETWORK_CALLBACK_TIMEOUT_MS,
entry -> defaultNetwork.equals(entry.getNetwork()));
}, /* cleanup */ () -> {
mCM.unregisterNetworkCallback(defaultNetworkCallback);
});
}
private ByteBuffer buildIpv4UdpPacket(final Inet4Address dstAddr, final Inet4Address srcAddr, private ByteBuffer buildIpv4UdpPacket(final Inet4Address dstAddr, final Inet4Address srcAddr,
final short dstPort, final short srcPort, final byte[] payload) throws IOException { final short dstPort, final short srcPort, final byte[] payload) throws IOException {
@@ -1756,7 +1814,7 @@ public class VpnTest {
} }
private class DetailedBlockedStatusCallback extends TestableNetworkCallback { private class DetailedBlockedStatusCallback extends TestableNetworkCallback {
public void expectAvailableCallbacks(Network network) { public void expectAvailableCallbacksWithBlockedReasonNone(Network network) {
super.expectAvailableCallbacks(network, false /* suspended */, true /* validated */, super.expectAvailableCallbacks(network, false /* suspended */, true /* validated */,
BLOCKED_REASON_NONE, NETWORK_CALLBACK_TIMEOUT_MS); BLOCKED_REASON_NONE, NETWORK_CALLBACK_TIMEOUT_MS);
} }

View File

@@ -120,4 +120,8 @@ public class HostsideVpnTests extends HostsideNetworkTestCase {
public void testBlockIncomingPackets() throws Exception { public void testBlockIncomingPackets() throws Exception {
runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testBlockIncomingPackets"); runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testBlockIncomingPackets");
} }
public void testSetVpnDefaultForUids() throws Exception {
runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testSetVpnDefaultForUids");
}
} }

View File

@@ -2379,7 +2379,7 @@ public class ConnectivityManagerTest {
} }
private class DetailedBlockedStatusCallback extends TestableNetworkCallback { private class DetailedBlockedStatusCallback extends TestableNetworkCallback {
public void expectAvailableCallbacks(Network network) { public void expectAvailableCallbacksWithBlockedReasonNone(Network network) {
super.expectAvailableCallbacks(network, false /* suspended */, true /* validated */, super.expectAvailableCallbacks(network, false /* suspended */, true /* validated */,
BLOCKED_REASON_NONE, NETWORK_CALLBACK_TIMEOUT_MS); BLOCKED_REASON_NONE, NETWORK_CALLBACK_TIMEOUT_MS);
} }
@@ -2432,7 +2432,7 @@ public class ConnectivityManagerTest {
final List<DetailedBlockedStatusCallback> allCallbacks = final List<DetailedBlockedStatusCallback> allCallbacks =
List.of(myUidCallback, otherUidCallback); List.of(myUidCallback, otherUidCallback);
for (DetailedBlockedStatusCallback callback : allCallbacks) { for (DetailedBlockedStatusCallback callback : allCallbacks) {
callback.expectAvailableCallbacks(defaultNetwork); callback.expectAvailableCallbacksWithBlockedReasonNone(defaultNetwork);
} }
final Range<Integer> myUidRange = new Range<>(myUid, myUid); final Range<Integer> myUidRange = new Range<>(myUid, myUid);