[mdns] add support for advertising subtypes
This commit adds support of advertising and discovering services
with subtypes.
With this change, client can publish a new service with subtypes with
code:
```
NsdServiceInfo info = new NsdServiceInfo();
info.setServiceName("My Service");
info.setServiceType("_meshcop._udp");
info.setSubtypes(Set.of("_abc"));
nsdManager.registerService(info, PROTOCOL_DNS_SD, listener);
```
Bug: 265095929
Test: atest CtsNetTestCases FrameworksNetTests
Change-Id: Ia83182e2d43002243d1ef4357d14a8056d7da14b
diff --git a/framework-t/api/current.txt b/framework-t/api/current.txt
index 86745d4..bbf5181 100644
--- a/framework-t/api/current.txt
+++ b/framework-t/api/current.txt
@@ -251,6 +251,7 @@
method public int getPort();
method public String getServiceName();
method public String getServiceType();
+ method @FlaggedApi("com.android.net.flags.nsd_subtypes_support_enabled") @NonNull public java.util.Set<java.lang.String> getSubtypes();
method public void removeAttribute(String);
method public void setAttribute(String, String);
method @Deprecated public void setHost(java.net.InetAddress);
@@ -259,6 +260,7 @@
method public void setPort(int);
method public void setServiceName(String);
method public void setServiceType(String);
+ method @FlaggedApi("com.android.net.flags.nsd_subtypes_support_enabled") public void setSubtypes(@NonNull java.util.Set<java.lang.String>);
method public void writeToParcel(android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.net.nsd.NsdServiceInfo> CREATOR;
}
diff --git a/framework-t/src/android/net/nsd/NsdManager.java b/framework-t/src/android/net/nsd/NsdManager.java
index bf01a9d..fcf79eb 100644
--- a/framework-t/src/android/net/nsd/NsdManager.java
+++ b/framework-t/src/android/net/nsd/NsdManager.java
@@ -150,6 +150,8 @@
public static class Flags {
static final String REGISTER_NSD_OFFLOAD_ENGINE_API =
"com.android.net.flags.register_nsd_offload_engine_api";
+ static final String NSD_SUBTYPES_SUPPORT_ENABLED =
+ "com.android.net.flags.nsd_subtypes_support_enabled";
}
/**
diff --git a/framework-t/src/android/net/nsd/NsdServiceInfo.java b/framework-t/src/android/net/nsd/NsdServiceInfo.java
index caeecdd..46c278a 100644
--- a/framework-t/src/android/net/nsd/NsdServiceInfo.java
+++ b/framework-t/src/android/net/nsd/NsdServiceInfo.java
@@ -16,6 +16,9 @@
package android.net.nsd;
+import static java.nio.charset.StandardCharsets.UTF_8;
+
+import android.annotation.FlaggedApi;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.compat.annotation.UnsupportedAppUsage;
@@ -24,6 +27,7 @@
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import com.android.net.module.util.InetAddressUtils;
@@ -35,6 +39,7 @@
import java.util.Collections;
import java.util.List;
import java.util.Map;
+import java.util.Set;
/**
* A class representing service information for network service discovery
@@ -48,6 +53,8 @@
private String mServiceType;
+ private final Set<String> mSubtypes = new ArraySet<>();
+
private final ArrayMap<String, byte[]> mTxtRecord = new ArrayMap<>();
private final List<InetAddress> mHostAddresses = new ArrayList<>();
@@ -391,11 +398,41 @@
mInterfaceIndex = interfaceIndex;
}
+ /**
+ * Sets the subtypes to be advertised for this service instance.
+ *
+ * The elements in {@code subtypes} should be the subtype identifiers which have the trailing
+ * "._sub" removed. For example, the subtype should be "_printer" for
+ * "_printer._sub._http._tcp.local".
+ *
+ * Only one subtype will be registered if multiple elements of {@code subtypes} have the same
+ * case-insensitive value.
+ */
+ @FlaggedApi(NsdManager.Flags.NSD_SUBTYPES_SUPPORT_ENABLED)
+ public void setSubtypes(@NonNull Set<String> subtypes) {
+ mSubtypes.clear();
+ mSubtypes.addAll(subtypes);
+ }
+
+ /**
+ * Returns subtypes of this service instance.
+ *
+ * When this object is returned by the service discovery/browse APIs (etc. {@link
+ * NsdManager.DiscoveryListener}), the return value may or may not include the subtypes of this
+ * service.
+ */
+ @FlaggedApi(NsdManager.Flags.NSD_SUBTYPES_SUPPORT_ENABLED)
+ @NonNull
+ public Set<String> getSubtypes() {
+ return Collections.unmodifiableSet(mSubtypes);
+ }
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("name: ").append(mServiceName)
.append(", type: ").append(mServiceType)
+ .append(", subtypes: ").append(TextUtils.join(", ", mSubtypes))
.append(", hostAddresses: ").append(TextUtils.join(", ", mHostAddresses))
.append(", port: ").append(mPort)
.append(", network: ").append(mNetwork);
@@ -414,6 +451,7 @@
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mServiceName);
dest.writeString(mServiceType);
+ dest.writeStringList(new ArrayList<>(mSubtypes));
dest.writeInt(mPort);
// TXT record key/value pairs.
@@ -445,6 +483,7 @@
NsdServiceInfo info = new NsdServiceInfo();
info.mServiceName = in.readString();
info.mServiceType = in.readString();
+ info.setSubtypes(new ArraySet<>(in.createStringArrayList()));
info.mPort = in.readInt();
// TXT record key/value pairs.