diff --git a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java index 938fc3f204..64df46e11b 100644 --- a/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java +++ b/service-t/src/com/android/server/connectivity/mdns/MdnsServiceInfo.java @@ -31,10 +31,10 @@ import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.TreeMap; /** * A class representing a discovered mDNS service instance. @@ -205,17 +205,14 @@ public class MdnsServiceInfo implements Parcelable { // compatibility. We should prefer only {@code textEntries} if it's not null. List entries = (this.textEntries != null) ? this.textEntries : parseTextStrings(this.textStrings); - Map attributes = new HashMap<>(entries.size()); + // The map of attributes is case-insensitive. + final Map attributes = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); for (TextEntry entry : entries) { - String key = entry.getKey().toLowerCase(Locale.ENGLISH); - // Per https://datatracker.ietf.org/doc/html/rfc6763#section-6.4, only the first entry // of the same key should be accepted: // If a client receives a TXT record containing the same key more than once, then the // client MUST silently ignore all but the first occurrence of that attribute. - if (!attributes.containsKey(key)) { - attributes.put(key, entry.getValue()); - } + attributes.putIfAbsent(entry.getKey(), entry.getValue()); } this.attributes = Collections.unmodifiableMap(attributes); this.interfaceIndex = interfaceIndex; @@ -311,12 +308,12 @@ public class MdnsServiceInfo implements Parcelable { */ @Nullable public byte[] getAttributeAsBytes(@NonNull String key) { - return attributes.get(key.toLowerCase(Locale.ENGLISH)); + return attributes.get(key); } /** Returns an immutable map of all attributes. */ public Map getAttributes() { - Map map = new HashMap<>(attributes.size()); + Map map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); for (Map.Entry kv : attributes.entrySet()) { final byte[] value = kv.getValue(); map.put(kv.getKey(), value == null ? null : new String(value, UTF_8)); diff --git a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceInfoTest.java b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceInfoTest.java index 76728cf419..4db0f1a421 100644 --- a/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceInfoTest.java +++ b/tests/unit/java/com/android/server/connectivity/mdns/MdnsServiceInfoTest.java @@ -118,6 +118,26 @@ public class MdnsServiceInfoTest { info.getAttributes()); } + @Test + public void constructor_createWithUppercaseKeys_correctAttributes() { + MdnsServiceInfo info = + new MdnsServiceInfo( + "my-mdns-service", + new String[] {"_testtype", "_tcp"}, + List.of(), + new String[] {"my-host", "local"}, + 12345, + "192.168.1.1", + "2001::1", + List.of("KEY=Value"), + /* textEntries= */ null); + + assertEquals("Value", info.getAttributeByKey("key")); + assertEquals("Value", info.getAttributeByKey("KEY")); + assertEquals(1, info.getAttributes().size()); + assertEquals("KEY", info.getAttributes().keySet().iterator().next()); + } + @Test public void getInterfaceIndex_constructorWithDefaultValues_returnsMinusOne() { MdnsServiceInfo info =