[Thread] add vendor & model name support for net diag
1. allow OEMs to default the vendor and model name to system properties.
2. use the vendor & model name for net diag TLVs
Change-Id: I30e988ba3e9cb9f9c5dc3a096f162d5dbcdfbc11
diff --git a/service/ServiceConnectivityResources/res/values/config_thread.xml b/service/ServiceConnectivityResources/res/values/config_thread.xml
index a458c7f..62b12fb 100644
--- a/service/ServiceConnectivityResources/res/values/config_thread.xml
+++ b/service/ServiceConnectivityResources/res/values/config_thread.xml
@@ -46,11 +46,12 @@
<bool name="config_thread_location_use_for_country_code_enabled">true</bool>
<!-- Specifies the UTF-8 vendor name of this device. If this value is not an empty string, it
- will be included in TXT value (key is 'vn') of the "_meshcop._udp" mDNS service which is
- published by the Thread service. A non-empty string value must not exceed length of 24 UTF-8
- bytes.
+ will be included in TXT value (key is 'vn') of the "_meshcop._udp" mDNS service as well as the
+ Vendor Name TLV for network diagnostic. A non-empty string value must not exceed length of 24
+ UTF-8 bytes. A special value "ro.product.manufacturer" indicates this value should be derived
+ from the `ro.product.manufacturer` system property.
-->
- <string translatable="false" name="config_thread_vendor_name">Android</string>
+ <string translatable="false" name="config_thread_vendor_name">ro.product.manufacturer</string>
<!-- Specifies the 24 bits vendor OUI of this device. If this value is not an empty string, it
will be included in TXT (key is 'vo') value of the "_meshcop._udp" mDNS service which is
@@ -61,11 +62,12 @@
<string translatable="false" name="config_thread_vendor_oui"></string>
<!-- Specifies the UTF-8 product model name of this device. If this value is not an empty
- string, it will be included in TXT (key is 'mn') value of the "_meshcop._udp" mDNS service
- which is published by the Thread service. A non-empty string value must not exceed length of 24
- UTF-8 bytes.
+ string, it will be included in TXT (key is 'mn') value of the "_meshcop._udp" mDNS service as
+ well as the Vendor Model TLV for network diagnostic. A non-empty string value must not exceed
+ length of 24 UTF-8 bytes. A special value "ro.product.model" indicates this value should be
+ derived from the `ro.product.model` system property.
-->
- <string translatable="false" name="config_thread_model_name">Thread Border Router</string>
+ <string translatable="false" name="config_thread_model_name">ro.product.model</string>
<!-- Specifies vendor-specific mDNS TXT entries which will be included in the "_meshcop._udp"
service. The TXT entries list MUST conform to the format requirement in RFC 6763 section 6. For
diff --git a/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java b/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java
index d859fb2..e99c88e 100644
--- a/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java
+++ b/thread/service/java/com/android/server/thread/ThreadNetworkControllerService.java
@@ -128,6 +128,7 @@
import com.android.net.module.util.SharedLog;
import com.android.server.ServiceManagerWrapper;
import com.android.server.connectivity.ConnectivityResources;
+import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.thread.openthread.BackboneRouterState;
import com.android.server.thread.openthread.DnsTxtAttribute;
import com.android.server.thread.openthread.IChannelMasksReceiver;
@@ -191,6 +192,7 @@
private final Context mContext;
private final Handler mHandler;
+ private final MockableSystemProperties mSystemProperties;
// Below member fields can only be accessed from the handler thread (`mHandler`). In
// particular, the constructor does not run on the handler thread, so it must not touch any of
@@ -235,6 +237,7 @@
ThreadNetworkControllerService(
Context context,
Handler handler,
+ MockableSystemProperties systemProperties,
NetworkProvider networkProvider,
Supplier<IOtDaemon> otDaemonSupplier,
ConnectivityManager connectivityManager,
@@ -249,6 +252,7 @@
Map<Network, LinkProperties> networkToLinkProperties) {
mContext = context;
mHandler = handler;
+ mSystemProperties = systemProperties;
mNetworkProvider = networkProvider;
mOtDaemonSupplier = otDaemonSupplier;
mConnectivityManager = connectivityManager;
@@ -286,6 +290,7 @@
return new ThreadNetworkControllerService(
context,
handler,
+ new MockableSystemProperties(),
networkProvider,
() -> IOtDaemon.Stub.asInterface(ServiceManagerWrapper.waitForService("ot_daemon")),
connectivityManager,
@@ -355,7 +360,7 @@
newOtDaemonConfig(mPersistentSettings.getConfiguration()),
mTunIfController.getTunFd(),
mNsdPublisher,
- getMeshcopTxtAttributes(mResources.get()),
+ getMeshcopTxtAttributes(mResources.get(), mSystemProperties),
mCountryCodeSupplier.get(),
FeatureFlags.isTrelEnabled(),
mOtDaemonCallbackProxy);
@@ -365,10 +370,37 @@
return mOtDaemon;
}
+ static String getVendorName(Resources resources, MockableSystemProperties systemProperties) {
+ final String PROP_MANUFACTURER = "ro.product.manufacturer";
+ String vendorName = resources.getString(R.string.config_thread_vendor_name);
+ if (vendorName.equalsIgnoreCase(PROP_MANUFACTURER)) {
+ vendorName = systemProperties.get(PROP_MANUFACTURER);
+ // Assume it's always ASCII chars in ro.product.manufacturer
+ if (vendorName.length() > MAX_VENDOR_NAME_UTF8_BYTES) {
+ vendorName = vendorName.substring(0, MAX_VENDOR_NAME_UTF8_BYTES);
+ }
+ }
+ return vendorName;
+ }
+
+ static String getModelName(Resources resources, MockableSystemProperties systemProperties) {
+ final String PROP_MODEL = "ro.product.model";
+ String modelName = resources.getString(R.string.config_thread_model_name);
+ if (modelName.equalsIgnoreCase(PROP_MODEL)) {
+ modelName = systemProperties.get(PROP_MODEL);
+ // Assume it's always ASCII chars in ro.product.model
+ if (modelName.length() > MAX_MODEL_NAME_UTF8_BYTES) {
+ modelName = modelName.substring(0, MAX_MODEL_NAME_UTF8_BYTES);
+ }
+ }
+ return modelName;
+ }
+
@VisibleForTesting
- static MeshcopTxtAttributes getMeshcopTxtAttributes(Resources resources) {
- final String modelName = resources.getString(R.string.config_thread_model_name);
- final String vendorName = resources.getString(R.string.config_thread_vendor_name);
+ static MeshcopTxtAttributes getMeshcopTxtAttributes(
+ Resources resources, MockableSystemProperties systemProperties) {
+ final String vendorName = getVendorName(resources, systemProperties);
+ final String modelName = getModelName(resources, systemProperties);
final String vendorOui = resources.getString(R.string.config_thread_vendor_oui);
final String[] vendorSpecificTxts =
resources.getStringArray(R.array.config_thread_mdns_vendor_specific_txts);
@@ -637,6 +669,8 @@
.setSrpServerWaitForBorderRoutingEnabled(srpServerWaitEnabled)
.setBorderRouterAutoJoinEnabled(autoJoinEnabled)
.setCountryCodeEnabled(countryCodeEnabled)
+ .setVendorName(getVendorName(mResources.get(), mSystemProperties))
+ .setModelName(getModelName(mResources.get(), mSystemProperties))
.build();
}
diff --git a/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java b/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java
index c4e373a..a9c0da2 100644
--- a/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java
+++ b/thread/tests/integration/src/android/net/thread/ServiceDiscoveryTest.java
@@ -48,6 +48,7 @@
import android.net.thread.utils.ThreadFeatureCheckerRule.RequiresThreadFeature;
import android.net.thread.utils.ThreadNetworkControllerWrapper;
import android.os.HandlerThread;
+import android.os.SystemProperties;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.LargeTest;
@@ -454,14 +455,22 @@
}
@Test
- public void meshcopOverlay_vendorAndModelNameAreSetToOverlayValue() throws Exception {
+ public void meshcopOverlay_vendorAndModelNameAreSetToSystemProperties() throws Exception {
NsdServiceInfo discoveredService = discoverService(mNsdManager, "_meshcop._udp");
assertThat(discoveredService).isNotNull();
NsdServiceInfo meshcopService = resolveService(mNsdManager, discoveredService);
+ String expectedVendorName = SystemProperties.get("ro.product.manufacturer");
+ if (expectedVendorName.length() > 24) {
+ expectedVendorName = expectedVendorName.substring(0, 24);
+ }
+ String expectedModelName = SystemProperties.get("ro.product.model");
+ if (expectedModelName.length() > 24) {
+ expectedModelName = expectedModelName.substring(0, 24);
+ }
Map<String, byte[]> txtMap = meshcopService.getAttributes();
- assertThat(txtMap.get("vn")).isEqualTo("Android".getBytes(UTF_8));
- assertThat(txtMap.get("mn")).isEqualTo("Thread Border Router".getBytes(UTF_8));
+ assertThat(txtMap.get("vn")).isEqualTo(expectedVendorName.getBytes(UTF_8));
+ assertThat(txtMap.get("mn")).isEqualTo(expectedModelName.getBytes(UTF_8));
}
@Test
diff --git a/thread/tests/integration/src/android/net/thread/ThreadIntegrationTest.java b/thread/tests/integration/src/android/net/thread/ThreadIntegrationTest.java
index b608c5d..c56db02 100644
--- a/thread/tests/integration/src/android/net/thread/ThreadIntegrationTest.java
+++ b/thread/tests/integration/src/android/net/thread/ThreadIntegrationTest.java
@@ -24,6 +24,8 @@
import static android.net.thread.utils.IntegrationTestUtils.getIpv6Addresses;
import static android.net.thread.utils.IntegrationTestUtils.getIpv6LinkAddresses;
import static android.net.thread.utils.IntegrationTestUtils.waitFor;
+import static android.net.thread.utils.OtDaemonController.DIAG_VENDOR_MODEL_TLV_TYPE;
+import static android.net.thread.utils.OtDaemonController.DIAG_VENDOR_NAME_TLV_TYPE;
import static android.net.thread.utils.ThreadNetworkControllerWrapper.JOIN_TIMEOUT;
import static android.os.SystemClock.elapsedRealtime;
@@ -290,6 +292,17 @@
// TODO: b/376217403 - enables / disables Border Agent at runtime
}
+ @Test
+ public void networkDiagnostic_vendorAndModelNameAreSet() throws Exception {
+ mController.joinAndWait(DEFAULT_DATASET);
+
+ var tlvTypes = List.of(DIAG_VENDOR_NAME_TLV_TYPE, DIAG_VENDOR_MODEL_TLV_TYPE);
+ var result = mOtCtl.netDiagGet(mOtCtl.getMlEid(), tlvTypes);
+
+ assertThat(result.get("Vendor Name")).isNotEmpty();
+ assertThat(result.get("Vendor Model")).isNotEmpty();
+ }
+
private NetworkCapabilities registerNetworkCallbackAndWait(NetworkRequest request)
throws Exception {
CompletableFuture<Network> networkFuture = new CompletableFuture<>();
diff --git a/thread/tests/unit/src/com/android/server/thread/ThreadNetworkControllerServiceTest.java b/thread/tests/unit/src/com/android/server/thread/ThreadNetworkControllerServiceTest.java
index 63d6130..a73390c 100644
--- a/thread/tests/unit/src/com/android/server/thread/ThreadNetworkControllerServiceTest.java
+++ b/thread/tests/unit/src/com/android/server/thread/ThreadNetworkControllerServiceTest.java
@@ -34,6 +34,7 @@
import static android.net.thread.ThreadNetworkManager.PERMISSION_THREAD_NETWORK_PRIVILEGED;
import static android.net.thread.ThreadNetworkManager.PERMISSION_THREAD_NETWORK_TESTING;
+import static com.android.server.thread.ThreadNetworkControllerService.getMeshcopTxtAttributes;
import static com.android.server.thread.ThreadNetworkCountryCode.DEFAULT_COUNTRY_CODE;
import static com.android.server.thread.ThreadPersistentSettings.KEY_THREAD_ENABLED;
import static com.android.server.thread.openthread.IOtDaemon.ErrorCode.OT_ERROR_INVALID_STATE;
@@ -49,8 +50,6 @@
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.ArgumentMatchers.isNotNull;
-import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.clearInvocations;
@@ -101,10 +100,10 @@
import com.android.dx.mockito.inline.extended.ExtendedMockito;
import com.android.net.module.util.RoutingCoordinatorManager;
import com.android.server.connectivity.ConnectivityResources;
+import com.android.server.connectivity.MockableSystemProperties;
import com.android.server.thread.openthread.DnsTxtAttribute;
import com.android.server.thread.openthread.IOtStatusReceiver;
import com.android.server.thread.openthread.MeshcopTxtAttributes;
-import com.android.server.thread.openthread.OtDaemonConfiguration;
import com.android.server.thread.openthread.testing.FakeOtDaemon;
import org.junit.After;
@@ -181,6 +180,7 @@
private static final String TEST_MODEL_NAME = "test model";
private static final LinkAddress TEST_NAT64_CIDR = new LinkAddress("192.168.255.0/24");
+ @Mock private MockableSystemProperties mMockSystemProperties;
@Mock private ConnectivityManager mMockConnectivityManager;
@Mock private RoutingCoordinatorManager mMockRoutingCoordinatorManager;
@Mock private NetworkAgent mMockNetworkAgent;
@@ -271,6 +271,7 @@
new ThreadNetworkControllerService(
mContext,
handler,
+ mMockSystemProperties,
networkProvider,
() -> mFakeOtDaemon,
mMockConnectivityManager,
@@ -336,6 +337,23 @@
}
@Test
+ public void initialize_vendorAndModelNameSetToProperty_propertiesAreSetToOtDaemon()
+ throws Exception {
+ when(mMockSystemProperties.get(eq("ro.product.manufacturer"))).thenReturn("Banana");
+ when(mResources.getString(eq(R.string.config_thread_vendor_name)))
+ .thenReturn("ro.product.manufacturer");
+ when(mMockSystemProperties.get(eq("ro.product.model"))).thenReturn("Orange");
+ when(mResources.getString(eq(R.string.config_thread_model_name)))
+ .thenReturn("ro.product.model");
+
+ mService.initialize();
+ mTestLooper.dispatchAll();
+
+ assertThat(mFakeOtDaemon.getConfiguration().vendorName).isEqualTo("Banana");
+ assertThat(mFakeOtDaemon.getConfiguration().modelName).isEqualTo("Orange");
+ }
+
+ @Test
public void initialize_nat64Disabled_doesNotRequestNat64CidrAndConfiguresOtDaemon()
throws Exception {
ThreadConfiguration config =
@@ -345,8 +363,7 @@
mTestLooper.dispatchAll();
verify(mMockRoutingCoordinatorManager, never()).requestDownstreamAddress(any());
- verify(mFakeOtDaemon, times(1)).setNat64Cidr(isNull(), any());
- verify(mFakeOtDaemon, never()).setNat64Cidr(isNotNull(), any());
+ assertThat(mFakeOtDaemon.getNat64Cidr()).isNull();
}
@Test
@@ -359,11 +376,8 @@
mTestLooper.dispatchAll();
verify(mMockRoutingCoordinatorManager, times(1)).requestDownstreamAddress(any());
- verify(mFakeOtDaemon, times(1))
- .setConfiguration(
- new OtDaemonConfiguration.Builder().setNat64Enabled(true).build(),
- null /* receiver */);
- verify(mFakeOtDaemon, times(1)).setNat64Cidr(eq(TEST_NAT64_CIDR.toString()), any());
+ assertThat(mFakeOtDaemon.getConfiguration().nat64Enabled).isTrue();
+ assertThat(mFakeOtDaemon.getNat64Cidr()).isEqualTo(TEST_NAT64_CIDR.toString());
}
@Test
@@ -400,7 +414,7 @@
when(mResources.getString(eq(R.string.config_thread_vendor_name))).thenReturn("");
MeshcopTxtAttributes meshcopTxts =
- ThreadNetworkControllerService.getMeshcopTxtAttributes(mResources);
+ getMeshcopTxtAttributes(mResources, mMockSystemProperties);
assertThat(meshcopTxts.vendorName).isEqualTo("");
}
@@ -412,7 +426,31 @@
assertThrows(
IllegalStateException.class,
- () -> ThreadNetworkControllerService.getMeshcopTxtAttributes(mResources));
+ () -> getMeshcopTxtAttributes(mResources, mMockSystemProperties));
+ }
+
+ @Test
+ public void getMeshcopTxtAttributes_VendorNameSetToManufacturer_manufacturerPropertyIsUsed() {
+ when(mMockSystemProperties.get(eq("ro.product.manufacturer"))).thenReturn("Banana");
+ when(mResources.getString(eq(R.string.config_thread_vendor_name)))
+ .thenReturn("ro.product.manufacturer");
+
+ MeshcopTxtAttributes meshcopTxts =
+ getMeshcopTxtAttributes(mResources, mMockSystemProperties);
+
+ assertThat(meshcopTxts.vendorName).isEqualTo("Banana");
+ }
+
+ @Test
+ public void getMeshcopTxtAttributes_ModelNameSetToModelProperty_modelPropertyIsUsed() {
+ when(mMockSystemProperties.get(eq("ro.product.model"))).thenReturn("Orange");
+ when(mResources.getString(eq(R.string.config_thread_model_name)))
+ .thenReturn("ro.product.model");
+
+ MeshcopTxtAttributes meshcopTxts =
+ getMeshcopTxtAttributes(mResources, mMockSystemProperties);
+
+ assertThat(meshcopTxts.modelName).isEqualTo("Orange");
}
@Test
@@ -422,14 +460,14 @@
assertThrows(
IllegalStateException.class,
- () -> ThreadNetworkControllerService.getMeshcopTxtAttributes(mResources));
+ () -> getMeshcopTxtAttributes(mResources, mMockSystemProperties));
}
@Test
public void getMeshcopTxtAttributes_emptyModelName_accepted() {
when(mResources.getString(eq(R.string.config_thread_model_name))).thenReturn("");
- var meshcopTxts = ThreadNetworkControllerService.getMeshcopTxtAttributes(mResources);
+ var meshcopTxts = getMeshcopTxtAttributes(mResources, mMockSystemProperties);
assertThat(meshcopTxts.modelName).isEqualTo("");
}
@@ -461,7 +499,7 @@
private byte[] getMeshcopTxtAttributesWithVendorOui(String vendorOui) {
when(mResources.getString(eq(R.string.config_thread_vendor_oui))).thenReturn(vendorOui);
- return ThreadNetworkControllerService.getMeshcopTxtAttributes(mResources).vendorOui;
+ return getMeshcopTxtAttributes(mResources, mMockSystemProperties).vendorOui;
}
@Test
@@ -886,16 +924,12 @@
verify(mockReceiver, times(1)).onSuccess();
verify(mMockRoutingCoordinatorManager, times(1)).requestDownstreamAddress(any());
- verify(mFakeOtDaemon, times(1))
- .setConfiguration(
- eq(new OtDaemonConfiguration.Builder().setNat64Enabled(true).build()),
- any(IOtStatusReceiver.class));
- verify(mFakeOtDaemon, times(1))
- .setNat64Cidr(eq(TEST_NAT64_CIDR.toString()), any(IOtStatusReceiver.class));
+ assertThat(mFakeOtDaemon.getConfiguration().nat64Enabled).isTrue();
+ assertThat(mFakeOtDaemon.getNat64Cidr()).isEqualTo(TEST_NAT64_CIDR.toString());
}
@Test
- public void setConfiguration_enablesNat64_otDaemonRemoteFailure_serviceDoesNotCrash()
+ public void setConfiguration_enablesNat64AndOtDaemonRemoteFailure_serviceDoesNotCrash()
throws Exception {
mService.initialize();
mTestLooper.dispatchAll();
@@ -929,12 +963,8 @@
verify(mockReceiver, times(1)).onSuccess();
verify(mMockRoutingCoordinatorManager, times(1)).releaseDownstream(any());
verify(mMockRoutingCoordinatorManager, never()).requestDownstreamAddress(any());
- verify(mFakeOtDaemon, times(1))
- .setConfiguration(
- eq(new OtDaemonConfiguration.Builder().setNat64Enabled(false).build()),
- any(IOtStatusReceiver.class));
- verify(mFakeOtDaemon, times(1)).setNat64Cidr(isNull(), any(IOtStatusReceiver.class));
- verify(mFakeOtDaemon, never()).setNat64Cidr(isNotNull(), any(IOtStatusReceiver.class));
+ assertThat(mFakeOtDaemon.getConfiguration().nat64Enabled).isFalse();
+ assertThat(mFakeOtDaemon.getNat64Cidr()).isNull();
}
@Test
diff --git a/thread/tests/utils/src/android/net/thread/utils/OtDaemonController.java b/thread/tests/utils/src/android/net/thread/utils/OtDaemonController.java
index d35b94e..41d9eaf 100644
--- a/thread/tests/utils/src/android/net/thread/utils/OtDaemonController.java
+++ b/thread/tests/utils/src/android/net/thread/utils/OtDaemonController.java
@@ -24,10 +24,13 @@
import com.android.compatibility.common.util.SystemUtil;
import java.net.Inet6Address;
+import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.stream.Collectors;
/**
@@ -37,6 +40,9 @@
* <p>Note that this class takes root privileged to run.
*/
public final class OtDaemonController {
+ public static final int DIAG_VENDOR_NAME_TLV_TYPE = 25;
+ public static final int DIAG_VENDOR_MODEL_TLV_TYPE = 26;
+
private static final String OT_CTL = "/system/bin/ot-ctl";
/**
@@ -188,6 +194,35 @@
}
/**
+ * Sends DIAG_GET request to the given peer device and returns the parsed result as a dict of
+ * the requested TLV values.
+ *
+ * <p>For example, a request {@code netDiagGet("fdad:3d13:7b11:4049:ed1a:7e87:4770:a345",
+ * [DIAG_VENDOR_NAME_TLV_TYPE, DIAG_VENDOR_MODEL_TLV_TYPE])} can return a dict of {@code
+ * {"Vendor Name" : "ABC", "Vendor Model" : "Cuttlefish"}}
+ */
+ public Map<String, String> netDiagGet(InetAddress peerAddr, List<Integer> tlvTypes) {
+ String tlvTypeList =
+ tlvTypes.stream().map(Object::toString).collect(Collectors.joining(" "));
+
+ List<String> outputs =
+ executeCommandAndParse(
+ "networkdiagnostic get " + peerAddr.getHostAddress() + " " + tlvTypeList);
+ Map<String, String> result = new HashMap<>();
+ for (String line : outputs) {
+ if (line.startsWith("DIAG_GET")) {
+ continue;
+ }
+ String[] keyValue = line.split(":");
+ if (keyValue.length != 2) {
+ throw new IllegalStateException("Unexpected OT output: " + line);
+ }
+ result.put(keyValue[0].strip(), keyValue[1].strip());
+ }
+ return result;
+ }
+
+ /**
* Executes a ot-ctl command and parse the output to a list of strings.
*
* <p>The trailing "Done" in the command output will be dropped.
diff --git a/thread/tests/utils/src/android/net/thread/utils/TapTestNetworkTracker.java b/thread/tests/utils/src/android/net/thread/utils/TapTestNetworkTracker.java
index 9a1a05b..62c2785 100644
--- a/thread/tests/utils/src/android/net/thread/utils/TapTestNetworkTracker.java
+++ b/thread/tests/utils/src/android/net/thread/utils/TapTestNetworkTracker.java
@@ -16,44 +16,23 @@
package android.net.thread.utils;
import static android.Manifest.permission.MANAGE_TEST_NETWORKS;
-import static android.net.InetAddresses.parseNumericAddress;
-import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
-import static android.net.NetworkCapabilities.TRANSPORT_TEST;
-import static android.system.OsConstants.AF_INET6;
-import static android.system.OsConstants.IPPROTO_UDP;
-import static android.system.OsConstants.SOCK_DGRAM;
import static com.android.testutils.RecorderCallback.CallbackEntry.LINK_PROPERTIES_CHANGED;
import static com.android.testutils.TestPermissionUtil.runAsShell;
import android.content.Context;
import android.net.ConnectivityManager;
-import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
-import android.net.NetworkAgentConfig;
-import android.net.NetworkCapabilities;
-import android.net.NetworkRequest;
import android.net.TestNetworkInterface;
import android.net.TestNetworkManager;
-import android.net.TestNetworkSpecifier;
import android.os.Looper;
-import android.system.ErrnoException;
-import android.system.Os;
-import com.android.compatibility.common.util.PollingCheck;
import com.android.testutils.TestableNetworkAgent;
import com.android.testutils.TestableNetworkCallback;
-import java.io.FileDescriptor;
import java.io.IOException;
-import java.net.InterfaceAddress;
-import java.net.NetworkInterface;
-import java.net.SocketException;
import java.time.Duration;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
/** A class that can create/destroy a test network based on TAP interface. */
public final class TapTestNetworkTracker {