summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRemi NGUYEN VAN <reminv@google.com>2020-07-06 03:26:19 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2020-07-06 03:26:19 +0000
commite99c5ee2051025f5c7f9225f4576d5123e30a6e8 (patch)
treea470cd812f16e554f17faaa379485087eb07bb14
parente1cabba716f66dd8197f0c19bb6502af8cae9c24 (diff)
parent63e923abc2206a4df91135a8ab0e91d66aa6d9ad (diff)
Merge "Refine validation metrics" into rvc-dev am: bf45240a2a am: 63e923abc2
Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/modules/NetworkStack/+/12004083 Change-Id: I91fcb23b9c1511b2c830899c9cbbd64bc2201ac3
-rwxr-xr-xsrc/android/net/util/NetworkStackUtils.java15
-rw-r--r--src/com/android/networkstack/metrics/NetworkValidationMetrics.java84
-rwxr-xr-xsrc/com/android/server/connectivity/NetworkMonitor.java101
-rw-r--r--tests/unit/src/com/android/networkstack/metrics/NetworkValidationMetricsTest.java42
4 files changed, 169 insertions, 73 deletions
diff --git a/src/android/net/util/NetworkStackUtils.java b/src/android/net/util/NetworkStackUtils.java
index 19ca4b5..94de7c3 100755
--- a/src/android/net/util/NetworkStackUtils.java
+++ b/src/android/net/util/NetworkStackUtils.java
@@ -226,6 +226,15 @@ public class NetworkStackUtils {
public static final String DNS_PROBE_PRIVATE_IP_NO_INTERNET_VERSION =
"dns_probe_private_ip_no_internet";
+ /**
+ * Experiment flag to enable validation metrics sent by NetworkMonitor.
+ *
+ * Metrics are sent by default. They can be disabled by setting the flag to a number greater
+ * than the APK version (for example 999999999).
+ * @see #isFeatureEnabled(Context, String, String, boolean)
+ */
+ public static final String VALIDATION_METRICS_VERSION = "validation_metrics_version";
+
static {
System.loadLibrary("networkstackutilsjni");
}
@@ -348,6 +357,9 @@ public class NetworkStackUtils {
* {@link DeviceConfig} is enabled by comparing NetworkStack module version {@link NetworkStack}
* with current version of property. If this property version is valid, the corresponding
* experimental feature would be enabled, otherwise disabled.
+ *
+ * This is useful to ensure that if a module install is rolled back, flags are not left fully
+ * rolled out on a version where they have not been well tested.
* @param context The global context information about an app environment.
* @param namespace The namespace containing the property to look up.
* @param name The name of the property to look up.
@@ -363,6 +375,9 @@ public class NetworkStackUtils {
* {@link DeviceConfig} is enabled by comparing NetworkStack module version {@link NetworkStack}
* with current version of property. If this property version is valid, the corresponding
* experimental feature would be enabled, otherwise disabled.
+ *
+ * This is useful to ensure that if a module install is rolled back, flags are not left fully
+ * rolled out on a version where they have not been well tested.
* @param context The global context information about an app environment.
* @param namespace The namespace containing the property to look up.
* @param name The name of the property to look up.
diff --git a/src/com/android/networkstack/metrics/NetworkValidationMetrics.java b/src/com/android/networkstack/metrics/NetworkValidationMetrics.java
index 3789c5c..f27a939 100644
--- a/src/com/android/networkstack/metrics/NetworkValidationMetrics.java
+++ b/src/com/android/networkstack/metrics/NetworkValidationMetrics.java
@@ -60,9 +60,11 @@ public class NetworkValidationMetrics {
public static final int MAX_PROBE_EVENTS_COUNT = 20;
/**
- * Reset this NetworkValidationMetrics.
+ * Reset this NetworkValidationMetrics and start collecting timing and metrics.
+ *
+ * <p>This must be called when validation starts.
*/
- public void reset(@Nullable NetworkCapabilities nc) {
+ public void startCollection(@Nullable NetworkCapabilities nc) {
mStatsBuilder.clear();
mProbeEventsBuilder.clear();
mCapportApiDataBuilder.clear();
@@ -72,16 +74,23 @@ public class NetworkValidationMetrics {
}
/**
- * Returns the enum TransportType
+ * Returns the enum TransportType.
+ *
+ * <p>This method only supports a limited set of common transport type combinations that can be
+ * measured through metrics, and will return {@link TransportType#TT_UNKNOWN} for others. This
+ * ensures that, for example, metrics for a TRANSPORT_NEW_UNKNOWN | TRANSPORT_ETHERNET network
+ * cannot get aggregated with / compared with a "normal" TRANSPORT_ETHERNET network without
+ * noticing.
*
- * @param NetworkCapabilities
+ * @param nc Capabilities to extract transport type from.
* @return the TransportType which is defined in
* core/proto/android/stats/connectivity/network_stack.proto
*/
@VisibleForTesting
- public static TransportType getTransportTypeFromNC(
- @Nullable NetworkCapabilities nc) {
+ public static TransportType getTransportTypeFromNC(@Nullable NetworkCapabilities nc) {
if (nc == null) return TransportType.TT_UNKNOWN;
+
+ final int trCount = nc.getTransportTypes().length;
boolean hasCellular = nc.hasTransport(TRANSPORT_CELLULAR);
boolean hasWifi = nc.hasTransport(TRANSPORT_WIFI);
boolean hasBT = nc.hasTransport(TRANSPORT_BLUETOOTH);
@@ -90,13 +99,29 @@ public class NetworkValidationMetrics {
boolean hasWifiAware = nc.hasTransport(TRANSPORT_WIFI_AWARE);
boolean hasLopan = nc.hasTransport(TRANSPORT_LOWPAN);
- if (hasCellular && hasWifi && hasVpn) return TransportType.TT_WIFI_CELLULAR_VPN;
- if (hasWifi) return hasVpn ? TransportType.TT_WIFI_VPN : TransportType.TT_WIFI;
- if (hasCellular) return hasVpn ? TransportType.TT_CELLULAR_VPN : TransportType.TT_CELLULAR;
- if (hasBT) return hasVpn ? TransportType.TT_BLUETOOTH_VPN : TransportType.TT_BLUETOOTH;
- if (hasEthernet) return hasVpn ? TransportType.TT_ETHERNET_VPN : TransportType.TT_ETHERNET;
- if (hasWifiAware) return TransportType.TT_WIFI_AWARE;
- if (hasLopan) return TransportType.TT_LOWPAN;
+ // VPN networks are not subject to validation and should not see validation stats, but
+ // metrics could be added to measure private DNS probes only.
+ if (trCount == 3 && hasCellular && hasWifi && hasVpn) {
+ return TransportType.TT_WIFI_CELLULAR_VPN;
+ }
+
+ if (trCount == 2 && hasVpn) {
+ if (hasWifi) return TransportType.TT_WIFI_VPN;
+ if (hasCellular) return TransportType.TT_CELLULAR_VPN;
+ if (hasBT) return TransportType.TT_BLUETOOTH_VPN;
+ if (hasEthernet) return TransportType.TT_ETHERNET_VPN;
+ }
+
+ if (trCount == 1) {
+ if (hasWifi) return TransportType.TT_WIFI;
+ if (hasCellular) return TransportType.TT_CELLULAR;
+ if (hasBT) return TransportType.TT_BLUETOOTH;
+ if (hasEthernet) return TransportType.TT_ETHERNET;
+ if (hasWifiAware) return TransportType.TT_WIFI_AWARE;
+ if (hasLopan) return TransportType.TT_LOWPAN;
+ // TODO: consider having a TT_VPN for VPN-only transport
+ }
+
return TransportType.TT_UNKNOWN;
}
@@ -146,6 +171,8 @@ public class NetworkValidationMetrics {
*/
@VisibleForTesting
public static ValidationResult validationResultToEnum(int result, String redirectUrl) {
+ // TODO: consider adding a VR_PARTIAL_SUCCESS field to track cases where users accepted
+ // partial connectivity
if ((result & INetworkMonitor.NETWORK_VALIDATION_RESULT_VALID) != 0) {
return ValidationResult.VR_SUCCESS;
} else if (redirectUrl != null) {
@@ -158,12 +185,14 @@ public class NetworkValidationMetrics {
}
/**
- * Write each network probe event to mProbeEventsBuilder.
+ * Add a network probe event to the metrics builder.
*/
- public void setProbeEvent(final ProbeType type, final long durationUs, final ProbeResult result,
+ public void addProbeEvent(final ProbeType type, final long durationUs, final ProbeResult result,
@Nullable final CaptivePortalDataShim capportData) {
// When the number of ProbeEvents of mProbeEventsBuilder exceeds
// MAX_PROBE_EVENTS_COUNT, stop adding ProbeEvent.
+ // TODO: consider recording the total number of probes in a separate field to know how
+ // many probes are skipped.
if (mProbeEventsBuilder.getProbeEventCount() >= MAX_PROBE_EVENTS_COUNT) return;
int latencyUs = NetworkStackUtils.saturatedCast(durationUs);
@@ -178,7 +207,9 @@ public class NetworkValidationMetrics {
(capportData.getExpiryTimeMillis() - currentTimeMillis()) / 1000;
mCapportApiDataBuilder
.setRemainingTtlSecs(NetworkStackUtils.saturatedCast(secondsRemaining))
- .setRemainingBytes(NetworkStackUtils.saturatedCast(capportData.getByteLimit()))
+ // TODO: rename this field to setRemainingKBytes, or use a long
+ .setRemainingBytes(
+ NetworkStackUtils.saturatedCast(capportData.getByteLimit() / 1000))
.setHasPortalUrl((capportData.getUserPortalUrl() != null))
.setHasVenueInfo((capportData.getVenueInfoUrl() != null));
probeEventBuilder.setCapportApiData(mCapportApiDataBuilder);
@@ -196,25 +227,28 @@ public class NetworkValidationMetrics {
/**
* Write the NetworkValidationReported proto to statsd.
+ *
+ * <p>This is a no-op if {@link #startCollection(NetworkCapabilities)} was not called since the
+ * last call to this method.
*/
- public NetworkValidationReported sendValidationStats() {
+ public NetworkValidationReported maybeStopCollectionAndSend() {
if (!mWatch.isStarted()) return null;
mStatsBuilder.setProbeEvents(mProbeEventsBuilder);
mStatsBuilder.setLatencyMicros(NetworkStackUtils.saturatedCast(mWatch.stop()));
mStatsBuilder.setValidationIndex(mValidationIndex);
// write a random value(0 ~ 999) for sampling.
mStatsBuilder.setRandomNumber((int) (Math.random() * 1000));
- final NetworkValidationReported mStats = mStatsBuilder.build();
- final byte[] probeEvents = mStats.getProbeEvents().toByteArray();
+ final NetworkValidationReported stats = mStatsBuilder.build();
+ final byte[] probeEvents = stats.getProbeEvents().toByteArray();
NetworkStackStatsLog.write(NetworkStackStatsLog.NETWORK_VALIDATION_REPORTED,
- mStats.getTransportType().getNumber(),
+ stats.getTransportType().getNumber(),
probeEvents,
- mStats.getValidationResult().getNumber(),
- mStats.getLatencyMicros(),
- mStats.getValidationIndex(),
- mStats.getRandomNumber());
+ stats.getValidationResult().getNumber(),
+ stats.getLatencyMicros(),
+ stats.getValidationIndex(),
+ stats.getRandomNumber());
mWatch.reset();
- return mStats;
+ return stats;
}
}
diff --git a/src/com/android/server/connectivity/NetworkMonitor.java b/src/com/android/server/connectivity/NetworkMonitor.java
index 47c910a..40de26e 100755
--- a/src/com/android/server/connectivity/NetworkMonitor.java
+++ b/src/com/android/server/connectivity/NetworkMonitor.java
@@ -450,7 +450,14 @@ public class NetworkMonitor extends StateMachine {
protected boolean mIsCaptivePortalCheckEnabled;
private boolean mUseHttps;
- // The total number of captive portal detection attempts for this NetworkMonitor instance.
+ /**
+ * The total number of completed validation attempts (network validated or a captive portal was
+ * detected) for this NetworkMonitor instance.
+ * This does not include attempts that were interrupted, retried or finished with a result that
+ * is not success or portal. See {@code mValidationIndex} in {@link NetworkValidationMetrics}
+ * for a count of all attempts.
+ * TODO: remove when removing legacy metrics.
+ */
private int mValidations = 0;
// Set if the user explicitly selected "Do not use this network" in captive portal sign-in app.
@@ -504,6 +511,14 @@ public class NetworkMonitor extends StateMachine {
private final boolean mPrivateIpNoInternetEnabled;
+ private final boolean mMetricsEnabled;
+
+ // The validation metrics are accessed by individual probe threads, and by the StateMachine
+ // thread. All accesses must be synchronized to make sure the StateMachine thread can see
+ // reports from all probes.
+ // TODO: as that most usage is in the StateMachine thread and probes only add their probe
+ // events, consider having probes return their stats to the StateMachine, and only access this
+ // member on the StateMachine thread without synchronization.
@GuardedBy("mNetworkValidationMetrics")
private final NetworkValidationMetrics mNetworkValidationMetrics =
new NetworkValidationMetrics();
@@ -571,6 +586,8 @@ public class NetworkMonitor extends StateMachine {
mIsCaptivePortalCheckEnabled = getIsCaptivePortalCheckEnabled();
mPrivateIpNoInternetEnabled = getIsPrivateIpNoInternetEnabled();
+ mMetricsEnabled = deps.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY,
+ NetworkStackUtils.VALIDATION_METRICS_VERSION, true /* defaultEnabled */);
mUseHttps = getUseHttpsValidation();
mCaptivePortalUserAgent = getCaptivePortalUserAgent();
mCaptivePortalHttpsUrls = makeCaptivePortalHttpsUrls();
@@ -783,28 +800,48 @@ public class NetworkMonitor extends StateMachine {
}
}
- private void recordMetricsReset(@Nullable NetworkCapabilities nc) {
- synchronized (mNetworkValidationMetrics) {
- mNetworkValidationMetrics.reset(nc);
+ private void startMetricsCollection() {
+ if (!mMetricsEnabled) return;
+ try {
+ synchronized (mNetworkValidationMetrics) {
+ mNetworkValidationMetrics.startCollection(mNetworkCapabilities);
+ }
+ } catch (Exception e) {
+ Log.wtf(TAG, "Error resetting validation metrics", e);
}
}
- private void recordMetricsProbeEvent(ProbeType type, long latencyMicros, ProbeResult result,
+ private void recordProbeEventMetrics(ProbeType type, long latencyMicros, ProbeResult result,
CaptivePortalDataShim capportData) {
- synchronized (mNetworkValidationMetrics) {
- mNetworkValidationMetrics.setProbeEvent(type, latencyMicros, result, capportData);
+ if (!mMetricsEnabled) return;
+ try {
+ synchronized (mNetworkValidationMetrics) {
+ mNetworkValidationMetrics.addProbeEvent(type, latencyMicros, result, capportData);
+ }
+ } catch (Exception e) {
+ Log.wtf(TAG, "Error recording probe event", e);
}
}
- private void recordMetricsValidationResult(int result, String redirectUrl) {
- synchronized (mNetworkValidationMetrics) {
- mNetworkValidationMetrics.setValidationResult(result, redirectUrl);
+ private void recordValidationResult(int result, String redirectUrl) {
+ if (!mMetricsEnabled) return;
+ try {
+ synchronized (mNetworkValidationMetrics) {
+ mNetworkValidationMetrics.setValidationResult(result, redirectUrl);
+ }
+ } catch (Exception e) {
+ Log.wtf(TAG, "Error recording validation result", e);
}
}
- private void recordMetricsValidationStats() {
- synchronized (mNetworkValidationMetrics) {
- mNetworkValidationMetrics.sendValidationStats();
+ private void maybeStopCollectionAndSendMetrics() {
+ if (!mMetricsEnabled) return;
+ try {
+ synchronized (mNetworkValidationMetrics) {
+ mNetworkValidationMetrics.maybeStopCollectionAndSend();
+ }
+ } catch (Exception e) {
+ Log.wtf(TAG, "Error sending validation stats", e);
}
}
@@ -820,7 +857,7 @@ public class NetworkMonitor extends StateMachine {
transitionTo(mEvaluatingState);
return HANDLED;
case CMD_NETWORK_DISCONNECTED:
- recordMetricsValidationStats();
+ maybeStopCollectionAndSendMetrics();
logNetworkEvent(NetworkEvent.NETWORK_DISCONNECTED);
quit();
return HANDLED;
@@ -972,7 +1009,7 @@ public class NetworkMonitor extends StateMachine {
initSocketTrackingIfRequired();
// start periodical polling.
sendTcpPollingEvent();
- recordMetricsValidationStats();
+ maybeStopCollectionAndSendMetrics();
}
private void initSocketTrackingIfRequired() {
@@ -1323,7 +1360,7 @@ public class NetworkMonitor extends StateMachine {
sendMessageDelayed(CMD_CAPTIVE_PORTAL_RECHECK, 0 /* no UID */,
CAPTIVE_PORTAL_REEVALUATE_DELAY_MS);
mValidations++;
- recordMetricsValidationStats();
+ maybeStopCollectionAndSendMetrics();
}
@Override
@@ -1357,7 +1394,9 @@ public class NetworkMonitor extends StateMachine {
handlePrivateDnsEvaluationFailure();
// The private DNS probe fails-fast if the server hostname cannot
// be resolved. Record it as a failure with zero latency.
- recordMetricsProbeEvent(ProbeType.PT_PRIVDNS, 0 /* latency */,
+ // TODO: refactor this together with the probe recorded in
+ // sendPrivateDnsProbe, so logging is symmetric / easier to follow.
+ recordProbeEventMetrics(ProbeType.PT_PRIVDNS, 0 /* latency */,
ProbeResult.PR_FAILURE, null /* capportData */);
break;
}
@@ -1468,7 +1507,7 @@ public class NetworkMonitor extends StateMachine {
validationLog(PROBE_PRIVDNS, host,
String.format("%dus - Error: %s", time, uhe.getMessage()));
}
- recordMetricsProbeEvent(ProbeType.PT_PRIVDNS, time, success ? ProbeResult.PR_SUCCESS :
+ recordProbeEventMetrics(ProbeType.PT_PRIVDNS, time, success ? ProbeResult.PR_SUCCESS :
ProbeResult.PR_FAILURE, null /* capportData */);
logValidationProbe(time, PROBE_PRIVDNS, success ? DNS_SUCCESS : DNS_FAILURE);
return success;
@@ -1480,8 +1519,14 @@ public class NetworkMonitor extends StateMachine {
@Override
public void enter() {
- recordMetricsValidationStats();
- recordMetricsReset(mNetworkCapabilities);
+ // When starting a full probe cycle here, record any pending stats (for example if
+ // CMD_FORCE_REEVALUATE was called before evaluation finished, as can happen in
+ // EvaluatingPrivateDnsState).
+ maybeStopCollectionAndSendMetrics();
+ // Restart the metrics collection timers. Metrics will be stopped and sent when the
+ // validation attempt finishes (as success, failure or portal), or if it is interrupted
+ // (by being restarted or if NetworkMonitor stops).
+ startMetricsCollection();
if (mEvaluateAttempts >= BLAME_FOR_EVALUATION_ATTEMPTS) {
//Don't continue to blame UID forever.
TrafficStats.clearThreadStatsUid();
@@ -1563,7 +1608,9 @@ public class NetworkMonitor extends StateMachine {
private class WaitingForNextProbeState extends State {
@Override
public void enter() {
- recordMetricsValidationStats();
+ // Send metrics for this evaluation attempt. Metrics collection (and its timers) will be
+ // restarted when the next probe starts.
+ maybeStopCollectionAndSendMetrics();
scheduleNextProbe();
}
@@ -2313,7 +2360,7 @@ public class NetworkMonitor extends StateMachine {
// network validation (the HTTPS probe, which would likely fail anyway) or the PAC probe.
if (mPrivateIpNoInternetEnabled && probeType == ValidationProbeEvent.PROBE_HTTP
&& (proxy == null) && hasPrivateIpAddress(resolvedAddr)) {
- recordMetricsProbeEvent(NetworkValidationMetrics.probeTypeToEnum(probeType),
+ recordProbeEventMetrics(NetworkValidationMetrics.probeTypeToEnum(probeType),
0 /* latency */, ProbeResult.PR_PRIVATE_IP_DNS, null /* capportData */);
return CaptivePortalProbeResult.PRIVATE_IP;
}
@@ -2346,7 +2393,7 @@ public class NetworkMonitor extends StateMachine {
result = ValidationProbeEvent.DNS_FAILURE;
}
final long latency = watch.stop();
- recordMetricsProbeEvent(ProbeType.PT_DNS, latency,
+ recordProbeEventMetrics(ProbeType.PT_DNS, latency,
(result == ValidationProbeEvent.DNS_SUCCESS) ? ProbeResult.PR_SUCCESS :
ProbeResult.PR_FAILURE, null /* capportData */);
logValidationProbe(latency, ValidationProbeEvent.PROBE_DNS, result);
@@ -2473,7 +2520,7 @@ public class NetworkMonitor extends StateMachine {
} else {
probeResult = probeSpec.getResult(httpResponseCode, redirectUrl);
}
- recordMetricsProbeEvent(NetworkValidationMetrics.probeTypeToEnum(probeType),
+ recordProbeEventMetrics(NetworkValidationMetrics.probeTypeToEnum(probeType),
probeTimer.stop(), NetworkValidationMetrics.httpProbeResultToEnum(probeResult),
null /* capportData */);
return probeResult;
@@ -2629,6 +2676,8 @@ public class NetworkMonitor extends StateMachine {
}
private CaptivePortalDataShim sendCapportApiProbe() {
+ // TODO: consider adding metrics counters for each case returning null in this method
+ // (cases where the API is not implemented properly).
validationLog("Fetching captive portal data from " + mCaptivePortalApiUrl);
final String apiContent;
@@ -2689,7 +2738,7 @@ public class NetworkMonitor extends StateMachine {
if (mCaptivePortalApiUrl == null) return null;
final Stopwatch capportApiWatch = new Stopwatch().start();
final CaptivePortalDataShim capportData = sendCapportApiProbe();
- recordMetricsProbeEvent(ProbeType.PT_CAPPORT_API, capportApiWatch.stop(),
+ recordProbeEventMetrics(ProbeType.PT_CAPPORT_API, capportApiWatch.stop(),
capportData == null ? ProbeResult.PR_FAILURE : ProbeResult.PR_SUCCESS,
capportData);
return capportData;
@@ -3412,7 +3461,7 @@ public class NetworkMonitor extends StateMachine {
p.redirectUrl = redirectUrl;
p.timestampMillis = SystemClock.elapsedRealtime();
notifyNetworkTested(p);
- recordMetricsValidationResult(result, redirectUrl);
+ recordValidationResult(result, redirectUrl);
}
@VisibleForTesting
diff --git a/tests/unit/src/com/android/networkstack/metrics/NetworkValidationMetricsTest.java b/tests/unit/src/com/android/networkstack/metrics/NetworkValidationMetricsTest.java
index af68cde..98e7b63 100644
--- a/tests/unit/src/com/android/networkstack/metrics/NetworkValidationMetricsTest.java
+++ b/tests/unit/src/com/android/networkstack/metrics/NetworkValidationMetricsTest.java
@@ -26,7 +26,6 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static org.junit.Assume.assumeTrue;
import android.net.INetworkMonitor;
import android.net.NetworkCapabilities;
@@ -54,7 +53,7 @@ public class NetworkValidationMetricsTest {
private static final String TEST_VENUE_INFO_URL = "https://venue.example.com/info";
private static final int TTL_TOLERANCE_SECS = 10;
- private static final NetworkCapabilities WIFI_NOT_METERED_CAPABILITIES =
+ private static final NetworkCapabilities WIFI_CAPABILITIES =
new NetworkCapabilities()
.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
@@ -136,17 +135,17 @@ public class NetworkValidationMetricsTest {
@Test
public void testNetworkValidationMetrics_VerifyConsecutiveProbeFailure() throws Exception {
- final NetworkValidationMetrics Metrics = new NetworkValidationMetrics();
- Metrics.reset(WIFI_NOT_METERED_CAPABILITIES);
+ final NetworkValidationMetrics metrics = new NetworkValidationMetrics();
+ metrics.startCollection(WIFI_CAPABILITIES);
// 1. PT_DNS probe
- Metrics.setProbeEvent(ProbeType.PT_DNS, 1234, ProbeResult.PR_SUCCESS, null);
+ metrics.addProbeEvent(ProbeType.PT_DNS, 1234, ProbeResult.PR_SUCCESS, null);
// 2. Consecutive PT_HTTP probe failure
for (int i = 0; i < 30; i++) {
- Metrics.setProbeEvent(ProbeType.PT_HTTP, 1234, ProbeResult.PR_FAILURE, null);
+ metrics.addProbeEvent(ProbeType.PT_HTTP, 1234, ProbeResult.PR_FAILURE, null);
}
// Write metric into statsd
- final NetworkValidationReported stats = Metrics.sendValidationStats();
+ final NetworkValidationReported stats = metrics.maybeStopCollectionAndSend();
// The maximum number of probe records should be the same as MAX_PROBE_EVENTS_COUNT
final ProbeEvents probeEvents = stats.getProbeEvents();
@@ -156,40 +155,39 @@ public class NetworkValidationMetricsTest {
@Test
public void testNetworkValidationMetrics_VerifyCollectMetrics() throws Exception {
- assumeTrue(CaptivePortalDataShimImpl.isSupported());
- final long bytesRemaining = 10L;
+ final long bytesRemaining = 12_345L;
final long secondsRemaining = 3000L;
String apiContent = "{'captive': true,"
+ "'user-portal-url': '" + TEST_LOGIN_URL + "',"
+ "'venue-info-url': '" + TEST_VENUE_INFO_URL + "',"
+ "'bytes-remaining': " + bytesRemaining + ","
+ "'seconds-remaining': " + secondsRemaining + "}";
- final NetworkValidationMetrics Metrics = new NetworkValidationMetrics();
+ final NetworkValidationMetrics metrics = new NetworkValidationMetrics();
final int validationIndex = 1;
- final long longlatency = 2147483649L;
- Metrics.reset(WIFI_NOT_METERED_CAPABILITIES);
+ final long longlatency = Integer.MAX_VALUE + 12344567L;
+ metrics.startCollection(WIFI_CAPABILITIES);
final JSONObject info = new JSONObject(apiContent);
- final CaptivePortalDataShim captivePortalData =
- CaptivePortalDataShimImpl.fromJson(info);
+ final CaptivePortalDataShim captivePortalData = CaptivePortalDataShimImpl.isSupported()
+ ? CaptivePortalDataShimImpl.fromJson(info) : null;
// 1. PT_CAPPORT_API probe w CapportApiData info
- Metrics.setProbeEvent(ProbeType.PT_CAPPORT_API, 1234, ProbeResult.PR_SUCCESS,
+ metrics.addProbeEvent(ProbeType.PT_CAPPORT_API, 1234, ProbeResult.PR_SUCCESS,
captivePortalData);
// 2. PT_CAPPORT_API probe w/o CapportApiData info
- Metrics.setProbeEvent(ProbeType.PT_CAPPORT_API, 1234, ProbeResult.PR_FAILURE, null);
+ metrics.addProbeEvent(ProbeType.PT_CAPPORT_API, 1234, ProbeResult.PR_FAILURE, null);
// 3. PT_DNS probe
- Metrics.setProbeEvent(ProbeType.PT_DNS, 5678, ProbeResult.PR_FAILURE, null);
+ metrics.addProbeEvent(ProbeType.PT_DNS, 5678, ProbeResult.PR_FAILURE, null);
// 4. PT_HTTP probe
- Metrics.setProbeEvent(ProbeType.PT_HTTP, longlatency, ProbeResult.PR_PORTAL, null);
+ metrics.addProbeEvent(ProbeType.PT_HTTP, longlatency, ProbeResult.PR_PORTAL, null);
// add Validation result
- Metrics.setValidationResult(INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL, null);
+ metrics.setValidationResult(INetworkMonitor.NETWORK_VALIDATION_RESULT_PARTIAL, null);
// Write metric into statsd
- final NetworkValidationReported stats = Metrics.sendValidationStats();
+ final NetworkValidationReported stats = metrics.maybeStopCollectionAndSend();
// Verify: TransportType: WIFI
assertEquals(TransportType.TT_WIFI, stats.getTransportType());
@@ -207,13 +205,13 @@ public class NetworkValidationMetricsTest {
assertEquals(ProbeType.PT_CAPPORT_API, probeEvent.getProbeType());
assertEquals(1234, probeEvent.getLatencyMicros());
assertEquals(ProbeResult.PR_SUCCESS, probeEvent.getProbeResult());
- assertEquals(true, probeEvent.hasCapportApiData());
if (CaptivePortalDataShimImpl.isSupported()) {
+ assertTrue(probeEvent.hasCapportApiData());
// Set secondsRemaining to 3000 and check that getRemainingTtlSecs is within 10 seconds
final CapportApiData capportData = probeEvent.getCapportApiData();
assertTrue(capportData.getRemainingTtlSecs() <= secondsRemaining);
assertTrue(capportData.getRemainingTtlSecs() + TTL_TOLERANCE_SECS > secondsRemaining);
- assertEquals(captivePortalData.getByteLimit(), capportData.getRemainingBytes());
+ assertEquals(captivePortalData.getByteLimit() / 1000, capportData.getRemainingBytes());
} else {
assertFalse(probeEvent.hasCapportApiData());
}