[mdns] add API for discovery with subtype
This commit adds support of discovering services with explicit subtype.
With this change, a service can be discovered with subtype with:
```
nsdManager.discoverServices(
new DiscoveryRequest.Builder("_http._tcp", PROTOCOL_DNS_SD)
.setSubtype("_printer").build(),
executor, listener);
```
Bug: 265095929
Test: atest CtsNetTestCases FrameworksNetTests
Change-Id: Iba76283a003cf2d52a8c26e1de872c3e8e433350
This commit is contained in:
parent
7b2643f65f
commit
97d6aeb3a2
4 changed files with 497 additions and 37 deletions
247
framework-t/src/android/net/nsd/DiscoveryRequest.java
Normal file
247
framework-t/src/android/net/nsd/DiscoveryRequest.java
Normal file
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
* Copyright (C) 2023 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.
|
||||
*/
|
||||
|
||||
package android.net.nsd;
|
||||
|
||||
import android.annotation.FlaggedApi;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.net.Network;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Encapsulates parameters for {@link NsdManager#discoverServices}.
|
||||
*/
|
||||
@FlaggedApi(NsdManager.Flags.NSD_SUBTYPES_SUPPORT_ENABLED)
|
||||
public final class DiscoveryRequest implements Parcelable {
|
||||
private final int mProtocolType;
|
||||
|
||||
@NonNull
|
||||
private final String mServiceType;
|
||||
|
||||
@Nullable
|
||||
private final String mSubtype;
|
||||
|
||||
@Nullable
|
||||
private final Network mNetwork;
|
||||
|
||||
// TODO: add mDiscoveryConfig for more fine-grained discovery behavior control
|
||||
|
||||
@NonNull
|
||||
public static final Creator<DiscoveryRequest> CREATOR =
|
||||
new Creator<>() {
|
||||
@Override
|
||||
public DiscoveryRequest createFromParcel(Parcel in) {
|
||||
int protocolType = in.readInt();
|
||||
String serviceType = in.readString();
|
||||
String subtype = in.readString();
|
||||
Network network =
|
||||
in.readParcelable(Network.class.getClassLoader(), Network.class);
|
||||
return new DiscoveryRequest(protocolType, serviceType, subtype, network);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DiscoveryRequest[] newArray(int size) {
|
||||
return new DiscoveryRequest[size];
|
||||
}
|
||||
};
|
||||
|
||||
private DiscoveryRequest(int protocolType, @NonNull String serviceType,
|
||||
@Nullable String subtype, @Nullable Network network) {
|
||||
mProtocolType = protocolType;
|
||||
mServiceType = serviceType;
|
||||
mSubtype = subtype;
|
||||
mNetwork = network;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the service type in format of dot-joint string of two labels.
|
||||
*
|
||||
* For example, "_ipp._tcp" for internet printer and "_matter._tcp" for <a
|
||||
* href="https://csa-iot.org/all-solutions/matter">Matter</a> operational device.
|
||||
*/
|
||||
@NonNull
|
||||
public String getServiceType() {
|
||||
return mServiceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subtype without the trailing "._sub" label or {@code null} if no subtype is
|
||||
* specified.
|
||||
*
|
||||
* For example, the return value will be "_printer" for subtype "_printer._sub".
|
||||
*/
|
||||
@Nullable
|
||||
public String getSubtype() {
|
||||
return mSubtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the service discovery protocol.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public int getProtocolType() {
|
||||
return mProtocolType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Network} on which the query should be sent or {@code null} if no
|
||||
* network is specified.
|
||||
*/
|
||||
@Nullable
|
||||
public Network getNetwork() {
|
||||
return mNetwork;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(", protocolType: ").append(mProtocolType)
|
||||
.append(", serviceType: ").append(mServiceType)
|
||||
.append(", subtype: ").append(mSubtype)
|
||||
.append(", network: ").append(mNetwork);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
if (this == other) {
|
||||
return true;
|
||||
} else if (!(other instanceof DiscoveryRequest)) {
|
||||
return false;
|
||||
} else {
|
||||
DiscoveryRequest otherRequest = (DiscoveryRequest) other;
|
||||
return mProtocolType == otherRequest.mProtocolType
|
||||
&& Objects.equals(mServiceType, otherRequest.mServiceType)
|
||||
&& Objects.equals(mSubtype, otherRequest.mSubtype)
|
||||
&& Objects.equals(mNetwork, otherRequest.mNetwork);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(mProtocolType, mServiceType, mSubtype, mNetwork);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeInt(mProtocolType);
|
||||
dest.writeString(mServiceType);
|
||||
dest.writeString(mSubtype);
|
||||
dest.writeParcelable(mNetwork, flags);
|
||||
}
|
||||
|
||||
/** The builder for creating new {@link DiscoveryRequest} objects. */
|
||||
public static final class Builder {
|
||||
private final int mProtocolType;
|
||||
|
||||
@NonNull
|
||||
private String mServiceType;
|
||||
|
||||
@Nullable
|
||||
private String mSubtype;
|
||||
|
||||
@Nullable
|
||||
private Network mNetwork;
|
||||
|
||||
/**
|
||||
* Creates a new default {@link Builder} object with given service type.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code serviceType} is {@code null} or an empty
|
||||
* string
|
||||
*/
|
||||
public Builder(@NonNull String serviceType) {
|
||||
this(NsdManager.PROTOCOL_DNS_SD, serviceType);
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public Builder(int protocolType, @NonNull String serviceType) {
|
||||
NsdManager.checkProtocol(protocolType);
|
||||
mProtocolType = protocolType;
|
||||
setServiceType(serviceType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the service type to be discovered or {@code null} if no services should be queried.
|
||||
*
|
||||
* The {@code serviceType} must be a dot-joint string of two labels. For example,
|
||||
* "_ipp._tcp" for internet printer. Additionally, the first label must start with
|
||||
* underscore ('_') and the second label must be either "_udp" or "_tcp". Otherwise, {@link
|
||||
* NsdManager#discoverServices} will fail with {@link NsdManager#FAILURE_BAD_PARAMETER}.
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code serviceType} is {@code null} or an empty
|
||||
* string
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setServiceType(@NonNull String serviceType) {
|
||||
if (TextUtils.isEmpty(serviceType)) {
|
||||
throw new IllegalArgumentException("Service type cannot be empty");
|
||||
}
|
||||
mServiceType = serviceType;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the optional subtype of the services to be discovered.
|
||||
*
|
||||
* If a non-empty {@code subtype} is specified, it must start with underscore ('_') and
|
||||
* have the trailing "._sub" removed. Otherwise, {@link NsdManager#discoverServices} will
|
||||
* fail with {@link NsdManager#FAILURE_BAD_PARAMETER}. For example, {@code subtype} should
|
||||
* be "_printer" for DNS name "_printer._sub._http._tcp". In this case, only services with
|
||||
* this {@code subtype} will be queried, rather than all services of the base service type.
|
||||
*
|
||||
* Note that a non-empty service type must be specified with {@link #setServiceType} if a
|
||||
* non-empty subtype is specified by this method.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setSubtype(@Nullable String subtype) {
|
||||
mSubtype = subtype;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link Network} on which the discovery queries should be sent.
|
||||
*
|
||||
* @param network the discovery network or {@code null} if the query should be sent on
|
||||
* all supported networks
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setNetwork(@Nullable Network network) {
|
||||
mNetwork = network;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link DiscoveryRequest} object.
|
||||
*/
|
||||
@NonNull
|
||||
public DiscoveryRequest build() {
|
||||
return new DiscoveryRequest(mProtocolType, mServiceType, mSubtype, mNetwork);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@
|
|||
package android.net.nsd;
|
||||
|
||||
import android.os.Messenger;
|
||||
import android.net.nsd.DiscoveryRequest;
|
||||
import android.net.nsd.NsdServiceInfo;
|
||||
|
||||
/**
|
||||
|
|
@ -24,7 +25,7 @@ import android.net.nsd.NsdServiceInfo;
|
|||
* @hide
|
||||
*/
|
||||
oneway interface INsdManagerCallback {
|
||||
void onDiscoverServicesStarted(int listenerKey, in NsdServiceInfo info);
|
||||
void onDiscoverServicesStarted(int listenerKey, in DiscoveryRequest discoveryRequest);
|
||||
void onDiscoverServicesFailed(int listenerKey, int error);
|
||||
void onServiceFound(int listenerKey, in NsdServiceInfo info);
|
||||
void onServiceLost(int listenerKey, in NsdServiceInfo info);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
package android.net.nsd;
|
||||
|
||||
import android.net.nsd.AdvertisingRequest;
|
||||
import android.net.nsd.DiscoveryRequest;
|
||||
import android.net.nsd.INsdManagerCallback;
|
||||
import android.net.nsd.IOffloadEngine;
|
||||
import android.net.nsd.NsdServiceInfo;
|
||||
|
|
@ -30,7 +31,7 @@ import android.os.Messenger;
|
|||
interface INsdServiceConnector {
|
||||
void registerService(int listenerKey, in AdvertisingRequest advertisingRequest);
|
||||
void unregisterService(int listenerKey);
|
||||
void discoverServices(int listenerKey, in NsdServiceInfo serviceInfo);
|
||||
void discoverServices(int listenerKey, in DiscoveryRequest discoveryRequest);
|
||||
void stopDiscovery(int listenerKey);
|
||||
void resolveService(int listenerKey, in NsdServiceInfo serviceInfo);
|
||||
void startDaemon();
|
||||
|
|
@ -39,4 +40,4 @@ interface INsdServiceConnector {
|
|||
void unregisterServiceInfoCallback(int listenerKey);
|
||||
void registerOffloadEngine(String ifaceName, in IOffloadEngine cb, long offloadCapabilities, long offloadType);
|
||||
void unregisterOffloadEngine(in IOffloadEngine cb);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ import com.android.net.module.util.CollectionUtils;
|
|||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.regex.Matcher;
|
||||
|
|
@ -360,6 +361,8 @@ public final class NsdManager {
|
|||
@GuardedBy("mMapLock")
|
||||
private final SparseArray<NsdServiceInfo> mServiceMap = new SparseArray<>();
|
||||
@GuardedBy("mMapLock")
|
||||
private final SparseArray<DiscoveryRequest> mDiscoveryMap = new SparseArray<>();
|
||||
@GuardedBy("mMapLock")
|
||||
private final SparseArray<Executor> mExecutorMap = new SparseArray<>();
|
||||
private final Object mMapLock = new Object();
|
||||
// Map of listener key sent by client -> per-network discovery tracker
|
||||
|
|
@ -715,6 +718,12 @@ public final class NsdManager {
|
|||
mServHandler.sendMessage(mServHandler.obtainMessage(message, 0, listenerKey, info));
|
||||
}
|
||||
|
||||
private void sendDiscoveryRequest(
|
||||
int message, int listenerKey, DiscoveryRequest discoveryRequest) {
|
||||
mServHandler.sendMessage(
|
||||
mServHandler.obtainMessage(message, 0, listenerKey, discoveryRequest));
|
||||
}
|
||||
|
||||
private void sendError(int message, int listenerKey, int error) {
|
||||
mServHandler.sendMessage(mServHandler.obtainMessage(message, error, listenerKey));
|
||||
}
|
||||
|
|
@ -724,8 +733,8 @@ public final class NsdManager {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onDiscoverServicesStarted(int listenerKey, NsdServiceInfo info) {
|
||||
sendInfo(DISCOVER_SERVICES_STARTED, listenerKey, info);
|
||||
public void onDiscoverServicesStarted(int listenerKey, DiscoveryRequest discoveryRequest) {
|
||||
sendDiscoveryRequest(DISCOVER_SERVICES_STARTED, listenerKey, discoveryRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -1003,10 +1012,12 @@ public final class NsdManager {
|
|||
final Object obj = message.obj;
|
||||
final Object listener;
|
||||
final NsdServiceInfo ns;
|
||||
final DiscoveryRequest discoveryRequest;
|
||||
final Executor executor;
|
||||
synchronized (mMapLock) {
|
||||
listener = mListenerMap.get(key);
|
||||
ns = mServiceMap.get(key);
|
||||
discoveryRequest = mDiscoveryMap.get(key);
|
||||
executor = mExecutorMap.get(key);
|
||||
}
|
||||
if (listener == null) {
|
||||
|
|
@ -1014,17 +1025,22 @@ public final class NsdManager {
|
|||
return;
|
||||
}
|
||||
if (DBG) {
|
||||
Log.d(TAG, "received " + nameOf(what) + " for key " + key + ", service " + ns);
|
||||
if (discoveryRequest != null) {
|
||||
Log.d(TAG, "received " + nameOf(what) + " for key " + key + ", discovery "
|
||||
+ discoveryRequest);
|
||||
} else {
|
||||
Log.d(TAG, "received " + nameOf(what) + " for key " + key + ", service " + ns);
|
||||
}
|
||||
}
|
||||
switch (what) {
|
||||
case DISCOVER_SERVICES_STARTED:
|
||||
final String s = getNsdServiceInfoType((NsdServiceInfo) obj);
|
||||
final String s = getNsdServiceInfoType((DiscoveryRequest) obj);
|
||||
executor.execute(() -> ((DiscoveryListener) listener).onDiscoveryStarted(s));
|
||||
break;
|
||||
case DISCOVER_SERVICES_FAILED:
|
||||
removeListener(key);
|
||||
executor.execute(() -> ((DiscoveryListener) listener).onStartDiscoveryFailed(
|
||||
getNsdServiceInfoType(ns), errorCode));
|
||||
getNsdServiceInfoType(discoveryRequest), errorCode));
|
||||
break;
|
||||
case SERVICE_FOUND:
|
||||
executor.execute(() -> ((DiscoveryListener) listener).onServiceFound(
|
||||
|
|
@ -1039,12 +1055,12 @@ public final class NsdManager {
|
|||
// the effect for the client is indistinguishable from STOP_DISCOVERY_SUCCEEDED
|
||||
removeListener(key);
|
||||
executor.execute(() -> ((DiscoveryListener) listener).onStopDiscoveryFailed(
|
||||
getNsdServiceInfoType(ns), errorCode));
|
||||
getNsdServiceInfoType(discoveryRequest), errorCode));
|
||||
break;
|
||||
case STOP_DISCOVERY_SUCCEEDED:
|
||||
removeListener(key);
|
||||
executor.execute(() -> ((DiscoveryListener) listener).onDiscoveryStopped(
|
||||
getNsdServiceInfoType(ns)));
|
||||
getNsdServiceInfoType(discoveryRequest)));
|
||||
break;
|
||||
case REGISTER_SERVICE_FAILED:
|
||||
removeListener(key);
|
||||
|
|
@ -1117,21 +1133,33 @@ public final class NsdManager {
|
|||
return mListenerKey;
|
||||
}
|
||||
|
||||
// Assert that the listener is not in the map, then add it and returns its key
|
||||
private int putListener(Object listener, Executor e, NsdServiceInfo s) {
|
||||
checkListener(listener);
|
||||
final int key;
|
||||
private int putListener(Object listener, Executor e, NsdServiceInfo serviceInfo) {
|
||||
synchronized (mMapLock) {
|
||||
int valueIndex = mListenerMap.indexOfValue(listener);
|
||||
return putListener(listener, e, mServiceMap, serviceInfo);
|
||||
}
|
||||
}
|
||||
|
||||
private int putListener(Object listener, Executor e, DiscoveryRequest discoveryRequest) {
|
||||
synchronized (mMapLock) {
|
||||
return putListener(listener, e, mDiscoveryMap, discoveryRequest);
|
||||
}
|
||||
}
|
||||
|
||||
// Assert that the listener is not in the map, then add it and returns its key
|
||||
private <T> int putListener(Object listener, Executor e, SparseArray<T> map, T value) {
|
||||
synchronized (mMapLock) {
|
||||
checkListener(listener);
|
||||
final int key;
|
||||
final int valueIndex = mListenerMap.indexOfValue(listener);
|
||||
if (valueIndex != -1) {
|
||||
throw new IllegalArgumentException("listener already in use");
|
||||
}
|
||||
key = nextListenerKey();
|
||||
mListenerMap.put(key, listener);
|
||||
mServiceMap.put(key, s);
|
||||
map.put(key, value);
|
||||
mExecutorMap.put(key, e);
|
||||
return key;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
private int updateRegisteredListener(Object listener, Executor e, NsdServiceInfo s) {
|
||||
|
|
@ -1148,6 +1176,7 @@ public final class NsdManager {
|
|||
synchronized (mMapLock) {
|
||||
mListenerMap.remove(key);
|
||||
mServiceMap.remove(key);
|
||||
mDiscoveryMap.remove(key);
|
||||
mExecutorMap.remove(key);
|
||||
}
|
||||
}
|
||||
|
|
@ -1163,9 +1192,9 @@ public final class NsdManager {
|
|||
}
|
||||
}
|
||||
|
||||
private static String getNsdServiceInfoType(NsdServiceInfo s) {
|
||||
if (s == null) return "?";
|
||||
return s.getServiceType();
|
||||
private static String getNsdServiceInfoType(DiscoveryRequest r) {
|
||||
if (r == null) return "?";
|
||||
return r.getServiceType();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1406,15 +1435,44 @@ public final class NsdManager {
|
|||
if (TextUtils.isEmpty(serviceType)) {
|
||||
throw new IllegalArgumentException("Service type cannot be empty");
|
||||
}
|
||||
checkProtocol(protocolType);
|
||||
DiscoveryRequest request = new DiscoveryRequest.Builder(protocolType, serviceType)
|
||||
.setNetwork(network).build();
|
||||
discoverServices(request, executor, listener);
|
||||
}
|
||||
|
||||
NsdServiceInfo s = new NsdServiceInfo();
|
||||
s.setServiceType(serviceType);
|
||||
s.setNetwork(network);
|
||||
|
||||
int key = putListener(listener, executor, s);
|
||||
/**
|
||||
* Initiates service discovery to browse for instances of a service type. Service discovery
|
||||
* consumes network bandwidth and will continue until the application calls
|
||||
* {@link #stopServiceDiscovery}.
|
||||
*
|
||||
* <p> The function call immediately returns after sending a request to start service
|
||||
* discovery to the framework. The application is notified of a success to initiate
|
||||
* discovery through the callback {@link DiscoveryListener#onDiscoveryStarted} or a failure
|
||||
* through {@link DiscoveryListener#onStartDiscoveryFailed}.
|
||||
*
|
||||
* <p> Upon successful start, application is notified when a service is found with
|
||||
* {@link DiscoveryListener#onServiceFound} or when a service is lost with
|
||||
* {@link DiscoveryListener#onServiceLost}.
|
||||
*
|
||||
* <p> Upon failure to start, service discovery is not active and application does
|
||||
* not need to invoke {@link #stopServiceDiscovery}
|
||||
*
|
||||
* <p> The application should call {@link #stopServiceDiscovery} when discovery of this
|
||||
* service type is no longer required, and/or whenever the application is paused or
|
||||
* stopped.
|
||||
*
|
||||
* @param discoveryRequest the {@link DiscoveryRequest} object which specifies the discovery
|
||||
* parameters such as service type, subtype and network
|
||||
* @param executor Executor to run listener callbacks with
|
||||
* @param listener The listener notifies of a successful discovery and is used
|
||||
* to stop discovery on this serviceType through a call on {@link #stopServiceDiscovery}.
|
||||
*/
|
||||
@FlaggedApi(Flags.NSD_SUBTYPES_SUPPORT_ENABLED)
|
||||
public void discoverServices(@NonNull DiscoveryRequest discoveryRequest,
|
||||
@NonNull Executor executor, @NonNull DiscoveryListener listener) {
|
||||
int key = putListener(listener, executor, discoveryRequest);
|
||||
try {
|
||||
mService.discoverServices(key, s);
|
||||
mService.discoverServices(key, discoveryRequest);
|
||||
} catch (RemoteException e) {
|
||||
e.rethrowFromSystemServer();
|
||||
}
|
||||
|
|
@ -1465,12 +1523,10 @@ public final class NsdManager {
|
|||
throw new IllegalArgumentException("Service type cannot be empty");
|
||||
}
|
||||
Objects.requireNonNull(networkRequest, "NetworkRequest cannot be null");
|
||||
checkProtocol(protocolType);
|
||||
DiscoveryRequest discoveryRequest =
|
||||
new DiscoveryRequest.Builder(protocolType, serviceType).build();
|
||||
|
||||
NsdServiceInfo s = new NsdServiceInfo();
|
||||
s.setServiceType(serviceType);
|
||||
|
||||
final int baseListenerKey = putListener(listener, executor, s);
|
||||
final int baseListenerKey = putListener(listener, executor, discoveryRequest);
|
||||
|
||||
final PerNetworkDiscoveryTracker discoveryInfo = new PerNetworkDiscoveryTracker(
|
||||
serviceType, protocolType, executor, listener);
|
||||
|
|
@ -1602,6 +1658,7 @@ public final class NsdManager {
|
|||
* @param executor Executor to run callbacks with
|
||||
* @param listener to receive callback upon service update
|
||||
*/
|
||||
// TODO: use {@link DiscoveryRequest} to specify the service to be subscribed
|
||||
public void registerServiceInfoCallback(@NonNull NsdServiceInfo serviceInfo,
|
||||
@NonNull Executor executor, @NonNull ServiceInfoCallback listener) {
|
||||
checkServiceInfo(serviceInfo);
|
||||
|
|
@ -1643,7 +1700,7 @@ public final class NsdManager {
|
|||
Objects.requireNonNull(listener, "listener cannot be null");
|
||||
}
|
||||
|
||||
private static void checkProtocol(int protocolType) {
|
||||
static void checkProtocol(int protocolType) {
|
||||
if (protocolType != PROTOCOL_DNS_SD) {
|
||||
throw new IllegalArgumentException("Unsupported protocol");
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue