Add flags for allowlisting types for new NSD impl
The flags allow enabling MdnsDiscoveryManager or MdnsAdvertiser for specific service types only. For example: mdns_type_allowlist_flags = "_type1._tcp:flag1,_type2._tcp:flag2" mdns_discovery_manager_allowlist_flag1_version = 1234 mdns_advertiser_allowlist_flag2_version = 2345 will enable MdnsDiscoveryManager when discovering/resolving services of type _type1._tcp, and MdnsAdvertiser when advertising services of type _type2._tcp. Test: atest NsdServiceTest Bug: 270885892 Change-Id: I75c31a28472210bf8777409ea7aff1e3d8bf0a0d
This commit is contained in:
@@ -20,6 +20,7 @@ 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 android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
@@ -110,6 +111,34 @@ public class NsdService extends INsdManager.Stub {
|
||||
*/
|
||||
private static final String MDNS_ADVERTISER_VERSION = "mdns_advertiser_version";
|
||||
|
||||
/**
|
||||
* Comma-separated list of type:flag mappings indicating the flags to use to allowlist
|
||||
* discovery/advertising using MdnsDiscoveryManager / MdnsAdvertiser for a given type.
|
||||
*
|
||||
* For example _mytype._tcp.local and _othertype._tcp.local would be configured with:
|
||||
* _mytype._tcp:mytype,_othertype._tcp.local:othertype
|
||||
*
|
||||
* In which case the flags:
|
||||
* "mdns_discovery_manager_allowlist_mytype_version",
|
||||
* "mdns_advertiser_allowlist_mytype_version",
|
||||
* "mdns_discovery_manager_allowlist_othertype_version",
|
||||
* "mdns_advertiser_allowlist_othertype_version"
|
||||
* would be used to toggle MdnsDiscoveryManager / MdnsAdvertiser for each type. The flags will
|
||||
* be read with
|
||||
* {@link DeviceConfigUtils#isFeatureEnabled(Context, String, String, String, boolean)}.
|
||||
*
|
||||
* @see #MDNS_DISCOVERY_MANAGER_ALLOWLIST_FLAG_PREFIX
|
||||
* @see #MDNS_ADVERTISER_ALLOWLIST_FLAG_PREFIX
|
||||
* @see #MDNS_ALLOWLIST_FLAG_SUFFIX
|
||||
*/
|
||||
private static final String MDNS_TYPE_ALLOWLIST_FLAGS = "mdns_type_allowlist_flags";
|
||||
|
||||
private static final String MDNS_DISCOVERY_MANAGER_ALLOWLIST_FLAG_PREFIX =
|
||||
"mdns_discovery_manager_allowlist_";
|
||||
private static final String MDNS_ADVERTISER_ALLOWLIST_FLAG_PREFIX =
|
||||
"mdns_advertiser_allowlist_";
|
||||
private static final String MDNS_ALLOWLIST_FLAG_SUFFIX = "_version";
|
||||
|
||||
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;
|
||||
@@ -572,8 +601,9 @@ public class NsdService extends INsdManager.Stub {
|
||||
|
||||
final NsdServiceInfo info = args.serviceInfo;
|
||||
id = getUniqueId();
|
||||
if (mDeps.isMdnsDiscoveryManagerEnabled(mContext)) {
|
||||
final String serviceType = constructServiceType(info.getServiceType());
|
||||
if (mDeps.isMdnsDiscoveryManagerEnabled(mContext)
|
||||
|| useDiscoveryManagerForType(serviceType)) {
|
||||
if (serviceType == null) {
|
||||
clientInfo.onDiscoverServicesFailed(clientId,
|
||||
NsdManager.FAILURE_INTERNAL_ERROR);
|
||||
@@ -667,10 +697,11 @@ public class NsdService extends INsdManager.Stub {
|
||||
}
|
||||
|
||||
id = getUniqueId();
|
||||
if (mDeps.isMdnsAdvertiserEnabled(mContext)) {
|
||||
final NsdServiceInfo serviceInfo = args.serviceInfo;
|
||||
final String serviceType = serviceInfo.getServiceType();
|
||||
final String registerServiceType = constructServiceType(serviceType);
|
||||
if (mDeps.isMdnsAdvertiserEnabled(mContext)
|
||||
|| useAdvertiserForType(registerServiceType)) {
|
||||
if (registerServiceType == null) {
|
||||
Log.e(TAG, "Invalid service type: " + serviceType);
|
||||
clientInfo.onRegisterServiceFailed(clientId,
|
||||
@@ -686,7 +717,7 @@ public class NsdService extends INsdManager.Stub {
|
||||
storeAdvertiserRequestMap(clientId, id, clientInfo);
|
||||
} else {
|
||||
maybeStartDaemon();
|
||||
if (registerService(id, args.serviceInfo)) {
|
||||
if (registerService(id, serviceInfo)) {
|
||||
if (DBG) Log.d(TAG, "Register " + clientId + " " + id);
|
||||
storeLegacyRequestMap(clientId, id, clientInfo, msg.what);
|
||||
// Return success after mDns reports success
|
||||
@@ -748,8 +779,9 @@ public class NsdService extends INsdManager.Stub {
|
||||
|
||||
final NsdServiceInfo info = args.serviceInfo;
|
||||
id = getUniqueId();
|
||||
if (mDeps.isMdnsDiscoveryManagerEnabled(mContext)) {
|
||||
final String serviceType = constructServiceType(info.getServiceType());
|
||||
if (mDeps.isMdnsDiscoveryManagerEnabled(mContext)
|
||||
|| useDiscoveryManagerForType(serviceType)) {
|
||||
if (serviceType == null) {
|
||||
clientInfo.onResolveServiceFailed(clientId,
|
||||
NsdManager.FAILURE_INTERNAL_ERROR);
|
||||
@@ -1280,6 +1312,24 @@ public class NsdService extends INsdManager.Stub {
|
||||
MDNS_ADVERTISER_VERSION, false /* defaultEnabled */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type allowlist flag value.
|
||||
* @see #MDNS_TYPE_ALLOWLIST_FLAGS
|
||||
*/
|
||||
@Nullable
|
||||
public String getTypeAllowlistFlags() {
|
||||
return DeviceConfigUtils.getDeviceConfigProperty(NAMESPACE_TETHERING,
|
||||
MDNS_TYPE_ALLOWLIST_FLAGS, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DeviceConfigUtils#isFeatureEnabled(Context, String, String, String, boolean)
|
||||
*/
|
||||
public boolean isFeatureEnabled(Context context, String feature) {
|
||||
return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_TETHERING,
|
||||
feature, DeviceConfigUtils.TETHERING_MODULE_NAME, false /* defaultEnabled */);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see MdnsDiscoveryManager
|
||||
*/
|
||||
@@ -1305,6 +1355,41 @@ public class NsdService extends INsdManager.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether a type is allowlisted to use the Java backend.
|
||||
* @param type The service type
|
||||
* @param flagPrefix One of {@link #MDNS_ADVERTISER_ALLOWLIST_FLAG_PREFIX} or
|
||||
* {@link #MDNS_DISCOVERY_MANAGER_ALLOWLIST_FLAG_PREFIX}.
|
||||
*/
|
||||
private boolean isTypeAllowlistedForJavaBackend(@Nullable String type,
|
||||
@NonNull String flagPrefix) {
|
||||
if (type == null) return false;
|
||||
final String typesConfig = mDeps.getTypeAllowlistFlags();
|
||||
if (TextUtils.isEmpty(typesConfig)) return false;
|
||||
|
||||
final String mappingPrefix = type + ":";
|
||||
String mappedFlag = null;
|
||||
for (String mapping : TextUtils.split(typesConfig, ",")) {
|
||||
if (mapping.startsWith(mappingPrefix)) {
|
||||
mappedFlag = mapping.substring(mappingPrefix.length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mappedFlag == null) return false;
|
||||
|
||||
return mDeps.isFeatureEnabled(mContext,
|
||||
flagPrefix + mappedFlag + MDNS_ALLOWLIST_FLAG_SUFFIX);
|
||||
}
|
||||
|
||||
private boolean useDiscoveryManagerForType(@Nullable String type) {
|
||||
return isTypeAllowlistedForJavaBackend(type, MDNS_DISCOVERY_MANAGER_ALLOWLIST_FLAG_PREFIX);
|
||||
}
|
||||
|
||||
private boolean useAdvertiserForType(@Nullable String type) {
|
||||
return isTypeAllowlistedForJavaBackend(type, MDNS_ADVERTISER_ALLOWLIST_FLAG_PREFIX);
|
||||
}
|
||||
|
||||
public static NsdService create(Context context) {
|
||||
HandlerThread thread = new HandlerThread(TAG);
|
||||
thread.start();
|
||||
|
||||
@@ -1056,6 +1056,54 @@ public class NsdServiceTest {
|
||||
verify(mAdvertiser).removeService(serviceIdCaptor.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTypeSpecificFeatureFlagging() {
|
||||
doReturn("_type1._tcp:flag1,_type2._tcp:flag2").when(mDeps).getTypeAllowlistFlags();
|
||||
doReturn(true).when(mDeps).isFeatureEnabled(any(),
|
||||
eq("mdns_discovery_manager_allowlist_flag1_version"));
|
||||
doReturn(true).when(mDeps).isFeatureEnabled(any(),
|
||||
eq("mdns_advertiser_allowlist_flag2_version"));
|
||||
|
||||
final NsdManager client = connectClient(mService);
|
||||
final NsdServiceInfo service1 = new NsdServiceInfo(SERVICE_NAME, "_type1._tcp");
|
||||
service1.setHostAddresses(List.of(parseNumericAddress("2001:db8::123")));
|
||||
service1.setPort(1234);
|
||||
final NsdServiceInfo service2 = new NsdServiceInfo(SERVICE_NAME, "_type2._tcp");
|
||||
service2.setHostAddresses(List.of(parseNumericAddress("2001:db8::123")));
|
||||
service2.setPort(1234);
|
||||
|
||||
client.discoverServices(service1.getServiceType(),
|
||||
NsdManager.PROTOCOL_DNS_SD, mock(DiscoveryListener.class));
|
||||
client.discoverServices(service2.getServiceType(),
|
||||
NsdManager.PROTOCOL_DNS_SD, mock(DiscoveryListener.class));
|
||||
waitForIdle();
|
||||
|
||||
// The DiscoveryManager is enabled for _type1 but not _type2
|
||||
verify(mDiscoveryManager).registerListener(eq("_type1._tcp.local"), any(), any());
|
||||
verify(mDiscoveryManager, never()).registerListener(
|
||||
eq("_type2._tcp.local"), any(), any());
|
||||
|
||||
client.resolveService(service1, mock(ResolveListener.class));
|
||||
client.resolveService(service2, mock(ResolveListener.class));
|
||||
waitForIdle();
|
||||
|
||||
// Same behavior for resolve
|
||||
verify(mDiscoveryManager, times(2)).registerListener(
|
||||
eq("_type1._tcp.local"), any(), any());
|
||||
verify(mDiscoveryManager, never()).registerListener(
|
||||
eq("_type2._tcp.local"), any(), any());
|
||||
|
||||
client.registerService(service1, NsdManager.PROTOCOL_DNS_SD,
|
||||
mock(RegistrationListener.class));
|
||||
client.registerService(service2, NsdManager.PROTOCOL_DNS_SD,
|
||||
mock(RegistrationListener.class));
|
||||
waitForIdle();
|
||||
|
||||
// The advertiser is enabled for _type2 but not _type1
|
||||
verify(mAdvertiser, never()).addService(anyInt(), argThat(info -> matches(info, service1)));
|
||||
verify(mAdvertiser).addService(anyInt(), argThat(info -> matches(info, service2)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAdvertiseWithMdnsAdvertiser() {
|
||||
setMdnsAdvertiserEnabled();
|
||||
|
||||
Reference in New Issue
Block a user