[Feature sync] Propagate network interface index to MdnsServiceInfo
For Matter, in addition to the InetAddress and port, we also need to know the associated NetworkInterface index. With this change, the interface index is propagated from the MdnsSocketTypeClient through to MdnsServiceInfo based on a flag (defaulting to -1 for unspecified, if the flag is disabled). Validated end-to-end against a commissioned Matter device, enabling the flags, verifying the returned network index against an adb shell 'ip link show' output. Bug: 254155029 Test: atest FrameworksNetTests Change-Id: I96e804b32cdeeff3ed22da35a030df4d5dbb179a
This commit is contained in:
@@ -106,9 +106,9 @@ public class MdnsResponseDecoderTests {
|
||||
+ "63616C0000018001000000780004C0A8010A000001800100000078"
|
||||
+ "0004C0A8010A00000000000000");
|
||||
|
||||
private static final String DUMMY_CAST_SERVICE_NAME = "_googlecast";
|
||||
private static final String[] DUMMY_CAST_SERVICE_TYPE =
|
||||
new String[] {DUMMY_CAST_SERVICE_NAME, "_tcp", "local"};
|
||||
private static final String CAST_SERVICE_NAME = "_googlecast";
|
||||
private static final String[] CAST_SERVICE_TYPE =
|
||||
new String[] {CAST_SERVICE_NAME, "_tcp", "local"};
|
||||
|
||||
private final List<MdnsResponse> responses = new LinkedList<>();
|
||||
|
||||
@@ -116,13 +116,13 @@ public class MdnsResponseDecoderTests {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, DUMMY_CAST_SERVICE_TYPE);
|
||||
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
|
||||
assertNotNull(data);
|
||||
DatagramPacket packet = new DatagramPacket(data, data.length);
|
||||
packet.setSocketAddress(
|
||||
new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT));
|
||||
responses.clear();
|
||||
int errorCode = decoder.decode(packet, responses);
|
||||
int errorCode = decoder.decode(packet, responses, MdnsSocket.INTERFACE_INDEX_UNSPECIFIED);
|
||||
assertEquals(MdnsResponseDecoder.SUCCESS, errorCode);
|
||||
assertEquals(1, responses.size());
|
||||
}
|
||||
@@ -135,7 +135,7 @@ public class MdnsResponseDecoderTests {
|
||||
packet.setSocketAddress(
|
||||
new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT));
|
||||
responses.clear();
|
||||
int errorCode = decoder.decode(packet, responses);
|
||||
int errorCode = decoder.decode(packet, responses, MdnsSocket.INTERFACE_INDEX_UNSPECIFIED);
|
||||
assertEquals(MdnsResponseDecoder.SUCCESS, errorCode);
|
||||
assertEquals(2, responses.size());
|
||||
}
|
||||
@@ -153,7 +153,7 @@ public class MdnsResponseDecoderTests {
|
||||
|
||||
MdnsServiceRecord serviceRecord = response.getServiceRecord();
|
||||
String serviceName = serviceRecord.getServiceName();
|
||||
assertEquals(DUMMY_CAST_SERVICE_NAME, serviceName);
|
||||
assertEquals(CAST_SERVICE_NAME, serviceName);
|
||||
|
||||
String serviceInstanceName = serviceRecord.getServiceInstanceName();
|
||||
assertEquals("Johnny's Chromecast", serviceInstanceName);
|
||||
@@ -187,14 +187,14 @@ public class MdnsResponseDecoderTests {
|
||||
|
||||
@Test
|
||||
public void testDecodeIPv6AnswerPacket() throws IOException {
|
||||
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, DUMMY_CAST_SERVICE_TYPE);
|
||||
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
|
||||
assertNotNull(data6);
|
||||
DatagramPacket packet = new DatagramPacket(data6, data6.length);
|
||||
packet.setSocketAddress(
|
||||
new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT));
|
||||
|
||||
responses.clear();
|
||||
int errorCode = decoder.decode(packet, responses);
|
||||
int errorCode = decoder.decode(packet, responses, MdnsSocket.INTERFACE_INDEX_UNSPECIFIED);
|
||||
assertEquals(MdnsResponseDecoder.SUCCESS, errorCode);
|
||||
|
||||
MdnsResponse response = responses.get(0);
|
||||
@@ -234,4 +234,19 @@ public class MdnsResponseDecoderTests {
|
||||
response.setTextRecord(null);
|
||||
assertFalse(response.isComplete());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decode_withInterfaceIndex_populatesInterfaceIndex() {
|
||||
MdnsResponseDecoder decoder = new MdnsResponseDecoder(mClock, CAST_SERVICE_TYPE);
|
||||
assertNotNull(data6);
|
||||
DatagramPacket packet = new DatagramPacket(data6, data6.length);
|
||||
packet.setSocketAddress(
|
||||
new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT));
|
||||
|
||||
responses.clear();
|
||||
int errorCode = decoder.decode(packet, responses, /* interfaceIndex= */ 10);
|
||||
assertEquals(errorCode, MdnsResponseDecoder.SUCCESS);
|
||||
assertEquals(responses.size(), 1);
|
||||
assertEquals(responses.get(0).getInterfaceIndex(), 10);
|
||||
}
|
||||
}
|
||||
@@ -221,6 +221,19 @@ public class MdnsResponseTests {
|
||||
assertEquals(response.getTextRecord(), record);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInterfaceIndex_returnsDefaultValue() {
|
||||
MdnsResponse response = new MdnsResponse(/* now= */ 0);
|
||||
assertEquals(response.getInterfaceIndex(), -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInterfaceIndex_afterSet_returnsValue() {
|
||||
MdnsResponse response = new MdnsResponse(/* now= */ 0);
|
||||
response.setInterfaceIndex(5);
|
||||
assertEquals(response.getInterfaceIndex(), 5);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mergeRecordsFrom_indicates_change_on_ipv4_address() throws IOException {
|
||||
MdnsResponse response = makeMdnsResponse(
|
||||
|
||||
@@ -115,6 +115,40 @@ public class MdnsServiceInfoTest {
|
||||
info.getAttributes());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInterfaceIndex_constructorWithDefaultValues_returnsMinusOne() {
|
||||
MdnsServiceInfo info =
|
||||
new MdnsServiceInfo(
|
||||
"my-mdns-service",
|
||||
new String[] {"_googlecast", "_tcp"},
|
||||
List.of(),
|
||||
new String[] {"my-host", "local"},
|
||||
12345,
|
||||
"192.168.1.1",
|
||||
"2001::1",
|
||||
List.of());
|
||||
|
||||
assertEquals(info.getInterfaceIndex(), -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getInterfaceIndex_constructorWithInterfaceIndex_returnsProvidedIndex() {
|
||||
MdnsServiceInfo info =
|
||||
new MdnsServiceInfo(
|
||||
"my-mdns-service",
|
||||
new String[] {"_googlecast", "_tcp"},
|
||||
List.of(),
|
||||
new String[] {"my-host", "local"},
|
||||
12345,
|
||||
"192.168.1.1",
|
||||
"2001::1",
|
||||
List.of(),
|
||||
/* textEntries= */ null,
|
||||
/* interfaceIndex= */ 20);
|
||||
|
||||
assertEquals(info.getInterfaceIndex(), 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parcelable_canBeParceledAndUnparceled() {
|
||||
Parcel parcel = Parcel.obtain();
|
||||
|
||||
@@ -401,7 +401,8 @@ public class MdnsServiceTypeClientTests {
|
||||
ipV4Address,
|
||||
5353,
|
||||
Collections.singletonList("ABCDE"),
|
||||
Collections.emptyMap());
|
||||
Collections.emptyMap(),
|
||||
/* interfaceIndex= */ 20);
|
||||
client.processResponse(initialResponse);
|
||||
|
||||
// Process a second response with a different port and updated text attributes.
|
||||
@@ -411,7 +412,8 @@ public class MdnsServiceTypeClientTests {
|
||||
ipV4Address,
|
||||
5354,
|
||||
Collections.singletonList("ABCDE"),
|
||||
Collections.singletonMap("key", "value"));
|
||||
Collections.singletonMap("key", "value"),
|
||||
/* interfaceIndex= */ 20);
|
||||
client.processResponse(secondResponse);
|
||||
|
||||
// Verify onServiceFound was called once for the initial response.
|
||||
@@ -422,6 +424,7 @@ public class MdnsServiceTypeClientTests {
|
||||
assertEquals(initialServiceInfo.getPort(), 5353);
|
||||
assertEquals(initialServiceInfo.getSubtypes(), Collections.singletonList("ABCDE"));
|
||||
assertNull(initialServiceInfo.getAttributeByKey("key"));
|
||||
assertEquals(initialServiceInfo.getInterfaceIndex(), 20);
|
||||
|
||||
// Verify onServiceUpdated was called once for the second response.
|
||||
verify(mockListenerOne).onServiceUpdated(serviceInfoCaptor.capture());
|
||||
@@ -432,6 +435,7 @@ public class MdnsServiceTypeClientTests {
|
||||
assertTrue(updatedServiceInfo.hasSubtypes());
|
||||
assertEquals(updatedServiceInfo.getSubtypes(), Collections.singletonList("ABCDE"));
|
||||
assertEquals(updatedServiceInfo.getAttributeByKey("key"), "value");
|
||||
assertEquals(updatedServiceInfo.getInterfaceIndex(), 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -446,7 +450,8 @@ public class MdnsServiceTypeClientTests {
|
||||
ipV6Address,
|
||||
5353,
|
||||
Collections.singletonList("ABCDE"),
|
||||
Collections.emptyMap());
|
||||
Collections.emptyMap(),
|
||||
/* interfaceIndex= */ 20);
|
||||
client.processResponse(initialResponse);
|
||||
|
||||
// Process a second response with a different port and updated text attributes.
|
||||
@@ -456,7 +461,8 @@ public class MdnsServiceTypeClientTests {
|
||||
ipV6Address,
|
||||
5354,
|
||||
Collections.singletonList("ABCDE"),
|
||||
Collections.singletonMap("key", "value"));
|
||||
Collections.singletonMap("key", "value"),
|
||||
/* interfaceIndex= */ 20);
|
||||
client.processResponse(secondResponse);
|
||||
|
||||
System.out.println("secondResponses ip"
|
||||
@@ -470,6 +476,7 @@ public class MdnsServiceTypeClientTests {
|
||||
assertEquals(initialServiceInfo.getPort(), 5353);
|
||||
assertEquals(initialServiceInfo.getSubtypes(), Collections.singletonList("ABCDE"));
|
||||
assertNull(initialServiceInfo.getAttributeByKey("key"));
|
||||
assertEquals(initialServiceInfo.getInterfaceIndex(), 20);
|
||||
|
||||
// Verify onServiceUpdated was called once for the second response.
|
||||
verify(mockListenerOne).onServiceUpdated(serviceInfoCaptor.capture());
|
||||
@@ -480,6 +487,7 @@ public class MdnsServiceTypeClientTests {
|
||||
assertTrue(updatedServiceInfo.hasSubtypes());
|
||||
assertEquals(updatedServiceInfo.getSubtypes(), Collections.singletonList("ABCDE"));
|
||||
assertEquals(updatedServiceInfo.getAttributeByKey("key"), "value");
|
||||
assertEquals(updatedServiceInfo.getInterfaceIndex(), 20);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -727,7 +735,6 @@ public class MdnsServiceTypeClientTests {
|
||||
}
|
||||
}
|
||||
|
||||
// Creates a complete mDNS response.
|
||||
private MdnsResponse createResponse(
|
||||
@NonNull String serviceInstanceName,
|
||||
@NonNull String host,
|
||||
@@ -735,6 +742,19 @@ public class MdnsServiceTypeClientTests {
|
||||
@NonNull List<String> subtypes,
|
||||
@NonNull Map<String, String> textAttributes)
|
||||
throws Exception {
|
||||
return createResponse(serviceInstanceName, host, port, subtypes, textAttributes,
|
||||
/* interfaceIndex= */ -1);
|
||||
}
|
||||
|
||||
// Creates a complete mDNS response.
|
||||
private MdnsResponse createResponse(
|
||||
@NonNull String serviceInstanceName,
|
||||
@NonNull String host,
|
||||
int port,
|
||||
@NonNull List<String> subtypes,
|
||||
@NonNull Map<String, String> textAttributes,
|
||||
int interfaceIndex)
|
||||
throws Exception {
|
||||
String[] hostName = new String[]{"hostname"};
|
||||
MdnsServiceRecord serviceRecord = mock(MdnsServiceRecord.class);
|
||||
when(serviceRecord.getServiceHost()).thenReturn(hostName);
|
||||
@@ -747,10 +767,12 @@ public class MdnsServiceTypeClientTests {
|
||||
when(inetAddressRecord.getInet6Address())
|
||||
.thenReturn((Inet6Address) Inet6Address.getByName(host));
|
||||
response.setInet6AddressRecord(inetAddressRecord);
|
||||
response.setInterfaceIndex(interfaceIndex);
|
||||
} else {
|
||||
when(inetAddressRecord.getInet4Address())
|
||||
.thenReturn((Inet4Address) Inet4Address.getByName(host));
|
||||
response.setInet4AddressRecord(inetAddressRecord);
|
||||
response.setInterfaceIndex(interfaceIndex);
|
||||
}
|
||||
|
||||
MdnsTextRecord textRecord = mock(MdnsTextRecord.class);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.server.connectivity.mdns;
|
||||
|
||||
import static com.android.testutils.DevSdkIgnoreRuleKt.SC_V2;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
@@ -25,6 +26,7 @@ import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
@@ -45,6 +47,7 @@ import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
@@ -490,4 +493,58 @@ public class MdnsSocketClientTests {
|
||||
assertFalse(mdnsClient.receivedUnicastResponse);
|
||||
assertFalse(mdnsClient.cannotReceiveMulticastResponse.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void startDiscovery_andPropagateInterfaceIndex_includesInterfaceIndex()
|
||||
throws Exception {
|
||||
//MdnsConfigsFlagsImpl.allowNetworkInterfaceIndexPropagation.override(true);
|
||||
|
||||
when(mockMulticastSocket.getInterfaceIndex()).thenReturn(21);
|
||||
mdnsClient =
|
||||
new MdnsSocketClient(mContext, mockMulticastLock) {
|
||||
@Override
|
||||
MdnsSocket createMdnsSocket(int port) {
|
||||
if (port == MdnsConstants.MDNS_PORT) {
|
||||
return mockMulticastSocket;
|
||||
}
|
||||
return mockUnicastSocket;
|
||||
}
|
||||
};
|
||||
mdnsClient.setCallback(mockCallback);
|
||||
mdnsClient.startDiscovery();
|
||||
|
||||
ArgumentCaptor<MdnsResponse> mdnsResponseCaptor =
|
||||
ArgumentCaptor.forClass(MdnsResponse.class);
|
||||
verify(mockCallback, timeout(TIMEOUT).atLeast(1))
|
||||
.onResponseReceived(mdnsResponseCaptor.capture());
|
||||
assertEquals(21, mdnsResponseCaptor.getValue().getInterfaceIndex());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("MdnsConfigs is not configurable currently.")
|
||||
public void startDiscovery_andDoNotPropagateInterfaceIndex_doesNotIncludeInterfaceIndex()
|
||||
throws Exception {
|
||||
//MdnsConfigsFlagsImpl.allowNetworkInterfaceIndexPropagation.override(false);
|
||||
|
||||
when(mockMulticastSocket.getInterfaceIndex()).thenReturn(21);
|
||||
mdnsClient =
|
||||
new MdnsSocketClient(mContext, mockMulticastLock) {
|
||||
@Override
|
||||
MdnsSocket createMdnsSocket(int port) {
|
||||
if (port == MdnsConstants.MDNS_PORT) {
|
||||
return mockMulticastSocket;
|
||||
}
|
||||
return mockUnicastSocket;
|
||||
}
|
||||
};
|
||||
mdnsClient.setCallback(mockCallback);
|
||||
mdnsClient.startDiscovery();
|
||||
|
||||
ArgumentCaptor<MdnsResponse> mdnsResponseCaptor =
|
||||
ArgumentCaptor.forClass(MdnsResponse.class);
|
||||
verify(mockMulticastSocket, never()).getInterfaceIndex();
|
||||
verify(mockCallback, timeout(TIMEOUT).atLeast(1))
|
||||
.onResponseReceived(mdnsResponseCaptor.capture());
|
||||
assertEquals(-1, mdnsResponseCaptor.getValue().getInterfaceIndex());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user