Merge "[Feature sync] Resolve class-level nullness suppression"

This commit is contained in:
Treehugger Robot
2022-11-10 13:53:31 +00:00
committed by Gerrit Code Review
15 changed files with 149 additions and 144 deletions

View File

@@ -17,6 +17,7 @@
package com.android.server.connectivity.mdns; package com.android.server.connectivity.mdns;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Pair; import android.util.Pair;
@@ -38,8 +39,6 @@ import java.util.concurrent.Callable;
* and the list of the subtypes in the query as a {@link Pair}. If a query is failed to build, or if * and the list of the subtypes in the query as a {@link Pair}. If a query is failed to build, or if
* it can not be enqueued, then call to {@link #call()} returns {@code null}. * it can not be enqueued, then call to {@link #call()} returns {@code null}.
*/ */
// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<String>>> { public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<String>>> {
private static final String TAG = "MdnsQueryCallable"; private static final String TAG = "MdnsQueryCallable";
@@ -81,7 +80,10 @@ public class EnqueueMdnsQueryCallable implements Callable<Pair<Integer, List<Str
this.transactionId = transactionId; this.transactionId = transactionId;
} }
// Incompatible return type for override of Callable#call().
@SuppressWarnings("nullness:override.return.invalid")
@Override @Override
@Nullable
public Pair<Integer, List<String>> call() { public Pair<Integer, List<String>> call() {
try { try {
MdnsSocketClient requestSender = weakRequestSender.get(); MdnsSocketClient requestSender = weakRequestSender.get();

View File

@@ -16,19 +16,15 @@
package com.android.server.connectivity.mdns; package com.android.server.connectivity.mdns;
import android.annotation.TargetApi; import static java.nio.charset.StandardCharsets.UTF_8;
import android.os.Build;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/** mDNS-related constants. */ /** mDNS-related constants. */
// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
@VisibleForTesting @VisibleForTesting
public final class MdnsConstants { public final class MdnsConstants {
public static final int MDNS_PORT = 5353; public static final int MDNS_PORT = 5353;
@@ -48,7 +44,6 @@ public final class MdnsConstants {
private static final String MDNS_IPV4_HOST_ADDRESS = "224.0.0.251"; private static final String MDNS_IPV4_HOST_ADDRESS = "224.0.0.251";
private static final String MDNS_IPV6_HOST_ADDRESS = "FF02::FB"; private static final String MDNS_IPV6_HOST_ADDRESS = "FF02::FB";
private static InetAddress mdnsAddress; private static InetAddress mdnsAddress;
private static Charset utf8Charset;
private MdnsConstants() { private MdnsConstants() {
} }
@@ -79,16 +74,6 @@ public final class MdnsConstants {
} }
public static Charset getUtf8Charset() { public static Charset getUtf8Charset() {
synchronized (MdnsConstants.class) { return UTF_8;
if (utf8Charset == null) {
utf8Charset = getUtf8CharsetOnKitKat();
}
return utf8Charset;
}
}
@TargetApi(Build.VERSION_CODES.KITKAT)
private static Charset getUtf8CharsetOnKitKat() {
return StandardCharsets.UTF_8;
} }
} }

View File

@@ -16,6 +16,8 @@
package com.android.server.connectivity.mdns; package com.android.server.connectivity.mdns;
import android.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException; import java.io.IOException;
@@ -27,12 +29,10 @@ import java.util.Locale;
import java.util.Objects; import java.util.Objects;
/** An mDNS "AAAA" or "A" record, which holds an IPv6 or IPv4 address. */ /** An mDNS "AAAA" or "A" record, which holds an IPv6 or IPv4 address. */
// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
@VisibleForTesting @VisibleForTesting
public class MdnsInetAddressRecord extends MdnsRecord { public class MdnsInetAddressRecord extends MdnsRecord {
private Inet6Address inet6Address; @Nullable private Inet6Address inet6Address;
private Inet4Address inet4Address; @Nullable private Inet4Address inet4Address;
/** /**
* Constructs the {@link MdnsRecord} * Constructs the {@link MdnsRecord}
@@ -47,11 +47,13 @@ public class MdnsInetAddressRecord extends MdnsRecord {
} }
/** Returns the IPv6 address. */ /** Returns the IPv6 address. */
@Nullable
public Inet6Address getInet6Address() { public Inet6Address getInet6Address() {
return inet6Address; return inet6Address;
} }
/** Returns the IPv4 address. */ /** Returns the IPv4 address. */
@Nullable
public Inet4Address getInet4Address() { public Inet4Address getInet4Address() {
return inet4Address; return inet4Address;
} }
@@ -113,7 +115,7 @@ public class MdnsInetAddressRecord extends MdnsRecord {
} }
@Override @Override
public boolean equals(Object other) { public boolean equals(@Nullable Object other) {
if (this == other) { if (this == other) {
return true; return true;
} }

View File

@@ -16,14 +16,14 @@
package com.android.server.connectivity.mdns; package com.android.server.connectivity.mdns;
import android.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
/** An mDNS "PTR" record, which holds a name (the "pointer"). */ /** An mDNS "PTR" record, which holds a name (the "pointer"). */
// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
@VisibleForTesting @VisibleForTesting
public class MdnsPointerRecord extends MdnsRecord { public class MdnsPointerRecord extends MdnsRecord {
private String[] pointer; private String[] pointer;
@@ -66,7 +66,7 @@ public class MdnsPointerRecord extends MdnsRecord {
} }
@Override @Override
public boolean equals(Object other) { public boolean equals(@Nullable Object other) {
if (this == other) { if (this == other) {
return true; return true;
} }

View File

@@ -16,6 +16,10 @@
package com.android.server.connectivity.mdns; package com.android.server.connectivity.mdns;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import android.annotation.Nullable;
import android.os.SystemClock; import android.os.SystemClock;
import android.text.TextUtils; import android.text.TextUtils;
@@ -24,14 +28,11 @@ import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.TimeUnit;
/** /**
* Abstract base class for mDNS records. Stores the header fields and provides methods for reading * Abstract base class for mDNS records. Stores the header fields and provides methods for reading
* the record from and writing it to a packet. * the record from and writing it to a packet.
*/ */
// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public abstract class MdnsRecord { public abstract class MdnsRecord {
public static final int TYPE_A = 0x0001; public static final int TYPE_A = 0x0001;
public static final int TYPE_AAAA = 0x001C; public static final int TYPE_AAAA = 0x001C;
@@ -59,11 +60,14 @@ public abstract class MdnsRecord {
* @param reader The reader to read the record from. * @param reader The reader to read the record from.
* @throws IOException If an error occurs while reading the packet. * @throws IOException If an error occurs while reading the packet.
*/ */
// call to readData(com.android.server.connectivity.mdns.MdnsPacketReader) not allowed on given
// receiver.
@SuppressWarnings("nullness:method.invocation.invalid")
protected MdnsRecord(String[] name, int type, MdnsPacketReader reader) throws IOException { protected MdnsRecord(String[] name, int type, MdnsPacketReader reader) throws IOException {
this.name = name; this.name = name;
this.type = type; this.type = type;
cls = reader.readUInt16(); cls = reader.readUInt16();
ttlMillis = TimeUnit.SECONDS.toMillis(reader.readUInt32()); ttlMillis = SECONDS.toMillis(reader.readUInt32());
int dataLength = reader.readUInt16(); int dataLength = reader.readUInt16();
receiptTimeMillis = SystemClock.elapsedRealtime(); receiptTimeMillis = SystemClock.elapsedRealtime();
@@ -157,7 +161,7 @@ public abstract class MdnsRecord {
writer.writeUInt16(type); writer.writeUInt16(type);
writer.writeUInt16(cls); writer.writeUInt16(cls);
writer.writeUInt32(TimeUnit.MILLISECONDS.toSeconds(getRemainingTTL(now))); writer.writeUInt32(MILLISECONDS.toSeconds(getRemainingTTL(now)));
int dataLengthPos = writer.getWritePosition(); int dataLengthPos = writer.getWritePosition();
writer.writeUInt16(0); // data length writer.writeUInt16(0); // data length
@@ -194,7 +198,7 @@ public abstract class MdnsRecord {
} }
@Override @Override
public boolean equals(Object other) { public boolean equals(@Nullable Object other) {
if (!(other instanceof MdnsRecord)) { if (!(other instanceof MdnsRecord)) {
return false; return false;
} }
@@ -231,7 +235,7 @@ public abstract class MdnsRecord {
} }
@Override @Override
public boolean equals(Object other) { public boolean equals(@Nullable Object other) {
if (this == other) { if (this == other) {
return true; return true;
} }

View File

@@ -16,6 +16,8 @@
package com.android.server.connectivity.mdns; package com.android.server.connectivity.mdns;
import android.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException; import java.io.IOException;
@@ -25,8 +27,6 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
/** An mDNS response. */ /** An mDNS response. */
// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public class MdnsResponse { public class MdnsResponse {
private final List<MdnsRecord> records; private final List<MdnsRecord> records;
private final List<MdnsPointerRecord> pointerRecords; private final List<MdnsPointerRecord> pointerRecords;
@@ -78,7 +78,7 @@ public class MdnsResponse {
} }
@VisibleForTesting @VisibleForTesting
/* package */ synchronized void clearPointerRecords() { synchronized void clearPointerRecords() {
pointerRecords.clear(); pointerRecords.clear();
} }
@@ -91,15 +91,16 @@ public class MdnsResponse {
return false; return false;
} }
@Nullable
public synchronized List<String> getSubtypes() { public synchronized List<String> getSubtypes() {
List<String> subtypes = null; List<String> subtypes = null;
for (MdnsPointerRecord pointerRecord : pointerRecords) { for (MdnsPointerRecord pointerRecord : pointerRecords) {
if (pointerRecord.hasSubtype()) { String pointerRecordSubtype = pointerRecord.getSubtype();
if (pointerRecordSubtype != null) {
if (subtypes == null) { if (subtypes == null) {
subtypes = new LinkedList<>(); subtypes = new LinkedList<>();
} }
subtypes.add(pointerRecord.getSubtype()); subtypes.add(pointerRecordSubtype);
} }
} }
@@ -166,7 +167,8 @@ public class MdnsResponse {
} }
/** Sets the IPv4 address record. */ /** Sets the IPv4 address record. */
public synchronized boolean setInet4AddressRecord(MdnsInetAddressRecord newInet4AddressRecord) { public synchronized boolean setInet4AddressRecord(
@Nullable MdnsInetAddressRecord newInet4AddressRecord) {
if (recordsAreSame(this.inet4AddressRecord, newInet4AddressRecord)) { if (recordsAreSame(this.inet4AddressRecord, newInet4AddressRecord)) {
return false; return false;
} }
@@ -190,7 +192,8 @@ public class MdnsResponse {
} }
/** Sets the IPv6 address record. */ /** Sets the IPv6 address record. */
public synchronized boolean setInet6AddressRecord(MdnsInetAddressRecord newInet6AddressRecord) { public synchronized boolean setInet6AddressRecord(
@Nullable MdnsInetAddressRecord newInet6AddressRecord) {
if (recordsAreSame(this.inet6AddressRecord, newInet6AddressRecord)) { if (recordsAreSame(this.inet6AddressRecord, newInet6AddressRecord)) {
return false; return false;
} }

View File

@@ -31,8 +31,6 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
/** A class that decodes mDNS responses from UDP packets. */ /** A class that decodes mDNS responses from UDP packets. */
// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public class MdnsResponseDecoder { public class MdnsResponseDecoder {
public static final int SUCCESS = 0; public static final int SUCCESS = 0;
@@ -40,7 +38,7 @@ public class MdnsResponseDecoder {
private static final MdnsLogger LOGGER = new MdnsLogger(TAG); private static final MdnsLogger LOGGER = new MdnsLogger(TAG);
private final boolean allowMultipleSrvRecordsPerHost = private final boolean allowMultipleSrvRecordsPerHost =
MdnsConfigs.allowMultipleSrvRecordsPerHost(); MdnsConfigs.allowMultipleSrvRecordsPerHost();
private final String[] serviceType; @Nullable private final String[] serviceType;
private final Clock clock; private final Clock clock;
/** Constructs a new decoder that will extract responses for the given service type. */ /** Constructs a new decoder that will extract responses for the given service type. */

View File

@@ -72,7 +72,9 @@ public class MdnsServiceInfo implements Parcelable {
private final List<String> subtypes; private final List<String> subtypes;
private final String[] hostName; private final String[] hostName;
private final int port; private final int port;
@Nullable
private final String ipv4Address; private final String ipv4Address;
@Nullable
private final String ipv6Address; private final String ipv6Address;
final List<String> textStrings; final List<String> textStrings;
@Nullable @Nullable
@@ -85,12 +87,12 @@ public class MdnsServiceInfo implements Parcelable {
public MdnsServiceInfo( public MdnsServiceInfo(
String serviceInstanceName, String serviceInstanceName,
String[] serviceType, String[] serviceType,
List<String> subtypes, @Nullable List<String> subtypes,
String[] hostName, String[] hostName,
int port, int port,
String ipv4Address, @Nullable String ipv4Address,
String ipv6Address, @Nullable String ipv6Address,
List<String> textStrings) { @Nullable List<String> textStrings) {
this( this(
serviceInstanceName, serviceInstanceName,
serviceType, serviceType,
@@ -111,9 +113,9 @@ public class MdnsServiceInfo implements Parcelable {
List<String> subtypes, List<String> subtypes,
String[] hostName, String[] hostName,
int port, int port,
String ipv4Address, @Nullable String ipv4Address,
String ipv6Address, @Nullable String ipv6Address,
List<String> textStrings, @Nullable List<String> textStrings,
@Nullable List<TextEntry> textEntries) { @Nullable List<TextEntry> textEntries) {
this( this(
serviceInstanceName, serviceInstanceName,
@@ -136,12 +138,12 @@ public class MdnsServiceInfo implements Parcelable {
public MdnsServiceInfo( public MdnsServiceInfo(
String serviceInstanceName, String serviceInstanceName,
String[] serviceType, String[] serviceType,
List<String> subtypes, @Nullable List<String> subtypes,
String[] hostName, String[] hostName,
int port, int port,
String ipv4Address, @Nullable String ipv4Address,
String ipv6Address, @Nullable String ipv6Address,
List<String> textStrings, @Nullable List<String> textStrings,
@Nullable List<TextEntry> textEntries, @Nullable List<TextEntry> textEntries,
int interfaceIndex) { int interfaceIndex) {
this.serviceInstanceName = serviceInstanceName; this.serviceInstanceName = serviceInstanceName;
@@ -191,45 +193,44 @@ public class MdnsServiceInfo implements Parcelable {
return Collections.unmodifiableList(list); return Collections.unmodifiableList(list);
} }
/** @return the name of this service instance. */ /** Returns the name of this service instance. */
public String getServiceInstanceName() { public String getServiceInstanceName() {
return serviceInstanceName; return serviceInstanceName;
} }
/** @return the type of this service instance. */ /** Returns the type of this service instance. */
public String[] getServiceType() { public String[] getServiceType() {
return serviceType; return serviceType;
} }
/** @return the list of subtypes supported by this service instance. */ /** Returns the list of subtypes supported by this service instance. */
public List<String> getSubtypes() { public List<String> getSubtypes() {
return new ArrayList<>(subtypes); return new ArrayList<>(subtypes);
} }
/** /** Returns {@code true} if this service instance supports any subtypes. */
* @return {@code true} if this service instance supports any subtypes.
* @return {@code false} if this service instance does not support any subtypes.
*/
public boolean hasSubtypes() { public boolean hasSubtypes() {
return !subtypes.isEmpty(); return !subtypes.isEmpty();
} }
/** @return the host name of this service instance. */ /** Returns the host name of this service instance. */
public String[] getHostName() { public String[] getHostName() {
return hostName; return hostName;
} }
/** @return the port number of this service instance. */ /** Returns the port number of this service instance. */
public int getPort() { public int getPort() {
return port; return port;
} }
/** @return the IPV4 address of this service instance. */ /** Returns the IPV4 address of this service instance. */
@Nullable
public String getIpv4Address() { public String getIpv4Address() {
return ipv4Address; return ipv4Address;
} }
/** @return the IPV6 address of this service instance. */ /** Returns the IPV6 address of this service instance. */
@Nullable
public String getIpv6Address() { public String getIpv6Address() {
return ipv6Address; return ipv6Address;
} }
@@ -265,7 +266,7 @@ public class MdnsServiceInfo implements Parcelable {
return attributes.get(key.toLowerCase(Locale.ENGLISH)); return attributes.get(key.toLowerCase(Locale.ENGLISH));
} }
/** @return an immutable map of all attributes. */ /** Returns an immutable map of all attributes. */
public Map<String, String> getAttributes() { public Map<String, String> getAttributes() {
Map<String, String> map = new HashMap<>(attributes.size()); Map<String, String> map = new HashMap<>(attributes.size());
for (Map.Entry<String, byte[]> kv : attributes.entrySet()) { for (Map.Entry<String, byte[]> kv : attributes.entrySet()) {

View File

@@ -16,6 +16,8 @@
package com.android.server.connectivity.mdns; package com.android.server.connectivity.mdns;
import android.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import java.io.IOException; import java.io.IOException;
@@ -24,8 +26,6 @@ import java.util.Locale;
import java.util.Objects; import java.util.Objects;
/** An mDNS "SRV" record, which contains service information. */ /** An mDNS "SRV" record, which contains service information. */
// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
@VisibleForTesting @VisibleForTesting
public class MdnsServiceRecord extends MdnsRecord { public class MdnsServiceRecord extends MdnsRecord {
public static final int PROTO_NONE = 0; public static final int PROTO_NONE = 0;
@@ -131,7 +131,7 @@ public class MdnsServiceRecord extends MdnsRecord {
} }
@Override @Override
public boolean equals(Object other) { public boolean equals(@Nullable Object other) {
if (this == other) { if (this == other) {
return true; return true;
} }

View File

@@ -29,6 +29,8 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.server.connectivity.mdns.util.MdnsLogger; import com.android.server.connectivity.mdns.util.MdnsLogger;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@@ -43,8 +45,6 @@ import java.util.concurrent.ScheduledExecutorService;
* Instance of this class sends and receives mDNS packets of a given service type and invoke * Instance of this class sends and receives mDNS packets of a given service type and invoke
* registered {@link MdnsServiceBrowserListener} instances. * registered {@link MdnsServiceBrowserListener} instances.
*/ */
// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public class MdnsServiceTypeClient { public class MdnsServiceTypeClient {
private static final int DEFAULT_MTU = 1500; private static final int DEFAULT_MTU = 1500;
@@ -70,6 +70,7 @@ public class MdnsServiceTypeClient {
private long currentSessionId = 0; private long currentSessionId = 0;
@GuardedBy("lock") @GuardedBy("lock")
@Nullable
private Future<?> requestTaskFuture; private Future<?> requestTaskFuture;
/** /**
@@ -96,14 +97,25 @@ public class MdnsServiceTypeClient {
String ipv4Address = null; String ipv4Address = null;
String ipv6Address = null; String ipv6Address = null;
if (response.hasInet4AddressRecord()) { if (response.hasInet4AddressRecord()) {
ipv4Address = response.getInet4AddressRecord().getInet4Address().getHostAddress(); Inet4Address inet4Address = response.getInet4AddressRecord().getInet4Address();
ipv4Address = (inet4Address == null) ? null : inet4Address.getHostAddress();
} }
if (response.hasInet6AddressRecord()) { if (response.hasInet6AddressRecord()) {
ipv6Address = response.getInet6AddressRecord().getInet6Address().getHostAddress(); Inet6Address inet6Address = response.getInet6AddressRecord().getInet6Address();
ipv6Address = (inet6Address == null) ? null : inet6Address.getHostAddress();
}
if (ipv4Address == null && ipv6Address == null) {
throw new IllegalArgumentException(
"Either ipv4Address or ipv6Address must be non-null");
}
String serviceInstanceName = response.getServiceInstanceName();
if (serviceInstanceName == null) {
throw new IllegalStateException(
"mDNS response must have non-null service instance name");
} }
// TODO: Throw an error message if response doesn't have Inet6 or Inet4 address. // TODO: Throw an error message if response doesn't have Inet6 or Inet4 address.
return new MdnsServiceInfo( return new MdnsServiceInfo(
response.getServiceInstanceName(), serviceInstanceName,
serviceTypeLabels, serviceTypeLabels,
response.getSubtypes(), response.getSubtypes(),
hostName, hostName,
@@ -128,8 +140,7 @@ public class MdnsServiceTypeClient {
@NonNull MdnsSearchOptions searchOptions) { @NonNull MdnsSearchOptions searchOptions) {
synchronized (lock) { synchronized (lock) {
this.searchOptions = searchOptions; this.searchOptions = searchOptions;
if (!listeners.contains(listener)) { if (listeners.add(listener)) {
listeners.add(listener);
for (MdnsResponse existingResponse : instanceNameToResponse.values()) { for (MdnsResponse existingResponse : instanceNameToResponse.values()) {
if (existingResponse.isComplete()) { if (existingResponse.isComplete()) {
listener.onServiceFound( listener.onServiceFound(
@@ -212,7 +223,10 @@ public class MdnsServiceTypeClient {
if (currentResponse == null) { if (currentResponse == null) {
newServiceFound = true; newServiceFound = true;
currentResponse = response; currentResponse = response;
instanceNameToResponse.put(response.getServiceInstanceName(), currentResponse); String serviceInstanceName = response.getServiceInstanceName();
if (serviceInstanceName != null) {
instanceNameToResponse.put(serviceInstanceName, currentResponse);
}
} else if (currentResponse.mergeRecordsFrom(response)) { } else if (currentResponse.mergeRecordsFrom(response)) {
existingServiceChanged = true; existingServiceChanged = true;
} }
@@ -231,7 +245,10 @@ public class MdnsServiceTypeClient {
} }
} }
private void onGoodbyeReceived(@NonNull String serviceInstanceName) { private void onGoodbyeReceived(@Nullable String serviceInstanceName) {
if (serviceInstanceName == null) {
return;
}
instanceNameToResponse.remove(serviceInstanceName); instanceNameToResponse.remove(serviceInstanceName);
for (MdnsServiceBrowserListener listener : listeners) { for (MdnsServiceBrowserListener listener : listeners) {
listener.onServiceRemoved(serviceInstanceName); listener.onServiceRemoved(serviceInstanceName);
@@ -367,7 +384,7 @@ public class MdnsServiceTypeClient {
config.expectUnicastResponse, config.expectUnicastResponse,
config.transactionId) config.transactionId)
.call(); .call();
} catch (Exception e) { } catch (RuntimeException e) {
LOGGER.e(String.format("Failed to run EnqueueMdnsQueryCallable for subtype: %s", LOGGER.e(String.format("Failed to run EnqueueMdnsQueryCallable for subtype: %s",
TextUtils.join(",", config.subtypes)), e); TextUtils.join(",", config.subtypes)), e);
result = null; result = null;
@@ -405,8 +422,11 @@ public class MdnsServiceTypeClient {
== 0) { == 0) {
iter.remove(); iter.remove();
for (MdnsServiceBrowserListener listener : listeners) { for (MdnsServiceBrowserListener listener : listeners) {
listener.onServiceRemoved( String serviceInstanceName =
existingResponse.getServiceInstanceName()); existingResponse.getServiceInstanceName();
if (serviceInstanceName != null) {
listener.onServiceRemoved(serviceInstanceName);
}
} }
} }
} }

View File

@@ -34,8 +34,6 @@ import java.util.List;
* *
* @see MulticastSocket for javadoc of each public method. * @see MulticastSocket for javadoc of each public method.
*/ */
// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public class MdnsSocket { public class MdnsSocket {
private static final MdnsLogger LOGGER = new MdnsLogger("MdnsSocket"); private static final MdnsLogger LOGGER = new MdnsLogger("MdnsSocket");
@@ -44,16 +42,22 @@ public class MdnsSocket {
new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT); new InetSocketAddress(MdnsConstants.getMdnsIPv4Address(), MdnsConstants.MDNS_PORT);
private static final InetSocketAddress MULTICAST_IPV6_ADDRESS = private static final InetSocketAddress MULTICAST_IPV6_ADDRESS =
new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT); new InetSocketAddress(MdnsConstants.getMdnsIPv6Address(), MdnsConstants.MDNS_PORT);
private static boolean isOnIPv6OnlyNetwork = false;
private final MulticastNetworkInterfaceProvider multicastNetworkInterfaceProvider; private final MulticastNetworkInterfaceProvider multicastNetworkInterfaceProvider;
private final MulticastSocket multicastSocket; private final MulticastSocket multicastSocket;
private boolean isOnIPv6OnlyNetwork;
public MdnsSocket( public MdnsSocket(
@NonNull MulticastNetworkInterfaceProvider multicastNetworkInterfaceProvider, int port) @NonNull MulticastNetworkInterfaceProvider multicastNetworkInterfaceProvider, int port)
throws IOException { throws IOException {
this(multicastNetworkInterfaceProvider, new MulticastSocket(port));
}
@VisibleForTesting
MdnsSocket(@NonNull MulticastNetworkInterfaceProvider multicastNetworkInterfaceProvider,
MulticastSocket multicastSocket) throws IOException {
this.multicastNetworkInterfaceProvider = multicastNetworkInterfaceProvider; this.multicastNetworkInterfaceProvider = multicastNetworkInterfaceProvider;
this.multicastNetworkInterfaceProvider.startWatchingConnectivityChanges(); this.multicastNetworkInterfaceProvider.startWatchingConnectivityChanges();
multicastSocket = createMulticastSocket(port); this.multicastSocket = multicastSocket;
// RFC Spec: https://tools.ietf.org/html/rfc6762 // RFC Spec: https://tools.ietf.org/html/rfc6762
// Time to live is set 255, which is similar to the jMDNS implementation. // Time to live is set 255, which is similar to the jMDNS implementation.
multicastSocket.setTimeToLive(255); multicastSocket.setTimeToLive(255);
@@ -121,11 +125,6 @@ public class MdnsSocket {
} }
} }
@VisibleForTesting
MulticastSocket createMulticastSocket(int port) throws IOException {
return new MulticastSocket(port);
}
public boolean isOnIPv6OnlyNetwork() { public boolean isOnIPv6OnlyNetwork() {
return isOnIPv6OnlyNetwork; return isOnIPv6OnlyNetwork;
} }

View File

@@ -46,8 +46,6 @@ import java.util.concurrent.atomic.AtomicInteger;
* *
* <p>See https://tools.ietf.org/html/rfc6763 (namely sections 4 and 5). * <p>See https://tools.ietf.org/html/rfc6763 (namely sections 4 and 5).
*/ */
// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
public class MdnsSocketClient { public class MdnsSocketClient {
private static final String TAG = "MdnsClient"; private static final String TAG = "MdnsClient";
@@ -71,7 +69,7 @@ public class MdnsSocketClient {
final Queue<DatagramPacket> unicastPacketQueue = new ArrayDeque<>(); final Queue<DatagramPacket> unicastPacketQueue = new ArrayDeque<>();
private final Context context; private final Context context;
private final byte[] multicastReceiverBuffer = new byte[RECEIVER_BUFFER_SIZE]; private final byte[] multicastReceiverBuffer = new byte[RECEIVER_BUFFER_SIZE];
private final byte[] unicastReceiverBuffer; @Nullable private final byte[] unicastReceiverBuffer;
private final MdnsResponseDecoder responseDecoder; private final MdnsResponseDecoder responseDecoder;
private final MulticastLock multicastLock; private final MulticastLock multicastLock;
private final boolean useSeparateSocketForUnicast = private final boolean useSeparateSocketForUnicast =
@@ -94,20 +92,17 @@ public class MdnsSocketClient {
// If the phone is the bad state where it can't receive any multicast response. // If the phone is the bad state where it can't receive any multicast response.
@VisibleForTesting @VisibleForTesting
AtomicBoolean cannotReceiveMulticastResponse = new AtomicBoolean(false); AtomicBoolean cannotReceiveMulticastResponse = new AtomicBoolean(false);
@VisibleForTesting @VisibleForTesting @Nullable volatile Thread sendThread;
volatile Thread sendThread; @VisibleForTesting @Nullable Thread multicastReceiveThread;
@VisibleForTesting @VisibleForTesting @Nullable Thread unicastReceiveThread;
Thread multicastReceiveThread;
@VisibleForTesting
Thread unicastReceiveThread;
private volatile boolean shouldStopSocketLoop; private volatile boolean shouldStopSocketLoop;
private Callback callback; @Nullable private Callback callback;
private MdnsSocket multicastSocket; @Nullable private MdnsSocket multicastSocket;
private MdnsSocket unicastSocket; @Nullable private MdnsSocket unicastSocket;
private int receivedPacketNumber = 0; private int receivedPacketNumber = 0;
private Timer logMdnsPacketTimer; @Nullable private Timer logMdnsPacketTimer;
private AtomicInteger packetsCount; private AtomicInteger packetsCount;
private Timer checkMulticastResponseTimer; @Nullable private Timer checkMulticastResponseTimer;
public MdnsSocketClient(@NonNull Context context, @NonNull MulticastLock multicastLock) { public MdnsSocketClient(@NonNull Context context, @NonNull MulticastLock multicastLock) {
this.context = context; this.context = context;
@@ -248,7 +243,12 @@ public class MdnsSocketClient {
if (useSeparateSocketForUnicast) { if (useSeparateSocketForUnicast) {
unicastReceiveThread = unicastReceiveThread =
new Thread(() -> receiveThreadMain(unicastReceiverBuffer, unicastSocket)); new Thread(
() -> {
if (unicastReceiverBuffer != null) {
receiveThreadMain(unicastReceiverBuffer, unicastSocket);
}
});
unicastReceiveThread.setName("mdns-unicast-receive"); unicastReceiveThread.setName("mdns-unicast-receive");
unicastReceiveThread.start(); unicastReceiveThread.start();
} }
@@ -327,11 +327,15 @@ public class MdnsSocketClient {
unicastPacketsToSend.addAll(unicastPacketQueue); unicastPacketsToSend.addAll(unicastPacketQueue);
unicastPacketQueue.clear(); unicastPacketQueue.clear();
} }
if (unicastSocket != null) {
sendPackets(unicastPacketsToSend, unicastSocket);
}
} }
// Send all the packets. // Send multicast packets.
sendPackets(multicastPacketsToSend, multicastSocket); if (multicastSocket != null) {
sendPackets(unicastPacketsToSend, unicastSocket); sendPackets(multicastPacketsToSend, multicastSocket);
}
// Sleep ONLY if no more packets have been added to the queue, while packets // Sleep ONLY if no more packets have been added to the queue, while packets
// were being sent. // were being sent.
@@ -351,7 +355,9 @@ public class MdnsSocketClient {
} finally { } finally {
LOGGER.log("Send thread stopped."); LOGGER.log("Send thread stopped.");
try { try {
multicastSocket.leaveGroup(); if (multicastSocket != null) {
multicastSocket.leaveGroup();
}
} catch (Exception t) { } catch (Exception t) {
LOGGER.e("Failed to leave the group.", t); LOGGER.e("Failed to leave the group.", t);
} }
@@ -359,17 +365,19 @@ public class MdnsSocketClient {
// Close the socket first. This is the only way to interrupt a blocking receive. // Close the socket first. This is the only way to interrupt a blocking receive.
try { try {
// This is a race with the use of the file descriptor (b/27403984). // This is a race with the use of the file descriptor (b/27403984).
multicastSocket.close(); if (multicastSocket != null) {
multicastSocket.close();
}
if (unicastSocket != null) { if (unicastSocket != null) {
unicastSocket.close(); unicastSocket.close();
} }
} catch (Exception t) { } catch (RuntimeException t) {
LOGGER.e("Failed to close the mdns socket.", t); LOGGER.e("Failed to close the mdns socket.", t);
} }
} }
} }
private void receiveThreadMain(byte[] receiverBuffer, MdnsSocket socket) { private void receiveThreadMain(byte[] receiverBuffer, @Nullable MdnsSocket socket) {
DatagramPacket packet = new DatagramPacket(receiverBuffer, receiverBuffer.length); DatagramPacket packet = new DatagramPacket(receiverBuffer, receiverBuffer.length);
while (!shouldStopSocketLoop) { while (!shouldStopSocketLoop) {
@@ -500,7 +508,7 @@ public class MdnsSocketClient {
} }
public boolean isOnIPv6OnlyNetwork() { public boolean isOnIPv6OnlyNetwork() {
return multicastSocket.isOnIPv6OnlyNetwork(); return multicastSocket != null && multicastSocket.isOnIPv6OnlyNetwork();
} }
/** Callback for {@link MdnsSocketClient}. */ /** Callback for {@link MdnsSocketClient}. */

View File

@@ -16,6 +16,8 @@
package com.android.server.connectivity.mdns; package com.android.server.connectivity.mdns;
import android.annotation.Nullable;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.server.connectivity.mdns.MdnsServiceInfo.TextEntry; import com.android.server.connectivity.mdns.MdnsServiceInfo.TextEntry;
@@ -26,8 +28,6 @@ import java.util.List;
import java.util.Objects; import java.util.Objects;
/** An mDNS "TXT" record, which contains a list of {@link TextEntry}. */ /** An mDNS "TXT" record, which contains a list of {@link TextEntry}. */
// TODO(b/242631897): Resolve nullness suppression.
@SuppressWarnings("nullness")
@VisibleForTesting @VisibleForTesting
public class MdnsTextRecord extends MdnsRecord { public class MdnsTextRecord extends MdnsRecord {
private List<TextEntry> entries; private List<TextEntry> entries;
@@ -90,7 +90,7 @@ public class MdnsTextRecord extends MdnsRecord {
} }
@Override @Override
public boolean equals(Object other) { public boolean equals(@Nullable Object other) {
if (this == other) { if (this == other) {
return true; return true;
} }

View File

@@ -16,6 +16,7 @@
package com.android.server.connectivity.mdns.util; package com.android.server.connectivity.mdns.util;
import android.annotation.Nullable;
import android.text.TextUtils; import android.text.TextUtils;
import com.android.net.module.util.SharedLog; import com.android.net.module.util.SharedLog;
@@ -40,7 +41,7 @@ public class MdnsLogger {
mLog.log(message); mLog.log(message);
} }
public void log(String message, Object... args) { public void log(String message, @Nullable Object... args) {
mLog.log(message + " ; " + TextUtils.join(" ; ", args)); mLog.log(message + " ; " + TextUtils.join(" ; ", args));
} }

View File

@@ -53,7 +53,7 @@ public class MdnsSocketTests {
private SocketAddress socketIPv4Address; private SocketAddress socketIPv4Address;
private SocketAddress socketIPv6Address; private SocketAddress socketIPv6Address;
private byte[] data = new byte[25]; private final byte[] data = new byte[25];
private final DatagramPacket datagramPacket = new DatagramPacket(data, data.length); private final DatagramPacket datagramPacket = new DatagramPacket(data, data.length);
private NetworkInterface networkInterface; private NetworkInterface networkInterface;
@@ -74,14 +74,8 @@ public class MdnsSocketTests {
} }
@Test @Test
public void testMdnsSocket() throws IOException { public void mdnsSocket_basicFunctionality() throws IOException {
mdnsSocket = mdnsSocket = new MdnsSocket(mockMulticastNetworkInterfaceProvider, mockMulticastSocket);
new MdnsSocket(mockMulticastNetworkInterfaceProvider, MdnsConstants.MDNS_PORT) {
@Override
MulticastSocket createMulticastSocket(int port) throws IOException {
return mockMulticastSocket;
}
};
mdnsSocket.send(datagramPacket); mdnsSocket.send(datagramPacket);
verify(mockMulticastSocket).setNetworkInterface(networkInterface); verify(mockMulticastSocket).setNetworkInterface(networkInterface);
verify(mockMulticastSocket).send(datagramPacket); verify(mockMulticastSocket).send(datagramPacket);
@@ -100,20 +94,14 @@ public class MdnsSocketTests {
} }
@Test @Test
public void testIPv6OnlyNetwork_IPv6Enabled() throws IOException { public void ipv6OnlyNetwork_ipv6Enabled() throws IOException {
// Have mockMulticastNetworkInterfaceProvider send back an IPv6Only networkInterfaceWrapper // Have mockMulticastNetworkInterfaceProvider send back an IPv6Only networkInterfaceWrapper
networkInterface = createEmptyNetworkInterface(); networkInterface = createEmptyNetworkInterface();
when(mockNetworkInterfaceWrapper.getNetworkInterface()).thenReturn(networkInterface); when(mockNetworkInterfaceWrapper.getNetworkInterface()).thenReturn(networkInterface);
when(mockMulticastNetworkInterfaceProvider.getMulticastNetworkInterfaces()) when(mockMulticastNetworkInterfaceProvider.getMulticastNetworkInterfaces())
.thenReturn(Collections.singletonList(mockNetworkInterfaceWrapper)); .thenReturn(Collections.singletonList(mockNetworkInterfaceWrapper));
mdnsSocket = mdnsSocket = new MdnsSocket(mockMulticastNetworkInterfaceProvider, mockMulticastSocket);
new MdnsSocket(mockMulticastNetworkInterfaceProvider, MdnsConstants.MDNS_PORT) {
@Override
MulticastSocket createMulticastSocket(int port) throws IOException {
return mockMulticastSocket;
}
};
when(mockMulticastNetworkInterfaceProvider.isOnIpV6OnlyNetwork( when(mockMulticastNetworkInterfaceProvider.isOnIpV6OnlyNetwork(
Collections.singletonList(mockNetworkInterfaceWrapper))) Collections.singletonList(mockNetworkInterfaceWrapper)))
@@ -130,20 +118,14 @@ public class MdnsSocketTests {
} }
@Test @Test
public void testIPv6OnlyNetwork_IPv6Toggle() throws IOException { public void ipv6OnlyNetwork_ipv6Toggle() throws IOException {
// Have mockMulticastNetworkInterfaceProvider send back a networkInterfaceWrapper // Have mockMulticastNetworkInterfaceProvider send back a networkInterfaceWrapper
networkInterface = createEmptyNetworkInterface(); networkInterface = createEmptyNetworkInterface();
when(mockNetworkInterfaceWrapper.getNetworkInterface()).thenReturn(networkInterface); when(mockNetworkInterfaceWrapper.getNetworkInterface()).thenReturn(networkInterface);
when(mockMulticastNetworkInterfaceProvider.getMulticastNetworkInterfaces()) when(mockMulticastNetworkInterfaceProvider.getMulticastNetworkInterfaces())
.thenReturn(Collections.singletonList(mockNetworkInterfaceWrapper)); .thenReturn(Collections.singletonList(mockNetworkInterfaceWrapper));
mdnsSocket = mdnsSocket = new MdnsSocket(mockMulticastNetworkInterfaceProvider, mockMulticastSocket);
new MdnsSocket(mockMulticastNetworkInterfaceProvider, MdnsConstants.MDNS_PORT) {
@Override
MulticastSocket createMulticastSocket(int port) throws IOException {
return mockMulticastSocket;
}
};
when(mockMulticastNetworkInterfaceProvider.isOnIpV6OnlyNetwork( when(mockMulticastNetworkInterfaceProvider.isOnIpV6OnlyNetwork(
Collections.singletonList(mockNetworkInterfaceWrapper))) Collections.singletonList(mockNetworkInterfaceWrapper)))