From 9b0f749723483a4f0dd3b9b6ae49824d64cfc54d Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Thu, 27 Feb 2025 16:59:09 +0900 Subject: [PATCH] Add config_nsdOffloadServicesDenyList to NsdService This commit introduces the config_nsdOffloadServicesDenyList to NsdService to allow OEMs to specify services that should not be offloaded. This feature addresses potential memory limitations by enabling selective offloading, providing OEMs with greater control over resource management. Test: TH Change-Id: I846e7cfc37c3a71c50853707884cf0c0a9a6f971 --- .../connectivity/mdns/MdnsAdvertiser.java | 44 +++++++++++----- .../res/values/config.xml | 9 ++++ .../res/values/overlayable.xml | 1 + .../connectivity/mdns/MdnsAdvertiserTest.kt | 52 +++++++++++++++++++ 4 files changed, 94 insertions(+), 12 deletions(-) diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java index c3306bd3b9..bd00b706e8 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java @@ -35,6 +35,7 @@ import android.os.Build; import android.os.Looper; import android.text.TextUtils; import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Log; import android.util.SparseArray; @@ -93,6 +94,7 @@ public class MdnsAdvertiser { new ArrayMap<>(); private final MdnsFeatureFlags mMdnsFeatureFlags; private final Map mServiceTypeToOffloadPriority; + private final ArraySet mOffloadServiceTypeDenyList; /** * Dependencies for {@link MdnsAdvertiser}, useful for testing. @@ -160,6 +162,16 @@ public class MdnsAdvertiser { return mInterfaceOffloadServices.getOrDefault(interfaceName, Collections.emptyList()); } + private boolean isInOffloadDenyList(@NonNull String serviceType) { + for (int i = 0; i < mOffloadServiceTypeDenyList.size(); ++i) { + final String denyListServiceType = mOffloadServiceTypeDenyList.valueAt(i); + if (DnsUtils.equalsIgnoreDnsCase(serviceType, denyListServiceType)) { + return true; + } + } + return false; + } + private final MdnsInterfaceAdvertiser.Callback mInterfaceAdvertiserCb = new MdnsInterfaceAdvertiser.Callback() { @Override @@ -173,19 +185,25 @@ public class MdnsAdvertiser { if (mMdnsFeatureFlags.mIsMdnsOffloadFeatureEnabled // TODO: Enable offload when the serviceInfo contains a custom host. && TextUtils.isEmpty(registration.getServiceInfo().getHostname())) { - final String interfaceName = advertiser.getSocketInterfaceName(); - final List existingOffloadServiceInfoWrappers = - mInterfaceOffloadServices.computeIfAbsent(interfaceName, - k -> new ArrayList<>()); - // Remove existing offload services from cache for update. - existingOffloadServiceInfoWrappers.removeIf(item -> item.mServiceId == serviceId); + final String serviceType = registration.getServiceInfo().getServiceType(); + if (isInOffloadDenyList(serviceType)) { + mSharedLog.i("Offload denied for service type: " + serviceType); + } else { + final String interfaceName = advertiser.getSocketInterfaceName(); + final List existingOffloadServiceInfoWrappers = + mInterfaceOffloadServices.computeIfAbsent(interfaceName, + k -> new ArrayList<>()); + // Remove existing offload services from cache for update. + existingOffloadServiceInfoWrappers.removeIf( + item -> item.mServiceId == serviceId); - byte[] rawOffloadPacket = advertiser.getRawOffloadPayload(serviceId); - final OffloadServiceInfoWrapper newOffloadServiceInfoWrapper = createOffloadService( - serviceId, registration, rawOffloadPacket); - existingOffloadServiceInfoWrappers.add(newOffloadServiceInfoWrapper); - mCb.onOffloadStartOrUpdate(interfaceName, - newOffloadServiceInfoWrapper.mOffloadServiceInfo); + byte[] rawOffloadPacket = advertiser.getRawOffloadPayload(serviceId); + final OffloadServiceInfoWrapper newOffloadServiceInfoWrapper = + createOffloadService(serviceId, registration, rawOffloadPacket); + existingOffloadServiceInfoWrappers.add(newOffloadServiceInfoWrapper); + mCb.onOffloadStartOrUpdate(interfaceName, + newOffloadServiceInfoWrapper.mOffloadServiceInfo); + } } // Wait for all current interfaces to be done probing before notifying of success. @@ -846,6 +864,8 @@ public class MdnsAdvertiser { final ConnectivityResources res = new ConnectivityResources(context); mServiceTypeToOffloadPriority = parseOffloadPriorityList( res.get().getStringArray(R.array.config_nsdOffloadServicesPriority), sharedLog); + mOffloadServiceTypeDenyList = new ArraySet<>( + res.get().getStringArray(R.array.config_nsdOffloadServicesDenyList)); } private static Map parseOffloadPriorityList( diff --git a/service/ServiceConnectivityResources/res/values/config.xml b/service/ServiceConnectivityResources/res/values/config.xml index 2d3647a67f..1b0f29dcd6 100644 --- a/service/ServiceConnectivityResources/res/values/config.xml +++ b/service/ServiceConnectivityResources/res/values/config.xml @@ -135,6 +135,15 @@ + + + _googlezone._tcp + + false diff --git a/service/ServiceConnectivityResources/res/values/overlayable.xml b/service/ServiceConnectivityResources/res/values/overlayable.xml index 7ac86aacd6..5c0ba7879c 100644 --- a/service/ServiceConnectivityResources/res/values/overlayable.xml +++ b/service/ServiceConnectivityResources/res/values/overlayable.xml @@ -31,6 +31,7 @@ + diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt index e6e6ecca7c..087617ad62 100644 --- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt +++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsAdvertiserTest.kt @@ -99,6 +99,13 @@ private val GOOGLECAST_SERVICE = NsdServiceInfo("TestServiceName", "_googlecast. network = TEST_NETWORK_1 } +private val GOOGLEZONE_SERVICE = NsdServiceInfo("TestServiceName", "_GOOglezone._tcp").apply { + subtypes = setOf(TEST_SUBTYPE) + port = 12345 + hostAddresses = listOf(TEST_ADDR) + network = TEST_NETWORK_1 +} + private val SERVICE_1_SUBTYPE = NsdServiceInfo("TestServiceName", "_advertisertest._tcp").apply { subtypes = setOf(TEST_SUBTYPE) port = 12345 @@ -183,6 +190,10 @@ private val SERVICES_PRIORITY_LIST = arrayOf( "5:_otherprioritytest._tcp" ) +private val SERVICES_DENY_LIST = arrayOf( + "_googlezone._tcp", +) + @RunWith(DevSdkIgnoreRunner::class) @IgnoreUpTo(Build.VERSION_CODES.S_V2) class MdnsAdvertiserTest { @@ -247,6 +258,9 @@ class MdnsAdvertiserTest { doReturn(SERVICES_PRIORITY_LIST).`when`(resources).getStringArray( R.array.config_nsdOffloadServicesPriority ) + doReturn(SERVICES_DENY_LIST).`when`(resources).getStringArray( + R.array.config_nsdOffloadServicesDenyList + ) ConnectivityResources.setResourcesContextForTest(context) } @@ -523,6 +537,44 @@ class MdnsAdvertiserTest { ))) } + @Test + fun testAddService_NoOffloadForServiceTypeInDenyList() { + val advertiser = + MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps, sharedlog, flags, context) + postSync { + advertiser.addOrUpdateService( + SERVICE_ID_1, + GOOGLEZONE_SERVICE, + DEFAULT_ADVERTISING_OPTION, + TEST_CLIENT_UID_1 + ) + } + val socketCbCaptor = ArgumentCaptor.forClass(SocketCallback::class.java) + verify(socketProvider).requestSocket(eq(SERVICE_1.network), socketCbCaptor.capture()) + + val socketCb = socketCbCaptor.value + postSync { socketCb.onSocketCreated(TEST_SOCKETKEY_1, mockSocket1, listOf(TEST_LINKADDR)) } + + val intAdvCbCaptor1 = ArgumentCaptor.forClass(MdnsInterfaceAdvertiser.Callback::class.java) + verify(mockDeps).makeAdvertiser( + eq(mockSocket1), + eq(listOf(TEST_LINKADDR)), + eq(thread.looper), + any(), + intAdvCbCaptor1.capture(), + eq(TEST_HOSTNAME), + any(), + any() + ) + + doReturn(false).`when`(mockInterfaceAdvertiser1).isProbing(SERVICE_ID_1) + postSync { + intAdvCbCaptor1.value.onServiceProbingSucceeded(mockInterfaceAdvertiser1, SERVICE_ID_1) + } + + verify(cb, never()).onOffloadStartOrUpdate(eq(TEST_INTERFACE1), any()) + } + @Test fun testAddService_NoSubtypeForGoogleCastOffload() { val advertiser =