Provide offload service information update from DiscoveryManager
With this change, the OffloadEngine can receive updates when offload service information changes from DiscoveryManager. This allows the OffloadEngine to maintain offload services and to adjust its behavior accordingly. Bug: 410734687 Test: atest ConnectivityCoverageTests Flag: com.android.tethering.mainline.beta.nsd_selective_mdns_response_offload Change-Id: I6c6ba4e76b4a2a94cbfef37bec9d6f87357bec5f
This commit is contained in:
parent
6b09ae0ace
commit
f1ae69a950
9 changed files with 198 additions and 46 deletions
|
|
@ -27,4 +27,11 @@ flag {
|
|||
namespace: "com_android_tethering"
|
||||
description: "The flag enables the Tethering and WI-Fi P2p Group Owner mode local network agent."
|
||||
bug: "420590461"
|
||||
}
|
||||
|
||||
flag {
|
||||
name: "nsd_selective_mdns_response_offload"
|
||||
namespace: "com_android_tethering"
|
||||
description: "A flag to control whether the selective mDNS response offload should be enabled."
|
||||
bug: "410734687"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ import static com.android.server.connectivity.mdns.MdnsRecord.MAX_LABEL_LENGTH;
|
|||
import static com.android.server.connectivity.mdns.MdnsSearchOptions.AGGRESSIVE_QUERY_MODE;
|
||||
import static com.android.server.connectivity.mdns.MdnsSearchOptions.PASSIVE_QUERY_MODE;
|
||||
import static com.android.server.connectivity.mdns.util.MdnsUtils.Clock;
|
||||
import static com.android.server.connectivity.mdns.util.MdnsUtils.createOffloadServiceInfoFromFilterReplies;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
|
|
@ -116,6 +117,7 @@ import com.android.server.connectivity.mdns.MdnsServiceTypeClient.FilterRepliesI
|
|||
import com.android.server.connectivity.mdns.MdnsSocketProvider;
|
||||
import com.android.server.connectivity.mdns.OffloadCallback;
|
||||
import com.android.server.connectivity.mdns.util.MdnsUtils;
|
||||
import com.android.tethering.mainline.beta.Flags;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
|
|
@ -1991,6 +1993,8 @@ public class NsdService extends INsdManager.Stub {
|
|||
mContext, MdnsFeatureFlags.NSD_CACHE_FLUSH_PER_ADDRESS_TYPE))
|
||||
.setIsIgnoreTemporaryIPv6AddressesEnabled(mDeps.isTetheringFeatureNotChickenedOut(
|
||||
mContext, MdnsFeatureFlags.NSD_IGNORE_TEMPORARY_IPV6_ADDRESSES))
|
||||
.setIsSelectiveMdnsResponseOffloadEnabled(mDeps.isAconfigFlagEnabled(
|
||||
Flags.FLAG_NSD_SELECTIVE_MDNS_RESPONSE_OFFLOAD))
|
||||
.setOverrideProvider(new MdnsFeatureFlags.FlagOverrideProvider() {
|
||||
@Override
|
||||
public boolean isForceEnabledForTest(@NonNull String flag) {
|
||||
|
|
@ -2006,16 +2010,17 @@ public class NsdService extends INsdManager.Stub {
|
|||
}
|
||||
})
|
||||
.build();
|
||||
final MdnsOffloadCallback offloadCallback = new MdnsOffloadCallback();
|
||||
mMdnsSocketClient =
|
||||
new MdnsMultinetworkSocketClient(handler.getLooper(), mMdnsSocketProvider,
|
||||
LOGGER.forSubComponent("MdnsMultinetworkSocketClient"), mMdnsFeatureFlags);
|
||||
mMdnsDiscoveryManager = deps.makeMdnsDiscoveryManager(new ExecutorProvider(),
|
||||
mMdnsSocketClient, LOGGER.forSubComponent("MdnsDiscoveryManager"),
|
||||
mMdnsFeatureFlags);
|
||||
mMdnsFeatureFlags, offloadCallback);
|
||||
handler.post(() -> mMdnsSocketClient.setCallback(mMdnsDiscoveryManager));
|
||||
mAdvertiser = deps.makeMdnsAdvertiser(handler.getLooper(), mMdnsSocketProvider,
|
||||
new AdvertiserCallback(), LOGGER.forSubComponent("MdnsAdvertiser"),
|
||||
mMdnsFeatureFlags, mContext, new MdnsOffloadCallback());
|
||||
mMdnsFeatureFlags, mContext, offloadCallback);
|
||||
mClock = deps.makeClock();
|
||||
}
|
||||
|
||||
|
|
@ -2070,6 +2075,15 @@ public class NsdService extends INsdManager.Stub {
|
|||
return DeviceConfigUtils.isTetheringFeatureNotChickenedOut(context, feature);
|
||||
}
|
||||
|
||||
/** Get whether a feature config is enabled. */
|
||||
public boolean isAconfigFlagEnabled(String feature) {
|
||||
return switch (feature) {
|
||||
case Flags.FLAG_NSD_SELECTIVE_MDNS_RESPONSE_OFFLOAD ->
|
||||
Flags.nsdSelectiveMdnsResponseOffload();
|
||||
default -> throw new IllegalStateException("Unknown flag " + feature);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DeviceConfigUtils#getDeviceConfigPropertyInt
|
||||
*/
|
||||
|
|
@ -2084,9 +2098,9 @@ public class NsdService extends INsdManager.Stub {
|
|||
public MdnsDiscoveryManager makeMdnsDiscoveryManager(
|
||||
@NonNull ExecutorProvider executorProvider,
|
||||
@NonNull MdnsMultinetworkSocketClient socketClient, @NonNull SharedLog sharedLog,
|
||||
@NonNull MdnsFeatureFlags featureFlags) {
|
||||
@NonNull MdnsFeatureFlags featureFlags, @NonNull OffloadCallback cb) {
|
||||
return new MdnsDiscoveryManager(
|
||||
executorProvider, socketClient, sharedLog, featureFlags);
|
||||
executorProvider, socketClient, sharedLog, featureFlags, cb);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -2224,27 +2238,6 @@ public class NsdService extends INsdManager.Stub {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link OffloadServiceInfo} object from a {@link FilterRepliesInfo} instance.
|
||||
* This method facilitates the conversion of filtering criteria into a service information
|
||||
* object suitable for offloading mechanisms.
|
||||
*
|
||||
* @param info The {@link FilterRepliesInfo} containing the filtering criteria.
|
||||
* @return A new {@link OffloadServiceInfo} instance populated with data from the
|
||||
* {@code FilterRepliesInfo}.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static OffloadServiceInfo createOffloadServiceInfoFromFilterReplies(
|
||||
@NonNull FilterRepliesInfo info) {
|
||||
return new OffloadServiceInfo(
|
||||
new OffloadServiceInfo.Key(info.serviceName, info.serviceType),
|
||||
new ArrayList<>(info.subtypes),
|
||||
info.hostname,
|
||||
null /* offloadPayload */,
|
||||
0 /* priority */,
|
||||
OffloadEngine.OFFLOAD_TYPE_FILTER_REPLIES);
|
||||
}
|
||||
|
||||
private void sendAllOffloadServiceInfos(@NonNull OffloadEngineInfo offloadEngineInfo) {
|
||||
final String targetInterface = offloadEngineInfo.mInterfaceName;
|
||||
final IOffloadEngine offloadEngine = offloadEngineInfo.mOffloadEngine;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
|||
@NonNull private final PerSocketServiceTypeClients perSocketServiceTypeClients;
|
||||
@NonNull private final DiscoveryExecutor discoveryExecutor;
|
||||
@NonNull private final MdnsFeatureFlags mdnsFeatureFlags;
|
||||
@NonNull private final OffloadCallback offloadCallback;
|
||||
|
||||
// Only accessed on the handler thread, initialized before first use
|
||||
@Nullable
|
||||
|
|
@ -131,13 +132,15 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
|||
|
||||
public MdnsDiscoveryManager(@NonNull ExecutorProvider executorProvider,
|
||||
@NonNull MdnsSocketClientBase socketClient, @NonNull SharedLog sharedLog,
|
||||
@NonNull MdnsFeatureFlags mdnsFeatureFlags) {
|
||||
@NonNull MdnsFeatureFlags mdnsFeatureFlags,
|
||||
@NonNull OffloadCallback offloadCallback) {
|
||||
this.executorProvider = executorProvider;
|
||||
this.socketClient = socketClient;
|
||||
this.sharedLog = sharedLog;
|
||||
this.perSocketServiceTypeClients = new PerSocketServiceTypeClients();
|
||||
this.mdnsFeatureFlags = mdnsFeatureFlags;
|
||||
this.discoveryExecutor = new DiscoveryExecutor(socketClient.getLooper(), mdnsFeatureFlags);
|
||||
this.offloadCallback = offloadCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -387,7 +390,8 @@ public class MdnsDiscoveryManager implements MdnsSocketClientBase.Callback {
|
|||
return new MdnsServiceTypeClient(
|
||||
serviceType, socketClient,
|
||||
executorProvider.newServiceTypeClientSchedulerExecutor(), socketKey,
|
||||
sharedLog.forSubComponent(tag), looper, serviceCache, mdnsFeatureFlags);
|
||||
sharedLog.forSubComponent(tag), looper, serviceCache, mdnsFeatureFlags,
|
||||
offloadCallback);
|
||||
}
|
||||
|
||||
private List<MdnsServiceTypeClient> getMdnsServiceTypeClientByInterfaceName(
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ package com.android.server.connectivity.mdns;
|
|||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Build;
|
||||
|
||||
import androidx.annotation.ChecksSdkIntAtLeast;
|
||||
|
||||
/**
|
||||
* The class that contains mDNS feature flags;
|
||||
|
|
@ -180,6 +183,11 @@ public class MdnsFeatureFlags {
|
|||
// Flag for ignoring temporary IPv6 addresses in advertising
|
||||
public final boolean mIsIgnoreTemporaryIPv6AddressesEnabled;
|
||||
|
||||
// Flag for selective mDns response offload
|
||||
// This feature can only be enabled if the OffloadServiceInfo system API is available
|
||||
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.TIRAMISU)
|
||||
public final boolean mIsSelectiveMdnsResponseOffloadEnabled;
|
||||
|
||||
// Thread stats tag for MdnsSocketClient
|
||||
public final int mMdnsSocketThreadStatsTag;
|
||||
|
||||
|
|
@ -319,6 +327,7 @@ public class MdnsFeatureFlags {
|
|||
boolean isCacheFlushPerAddressTypeEnabled,
|
||||
boolean isOptimizedExpiredServiceRemovalEnabled,
|
||||
boolean isIgnoreTemporaryIPv6AddressesEnabled,
|
||||
boolean isSelectiveMdnsResponseOffloadEnabled,
|
||||
int mdnsSocketThreadStatsTag,
|
||||
@Nullable FlagOverrideProvider overrideProvider) {
|
||||
mIsMdnsOffloadFeatureEnabled = isOffloadFeatureEnabled;
|
||||
|
|
@ -339,6 +348,7 @@ public class MdnsFeatureFlags {
|
|||
mIsOptimizedExpiredServiceRemovalEnabled = isOptimizedExpiredServiceRemovalEnabled;
|
||||
mMdnsSocketThreadStatsTag = mdnsSocketThreadStatsTag;
|
||||
mIsIgnoreTemporaryIPv6AddressesEnabled = isIgnoreTemporaryIPv6AddressesEnabled;
|
||||
mIsSelectiveMdnsResponseOffloadEnabled = isSelectiveMdnsResponseOffloadEnabled;
|
||||
mOverrideProvider = overrideProvider;
|
||||
}
|
||||
|
||||
|
|
@ -368,6 +378,7 @@ public class MdnsFeatureFlags {
|
|||
private boolean mIsCacheFlushPerAddressTypeEnabled;
|
||||
private boolean mIsOptimizedExpiredServiceRemovalEnabled;
|
||||
private boolean mIsIgnoreTemporaryIPv6AddressesEnabled;
|
||||
private boolean mIsSelectiveMdnsResponseOffloadEnabled;
|
||||
private int mMdnsSocketThreadStatsTag;
|
||||
private FlagOverrideProvider mOverrideProvider;
|
||||
|
||||
|
|
@ -392,6 +403,7 @@ public class MdnsFeatureFlags {
|
|||
mIsCacheFlushPerAddressTypeEnabled = true; // Default enabled.
|
||||
mIsOptimizedExpiredServiceRemovalEnabled = false;
|
||||
mIsIgnoreTemporaryIPv6AddressesEnabled = true; // Default enabled.
|
||||
mIsSelectiveMdnsResponseOffloadEnabled = false;
|
||||
mMdnsSocketThreadStatsTag = MDNS_SOCKET_THREAD_STATS_TAG_NONE;
|
||||
mOverrideProvider = null;
|
||||
}
|
||||
|
|
@ -588,6 +600,17 @@ public class MdnsFeatureFlags {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the selective mDns response offload is enabled.
|
||||
*
|
||||
* @see #NSD_SELECTIVE_MDNS_RESPONSE_OFFLOAD
|
||||
*/
|
||||
public Builder setIsSelectiveMdnsResponseOffloadEnabled(
|
||||
boolean isSelectiveMdnsResponseOffloadEnabled) {
|
||||
mIsSelectiveMdnsResponseOffloadEnabled = isSelectiveMdnsResponseOffloadEnabled;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a {@link MdnsFeatureFlags} with the arguments supplied to this builder.
|
||||
*/
|
||||
|
|
@ -609,6 +632,7 @@ public class MdnsFeatureFlags {
|
|||
mIsCacheFlushPerAddressTypeEnabled,
|
||||
mIsOptimizedExpiredServiceRemovalEnabled,
|
||||
mIsIgnoreTemporaryIPv6AddressesEnabled,
|
||||
mIsSelectiveMdnsResponseOffloadEnabled,
|
||||
mMdnsSocketThreadStatsTag,
|
||||
mOverrideProvider);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import static com.android.server.connectivity.mdns.MdnsServiceCache.findMatchedR
|
|||
import static com.android.server.connectivity.mdns.MdnsQueryScheduler.ScheduledQueryTaskArgs;
|
||||
import static com.android.server.connectivity.mdns.util.MdnsUtils.Clock;
|
||||
import static com.android.server.connectivity.mdns.util.MdnsUtils.buildMdnsServiceInfoFromResponse;
|
||||
import static com.android.server.connectivity.mdns.util.MdnsUtils.createOffloadServiceInfoFromFilterReplies;
|
||||
import static com.android.server.connectivity.mdns.util.MdnsUtils.responseMatchesInstanceNameAndSubtypes;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
|
|
@ -97,6 +98,7 @@ public class MdnsServiceTypeClient {
|
|||
}
|
||||
};
|
||||
@NonNull private final MdnsFeatureFlags featureFlags;
|
||||
@NonNull private final OffloadCallback offloadCallback;
|
||||
private final ArrayMap<MdnsServiceBrowserListener, ListenerInfo> listeners =
|
||||
new ArrayMap<>();
|
||||
/**
|
||||
|
|
@ -444,9 +446,10 @@ public class MdnsServiceTypeClient {
|
|||
@NonNull SharedLog sharedLog,
|
||||
@NonNull Looper looper,
|
||||
@NonNull MdnsServiceCache serviceCache,
|
||||
@NonNull MdnsFeatureFlags featureFlags) {
|
||||
@NonNull MdnsFeatureFlags featureFlags,
|
||||
@NonNull OffloadCallback offloadCallback) {
|
||||
this(serviceType, socketClient, executor, new Clock(), socketKey, sharedLog, looper,
|
||||
new Dependencies(), serviceCache, featureFlags);
|
||||
new Dependencies(), serviceCache, featureFlags, offloadCallback);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
|
@ -460,7 +463,8 @@ public class MdnsServiceTypeClient {
|
|||
@NonNull Looper looper,
|
||||
@NonNull Dependencies dependencies,
|
||||
@NonNull MdnsServiceCache serviceCache,
|
||||
@NonNull MdnsFeatureFlags featureFlags) {
|
||||
@NonNull MdnsFeatureFlags featureFlags,
|
||||
@NonNull OffloadCallback offloadCallback) {
|
||||
this.serviceType = serviceType;
|
||||
this.socketClient = socketClient;
|
||||
this.executor = executor;
|
||||
|
|
@ -477,6 +481,7 @@ public class MdnsServiceTypeClient {
|
|||
this.featureFlags = featureFlags;
|
||||
this.scheduler = featureFlags.isAccurateDelayCallbackEnabled()
|
||||
? dependencies.createScheduler(handler) : null;
|
||||
this.offloadCallback = offloadCallback;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -535,10 +540,22 @@ public class MdnsServiceTypeClient {
|
|||
combinedInfo = getDiscoveryFilterRepliesInfo();
|
||||
}
|
||||
|
||||
final FilterRepliesInfo oldInfo = offloadInfo.get(serviceName);
|
||||
if (combinedInfo == null) {
|
||||
offloadInfo.remove(serviceName);
|
||||
if (featureFlags.mIsSelectiveMdnsResponseOffloadEnabled && oldInfo != null) {
|
||||
offloadCallback.onOffloadStop(
|
||||
socketKey.getInterfaceName(),
|
||||
createOffloadServiceInfoFromFilterReplies(oldInfo));
|
||||
}
|
||||
} else {
|
||||
offloadInfo.put(serviceName, combinedInfo);
|
||||
if (featureFlags.mIsSelectiveMdnsResponseOffloadEnabled
|
||||
&& (oldInfo == null || !oldInfo.equals(combinedInfo))) {
|
||||
offloadCallback.onOffloadStartOrUpdate(
|
||||
socketKey.getInterfaceName(),
|
||||
createOffloadServiceInfoFromFilterReplies(combinedInfo));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,10 @@ import static com.android.server.connectivity.mdns.MdnsConstants.FLAG_TRUNCATED;
|
|||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresApi;
|
||||
import android.net.Network;
|
||||
import android.net.nsd.OffloadEngine;
|
||||
import android.net.nsd.OffloadServiceInfo;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import android.util.ArraySet;
|
||||
|
|
@ -37,6 +40,7 @@ import com.android.server.connectivity.mdns.MdnsPacketWriter;
|
|||
import com.android.server.connectivity.mdns.MdnsRecord;
|
||||
import com.android.server.connectivity.mdns.MdnsResponse;
|
||||
import com.android.server.connectivity.mdns.MdnsServiceInfo;
|
||||
import com.android.server.connectivity.mdns.MdnsServiceTypeClient;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.DatagramPacket;
|
||||
|
|
@ -393,4 +397,31 @@ public class MdnsUtils {
|
|||
MdnsConstants.SUBTYPE_PREFIX + requiredSub, actualSub)));
|
||||
return matchesInstanceName && matchesSubtype;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an {@link OffloadServiceInfo} object from a
|
||||
* {@link MdnsServiceTypeClient.FilterRepliesInfo} instance.
|
||||
*
|
||||
* This method facilitates the conversion of filtering criteria into a service information
|
||||
* object suitable for offloading mechanisms.
|
||||
*
|
||||
* @param info The {@link MdnsServiceTypeClient.FilterRepliesInfo} containing the filtering
|
||||
* criteria.
|
||||
* @return A new {@link OffloadServiceInfo} instance populated with data from the
|
||||
* {@code FilterRepliesInfo}.
|
||||
*/
|
||||
@RequiresApi(Build.VERSION_CODES.TIRAMISU)
|
||||
public static OffloadServiceInfo createOffloadServiceInfoFromFilterReplies(
|
||||
@NonNull MdnsServiceTypeClient.FilterRepliesInfo info) {
|
||||
return new OffloadServiceInfo(
|
||||
new OffloadServiceInfo.Key(info.serviceName, info.serviceType),
|
||||
new ArrayList<>(info.subtypes),
|
||||
info.hostname,
|
||||
null /* offloadPayload */,
|
||||
// Set the priority to 0 because APF will not prioritize some services. Instead, it
|
||||
// would simply allow every mDNS reply to pass through if there are too many
|
||||
// offloaded services, so there is no point in setting priorities.
|
||||
0 /* priority */,
|
||||
OffloadEngine.OFFLOAD_TYPE_FILTER_REPLIES);
|
||||
}
|
||||
}
|
||||
|
|
@ -46,8 +46,8 @@ import static com.android.server.NsdService.DEFAULT_RUNNING_APP_ACTIVE_IMPORTANC
|
|||
import static com.android.server.NsdService.MdnsListener;
|
||||
import static com.android.server.NsdService.NO_TRANSACTION;
|
||||
import static com.android.server.NsdService.checkHostname;
|
||||
import static com.android.server.NsdService.createOffloadServiceInfoFromFilterReplies;
|
||||
import static com.android.server.NsdService.parseTypeAndSubtype;
|
||||
import static com.android.server.connectivity.mdns.util.MdnsUtils.createOffloadServiceInfoFromFilterReplies;
|
||||
import static com.android.testutils.ContextUtils.mockService;
|
||||
|
||||
import static libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
|
||||
|
|
@ -249,8 +249,10 @@ public class NsdServiceTest {
|
|||
doReturn(true).when(mMockMDnsM).resolve(
|
||||
anyInt(), anyString(), anyString(), anyString(), anyInt());
|
||||
doReturn(false).when(mDeps).isMdnsDiscoveryManagerEnabled(any(Context.class));
|
||||
doReturn(mDiscoveryManager).when(mDeps)
|
||||
.makeMdnsDiscoveryManager(any(), any(), any(), any());
|
||||
doAnswer(inv -> {
|
||||
mOffloadCallback = (OffloadCallback) inv.getArguments()[4];
|
||||
return mDiscoveryManager;
|
||||
}).when(mDeps).makeMdnsDiscoveryManager(any(), any(), any(), any(), any());
|
||||
doReturn(mMulticastLock).when(mWifiManager).createMulticastLock(any());
|
||||
doReturn(mSocketProvider).when(mDeps).makeMdnsSocketProvider(any(), any(), any(), any());
|
||||
doReturn(DEFAULT_RUNNING_APP_ACTIVE_IMPORTANCE_CUTOFF).when(mDeps).getDeviceConfigInt(
|
||||
|
|
@ -2141,10 +2143,22 @@ public class NsdServiceTest {
|
|||
verify(offloadEngine).onOffloadServiceUpdated(discoveryInfo);
|
||||
}
|
||||
|
||||
private static void verifyOffloadServiceUpdatedAndRemoved(String interfaceName,
|
||||
OffloadServiceInfo info, OffloadCallback cb, OffloadEngine offloadEngine) {
|
||||
// onOffloadStartOrUpdate callback triggered. The OffloadServiceInfo update should be sent
|
||||
// to the OffloadEngine.
|
||||
cb.onOffloadStartOrUpdate(interfaceName, info);
|
||||
verify(offloadEngine).onOffloadServiceUpdated(info);
|
||||
// onOffloadStop callback triggered. The OffloadServiceInfo removal should be sent to the
|
||||
// OffloadEngine.
|
||||
cb.onOffloadStop(interfaceName, info);
|
||||
verify(offloadEngine).onOffloadServiceRemoved(info);
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
public void testRegisterOffloadEngine_OffloadServiceUpdatedAndRemoved() {
|
||||
public void testRegisterOffloadEngine_OffloadServiceUpdatedAndRemoved_Advertiser() {
|
||||
final String interfaceName = "iface";
|
||||
final OffloadServiceInfo info = new OffloadServiceInfo(
|
||||
new OffloadServiceInfo.Key("_testService", "_testType"), List.of("_sub1", "_sub2"),
|
||||
|
|
@ -2157,14 +2171,29 @@ public class NsdServiceTest {
|
|||
// sent to the OffloadEngine.
|
||||
verify(mAdvertiser).getAllInterfaceOffloadServiceInfos(interfaceName);
|
||||
verify(offloadEngine, never()).onOffloadServiceUpdated(any());
|
||||
// onOffloadStartOrUpdate callback triggered. The OffloadServiceInfo update should be sent
|
||||
// to the OffloadEngine.
|
||||
mOffloadCallback.onOffloadStartOrUpdate(interfaceName, info);
|
||||
verify(offloadEngine).onOffloadServiceUpdated(info);
|
||||
// onOffloadStop callback triggered. The OffloadServiceInfo removal should be sent to the
|
||||
// OffloadEngine.
|
||||
mOffloadCallback.onOffloadStop(interfaceName, info);
|
||||
verify(offloadEngine).onOffloadServiceRemoved(info);
|
||||
verifyOffloadServiceUpdatedAndRemoved(
|
||||
interfaceName, info, mOffloadCallback, offloadEngine);
|
||||
}
|
||||
|
||||
@Test
|
||||
@EnableCompatChanges(ENABLE_PLATFORM_MDNS_BACKEND)
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
|
||||
public void testRegisterOffloadEngine_OffloadServiceUpdatedAndRemoved_DiscoveryManager() {
|
||||
final String interfaceName = "iface";
|
||||
final OffloadServiceInfo info = new OffloadServiceInfo(
|
||||
new OffloadServiceInfo.Key("", "_testType"), List.of("_sub1", "_sub2"),
|
||||
"Android.local", new byte[]{0x1, 0x2, 0x3}, 1 /* priority */,
|
||||
OFFLOAD_TYPE_FILTER_REPLIES);
|
||||
doReturn(Collections.emptyList()).when(mDiscoveryManager)
|
||||
.notifyOffloadStart(eq(interfaceName));
|
||||
final OffloadEngine offloadEngine = registerOffloadEngine(interfaceName);
|
||||
// Verify that the OffloadServiceInfo retrieves from the DiscoveryManager and that no info
|
||||
// is sent to the OffloadEngine.
|
||||
verify(mDiscoveryManager).notifyOffloadStart(eq(interfaceName));
|
||||
verify(offloadEngine, never()).onOffloadServiceUpdated(any());
|
||||
|
||||
verifyOffloadServiceUpdatedAndRemoved(
|
||||
interfaceName, info, mOffloadCallback, offloadEngine);
|
||||
}
|
||||
|
||||
private void waitForIdle() {
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ public class MdnsDiscoveryManagerTests {
|
|||
@Mock MdnsServiceBrowserListener mockListenerTwo;
|
||||
@Mock SharedLog sharedLog;
|
||||
@Mock MdnsServiceCache mockServiceCache;
|
||||
@Mock OffloadCallback mockCallback;
|
||||
private MdnsDiscoveryManager discoveryManager;
|
||||
private HandlerThread thread;
|
||||
private Handler handler;
|
||||
|
|
@ -117,7 +118,7 @@ public class MdnsDiscoveryManagerTests {
|
|||
doReturn(true).when(socketClient).supportsRequestingSpecificNetworks();
|
||||
createdServiceTypeClientCount = 0;
|
||||
discoveryManager = new MdnsDiscoveryManager(executorProvider, socketClient,
|
||||
sharedLog, MdnsFeatureFlags.newBuilder().build()) {
|
||||
sharedLog, MdnsFeatureFlags.newBuilder().build(), mockCallback) {
|
||||
@Override
|
||||
MdnsServiceTypeClient createServiceTypeClient(@NonNull String serviceType,
|
||||
@NonNull SocketKey socketKey) {
|
||||
|
|
@ -157,7 +158,8 @@ public class MdnsDiscoveryManagerTests {
|
|||
}
|
||||
|
||||
private MdnsDiscoveryManager makeDiscoveryManager(@NonNull MdnsFeatureFlags featureFlags) {
|
||||
return new MdnsDiscoveryManager(executorProvider, socketClient, sharedLog, featureFlags) {
|
||||
return new MdnsDiscoveryManager(executorProvider, socketClient, sharedLog, featureFlags,
|
||||
mockCallback) {
|
||||
@Override
|
||||
MdnsServiceTypeClient createServiceTypeClient(@NonNull String serviceType,
|
||||
@NonNull SocketKey socketKey) {
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import static com.android.server.connectivity.mdns.MdnsServiceTypeClient.EVENT_S
|
|||
import static com.android.server.connectivity.mdns.MdnsServiceTypeClient.NO_HOSTNAME;
|
||||
import static com.android.server.connectivity.mdns.MdnsServiceTypeClient.REMOVE_SERVICE_AFTER_QUERY_SENT_TIME;
|
||||
import static com.android.server.connectivity.mdns.MdnsServiceTypeClient.SERVICE_NAME_DISCOVERY;
|
||||
import static com.android.server.connectivity.mdns.util.MdnsUtils.createOffloadServiceInfoFromFilterReplies;
|
||||
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
|
@ -58,6 +59,7 @@ import android.annotation.NonNull;
|
|||
import android.annotation.Nullable;
|
||||
import android.net.InetAddresses;
|
||||
import android.net.Network;
|
||||
import android.net.nsd.OffloadServiceInfo;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
|
|
@ -138,6 +140,8 @@ public class MdnsServiceTypeClientTests {
|
|||
private MdnsServiceTypeClient.Dependencies mockDeps;
|
||||
@Mock
|
||||
private Scheduler mockScheduler;
|
||||
@Mock
|
||||
private OffloadCallback mockCallback;
|
||||
@Captor
|
||||
private ArgumentCaptor<MdnsServiceInfo> serviceInfoCaptor;
|
||||
|
||||
|
|
@ -277,7 +281,7 @@ public class MdnsServiceTypeClientTests {
|
|||
private MdnsServiceTypeClient makeMdnsServiceTypeClient(MdnsFeatureFlags featureFlags) {
|
||||
return new MdnsServiceTypeClient(SERVICE_TYPE, mockSocketClient, currentThreadExecutor,
|
||||
mockDecoderClock, socketKey, mockSharedLog, thread.getLooper(), mockDeps,
|
||||
serviceCache, featureFlags);
|
||||
serviceCache, featureFlags, mockCallback);
|
||||
}
|
||||
|
||||
@After
|
||||
|
|
@ -2357,7 +2361,7 @@ public class MdnsServiceTypeClientTests {
|
|||
final FilterRepliesInfo resolveInfo = new FilterRepliesInfo(
|
||||
instanceName, SERVICE_TYPE, List.of(), "hostname");
|
||||
final FilterRepliesInfo discoverInfo = new FilterRepliesInfo(
|
||||
SERVICE_NAME_DISCOVERY, SERVICE_TYPE, List.of(subtype), "" /* hostname */);
|
||||
SERVICE_NAME_DISCOVERY, SERVICE_TYPE, List.of(subtype), NO_HOSTNAME);
|
||||
assertTrue(offloadInfo.containsAll(Set.of(resolveInfo, discoverInfo)));
|
||||
|
||||
// Stop the resolution listener
|
||||
|
|
@ -2423,6 +2427,47 @@ public class MdnsServiceTypeClientTests {
|
|||
SERVICE_NAME_DISCOVERY, SERVICE_TYPE, List.of(subtype2), NO_HOSTNAME)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOffloadServiceInfoUpdate() {
|
||||
final MdnsFeatureFlags flags = MdnsFeatureFlags.newBuilder()
|
||||
.setIsSelectiveMdnsResponseOffloadEnabled(true).build();
|
||||
client = makeMdnsServiceTypeClient(flags);
|
||||
final String instanceName = "instance1";
|
||||
final String subtype = "subtype";
|
||||
final MdnsSearchOptions resolveOptions = MdnsSearchOptions.newBuilder()
|
||||
.setResolveInstanceName(instanceName).build();
|
||||
final MdnsSearchOptions discoverOptions = MdnsSearchOptions.newBuilder()
|
||||
.addSubtype(subtype).build();
|
||||
// Register two listener, one is for service resolution and one is for service discovery.
|
||||
startSendAndReceive(mockListenerOne, resolveOptions);
|
||||
startSendAndReceive(mockListenerTwo, discoverOptions);
|
||||
|
||||
final OffloadServiceInfo resolveInfo1 = createOffloadServiceInfoFromFilterReplies(
|
||||
new FilterRepliesInfo(
|
||||
instanceName, SERVICE_TYPE, List.of(), NO_HOSTNAME));
|
||||
verify(mockCallback).onOffloadStartOrUpdate(socketKey.getInterfaceName(), resolveInfo1);
|
||||
final OffloadServiceInfo discoverInfo = createOffloadServiceInfoFromFilterReplies(
|
||||
new FilterRepliesInfo(
|
||||
SERVICE_NAME_DISCOVERY, SERVICE_TYPE, List.of(subtype), NO_HOSTNAME));
|
||||
verify(mockCallback).onOffloadStartOrUpdate(socketKey.getInterfaceName(), discoverInfo);
|
||||
|
||||
// Get a service response
|
||||
processResponse(createResponse(instanceName, "192.0.2.0", 5353,
|
||||
MdnsUtils.constructFullSubtype(SERVICE_TYPE_LABELS, SUBTYPE),
|
||||
Collections.emptyMap() /* textAttributes */, TEST_TTL), socketKey);
|
||||
|
||||
final OffloadServiceInfo resolveInfo2 = createOffloadServiceInfoFromFilterReplies(
|
||||
new FilterRepliesInfo(
|
||||
instanceName, SERVICE_TYPE, List.of(), "hostname"));
|
||||
verify(mockCallback).onOffloadStartOrUpdate(socketKey.getInterfaceName(), resolveInfo2);
|
||||
|
||||
stopSendAndReceive(mockListenerOne);
|
||||
verify(mockCallback).onOffloadStop(socketKey.getInterfaceName(), resolveInfo2);
|
||||
|
||||
stopSendAndReceive(mockListenerTwo);
|
||||
verify(mockCallback).onOffloadStop(socketKey.getInterfaceName(), discoverInfo);
|
||||
}
|
||||
|
||||
private static MdnsServiceInfo matchServiceName(String name) {
|
||||
return argThat(info -> info.getServiceInstanceName().equals(name));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue