Expose measurement results to interested callers.
With this it's possible for callers to:
Network network = ...
LinkProperties lp = ...
NetworkDiagnostics netdiag = new NetworkDiagnostics(network, lp, 5000);
netdiag.startMeasurements();
netdiag.waitForMeasurements();
boolean result = true;
for (Measurement m : netdiag.getMeasurements()) {
if (!m.checkSucceeded()) {
result = false;
// Additional error handling here.
}
}
return result;
Bug: 21832299
Bug: 26780890
Change-Id: Iaf7ff029e2c6a998b574c23d0dcde8d57a467a22
diff --git a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
index 5fd39c0..dc62609 100644
--- a/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
+++ b/services/core/java/com/android/server/connectivity/NetworkDiagnostics.java
@@ -49,7 +49,9 @@
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.Arrays;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Random;
@@ -107,27 +109,33 @@
// so callers can wait for completion.
private final CountDownLatch mCountDownLatch;
- private class Measurement {
+ public class Measurement {
private static final String SUCCEEDED = "SUCCEEDED";
private static final String FAILED = "FAILED";
- // TODO: Refactor to make these private for better encapsulation.
- public String description = "";
- public long startTime;
- public long finishTime;
- public String result = "";
- public Thread thread;
+ private boolean succeeded;
- public void recordSuccess(String msg) {
+ // Package private. TODO: investigate better encapsulation.
+ String description = "";
+ long startTime;
+ long finishTime;
+ String result = "";
+ Thread thread;
+
+ public boolean checkSucceeded() { return succeeded; }
+
+ void recordSuccess(String msg) {
maybeFixupTimes();
+ succeeded = true;
result = SUCCEEDED + ": " + msg;
if (mCountDownLatch != null) {
mCountDownLatch.countDown();
}
}
- public void recordFailure(String msg) {
+ void recordFailure(String msg) {
maybeFixupTimes();
+ succeeded = false;
result = FAILED + ": " + msg;
if (mCountDownLatch != null) {
mCountDownLatch.countDown();
@@ -265,6 +273,51 @@
} catch (InterruptedException ignored) {}
}
+ public List<Measurement> getMeasurements() {
+ // TODO: Consider moving waitForMeasurements() in here to minimize the
+ // chance of caller errors.
+
+ ArrayList<Measurement> measurements = new ArrayList(totalMeasurementCount());
+
+ // Sort measurements IPv4 first.
+ for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
+ if (entry.getKey() instanceof Inet4Address) {
+ measurements.add(entry.getValue());
+ }
+ }
+ for (Map.Entry<Pair<InetAddress, InetAddress>, Measurement> entry :
+ mExplicitSourceIcmpChecks.entrySet()) {
+ if (entry.getKey().first instanceof Inet4Address) {
+ measurements.add(entry.getValue());
+ }
+ }
+ for (Map.Entry<InetAddress, Measurement> entry : mDnsUdpChecks.entrySet()) {
+ if (entry.getKey() instanceof Inet4Address) {
+ measurements.add(entry.getValue());
+ }
+ }
+
+ // IPv6 measurements second.
+ for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
+ if (entry.getKey() instanceof Inet6Address) {
+ measurements.add(entry.getValue());
+ }
+ }
+ for (Map.Entry<Pair<InetAddress, InetAddress>, Measurement> entry :
+ mExplicitSourceIcmpChecks.entrySet()) {
+ if (entry.getKey().first instanceof Inet6Address) {
+ measurements.add(entry.getValue());
+ }
+ }
+ for (Map.Entry<InetAddress, Measurement> entry : mDnsUdpChecks.entrySet()) {
+ if (entry.getKey() instanceof Inet6Address) {
+ measurements.add(entry.getValue());
+ }
+ }
+
+ return measurements;
+ }
+
public void dump(IndentingPrintWriter pw) {
pw.println(TAG + ":" + mDescription);
final long unfinished = mCountDownLatch.getCount();
@@ -276,30 +329,13 @@
}
pw.increaseIndent();
- for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
- if (entry.getKey() instanceof Inet4Address) {
- pw.println(entry.getValue().toString());
- }
+
+ String prefix;
+ for (Measurement m : getMeasurements()) {
+ prefix = m.checkSucceeded() ? "." : "F";
+ pw.println(prefix + " " + m.toString());
}
- for (Map.Entry<InetAddress, Measurement> entry : mIcmpChecks.entrySet()) {
- if (entry.getKey() instanceof Inet6Address) {
- pw.println(entry.getValue().toString());
- }
- }
- for (Map.Entry<Pair<InetAddress, InetAddress>, Measurement> entry :
- mExplicitSourceIcmpChecks.entrySet()) {
- pw.println(entry.getValue().toString());
- }
- for (Map.Entry<InetAddress, Measurement> entry : mDnsUdpChecks.entrySet()) {
- if (entry.getKey() instanceof Inet4Address) {
- pw.println(entry.getValue().toString());
- }
- }
- for (Map.Entry<InetAddress, Measurement> entry : mDnsUdpChecks.entrySet()) {
- if (entry.getKey() instanceof Inet6Address) {
- pw.println(entry.getValue().toString());
- }
- }
+
pw.decreaseIndent();
}