Merge changes If13254d4,I2424bd4f
* changes:
Sendcallback when setting eth interface up
ethernet: add test for enable/disable interface
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index 770c092..a7028b7 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -85,7 +85,7 @@
bpfs: [
"block.o",
"clatd.o",
- "dscp_policy.o",
+ "dscpPolicy.o",
"netd.o",
"offload.o",
"offload@btf.o",
@@ -209,7 +209,7 @@
bpfs: [
"block.o",
"clatd.o",
- "dscp_policy.o",
+ "dscpPolicy.o",
"netd.o",
"offload@inprocess.o",
"test@inprocess.o",
diff --git a/Tethering/src/android/net/ip/NeighborPacketForwarder.java b/Tethering/src/android/net/ip/NeighborPacketForwarder.java
index 723bd63..8384562 100644
--- a/Tethering/src/android/net/ip/NeighborPacketForwarder.java
+++ b/Tethering/src/android/net/ip/NeighborPacketForwarder.java
@@ -23,6 +23,7 @@
import static android.system.OsConstants.SOCK_DGRAM;
import static android.system.OsConstants.SOCK_NONBLOCK;
import static android.system.OsConstants.SOCK_RAW;
+import static android.system.OsConstants.ENODEV;
import android.net.util.SocketUtils;
import android.os.Handler;
@@ -131,7 +132,13 @@
ETH_P_IPV6, mListenIfaceParams.index);
Os.bind(mFd, bindAddress);
} catch (ErrnoException | SocketException e) {
- Log.wtf(mTag, "Failed to create socket", e);
+ // An ENODEV(No such device) will rise if tethering stopped before this function, this
+ // may happen when enable/disable tethering quickly.
+ if (e instanceof ErrnoException && ((ErrnoException) e).errno == ENODEV) {
+ Log.w(mTag, "Failed to create socket because tethered interface is gone", e);
+ } else {
+ Log.wtf(mTag, "Failed to create socket", e);
+ }
closeSocketQuietly(mFd);
return null;
}
diff --git a/bpf_progs/Android.bp b/bpf_progs/Android.bp
index 6ab5281..c2e28f4 100644
--- a/bpf_progs/Android.bp
+++ b/bpf_progs/Android.bp
@@ -72,8 +72,8 @@
}
bpf {
- name: "dscp_policy.o",
- srcs: ["dscp_policy.c"],
+ name: "dscpPolicy.o",
+ srcs: ["dscpPolicy.c"],
btf: true,
cflags: [
"-Wall",
diff --git a/bpf_progs/dscp_policy.c b/bpf_progs/dscpPolicy.c
similarity index 99%
rename from bpf_progs/dscp_policy.c
rename to bpf_progs/dscpPolicy.c
index e45c1d4..25abd2b 100644
--- a/bpf_progs/dscp_policy.c
+++ b/bpf_progs/dscpPolicy.c
@@ -31,7 +31,7 @@
#define BPFLOADER_MIN_VER BPFLOADER_T_BETA3_VERSION
#include "bpf_helpers.h"
-#include "dscp_policy.h"
+#include "dscpPolicy.h"
#define ECN_MASK 3
#define IP4_OFFSET(field, header) (header + offsetof(struct iphdr, field))
diff --git a/bpf_progs/dscp_policy.h b/bpf_progs/dscpPolicy.h
similarity index 100%
rename from bpf_progs/dscp_policy.h
rename to bpf_progs/dscpPolicy.h
diff --git a/framework/src/android/net/ITestNetworkManager.aidl b/framework/src/android/net/ITestNetworkManager.aidl
index d18b931..9432acb 100644
--- a/framework/src/android/net/ITestNetworkManager.aidl
+++ b/framework/src/android/net/ITestNetworkManager.aidl
@@ -30,7 +30,8 @@
interface ITestNetworkManager
{
TestNetworkInterface createInterface(boolean isTun, boolean hasCarrier, boolean bringUp,
- in LinkAddress[] addrs, in @nullable String iface);
+ boolean disableIpv6ProvisioningDelay, in LinkAddress[] addrs,
+ in @nullable String iface);
void setCarrierEnabled(in TestNetworkInterface iface, boolean enabled);
diff --git a/framework/src/android/net/TestNetworkManager.java b/framework/src/android/net/TestNetworkManager.java
index 788834a..b64299f 100644
--- a/framework/src/android/net/TestNetworkManager.java
+++ b/framework/src/android/net/TestNetworkManager.java
@@ -59,6 +59,8 @@
private static final boolean TUN = true;
private static final boolean BRING_UP = true;
private static final boolean CARRIER_UP = true;
+ // sets disableIpv6ProvisioningDelay to false.
+ private static final boolean USE_IPV6_PROV_DELAY = false;
private static final LinkAddress[] NO_ADDRS = new LinkAddress[0];
/** @hide */
@@ -167,8 +169,8 @@
public TestNetworkInterface createTunInterface(@NonNull Collection<LinkAddress> linkAddrs) {
try {
final LinkAddress[] arr = new LinkAddress[linkAddrs.size()];
- return mService.createInterface(TUN, CARRIER_UP, BRING_UP, linkAddrs.toArray(arr),
- null /* iface */);
+ return mService.createInterface(TUN, CARRIER_UP, BRING_UP, USE_IPV6_PROV_DELAY,
+ linkAddrs.toArray(arr), null /* iface */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -186,7 +188,8 @@
@NonNull
public TestNetworkInterface createTapInterface() {
try {
- return mService.createInterface(TAP, CARRIER_UP, BRING_UP, NO_ADDRS, null /* iface */);
+ return mService.createInterface(TAP, CARRIER_UP, BRING_UP, USE_IPV6_PROV_DELAY,
+ NO_ADDRS, null /* iface */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -204,7 +207,8 @@
@NonNull
public TestNetworkInterface createTapInterface(@NonNull LinkAddress[] linkAddrs) {
try {
- return mService.createInterface(TAP, CARRIER_UP, BRING_UP, linkAddrs, null /* iface */);
+ return mService.createInterface(TAP, CARRIER_UP, BRING_UP, USE_IPV6_PROV_DELAY,
+ linkAddrs, null /* iface */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -223,7 +227,8 @@
@NonNull
public TestNetworkInterface createTapInterface(boolean bringUp) {
try {
- return mService.createInterface(TAP, CARRIER_UP, bringUp, NO_ADDRS, null /* iface */);
+ return mService.createInterface(TAP, CARRIER_UP, bringUp, USE_IPV6_PROV_DELAY,
+ NO_ADDRS, null /* iface */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -245,7 +250,8 @@
@NonNull
public TestNetworkInterface createTapInterface(boolean bringUp, @NonNull String iface) {
try {
- return mService.createInterface(TAP, CARRIER_UP, bringUp, NO_ADDRS, iface);
+ return mService.createInterface(TAP, CARRIER_UP, bringUp, USE_IPV6_PROV_DELAY,
+ NO_ADDRS, iface);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -264,7 +270,49 @@
@NonNull
public TestNetworkInterface createTapInterface(boolean carrierUp, boolean bringUp) {
try {
- return mService.createInterface(TAP, carrierUp, bringUp, NO_ADDRS, null /* iface */);
+ return mService.createInterface(TAP, carrierUp, bringUp, USE_IPV6_PROV_DELAY, NO_ADDRS,
+ null /* iface */);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Create a tap interface for testing purposes.
+ *
+ * @param carrierUp whether the created interface has a carrier or not.
+ * @param bringUp whether to bring up the interface before returning it.
+ * @param disableIpv6ProvisioningDelay whether to disable DAD and RS delay.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
+ @NonNull
+ public TestNetworkInterface createTapInterface(boolean carrierUp, boolean bringUp,
+ boolean disableIpv6ProvisioningDelay) {
+ try {
+ return mService.createInterface(TAP, carrierUp, bringUp, disableIpv6ProvisioningDelay,
+ NO_ADDRS, null /* iface */);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Create a tap interface for testing purposes.
+ *
+ * @param disableIpv6ProvisioningDelay whether to disable DAD and RS delay.
+ * @param linkAddrs an array of LinkAddresses to assign to the TAP interface
+ * @return A TestNetworkInterface representing the underlying TAP interface. Close the contained
+ * ParcelFileDescriptor to tear down the TAP interface.
+ * @hide
+ */
+ @RequiresPermission(Manifest.permission.MANAGE_TEST_NETWORKS)
+ @NonNull
+ public TestNetworkInterface createTapInterface(boolean disableIpv6ProvisioningDelay,
+ @NonNull LinkAddress[] linkAddrs) {
+ try {
+ return mService.createInterface(TAP, CARRIER_UP, BRING_UP, disableIpv6ProvisioningDelay,
+ linkAddrs, null /* iface */);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/service/src/com/android/server/TestNetworkService.java b/service/src/com/android/server/TestNetworkService.java
index 1209579..dc922f4 100644
--- a/service/src/com/android/server/TestNetworkService.java
+++ b/service/src/com/android/server/TestNetworkService.java
@@ -120,7 +120,7 @@
*/
@Override
public TestNetworkInterface createInterface(boolean isTun, boolean hasCarrier, boolean bringUp,
- LinkAddress[] linkAddrs, @Nullable String iface) {
+ boolean disableIpv6ProvisioningDelay, LinkAddress[] linkAddrs, @Nullable String iface) {
enforceTestNetworkPermissions(mContext);
Objects.requireNonNull(linkAddrs, "missing linkAddrs");
@@ -137,6 +137,14 @@
try {
ParcelFileDescriptor tunIntf = ParcelFileDescriptor.adoptFd(
nativeCreateTunTap(isTun, hasCarrier, interfaceName));
+
+ // Disable DAD and remove router_solicitation_delay before assigning link addresses.
+ if (disableIpv6ProvisioningDelay) {
+ mNetd.setProcSysNet(
+ INetd.IPV6, INetd.CONF, interfaceName, "router_solicitation_delay", "0");
+ mNetd.setProcSysNet(INetd.IPV6, INetd.CONF, interfaceName, "dad_transmits", "0");
+ }
+
for (LinkAddress addr : linkAddrs) {
mNetd.interfaceAddAddress(
interfaceName,
diff --git a/service/src/com/android/server/connectivity/DscpPolicyTracker.java b/service/src/com/android/server/connectivity/DscpPolicyTracker.java
index 7829d1a..0e9b459 100644
--- a/service/src/com/android/server/connectivity/DscpPolicyTracker.java
+++ b/service/src/com/android/server/connectivity/DscpPolicyTracker.java
@@ -52,12 +52,12 @@
private static final String TAG = DscpPolicyTracker.class.getSimpleName();
private static final String PROG_PATH =
- "/sys/fs/bpf/net_shared/prog_dscp_policy_schedcls_set_dscp";
+ "/sys/fs/bpf/net_shared/prog_dscpPolicy_schedcls_set_dscp";
// Name is "map + *.o + map_name + map". Can probably shorten this
private static final String IPV4_POLICY_MAP_PATH = makeMapPath(
- "dscp_policy_ipv4_dscp_policies");
+ "dscpPolicy_ipv4_dscp_policies");
private static final String IPV6_POLICY_MAP_PATH = makeMapPath(
- "dscp_policy_ipv6_dscp_policies");
+ "dscpPolicy_ipv6_dscp_policies");
private static final int MAX_POLICIES = 16;
private static String makeMapPath(String which) {
@@ -213,7 +213,7 @@
}
/**
- * Add the provided DSCP policy to the bpf map. Attach bpf program dscp_policy to iface
+ * Add the provided DSCP policy to the bpf map. Attach bpf program dscpPolicy to iface
* if not already attached. Response will be sent back to nai with status.
*
* DSCP_POLICY_STATUS_SUCCESS - if policy was added successfully
diff --git a/tests/common/Android.bp b/tests/common/Android.bp
index efea0f9..5c9cc63 100644
--- a/tests/common/Android.bp
+++ b/tests/common/Android.bp
@@ -21,6 +21,19 @@
default_applicable_licenses: ["Android-Apache-2.0"],
}
+// The target SDK version of the "latest released SDK" CTS tests.
+// This should be updated soon after a new SDK level is finalized.
+// It is different from the target SDK version of production code (e.g., the Tethering,
+// NetworkStack, and CaptivePortalLogin APKs):
+// - The target SDK of production code influences the behaviour of the production code.
+// - The target SDK of the CTS tests validates the behaviour seen by apps that call production APIs.
+// - The behaviour seen by apps that target previous SDKs is tested by previous CTS versions
+// (currently, CTS 10, 11, and 12).
+java_defaults {
+ name: "ConnectivityTestsLatestSdkDefaults",
+ target_sdk_version: "33",
+}
+
java_library {
name: "FrameworksNetCommonTests",
defaults: ["framework-connectivity-internal-test-defaults"],
@@ -80,9 +93,9 @@
name: "ConnectivityCoverageTests",
// Tethering started on SDK 30
min_sdk_version: "30",
- target_sdk_version: "31",
test_suites: ["general-tests", "mts-tethering"],
defaults: [
+ "ConnectivityTestsLatestSdkDefaults",
"framework-connectivity-internal-test-defaults",
"FrameworksNetTests-jni-defaults",
"libnetworkstackutilsjni_deps",
diff --git a/tests/common/java/android/net/NetworkProviderTest.kt b/tests/common/java/android/net/NetworkProviderTest.kt
index 3ceacf8..c0e7f61 100644
--- a/tests/common/java/android/net/NetworkProviderTest.kt
+++ b/tests/common/java/android/net/NetworkProviderTest.kt
@@ -30,6 +30,7 @@
import android.os.Looper
import android.util.Log
import androidx.test.InstrumentationRegistry
+import com.android.modules.utils.build.SdkLevel.isAtLeastS
import com.android.net.module.util.ArrayTrackRecord
import com.android.testutils.CompatUtil
import com.android.testutils.ConnectivityModuleTest
@@ -38,7 +39,6 @@
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.TestableNetworkOfferCallback
-import com.android.testutils.isDevSdkInRange
import org.junit.After
import org.junit.Before
import org.junit.Rule
@@ -376,7 +376,7 @@
doReturn(mCm).`when`(mockContext).getSystemService(Context.CONNECTIVITY_SERVICE)
val provider = createNetworkProvider(mockContext)
// ConnectivityManager not required at creation time after R
- if (!isDevSdkInRange(0, Build.VERSION_CODES.R)) {
+ if (isAtLeastS()) {
verifyNoMoreInteractions(mockContext)
}
diff --git a/tests/cts/hostside/aidl/com/android/cts/net/hostside/IRemoteSocketFactory.aidl b/tests/cts/hostside/aidl/com/android/cts/net/hostside/IRemoteSocketFactory.aidl
index 68176ad..6986e7e 100644
--- a/tests/cts/hostside/aidl/com/android/cts/net/hostside/IRemoteSocketFactory.aidl
+++ b/tests/cts/hostside/aidl/com/android/cts/net/hostside/IRemoteSocketFactory.aidl
@@ -20,6 +20,7 @@
interface IRemoteSocketFactory {
ParcelFileDescriptor openSocketFd(String host, int port, int timeoutMs);
+ ParcelFileDescriptor openDatagramSocketFd();
String getPackageName();
int getUid();
}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/RemoteSocketFactoryClient.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/RemoteSocketFactoryClient.java
index 80f99b6..01fbd66 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/RemoteSocketFactoryClient.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/RemoteSocketFactoryClient.java
@@ -83,9 +83,19 @@
public FileDescriptor openSocketFd(String host, int port, int timeoutMs)
throws RemoteException, ErrnoException, IOException {
// Dup the filedescriptor so ParcelFileDescriptor's finalizer doesn't garbage collect it
- // and cause our fd to become invalid. http://b/35927643 .
- ParcelFileDescriptor pfd = mService.openSocketFd(host, port, timeoutMs);
- FileDescriptor fd = Os.dup(pfd.getFileDescriptor());
+ // and cause fd to become invalid. http://b/35927643.
+ final ParcelFileDescriptor pfd = mService.openSocketFd(host, port, timeoutMs);
+ final FileDescriptor fd = Os.dup(pfd.getFileDescriptor());
+ pfd.close();
+ return fd;
+ }
+
+ public FileDescriptor openDatagramSocketFd()
+ throws RemoteException, ErrnoException, IOException {
+ // Dup the filedescriptor so ParcelFileDescriptor's finalizer doesn't garbage collect it
+ // and cause fd to become invalid. http://b/35927643.
+ final ParcelFileDescriptor pfd = mService.openDatagramSocketFd();
+ final FileDescriptor fd = Os.dup(pfd.getFileDescriptor());
pfd.close();
return fd;
}
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
index dd8b523..5f032be 100755
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/VpnTest.java
@@ -16,6 +16,7 @@
package com.android.cts.net.hostside;
+import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static android.content.pm.PackageManager.FEATURE_TELEPHONY;
import static android.content.pm.PackageManager.FEATURE_WIFI;
@@ -35,6 +36,8 @@
import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
+import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_LOCKDOWN_VPN;
+import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_NONE;
import static com.android.testutils.Cleanup.testAndCleanup;
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
@@ -59,12 +62,15 @@
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.ConnectivityManager.NetworkCallback;
+import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.Proxy;
import android.net.ProxyInfo;
+import android.net.TestNetworkInterface;
+import android.net.TestNetworkManager;
import android.net.TransportInfo;
import android.net.Uri;
import android.net.VpnManager;
@@ -72,6 +78,7 @@
import android.net.VpnTransportInfo;
import android.net.cts.util.CtsNetUtils;
import android.net.wifi.WifiManager;
+import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.ParcelFileDescriptor;
@@ -90,11 +97,13 @@
import android.test.MoreAsserts;
import android.text.TextUtils;
import android.util.Log;
+import android.util.Range;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.compatibility.common.util.BlockingBroadcastReceiver;
import com.android.modules.utils.build.SdkLevel;
+import com.android.net.module.util.PacketBuilder;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
import com.android.testutils.RecorderCallback;
@@ -113,12 +122,14 @@
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
+import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
@@ -164,6 +175,12 @@
private static final String PRIVATE_DNS_SPECIFIER_SETTING = "private_dns_specifier";
private static final int NETWORK_CALLBACK_TIMEOUT_MS = 30_000;
+ private static final LinkAddress TEST_IP4_DST_ADDR = new LinkAddress("198.51.100.1/24");
+ private static final LinkAddress TEST_IP4_SRC_ADDR = new LinkAddress("198.51.100.2/24");
+ private static final LinkAddress TEST_IP6_DST_ADDR = new LinkAddress("2001:db8:1:3::1/64");
+ private static final LinkAddress TEST_IP6_SRC_ADDR = new LinkAddress("2001:db8:1:3::2/64");
+ private static final short TEST_SRC_PORT = 5555;
+
public static String TAG = "VpnTest";
public static int TIMEOUT_MS = 3 * 1000;
public static int SOCKET_TIMEOUT_MS = 100;
@@ -1572,4 +1589,180 @@
return future.get(timeout, unit);
}
}
+
+ private static final boolean EXPECT_PASS = false;
+ private static final boolean EXPECT_BLOCK = true;
+
+ @Test @IgnoreUpTo(Build.VERSION_CODES.R)
+ public void testBlockIncomingPackets() throws Exception {
+ assumeTrue(supportedHardware());
+ final Network network = mCM.getActiveNetwork();
+ assertNotNull("Requires a working Internet connection", network);
+
+ final int remoteUid = mRemoteSocketFactoryClient.getUid();
+ final List<Range<Integer>> lockdownRange = List.of(new Range<>(remoteUid, remoteUid));
+ final DetailedBlockedStatusCallback remoteUidCallback = new DetailedBlockedStatusCallback();
+
+ // Create a TUN interface
+ final FileDescriptor tunFd = runWithShellPermissionIdentity(() -> {
+ final TestNetworkManager tnm = getInstrumentation().getContext().getSystemService(
+ TestNetworkManager.class);
+ final TestNetworkInterface iface = tnm.createTunInterface(List.of(
+ TEST_IP4_DST_ADDR, TEST_IP6_DST_ADDR));
+ return iface.getFileDescriptor().getFileDescriptor();
+ }, MANAGE_TEST_NETWORKS);
+
+ // Create a remote UDP socket
+ final FileDescriptor remoteUdpFd = mRemoteSocketFactoryClient.openDatagramSocketFd();
+
+ testAndCleanup(() -> {
+ runWithShellPermissionIdentity(() -> {
+ mCM.registerDefaultNetworkCallbackForUid(remoteUid, remoteUidCallback,
+ new Handler(Looper.getMainLooper()));
+ }, NETWORK_SETTINGS);
+ remoteUidCallback.expectAvailableCallbacks(network);
+
+ // The remote UDP socket can receive packets coming from the TUN interface
+ checkBlockIncomingPacket(tunFd, remoteUdpFd, EXPECT_PASS);
+
+ // Lockdown uid that has the remote UDP socket
+ runWithShellPermissionIdentity(() -> {
+ mCM.setRequireVpnForUids(true /* requireVpn */, lockdownRange);
+ }, NETWORK_SETTINGS);
+
+ // setRequireVpnForUids setup a lockdown rule asynchronously. So it needs to wait for
+ // BlockedStatusCallback to be fired before checking the blocking status of incoming
+ // packets.
+ remoteUidCallback.expectBlockedStatusCallback(network, BLOCKED_REASON_LOCKDOWN_VPN);
+
+ if (SdkLevel.isAtLeastT()) {
+ // On T and above, lockdown rule drop packets not coming from lo regardless of the
+ // VPN connectivity.
+ checkBlockIncomingPacket(tunFd, remoteUdpFd, EXPECT_BLOCK);
+ }
+
+ // Start the VPN that has default routes. This VPN should have interface filtering rule
+ // for incoming packet and drop packets not coming from lo nor the VPN interface.
+ final String allowedApps =
+ mRemoteSocketFactoryClient.getPackageName() + "," + mPackageName;
+ startVpn(new String[]{"192.0.2.2/32", "2001:db8:1:2::ffe/128"},
+ new String[]{"0.0.0.0/0", "::/0"}, allowedApps, "" /* disallowedApplications */,
+ null /* proxyInfo */, null /* underlyingNetworks */,
+ false /* isAlwaysMetered */);
+
+ checkBlockIncomingPacket(tunFd, remoteUdpFd, EXPECT_BLOCK);
+ }, /* cleanup */ () -> {
+ mCM.unregisterNetworkCallback(remoteUidCallback);
+ }, /* cleanup */ () -> {
+ Os.close(tunFd);
+ }, /* cleanup */ () -> {
+ Os.close(remoteUdpFd);
+ }, /* cleanup */ () -> {
+ runWithShellPermissionIdentity(() -> {
+ mCM.setRequireVpnForUids(false /* requireVpn */, lockdownRange);
+ }, NETWORK_SETTINGS);
+ });
+ }
+
+ private ByteBuffer buildIpv4UdpPacket(final Inet4Address dstAddr, final Inet4Address srcAddr,
+ final short dstPort, final short srcPort, final byte[] payload) throws IOException {
+
+ final ByteBuffer buffer = PacketBuilder.allocate(false /* hasEther */,
+ OsConstants.IPPROTO_IP, OsConstants.IPPROTO_UDP, payload.length);
+ final PacketBuilder packetBuilder = new PacketBuilder(buffer);
+
+ packetBuilder.writeIpv4Header(
+ (byte) 0 /* TOS */,
+ (short) 27149 /* ID */,
+ (short) 0x4000 /* flags=DF, offset=0 */,
+ (byte) 64 /* TTL */,
+ (byte) OsConstants.IPPROTO_UDP,
+ srcAddr,
+ dstAddr);
+ packetBuilder.writeUdpHeader(srcPort, dstPort);
+ buffer.put(payload);
+
+ return packetBuilder.finalizePacket();
+ }
+
+ private ByteBuffer buildIpv6UdpPacket(final Inet6Address dstAddr, final Inet6Address srcAddr,
+ final short dstPort, final short srcPort, final byte[] payload) throws IOException {
+
+ final ByteBuffer buffer = PacketBuilder.allocate(false /* hasEther */,
+ OsConstants.IPPROTO_IPV6, OsConstants.IPPROTO_UDP, payload.length);
+ final PacketBuilder packetBuilder = new PacketBuilder(buffer);
+
+ packetBuilder.writeIpv6Header(
+ 0x60000000 /* version=6, traffic class=0, flow label=0 */,
+ (byte) OsConstants.IPPROTO_UDP,
+ (short) 64 /* hop limit */,
+ srcAddr,
+ dstAddr);
+ packetBuilder.writeUdpHeader(srcPort, dstPort);
+ buffer.put(payload);
+
+ return packetBuilder.finalizePacket();
+ }
+
+ private void checkBlockUdp(
+ final FileDescriptor srcTunFd,
+ final FileDescriptor dstUdpFd,
+ final boolean ipv6,
+ final boolean expectBlock) throws Exception {
+ final Random random = new Random();
+ final byte[] sendData = new byte[100];
+ random.nextBytes(sendData);
+ final short dstPort = (short) ((InetSocketAddress) Os.getsockname(dstUdpFd)).getPort();
+
+ ByteBuffer buf;
+ if (ipv6) {
+ buf = buildIpv6UdpPacket(
+ (Inet6Address) TEST_IP6_DST_ADDR.getAddress(),
+ (Inet6Address) TEST_IP6_SRC_ADDR.getAddress(),
+ dstPort, TEST_SRC_PORT, sendData);
+ } else {
+ buf = buildIpv4UdpPacket(
+ (Inet4Address) TEST_IP4_DST_ADDR.getAddress(),
+ (Inet4Address) TEST_IP4_SRC_ADDR.getAddress(),
+ dstPort, TEST_SRC_PORT, sendData);
+ }
+
+ Os.write(srcTunFd, buf);
+
+ final StructPollfd pollfd = new StructPollfd();
+ pollfd.events = (short) POLLIN;
+ pollfd.fd = dstUdpFd;
+ final int ret = Os.poll(new StructPollfd[]{pollfd}, SOCKET_TIMEOUT_MS);
+
+ if (expectBlock) {
+ assertEquals("Expect not to receive a packet but received a packet", 0, ret);
+ } else {
+ assertEquals("Expect to receive a packet but did not receive a packet", 1, ret);
+ final byte[] recvData = new byte[sendData.length];
+ final int readSize = Os.read(dstUdpFd, recvData, 0 /* byteOffset */, recvData.length);
+ assertEquals(recvData.length, readSize);
+ MoreAsserts.assertEquals(sendData, recvData);
+ }
+ }
+
+ private void checkBlockIncomingPacket(
+ final FileDescriptor srcTunFd,
+ final FileDescriptor dstUdpFd,
+ final boolean expectBlock) throws Exception {
+ checkBlockUdp(srcTunFd, dstUdpFd, false /* ipv6 */, expectBlock);
+ checkBlockUdp(srcTunFd, dstUdpFd, true /* ipv6 */, expectBlock);
+ }
+
+ private class DetailedBlockedStatusCallback extends TestableNetworkCallback {
+ public void expectAvailableCallbacks(Network network) {
+ super.expectAvailableCallbacks(network, false /* suspended */, true /* validated */,
+ BLOCKED_REASON_NONE, NETWORK_CALLBACK_TIMEOUT_MS);
+ }
+ public void expectBlockedStatusCallback(Network network, int blockedStatus) {
+ super.expectBlockedStatusCallback(blockedStatus, network, NETWORK_CALLBACK_TIMEOUT_MS);
+ }
+ public void onBlockedStatusChanged(Network network, int blockedReasons) {
+ getHistory().add(new CallbackEntry.BlockedStatusInt(network, blockedReasons));
+ }
+ }
}
diff --git a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/RemoteSocketFactoryService.java b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/RemoteSocketFactoryService.java
index b1b7d77..fb6d16f 100644
--- a/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/RemoteSocketFactoryService.java
+++ b/tests/cts/hostside/app2/src/com/android/cts/net/hostside/app2/RemoteSocketFactoryService.java
@@ -17,16 +17,17 @@
package com.android.cts.net.hostside.app2;
import android.app.Service;
-import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.Process;
-import android.util.Log;
import com.android.cts.net.hostside.IRemoteSocketFactory;
+import java.io.UncheckedIOException;
+import java.net.DatagramSocket;
import java.net.Socket;
+import java.net.SocketException;
public class RemoteSocketFactoryService extends Service {
@@ -54,6 +55,16 @@
public int getUid() {
return Process.myUid();
}
+
+ @Override
+ public ParcelFileDescriptor openDatagramSocketFd() {
+ try {
+ final DatagramSocket s = new DatagramSocket();
+ return ParcelFileDescriptor.fromDatagramSocket(s);
+ } catch (SocketException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
};
@Override
diff --git a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
index 3821f87..4d90a4a 100644
--- a/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
+++ b/tests/cts/hostside/src/com/android/cts/net/HostsideVpnTests.java
@@ -116,4 +116,8 @@
public void testInterleavedRoutes() throws Exception {
runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testInterleavedRoutes");
}
+
+ public void testBlockIncomingPackets() throws Exception {
+ runDeviceTests(TEST_PKG, TEST_PKG + ".VpnTest", "testBlockIncomingPackets");
+ }
}
diff --git a/tests/cts/net/Android.bp b/tests/cts/net/Android.bp
index a6ed762..62f37bb 100644
--- a/tests/cts/net/Android.bp
+++ b/tests/cts/net/Android.bp
@@ -72,9 +72,9 @@
android_test {
name: "CtsNetTestCases",
defaults: ["CtsNetTestCasesDefaults", "ConnectivityNextEnableDefaults"],
- // TODO: CTS should not depend on the entirety of the networkstack code.
static_libs: [
- "NetworkStackApiCurrentLib",
+ "DhcpPacketLib",
+ "NetworkStackApiCurrentShims",
],
test_suites: [
"cts",
@@ -86,7 +86,8 @@
name: "CtsNetTestCasesApiStableDefaults",
// TODO: CTS should not depend on the entirety of the networkstack code.
static_libs: [
- "NetworkStackApiStableLib",
+ "DhcpPacketLib",
+ "NetworkStackApiStableShims",
],
jni_uses_sdk_apis: true,
min_sdk_version: "29",
@@ -98,10 +99,10 @@
android_test {
name: "CtsNetTestCasesLatestSdk",
defaults: [
+ "ConnectivityTestsLatestSdkDefaults",
"CtsNetTestCasesDefaults",
"CtsNetTestCasesApiStableDefaults",
],
- target_sdk_version: "33",
test_suites: [
"general-tests",
"mts-dnsresolver",
diff --git a/tests/cts/net/native/src/BpfCompatTest.cpp b/tests/cts/net/native/src/BpfCompatTest.cpp
index 3aec4c7..5c02b0d 100644
--- a/tests/cts/net/native/src/BpfCompatTest.cpp
+++ b/tests/cts/net/native/src/BpfCompatTest.cpp
@@ -31,7 +31,10 @@
std::ifstream elfFile(elfPath, std::ios::in | std::ios::binary);
ASSERT_TRUE(elfFile.is_open());
- if (android::modules::sdklevel::IsAtLeastT()) {
+ if (android::modules::sdklevel::IsAtLeastU()) {
+ EXPECT_EQ(120, readSectionUint("size_of_bpf_map_def", elfFile, 0));
+ EXPECT_EQ(92, readSectionUint("size_of_bpf_prog_def", elfFile, 0));
+ } else if (android::modules::sdklevel::IsAtLeastT()) {
EXPECT_EQ(116, readSectionUint("size_of_bpf_map_def", elfFile, 0));
EXPECT_EQ(92, readSectionUint("size_of_bpf_prog_def", elfFile, 0));
} else {
diff --git a/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt b/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
index 1b77d5f..aad8804 100644
--- a/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
+++ b/tests/cts/net/src/android/net/cts/CaptivePortalTest.kt
@@ -37,9 +37,8 @@
import android.net.cts.NetworkValidationTestUtil.setHttpsUrlDeviceConfig
import android.net.cts.NetworkValidationTestUtil.setUrlExpirationDeviceConfig
import android.net.cts.util.CtsNetUtils
-import android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL
-import android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL
-import android.os.Build
+import com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL
+import com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL
import android.platform.test.annotations.AppModeFull
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY
@@ -47,11 +46,11 @@
import android.util.Log
import androidx.test.platform.app.InstrumentationRegistry.getInstrumentation
import androidx.test.runner.AndroidJUnit4
+import com.android.modules.utils.build.SdkLevel.isAtLeastR
import com.android.testutils.RecorderCallback
import com.android.testutils.TestHttpServer
import com.android.testutils.TestHttpServer.Request
import com.android.testutils.TestableNetworkCallback
-import com.android.testutils.isDevSdkInRange
import com.android.testutils.runAsShell
import fi.iki.elonen.NanoHTTPD.Response.Status
import junit.framework.AssertionFailedError
@@ -196,8 +195,8 @@
assertNotEquals(network, cm.activeNetwork, wifiDefaultMessage)
val startPortalAppPermission =
- if (isDevSdkInRange(0, Build.VERSION_CODES.Q)) CONNECTIVITY_INTERNAL
- else NETWORK_SETTINGS
+ if (isAtLeastR()) NETWORK_SETTINGS
+ else CONNECTIVITY_INTERNAL
runAsShell(startPortalAppPermission) { cm.startCaptivePortalApp(network) }
// Expect the portal content to be fetched at some point after detecting the portal.
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 5a56e2b..47f8191 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -37,9 +37,14 @@
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.net.ConnectivityManager.EXTRA_NETWORK;
import static android.net.ConnectivityManager.EXTRA_NETWORK_REQUEST;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2;
import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED;
+import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY;
import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
import static android.net.ConnectivityManager.PROFILE_NETWORK_PREFERENCE_ENTERPRISE;
@@ -75,8 +80,6 @@
import static android.net.cts.util.CtsNetUtils.TEST_HOST;
import static android.net.cts.util.CtsNetUtils.TestNetworkCallback;
import static android.net.cts.util.CtsTetheringUtils.TestTetheringEventCallback;
-import static android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL;
-import static android.net.util.NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
import static android.os.Process.INVALID_UID;
import static android.provider.Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE;
@@ -88,6 +91,8 @@
import static com.android.compatibility.common.util.SystemUtil.runShellCommand;
import static com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity;
import static com.android.modules.utils.build.SdkLevel.isAtLeastS;
+import static com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL;
+import static com.android.net.module.util.NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_LOCKDOWN_VPN;
import static com.android.networkstack.apishim.ConstantsShim.BLOCKED_REASON_NONE;
import static com.android.testutils.Cleanup.testAndCleanup;
@@ -186,7 +191,6 @@
import com.android.testutils.CompatUtil;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
-import com.android.testutils.DevSdkIgnoreRuleKt;
import com.android.testutils.DeviceInfoUtils;
import com.android.testutils.DumpTestUtils;
import com.android.testutils.RecorderCallback.CallbackEntry;
@@ -331,11 +335,10 @@
mCtsNetUtils = new CtsNetUtils(mContext);
mTm = mContext.getSystemService(TelephonyManager.class);
- if (DevSdkIgnoreRuleKt.isDevSdkInRange(null /* minExclusive */,
- Build.VERSION_CODES.R /* maxInclusive */)) {
- addLegacySupportedNetworkTypes();
- } else {
+ if (isAtLeastS()) {
addSupportedNetworkTypes();
+ } else {
+ addLegacySupportedNetworkTypes();
}
mUiAutomation = mInstrumentation.getUiAutomation();
@@ -3298,84 +3301,76 @@
private static final boolean EXPECT_PASS = false;
private static final boolean EXPECT_BLOCK = true;
+ private static final boolean ALLOWLIST = true;
+ private static final boolean DENYLIST = false;
- private void doTestFirewallBlockingDenyRule(final int chain) {
+ private void doTestFirewallBlocking(final int chain, final boolean isAllowList) {
+ final int myUid = Process.myUid();
+ final int ruleToAddMatch = isAllowList ? FIREWALL_RULE_ALLOW : FIREWALL_RULE_DENY;
+ final int ruleToRemoveMatch = isAllowList ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW;
+
runWithShellPermissionIdentity(() -> {
- try (DatagramSocket srcSock = new DatagramSocket();
- DatagramSocket dstSock = new DatagramSocket()) {
+ // Firewall chain status will be restored after the test.
+ final boolean wasChainEnabled = mCm.getFirewallChainEnabled(chain);
+ final DatagramSocket srcSock = new DatagramSocket();
+ final DatagramSocket dstSock = new DatagramSocket();
+ testAndCleanup(() -> {
+ if (wasChainEnabled) {
+ mCm.setFirewallChainEnabled(chain, false /* enable */);
+ }
dstSock.setSoTimeout(SOCKET_TIMEOUT_MS);
- // No global config, No uid config
+ // Chain disabled, UID not on chain.
checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
- // Has global config, No uid config
+ // Chain enabled, UID not on chain.
mCm.setFirewallChainEnabled(chain, true /* enable */);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
+ assertTrue(mCm.getFirewallChainEnabled(chain));
+ checkFirewallBlocking(srcSock, dstSock, isAllowList ? EXPECT_BLOCK : EXPECT_PASS);
- // Has global config, Has uid config
- mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_DENY);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_BLOCK);
+ // Chain enabled, UID on chain.
+ mCm.setUidFirewallRule(chain, myUid, ruleToAddMatch);
+ checkFirewallBlocking(srcSock, dstSock, isAllowList ? EXPECT_PASS : EXPECT_BLOCK);
- // No global config, Has uid config
+ // Chain disabled, UID on chain.
mCm.setFirewallChainEnabled(chain, false /* enable */);
+ assertFalse(mCm.getFirewallChainEnabled(chain));
checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
- // No global config, No uid config
- mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_ALLOW);
+ // Chain disabled, UID not on chain.
+ mCm.setUidFirewallRule(chain, myUid, ruleToRemoveMatch);
checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
- } finally {
- mCm.setFirewallChainEnabled(chain, false /* enable */);
- mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_ALLOW);
- }
- }, NETWORK_SETTINGS);
- }
-
- private void doTestFirewallBlockingAllowRule(final int chain) {
- runWithShellPermissionIdentity(() -> {
- try (DatagramSocket srcSock = new DatagramSocket();
- DatagramSocket dstSock = new DatagramSocket()) {
- dstSock.setSoTimeout(SOCKET_TIMEOUT_MS);
-
- // No global config, No uid config
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
-
- // Has global config, No uid config
- mCm.setFirewallChainEnabled(chain, true /* enable */);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_BLOCK);
-
- // Has global config, Has uid config
- mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_ALLOW);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
-
- // No global config, Has uid config
- mCm.setFirewallChainEnabled(chain, false /* enable */);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
-
- // No global config, No uid config
- mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_DENY);
- checkFirewallBlocking(srcSock, dstSock, EXPECT_PASS);
- } finally {
- mCm.setFirewallChainEnabled(chain, false /* enable */);
- mCm.setUidFirewallRule(chain, Process.myUid(), FIREWALL_RULE_DENY);
- }
+ }, /* cleanup */ () -> {
+ srcSock.close();
+ dstSock.close();
+ }, /* cleanup */ () -> {
+ // Restore the global chain status
+ mCm.setFirewallChainEnabled(chain, wasChainEnabled);
+ }, /* cleanup */ () -> {
+ try {
+ mCm.setUidFirewallRule(chain, myUid, ruleToRemoveMatch);
+ } catch (IllegalStateException ignored) {
+ // Removing match causes an exception when the rule entry for the uid does
+ // not exist. But this is fine and can be ignored.
+ }
+ });
}, NETWORK_SETTINGS);
}
@Test @IgnoreUpTo(SC_V2)
@AppModeFull(reason = "Socket cannot bind in instant app mode")
public void testFirewallBlocking() {
- // Following tests affect the actual state of networking on the device after the test.
- // This might cause unexpected behaviour of the device. So, we skip them for now.
- // We will enable following tests after adding the logic of firewall state restoring.
- // doTestFirewallBlockingAllowRule(FIREWALL_CHAIN_DOZABLE);
- // doTestFirewallBlockingAllowRule(FIREWALL_CHAIN_POWERSAVE);
- // doTestFirewallBlockingAllowRule(FIREWALL_CHAIN_RESTRICTED);
- // doTestFirewallBlockingAllowRule(FIREWALL_CHAIN_LOW_POWER_STANDBY);
+ // ALLOWLIST means the firewall denies all by default, uids must be explicitly allowed
+ doTestFirewallBlocking(FIREWALL_CHAIN_DOZABLE, ALLOWLIST);
+ doTestFirewallBlocking(FIREWALL_CHAIN_POWERSAVE, ALLOWLIST);
+ doTestFirewallBlocking(FIREWALL_CHAIN_RESTRICTED, ALLOWLIST);
+ doTestFirewallBlocking(FIREWALL_CHAIN_LOW_POWER_STANDBY, ALLOWLIST);
- // doTestFirewallBlockingDenyRule(FIREWALL_CHAIN_STANDBY);
- doTestFirewallBlockingDenyRule(FIREWALL_CHAIN_OEM_DENY_1);
- doTestFirewallBlockingDenyRule(FIREWALL_CHAIN_OEM_DENY_2);
- doTestFirewallBlockingDenyRule(FIREWALL_CHAIN_OEM_DENY_3);
+ // DENYLIST means the firewall allows all by default, uids must be explicitly denyed
+ doTestFirewallBlocking(FIREWALL_CHAIN_STANDBY, DENYLIST);
+ doTestFirewallBlocking(FIREWALL_CHAIN_OEM_DENY_1, DENYLIST);
+ doTestFirewallBlocking(FIREWALL_CHAIN_OEM_DENY_2, DENYLIST);
+ doTestFirewallBlocking(FIREWALL_CHAIN_OEM_DENY_3, DENYLIST);
}
private void assumeTestSApis() {
diff --git a/tests/cts/net/src/android/net/cts/NetworkValidationTestUtil.kt b/tests/cts/net/src/android/net/cts/NetworkValidationTestUtil.kt
index 462c8a3..375bfb8 100644
--- a/tests/cts/net/src/android/net/cts/NetworkValidationTestUtil.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkValidationTestUtil.kt
@@ -17,9 +17,9 @@
package android.net.cts
import android.Manifest.permission.WRITE_DEVICE_CONFIG
-import android.net.util.NetworkStackUtils
import android.provider.DeviceConfig
import android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY
+import com.android.net.module.util.NetworkStackConstants
import com.android.testutils.runAsShell
/**
@@ -35,41 +35,41 @@
@JvmStatic fun clearValidationTestUrlsDeviceConfig() {
runAsShell(WRITE_DEVICE_CONFIG) {
DeviceConfig.setProperty(NAMESPACE_CONNECTIVITY,
- NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL, null, false)
+ NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL, null, false)
DeviceConfig.setProperty(NAMESPACE_CONNECTIVITY,
- NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL, null, false)
+ NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL, null, false)
DeviceConfig.setProperty(NAMESPACE_CONNECTIVITY,
- NetworkStackUtils.TEST_URL_EXPIRATION_TIME, null, false)
+ NetworkStackConstants.TEST_URL_EXPIRATION_TIME, null, false)
}
}
/**
* Set the test validation HTTPS URL.
*
- * @see NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL
+ * @see NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL
*/
@JvmStatic
fun setHttpsUrlDeviceConfig(rule: DeviceConfigRule, url: String?) =
rule.setConfig(NAMESPACE_CONNECTIVITY,
- NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTPS_URL, url)
+ NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTPS_URL, url)
/**
* Set the test validation HTTP URL.
*
- * @see NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL
+ * @see NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL
*/
@JvmStatic
fun setHttpUrlDeviceConfig(rule: DeviceConfigRule, url: String?) =
rule.setConfig(NAMESPACE_CONNECTIVITY,
- NetworkStackUtils.TEST_CAPTIVE_PORTAL_HTTP_URL, url)
+ NetworkStackConstants.TEST_CAPTIVE_PORTAL_HTTP_URL, url)
/**
* Set the test validation URL expiration.
*
- * @see NetworkStackUtils.TEST_URL_EXPIRATION_TIME
+ * @see NetworkStackConstants.TEST_URL_EXPIRATION_TIME
*/
@JvmStatic
fun setUrlExpirationDeviceConfig(rule: DeviceConfigRule, timestamp: Long?) =
rule.setConfig(NAMESPACE_CONNECTIVITY,
- NetworkStackUtils.TEST_URL_EXPIRATION_TIME, timestamp?.toString())
+ NetworkStackConstants.TEST_URL_EXPIRATION_TIME, timestamp?.toString())
}
diff --git a/tests/cts/tethering/Android.bp b/tests/cts/tethering/Android.bp
index 6096a8b..42949a4 100644
--- a/tests/cts/tethering/Android.bp
+++ b/tests/cts/tethering/Android.bp
@@ -53,10 +53,12 @@
// mainline modules on release devices.
android_test {
name: "CtsTetheringTestLatestSdk",
- defaults: ["CtsTetheringTestDefaults"],
+ defaults: [
+ "ConnectivityTestsLatestSdkDefaults",
+ "CtsTetheringTestDefaults",
+ ],
min_sdk_version: "30",
- target_sdk_version: "33",
static_libs: [
"TetheringIntegrationTestsLatestSdkLib",
diff --git a/tests/mts/bpf_existence_test.cpp b/tests/mts/bpf_existence_test.cpp
index 2613363..67b4f42 100644
--- a/tests/mts/bpf_existence_test.cpp
+++ b/tests/mts/bpf_existence_test.cpp
@@ -87,13 +87,13 @@
SHARED "map_block_blocked_ports_map",
SHARED "map_clatd_clat_egress4_map",
SHARED "map_clatd_clat_ingress6_map",
- SHARED "map_dscp_policy_ipv4_dscp_policies_map",
- SHARED "map_dscp_policy_ipv4_socket_to_policies_map_A",
- SHARED "map_dscp_policy_ipv4_socket_to_policies_map_B",
- SHARED "map_dscp_policy_ipv6_dscp_policies_map",
- SHARED "map_dscp_policy_ipv6_socket_to_policies_map_A",
- SHARED "map_dscp_policy_ipv6_socket_to_policies_map_B",
- SHARED "map_dscp_policy_switch_comp_map",
+ SHARED "map_dscpPolicy_ipv4_dscp_policies_map",
+ SHARED "map_dscpPolicy_ipv4_socket_to_policies_map_A",
+ SHARED "map_dscpPolicy_ipv4_socket_to_policies_map_B",
+ SHARED "map_dscpPolicy_ipv6_dscp_policies_map",
+ SHARED "map_dscpPolicy_ipv6_socket_to_policies_map_A",
+ SHARED "map_dscpPolicy_ipv6_socket_to_policies_map_B",
+ SHARED "map_dscpPolicy_switch_comp_map",
NETD "map_netd_app_uid_stats_map",
NETD "map_netd_configuration_map",
NETD "map_netd_cookie_tag_map",
@@ -126,8 +126,8 @@
// Provided by *current* mainline module for T+ devices with 5.15+ kernels
static const set<string> MAINLINE_FOR_T_5_15_PLUS = {
- SHARED "prog_dscp_policy_schedcls_set_dscp_ether",
- SHARED "prog_dscp_policy_schedcls_set_dscp_raw_ip",
+ SHARED "prog_dscpPolicy_schedcls_set_dscp_ether",
+ SHARED "prog_dscpPolicy_schedcls_set_dscp_raw_ip",
};
void addAll(set<string>* a, const set<string>& b) {
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index 58d002a..07884cf 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -16,6 +16,8 @@
package com.android.server;
+import static android.net.nsd.NsdManager.FAILURE_INTERNAL_ERROR;
+
import static libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
import static libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
@@ -44,11 +46,15 @@
import android.net.mdns.aidl.DiscoveryInfo;
import android.net.mdns.aidl.GetAddressInfo;
import android.net.mdns.aidl.IMDnsEventListener;
+import android.net.mdns.aidl.RegistrationInfo;
import android.net.mdns.aidl.ResolutionInfo;
import android.net.nsd.INsdManagerCallback;
import android.net.nsd.INsdServiceConnector;
import android.net.nsd.MDnsManager;
import android.net.nsd.NsdManager;
+import android.net.nsd.NsdManager.DiscoveryListener;
+import android.net.nsd.NsdManager.RegistrationListener;
+import android.net.nsd.NsdManager.ResolveListener;
import android.net.nsd.NsdServiceInfo;
import android.os.Binder;
import android.os.Build;
@@ -226,7 +232,7 @@
request.setPort(PORT);
// Client registration request
- NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class);
+ final RegistrationListener listener1 = mock(RegistrationListener.class);
client.registerService(request, PROTOCOL, listener1);
waitForIdle();
verify(mMockMDnsM).registerEventListener(any());
@@ -235,13 +241,13 @@
eq(2), eq(SERVICE_NAME), eq(SERVICE_TYPE), eq(PORT), any(), eq(IFACE_IDX_ANY));
// Client discovery request
- NsdManager.DiscoveryListener listener2 = mock(NsdManager.DiscoveryListener.class);
+ final DiscoveryListener listener2 = mock(DiscoveryListener.class);
client.discoverServices(SERVICE_TYPE, PROTOCOL, listener2);
waitForIdle();
verify(mMockMDnsM).discover(3 /* id */, SERVICE_TYPE, IFACE_IDX_ANY);
// Client resolve request
- NsdManager.ResolveListener listener3 = mock(NsdManager.ResolveListener.class);
+ final ResolveListener listener3 = mock(ResolveListener.class);
client.resolveService(request, listener3);
waitForIdle();
verify(mMockMDnsM).resolve(
@@ -263,7 +269,7 @@
final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
request.setPort(PORT);
- NsdManager.RegistrationListener listener1 = mock(NsdManager.RegistrationListener.class);
+ final RegistrationListener listener1 = mock(RegistrationListener.class);
client.registerService(request, PROTOCOL, listener1);
waitForIdle();
verify(mMockMDnsM).registerEventListener(any());
@@ -285,17 +291,22 @@
verify(mMockMDnsM, never()).stopDaemon();
}
+ private IMDnsEventListener getEventListener() {
+ final ArgumentCaptor<IMDnsEventListener> listenerCaptor =
+ ArgumentCaptor.forClass(IMDnsEventListener.class);
+ verify(mMockMDnsM).registerEventListener(listenerCaptor.capture());
+ return listenerCaptor.getValue();
+ }
+
@Test
public void testDiscoverOnTetheringDownstream() throws Exception {
final NsdManager client = connectClient(mService);
final int interfaceIdx = 123;
- final NsdManager.DiscoveryListener discListener = mock(NsdManager.DiscoveryListener.class);
+ final DiscoveryListener discListener = mock(DiscoveryListener.class);
client.discoverServices(SERVICE_TYPE, PROTOCOL, discListener);
waitForIdle();
- final ArgumentCaptor<IMDnsEventListener> listenerCaptor =
- ArgumentCaptor.forClass(IMDnsEventListener.class);
- verify(mMockMDnsM).registerEventListener(listenerCaptor.capture());
+ final IMDnsEventListener eventListener = getEventListener();
final ArgumentCaptor<Integer> discIdCaptor = ArgumentCaptor.forClass(Integer.class);
verify(mMockMDnsM).discover(discIdCaptor.capture(), eq(SERVICE_TYPE),
eq(0) /* interfaceIdx */);
@@ -311,7 +322,6 @@
DOMAIN_NAME,
interfaceIdx,
INetd.LOCAL_NET_ID); // LOCAL_NET_ID (99) used on tethering downstreams
- final IMDnsEventListener eventListener = listenerCaptor.getValue();
eventListener.onServiceDiscoveryStatus(discoveryInfo);
waitForIdle();
@@ -326,7 +336,7 @@
assertEquals(interfaceIdx, foundInfo.getInterfaceIndex());
// After discovering the service, verify resolving it
- final NsdManager.ResolveListener resolveListener = mock(NsdManager.ResolveListener.class);
+ final ResolveListener resolveListener = mock(ResolveListener.class);
client.resolveService(foundInfo, resolveListener);
waitForIdle();
@@ -378,6 +388,154 @@
assertEquals(interfaceIdx, resolvedService.getInterfaceIndex());
}
+ @Test
+ public void testServiceRegistrationSuccessfulAndFailed() throws Exception {
+ final NsdManager client = connectClient(mService);
+ final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+ request.setPort(PORT);
+ final RegistrationListener regListener = mock(RegistrationListener.class);
+ client.registerService(request, PROTOCOL, regListener);
+ waitForIdle();
+
+ final IMDnsEventListener eventListener = getEventListener();
+ final ArgumentCaptor<Integer> regIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockMDnsM).registerService(regIdCaptor.capture(),
+ eq(SERVICE_NAME), eq(SERVICE_TYPE), eq(PORT), any(), eq(IFACE_IDX_ANY));
+
+ // Register service successfully.
+ final RegistrationInfo registrationInfo = new RegistrationInfo(
+ regIdCaptor.getValue(),
+ IMDnsEventListener.SERVICE_REGISTERED,
+ SERVICE_NAME,
+ SERVICE_TYPE,
+ PORT,
+ new byte[0] /* txtRecord */,
+ IFACE_IDX_ANY);
+ eventListener.onServiceRegistrationStatus(registrationInfo);
+
+ final ArgumentCaptor<NsdServiceInfo> registeredInfoCaptor =
+ ArgumentCaptor.forClass(NsdServiceInfo.class);
+ verify(regListener, timeout(TIMEOUT_MS))
+ .onServiceRegistered(registeredInfoCaptor.capture());
+ final NsdServiceInfo registeredInfo = registeredInfoCaptor.getValue();
+ assertEquals(SERVICE_NAME, registeredInfo.getServiceName());
+
+ // Fail to register service.
+ final RegistrationInfo registrationFailedInfo = new RegistrationInfo(
+ regIdCaptor.getValue(),
+ IMDnsEventListener.SERVICE_REGISTRATION_FAILED,
+ null /* serviceName */,
+ null /* registrationType */,
+ 0 /* port */,
+ new byte[0] /* txtRecord */,
+ IFACE_IDX_ANY);
+ eventListener.onServiceRegistrationStatus(registrationFailedInfo);
+ verify(regListener, timeout(TIMEOUT_MS))
+ .onRegistrationFailed(any(), eq(FAILURE_INTERNAL_ERROR));
+ }
+
+ @Test
+ public void testServiceDiscoveryFailed() throws Exception {
+ final NsdManager client = connectClient(mService);
+ final DiscoveryListener discListener = mock(DiscoveryListener.class);
+ client.discoverServices(SERVICE_TYPE, PROTOCOL, discListener);
+ waitForIdle();
+
+ final IMDnsEventListener eventListener = getEventListener();
+ final ArgumentCaptor<Integer> discIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockMDnsM).discover(discIdCaptor.capture(), eq(SERVICE_TYPE), eq(IFACE_IDX_ANY));
+ verify(discListener, timeout(TIMEOUT_MS)).onDiscoveryStarted(SERVICE_TYPE);
+
+ // Fail to discover service.
+ final DiscoveryInfo discoveryFailedInfo = new DiscoveryInfo(
+ discIdCaptor.getValue(),
+ IMDnsEventListener.SERVICE_DISCOVERY_FAILED,
+ null /* serviceName */,
+ null /* registrationType */,
+ null /* domainName */,
+ IFACE_IDX_ANY,
+ 0 /* netId */);
+ eventListener.onServiceDiscoveryStatus(discoveryFailedInfo);
+ verify(discListener, timeout(TIMEOUT_MS))
+ .onStartDiscoveryFailed(SERVICE_TYPE, FAILURE_INTERNAL_ERROR);
+ }
+
+ @Test
+ public void testServiceResolutionFailed() throws Exception {
+ final NsdManager client = connectClient(mService);
+ final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+ final ResolveListener resolveListener = mock(ResolveListener.class);
+ client.resolveService(request, resolveListener);
+ waitForIdle();
+
+ final IMDnsEventListener eventListener = getEventListener();
+ final ArgumentCaptor<Integer> resolvIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE),
+ eq("local.") /* domain */, eq(IFACE_IDX_ANY));
+
+ // Fail to resolve service.
+ final ResolutionInfo resolutionFailedInfo = new ResolutionInfo(
+ resolvIdCaptor.getValue(),
+ IMDnsEventListener.SERVICE_RESOLUTION_FAILED,
+ null /* serviceName */,
+ null /* serviceType */,
+ null /* domain */,
+ null /* serviceFullName */,
+ null /* domainName */,
+ 0 /* port */,
+ new byte[0] /* txtRecord */,
+ IFACE_IDX_ANY);
+ eventListener.onServiceResolutionStatus(resolutionFailedInfo);
+ verify(resolveListener, timeout(TIMEOUT_MS))
+ .onResolveFailed(any(), eq(FAILURE_INTERNAL_ERROR));
+ }
+
+ @Test
+ public void testGettingAddressFailed() throws Exception {
+ final NsdManager client = connectClient(mService);
+ final NsdServiceInfo request = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
+ final ResolveListener resolveListener = mock(ResolveListener.class);
+ client.resolveService(request, resolveListener);
+ waitForIdle();
+
+ final IMDnsEventListener eventListener = getEventListener();
+ final ArgumentCaptor<Integer> resolvIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockMDnsM).resolve(resolvIdCaptor.capture(), eq(SERVICE_NAME), eq(SERVICE_TYPE),
+ eq("local.") /* domain */, eq(IFACE_IDX_ANY));
+
+ // Resolve service successfully.
+ final ResolutionInfo resolutionInfo = new ResolutionInfo(
+ resolvIdCaptor.getValue(),
+ IMDnsEventListener.SERVICE_RESOLVED,
+ null /* serviceName */,
+ null /* serviceType */,
+ null /* domain */,
+ SERVICE_FULL_NAME,
+ DOMAIN_NAME,
+ PORT,
+ new byte[0] /* txtRecord */,
+ IFACE_IDX_ANY);
+ doReturn(true).when(mMockMDnsM).getServiceAddress(anyInt(), any(), anyInt());
+ eventListener.onServiceResolutionStatus(resolutionInfo);
+ waitForIdle();
+
+ final ArgumentCaptor<Integer> getAddrIdCaptor = ArgumentCaptor.forClass(Integer.class);
+ verify(mMockMDnsM).getServiceAddress(getAddrIdCaptor.capture(), eq(DOMAIN_NAME),
+ eq(IFACE_IDX_ANY));
+
+ // Fail to get service address.
+ final GetAddressInfo gettingAddrFailedInfo = new GetAddressInfo(
+ getAddrIdCaptor.getValue(),
+ IMDnsEventListener.SERVICE_GET_ADDR_FAILED,
+ null /* hostname */,
+ null /* address */,
+ IFACE_IDX_ANY,
+ 0 /* netId */);
+ eventListener.onGettingServiceAddressStatus(gettingAddrFailedInfo);
+ verify(resolveListener, timeout(TIMEOUT_MS))
+ .onResolveFailed(any(), eq(FAILURE_INTERNAL_ERROR));
+ }
+
private void waitForIdle() {
HandlerUtils.waitForIdle(mHandler, TIMEOUT_MS);
}