Merge "Fix template for test network needs fine location permission"
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/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/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/MdnsDiscoveryManager.java b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
index 64985ad..8ca93df 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
@@ -82,7 +82,11 @@
final List<MdnsServiceTypeClient> list = new ArrayList<>();
for (int i = 0; i < clients.size(); i++) {
final Pair<String, Network> perNetworkServiceType = clients.keyAt(i);
- if (isNetworkMatched(network, perNetworkServiceType.second)) {
+ final Network serviceTypeNetwork = perNetworkServiceType.second;
+ // The serviceTypeNetwork would be null if the MdnsSocketClient is being used. This
+ // is also the case if the socket is for a tethering interface. In either of these
+ // cases, the client is expected to process any responses.
+ if (serviceTypeNetwork == null || isNetworkMatched(network, serviceTypeNetwork)) {
list.add(clients.valueAt(i));
}
}
@@ -167,12 +171,12 @@
// No listener is registered for the service type anymore, remove it from the list
// of the service type clients.
perNetworkServiceTypeClients.remove(serviceTypeClient);
- if (perNetworkServiceTypeClients.isEmpty()) {
- // No discovery request. Stops the socket client.
- socketClient.stopDiscovery();
- }
}
}
+ if (perNetworkServiceTypeClients.isEmpty()) {
+ // No discovery request. Stops the socket client.
+ socketClient.stopDiscovery();
+ }
// Unrequested the network.
socketClient.notifyNetworkUnrequested(listener);
}
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_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/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/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/hostside/src/com/android/cts/net/ProcNetTest.java b/tests/cts/hostside/src/com/android/cts/net/ProcNetTest.java
index 19e61c6..1a528b1 100644
--- a/tests/cts/hostside/src/com/android/cts/net/ProcNetTest.java
+++ b/tests/cts/hostside/src/com/android/cts/net/ProcNetTest.java
@@ -166,4 +166,15 @@
assertTrue(interval <= upperBoundSec);
}
}
+
+ /**
+ * Verify that cubic is used as the congestion control algorithm.
+ * (This repeats the VTS test, and is here for good performance of the internet as a whole.)
+ * TODO: revisit this once a better CC algorithm like BBR2 is available.
+ */
+ public void testCongestionControl() throws Exception {
+ String path = "/proc/sys/net/ipv4/tcp_congestion_control";
+ String value = mDevice.executeAdbCommand("shell", "cat", path).trim();
+ assertEquals(value, "cubic");
+ }
}
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/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/MdnsDiscoveryManagerTests.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
index 7e7e6a4..e12d9a6 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsDiscoveryManagerTests.java
@@ -18,8 +18,8 @@
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
-import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -38,6 +38,7 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
+import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import java.io.IOException;
@@ -53,15 +54,23 @@
private static final String SERVICE_TYPE_1 = "_googlecast._tcp.local";
private static final String SERVICE_TYPE_2 = "_test._tcp.local";
+ private static final Network NETWORK_1 = Mockito.mock(Network.class);
+ private static final Network NETWORK_2 = Mockito.mock(Network.class);
private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_1 =
Pair.create(SERVICE_TYPE_1, null);
+ private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_1_1 =
+ Pair.create(SERVICE_TYPE_1, NETWORK_1);
private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_2 =
Pair.create(SERVICE_TYPE_2, null);
+ private static final Pair<String, Network> PER_NETWORK_SERVICE_TYPE_2_2 =
+ Pair.create(SERVICE_TYPE_2, NETWORK_2);
@Mock private ExecutorProvider executorProvider;
@Mock private MdnsSocketClientBase socketClient;
@Mock private MdnsServiceTypeClient mockServiceTypeClientOne;
+ @Mock private MdnsServiceTypeClient mockServiceTypeClientOne1;
@Mock private MdnsServiceTypeClient mockServiceTypeClientTwo;
+ @Mock private MdnsServiceTypeClient mockServiceTypeClientTwo2;
@Mock MdnsServiceBrowserListener mockListenerOne;
@Mock MdnsServiceBrowserListener mockListenerTwo;
@@ -71,11 +80,6 @@
public void setUp() {
MockitoAnnotations.initMocks(this);
- when(mockServiceTypeClientOne.getServiceTypeLabels())
- .thenReturn(TextUtils.split(SERVICE_TYPE_1, "\\."));
- when(mockServiceTypeClientTwo.getServiceTypeLabels())
- .thenReturn(TextUtils.split(SERVICE_TYPE_2, "\\."));
-
discoveryManager = new MdnsDiscoveryManager(executorProvider, socketClient) {
@Override
MdnsServiceTypeClient createServiceTypeClient(@NonNull String serviceType,
@@ -84,31 +88,37 @@
Pair.create(serviceType, network);
if (perNetworkServiceType.equals(PER_NETWORK_SERVICE_TYPE_1)) {
return mockServiceTypeClientOne;
+ } else if (perNetworkServiceType.equals(PER_NETWORK_SERVICE_TYPE_1_1)) {
+ return mockServiceTypeClientOne1;
} else if (perNetworkServiceType.equals(PER_NETWORK_SERVICE_TYPE_2)) {
return mockServiceTypeClientTwo;
+ } else if (perNetworkServiceType.equals(PER_NETWORK_SERVICE_TYPE_2_2)) {
+ return mockServiceTypeClientTwo2;
}
return null;
}
};
}
- private void verifyListenerRegistration(String serviceType, MdnsServiceBrowserListener listener,
- MdnsServiceTypeClient client) throws IOException {
+ private SocketCreationCallback expectSocketCreationCallback(String serviceType,
+ MdnsServiceBrowserListener listener, MdnsSearchOptions options) throws IOException {
final ArgumentCaptor<SocketCreationCallback> callbackCaptor =
ArgumentCaptor.forClass(SocketCreationCallback.class);
- discoveryManager.registerListener(serviceType, listener,
- MdnsSearchOptions.getDefaultOptions());
+ discoveryManager.registerListener(serviceType, listener, options);
verify(socketClient).startDiscovery();
verify(socketClient).notifyNetworkRequested(
- eq(listener), any(), callbackCaptor.capture());
- final SocketCreationCallback callback = callbackCaptor.getValue();
- callback.onSocketCreated(null /* network */);
- verify(client).startSendAndReceive(listener, MdnsSearchOptions.getDefaultOptions());
+ eq(listener), eq(options.getNetwork()), callbackCaptor.capture());
+ return callbackCaptor.getValue();
}
@Test
public void registerListener_unregisterListener() throws IOException {
- verifyListenerRegistration(SERVICE_TYPE_1, mockListenerOne, mockServiceTypeClientOne);
+ final MdnsSearchOptions options =
+ MdnsSearchOptions.newBuilder().setNetwork(null /* network */).build();
+ final SocketCreationCallback callback = expectSocketCreationCallback(
+ SERVICE_TYPE_1, mockListenerOne, options);
+ callback.onSocketCreated(null /* network */);
+ verify(mockServiceTypeClientOne).startSendAndReceive(mockListenerOne, options);
when(mockServiceTypeClientOne.stopSendAndReceive(mockListenerOne)).thenReturn(true);
discoveryManager.unregisterListener(SERVICE_TYPE_1, mockListenerOne);
@@ -118,30 +128,67 @@
@Test
public void registerMultipleListeners() throws IOException {
- verifyListenerRegistration(SERVICE_TYPE_1, mockListenerOne, mockServiceTypeClientOne);
- verifyListenerRegistration(SERVICE_TYPE_2, mockListenerTwo, mockServiceTypeClientTwo);
+ final MdnsSearchOptions options =
+ MdnsSearchOptions.newBuilder().setNetwork(null /* network */).build();
+ final SocketCreationCallback callback = expectSocketCreationCallback(
+ SERVICE_TYPE_1, mockListenerOne, options);
+ callback.onSocketCreated(null /* network */);
+ verify(mockServiceTypeClientOne).startSendAndReceive(mockListenerOne, options);
+ callback.onSocketCreated(NETWORK_1);
+ verify(mockServiceTypeClientOne1).startSendAndReceive(mockListenerOne, options);
+
+ final SocketCreationCallback callback2 = expectSocketCreationCallback(
+ SERVICE_TYPE_2, mockListenerTwo, options);
+ callback2.onSocketCreated(null /* network */);
+ verify(mockServiceTypeClientTwo).startSendAndReceive(mockListenerTwo, options);
+ callback2.onSocketCreated(NETWORK_2);
+ verify(mockServiceTypeClientTwo2).startSendAndReceive(mockListenerTwo, options);
}
@Test
public void onResponseReceived() throws IOException {
- verifyListenerRegistration(SERVICE_TYPE_1, mockListenerOne, mockServiceTypeClientOne);
- verifyListenerRegistration(SERVICE_TYPE_2, mockListenerTwo, mockServiceTypeClientTwo);
+ final MdnsSearchOptions options1 =
+ MdnsSearchOptions.newBuilder().setNetwork(null /* network */).build();
+ final SocketCreationCallback callback = expectSocketCreationCallback(
+ SERVICE_TYPE_1, mockListenerOne, options1);
+ callback.onSocketCreated(null /* network */);
+ verify(mockServiceTypeClientOne).startSendAndReceive(mockListenerOne, options1);
+ callback.onSocketCreated(NETWORK_1);
+ verify(mockServiceTypeClientOne1).startSendAndReceive(mockListenerOne, options1);
- MdnsPacket responseForServiceTypeOne = createMdnsPacket(SERVICE_TYPE_1);
+ final MdnsSearchOptions options2 =
+ MdnsSearchOptions.newBuilder().setNetwork(NETWORK_2).build();
+ final SocketCreationCallback callback2 = expectSocketCreationCallback(
+ SERVICE_TYPE_2, mockListenerTwo, options2);
+ callback2.onSocketCreated(NETWORK_2);
+ verify(mockServiceTypeClientTwo2).startSendAndReceive(mockListenerTwo, options2);
+
+ final MdnsPacket responseForServiceTypeOne = createMdnsPacket(SERVICE_TYPE_1);
final int ifIndex = 1;
discoveryManager.onResponseReceived(responseForServiceTypeOne, ifIndex, null /* network */);
verify(mockServiceTypeClientOne).processResponse(responseForServiceTypeOne, ifIndex,
null /* network */);
-
- MdnsPacket responseForServiceTypeTwo = createMdnsPacket(SERVICE_TYPE_2);
- discoveryManager.onResponseReceived(responseForServiceTypeTwo, ifIndex, null /* network */);
- verify(mockServiceTypeClientTwo).processResponse(responseForServiceTypeTwo, ifIndex,
+ verify(mockServiceTypeClientOne1).processResponse(responseForServiceTypeOne, ifIndex,
+ null /* network */);
+ verify(mockServiceTypeClientTwo2).processResponse(responseForServiceTypeOne, ifIndex,
null /* network */);
- MdnsPacket responseForSubtype = createMdnsPacket("subtype._sub._googlecast._tcp.local");
- discoveryManager.onResponseReceived(responseForSubtype, ifIndex, null /* network */);
- verify(mockServiceTypeClientOne).processResponse(responseForSubtype, ifIndex,
- null /* network */);
+ final MdnsPacket responseForServiceTypeTwo = createMdnsPacket(SERVICE_TYPE_2);
+ discoveryManager.onResponseReceived(responseForServiceTypeTwo, ifIndex, NETWORK_1);
+ verify(mockServiceTypeClientOne).processResponse(responseForServiceTypeTwo, ifIndex,
+ NETWORK_1);
+ verify(mockServiceTypeClientOne1).processResponse(responseForServiceTypeTwo, ifIndex,
+ NETWORK_1);
+ verify(mockServiceTypeClientTwo2, never()).processResponse(responseForServiceTypeTwo,
+ ifIndex, NETWORK_1);
+
+ final MdnsPacket responseForSubtype =
+ createMdnsPacket("subtype._sub._googlecast._tcp.local");
+ discoveryManager.onResponseReceived(responseForSubtype, ifIndex, NETWORK_2);
+ verify(mockServiceTypeClientOne).processResponse(responseForSubtype, ifIndex, NETWORK_2);
+ verify(mockServiceTypeClientOne1, never()).processResponse(
+ responseForSubtype, ifIndex, NETWORK_2);
+ verify(mockServiceTypeClientTwo2).processResponse(responseForSubtype, ifIndex, NETWORK_2);
}
private MdnsPacket createMdnsPacket(String serviceType) {
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")
+ }
}