Merge "Use private dns port definition in static lib"
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..1e0d544 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
@@ -148,6 +142,7 @@
public static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
private static final long CLEANUP_DELAY_MS = 10000;
private static final int IFACE_IDX_ANY = 0;
+ private static final SharedLog LOGGER = new SharedLog("serviceDiscovery");
private final Context mContext;
private final NsdStateMachine mNsdStateMachine;
@@ -163,7 +158,7 @@
private final MdnsSocketProvider mMdnsSocketProvider;
@NonNull
private final MdnsAdvertiser mAdvertiser;
- private final SharedLog mServiceLogs = new SharedLog(TAG);
+ private final SharedLog mServiceLogs = LOGGER.forSubComponent(TAG);
// WARNING : Accessing these values in any thread is not safe, it must only be changed in the
// state machine thread. If change this outside state machine, it will need to introduce
// synchronization.
@@ -570,18 +565,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,
@@ -1343,17 +1327,18 @@
mMDnsEventCallback = new MDnsEventCallback(mNsdStateMachine);
mDeps = deps;
- mMdnsSocketProvider = deps.makeMdnsSocketProvider(ctx, handler.getLooper());
+ mMdnsSocketProvider = deps.makeMdnsSocketProvider(ctx, handler.getLooper(),
+ LOGGER.forSubComponent("MdnsSocketProvider"));
// Netlink monitor starts on boot, and intentionally never stopped, to ensure that all
// address events are received.
handler.post(mMdnsSocketProvider::startNetLinkMonitor);
mMdnsSocketClient =
new MdnsMultinetworkSocketClient(handler.getLooper(), mMdnsSocketProvider);
- mMdnsDiscoveryManager =
- deps.makeMdnsDiscoveryManager(new ExecutorProvider(), mMdnsSocketClient);
+ mMdnsDiscoveryManager = deps.makeMdnsDiscoveryManager(new ExecutorProvider(),
+ mMdnsSocketClient, LOGGER.forSubComponent("MdnsDiscoveryManager"));
handler.post(() -> mMdnsSocketClient.setCallback(mMdnsDiscoveryManager));
mAdvertiser = deps.makeMdnsAdvertiser(handler.getLooper(), mMdnsSocketProvider,
- new AdvertiserCallback());
+ new AdvertiserCallback(), LOGGER.forSubComponent("MdnsAdvertiser"));
}
/**
@@ -1368,8 +1353,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 +1365,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 */);
}
/**
@@ -1406,8 +1392,9 @@
* @see MdnsDiscoveryManager
*/
public MdnsDiscoveryManager makeMdnsDiscoveryManager(
- ExecutorProvider executorProvider, MdnsSocketClientBase socketClient) {
- return new MdnsDiscoveryManager(executorProvider, socketClient);
+ @NonNull ExecutorProvider executorProvider,
+ @NonNull MdnsSocketClientBase socketClient, @NonNull SharedLog sharedLog) {
+ return new MdnsDiscoveryManager(executorProvider, socketClient, sharedLog);
}
/**
@@ -1415,15 +1402,16 @@
*/
public MdnsAdvertiser makeMdnsAdvertiser(
@NonNull Looper looper, @NonNull MdnsSocketProvider socketProvider,
- @NonNull MdnsAdvertiser.AdvertiserCallback cb) {
- return new MdnsAdvertiser(looper, socketProvider, cb);
+ @NonNull MdnsAdvertiser.AdvertiserCallback cb, @NonNull SharedLog sharedLog) {
+ return new MdnsAdvertiser(looper, socketProvider, cb, sharedLog);
}
/**
* @see MdnsSocketProvider
*/
- public MdnsSocketProvider makeMdnsSocketProvider(Context context, Looper looper) {
- return new MdnsSocketProvider(context, looper);
+ public MdnsSocketProvider makeMdnsSocketProvider(@NonNull Context context,
+ @NonNull Looper looper, @NonNull SharedLog sharedLog) {
+ return new MdnsSocketProvider(context, looper, sharedLog);
}
}
@@ -1785,30 +1773,10 @@
// Dump service and clients logs
pw.println();
+ pw.println("Logs:");
pw.increaseIndent();
mServiceLogs.reverseDump(pw);
pw.decreaseIndent();
-
- // Dump advertiser related logs
- pw.println();
- pw.println("Advertiser:");
- pw.increaseIndent();
- mAdvertiser.dump(pw);
- pw.decreaseIndent();
-
- // Dump discoverymanager related logs
- pw.println();
- pw.println("DiscoveryManager:");
- pw.increaseIndent();
- mMdnsDiscoveryManager.dump(pw);
- pw.decreaseIndent();
-
- // Dump socketprovider related logs
- pw.println();
- pw.println("SocketProvider:");
- pw.increaseIndent();
- mMdnsSocketProvider.dump(pw);
- pw.decreaseIndent();
}
private abstract static class ClientRequest {
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..655c364 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,8 +31,8 @@
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;
import java.util.Map;
import java.util.UUID;
@@ -48,7 +50,7 @@
// Top-level domain for link-local queries, as per RFC6762 3.
private static final String LOCAL_TLD = "local";
- private static final SharedLog LOGGER = new SharedLog(TAG);
+
private final Looper mLooper;
private final AdvertiserCallback mCb;
@@ -68,6 +70,7 @@
private final Dependencies mDeps;
private String[] mDeviceHostName;
+ @NonNull private final SharedLog mSharedLog;
/**
* Dependencies for {@link MdnsAdvertiser}, useful for testing.
@@ -81,11 +84,11 @@
@NonNull List<LinkAddress> initialAddresses,
@NonNull Looper looper, @NonNull byte[] packetCreationBuffer,
@NonNull MdnsInterfaceAdvertiser.Callback cb,
- @NonNull String[] deviceHostName) {
+ @NonNull String[] deviceHostName,
+ @NonNull SharedLog sharedLog) {
// Note NetworkInterface is final and not mockable
- final String logTag = socket.getInterface().getName();
- return new MdnsInterfaceAdvertiser(logTag, socket, initialAddresses, looper,
- packetCreationBuffer, cb, deviceHostName, LOGGER.forSubComponent(logTag));
+ return new MdnsInterfaceAdvertiser(socket, initialAddresses, looper,
+ packetCreationBuffer, cb, deviceHostName, sharedLog);
}
/**
@@ -132,7 +135,7 @@
@Override
public void onServiceConflict(@NonNull MdnsInterfaceAdvertiser advertiser, int serviceId) {
- LOGGER.i("Found conflict, restarted probing for service " + serviceId);
+ mSharedLog.i("Found conflict, restarted probing for service " + serviceId);
final Registration registration = mRegistrations.get(serviceId);
if (registration == null) return;
@@ -288,7 +291,8 @@
MdnsInterfaceAdvertiser advertiser = mAllAdvertisers.get(socket);
if (advertiser == null) {
advertiser = mDeps.makeAdvertiser(socket, addresses, mLooper, mPacketCreationBuffer,
- mInterfaceAdvertiserCb, mDeviceHostName);
+ mInterfaceAdvertiserCb, mDeviceHostName,
+ mSharedLog.forSubComponent(socket.getInterface().getName()));
mAllAdvertisers.put(socket, advertiser);
advertiser.start();
}
@@ -359,7 +363,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 +376,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;
@@ -406,18 +417,20 @@
}
public MdnsAdvertiser(@NonNull Looper looper, @NonNull MdnsSocketProvider socketProvider,
- @NonNull AdvertiserCallback cb) {
- this(looper, socketProvider, cb, new Dependencies());
+ @NonNull AdvertiserCallback cb, @NonNull SharedLog sharedLog) {
+ this(looper, socketProvider, cb, new Dependencies(), sharedLog);
}
@VisibleForTesting
MdnsAdvertiser(@NonNull Looper looper, @NonNull MdnsSocketProvider socketProvider,
- @NonNull AdvertiserCallback cb, @NonNull Dependencies deps) {
+ @NonNull AdvertiserCallback cb, @NonNull Dependencies deps,
+ @NonNull SharedLog sharedLog) {
mLooper = looper;
mCb = cb;
mSocketProvider = socketProvider;
mDeps = deps;
mDeviceHostName = deps.generateHostname();
+ mSharedLog = sharedLog;
}
private void checkThread() {
@@ -440,7 +453,7 @@
return;
}
- LOGGER.i("Adding service " + service + " with ID " + id);
+ mSharedLog.i("Adding service " + service + " with ID " + id);
final Network network = service.getNetwork();
final Registration registration = new Registration(service);
@@ -472,7 +485,7 @@
public void removeService(int id) {
checkThread();
if (!mRegistrations.contains(id)) return;
- LOGGER.i("Removing service with ID " + id);
+ mSharedLog.i("Removing service with ID " + id);
for (int i = mAdvertiserRequests.size() - 1; i >= 0; i--) {
final InterfaceAdvertiserRequest advertiser = mAdvertiserRequests.valueAt(i);
advertiser.removeService(id);
@@ -484,10 +497,6 @@
}
}
- /** Dump info to dumpsys */
- public void dump(PrintWriter pw) {
- LOGGER.reverseDump(pw);
- }
private static <K, V> boolean any(@NonNull ArrayMap<K, V> map,
@NonNull BiPredicate<K, V> predicate) {
for (int i = 0; i < map.size(); i++) {
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..849eac1 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsDiscoveryManager.java
@@ -32,7 +32,6 @@
import com.android.net.module.util.SharedLog;
import java.io.IOException;
-import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -43,10 +42,10 @@
public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
private static final String TAG = MdnsDiscoveryManager.class.getSimpleName();
public static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
- private static final SharedLog LOGGER = new SharedLog(TAG);
private final ExecutorProvider executorProvider;
private final MdnsSocketClientBase socketClient;
+ @NonNull private final SharedLog sharedLog;
@GuardedBy("this")
@NonNull private final PerNetworkServiceTypeClients perNetworkServiceTypeClients;
@@ -82,7 +81,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));
}
}
@@ -100,9 +103,10 @@
}
public MdnsDiscoveryManager(@NonNull ExecutorProvider executorProvider,
- @NonNull MdnsSocketClientBase socketClient) {
+ @NonNull MdnsSocketClientBase socketClient, @NonNull SharedLog sharedLog) {
this.executorProvider = executorProvider;
this.socketClient = socketClient;
+ this.sharedLog = sharedLog;
perNetworkServiceTypeClients = new PerNetworkServiceTypeClients();
}
@@ -120,13 +124,13 @@
@NonNull String serviceType,
@NonNull MdnsServiceBrowserListener listener,
@NonNull MdnsSearchOptions searchOptions) {
- LOGGER.i("Registering listener for serviceType: " + serviceType);
+ sharedLog.i("Registering listener for serviceType: " + serviceType);
if (perNetworkServiceTypeClients.isEmpty()) {
// First listener. Starts the socket client.
try {
socketClient.startDiscovery();
} catch (IOException e) {
- LOGGER.e("Failed to start discover.", e);
+ sharedLog.e("Failed to start discover.", e);
return;
}
}
@@ -155,7 +159,7 @@
@RequiresPermission(permission.CHANGE_WIFI_MULTICAST_STATE)
public synchronized void unregisterListener(
@NonNull String serviceType, @NonNull MdnsServiceBrowserListener listener) {
- LOGGER.i("Unregistering listener for serviceType:" + serviceType);
+ sharedLog.i("Unregistering listener for serviceType:" + serviceType);
final List<MdnsServiceTypeClient> serviceTypeClients =
perNetworkServiceTypeClients.getByServiceType(serviceType);
if (serviceTypeClients.isEmpty()) {
@@ -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);
}
@@ -195,19 +199,13 @@
}
}
- /** Dump info to dumpsys */
- public void dump(PrintWriter pw) {
- LOGGER.reverseDump(pw);
- }
-
@VisibleForTesting
MdnsServiceTypeClient createServiceTypeClient(@NonNull String serviceType,
@Nullable Network network) {
- LOGGER.log("createServiceTypeClient for serviceType:" + serviceType
- + " network:" + network);
+ sharedLog.log("createServiceTypeClient for type:" + serviceType + ", net:" + network);
return new MdnsServiceTypeClient(
serviceType, socketClient,
executorProvider.newServiceTypeClientSchedulerExecutor(), network,
- LOGGER.forSubComponent(serviceType + "-" + network));
+ sharedLog.forSubComponent(serviceType + "-" + network));
}
}
\ No newline at end of file
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java b/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java
index 9eaa580..4e09515 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiser.java
@@ -170,29 +170,29 @@
}
}
- public MdnsInterfaceAdvertiser(@NonNull String logTag,
- @NonNull MdnsInterfaceSocket socket, @NonNull List<LinkAddress> initialAddresses,
- @NonNull Looper looper, @NonNull byte[] packetCreationBuffer, @NonNull Callback cb,
+ public MdnsInterfaceAdvertiser(@NonNull MdnsInterfaceSocket socket,
+ @NonNull List<LinkAddress> initialAddresses, @NonNull Looper looper,
+ @NonNull byte[] packetCreationBuffer, @NonNull Callback cb,
@NonNull String[] deviceHostName, @NonNull SharedLog sharedLog) {
- this(logTag, socket, initialAddresses, looper, packetCreationBuffer, cb,
+ this(socket, initialAddresses, looper, packetCreationBuffer, cb,
new Dependencies(), deviceHostName, sharedLog);
}
- public MdnsInterfaceAdvertiser(@NonNull String logTag,
- @NonNull MdnsInterfaceSocket socket, @NonNull List<LinkAddress> initialAddresses,
- @NonNull Looper looper, @NonNull byte[] packetCreationBuffer, @NonNull Callback cb,
- @NonNull Dependencies deps, @NonNull String[] deviceHostName,
- @NonNull SharedLog sharedLog) {
- mTag = MdnsInterfaceAdvertiser.class.getSimpleName() + "/" + logTag;
+ public MdnsInterfaceAdvertiser(@NonNull MdnsInterfaceSocket socket,
+ @NonNull List<LinkAddress> initialAddresses, @NonNull Looper looper,
+ @NonNull byte[] packetCreationBuffer, @NonNull Callback cb, @NonNull Dependencies deps,
+ @NonNull String[] deviceHostName, @NonNull SharedLog sharedLog) {
+ mTag = MdnsInterfaceAdvertiser.class.getSimpleName() + "/" + sharedLog.getTag();
mRecordRepository = deps.makeRecordRepository(looper, deviceHostName);
mRecordRepository.updateAddresses(initialAddresses);
mSocket = socket;
mCb = cb;
mCbHandler = new Handler(looper);
- mReplySender = deps.makeReplySender(logTag, looper, socket, packetCreationBuffer);
- mAnnouncer = deps.makeMdnsAnnouncer(logTag, looper, mReplySender,
+ mReplySender = deps.makeReplySender(sharedLog.getTag(), looper, socket,
+ packetCreationBuffer);
+ mAnnouncer = deps.makeMdnsAnnouncer(sharedLog.getTag(), looper, mReplySender,
mAnnouncingCallback);
- mProber = deps.makeMdnsProber(logTag, looper, mReplySender, mProbingCallback);
+ mProber = deps.makeMdnsProber(sharedLog.getTag(), looper, mReplySender, mProbingCallback);
mSharedLog = sharedLog;
}
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/MdnsServiceTypeClient.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
index 72b931d..6585d44 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceTypeClient.java
@@ -288,16 +288,16 @@
if (!responseMatchesOptions(response, listeners.valueAt(i))) continue;
final MdnsServiceBrowserListener listener = listeners.keyAt(i);
if (newServiceFound) {
- sharedLog.log("onServiceNameDiscovered: " + serviceInstanceName);
+ sharedLog.log("onServiceNameDiscovered: " + serviceInfo);
listener.onServiceNameDiscovered(serviceInfo);
}
if (response.isComplete()) {
if (newServiceFound || serviceBecomesComplete) {
- sharedLog.log("onServiceFound: " + serviceInstanceName);
+ sharedLog.log("onServiceFound: " + serviceInfo);
listener.onServiceFound(serviceInfo);
} else {
- sharedLog.log("onServiceUpdated: " + serviceInstanceName);
+ sharedLog.log("onServiceUpdated: " + serviceInfo);
listener.onServiceUpdated(serviceInfo);
}
}
@@ -315,10 +315,10 @@
final MdnsServiceInfo serviceInfo =
buildMdnsServiceInfoFromResponse(response, serviceTypeLabels);
if (response.isComplete()) {
- sharedLog.log("onServiceRemoved: " + serviceInstanceName);
+ sharedLog.log("onServiceRemoved: " + serviceInfo);
listener.onServiceRemoved(serviceInfo);
}
- sharedLog.log("onServiceNameRemoved: " + serviceInstanceName);
+ sharedLog.log("onServiceNameRemoved: " + serviceInfo);
listener.onServiceNameRemoved(serviceInfo);
}
}
@@ -535,19 +535,17 @@
continue;
}
final MdnsServiceBrowserListener listener = listeners.keyAt(i);
- String serviceInstanceName =
- existingResponse.getServiceInstanceName();
- if (serviceInstanceName != null) {
+ if (existingResponse.getServiceInstanceName() != null) {
final MdnsServiceInfo serviceInfo =
buildMdnsServiceInfoFromResponse(
existingResponse, serviceTypeLabels);
if (existingResponse.isComplete()) {
sharedLog.log("TTL expired. onServiceRemoved: "
- + serviceInstanceName);
+ + serviceInfo);
listener.onServiceRemoved(serviceInfo);
}
sharedLog.log("TTL expired. onServiceNameRemoved: "
- + serviceInstanceName);
+ + serviceInfo);
listener.onServiceNameRemoved(serviceInfo);
}
}
diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java
index d090a4d..ca61d34 100644
--- a/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java
+++ b/service-t/src/com/android/server/connectivity/mdns/MdnsSocketProvider.java
@@ -47,7 +47,6 @@
import com.android.net.module.util.SharedLog;
import java.io.IOException;
-import java.io.PrintWriter;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.util.ArrayList;
@@ -69,7 +68,6 @@
// But 1440 should generally be enough because of standard Ethernet.
// Note: mdnsresponder mDNSEmbeddedAPI.h uses 8940 for Ethernet jumbo frames.
private static final int READ_BUFFER_SIZE = 2048;
- private static final SharedLog LOGGER = new SharedLog(TAG);
private static final int IFACE_IDX_NOT_EXIST = -1;
@NonNull private final Context mContext;
@NonNull private final Looper mLooper;
@@ -78,6 +76,7 @@
@NonNull private final NetworkCallback mNetworkCallback;
@NonNull private final TetheringEventCallback mTetheringEventCallback;
@NonNull private final AbstractSocketNetlink mSocketNetlinkMonitor;
+ @NonNull private final SharedLog mSharedLog;
private final ArrayMap<Network, SocketInfo> mNetworkSockets = new ArrayMap<>();
private final ArrayMap<String, SocketInfo> mTetherInterfaceSockets = new ArrayMap<>();
private final ArrayMap<Network, LinkProperties> mActiveNetworksLinkProperties =
@@ -94,16 +93,18 @@
private boolean mMonitoringSockets = false;
private boolean mRequestStop = false;
- public MdnsSocketProvider(@NonNull Context context, @NonNull Looper looper) {
- this(context, looper, new Dependencies());
+ public MdnsSocketProvider(@NonNull Context context, @NonNull Looper looper,
+ @NonNull SharedLog sharedLog) {
+ this(context, looper, new Dependencies(), sharedLog);
}
MdnsSocketProvider(@NonNull Context context, @NonNull Looper looper,
- @NonNull Dependencies deps) {
+ @NonNull Dependencies deps, @NonNull SharedLog sharedLog) {
mContext = context;
mLooper = looper;
mHandler = new Handler(looper);
mDependencies = deps;
+ mSharedLog = sharedLog;
mNetworkCallback = new NetworkCallback() {
@Override
public void onLost(Network network) {
@@ -135,8 +136,8 @@
}
};
- mSocketNetlinkMonitor = mDependencies.createSocketNetlinkMonitor(mHandler, LOGGER,
- new NetLinkMessageProcessor());
+ mSocketNetlinkMonitor = mDependencies.createSocketNetlinkMonitor(mHandler,
+ mSharedLog.forSubComponent("NetlinkMonitor"), new NetLinkMessageProcessor());
}
/**
@@ -253,7 +254,7 @@
Log.d(TAG, "Already monitoring sockets.");
return;
}
- LOGGER.i("Start monitoring sockets.");
+ mSharedLog.i("Start monitoring sockets.");
mContext.getSystemService(ConnectivityManager.class).registerNetworkCallback(
new NetworkRequest.Builder().clearCapabilities().build(),
mNetworkCallback, mHandler);
@@ -282,7 +283,7 @@
// Only unregister the network callback if there is no socket request.
if (mCallbacksToRequestedNetworks.isEmpty()) {
- LOGGER.i("Stop monitoring sockets.");
+ mSharedLog.i("Stop monitoring sockets.");
mContext.getSystemService(ConnectivityManager.class)
.unregisterNetworkCallback(mNetworkCallback);
@@ -420,7 +421,7 @@
return;
}
- LOGGER.log("Create socket on net:" + networkKey + ", ifName:" + interfaceName);
+ mSharedLog.log("Create socket on net:" + networkKey + ", ifName:" + interfaceName);
final MdnsInterfaceSocket socket = mDependencies.createMdnsInterfaceSocket(
networkInterface.getNetworkInterface(), MdnsConstants.MDNS_PORT, mLooper,
mPacketReadBuffer);
@@ -441,7 +442,7 @@
notifySocketCreated(((NetworkAsKey) networkKey).mNetwork, socket, addresses);
}
} catch (IOException e) {
- LOGGER.e("Create socket failed ifName:" + interfaceName, e);
+ mSharedLog.e("Create socket failed ifName:" + interfaceName, e);
}
}
@@ -470,7 +471,7 @@
// transports above in priority.
return iface.supportsMulticast();
} catch (SocketException e) {
- LOGGER.e("Error checking interface flags", e);
+ mSharedLog.e("Error checking interface flags", e);
return false;
}
}
@@ -481,7 +482,7 @@
socketInfo.mSocket.destroy();
notifyInterfaceDestroyed(network, socketInfo.mSocket);
- LOGGER.log("Remove socket on net:" + network);
+ mSharedLog.log("Remove socket on net:" + network);
}
private void removeTetherInterfaceSocket(String interfaceName) {
@@ -489,7 +490,7 @@
if (socketInfo == null) return;
socketInfo.mSocket.destroy();
notifyInterfaceDestroyed(null /* network */, socketInfo.mSocket);
- LOGGER.log("Remove socket on ifName:" + interfaceName);
+ mSharedLog.log("Remove socket on ifName:" + interfaceName);
}
private void notifySocketCreated(Network network, MdnsInterfaceSocket socket,
@@ -561,6 +562,7 @@
*/
public void requestSocket(@Nullable Network network, @NonNull SocketCallback cb) {
ensureRunningOnHandlerThread(mHandler);
+ mSharedLog.log("requestSocket for net:" + network);
mCallbacksToRequestedNetworks.put(cb, network);
if (network == null) {
// Does not specify a required network, create sockets for all possible
@@ -584,6 +586,7 @@
/*** Unrequest the socket */
public void unrequestSocket(@NonNull SocketCallback cb) {
ensureRunningOnHandlerThread(mHandler);
+ mSharedLog.log("unrequestSocket");
mCallbacksToRequestedNetworks.remove(cb);
if (hasAllNetworksRequest()) {
// Still has a request for all networks (interfaces).
@@ -598,7 +601,7 @@
info.mSocket.destroy();
// Still notify to unrequester for socket destroy.
cb.onInterfaceDestroyed(network, info.mSocket);
- LOGGER.log("Remove socket on net:" + network + " after unrequestSocket");
+ mSharedLog.log("Remove socket on net:" + network + " after unrequestSocket");
}
// Remove all sockets for tethering interface because these sockets do not have associated
@@ -609,7 +612,7 @@
info.mSocket.destroy();
// Still notify to unrequester for socket destroy.
cb.onInterfaceDestroyed(null /* network */, info.mSocket);
- LOGGER.log("Remove socket on ifName:" + mTetherInterfaceSockets.keyAt(i)
+ mSharedLog.log("Remove socket on ifName:" + mTetherInterfaceSockets.keyAt(i)
+ " after unrequestSocket");
}
mTetherInterfaceSockets.clear();
@@ -618,10 +621,6 @@
maybeStopMonitoringSockets();
}
- /** Dump info to dumpsys */
- public void dump(PrintWriter pw) {
- LOGGER.reverseDump(pw);
- }
/*** Callbacks for listening socket changes */
public interface SocketCallback {
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-t/src/com/android/server/net/NetworkStatsService.java b/service-t/src/com/android/server/net/NetworkStatsService.java
index f977a27..e7ef510 100644
--- a/service-t/src/com/android/server/net/NetworkStatsService.java
+++ b/service-t/src/com/android/server/net/NetworkStatsService.java
@@ -46,6 +46,7 @@
import static android.net.NetworkStats.UID_ALL;
import static android.net.NetworkStatsHistory.FIELD_ALL;
import static android.net.NetworkTemplate.MATCH_MOBILE;
+import static android.net.NetworkTemplate.MATCH_TEST;
import static android.net.NetworkTemplate.MATCH_WIFI;
import static android.net.TrafficStats.KB_IN_BYTES;
import static android.net.TrafficStats.MB_IN_BYTES;
@@ -1582,7 +1583,9 @@
// For a template with wifi network keys, it is possible for a malicious
// client to track the user locations via querying data usage. Thus, enforce
// fine location permission check.
- if (!template.getWifiNetworkKeys().isEmpty()) {
+ // For a template with MATCH_TEST, since the wifi network key is just a placeholder
+ // to identify a specific test network, it is not related to track user location.
+ if (!template.getWifiNetworkKeys().isEmpty() && template.getMatchRule() != MATCH_TEST) {
final boolean canAccessFineLocation = mLocationPermissionChecker
.checkCallersLocationPermission(callingPackage,
null /* featureId */,
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..b5c9b0a 100755
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -17,6 +17,7 @@
package com.android.server;
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
+import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN;
import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.FEATURE_WIFI;
@@ -91,7 +92,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;
@@ -110,6 +111,8 @@
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
+import android.app.ActivityManager;
+import android.app.ActivityManager.UidFrozenStateChangedCallback;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
import android.app.PendingIntent;
@@ -787,6 +790,11 @@
private static final int EVENT_SET_LOW_TCP_POLLING_UNTIL = 60;
/**
+ * Event to inform the ConnectivityService handler when a uid has been frozen or unfrozen.
+ */
+ private static final int EVENT_UID_FROZEN_STATE_CHANGED = 61;
+
+ /**
* Argument for {@link #EVENT_PROVISIONING_NOTIFICATION} to indicate that the notification
* should be shown.
*/
@@ -1393,9 +1401,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 */);
}
/**
@@ -1691,6 +1699,32 @@
} else {
mCdmps = null;
}
+
+ if (SdkLevel.isAtLeastU()
+ && mDeps.isFeatureEnabled(context, KEY_DESTROY_FROZEN_SOCKETS_VERSION)) {
+ final UidFrozenStateChangedCallback frozenStateChangedCallback =
+ new UidFrozenStateChangedCallback() {
+ @Override
+ public void onUidFrozenStateChanged(int[] uids, int[] frozenStates) {
+ if (uids.length != frozenStates.length) {
+ Log.wtf(TAG, "uids has length " + uids.length
+ + " but frozenStates has length " + frozenStates.length);
+ return;
+ }
+
+ final UidFrozenStateChangedArgs args =
+ new UidFrozenStateChangedArgs(uids, frozenStates);
+
+ mHandler.sendMessage(
+ mHandler.obtainMessage(EVENT_UID_FROZEN_STATE_CHANGED, args));
+ }
+ };
+
+ final ActivityManager activityManager =
+ mContext.getSystemService(ActivityManager.class);
+ activityManager.registerUidFrozenStateChangedCallback(
+ (Runnable r) -> r.run(), frozenStateChangedCallback);
+ }
}
/**
@@ -2619,7 +2653,8 @@
final ArrayList<NetworkStateSnapshot> result = new ArrayList<>();
for (Network network : getAllNetworks()) {
final NetworkAgentInfo nai = getNetworkAgentInfoForNetwork(network);
- if (nai != null && nai.everConnected()) {
+ final boolean includeNetwork = (nai != null) && nai.isCreated();
+ if (includeNetwork) {
// TODO (b/73321673) : NetworkStateSnapshot contains a copy of the
// NetworkCapabilities, which may contain UIDs of apps to which the
// network applies. Should the UIDs be cleared so as not to leak or
@@ -2859,6 +2894,39 @@
setUidBlockedReasons(uid, blockedReasons);
}
+ static final class UidFrozenStateChangedArgs {
+ final int[] mUids;
+ final int[] mFrozenStates;
+
+ UidFrozenStateChangedArgs(int[] uids, int[] frozenStates) {
+ mUids = uids;
+ mFrozenStates = frozenStates;
+ }
+ }
+
+ private void handleFrozenUids(int[] uids, int[] frozenStates) {
+ final ArraySet<Range<Integer>> ranges = new ArraySet<>();
+
+ for (int i = 0; i < uids.length; i++) {
+ if (frozenStates[i] == UID_FROZEN_STATE_FROZEN) {
+ Integer uidAsInteger = Integer.valueOf(uids[i]);
+ ranges.add(new Range(uidAsInteger, uidAsInteger));
+ }
+ }
+
+ if (!ranges.isEmpty()) {
+ final Set<Integer> exemptUids = new ArraySet<>();
+ try {
+ mDeps.destroyLiveTcpSockets(ranges, exemptUids);
+ } catch (Exception e) {
+ loge("Exception in socket destroy: " + e);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ static final String KEY_DESTROY_FROZEN_SOCKETS_VERSION = "destroy_frozen_sockets_version";
+
private void enforceInternetPermission() {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.INTERNET,
@@ -3812,9 +3880,9 @@
break;
}
case NetworkAgent.EVENT_UNREGISTER_AFTER_REPLACEMENT: {
- if (!nai.isCreated()) {
- Log.d(TAG, "unregisterAfterReplacement on uncreated " + nai.toShortString()
- + ", tearing down instead");
+ if (!nai.everConnected()) {
+ Log.d(TAG, "unregisterAfterReplacement on never-connected "
+ + nai.toShortString() + ", tearing down instead");
teardownUnneededNetwork(nai);
break;
}
@@ -4399,6 +4467,25 @@
}
}
+ @VisibleForTesting
+ protected static boolean shouldCreateNetworksImmediately() {
+ // Before U, physical networks are only created when the agent advances to CONNECTED.
+ // In U and above, all networks are immediately created when the agent is registered.
+ return SdkLevel.isAtLeastU();
+ }
+
+ private static boolean shouldCreateNativeNetwork(@NonNull NetworkAgentInfo nai,
+ @NonNull NetworkInfo.State state) {
+ if (nai.isCreated()) return false;
+ if (state == NetworkInfo.State.CONNECTED) return true;
+ if (state != NetworkInfo.State.CONNECTING) {
+ // TODO: throw if no WTFs are observed in the field.
+ Log.wtf(TAG, "Uncreated network in invalid state: " + state);
+ return false;
+ }
+ return nai.isVPN() || shouldCreateNetworksImmediately();
+ }
+
private static boolean shouldDestroyNativeNetwork(@NonNull NetworkAgentInfo nai) {
return nai.isCreated() && !nai.isDestroyed();
}
@@ -5722,6 +5809,10 @@
mKeepaliveTracker.handleSetTestLowTcpPollingTimer(time);
break;
}
+ case EVENT_UID_FROZEN_STATE_CHANGED:
+ UidFrozenStateChangedArgs args = (UidFrozenStateChangedArgs) msg.obj;
+ handleFrozenUids(args.mUids, args.mFrozenStates);
+ break;
}
}
}
@@ -7837,7 +7928,7 @@
if (isDefaultNetwork(networkAgent)) {
handleApplyDefaultProxy(newLp.getHttpProxy());
- } else {
+ } else if (networkAgent.everConnected()) {
updateProxy(newLp, oldLp);
}
@@ -7871,6 +7962,10 @@
mKeepaliveTracker.handleCheckKeepalivesStillValid(networkAgent);
}
+ private void applyInitialLinkProperties(@NonNull NetworkAgentInfo nai) {
+ updateLinkProperties(nai, new LinkProperties(nai.linkProperties), null);
+ }
+
/**
* @param naData captive portal data from NetworkAgent
* @param apiData captive portal data from capport API
@@ -9633,21 +9728,32 @@
+ oldInfo.getState() + " to " + state);
}
- if (!networkAgent.isCreated()
- && (state == NetworkInfo.State.CONNECTED
- || (state == NetworkInfo.State.CONNECTING && networkAgent.isVPN()))) {
-
+ if (shouldCreateNativeNetwork(networkAgent, state)) {
// A network that has just connected has zero requests and is thus a foreground network.
networkAgent.networkCapabilities.addCapability(NET_CAPABILITY_FOREGROUND);
if (!createNativeNetwork(networkAgent)) return;
+
+ networkAgent.setCreated();
+
+ // If the network is created immediately on register, then apply the LinkProperties now.
+ // Otherwise, this is done further down when the network goes into connected state.
+ // Applying the LinkProperties means that the network is ready to carry traffic -
+ // interfaces and routing rules have been added, DNS servers programmed, etc.
+ // For VPNs, this must be done before the capabilities are updated, because as soon as
+ // that happens, UIDs are routed to the network.
+ if (shouldCreateNetworksImmediately()) {
+ applyInitialLinkProperties(networkAgent);
+ }
+
+ // TODO: should this move earlier? It doesn't seem to have anything to do with whether
+ // a network is created or not.
if (networkAgent.propagateUnderlyingCapabilities()) {
// Initialize the network's capabilities to their starting values according to the
// underlying networks. This ensures that the capabilities are correct before
// anything happens to the network.
updateCapabilitiesForNetwork(networkAgent);
}
- networkAgent.setCreated();
networkAgent.onNetworkCreated();
updateAllowedUids(networkAgent, null, networkAgent.networkCapabilities);
updateProfileAllowedNetworks();
@@ -9661,8 +9767,19 @@
networkAgent.getAndSetNetworkCapabilities(networkAgent.networkCapabilities);
handlePerNetworkPrivateDnsConfig(networkAgent, mDnsManager.getPrivateDnsConfig());
- updateLinkProperties(networkAgent, new LinkProperties(networkAgent.linkProperties),
- null);
+ if (!shouldCreateNetworksImmediately()) {
+ applyInitialLinkProperties(networkAgent);
+ } else {
+ // The network was created when the agent registered, and the LinkProperties are
+ // already up-to-date. However, updateLinkProperties also makes some changes only
+ // when the network connects. Apply those changes here. On T and below these are
+ // handled by the applyInitialLinkProperties call just above.
+ // TODO: stop relying on updateLinkProperties(..., null) to do this.
+ // If something depends on both LinkProperties and connected state, it should be in
+ // this method as well.
+ networkAgent.clatd.update();
+ updateProxy(networkAgent.linkProperties, null);
+ }
// If a rate limit has been configured and is applicable to this network (network
// provides internet connectivity), apply it. The tc police filter cannot be attached
diff --git a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
index ee8ab68..e2ef981 100644
--- a/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
+++ b/service/src/com/android/server/connectivity/AutomaticOnOffKeepaliveTracker.java
@@ -583,12 +583,8 @@
*/
public void dump(IndentingPrintWriter pw) {
mKeepaliveTracker.dump(pw);
- // Reading DeviceConfig will check if the calling uid and calling package name are the same.
- // Clear calling identity to align the calling uid and package so that it won't fail if cts
- // would like to do the dump()
- final boolean featureEnabled = BinderUtils.withCleanCallingIdentity(
- () -> mDependencies.isFeatureEnabled(AUTOMATIC_ON_OFF_KEEPALIVE_VERSION,
- true /* defaultEnabled */));
+ final boolean featureEnabled = mDependencies.isFeatureEnabled(
+ AUTOMATIC_ON_OFF_KEEPALIVE_VERSION, true /* defaultEnabled */);
pw.println("AutomaticOnOff enabled: " + featureEnabled);
pw.increaseIndent();
for (AutomaticOnOffKeepalive autoKi : mAutomaticOnOffKeepalives) {
@@ -841,8 +837,12 @@
* @return whether the feature is enabled
*/
public boolean isFeatureEnabled(@NonNull final String name, final boolean defaultEnabled) {
- return DeviceConfigUtils.isFeatureEnabled(mContext, NAMESPACE_TETHERING, name,
- defaultEnabled);
+ // Reading DeviceConfig will check if the calling uid and calling package name are the
+ // same. Clear calling identity to align the calling uid and package so that it won't
+ // fail if cts would like to do the dump()
+ return BinderUtils.withCleanCallingIdentity(() ->
+ DeviceConfigUtils.isFeatureEnabled(mContext, NAMESPACE_TETHERING, name,
+ 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/NetworkAgentTest.kt b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
index 869562b..af8938a 100644
--- a/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
+++ b/tests/cts/net/src/android/net/cts/NetworkAgentTest.kt
@@ -29,9 +29,9 @@
import android.net.NattKeepalivePacketData
import android.net.Network
import android.net.NetworkAgent
-import android.net.NetworkAgentConfig
import android.net.NetworkAgent.INVALID_NETWORK
import android.net.NetworkAgent.VALID_NETWORK
+import android.net.NetworkAgentConfig
import android.net.NetworkCapabilities
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED
@@ -46,21 +46,23 @@
import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
import android.net.NetworkCapabilities.TRANSPORT_TEST
-import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkCapabilities.TRANSPORT_VPN
+import android.net.NetworkCapabilities.TRANSPORT_WIFI
import android.net.NetworkInfo
import android.net.NetworkProvider
import android.net.NetworkReleasedException
import android.net.NetworkRequest
import android.net.NetworkScore
-import android.net.RouteInfo
import android.net.QosCallback
-import android.net.QosCallbackException
import android.net.QosCallback.QosCallbackRegistrationException
+import android.net.QosCallbackException
import android.net.QosSession
import android.net.QosSessionAttributes
import android.net.QosSocketInfo
+import android.net.RouteInfo
import android.net.SocketKeepalive
+import android.net.TestNetworkInterface
+import android.net.TestNetworkManager
import android.net.Uri
import android.net.VpnManager
import android.net.VpnTransportInfo
@@ -71,6 +73,7 @@
import android.os.Handler
import android.os.HandlerThread
import android.os.Message
+import android.os.Process
import android.os.SystemClock
import android.platform.test.annotations.AppModeFull
import android.system.OsConstants.IPPROTO_TCP
@@ -89,6 +92,7 @@
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.RecorderCallback.CallbackEntry.Available
import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus
+import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
import com.android.testutils.RecorderCallback.CallbackEntry.Losing
import com.android.testutils.RecorderCallback.CallbackEntry.Lost
@@ -178,6 +182,7 @@
private val agentsToCleanUp = mutableListOf<NetworkAgent>()
private val callbacksToCleanUp = mutableListOf<TestableNetworkCallback>()
private var qosTestSocket: Closeable? = null // either Socket or DatagramSocket
+ private val ifacesToCleanUp = mutableListOf<TestNetworkInterface>()
@Before
fun setUp() {
@@ -189,6 +194,7 @@
fun tearDown() {
agentsToCleanUp.forEach { it.unregister() }
callbacksToCleanUp.forEach { mCM.unregisterNetworkCallback(it) }
+ ifacesToCleanUp.forEach { it.fileDescriptor.close() }
qosTestSocket?.close()
mHandlerThread.quitSafely()
mHandlerThread.join()
@@ -269,7 +275,7 @@
removeCapability(NET_CAPABILITY_INTERNET)
addCapability(NET_CAPABILITY_NOT_SUSPENDED)
addCapability(NET_CAPABILITY_NOT_ROAMING)
- addCapability(NET_CAPABILITY_NOT_VPN)
+ if (!transports.contains(TRANSPORT_VPN)) addCapability(NET_CAPABILITY_NOT_VPN)
if (SdkLevel.isAtLeastS()) {
addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
}
@@ -304,7 +310,7 @@
context: Context = realContext,
specifier: String? = UUID.randomUUID().toString(),
initialConfig: NetworkAgentConfig? = null,
- expectedInitSignalStrengthThresholds: IntArray? = intArrayOf(),
+ expectedInitSignalStrengthThresholds: IntArray = intArrayOf(),
transports: IntArray = intArrayOf()
): Pair<TestableNetworkAgent, TestableNetworkCallback> {
val callback = TestableNetworkCallback()
@@ -317,8 +323,7 @@
agent.register()
agent.markConnected()
agent.expectCallback<OnNetworkCreated>()
- agent.expectSignalStrengths(expectedInitSignalStrengthThresholds)
- agent.expectValidationBypassedStatus()
+ agent.expectPostConnectionCallbacks(expectedInitSignalStrengthThresholds)
callback.expectAvailableThenValidatedCallbacks(agent.network!!)
return agent to callback
}
@@ -336,6 +341,19 @@
mFakeConnectivityService.connect(it.registerForTest(Network(FAKE_NET_ID)))
}
+ private fun TestableNetworkAgent.expectPostConnectionCallbacks(
+ thresholds: IntArray = intArrayOf()
+ ) {
+ expectSignalStrengths(thresholds)
+ expectValidationBypassedStatus()
+ assertNoCallback()
+ }
+
+ private fun createTunInterface(): TestNetworkInterface = realContext.getSystemService(
+ TestNetworkManager::class.java)!!.createTunInterface(emptyList()).also {
+ ifacesToCleanUp.add(it)
+ }
+
fun assertLinkPropertiesEventually(
n: Network,
description: String,
@@ -1291,8 +1309,12 @@
requestNetwork(makeTestNetworkRequest(specifier = specifier6), callback)
val agent6 = createNetworkAgent(specifier = specifier6)
val network6 = agent6.register()
- // No callbacks are sent, so check the LinkProperties to see if the network has connected.
- assertLinkPropertiesEventuallyNotNull(agent6.network!!)
+ if (SdkLevel.isAtLeastU()) {
+ agent6.expectCallback<OnNetworkCreated>()
+ } else {
+ // No callbacks are sent, so check LinkProperties to wait for the network to be created.
+ assertLinkPropertiesEventuallyNotNull(agent6.network!!)
+ }
// unregisterAfterReplacement tears down the network immediately.
// Approximately check that this is the case by picking an unregister timeout that's longer
@@ -1301,8 +1323,9 @@
val timeoutMs = agent6.DEFAULT_TIMEOUT_MS.toInt() + 1_000
agent6.unregisterAfterReplacement(timeoutMs)
agent6.expectCallback<OnNetworkUnwanted>()
- if (!SdkLevel.isAtLeastT()) {
+ if (!SdkLevel.isAtLeastT() || SdkLevel.isAtLeastU()) {
// Before T, onNetworkDestroyed is called even if the network was never created.
+ // On U+, the network was created by register(). Destroying it sends onNetworkDestroyed.
agent6.expectCallback<OnNetworkDestroyed>()
}
// Poll for LinkProperties becoming null, because when onNetworkUnwanted is called, the
@@ -1375,4 +1398,101 @@
callback.expect<Available>(agent.network!!)
callback.eventuallyExpect<Lost> { it.network == agent.network }
}
+
+ fun doTestNativeNetworkCreation(expectCreatedImmediately: Boolean, transports: IntArray) {
+ val iface = createTunInterface()
+ val ifName = iface.interfaceName
+ val nc = makeTestNetworkCapabilities(ifName, transports).also {
+ if (transports.contains(TRANSPORT_VPN)) {
+ val sessionId = "NetworkAgentTest-${Process.myPid()}"
+ it.transportInfo = VpnTransportInfo(VpnManager.TYPE_VPN_PLATFORM, sessionId,
+ /*bypassable=*/ false, /*longLivedTcpConnectionsExpensive=*/ false)
+ it.underlyingNetworks = listOf()
+ }
+ }
+ val lp = LinkProperties().apply {
+ interfaceName = ifName
+ addLinkAddress(LinkAddress("2001:db8::1/64"))
+ addRoute(RouteInfo(IpPrefix("2001:db8::/64"), null /* nextHop */, ifName))
+ addRoute(RouteInfo(IpPrefix("::/0"),
+ InetAddresses.parseNumericAddress("fe80::abcd"),
+ ifName))
+ }
+
+ // File a request containing the agent's specifier to receive callbacks and to ensure that
+ // the agent is not torn down due to being unneeded.
+ val request = makeTestNetworkRequest(specifier = ifName)
+ val requestCallback = TestableNetworkCallback()
+ requestNetwork(request, requestCallback)
+
+ val listenCallback = TestableNetworkCallback()
+ registerNetworkCallback(request, listenCallback)
+
+ // Register the NetworkAgent...
+ val agent = createNetworkAgent(realContext, initialNc = nc, initialLp = lp)
+ val network = agent.register()
+
+ // ... and then change the NetworkCapabilities and LinkProperties.
+ nc.addCapability(NET_CAPABILITY_TEMPORARILY_NOT_METERED)
+ agent.sendNetworkCapabilities(nc)
+ lp.addLinkAddress(LinkAddress("192.0.2.2/25"))
+ lp.addRoute(RouteInfo(IpPrefix("192.0.2.0/25"), null /* nextHop */, ifName))
+ agent.sendLinkProperties(lp)
+
+ requestCallback.assertNoCallback()
+ listenCallback.assertNoCallback()
+ if (!expectCreatedImmediately) {
+ agent.assertNoCallback()
+ agent.markConnected()
+ agent.expectCallback<OnNetworkCreated>()
+ } else {
+ agent.expectCallback<OnNetworkCreated>()
+ agent.markConnected()
+ }
+ agent.expectPostConnectionCallbacks()
+
+ // onAvailable must be called only when the network connects, and no other callbacks may be
+ // called before that happens. The callbacks report the state of the network as it was when
+ // it connected, so they reflect the NC and LP changes made after registration.
+ requestCallback.expect<Available>(network)
+ listenCallback.expect<Available>(network)
+
+ requestCallback.expect<CapabilitiesChanged>(network) { it.caps.hasCapability(
+ NET_CAPABILITY_TEMPORARILY_NOT_METERED) }
+ listenCallback.expect<CapabilitiesChanged>(network) { it.caps.hasCapability(
+ NET_CAPABILITY_TEMPORARILY_NOT_METERED) }
+
+ requestCallback.expect<LinkPropertiesChanged>(network) { it.lp.equals(lp) }
+ listenCallback.expect<LinkPropertiesChanged>(network) { it.lp.equals(lp) }
+
+ requestCallback.expect<BlockedStatus>()
+ listenCallback.expect<BlockedStatus>()
+
+ // Except for network validation, ensure no more callbacks are sent.
+ requestCallback.expectCaps(network) {
+ it.hasCapability(NET_CAPABILITY_VALIDATED)
+ }
+ listenCallback.expectCaps(network) {
+ it.hasCapability(NET_CAPABILITY_VALIDATED)
+ }
+ unregister(agent)
+ // Lost implicitly checks that no further callbacks happened after connect.
+ requestCallback.expect<Lost>(network)
+ listenCallback.expect<Lost>(network)
+ assertNull(mCM.getLinkProperties(network))
+ }
+
+ @Test
+ fun testNativeNetworkCreation_PhysicalNetwork() {
+ // On T and below, the native network is only created when the agent connects.
+ // Starting in U, the native network is created as soon as the agent is registered.
+ doTestNativeNetworkCreation(expectCreatedImmediately = SdkLevel.isAtLeastU(),
+ intArrayOf(TRANSPORT_CELLULAR))
+ }
+
+ @Test
+ fun testNativeNetworkCreation_Vpn() {
+ // VPN networks are always created as soon as the agent is registered.
+ doTestNativeNetworkCreation(expectCreatedImmediately = true, intArrayOf(TRANSPORT_VPN))
+ }
}
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..9d7b21f 100755
--- a/tests/unit/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/unit/java/com/android/server/ConnectivityServiceTest.java
@@ -30,6 +30,8 @@
import static android.Manifest.permission.NETWORK_SETUP_WIZARD;
import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.PACKET_KEEPALIVE_OFFLOAD;
+import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN;
+import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_UNFROZEN;
import static android.app.PendingIntent.FLAG_IMMUTABLE;
import static android.content.Intent.ACTION_PACKAGE_ADDED;
import static android.content.Intent.ACTION_PACKAGE_REMOVED;
@@ -148,6 +150,7 @@
import static android.os.Process.INVALID_UID;
import static android.system.OsConstants.IPPROTO_TCP;
+import static com.android.server.ConnectivityService.KEY_DESTROY_FROZEN_SOCKETS_VERSION;
import static com.android.server.ConnectivityService.MAX_NETWORK_REQUESTS_PER_SYSTEM_UID;
import static com.android.server.ConnectivityService.PREFERENCE_ORDER_MOBILE_DATA_PREFERERRED;
import static com.android.server.ConnectivityService.PREFERENCE_ORDER_OEM;
@@ -224,6 +227,8 @@
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityManager.UidFrozenStateChangedCallback;
import android.app.AlarmManager;
import android.app.AppOpsManager;
import android.app.BroadcastOptions;
@@ -609,6 +614,7 @@
@Mock CarrierPrivilegeAuthenticator mCarrierPrivilegeAuthenticator;
@Mock TetheringManager mTetheringManager;
@Mock BroadcastOptionsShim mBroadcastOptionsShim;
+ @Mock ActivityManager mActivityManager;
// BatteryStatsManager is final and cannot be mocked with regular mockito, so just mock the
// underlying binder calls.
@@ -732,6 +738,7 @@
if (Context.BATTERY_STATS_SERVICE.equals(name)) return mBatteryStatsManager;
if (Context.PAC_PROXY_SERVICE.equals(name)) return mPacProxyManager;
if (Context.TETHERING_SERVICE.equals(name)) return mTetheringManager;
+ if (Context.ACTIVITY_SERVICE.equals(name)) return mActivityManager;
return super.getSystemService(name);
}
@@ -2077,12 +2084,14 @@
}
@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;
+ case KEY_DESTROY_FROZEN_SOCKETS_VERSION:
+ return true;
default:
- return super.isFeatureEnabled(context, name, defaultEnabled);
+ return super.isFeatureEnabled(context, name);
}
}
@@ -3801,6 +3810,12 @@
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, callbacks);
+ if (mService.shouldCreateNetworksImmediately()) {
+ assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } else {
+ assertNull(eventOrder.poll());
+ }
+
// Connect a network, and file a request for it after it has come up, to ensure the nascent
// timer is cleared and the test does not have to wait for it. Filing the request after the
// network has come up is necessary because ConnectivityService does not appear to clear the
@@ -3808,7 +3823,12 @@
// connected.
// TODO: fix this bug, file the request before connecting, and remove the waitForIdle.
mWiFiAgent.connectWithoutInternet();
- waitForIdle();
+ if (!mService.shouldCreateNetworksImmediately()) {
+ assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+ } else {
+ waitForIdle();
+ assertNull(eventOrder.poll());
+ }
mCm.requestNetwork(request, callback);
callback.expectAvailableCallbacksUnvalidated(mWiFiAgent);
@@ -3825,7 +3845,6 @@
// Disconnect the network and check that events happened in the right order.
mCm.unregisterNetworkCallback(callback);
- assertEquals("onNetworkCreated", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertEquals("onNetworkUnwanted", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertEquals("timePasses", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
assertEquals("onNetworkDisconnected", eventOrder.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
@@ -7611,7 +7630,9 @@
// Simple connection with initial LP should have updated ifaces.
mCellAgent.connect(false);
waitForIdle();
- expectNotifyNetworkStatus(onlyCell(), onlyCell(), MOBILE_IFNAME);
+ List<Network> allNetworks = mService.shouldCreateNetworksImmediately()
+ ? cellAndWifi() : onlyCell();
+ expectNotifyNetworkStatus(allNetworks, onlyCell(), MOBILE_IFNAME);
reset(mStatsManager);
// Verify change fields other than interfaces does not trigger a notification to NSS.
@@ -7920,9 +7941,13 @@
setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ final int netId = mCellAgent.getNetwork().netId;
waitForIdle();
- verify(mMockDnsResolver, never()).setResolverConfiguration(any());
- verifyNoMoreInteractions(mMockDnsResolver);
+ if (mService.shouldCreateNetworksImmediately()) {
+ verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
+ } else {
+ verify(mMockDnsResolver, never()).setResolverConfiguration(any());
+ }
final LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
@@ -7938,10 +7963,13 @@
mCellAgent.sendLinkProperties(cellLp);
mCellAgent.connect(false);
waitForIdle();
-
- verify(mMockDnsResolver, times(1)).createNetworkCache(eq(mCellAgent.getNetwork().netId));
- // CS tells dnsresolver about the empty DNS config for this network.
+ if (!mService.shouldCreateNetworksImmediately()) {
+ // CS tells dnsresolver about the empty DNS config for this network.
+ verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
+ }
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(any());
+
+ verifyNoMoreInteractions(mMockDnsResolver);
reset(mMockDnsResolver);
cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
@@ -8056,10 +8084,13 @@
mCm.requestNetwork(cellRequest, cellNetworkCallback);
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
+ final int netId = mCellAgent.getNetwork().netId;
waitForIdle();
- // CS tells netd about the empty DNS config for this network.
- verify(mMockDnsResolver, never()).setResolverConfiguration(any());
- verifyNoMoreInteractions(mMockDnsResolver);
+ if (mService.shouldCreateNetworksImmediately()) {
+ verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
+ } else {
+ verify(mMockDnsResolver, never()).setResolverConfiguration(any());
+ }
final LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
@@ -8078,7 +8109,9 @@
mCellAgent.sendLinkProperties(cellLp);
mCellAgent.connect(false);
waitForIdle();
- verify(mMockDnsResolver, times(1)).createNetworkCache(eq(mCellAgent.getNetwork().netId));
+ if (!mService.shouldCreateNetworksImmediately()) {
+ verify(mMockDnsResolver, times(1)).createNetworkCache(netId);
+ }
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
mResolverParamsParcelCaptor.capture());
ResolverParamsParcel resolvrParams = mResolverParamsParcelCaptor.getValue();
@@ -8089,6 +8122,7 @@
assertEquals(2, resolvrParams.tlsServers.length);
assertTrue(new ArraySet<>(resolvrParams.tlsServers).containsAll(
asList("2001:db8::1", "192.0.2.1")));
+ verifyNoMoreInteractions(mMockDnsResolver);
reset(mMockDnsResolver);
cellNetworkCallback.expect(AVAILABLE, mCellAgent);
cellNetworkCallback.expect(NETWORK_CAPS_UPDATED, mCellAgent);
@@ -10416,7 +10450,8 @@
if (inOrder != null) {
return inOrder.verify(t);
} else {
- return verify(t);
+ // times(1) for consistency with the above. InOrder#verify always implies times(1).
+ return verify(t, times(1));
}
}
@@ -10465,6 +10500,21 @@
}
}
+ private void expectNativeNetworkCreated(int netId, int permission, String iface,
+ InOrder inOrder) throws Exception {
+ verifyWithOrder(inOrder, mMockNetd).networkCreate(nativeNetworkConfigPhysical(netId,
+ permission));
+ verifyWithOrder(inOrder, mMockDnsResolver).createNetworkCache(eq(netId));
+ if (iface != null) {
+ verifyWithOrder(inOrder, mMockNetd).networkAddInterface(netId, iface);
+ }
+ }
+
+ private void expectNativeNetworkCreated(int netId, int permission, String iface)
+ throws Exception {
+ expectNativeNetworkCreated(netId, permission, iface, null /* inOrder */);
+ }
+
@Test
public void testStackedLinkProperties() throws Exception {
final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
@@ -10502,11 +10552,8 @@
int cellNetId = mCellAgent.getNetwork().netId;
waitForIdle();
- verify(mMockNetd, times(1)).networkCreate(nativeNetworkConfigPhysical(cellNetId,
- INetd.PERMISSION_NONE));
+ expectNativeNetworkCreated(cellNetId, INetd.PERMISSION_NONE, MOBILE_IFNAME);
assertRoutesAdded(cellNetId, ipv6Subnet, ipv6Default);
- verify(mMockDnsResolver, times(1)).createNetworkCache(eq(cellNetId));
- verify(mMockNetd, times(1)).networkAddInterface(cellNetId, MOBILE_IFNAME);
final ArrayTrackRecord<ReportedInterfaces>.ReadHead readHead =
mDeps.mReportedInterfaceHistory.newReadHead();
assertNotNull(readHead.poll(TIMEOUT_MS, ri -> ri.contentEquals(mServiceContext,
@@ -15053,7 +15100,7 @@
UserHandle testHandle,
TestNetworkCallback profileDefaultNetworkCallback,
TestNetworkCallback disAllowProfileDefaultNetworkCallback) throws Exception {
- final InOrder inOrder = inOrder(mMockNetd);
+ final InOrder inOrder = inOrder(mMockNetd, mMockDnsResolver);
mCellAgent = new TestNetworkAgentWrapper(TRANSPORT_CELLULAR);
mCellAgent.connect(true);
@@ -15069,8 +15116,16 @@
final TestNetworkAgentWrapper workAgent =
makeEnterpriseNetworkAgent(profileNetworkPreference.getPreferenceEnterpriseId());
+ if (mService.shouldCreateNetworksImmediately()) {
+ expectNativeNetworkCreated(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM,
+ null /* iface */, inOrder);
+ }
if (connectWorkProfileAgentAhead) {
workAgent.connect(false);
+ if (!mService.shouldCreateNetworksImmediately()) {
+ expectNativeNetworkCreated(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM,
+ null /* iface */, inOrder);
+ }
}
final TestOnCompleteListener listener = new TestOnCompleteListener();
@@ -15110,6 +15165,11 @@
if (!connectWorkProfileAgentAhead) {
workAgent.connect(false);
+ if (!mService.shouldCreateNetworksImmediately()) {
+ inOrder.verify(mMockNetd).networkCreate(
+ nativeNetworkConfigPhysical(workAgent.getNetwork().netId,
+ INetd.PERMISSION_SYSTEM));
+ }
}
profileDefaultNetworkCallback.expectAvailableCallbacksUnvalidated(workAgent);
@@ -15118,8 +15178,6 @@
}
mSystemDefaultNetworkCallback.assertNoCallback();
mDefaultNetworkCallback.assertNoCallback();
- inOrder.verify(mMockNetd).networkCreate(
- nativeNetworkConfigPhysical(workAgent.getNetwork().netId, INetd.PERMISSION_SYSTEM));
inOrder.verify(mMockNetd).networkAddUidRangesParcel(new NativeUidRangeConfig(
workAgent.getNetwork().netId,
uidRangeFor(testHandle, profileNetworkPreference),
@@ -17638,6 +17696,22 @@
verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
}
+ private void verifyMtuSetOnWifiInterfaceOnlyUpToT(int mtu) throws Exception {
+ if (!mService.shouldCreateNetworksImmediately()) {
+ verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
+ } else {
+ verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
+ }
+ }
+
+ private void verifyMtuSetOnWifiInterfaceOnlyStartingFromU(int mtu) throws Exception {
+ if (mService.shouldCreateNetworksImmediately()) {
+ verify(mMockNetd, times(1)).interfaceSetMtu(WIFI_IFNAME, mtu);
+ } else {
+ verify(mMockNetd, never()).interfaceSetMtu(eq(WIFI_IFNAME), anyInt());
+ }
+ }
+
@Test
public void testSendLinkPropertiesSetInterfaceMtuBeforeConnect() throws Exception {
final int mtu = 1281;
@@ -17652,8 +17726,8 @@
reset(mMockNetd);
mWiFiAgent.connect(false /* validated */);
- // The MTU is always (re-)applied when the network connects.
- verifyMtuSetOnWifiInterface(mtu);
+ // Before U, the MTU is always (re-)applied when the network connects.
+ verifyMtuSetOnWifiInterfaceOnlyUpToT(mtu);
}
@Test
@@ -17663,13 +17737,13 @@
lp.setInterfaceName(WIFI_IFNAME);
lp.setMtu(mtu);
- // Registering an agent with an MTU doesn't set the MTU...
+ // Registering an agent with an MTU only sets the MTU on U+.
mWiFiAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI, lp);
waitForIdle();
- verifyMtuNeverSetOnWifiInterface();
+ verifyMtuSetOnWifiInterfaceOnlyStartingFromU(mtu);
reset(mMockNetd);
- // ... but prevents future updates with the same MTU from setting the MTU.
+ // Future updates with the same MTU don't set the MTU even on T when it's not set initially.
mWiFiAgent.sendLinkProperties(lp);
waitForIdle();
verifyMtuNeverSetOnWifiInterface();
@@ -17682,8 +17756,8 @@
reset(mMockNetd);
mWiFiAgent.connect(false /* validated */);
- // The MTU is always (re-)applied when the network connects.
- verifyMtuSetOnWifiInterface(mtu + 1);
+ // Before U, the MTU is always (re-)applied when the network connects.
+ verifyMtuSetOnWifiInterfaceOnlyUpToT(mtu + 1);
}
@Test
@@ -17833,4 +17907,35 @@
verify(mMockNetd, never()).wakeupAddInterface(eq(ethernetIface), anyString(), anyInt(),
anyInt());
}
+
+ private static final int TEST_FROZEN_UID = 1000;
+ private static final int TEST_UNFROZEN_UID = 2000;
+
+ /**
+ * Send a UidFrozenStateChanged message to ConnectivityService. Verify that only the frozen UID
+ * gets passed to socketDestroy().
+ */
+ @Test
+ @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
+ public void testFrozenUidSocketDestroy() throws Exception {
+ ArgumentCaptor<UidFrozenStateChangedCallback> callbackArg =
+ ArgumentCaptor.forClass(UidFrozenStateChangedCallback.class);
+
+ verify(mActivityManager).registerUidFrozenStateChangedCallback(any(),
+ callbackArg.capture());
+
+ final int[] uids = {TEST_FROZEN_UID, TEST_UNFROZEN_UID};
+ final int[] frozenStates = {UID_FROZEN_STATE_FROZEN, UID_FROZEN_STATE_UNFROZEN};
+
+ callbackArg.getValue().onUidFrozenStateChanged(uids, frozenStates);
+
+ waitForIdle();
+
+ final Set<Integer> exemptUids = new ArraySet();
+ final UidRange frozenUidRange = new UidRange(TEST_FROZEN_UID, TEST_FROZEN_UID);
+ final Set<UidRange> ranges = Collections.singleton(frozenUidRange);
+
+ verify(mDeps).destroyLiveTcpSockets(eq(UidRange.toIntRanges(ranges)),
+ eq(exemptUids));
+ }
}
diff --git a/tests/unit/java/com/android/server/NsdServiceTest.java b/tests/unit/java/com/android/server/NsdServiceTest.java
index 2ed989e..14b4280 100644
--- a/tests/unit/java/com/android/server/NsdServiceTest.java
+++ b/tests/unit/java/com/android/server/NsdServiceTest.java
@@ -175,9 +175,9 @@
doReturn(true).when(mMockMDnsM).resolve(
anyInt(), anyString(), anyString(), anyString(), anyInt());
doReturn(false).when(mDeps).isMdnsDiscoveryManagerEnabled(any(Context.class));
- doReturn(mDiscoveryManager).when(mDeps).makeMdnsDiscoveryManager(any(), any());
- doReturn(mSocketProvider).when(mDeps).makeMdnsSocketProvider(any(), any());
- doReturn(mAdvertiser).when(mDeps).makeMdnsAdvertiser(any(), any(), any());
+ doReturn(mDiscoveryManager).when(mDeps).makeMdnsDiscoveryManager(any(), any(), any());
+ doReturn(mSocketProvider).when(mDeps).makeMdnsSocketProvider(any(), any(), any());
+ doReturn(mAdvertiser).when(mDeps).makeMdnsAdvertiser(any(), any(), any(), any());
mService = makeService();
}
@@ -1122,7 +1122,7 @@
// final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
final ArgumentCaptor<MdnsAdvertiser.AdvertiserCallback> cbCaptor =
ArgumentCaptor.forClass(MdnsAdvertiser.AdvertiserCallback.class);
- verify(mDeps).makeMdnsAdvertiser(any(), any(), cbCaptor.capture());
+ verify(mDeps).makeMdnsAdvertiser(any(), any(), cbCaptor.capture(), any());
final NsdServiceInfo regInfo = new NsdServiceInfo(SERVICE_NAME, SERVICE_TYPE);
regInfo.setHost(parseNumericAddress("192.0.2.123"));
@@ -1161,7 +1161,7 @@
// final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
final ArgumentCaptor<MdnsAdvertiser.AdvertiserCallback> cbCaptor =
ArgumentCaptor.forClass(MdnsAdvertiser.AdvertiserCallback.class);
- verify(mDeps).makeMdnsAdvertiser(any(), any(), cbCaptor.capture());
+ verify(mDeps).makeMdnsAdvertiser(any(), any(), cbCaptor.capture(), any());
final NsdServiceInfo regInfo = new NsdServiceInfo(SERVICE_NAME, "invalid_type");
regInfo.setHost(parseNumericAddress("192.0.2.123"));
@@ -1186,7 +1186,7 @@
// final String serviceTypeWithLocalDomain = SERVICE_TYPE + ".local";
final ArgumentCaptor<MdnsAdvertiser.AdvertiserCallback> cbCaptor =
ArgumentCaptor.forClass(MdnsAdvertiser.AdvertiserCallback.class);
- verify(mDeps).makeMdnsAdvertiser(any(), any(), cbCaptor.capture());
+ verify(mDeps).makeMdnsAdvertiser(any(), any(), cbCaptor.capture(), any());
final NsdServiceInfo regInfo = new NsdServiceInfo("a".repeat(70), SERVICE_TYPE);
regInfo.setHost(parseNumericAddress("192.0.2.123"));
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..3bb08a6 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt
@@ -23,11 +23,13 @@
import android.os.Build
import android.os.Handler
import android.os.HandlerThread
+import com.android.net.module.util.SharedLog
import com.android.server.connectivity.mdns.MdnsAdvertiser.AdvertiserCallback
import com.android.server.connectivity.mdns.MdnsSocketProvider.SocketCallback
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
import com.android.testutils.waitForIdle
+import java.net.NetworkInterface
import java.util.Objects
import org.junit.After
import org.junit.Before
@@ -47,6 +49,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 +60,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 {
@@ -73,6 +91,7 @@
private val handler by lazy { Handler(thread.looper) }
private val socketProvider = mock(MdnsSocketProvider::class.java)
private val cb = mock(AdvertiserCallback::class.java)
+ private val sharedlog = mock(SharedLog::class.java)
private val mockSocket1 = mock(MdnsInterfaceSocket::class.java)
private val mockSocket2 = mock(MdnsInterfaceSocket::class.java)
@@ -85,13 +104,15 @@
thread.start()
doReturn(TEST_HOSTNAME).`when`(mockDeps).generateHostname()
doReturn(mockInterfaceAdvertiser1).`when`(mockDeps).makeAdvertiser(eq(mockSocket1),
- any(), any(), any(), any(), eq(TEST_HOSTNAME)
+ any(), any(), any(), any(), eq(TEST_HOSTNAME), any()
)
doReturn(mockInterfaceAdvertiser2).`when`(mockDeps).makeAdvertiser(eq(mockSocket2),
- any(), any(), any(), any(), eq(TEST_HOSTNAME)
+ any(), any(), any(), any(), eq(TEST_HOSTNAME), any()
)
doReturn(true).`when`(mockInterfaceAdvertiser1).isProbing(anyInt())
doReturn(true).`when`(mockInterfaceAdvertiser2).isProbing(anyInt())
+ doReturn(createEmptyNetworkInterface()).`when`(mockSocket1).getInterface()
+ doReturn(createEmptyNetworkInterface()).`when`(mockSocket2).getInterface()
}
@After
@@ -100,9 +121,15 @@
thread.join()
}
+ private fun createEmptyNetworkInterface(): NetworkInterface {
+ val constructor = NetworkInterface::class.java.getDeclaredConstructor()
+ constructor.isAccessible = true
+ return constructor.newInstance()
+ }
+
@Test
fun testAddService_OneNetwork() {
- val advertiser = MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps)
+ val advertiser = MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps, sharedlog)
postSync { advertiser.addService(SERVICE_ID_1, SERVICE_1) }
val socketCbCaptor = ArgumentCaptor.forClass(SocketCallback::class.java)
@@ -118,7 +145,8 @@
eq(thread.looper),
any(),
intAdvCbCaptor.capture(),
- eq(TEST_HOSTNAME)
+ eq(TEST_HOSTNAME),
+ any()
)
doReturn(false).`when`(mockInterfaceAdvertiser1).isProbing(SERVICE_ID_1)
@@ -132,7 +160,7 @@
@Test
fun testAddService_AllNetworks() {
- val advertiser = MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps)
+ val advertiser = MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps, sharedlog)
postSync { advertiser.addService(SERVICE_ID_1, ALL_NETWORKS_SERVICE) }
val socketCbCaptor = ArgumentCaptor.forClass(SocketCallback::class.java)
@@ -146,10 +174,10 @@
val intAdvCbCaptor1 = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
val intAdvCbCaptor2 = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java)
verify(mockDeps).makeAdvertiser(eq(mockSocket1), eq(listOf(TEST_LINKADDR)),
- eq(thread.looper), any(), intAdvCbCaptor1.capture(), eq(TEST_HOSTNAME)
+ eq(thread.looper), any(), intAdvCbCaptor1.capture(), eq(TEST_HOSTNAME), any()
)
verify(mockDeps).makeAdvertiser(eq(mockSocket2), eq(listOf(TEST_LINKADDR)),
- eq(thread.looper), any(), intAdvCbCaptor2.capture(), eq(TEST_HOSTNAME)
+ eq(thread.looper), any(), intAdvCbCaptor2.capture(), eq(TEST_HOSTNAME), any()
)
doReturn(false).`when`(mockInterfaceAdvertiser1).isProbing(SERVICE_ID_1)
@@ -178,7 +206,7 @@
@Test
fun testAddService_Conflicts() {
- val advertiser = MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps)
+ val advertiser = MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps, sharedlog)
postSync { advertiser.addService(SERVICE_ID_1, SERVICE_1) }
val oneNetSocketCbCaptor = ArgumentCaptor.forClass(SocketCallback::class.java)
@@ -191,6 +219,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,18 +231,30 @@
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)
+ eq(thread.looper), any(), intAdvCbCaptor.capture(), eq(TEST_HOSTNAME), any()
)
verify(mockInterfaceAdvertiser1).addService(eq(SERVICE_ID_1),
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(
@@ -233,7 +276,7 @@
@Test
fun testRemoveService_whenAllServiceRemoved_thenUpdateHostName() {
- val advertiser = MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps)
+ val advertiser = MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps, sharedlog)
verify(mockDeps, times(1)).generateHostname()
postSync { advertiser.addService(SERVICE_ID_1, SERVICE_1) }
postSync { advertiser.removeService(SERVICE_ID_1) }
@@ -251,7 +294,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..0a23ba5 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;
@@ -29,6 +29,7 @@
import android.text.TextUtils;
import android.util.Pair;
+import com.android.net.module.util.SharedLog;
import com.android.server.connectivity.mdns.MdnsSocketClientBase.SocketCreationCallback;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
@@ -38,6 +39,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,30 +55,34 @@
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;
+ @Mock SharedLog sharedLog;
private MdnsDiscoveryManager discoveryManager;
@Before
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) {
+ discoveryManager = new MdnsDiscoveryManager(executorProvider, socketClient, sharedLog) {
@Override
MdnsServiceTypeClient createServiceTypeClient(@NonNull String serviceType,
@Nullable Network network) {
@@ -84,31 +90,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 +130,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/MdnsInterfaceAdvertiserTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiserTest.kt
index 9c0abfc..ee190af 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiserTest.kt
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsInterfaceAdvertiserTest.kt
@@ -76,7 +76,7 @@
private val replySender = mock(MdnsReplySender::class.java)
private val announcer = mock(MdnsAnnouncer::class.java)
private val prober = mock(MdnsProber::class.java)
- private val sharedlog = mock(SharedLog::class.java)
+ private val sharedlog = SharedLog("MdnsInterfaceAdvertiserTest")
@Suppress("UNCHECKED_CAST")
private val probeCbCaptor = ArgumentCaptor.forClass(PacketRepeaterCallback::class.java)
as ArgumentCaptor<PacketRepeaterCallback<ProbingInfo>>
@@ -92,7 +92,6 @@
private val advertiser by lazy {
MdnsInterfaceAdvertiser(
- LOG_TAG,
socket,
TEST_ADDRS,
thread.looper,
@@ -116,6 +115,7 @@
val knownServices = mutableSetOf<Int>()
doAnswer { inv ->
knownServices.add(inv.getArgument(0))
+
-1
}.`when`(repository).addService(anyInt(), any())
doAnswer { inv ->
diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
index 6f3322b..744ec84 100644
--- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
+++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsSocketProviderTest.java
@@ -111,6 +111,7 @@
private MdnsSocketProvider mSocketProvider;
private NetworkCallback mNetworkCallback;
private TetheringEventCallback mTetheringEventCallback;
+ private SharedLog mLog = new SharedLog("MdnsSocketProviderTest");
private TestNetlinkMonitor mTestSocketNetLinkMonitor;
@Before
@@ -153,7 +154,7 @@
return mTestSocketNetLinkMonitor;
}).when(mDeps).createSocketNetlinkMonitor(any(), any(),
any());
- mSocketProvider = new MdnsSocketProvider(mContext, thread.getLooper(), mDeps);
+ mSocketProvider = new MdnsSocketProvider(mContext, thread.getLooper(), mDeps, mLog);
}
private void startMonitoringSockets() {
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")
+ }
}
diff --git a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
index 99f6d63..b8b0289 100644
--- a/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
+++ b/tests/unit/java/com/android/server/net/NetworkStatsServiceTest.java
@@ -1926,12 +1926,17 @@
// Templates w/o wifi network keys can query stats as usual.
assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0);
assertNetworkTotal(sTemplateImsi1, 0L, 0L, 0L, 0L, 0);
+ // Templates for test network does not need to enforce location permission.
+ final NetworkTemplate templateTestIface1 = new NetworkTemplate.Builder(MATCH_TEST)
+ .setWifiNetworkKeys(Set.of(TEST_IFACE)).build();
+ assertNetworkTotal(templateTestIface1, 0L, 0L, 0L, 0L, 0);
doReturn(true).when(mLocationPermissionChecker)
.checkCallersLocationPermission(any(), any(), anyInt(), anyBoolean(), any());
assertNetworkTotal(sTemplateCarrierWifi1, 0L, 0L, 0L, 0L, 0);
assertNetworkTotal(sTemplateWifi, 0L, 0L, 0L, 0L, 0);
assertNetworkTotal(sTemplateImsi1, 0L, 0L, 0L, 0L, 0);
+ assertNetworkTotal(templateTestIface1, 0L, 0L, 0L, 0L, 0);
}
/**