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_DISCOVERY_MANAGER_EVENT;
|
||||||
import static android.net.nsd.NsdManager.MDNS_SERVICE_EVENT;
|
import static android.net.nsd.NsdManager.MDNS_SERVICE_EVENT;
|
||||||
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
|
import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY;
|
||||||
|
import static android.provider.DeviceConfig.NAMESPACE_TETHERING;
|
||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
@@ -110,6 +111,34 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
*/
|
*/
|
||||||
private static final String MDNS_ADVERTISER_VERSION = "mdns_advertiser_version";
|
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);
|
public static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
|
||||||
private static final long CLEANUP_DELAY_MS = 10000;
|
private static final long CLEANUP_DELAY_MS = 10000;
|
||||||
private static final int IFACE_IDX_ANY = 0;
|
private static final int IFACE_IDX_ANY = 0;
|
||||||
@@ -572,8 +601,9 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
|
|
||||||
final NsdServiceInfo info = args.serviceInfo;
|
final NsdServiceInfo info = args.serviceInfo;
|
||||||
id = getUniqueId();
|
id = getUniqueId();
|
||||||
if (mDeps.isMdnsDiscoveryManagerEnabled(mContext)) {
|
|
||||||
final String serviceType = constructServiceType(info.getServiceType());
|
final String serviceType = constructServiceType(info.getServiceType());
|
||||||
|
if (mDeps.isMdnsDiscoveryManagerEnabled(mContext)
|
||||||
|
|| useDiscoveryManagerForType(serviceType)) {
|
||||||
if (serviceType == null) {
|
if (serviceType == null) {
|
||||||
clientInfo.onDiscoverServicesFailed(clientId,
|
clientInfo.onDiscoverServicesFailed(clientId,
|
||||||
NsdManager.FAILURE_INTERNAL_ERROR);
|
NsdManager.FAILURE_INTERNAL_ERROR);
|
||||||
@@ -667,10 +697,11 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
id = getUniqueId();
|
id = getUniqueId();
|
||||||
if (mDeps.isMdnsAdvertiserEnabled(mContext)) {
|
|
||||||
final NsdServiceInfo serviceInfo = args.serviceInfo;
|
final NsdServiceInfo serviceInfo = args.serviceInfo;
|
||||||
final String serviceType = serviceInfo.getServiceType();
|
final String serviceType = serviceInfo.getServiceType();
|
||||||
final String registerServiceType = constructServiceType(serviceType);
|
final String registerServiceType = constructServiceType(serviceType);
|
||||||
|
if (mDeps.isMdnsAdvertiserEnabled(mContext)
|
||||||
|
|| useAdvertiserForType(registerServiceType)) {
|
||||||
if (registerServiceType == null) {
|
if (registerServiceType == null) {
|
||||||
Log.e(TAG, "Invalid service type: " + serviceType);
|
Log.e(TAG, "Invalid service type: " + serviceType);
|
||||||
clientInfo.onRegisterServiceFailed(clientId,
|
clientInfo.onRegisterServiceFailed(clientId,
|
||||||
@@ -686,7 +717,7 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
storeAdvertiserRequestMap(clientId, id, clientInfo);
|
storeAdvertiserRequestMap(clientId, id, clientInfo);
|
||||||
} else {
|
} else {
|
||||||
maybeStartDaemon();
|
maybeStartDaemon();
|
||||||
if (registerService(id, args.serviceInfo)) {
|
if (registerService(id, serviceInfo)) {
|
||||||
if (DBG) Log.d(TAG, "Register " + clientId + " " + id);
|
if (DBG) Log.d(TAG, "Register " + clientId + " " + id);
|
||||||
storeLegacyRequestMap(clientId, id, clientInfo, msg.what);
|
storeLegacyRequestMap(clientId, id, clientInfo, msg.what);
|
||||||
// Return success after mDns reports success
|
// Return success after mDns reports success
|
||||||
@@ -748,8 +779,9 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
|
|
||||||
final NsdServiceInfo info = args.serviceInfo;
|
final NsdServiceInfo info = args.serviceInfo;
|
||||||
id = getUniqueId();
|
id = getUniqueId();
|
||||||
if (mDeps.isMdnsDiscoveryManagerEnabled(mContext)) {
|
|
||||||
final String serviceType = constructServiceType(info.getServiceType());
|
final String serviceType = constructServiceType(info.getServiceType());
|
||||||
|
if (mDeps.isMdnsDiscoveryManagerEnabled(mContext)
|
||||||
|
|| useDiscoveryManagerForType(serviceType)) {
|
||||||
if (serviceType == null) {
|
if (serviceType == null) {
|
||||||
clientInfo.onResolveServiceFailed(clientId,
|
clientInfo.onResolveServiceFailed(clientId,
|
||||||
NsdManager.FAILURE_INTERNAL_ERROR);
|
NsdManager.FAILURE_INTERNAL_ERROR);
|
||||||
@@ -1280,6 +1312,24 @@ public class NsdService extends INsdManager.Stub {
|
|||||||
MDNS_ADVERTISER_VERSION, false /* defaultEnabled */);
|
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
|
* @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) {
|
public static NsdService create(Context context) {
|
||||||
HandlerThread thread = new HandlerThread(TAG);
|
HandlerThread thread = new HandlerThread(TAG);
|
||||||
thread.start();
|
thread.start();
|
||||||
|
|||||||
@@ -1056,6 +1056,54 @@ public class NsdServiceTest {
|
|||||||
verify(mAdvertiser).removeService(serviceIdCaptor.getValue());
|
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
|
@Test
|
||||||
public void testAdvertiseWithMdnsAdvertiser() {
|
public void testAdvertiseWithMdnsAdvertiser() {
|
||||||
setMdnsAdvertiserEnabled();
|
setMdnsAdvertiserEnabled();
|
||||||
|
|||||||
Reference in New Issue
Block a user