From c275a9e7efb207f1e2e2b238b19aea3541e6d78d Mon Sep 17 00:00:00 2001 From: Yuyang Huang Date: Fri, 25 Aug 2023 18:03:22 +0900 Subject: [PATCH] Send OffloadServiceInfos when registerOffloadEngine is called When the OffloadEngine is registered, it should get notice about all the currently offloaded service. Bug: 297314970 Test: atest CtsNetTestCases Change-Id: I1b977a40476a1f5c30a075b559e72656a42865ae --- .../src/com/android/server/NsdService.java | 19 +++- .../connectivity/mdns/MdnsAdvertiser.java | 21 ++++- .../net/src/android/net/cts/NsdManagerTest.kt | 87 ++++++++++++------- 3 files changed, 93 insertions(+), 34 deletions(-) diff --git a/service-t/src/com/android/server/NsdService.java b/service-t/src/com/android/server/NsdService.java index eb73ee5bea..69d5c5bcd4 100644 --- a/service-t/src/com/android/server/NsdService.java +++ b/service-t/src/com/android/server/NsdService.java @@ -1162,7 +1162,7 @@ public class NsdService extends INsdManager.Stub { // TODO: Limits the number of registrations created by a given class. mOffloadEngines.register(offloadEngineInfo.mOffloadEngine, offloadEngineInfo); - // TODO: Sends all the existing OffloadServiceInfos back. + sendAllOffloadServiceInfos(offloadEngineInfo); break; case NsdManager.UNREGISTER_OFFLOAD_ENGINE: mOffloadEngines.unregister((IOffloadEngine) msg.obj); @@ -1834,6 +1834,21 @@ public class NsdService extends INsdManager.Stub { } } + private void sendAllOffloadServiceInfos(@NonNull OffloadEngineInfo offloadEngineInfo) { + final String targetInterface = offloadEngineInfo.mInterfaceName; + final IOffloadEngine offloadEngine = offloadEngineInfo.mOffloadEngine; + final List offloadWrappers = + mAdvertiser.getAllInterfaceOffloadServiceInfos(targetInterface); + for (MdnsAdvertiser.OffloadServiceInfoWrapper wrapper : offloadWrappers) { + try { + offloadEngine.onOffloadServiceUpdated(wrapper.mOffloadServiceInfo); + } catch (RemoteException e) { + // Can happen in regular cases, do not log a stacktrace + Log.i(TAG, "Failed to send offload callback, remote died: " + e.getMessage()); + } + } + } + private void sendOffloadServiceInfosUpdate(@NonNull String targetInterfaceName, @NonNull OffloadServiceInfo offloadServiceInfo, boolean isRemove) { final int count = mOffloadEngines.beginBroadcast(); @@ -1857,7 +1872,7 @@ public class NsdService extends INsdManager.Stub { } } catch (RemoteException e) { // Can happen in regular cases, do not log a stacktrace - Log.i(TAG, "Failed to send offload callback, remote died", e); + Log.i(TAG, "Failed to send offload callback, remote died: " + e.getMessage()); } } } finally { 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 dd72d11571..f43df4545b 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsAdvertiser.java @@ -37,6 +37,7 @@ import com.android.net.module.util.SharedLog; import com.android.server.connectivity.mdns.util.MdnsUtils; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.UUID; @@ -117,6 +118,17 @@ public class MdnsAdvertiser { } } + /** + * Gets the current status of the OffloadServiceInfos per interface. + * @param interfaceName the target interfaceName + * @return the list of current offloaded services. + */ + @NonNull + public List getAllInterfaceOffloadServiceInfos( + @NonNull String interfaceName) { + return mInterfaceOffloadServices.getOrDefault(interfaceName, Collections.emptyList()); + } + private final MdnsInterfaceAdvertiser.Callback mInterfaceAdvertiserCb = new MdnsInterfaceAdvertiser.Callback() { @Override @@ -385,9 +397,12 @@ public class MdnsAdvertiser { } } - private static class OffloadServiceInfoWrapper { - private final @NonNull OffloadServiceInfo mOffloadServiceInfo; - private final int mServiceId; + /** + * The wrapper class for OffloadServiceInfo including the serviceId. + */ + public static class OffloadServiceInfoWrapper { + public final @NonNull OffloadServiceInfo mOffloadServiceInfo; + public final int mServiceId; OffloadServiceInfoWrapper(int serviceId, OffloadServiceInfo offloadServiceInfo) { mOffloadServiceInfo = offloadServiceInfo; diff --git a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt index 49a6ef1b84..508e924113 100644 --- a/tests/cts/net/src/android/net/cts/NsdManagerTest.kt +++ b/tests/cts/net/src/android/net/cts/NsdManagerTest.kt @@ -163,6 +163,7 @@ class NsdManagerTest { private val cm by lazy { context.getSystemService(ConnectivityManager::class.java)!! } private val serviceName = "NsdTest%09d".format(Random().nextInt(1_000_000_000)) + private val serviceName2 = "NsdTest%09d".format(Random().nextInt(1_000_000_000)) private val serviceType = "_nmt%09d._tcp".format(Random().nextInt(1_000_000_000)) private val handlerThread = HandlerThread(NsdManagerTest::class.java.simpleName) private val ctsNetUtils by lazy{ CtsNetUtils(context) } @@ -890,10 +891,11 @@ class NsdManagerTest { } } - fun checkOffloadServiceInfo(serviceInfo: OffloadServiceInfo) { - assertEquals(serviceName, serviceInfo.key.serviceName) - assertEquals(serviceType, serviceInfo.key.serviceType) - assertEquals(listOf("_subtype"), serviceInfo.subtypes) + fun checkOffloadServiceInfo(serviceInfo: OffloadServiceInfo, si: NsdServiceInfo) { + val expectedServiceType = si.serviceType.split(",")[0] + assertEquals(si.serviceName, serviceInfo.key.serviceName) + assertEquals(expectedServiceType, serviceInfo.key.serviceType) + assertEquals(listOf("_subtype"), serviceInfo.subtypes) assertTrue(serviceInfo.hostname.startsWith("Android_")) assertTrue(serviceInfo.hostname.endsWith("local")) assertEquals(0, serviceInfo.priority) @@ -907,36 +909,63 @@ class NsdManagerTest { // The offload callbacks are only supported with the new backend, // enabled with target SDK U+. assumeTrue(isAtLeastU() || targetSdkVersion > Build.VERSION_CODES.TIRAMISU) + + // TODO: also have a test that use an executor that runs in a different thread, and pass + // in the thread ID NsdServiceInfo to check it + val si1 = NsdServiceInfo() + si1.serviceType = "$serviceType,_subtype" + si1.serviceName = serviceName + si1.network = testNetwork1.network + si1.port = 23456 + val record1 = NsdRegistrationRecord() + + val si2 = NsdServiceInfo() + si2.serviceType = "$serviceType,_subtype" + si2.serviceName = serviceName2 + si2.network = testNetwork1.network + si2.port = 12345 + val record2 = NsdRegistrationRecord() val offloadEngine = TestNsdOffloadEngine() - runAsShell(NETWORK_SETTINGS) { - nsdManager.registerOffloadEngine(testNetwork1.iface.interfaceName, - OffloadEngine.OFFLOAD_TYPE_REPLY.toLong(), - OffloadEngine.OFFLOAD_CAPABILITY_BYPASS_MULTICAST_LOCK.toLong(), - { it.run() }, offloadEngine) - } - val si = NsdServiceInfo() - si.serviceType = "$serviceType,_subtype" - si.serviceName = serviceName - si.network = testNetwork1.network - si.port = 12345 - val record = NsdRegistrationRecord() - nsdManager.registerService(si, NsdManager.PROTOCOL_DNS_SD, record) - val addOrUpdateEvent = offloadEngine - .expectCallbackEventually { - it.info.key.serviceName == serviceName + tryTest { + // Register service before the OffloadEngine is registered. + nsdManager.registerService(si1, NsdManager.PROTOCOL_DNS_SD, record1) + record1.expectCallback() + runAsShell(NETWORK_SETTINGS) { + nsdManager.registerOffloadEngine(testNetwork1.iface.interfaceName, + OffloadEngine.OFFLOAD_TYPE_REPLY.toLong(), + OffloadEngine.OFFLOAD_CAPABILITY_BYPASS_MULTICAST_LOCK.toLong(), + { it.run() }, offloadEngine) } - checkOffloadServiceInfo(addOrUpdateEvent.info) + val addOrUpdateEvent1 = offloadEngine + .expectCallbackEventually { + it.info.key.serviceName == si1.serviceName + } + checkOffloadServiceInfo(addOrUpdateEvent1.info, si1) - nsdManager.unregisterService(record) - val unregisterEvent = offloadEngine - .expectCallbackEventually { - it.info.key.serviceName == serviceName + // Register service after OffloadEngine is registered. + nsdManager.registerService(si2, NsdManager.PROTOCOL_DNS_SD, record2) + record2.expectCallback() + val addOrUpdateEvent2 = offloadEngine + .expectCallbackEventually { + it.info.key.serviceName == si2.serviceName + } + checkOffloadServiceInfo(addOrUpdateEvent2.info, si2) + + nsdManager.unregisterService(record2) + record2.expectCallback() + val unregisterEvent = offloadEngine + .expectCallbackEventually { + it.info.key.serviceName == si2.serviceName + } + checkOffloadServiceInfo(unregisterEvent.info, si2) + } cleanupStep { + runAsShell(NETWORK_SETTINGS) { + nsdManager.unregisterOffloadEngine(offloadEngine) } - checkOffloadServiceInfo(unregisterEvent.info) - - runAsShell(NETWORK_SETTINGS) { - nsdManager.unregisterOffloadEngine(offloadEngine) + } cleanup { + nsdManager.unregisterService(record1) + record1.expectCallback() } }