Exclude Google Cast app subtypes from mDNS offload

This commit excludes Google Cast app subtypes from mDNS offloading. The
large number of subtypes would consume excessive firmware resources if
offloaded.

Test: TH
Change-Id: I562a94187dc5c710ca37d4997e9ed6c1602918b6
This commit is contained in:
Yuyang Huang 2025-02-06 23:01:00 +09:00
commit 9cb8a29436
2 changed files with 68 additions and 1 deletions

View file

@ -1007,6 +1007,19 @@ public class MdnsAdvertiser {
});
}
private List<String> getOffloadSubtype(@NonNull NsdServiceInfo nsdServiceInfo) {
// Workaround: Google Cast doesn't announce subtypes per DNS-SD/mDNS spec.
// Thus, subtypes aren't offloaded; only "_googlecast._tcp" is.
// Subtype responses occur when hardware offload is off.
// This solution works because Google Cast doesn't follow the intended usage of subtypes in
// the spec, as it always discovers for both the subtype+base type, and only uses the mDNS
// subtype as an optimization.
if (nsdServiceInfo.getServiceType().equals("_googlecast._tcp")) {
return new ArrayList<>();
}
return new ArrayList<>(nsdServiceInfo.getSubtypes());
}
private OffloadServiceInfoWrapper createOffloadService(int serviceId,
@NonNull Registration registration, byte[] rawOffloadPacket) {
final NsdServiceInfo nsdServiceInfo = registration.getServiceInfo();
@ -1017,7 +1030,7 @@ public class MdnsAdvertiser {
final OffloadServiceInfo offloadServiceInfo = new OffloadServiceInfo(
new OffloadServiceInfo.Key(nsdServiceInfo.getServiceName(),
nsdServiceInfo.getServiceType()),
new ArrayList<>(nsdServiceInfo.getSubtypes()),
getOffloadSubtype(nsdServiceInfo),
String.join(".", mDeviceHostName),
rawOffloadPacket,
priority,

View file

@ -92,6 +92,13 @@ private val SERVICE_1 = NsdServiceInfo("TestServiceName", "_advertisertest._tcp"
network = TEST_NETWORK_1
}
private val GOOGLECAST_SERVICE = NsdServiceInfo("TestServiceName", "_googlecast._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
@ -143,6 +150,15 @@ private val OFFLOAD_SERVICEINFO = OffloadServiceInfo(
OffloadEngine.OFFLOAD_TYPE_REPLY.toLong()
)
private val OFFLOAD_SERVICE_INFO_GOOGLECAST = OffloadServiceInfo(
OffloadServiceInfo.Key("TestServiceName", "_googlecast._tcp"),
listOf(),
"Android_test.local",
TEST_OFFLOAD_PACKET1,
Int.MAX_VALUE,
OffloadEngine.OFFLOAD_TYPE_REPLY.toLong()
)
private val OFFLOAD_SERVICEINFO_NO_SUBTYPE = OffloadServiceInfo(
OffloadServiceInfo.Key("TestServiceName", "_advertisertest._tcp"),
listOf(),
@ -507,6 +523,44 @@ class MdnsAdvertiserTest {
)))
}
@Test
fun testAddService_NoSubtypeForGoogleCastOffload() {
val advertiser =
MdnsAdvertiser(thread.looper, socketProvider, cb, mockDeps, sharedlog, flags, context)
postSync {
advertiser.addOrUpdateService(
SERVICE_ID_1,
GOOGLECAST_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).onOffloadStartOrUpdate(eq(TEST_INTERFACE1), eq(OFFLOAD_SERVICE_INFO_GOOGLECAST))
}
@Test
fun testAddService_Conflicts() {
val advertiser =