Better ConnectivityMetricsEvent printing

This patch adds more information printing for IpConnectivity event
classes in android.net.metrics.

example:

ConnectivityMetricsEvent(14:36:35.799, 0, 1026): DhcpClientEvent(wlan0, DhcpRequestingState)
ConnectivityMetricsEvent(14:36:35.805, 0, 1026): DhcpClientEvent(wlan0, DhcpHaveAddressState)
ConnectivityMetricsEvent(14:36:35.809, 0, 4096): IpManagerEvent(wlan0, PROVISIONING_OK, 155ms)
ConnectivityMetricsEvent(14:36:35.810, 0, 1026): DhcpClientEvent(wlan0, DhcpBoundState)
ConnectivityMetricsEvent(14:36:35.871, 0, 2048): NetworkEvent(101, NETWORK_CONNECTED, 0ms)
ConnectivityMetricsEvent(14:36:35.874, 0, 2051): ValidationProbeEvent(101, PROBE_HTTP:599, 3ms)
ConnectivityMetricsEvent(14:36:35.874, 0, 2048): NetworkEvent(101, NETWORK_VALIDATION_FAILED, 0ms)
ConnectivityMetricsEvent(14:36:35.928, 0, 3072): DefaultNetworkEvent(0 -> 101, [WIFI], IPv4: false, IPv6: false)
ConnectivityMetricsEvent(14:36:37.008, 0, 2051): ValidationProbeEvent(101, PROBE_HTTP:204, 134ms)
ConnectivityMetricsEvent(14:36:37.008, 0, 2050): NetworkEvent(101, NETWORK_VALIDATED, 1137ms)

Also fixes a couple of event logging issues:
  - do no record spurious receive DhcpErrorEvent when a network goes down.
  - add an eventType field to IpManagerEvent instead of using the
    loggger component tag.

Bug: 28204408
Change-Id: Ia6f4ccfd7a0c63a5ccec18825f226c0b5781217b
diff --git a/core/java/android/net/ConnectivityMetricsEvent.java b/core/java/android/net/ConnectivityMetricsEvent.java
index 71ba65f..eaaef7f 100644
--- a/core/java/android/net/ConnectivityMetricsEvent.java
+++ b/core/java/android/net/ConnectivityMetricsEvent.java
@@ -77,8 +77,8 @@
     }
 
     public String toString() {
-        return String.format("ConnectivityMetricsEvent(%d, %d, %d): %s", timestamp,
-                componentTag, eventTag, data);
+        return String.format("ConnectivityMetricsEvent(%tT.%tL, %d, %d): %s",
+                timestamp, timestamp, componentTag, eventTag, data);
     }
 
     /** {@hide} */
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 64186145..6243f46 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -809,17 +809,7 @@
     @Override
     public String toString() {
         int[] types = getTransportTypes();
-        String transports = (types.length > 0 ? " Transports: " : "");
-        for (int i = 0; i < types.length;) {
-            switch (types[i]) {
-                case TRANSPORT_CELLULAR:    transports += "CELLULAR"; break;
-                case TRANSPORT_WIFI:        transports += "WIFI"; break;
-                case TRANSPORT_BLUETOOTH:   transports += "BLUETOOTH"; break;
-                case TRANSPORT_ETHERNET:    transports += "ETHERNET"; break;
-                case TRANSPORT_VPN:         transports += "VPN"; break;
-            }
-            if (++i < types.length) transports += "|";
-        }
+        String transports = (types.length > 0) ? " Transports: " + transportNamesOf(types) : "";
 
         types = getCapabilities();
         String capabilities = (types.length > 0 ? " Capabilities: " : "");
@@ -859,4 +849,22 @@
 
         return "[" + transports + capabilities + upBand + dnBand + specifier + signalStrength + "]";
     }
+
+    /**
+     * @hide
+     */
+    public static String transportNamesOf(int[] types) {
+        String transports = "";
+        for (int i = 0; i < types.length;) {
+            switch (types[i]) {
+                case TRANSPORT_CELLULAR:    transports += "CELLULAR"; break;
+                case TRANSPORT_WIFI:        transports += "WIFI"; break;
+                case TRANSPORT_BLUETOOTH:   transports += "BLUETOOTH"; break;
+                case TRANSPORT_ETHERNET:    transports += "ETHERNET"; break;
+                case TRANSPORT_VPN:         transports += "VPN"; break;
+            }
+            if (++i < types.length) transports += "|";
+        }
+        return transports;
+    }
 }
diff --git a/core/java/android/net/metrics/DefaultNetworkEvent.java b/core/java/android/net/metrics/DefaultNetworkEvent.java
index f3c357b..1864a1e 100644
--- a/core/java/android/net/metrics/DefaultNetworkEvent.java
+++ b/core/java/android/net/metrics/DefaultNetworkEvent.java
@@ -17,6 +17,7 @@
 package android.net.metrics;
 
 import android.annotation.SystemApi;
+import android.net.NetworkCapabilities;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -65,6 +66,12 @@
         return 0;
     }
 
+    @Override
+    public String toString() {
+      return String.format("DefaultNetworkEvent(%d -> %d, %s, IPv4: %b, IPv6: %b)", prevNetId,
+              netId, NetworkCapabilities.transportNamesOf(transportTypes), prevIPv4, prevIPv6);
+    }
+
     public static final Parcelable.Creator<DefaultNetworkEvent> CREATOR
         = new Parcelable.Creator<DefaultNetworkEvent>() {
         public DefaultNetworkEvent createFromParcel(Parcel in) {
diff --git a/core/java/android/net/metrics/DhcpClientEvent.java b/core/java/android/net/metrics/DhcpClientEvent.java
index 6e295a9..d94473b 100644
--- a/core/java/android/net/metrics/DhcpClientEvent.java
+++ b/core/java/android/net/metrics/DhcpClientEvent.java
@@ -47,6 +47,11 @@
         return 0;
     }
 
+    @Override
+    public String toString() {
+        return String.format("DhcpClientEvent(%s, %s)", ifName, msg);
+    }
+
     public static final Parcelable.Creator<DhcpClientEvent> CREATOR
         = new Parcelable.Creator<DhcpClientEvent>() {
         public DhcpClientEvent createFromParcel(Parcel in) {
diff --git a/core/java/android/net/metrics/DhcpErrorEvent.java b/core/java/android/net/metrics/DhcpErrorEvent.java
index 46fdd18..b809209 100644
--- a/core/java/android/net/metrics/DhcpErrorEvent.java
+++ b/core/java/android/net/metrics/DhcpErrorEvent.java
@@ -19,6 +19,9 @@
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.SparseArray;
+
+import com.android.internal.util.MessageUtils;
 
 /**
  * {@hide} Event class used to record error events when parsing DHCP response packets.
@@ -103,4 +106,15 @@
     private static int makeErrorCode(int type, int subtype) {
         return (type << 24) | ((0xFF & subtype) << 16);
     }
+
+    @Override
+    public String toString() {
+        return String.format("DhcpErrorEvent(%s, %s)", ifName, Decoder.constants.get(errorCode));
+    }
+
+    final static class Decoder {
+        static final SparseArray<String> constants =
+                MessageUtils.findMessageNames(new Class[]{DhcpErrorEvent.class},
+                new String[]{"L2_", "L3_", "L4_", "BOOTP_", "DHCP_", "BUFFER_", "RECEIVE_"});
+    }
 }
diff --git a/core/java/android/net/metrics/DnsEvent.java b/core/java/android/net/metrics/DnsEvent.java
index bf6e95c..fde3e9e 100644
--- a/core/java/android/net/metrics/DnsEvent.java
+++ b/core/java/android/net/metrics/DnsEvent.java
@@ -63,6 +63,11 @@
         return 0;
     }
 
+    @Override
+    public String toString() {
+        return String.format("DnsEvent(%d, %d events)", netId, eventTypes.length);
+    }
+
     public static final Parcelable.Creator<DnsEvent> CREATOR = new Parcelable.Creator<DnsEvent>() {
         @Override
         public DnsEvent createFromParcel(Parcel in) {
diff --git a/core/java/android/net/metrics/IpManagerEvent.java b/core/java/android/net/metrics/IpManagerEvent.java
index 5bbcbf1..fcc7608 100644
--- a/core/java/android/net/metrics/IpManagerEvent.java
+++ b/core/java/android/net/metrics/IpManagerEvent.java
@@ -19,27 +19,39 @@
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.SparseArray;
+
+import com.android.internal.util.MessageUtils;
 
 /**
  * {@hide}
  */
 @SystemApi
 public final class IpManagerEvent extends IpConnectivityEvent implements Parcelable {
+
+    public static final int PROVISIONING_OK    = 1;
+    public static final int PROVISIONING_FAIL  = 2;
+    public static final int COMPLETE_LIFECYCLE = 3;
+
     public final String ifName;
+    public final int eventType;
     public final long durationMs;
 
-    private IpManagerEvent(String ifName, long duration) {
+    private IpManagerEvent(String ifName, int eventType, long duration) {
         this.ifName = ifName;
+        this.eventType = eventType;
         this.durationMs = duration;
     }
 
     private IpManagerEvent(Parcel in) {
         this.ifName = in.readString();
+        this.eventType = in.readInt();
         this.durationMs = in.readLong();
     }
 
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(ifName);
+        out.writeInt(eventType);
         out.writeLong(durationMs);
     }
 
@@ -59,6 +71,17 @@
     };
 
     public static void logEvent(int eventType, String ifName, long durationMs) {
-        logEvent(eventType, new IpManagerEvent(ifName, durationMs));
+        logEvent(IPCE_IPMGR_BASE, new IpManagerEvent(ifName, eventType, durationMs));
+    }
+
+    @Override
+    public String toString() {
+        return String.format("IpManagerEvent(%s, %s, %dms)",
+                ifName, Decoder.constants.get(eventType), durationMs);
+    }
+
+    final static class Decoder {
+        static final SparseArray<String> constants = MessageUtils.findMessageNames(
+                new Class[]{IpManagerEvent.class}, new String[]{"PROVISIONING_", "COMPLETE_"});
     }
 };
diff --git a/core/java/android/net/metrics/IpReachabilityEvent.java b/core/java/android/net/metrics/IpReachabilityEvent.java
index 73dcb94..b0eed61 100644
--- a/core/java/android/net/metrics/IpReachabilityEvent.java
+++ b/core/java/android/net/metrics/IpReachabilityEvent.java
@@ -19,6 +19,9 @@
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.SparseArray;
+
+import com.android.internal.util.MessageUtils;
 
 /**
  * {@hide}
@@ -81,4 +84,16 @@
     public static void logProvisioningLost(String ifName) {
         logEvent(IPCE_IPRM_PROVISIONING_LOST, new IpReachabilityEvent(ifName, PROVISIONING_LOST));
     }
+
+    @Override
+    public String toString() {
+        return String.format("IpReachabilityEvent(%s, %s)", ifName,
+                Decoder.constants.get(eventType));
+    }
+
+    final static class Decoder {
+        static final SparseArray<String> constants =
+                MessageUtils.findMessageNames(new Class[]{IpReachabilityEvent.class},
+                new String[]{"PROBE", "PROVISIONING_", "NUD_"});
+    }
 };
diff --git a/core/java/android/net/metrics/NetworkEvent.java b/core/java/android/net/metrics/NetworkEvent.java
index b15dcee..d3dfa0d 100644
--- a/core/java/android/net/metrics/NetworkEvent.java
+++ b/core/java/android/net/metrics/NetworkEvent.java
@@ -19,6 +19,9 @@
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.SparseArray;
+
+import com.android.internal.util.MessageUtils;
 
 /**
  * {@hide}
@@ -83,4 +86,15 @@
         final NetworkEvent ev = new NetworkEvent(netId, NETWORK_CAPTIVE_PORTAL_FOUND, durationMs);
         logEvent(IPCE_NETMON_CAPPORT_FOUND, ev);
     }
+
+    @Override
+    public String toString() {
+        return String.format("NetworkEvent(%d, %s, %dms)",
+                netId, Decoder.constants.get(eventType), durationMs);
+    }
+
+    final static class Decoder {
+        static final SparseArray<String> constants = MessageUtils.findMessageNames(
+                new Class[]{NetworkEvent.class}, new String[]{"NETWORK_"});
+    }
 };
diff --git a/core/java/android/net/metrics/ValidationProbeEvent.java b/core/java/android/net/metrics/ValidationProbeEvent.java
index 0a524c6..560fd84 100644
--- a/core/java/android/net/metrics/ValidationProbeEvent.java
+++ b/core/java/android/net/metrics/ValidationProbeEvent.java
@@ -19,6 +19,9 @@
 import android.annotation.SystemApi;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.SparseArray;
+
+import com.android.internal.util.MessageUtils;
 
 /**
  * {@hide}
@@ -72,6 +75,17 @@
 
     public static void logEvent(int netId, long durationMs, int probeType, int returnCode) {
         logEvent(IPCE_NETMON_PORTAL_PROBE,
-                 new ValidationProbeEvent(netId, durationMs, probeType, returnCode));
+                new ValidationProbeEvent(netId, durationMs, probeType, returnCode));
+    }
+
+    @Override
+    public String toString() {
+        return String.format("ValidationProbeEvent(%d, %s:%d, %dms)",
+                netId, Decoder.constants.get(probeType), returnCode, durationMs);
+    }
+
+    final static class Decoder {
+        static final SparseArray<String> constants = MessageUtils.findMessageNames(
+                new Class[]{ValidationProbeEvent.class}, new String[]{"PROBE_"});
     }
 };