DO NOT MERGE NetworkMonitor metrics: add first validation information

This patch adds first validation information to:
  - ValidationProbeEvent, by extending the probe_type int field of to
    also include a bit indicating if the probe was part of a first
    validation attempt or not.
  - NetworkMonitorEvent, by defining new contants for the event_type
    field.

Test: $ runtest frameworks-net
      + manually generating events and inspecting the
        output of $ adb shell dumpsys connmetrics list
Bug: b/32198726

(cherry picked from commit 147aa6d53b)

Change-Id: I7ed954dee006f8804a5bf8940eec180714bddd07
This commit is contained in:
Hugo Benichi
2016-11-15 23:23:24 +09:00
parent a4f17bcbdf
commit dd22982e25
3 changed files with 85 additions and 12 deletions

View File

@@ -41,6 +41,15 @@ public final class NetworkEvent implements Parcelable {
public static final int NETWORK_UNLINGER = 6;
public static final int NETWORK_DISCONNECTED = 7;
/** {@hide} */
public static final int NETWORK_FIRST_VALIDATION_SUCCESS = 8;
/** {@hide} */
public static final int NETWORK_REVALIDATION_SUCCESS = 9;
/** {@hide} */
public static final int NETWORK_FIRST_VALIDATION_PORTAL_FOUND = 10;
/** {@hide} */
public static final int NETWORK_REVALIDATION_PORTAL_FOUND = 11;
/** {@hide} */
@IntDef(value = {
NETWORK_CONNECTED,
@@ -50,6 +59,10 @@ public final class NetworkEvent implements Parcelable {
NETWORK_LINGER,
NETWORK_UNLINGER,
NETWORK_DISCONNECTED,
NETWORK_FIRST_VALIDATION_SUCCESS,
NETWORK_REVALIDATION_SUCCESS,
NETWORK_FIRST_VALIDATION_PORTAL_FOUND,
NETWORK_REVALIDATION_PORTAL_FOUND,
})
@Retention(RetentionPolicy.SOURCE)
public @interface EventType {}

View File

@@ -44,10 +44,8 @@ public final class ValidationProbeEvent implements Parcelable {
public static final int DNS_FAILURE = 0;
public static final int DNS_SUCCESS = 1;
/** {@hide} */
@IntDef(value = {PROBE_DNS, PROBE_HTTP, PROBE_HTTPS, PROBE_PAC})
@Retention(RetentionPolicy.SOURCE)
public @interface ProbeType {}
private static final int FIRST_VALIDATION = 1 << 8;
private static final int REVALIDATION = 2 << 8;
/** {@hide} */
@IntDef(value = {DNS_FAILURE, DNS_SUCCESS})
@@ -56,12 +54,17 @@ public final class ValidationProbeEvent implements Parcelable {
public final int netId;
public final long durationMs;
public final @ProbeType int probeType;
// probeType byte format (MSB to LSB):
// byte 0: unused
// byte 1: unused
// byte 2: 0 = UNKNOWN, 1 = FIRST_VALIDATION, 2 = REVALIDATION
// byte 3: PROBE_* constant
public final int probeType;
public final @ReturnCode int returnCode;
/** {@hide} */
public ValidationProbeEvent(
int netId, long durationMs, @ProbeType int probeType, @ReturnCode int returnCode) {
int netId, long durationMs, int probeType, @ReturnCode int returnCode) {
this.netId = netId;
this.durationMs = durationMs;
this.probeType = probeType;
@@ -99,9 +102,19 @@ public final class ValidationProbeEvent implements Parcelable {
}
};
/** @hide */
public static int makeProbeType(int probeType, boolean firstValidation) {
return (probeType & 0xff) | (firstValidation ? FIRST_VALIDATION : REVALIDATION);
}
/** @hide */
public static String getProbeName(int probeType) {
return Decoder.constants.get(probeType, "PROBE_???");
return Decoder.constants.get(probeType & 0xff, "PROBE_???");
}
/** @hide */
public static String getValidationStage(int probeType) {
return Decoder.constants.get(probeType & 0xff00, "UNKNOWN");
}
public static void logEvent(int netId, long durationMs, int probeType, int returnCode) {
@@ -109,12 +122,13 @@ public final class ValidationProbeEvent implements Parcelable {
@Override
public String toString() {
return String.format("ValidationProbeEvent(%d, %s:%d, %dms)",
netId, getProbeName(probeType), returnCode, durationMs);
return String.format("ValidationProbeEvent(%d, %s:%d %s, %dms)", netId,
getProbeName(probeType), returnCode, getValidationStage(probeType), durationMs);
}
final static class Decoder {
static final SparseArray<String> constants = MessageUtils.findMessageNames(
new Class[]{ValidationProbeEvent.class}, new String[]{"PROBE_"});
new Class[]{ValidationProbeEvent.class},
new String[]{"PROBE_", "FIRST_", "REVALIDATION"});
}
}

View File

@@ -97,6 +97,24 @@ public class NetworkMonitor extends StateMachine {
private static final int SOCKET_TIMEOUT_MS = 10000;
private static final int PROBE_TIMEOUT_MS = 3000;
static enum EvaluationResult {
VALIDATED(true),
CAPTIVE_PORTAL(false);
final boolean isValidated;
EvaluationResult(boolean isValidated) {
this.isValidated = isValidated;
}
}
static enum ValidationStage {
FIRST_VALIDATION(true),
REVALIDATION(false);
final boolean isFirstValidation;
ValidationStage(boolean isFirstValidation) {
this.isFirstValidation = isFirstValidation;
}
}
public static final String ACTION_NETWORK_CONDITIONS_MEASURED =
"android.net.conn.NETWORK_CONDITIONS_MEASURED";
public static final String EXTRA_CONNECTIVITY_TYPE = "extra_connectivity_type";
@@ -216,6 +234,8 @@ public class NetworkMonitor extends StateMachine {
protected boolean mIsCaptivePortalCheckEnabled;
private boolean mUseHttps;
// The total number of captive portal detection attempts for this NetworkMonitor instance.
private int mValidations = 0;
// Set if the user explicitly selected "Do not use this network" in captive portal sign-in app.
private boolean mUserDoesNotWant = false;
@@ -290,6 +310,10 @@ public class NetworkMonitor extends StateMachine {
return validationLogs.readOnlyLocalLog();
}
private ValidationStage validationStage() {
return 0 == mValidations ? ValidationStage.FIRST_VALIDATION : ValidationStage.REVALIDATION;
}
// DefaultState is the parent of all States. It exists only to handle CMD_* messages but
// does not entail any real state (hence no enter() or exit() routines).
private class DefaultState extends State {
@@ -366,9 +390,11 @@ public class NetworkMonitor extends StateMachine {
private class ValidatedState extends State {
@Override
public void enter() {
maybeLogEvaluationResult(NetworkEvent.NETWORK_VALIDATED);
maybeLogEvaluationResult(
networkEventType(validationStage(), EvaluationResult.VALIDATED));
mConnectivityServiceHandler.sendMessage(obtainMessage(EVENT_NETWORK_TESTED,
NETWORK_TEST_RESULT_VALID, mNetworkAgentInfo.network.netId, null));
mValidations++;
}
@Override
@@ -584,7 +610,8 @@ public class NetworkMonitor extends StateMachine {
@Override
public void enter() {
maybeLogEvaluationResult(NetworkEvent.NETWORK_CAPTIVE_PORTAL_FOUND);
maybeLogEvaluationResult(
networkEventType(validationStage(), EvaluationResult.CAPTIVE_PORTAL));
// Don't annoy user with sign-in notifications.
if (mDontDisplaySigninNotification) return;
// Create a CustomIntentReceiver that sends us a
@@ -604,6 +631,7 @@ public class NetworkMonitor extends StateMachine {
// Retest for captive portal occasionally.
sendMessageDelayed(CMD_CAPTIVE_PORTAL_RECHECK, 0 /* no UID */,
CAPTIVE_PORTAL_REEVALUATE_DELAY_MS);
mValidations++;
}
@Override
@@ -974,6 +1002,22 @@ public class NetworkMonitor extends StateMachine {
mMetricsLog.log(new NetworkEvent(mNetId, evtype));
}
private int networkEventType(ValidationStage s, EvaluationResult r) {
if (s.isFirstValidation) {
if (r.isValidated) {
return NetworkEvent.NETWORK_FIRST_VALIDATION_SUCCESS;
} else {
return NetworkEvent.NETWORK_FIRST_VALIDATION_PORTAL_FOUND;
}
} else {
if (r.isValidated) {
return NetworkEvent.NETWORK_REVALIDATION_SUCCESS;
} else {
return NetworkEvent.NETWORK_REVALIDATION_PORTAL_FOUND;
}
}
}
private void maybeLogEvaluationResult(int evtype) {
if (mEvaluationTimer.isRunning()) {
mMetricsLog.log(new NetworkEvent(mNetId, evtype, mEvaluationTimer.stop()));
@@ -982,6 +1026,8 @@ public class NetworkMonitor extends StateMachine {
}
private void logValidationProbe(long durationMs, int probeType, int probeResult) {
probeType =
ValidationProbeEvent.makeProbeType(probeType, validationStage().isFirstValidation);
mMetricsLog.log(new ValidationProbeEvent(mNetId, durationMs, probeType, probeResult));
}
}