Merge "Process all responses if the network is null in MdnsServiceTypeClient"
diff --git a/Tethering/Android.bp b/Tethering/Android.bp
index 83ca2b7..b88ec7f 100644
--- a/Tethering/Android.bp
+++ b/Tethering/Android.bp
@@ -119,7 +119,6 @@
name: "libcom_android_networkstack_tethering_util_jni",
sdk_version: "30",
apex_available: [
- "//apex_available:platform", // Used by InProcessTethering
"com.android.tethering",
],
min_sdk_version: "30",
@@ -188,24 +187,6 @@
lint: { strict_updatability_linting: true },
}
-// Non-updatable tethering running in the system server process for devices not using the module
-android_app {
- name: "InProcessTethering",
- defaults: [
- "TetheringAppDefaults",
- "TetheringApiLevel",
- "ConnectivityNextEnableDefaults",
- "TetheringReleaseTargetSdk"
- ],
- static_libs: ["TetheringApiCurrentLib"],
- certificate: "platform",
- manifest: "AndroidManifest_InProcess.xml",
- // InProcessTethering is a replacement for Tethering
- overrides: ["Tethering"],
- apex_available: ["com.android.tethering"],
- lint: { strict_updatability_linting: true },
-}
-
// Updatable tethering packaged for finalized API
android_app {
name: "Tethering",
diff --git a/Tethering/AndroidManifest_InProcess.xml b/Tethering/AndroidManifest_InProcess.xml
deleted file mode 100644
index b1f1240..0000000
--- a/Tethering/AndroidManifest_InProcess.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
--->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.networkstack.tethering.inprocess"
- android:sharedUserId="android.uid.system"
- android:process="system">
- <uses-sdk android:minSdkVersion="29" android:targetSdkVersion="29" />
- <application>
- <service android:name="com.android.networkstack.tethering.TetheringService"
- android:process="system"
- android:permission="android.permission.MAINLINE_NETWORK_STACK"
- android:exported="true">
- <intent-filter>
- <action android:name="android.net.ITetheringConnector.InProcess"/>
- </intent-filter>
- </service>
- </application>
-</manifest>
diff --git a/Tethering/apex/Android.bp b/Tethering/apex/Android.bp
index d84fef3..4506e5a 100644
--- a/Tethering/apex/Android.bp
+++ b/Tethering/apex/Android.bp
@@ -19,13 +19,6 @@
}
prebuilt_etc {
- name: "TetheringInProcessFlag",
- src: "in-process",
- filename_from_src: true,
- sub_dir: "flag",
-}
-
-prebuilt_etc {
name: "TetheringOutOfProcessFlag",
src: "out-of-process",
filename_from_src: true,
@@ -254,27 +247,3 @@
standalone_contents: ["service-connectivity"],
apex_available: ["com.android.tethering"],
}
-
-override_apex {
- name: "com.android.tethering.inprocess",
- base: "com.android.tethering",
- package_name: "com.android.tethering.inprocess",
- enabled: enable_tethering_next_apex,
- bpfs: [
- "block.o",
- "clatd.o",
- "dscpPolicy.o",
- "netd.o",
- "offload@inprocess.o",
- "test@inprocess.o",
- ],
- apps: [
- "ServiceConnectivityResources",
- "InProcessTethering",
- ],
- prebuilts: [
- "current_sdkinfo",
- "privapp_allowlist_com.android.tethering",
- "TetheringInProcessFlag",
- ],
-}
diff --git a/Tethering/tests/integration/base/android/net/TetheringTester.java b/Tethering/tests/integration/base/android/net/TetheringTester.java
index ae39b24..1c0803e 100644
--- a/Tethering/tests/integration/base/android/net/TetheringTester.java
+++ b/Tethering/tests/integration/base/android/net/TetheringTester.java
@@ -628,7 +628,7 @@
return false;
}
- private void sendUploadPacket(ByteBuffer packet) throws Exception {
+ public void sendUploadPacket(ByteBuffer packet) throws Exception {
mDownstreamReader.sendResponse(packet);
}
@@ -680,4 +680,12 @@
return verifyPacketNotNull("Download fail", getDownloadPacket(filter));
}
+
+ // Send DHCPDISCOVER to DHCP server to see if DHCP server is still alive to handle
+ // the upcoming DHCP packets. This method should be only used when we know the DHCP
+ // server has been created successfully before.
+ public boolean testDhcpServerAlive(final MacAddress mac) throws Exception {
+ sendDhcpDiscover(mac.toByteArray());
+ return getNextDhcpPacket() != null;
+ }
}
diff --git a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
index 55854e2..21927df 100644
--- a/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
+++ b/Tethering/tests/integration/src/android/net/EthernetTetheringTest.java
@@ -39,6 +39,7 @@
import static com.android.net.module.util.NetworkStackConstants.IPV4_LENGTH_OFFSET;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@@ -839,4 +840,41 @@
REMOTE_NAT64_ADDR /* downloadSrcIp */, clatIp6 /* downloadDstIp */,
tester, true /* isClat */);
}
+
+ private static final byte[] ZeroLengthDhcpPacket = new byte[] {
+ // scapy.Ether(
+ // dst="ff:ff:ff:ff:ff:ff")
+ // scapy.IP(
+ // dst="255.255.255.255")
+ // scapy.UDP(sport=68, dport=67)
+ /* Ethernet Header */
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff,
+ (byte) 0xe0, (byte) 0x4f, (byte) 0x43, (byte) 0xe6, (byte) 0xfb, (byte) 0xd2,
+ (byte) 0x08, (byte) 0x00,
+ /* Ip header */
+ (byte) 0x45, (byte) 0x00, (byte) 0x00, (byte) 0x1c, (byte) 0x00, (byte) 0x01,
+ (byte) 0x00, (byte) 0x00, (byte) 0x40, (byte) 0x11, (byte) 0xb6, (byte) 0x58,
+ (byte) 0x64, (byte) 0x4f, (byte) 0x60, (byte) 0x29, (byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff,
+ /* UDP header */
+ (byte) 0x00, (byte) 0x44, (byte) 0x00, (byte) 0x43,
+ (byte) 0x00, (byte) 0x08, (byte) 0x3a, (byte) 0xdf
+ };
+
+ @Test
+ public void testTetherZeroLengthDhcpPacket() throws Exception {
+ final TetheringTester tester = initTetheringTester(toList(TEST_IP4_ADDR),
+ toList(TEST_IP4_DNS));
+ tester.createTetheredDevice(TEST_MAC, false /* hasIpv6 */);
+
+ // Send a zero-length DHCP packet to upstream DHCP server.
+ final ByteBuffer packet = ByteBuffer.wrap(ZeroLengthDhcpPacket);
+ tester.sendUploadPacket(packet);
+
+ // Send DHCPDISCOVER packet from another downstream tethered device to verify that upstream
+ // DHCP server has closed the listening socket and stopped reading, then we will not receive
+ // any DHCPOFFER in this case.
+ final MacAddress macAddress = MacAddress.fromString("11:22:33:44:55:66");
+ assertFalse(tester.testDhcpServerAlive(macAddress));
+ }
}
diff --git a/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java b/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
index b3fb3e4..81d4fbe 100644
--- a/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
+++ b/Tethering/tests/privileged/src/com/android/networkstack/tethering/ConntrackSocketTest.java
@@ -106,6 +106,7 @@
ConntrackMessage.Tuple tuple = ctmsg.tupleOrig;
if (nlmsghdr.nlmsg_type == (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_NEW)
+ && tuple != null
&& tuple.protoNum == IPPROTO_TCP
&& tuple.srcIp.equals(local.getAddress())
&& tuple.dstIp.equals(remote.getAddress())
diff --git a/bpf_progs/Android.bp b/bpf_progs/Android.bp
index 229dce3..b3f8ed6 100644
--- a/bpf_progs/Android.bp
+++ b/bpf_progs/Android.bp
@@ -103,18 +103,6 @@
}
bpf {
- name: "offload@inprocess.o",
- srcs: ["offload@inprocess.c"],
- btf: true,
- cflags: [
- "-Wall",
- "-Werror",
- "-DBTF",
- "-DINPROCESS",
- ],
-}
-
-bpf {
name: "test.o",
srcs: ["test.c"],
cflags: [
@@ -135,18 +123,6 @@
}
bpf {
- name: "test@inprocess.o",
- srcs: ["test@inprocess.c"],
- btf: true,
- cflags: [
- "-Wall",
- "-Werror",
- "-DBTF",
- "-DINPROCESS",
- ],
-}
-
-bpf {
name: "clatd.o",
srcs: ["clatd.c"],
btf: true,
diff --git a/bpf_progs/offload.c b/bpf_progs/offload.c
index f4d4254..80d1a41 100644
--- a/bpf_progs/offload.c
+++ b/bpf_progs/offload.c
@@ -38,13 +38,7 @@
// Warning: values other than AID_ROOT don't work for map uid on BpfLoader < v0.21
#define TETHERING_UID AID_ROOT
-#ifdef INPROCESS
-#define DEFAULT_BPF_MAP_SELINUX_CONTEXT "fs_bpf_net_shared"
-#define DEFAULT_BPF_PROG_SELINUX_CONTEXT "fs_bpf_net_shared"
-#define TETHERING_GID AID_SYSTEM
-#else
#define TETHERING_GID AID_NETWORK_STACK
-#endif
#include "bpf_helpers.h"
#include "bpf_net_helpers.h"
diff --git a/bpf_progs/offload@inprocess.c b/bpf_progs/offload@inprocess.c
deleted file mode 120000
index 4092e0d..0000000
--- a/bpf_progs/offload@inprocess.c
+++ /dev/null
@@ -1 +0,0 @@
-offload.c
\ No newline at end of file
diff --git a/bpf_progs/test.c b/bpf_progs/test.c
index d1f780f..091743c 100644
--- a/bpf_progs/test.c
+++ b/bpf_progs/test.c
@@ -32,13 +32,7 @@
// Warning: values other than AID_ROOT don't work for map uid on BpfLoader < v0.21
#define TETHERING_UID AID_ROOT
-#ifdef INPROCESS
-#define DEFAULT_BPF_MAP_SELINUX_CONTEXT "fs_bpf_net_shared"
-#define DEFAULT_BPF_PROG_SELINUX_CONTEXT "fs_bpf_net_shared"
-#define TETHERING_GID AID_SYSTEM
-#else
#define TETHERING_GID AID_NETWORK_STACK
-#endif
// This is non production code, only used for testing
// Needed because the bitmap array definition is non-kosher for pre-T OS devices.
diff --git a/bpf_progs/test@inprocess.c b/bpf_progs/test@inprocess.c
deleted file mode 120000
index aeebb26..0000000
--- a/bpf_progs/test@inprocess.c
+++ /dev/null
@@ -1 +0,0 @@
-test.c
\ No newline at end of file
diff --git a/framework/src/android/net/NetworkCapabilities.java b/framework/src/android/net/NetworkCapabilities.java
index 3cc9c65..92e9599 100644
--- a/framework/src/android/net/NetworkCapabilities.java
+++ b/framework/src/android/net/NetworkCapabilities.java
@@ -1348,6 +1348,18 @@
}
/**
+ * Gets the transports as an int. Internal callers only.
+ *
+ * Prefer getTransportTypes/hasTransportType if not immediately collapsing back into a scalar.
+ *
+ * @return a long integer representing the transport types.
+ * @hide
+ */
+ public long getTransportTypesInternal() {
+ return mTransportTypes;
+ }
+
+ /**
* Sets all the transports set on this {@code NetworkCapability} instance.
* This overwrites any existing transports.
*
diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java
index a62ee7f..f30f120 100644
--- a/service-t/src/com/android/server/NsdService.java
+++ b/service-t/src/com/android/server/NsdService.java
@@ -19,10 +19,10 @@
import static android.net.ConnectivityManager.NETID_UNSET;
import static android.net.nsd.NsdManager.MDNS_DISCOVERY_MANAGER_EVENT;
import static android.net.nsd.NsdManager.MDNS_SERVICE_EVENT;
-import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
import static com.android.modules.utils.build.SdkLevel.isAtLeastU;
+import static com.android.server.connectivity.mdns.MdnsRecord.MAX_LABEL_LENGTH;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -73,6 +73,7 @@
import com.android.server.connectivity.mdns.MdnsServiceInfo;
import com.android.server.connectivity.mdns.MdnsSocketClientBase;
import com.android.server.connectivity.mdns.MdnsSocketProvider;
+import com.android.server.connectivity.mdns.util.MdnsUtils;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -81,11 +82,6 @@
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -108,8 +104,6 @@
*/
private static final String MDNS_DISCOVERY_MANAGER_VERSION = "mdns_discovery_manager_version";
private static final String LOCAL_DOMAIN_NAME = "local";
- // Max label length as per RFC 1034/1035
- private static final int MAX_LABEL_LENGTH = 63;
/**
* Enable advertising using the Java MdnsAdvertiser, instead of the legacy mdnsresponder
@@ -570,18 +564,7 @@
*/
@NonNull
private String truncateServiceName(@NonNull String originalName) {
- // UTF-8 is at most 4 bytes per character; return early in the common case where
- // the name can't possibly be over the limit given its string length.
- if (originalName.length() <= MAX_LABEL_LENGTH / 4) return originalName;
-
- final Charset utf8 = StandardCharsets.UTF_8;
- final CharsetEncoder encoder = utf8.newEncoder();
- final ByteBuffer out = ByteBuffer.allocate(MAX_LABEL_LENGTH);
- // encode will write as many characters as possible to the out buffer, and just
- // return an overflow code if there were too many characters (no need to check the
- // return code here, this method truncates the name on purpose).
- encoder.encode(CharBuffer.wrap(originalName), out, true /* endOfInput */);
- return new String(out.array(), 0, out.position(), utf8);
+ return MdnsUtils.truncateServiceName(originalName, MAX_LABEL_LENGTH);
}
private void stopDiscoveryManagerRequest(ClientRequest request, int clientId, int id,
@@ -1368,8 +1351,8 @@
* @return true if the MdnsDiscoveryManager feature is enabled.
*/
public boolean isMdnsDiscoveryManagerEnabled(Context context) {
- return isAtLeastU() || DeviceConfigUtils.isFeatureEnabled(context,
- NAMESPACE_CONNECTIVITY, MDNS_DISCOVERY_MANAGER_VERSION,
+ return isAtLeastU() || DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_TETHERING,
+ MDNS_DISCOVERY_MANAGER_VERSION, DeviceConfigUtils.TETHERING_MODULE_NAME,
false /* defaultEnabled */);
}
@@ -1380,8 +1363,9 @@
* @return true if the MdnsAdvertiser feature is enabled.
*/
public boolean isMdnsAdvertiserEnabled(Context context) {
- return isAtLeastU() || DeviceConfigUtils.isFeatureEnabled(context,
- NAMESPACE_CONNECTIVITY, MDNS_ADVERTISER_VERSION, false /* defaultEnabled */);
+ return isAtLeastU() || DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_TETHERING,
+ MDNS_ADVERTISER_VERSION, DeviceConfigUtils.TETHERING_MODULE_NAME,
+ false /* defaultEnabled */);
}
/**
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java
index 33fef9d..a332da7 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java
@@ -16,6 +16,8 @@
package com.android.server.connectivity.mdns;
+import static com.android.server.connectivity.mdns.MdnsRecord.MAX_LABEL_LENGTH;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.LinkAddress;
@@ -29,6 +31,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.net.module.util.SharedLog;
+import com.android.server.connectivity.mdns.util.MdnsUtils;
import java.io.PrintWriter;
import java.util.List;
@@ -359,7 +362,7 @@
// "Name (2)", then "Name (3)" etc.
// TODO: use a hidden method in NsdServiceInfo once MdnsAdvertiser is moved to service-t
final NsdServiceInfo newInfo = new NsdServiceInfo();
- newInfo.setServiceName(mOriginalName + " (" + (mConflictCount + renameCount + 1) + ")");
+ newInfo.setServiceName(getUpdatedServiceName(renameCount));
newInfo.setServiceType(mServiceInfo.getServiceType());
for (Map.Entry<String, byte[]> attr : mServiceInfo.getAttributes().entrySet()) {
newInfo.setAttribute(attr.getKey(),
@@ -372,6 +375,13 @@
return newInfo;
}
+ private String getUpdatedServiceName(int renameCount) {
+ final String suffix = " (" + (mConflictCount + renameCount + 1) + ")";
+ final String truncatedServiceName = MdnsUtils.truncateServiceName(mOriginalName,
+ MAX_LABEL_LENGTH - suffix.length());
+ return truncatedServiceName + suffix;
+ }
+
@NonNull
public NsdServiceInfo getServiceInfo() {
return mServiceInfo;
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java b/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java
index bcee9d1..19630e3 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsRecord.java
@@ -46,6 +46,8 @@
public static final long RECEIPT_TIME_NOT_SENT = 0L;
public static final int CLASS_ANY = 0x00ff;
+ /** Max label length as per RFC 1034/1035 */
+ public static final int MAX_LABEL_LENGTH = 63;
/** Status indicating that the record is current. */
public static final int STATUS_OK = 0;
diff --git a/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java b/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java
index 4b9759d..5cc789f 100644
--- a/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java
+++ b/service-t/src/com/android/server/connectivity/mdns/util/MdnsUtils.java
@@ -21,6 +21,12 @@
import android.net.Network;
import android.os.Handler;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.StandardCharsets;
+
/**
* Mdns utility functions.
*/
@@ -73,4 +79,22 @@
@Nullable Network currentNetwork) {
return targetNetwork == null || targetNetwork.equals(currentNetwork);
}
-}
+
+ /**
+ * Truncate a service name to up to maxLength UTF-8 bytes.
+ */
+ public static String truncateServiceName(@NonNull String originalName, int maxLength) {
+ // UTF-8 is at most 4 bytes per character; return early in the common case where
+ // the name can't possibly be over the limit given its string length.
+ if (originalName.length() <= maxLength / 4) return originalName;
+
+ final Charset utf8 = StandardCharsets.UTF_8;
+ final CharsetEncoder encoder = utf8.newEncoder();
+ final ByteBuffer out = ByteBuffer.allocate(maxLength);
+ // encode will write as many characters as possible to the out buffer, and just
+ // return an overflow code if there were too many characters (no need to check the
+ // return code here, this method truncates the name on purpose).
+ encoder.encode(CharBuffer.wrap(originalName), out, true /* endOfInput */);
+ return new String(out.array(), 0, out.position(), utf8);
+ }
+}
\ No newline at end of file
diff --git a/service/jni/com_android_server_BpfNetMaps.cpp b/service/jni/com_android_server_BpfNetMaps.cpp
index 77cffda..9ced44e 100644
--- a/service/jni/com_android_server_BpfNetMaps.cpp
+++ b/service/jni/com_android_server_BpfNetMaps.cpp
@@ -54,6 +54,10 @@
if (!isOk(status)) {
uid_t uid = getuid();
ALOGE("BpfNetMaps jni init failure as uid=%d", uid);
+ // We probably only ever get called from system_server (ie. AID_SYSTEM)
+ // or from tests, and never from network_stack (ie. AID_NETWORK_STACK).
+ // However, if we ever do add calls from production network_stack code
+ // we do want to make sure this initializes correctly.
// TODO: Fix tests to not use this jni lib, so we can unconditionally abort()
if (uid == AID_SYSTEM || uid == AID_NETWORK_STACK) abort();
}
diff --git a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
index 8d909ed..d966070 100644
--- a/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
+++ b/service/jni/com_android_server_connectivity_ClatCoordinator.cpp
@@ -90,11 +90,6 @@
#undef ALOGF
-bool isGsiImage() {
- // this implementation matches 2 other places in the codebase (same function name too)
- return !access("/system/system_ext/etc/init/init.gsi.rc", F_OK);
-}
-
static const char* kClatdDir = "/apex/com.android.tethering/bin/for-system";
static const char* kClatdBin = "/apex/com.android.tethering/bin/for-system/clatd";
@@ -135,14 +130,6 @@
#undef V2
- // HACK: Some old vendor kernels lack ~5.10 backport of 'bpffs selinux genfscon' support.
- // This is *NOT* supported, but let's allow, at least for now, U+ GSI to boot on them.
- // (without this hack pixel5 R vendor + U gsi breaks)
- if (isGsiImage() && !bpf::isAtLeastKernelVersion(5, 10, 0)) {
- ALOGE("GSI with *BAD* pre-5.10 kernel lacking bpffs selinux genfscon support.");
- return;
- }
-
if (fatal) abort();
}
diff --git a/service/jni/onload.cpp b/service/jni/onload.cpp
index 4bbaae6..ed74430 100644
--- a/service/jni/onload.cpp
+++ b/service/jni/onload.cpp
@@ -38,11 +38,11 @@
return JNI_ERR;
}
- if (register_com_android_server_BpfNetMaps(env) < 0) {
- return JNI_ERR;
- }
-
if (android::modules::sdklevel::IsAtLeastT()) {
+ if (register_com_android_server_BpfNetMaps(env) < 0) {
+ return JNI_ERR;
+ }
+
if (register_com_android_server_connectivity_ClatCoordinator(env) < 0) {
return JNI_ERR;
}
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index b4fce37..84e581e 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -281,8 +281,8 @@
if (sEnableJavaBpfMap == null) {
sEnableJavaBpfMap = SdkLevel.isAtLeastU() ||
DeviceConfigUtils.isFeatureEnabled(context,
- DeviceConfig.NAMESPACE_TETHERING, BPF_NET_MAPS_ENABLE_JAVA_BPF_MAP,
- false /* defaultValue */);
+ DeviceConfig.NAMESPACE_TETHERING, BPF_NET_MAPS_ENABLE_JAVA_BPF_MAP,
+ DeviceConfigUtils.TETHERING_MODULE_NAME, false /* defaultValue */);
}
Log.d(TAG, "BpfNetMaps is initialized with sEnableJavaBpfMap=" + sEnableJavaBpfMap);
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index c080c59..fa770a9 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -91,7 +91,7 @@
import static android.net.OemNetworkPreferences.OEM_NETWORK_PREFERENCE_TEST_ONLY;
import static android.os.Process.INVALID_UID;
import static android.os.Process.VPN_UID;
-import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
+import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
import static android.system.OsConstants.ETH_P_ALL;
import static android.system.OsConstants.IPPROTO_TCP;
import static android.system.OsConstants.IPPROTO_UDP;
@@ -1393,9 +1393,9 @@
/**
* @see DeviceConfigUtils#isFeatureEnabled
*/
- public boolean isFeatureEnabled(Context context, String name, boolean defaultEnabled) {
- return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name,
- TETHERING_MODULE_NAME, defaultEnabled);
+ public boolean isFeatureEnabled(Context context, String name) {
+ return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_TETHERING, name,
+ TETHERING_MODULE_NAME, false /* defaultValue */);
}
/**
diff --git a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
index ee8ab68..7c23816 100644
--- a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
@@ -842,7 +842,7 @@
*/
public boolean isFeatureEnabled(@NonNull final String name, final boolean defaultEnabled) {
return DeviceConfigUtils.isFeatureEnabled(mContext, NAMESPACE_TETHERING, name,
- defaultEnabled);
+ DeviceConfigUtils.TETHERING_MODULE_NAME, defaultEnabled);
}
/**
diff --git a/service/src/com/android/server/connectivity/ConnectivityFlags.java b/service/src/com/android/server/connectivity/ConnectivityFlags.java
index 122ea1c..9039a14 100644
--- a/service/src/com/android/server/connectivity/ConnectivityFlags.java
+++ b/service/src/com/android/server/connectivity/ConnectivityFlags.java
@@ -61,6 +61,6 @@
*/
public void loadFlags(ConnectivityService.Dependencies deps, Context ctx) {
mNoRematchAllRequestsOnRegister = deps.isFeatureEnabled(
- ctx, NO_REMATCH_ALL_REQUESTS_ON_REGISTER, false /* defaultEnabled */);
+ ctx, NO_REMATCH_ALL_REQUESTS_ON_REGISTER);
}
}
diff --git a/service/src/com/android/server/connectivity/NetworkDiagnostics.java b/service/src/com/android/server/connectivity/NetworkDiagnostics.java
index 4eba74b..15d0925 100644
--- a/service/src/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/service/src/com/android/server/connectivity/NetworkDiagnostics.java
@@ -19,6 +19,9 @@
import static android.system.OsConstants.*;
import static com.android.net.module.util.NetworkStackConstants.ICMP_HEADER_LEN;
+import static com.android.net.module.util.NetworkStackConstants.IPV4_HEADER_MIN_LEN;
+import static com.android.net.module.util.NetworkStackConstants.IPV6_HEADER_LEN;
+import static com.android.net.module.util.NetworkStackConstants.IPV6_MIN_MTU;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -35,6 +38,7 @@
import android.system.Os;
import android.system.StructTimeval;
import android.text.TextUtils;
+import android.util.Log;
import android.util.Pair;
import com.android.internal.util.IndentingPrintWriter;
@@ -174,7 +178,7 @@
}
}
- private final Map<InetAddress, Measurement> mIcmpChecks = new HashMap<>();
+ private final Map<Pair<InetAddress, Integer>, Measurement> mIcmpChecks = new HashMap<>();
private final Map<Pair<InetAddress, InetAddress>, Measurement> mExplicitSourceIcmpChecks =
new HashMap<>();
private final Map<InetAddress, Measurement> mDnsUdpChecks = new HashMap<>();
@@ -207,17 +211,21 @@
mLinkProperties.addDnsServer(TEST_DNS6);
}
+ final int mtu = mLinkProperties.getMtu();
for (RouteInfo route : mLinkProperties.getRoutes()) {
if (route.getType() == RouteInfo.RTN_UNICAST && route.hasGateway()) {
InetAddress gateway = route.getGateway();
- prepareIcmpMeasurement(gateway);
+ // Use mtu in the route if exists. Otherwise, use the one in the link property.
+ final int routeMtu = route.getMtu();
+ prepareIcmpMeasurements(gateway, (routeMtu > 0) ? routeMtu : mtu);
if (route.isIPv6Default()) {
prepareExplicitSourceIcmpMeasurements(gateway);
}
}
}
+
for (InetAddress nameserver : mLinkProperties.getDnsServers()) {
- prepareIcmpMeasurement(nameserver);
+ prepareIcmpMeasurements(nameserver, mtu);
prepareDnsMeasurement(nameserver);
// Unlike the DnsResolver which doesn't do certificate validation in opportunistic mode,
@@ -263,11 +271,50 @@
localAddr.getHostAddress(), inetSockAddr.getPort());
}
- private void prepareIcmpMeasurement(InetAddress target) {
- if (!mIcmpChecks.containsKey(target)) {
- Measurement measurement = new Measurement();
- measurement.thread = new Thread(new IcmpCheck(target, 0, measurement));
- mIcmpChecks.put(target, measurement);
+ private static int getHeaderLen(@NonNull InetAddress target) {
+ // Convert IPv4 mapped v6 address to v4 if any.
+ try {
+ final InetAddress addr = InetAddress.getByAddress(target.getAddress());
+ // An ICMPv6 header is technically 4 bytes, but the implementation in IcmpCheck#run()
+ // will always fill in another 4 bytes padding in the v6 diagnostic packets, so the size
+ // before icmp data is always 8 bytes in the implementation of ICMP diagnostics for both
+ // v4 and v6 packets. Thus, it's fine to use the v4 header size in the length
+ // calculation.
+ if (addr instanceof Inet6Address) {
+ return IPV6_HEADER_LEN + ICMP_HEADER_LEN;
+ }
+ } catch (UnknownHostException e) {
+ Log.e(TAG, "Create InetAddress fail(" + target + "): " + e);
+ }
+
+ return IPV4_HEADER_MIN_LEN + ICMP_HEADER_LEN;
+ }
+
+ private void prepareIcmpMeasurements(@NonNull InetAddress target, int targetNetworkMtu) {
+ // Test with different size payload ICMP.
+ // 1. Test with 0 payload.
+ addPayloadIcmpMeasurement(target, 0);
+ final int header = getHeaderLen(target);
+ // 2. Test with full size MTU.
+ addPayloadIcmpMeasurement(target, targetNetworkMtu - header);
+ // 3. If v6, make another measurement with the full v6 min MTU, unless that's what
+ // was done above.
+ if ((target instanceof Inet6Address) && (targetNetworkMtu != IPV6_MIN_MTU)) {
+ addPayloadIcmpMeasurement(target, IPV6_MIN_MTU - header);
+ }
+ }
+
+ private void addPayloadIcmpMeasurement(@NonNull InetAddress target, int payloadLen) {
+ // This can happen if the there is no mtu filled(which is 0) in the link property.
+ // The value becomes negative after minus header length.
+ if (payloadLen < 0) return;
+
+ final Pair<InetAddress, Integer> lenTarget =
+ new Pair<>(target, Integer.valueOf(payloadLen));
+ if (!mIcmpChecks.containsKey(lenTarget)) {
+ final Measurement measurement = new Measurement();
+ measurement.thread = new Thread(new IcmpCheck(target, payloadLen, measurement));
+ mIcmpChecks.put(lenTarget, measurement);
}
}
@@ -336,8 +383,8 @@
ArrayList<Measurement> measurements = new ArrayList(totalMeasurementCount());
// Sort measurements IPv4 first.
- for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
- if (entry.getKey() instanceof Inet4Address) {
+ for (Map.Entry<Pair<InetAddress, Integer>, Measurement> entry : mIcmpChecks.entrySet()) {
+ if (entry.getKey().first instanceof Inet4Address) {
measurements.add(entry.getValue());
}
}
@@ -359,8 +406,8 @@
}
// IPv6 measurements second.
- for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
- if (entry.getKey() instanceof Inet6Address) {
+ for (Map.Entry<Pair<InetAddress, Integer>, Measurement> entry : mIcmpChecks.entrySet()) {
+ if (entry.getKey().first instanceof Inet6Address) {
measurements.add(entry.getValue());
}
}
diff --git a/tests/cts/hostside/app/Android.bp b/tests/cts/hostside/app/Android.bp
index 12e7d33..2245382 100644
--- a/tests/cts/hostside/app/Android.bp
+++ b/tests/cts/hostside/app/Android.bp
@@ -30,7 +30,6 @@
"cts-net-utils",
"ctstestrunner-axt",
"modules-utils-build",
- "ub-uiautomator",
],
libs: [
"android.test.runner",
diff --git a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataWarningReceiverTest.java b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataWarningReceiverTest.java
index b2e81ff..13bbab6 100644
--- a/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataWarningReceiverTest.java
+++ b/tests/cts/hostside/app/src/com/android/cts/net/hostside/DataWarningReceiverTest.java
@@ -19,18 +19,18 @@
import static com.android.cts.net.hostside.NetworkPolicyTestUtils.clearSnoozeTimestamps;
import android.content.pm.PackageManager;
-import android.support.test.uiautomator.By;
-import android.support.test.uiautomator.Direction;
-import android.support.test.uiautomator.UiObject2;
-import android.support.test.uiautomator.Until;
import android.telephony.SubscriptionManager;
import android.telephony.SubscriptionPlan;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.Direction;
import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.Until;
import com.android.compatibility.common.util.SystemUtil;
-import com.android.compatibility.common.util.UiAutomatorUtils;
+import com.android.compatibility.common.util.UiAutomatorUtils2;
import org.junit.After;
import org.junit.Assume;
@@ -84,7 +84,7 @@
final UiDevice uiDevice = UiDevice.getInstance(mInstrumentation);
uiDevice.openNotification();
try {
- final UiObject2 uiObject = UiAutomatorUtils.waitFindObject(
+ final UiObject2 uiObject = UiAutomatorUtils2.waitFindObject(
By.text("Data warning"));
Assume.assumeNotNull(uiObject);
uiObject.wait(Until.clickable(true), 10_000L);
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 624acd3..73a6502 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
@@ -100,9 +100,6 @@
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.Settings;
-import android.support.test.uiautomator.UiDevice;
-import android.support.test.uiautomator.UiObject;
-import android.support.test.uiautomator.UiSelector;
import android.system.ErrnoException;
import android.system.Os;
import android.system.OsConstants;
@@ -114,6 +111,9 @@
import android.util.Range;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiSelector;
import com.android.compatibility.common.util.BlockingBroadcastReceiver;
import com.android.modules.utils.build.SdkLevel;
diff --git a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
index 423b2bd..8b059e3 100644
--- a/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/ConnectivityManagerTest.java
@@ -1901,6 +1901,9 @@
*/
@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
+ // getSupportedKeepalives is available in updatable ConnectivityManager (S+)
+ // Also, this feature is not mainlined before S, and it's fine to skip on R- devices.
+ @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest
@RequiresDevice // Keepalive is not supported on virtual hardware
public void testSocketKeepaliveLimitWifi() throws Exception {
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
@@ -1951,6 +1954,9 @@
*/
@AppModeFull(reason = "Cannot request network in instant app mode")
@Test
+ // getSupportedKeepalives is available in updatable ConnectivityManager (S+)
+ // Also, this feature is not mainlined before S, and it's fine to skip on R- devices.
+ @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest
@RequiresDevice // Keepalive is not supported on virtual hardware
public void testSocketKeepaliveLimitTelephony() throws Exception {
if (!mPackageManager.hasSystemFeature(FEATURE_TELEPHONY)) {
@@ -1997,6 +2003,9 @@
*/
@AppModeFull(reason = "Cannot get WifiManager in instant app mode")
@Test
+ // getSupportedKeepalives is available in updatable ConnectivityManager (S+)
+ // Also, this feature is not mainlined before S, and it's fine to skip on R- devices.
+ @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) @ConnectivityModuleTest
@RequiresDevice // Keepalive is not supported on virtual hardware
public void testSocketKeepaliveUnprivileged() throws Exception {
assumeTrue(mPackageManager.hasSystemFeature(FEATURE_WIFI));
@@ -2564,6 +2573,14 @@
tetherUtils.registerTetheringEventCallback();
try {
tetherEventCallback.assumeWifiTetheringSupported(mContext);
+ // To prevent WiFi-to-WiFi interruption while entering APM:
+ // - If WiFi is retained while entering APM, hotspot will also remain enabled.
+ // - If WiFi is off before APM or disabled while entering APM, hotspot will be
+ // disabled.
+ //
+ // To ensure hotspot always be disabled after enabling APM, disable wifi before
+ // enabling the hotspot.
+ mCtsNetUtils.disableWifi();
tetherUtils.startWifiTethering(tetherEventCallback);
// Update setting to verify the behavior.
@@ -2597,6 +2614,7 @@
ConnectivitySettingsManager.setPrivateDnsMode(mContext, curPrivateDnsMode);
tetherUtils.unregisterTetheringEventCallback(tetherEventCallback);
tetherUtils.stopAllTethering();
+ mCtsNetUtils.ensureWifiConnected();
}
}
@@ -2960,13 +2978,13 @@
allowBadWifi();
- final Network cellNetwork = mCtsNetUtils.connectToCell();
- final Network wifiNetwork = prepareValidatedNetwork();
-
- registerDefaultNetworkCallback(defaultCb);
- registerNetworkCallback(makeWifiNetworkRequest(), wifiCb);
-
try {
+ final Network cellNetwork = mCtsNetUtils.connectToCell();
+ final Network wifiNetwork = prepareValidatedNetwork();
+
+ registerDefaultNetworkCallback(defaultCb);
+ registerNetworkCallback(makeWifiNetworkRequest(), wifiCb);
+
// Verify wifi is the default network.
defaultCb.eventuallyExpect(CallbackEntry.AVAILABLE, NETWORK_CALLBACK_TIMEOUT_MS,
entry -> wifiNetwork.equals(entry.getNetwork()));
diff --git a/tests/cts/net/src/android/net/cts/NetworkScoreTest.kt b/tests/cts/net/src/android/net/cts/NetworkScoreTest.kt
index fcfecad..2704dd3 100644
--- a/tests/cts/net/src/android/net/cts/NetworkScoreTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkScoreTest.kt
@@ -30,6 +30,7 @@
import android.os.Build
import android.os.Handler
import android.os.HandlerThread
+import android.util.Log
import androidx.test.InstrumentationRegistry
import com.android.compatibility.common.util.SystemUtil.runWithShellPermissionIdentity
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
@@ -41,6 +42,7 @@
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
+import java.util.Collections
// This test doesn't really have a constraint on how fast the methods should return. If it's
// going to fail, it will simply wait forever, so setting a high timeout lowers the flake ratio
@@ -64,10 +66,11 @@
@IgnoreUpTo(Build.VERSION_CODES.R)
@RunWith(DevSdkIgnoreRunner::class)
class NetworkScoreTest {
+ private val TAG = javaClass.simpleName
private val mCm = testContext.getSystemService(ConnectivityManager::class.java)
- private val mHandlerThread = HandlerThread("${javaClass.simpleName} handler thread")
+ private val mHandlerThread = HandlerThread("$TAG handler thread")
private val mHandler by lazy { Handler(mHandlerThread.looper) }
- private val agentsToCleanUp = mutableListOf<NetworkAgent>()
+ private val agentsToCleanUp = Collections.synchronizedList(mutableListOf<NetworkAgent>())
private val callbacksToCleanUp = mutableListOf<TestableNetworkCallback>()
@Before
@@ -83,15 +86,18 @@
.addTransportType(NetworkCapabilities.TRANSPORT_TEST).build(), cb, mHandler
)
}
+ Log.i(TAG, "Teardown on thread ${System.identityHashCode(Thread.currentThread())} " +
+ "cleaning up ${agentsToCleanUp.size} agents")
agentsToCleanUp.forEach {
+ Log.i(TAG, "Unregister agent for net ${it.network}")
it.unregister()
agentCleanUpCb.eventuallyExpect<CallbackEntry.Lost> { cb -> cb.network == it.network }
}
mCm.unregisterNetworkCallback(agentCleanUpCb)
+ callbacksToCleanUp.forEach { mCm.unregisterNetworkCallback(it) }
mHandlerThread.quitSafely()
mHandlerThread.join()
- callbacksToCleanUp.forEach { mCm.unregisterNetworkCallback(it) }
}
// Returns a networkCallback that sends onAvailable on the best network with TRANSPORT_TEST.
@@ -145,6 +151,8 @@
val agent = object : NetworkAgent(context, looper, "NetworkScore test agent", nc,
LinkProperties(), score, config, NetworkProvider(context, looper,
"NetworkScore test provider")) {}.also {
+ Log.i(TAG, "Add on thread ${System.identityHashCode(Thread.currentThread())} " +
+ "agent to clean up $it")
agentsToCleanUp.add(it)
}
runWithShellPermissionIdentity({ agent.register() }, MANAGE_TEST_NETWORKS)
diff --git a/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java b/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
index f86c5cd..d8a0b07 100644
--- a/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
+++ b/tests/cts/net/src/android/net/cts/NetworkStatsManagerTest.java
@@ -210,7 +210,6 @@
private long mStartTime;
private long mEndTime;
- private long mBytesRead;
private String mWriteSettingsMode;
private String mUsageStatsMode;
@@ -229,6 +228,7 @@
TrafficStats.setThreadStatsTag(NETWORK_TAG);
urlc = (HttpURLConnection) network.openConnection(url);
urlc.setConnectTimeout(TIMEOUT_MILLIS);
+ urlc.setReadTimeout(TIMEOUT_MILLIS);
urlc.setUseCaches(false);
// Disable compression so we generate enough traffic that assertWithinPercentage will
// not be affected by the small amount of traffic (5-10kB) sent by the test harness.
@@ -236,11 +236,10 @@
urlc.connect();
boolean ping = urlc.getResponseCode() == 200;
if (ping) {
- in = new InputStreamReader(
- (InputStream) urlc.getContent());
-
- mBytesRead = 0;
- while (in.read() != -1) ++mBytesRead;
+ in = new InputStreamReader((InputStream) urlc.getContent());
+ // Since the test doesn't really care about the precise amount of data, instead
+ // of reading all contents, just read few bytes at the beginning.
+ in.read();
}
} catch (Exception e) {
Log.i(LOG_TAG, "Badness during exercising remote server: " + e);
@@ -379,7 +378,7 @@
.build(), callback);
synchronized (this) {
try {
- wait((int) (TIMEOUT_MILLIS * 1.2));
+ wait((int) (TIMEOUT_MILLIS * 2.4));
} catch (InterruptedException e) {
}
}
@@ -394,7 +393,7 @@
assertFalse(mNetworkInterfacesToTest[networkTypeIndex].getSystemFeature()
+ " is a reported system feature, "
+ "however no corresponding connected network interface was found or the attempt "
- + "to connect has timed out (timeout = " + TIMEOUT_MILLIS + "ms)."
+ + "to connect and read has timed out (timeout = " + (TIMEOUT_MILLIS * 2) + "ms)."
+ mNetworkInterfacesToTest[networkTypeIndex].getErrorMessage(), hasFeature);
return false;
}
diff --git a/tests/unit/java/com/android/server/ConnectivityServiceTest.java b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
index 877df98..d186920 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -2077,12 +2077,12 @@
}
@Override
- public boolean isFeatureEnabled(Context context, String name, boolean defaultEnabled) {
+ public boolean isFeatureEnabled(Context context, String name) {
switch (name) {
case ConnectivityFlags.NO_REMATCH_ALL_REQUESTS_ON_REGISTER:
return true;
default:
- return super.isFeatureEnabled(context, name, defaultEnabled);
+ return super.isFeatureEnabled(context, name);
}
}
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
index a917361..4b495cd 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
@@ -47,6 +47,8 @@
private const val SERVICE_ID_1 = 1
private const val SERVICE_ID_2 = 2
+private const val LONG_SERVICE_ID_1 = 3
+private const val LONG_SERVICE_ID_2 = 4
private const val TIMEOUT_MS = 10_000L
private val TEST_ADDR = parseNumericAddress("2001:db8::123")
private val TEST_LINKADDR = LinkAddress(TEST_ADDR, 64 /* prefixLength */)
@@ -56,16 +58,30 @@
private val SERVICE_1 = NsdServiceInfo("TestServiceName", "_advertisertest._tcp").apply {
port = 12345
- host = TEST_ADDR
+ hostAddresses = listOf(TEST_ADDR)
network = TEST_NETWORK_1
}
+private val LONG_SERVICE_1 =
+ NsdServiceInfo("a".repeat(48) + "TestServiceName", "_longadvertisertest._tcp").apply {
+ port = 12345
+ hostAddresses = listOf(TEST_ADDR)
+ network = TEST_NETWORK_1
+ }
+
private val ALL_NETWORKS_SERVICE = NsdServiceInfo("TestServiceName", "_advertisertest._tcp").apply {
port = 12345
- host = TEST_ADDR
+ hostAddresses = listOf(TEST_ADDR)
network = null
}
+private val LONG_ALL_NETWORKS_SERVICE =
+ NsdServiceInfo("a".repeat(48) + "TestServiceName", "_longadvertisertest._tcp").apply {
+ port = 12345
+ hostAddresses = listOf(TEST_ADDR)
+ network = null
+ }
+
@RunWith(DevSdkIgnoreRunner::class)
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
class MdnsAdvertiserTest {
@@ -191,6 +207,9 @@
verify(socketProvider).requestSocket(eq(null), allNetSocketCbCaptor.capture())
val allNetSocketCb = allNetSocketCbCaptor.value
+ postSync { advertiser.addService(LONG_SERVICE_ID_1, LONG_SERVICE_1) }
+ postSync { advertiser.addService(LONG_SERVICE_ID_2, LONG_ALL_NETWORKS_SERVICE) }
+
// Callbacks for matching network and all networks both get the socket
postSync {
oneNetSocketCb.onSocketCreated(TEST_NETWORK_1, mockSocket1, listOf(TEST_LINKADDR))
@@ -200,10 +219,18 @@
val expectedRenamed = NsdServiceInfo(
"${ALL_NETWORKS_SERVICE.serviceName} (2)", ALL_NETWORKS_SERVICE.serviceType).apply {
port = ALL_NETWORKS_SERVICE.port
- host = ALL_NETWORKS_SERVICE.host
+ hostAddresses = ALL_NETWORKS_SERVICE.hostAddresses
network = ALL_NETWORKS_SERVICE.network
}
+ val expectedLongRenamed = NsdServiceInfo(
+ "${LONG_ALL_NETWORKS_SERVICE.serviceName.dropLast(4)} (2)",
+ LONG_ALL_NETWORKS_SERVICE.serviceType).apply {
+ port = LONG_ALL_NETWORKS_SERVICE.port
+ hostAddresses = LONG_ALL_NETWORKS_SERVICE.hostAddresses
+ network = LONG_ALL_NETWORKS_SERVICE.network
+ }
+
val intAdvCbCaptor = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
verify(mockDeps).makeAdvertiser(eq(mockSocket1), eq(listOf(TEST_LINKADDR)),
eq(thread.looper), any(), intAdvCbCaptor.capture(), eq(TEST_HOSTNAME)
@@ -212,6 +239,10 @@
argThat { it.matches(SERVICE_1) })
verify(mockInterfaceAdvertiser1).addService(eq(SERVICE_ID_2),
argThat { it.matches(expectedRenamed) })
+ verify(mockInterfaceAdvertiser1).addService(eq(LONG_SERVICE_ID_1),
+ argThat { it.matches(LONG_SERVICE_1) })
+ verify(mockInterfaceAdvertiser1).addService(eq(LONG_SERVICE_ID_2),
+ argThat { it.matches(expectedLongRenamed) })
doReturn(false).`when`(mockInterfaceAdvertiser1).isProbing(SERVICE_ID_1)
postSync { intAdvCbCaptor.value.onRegisterServiceSucceeded(
@@ -251,7 +282,7 @@
return Objects.equals(serviceName, other.serviceName) &&
Objects.equals(serviceType, other.serviceType) &&
Objects.equals(attributes, other.attributes) &&
- Objects.equals(host, other.host) &&
+ Objects.equals(hostAddresses, other.hostAddresses) &&
port == other.port &&
Objects.equals(network, other.network)
}
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt
index f584ed5..61c3a70 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/util/MdnsUtilsTest.kt
@@ -19,6 +19,7 @@
import android.os.Build
import com.android.server.connectivity.mdns.util.MdnsUtils.equalsIgnoreDnsCase
import com.android.server.connectivity.mdns.util.MdnsUtils.toDnsLowerCase
+import com.android.server.connectivity.mdns.util.MdnsUtils.truncateServiceName
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRunner
import org.junit.Assert.assertEquals
@@ -65,4 +66,10 @@
"Test: >\ud83c\udff4\udb40\udc67\udb40\udc62\udb40" +
"\udc77\udb40\udc6c\udb40\udc73\udb40\udc7f<"))
}
+
+ @Test
+ fun testTruncateServiceName() {
+ assertEquals(truncateServiceName("测试abcde", 7), "测试a")
+ assertEquals(truncateServiceName("测试abcde", 100), "测试abcde")
+ }
}