Merge "Track moving of OkHttp facade API to new package."
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 4bb8844..db12dd9 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.IntDef;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -23,6 +24,8 @@
 import com.android.internal.util.BitUtils;
 import com.android.internal.util.Preconditions;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
 import java.util.StringJoiner;
 
@@ -77,6 +80,31 @@
      */
     private long mNetworkCapabilities;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "NET_CAPABILITY_" }, value = {
+            NET_CAPABILITY_MMS,
+            NET_CAPABILITY_SUPL,
+            NET_CAPABILITY_DUN,
+            NET_CAPABILITY_FOTA,
+            NET_CAPABILITY_IMS,
+            NET_CAPABILITY_CBS,
+            NET_CAPABILITY_WIFI_P2P,
+            NET_CAPABILITY_IA,
+            NET_CAPABILITY_RCS,
+            NET_CAPABILITY_XCAP,
+            NET_CAPABILITY_EIMS,
+            NET_CAPABILITY_NOT_METERED,
+            NET_CAPABILITY_INTERNET,
+            NET_CAPABILITY_NOT_RESTRICTED,
+            NET_CAPABILITY_TRUSTED,
+            NET_CAPABILITY_NOT_VPN,
+            NET_CAPABILITY_VALIDATED,
+            NET_CAPABILITY_CAPTIVE_PORTAL,
+            NET_CAPABILITY_FOREGROUND,
+    })
+    public @interface NetCapability { }
+
     /**
      * Indicates this is a network that has the ability to reach the
      * carrier's MMSC for sending and receiving MMS messages.
@@ -260,11 +288,11 @@
      * Multiple capabilities may be applied sequentially.  Note that when searching
      * for a network to satisfy a request, all capabilities requested must be satisfied.
      *
-     * @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be added.
+     * @param capability the capability to be added.
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
-    public NetworkCapabilities addCapability(int capability) {
+    public NetworkCapabilities addCapability(@NetCapability int capability) {
         if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
             throw new IllegalArgumentException("NetworkCapability out of range");
         }
@@ -275,11 +303,11 @@
     /**
      * Removes (if found) the given capability from this {@code NetworkCapability} instance.
      *
-     * @param capability the {@code NetworkCapabilities.NET_CAPABILTIY_*} to be removed.
+     * @param capability the capability to be removed.
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
-    public NetworkCapabilities removeCapability(int capability) {
+    public NetworkCapabilities removeCapability(@NetCapability int capability) {
         if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
             throw new IllegalArgumentException("NetworkCapability out of range");
         }
@@ -290,21 +318,20 @@
     /**
      * Gets all the capabilities set on this {@code NetworkCapability} instance.
      *
-     * @return an array of {@code NetworkCapabilities.NET_CAPABILITY_*} values
-     *         for this instance.
+     * @return an array of capability values for this instance.
      * @hide
      */
-    public int[] getCapabilities() {
+    public @NetCapability int[] getCapabilities() {
         return BitUtils.unpackBits(mNetworkCapabilities);
     }
 
     /**
      * Tests for the presence of a capabilitity on this instance.
      *
-     * @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be tested for.
+     * @param capability the capabilities to be tested for.
      * @return {@code true} if set on this instance.
      */
-    public boolean hasCapability(int capability) {
+    public boolean hasCapability(@NetCapability int capability) {
         if (capability < MIN_NET_CAPABILITY || capability > MAX_NET_CAPABILITY) {
             return false;
         }
@@ -385,6 +412,19 @@
      */
     private long mTransportTypes;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = { "TRANSPORT_" }, value = {
+            TRANSPORT_CELLULAR,
+            TRANSPORT_WIFI,
+            TRANSPORT_BLUETOOTH,
+            TRANSPORT_ETHERNET,
+            TRANSPORT_VPN,
+            TRANSPORT_WIFI_AWARE,
+            TRANSPORT_LOWPAN,
+    })
+    public @interface Transport { }
+
     /**
      * Indicates this network uses a Cellular transport.
      */
@@ -426,7 +466,7 @@
     public static final int MAX_TRANSPORT = TRANSPORT_LOWPAN;
 
     /** @hide */
-    public static boolean isValidTransport(int transportType) {
+    public static boolean isValidTransport(@Transport int transportType) {
         return (MIN_TRANSPORT <= transportType) && (transportType <= MAX_TRANSPORT);
     }
 
@@ -449,11 +489,11 @@
      * to be selected.  This is logically different than
      * {@code NetworkCapabilities.NET_CAPABILITY_*} listed above.
      *
-     * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be added.
+     * @param transportType the transport type to be added.
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
-    public NetworkCapabilities addTransportType(int transportType) {
+    public NetworkCapabilities addTransportType(@Transport int transportType) {
         checkValidTransportType(transportType);
         mTransportTypes |= 1 << transportType;
         setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
@@ -463,11 +503,11 @@
     /**
      * Removes (if found) the given transport from this {@code NetworkCapability} instance.
      *
-     * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be removed.
+     * @param transportType the transport type to be removed.
      * @return This NetworkCapabilities instance, to facilitate chaining.
      * @hide
      */
-    public NetworkCapabilities removeTransportType(int transportType) {
+    public NetworkCapabilities removeTransportType(@Transport int transportType) {
         checkValidTransportType(transportType);
         mTransportTypes &= ~(1 << transportType);
         setNetworkSpecifier(mNetworkSpecifier); // used for exception checking
@@ -477,21 +517,20 @@
     /**
      * Gets all the transports set on this {@code NetworkCapability} instance.
      *
-     * @return an array of {@code NetworkCapabilities.TRANSPORT_*} values
-     *         for this instance.
+     * @return an array of transport type values for this instance.
      * @hide
      */
-    public int[] getTransportTypes() {
+    public @Transport int[] getTransportTypes() {
         return BitUtils.unpackBits(mTransportTypes);
     }
 
     /**
      * Tests for the presence of a transport on this instance.
      *
-     * @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be tested for.
+     * @param transportType the transport type to be tested for.
      * @return {@code true} if set on this instance.
      */
-    public boolean hasTransport(int transportType) {
+    public boolean hasTransport(@Transport int transportType) {
         return isValidTransport(transportType) && ((mTransportTypes & (1 << transportType)) != 0);
     }
 
@@ -896,7 +935,7 @@
     /**
      * @hide
      */
-    public static String capabilityNamesOf(int[] capabilities) {
+    public static String capabilityNamesOf(@NetCapability int[] capabilities) {
         StringJoiner joiner = new StringJoiner("|");
         if (capabilities != null) {
             for (int c : capabilities) {
@@ -909,7 +948,7 @@
     /**
      * @hide
      */
-    public static String capabilityNameOf(int capability) {
+    public static String capabilityNameOf(@NetCapability int capability) {
         switch (capability) {
             case NET_CAPABILITY_MMS:            return "MMS";
             case NET_CAPABILITY_SUPL:           return "SUPL";
@@ -937,7 +976,7 @@
     /**
      * @hide
      */
-    public static String transportNamesOf(int[] types) {
+    public static String transportNamesOf(@Transport int[] types) {
         StringJoiner joiner = new StringJoiner("|");
         if (types != null) {
             for (int t : types) {
@@ -950,14 +989,14 @@
     /**
      * @hide
      */
-    public static String transportNameOf(int transport) {
+    public static String transportNameOf(@Transport int transport) {
         if (!isValidTransport(transport)) {
             return "UNKNOWN";
         }
         return TRANSPORT_NAMES[transport];
     }
 
-    private static void checkValidTransportType(int transport) {
+    private static void checkValidTransportType(@Transport int transport) {
         Preconditions.checkArgument(
                 isValidTransport(transport), "Invalid TransportType " + transport);
     }
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 95a8bb4..25b1705 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -155,14 +155,13 @@
          * Add the given capability requirement to this builder.  These represent
          * the requested network's required capabilities.  Note that when searching
          * for a network to satisfy a request, all capabilities requested must be
-         * satisfied.  See {@link NetworkCapabilities} for {@code NET_CAPABILITY_*}
-         * definitions.
+         * satisfied.
          *
-         * @param capability The {@code NetworkCapabilities.NET_CAPABILITY_*} to add.
+         * @param capability The capability to add.
          * @return The builder to facilitate chaining
          *         {@code builder.addCapability(...).addCapability();}.
          */
-        public Builder addCapability(int capability) {
+        public Builder addCapability(@NetworkCapabilities.NetCapability int capability) {
             mNetworkCapabilities.addCapability(capability);
             return this;
         }
@@ -170,10 +169,10 @@
         /**
          * Removes (if found) the given capability from this builder instance.
          *
-         * @param capability The {@code NetworkCapabilities.NET_CAPABILITY_*} to remove.
+         * @param capability The capability to remove.
          * @return The builder to facilitate chaining.
          */
-        public Builder removeCapability(int capability) {
+        public Builder removeCapability(@NetworkCapabilities.NetCapability int capability) {
             mNetworkCapabilities.removeCapability(capability);
             return this;
         }
@@ -208,13 +207,12 @@
          * Adds the given transport requirement to this builder.  These represent
          * the set of allowed transports for the request.  Only networks using one
          * of these transports will satisfy the request.  If no particular transports
-         * are required, none should be specified here.  See {@link NetworkCapabilities}
-         * for {@code TRANSPORT_*} definitions.
+         * are required, none should be specified here.
          *
-         * @param transportType The {@code NetworkCapabilities.TRANSPORT_*} to add.
+         * @param transportType The transport type to add.
          * @return The builder to facilitate chaining.
          */
-        public Builder addTransportType(int transportType) {
+        public Builder addTransportType(@NetworkCapabilities.Transport int transportType) {
             mNetworkCapabilities.addTransportType(transportType);
             return this;
         }
@@ -222,10 +220,10 @@
         /**
          * Removes (if found) the given transport from this builder instance.
          *
-         * @param transportType The {@code NetworkCapabilities.TRANSPORT_*} to remove.
+         * @param transportType The transport type to remove.
          * @return The builder to facilitate chaining.
          */
-        public Builder removeTransportType(int transportType) {
+        public Builder removeTransportType(@NetworkCapabilities.Transport int transportType) {
             mNetworkCapabilities.removeTransportType(transportType);
             return this;
         }
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 5c11100..25c96d1 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -71,7 +71,6 @@
 import android.net.RouteInfo;
 import android.net.UidRange;
 import android.net.Uri;
-import android.net.metrics.DefaultNetworkEvent;
 import android.net.metrics.IpConnectivityLog;
 import android.net.metrics.NetworkEvent;
 import android.net.util.MultinetworkPolicyTracker;
@@ -129,6 +128,7 @@
 import com.android.server.LocalServices;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.connectivity.DataConnectionStats;
+import com.android.server.connectivity.IpConnectivityMetrics;
 import com.android.server.connectivity.KeepaliveTracker;
 import com.android.server.connectivity.LingerMonitor;
 import com.android.server.connectivity.MockableSystemProperties;
@@ -2283,7 +2283,7 @@
                 // Let rematchAllNetworksAndRequests() below record a new default network event
                 // if there is a fallback. Taken together, the two form a X -> 0, 0 -> Y sequence
                 // whose timestamps tell how long it takes to recover a default network.
-                logDefaultNetworkEvent(null, nai);
+                metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(null, nai);
             }
             notifyIfacesChangedForNetworkStats();
             // TODO - we shouldn't send CALLBACK_LOST to requests that can be satisfied
@@ -5012,7 +5012,8 @@
             // Notify system services that this network is up.
             makeDefault(newNetwork);
             // Log 0 -> X and Y -> X default network transitions, where X is the new default.
-            logDefaultNetworkEvent(newNetwork, oldDefaultNetwork);
+            metricsLogger().defaultNetworkMetrics().logDefaultNetworkEvent(
+                    newNetwork, oldDefaultNetwork);
             // Have a new default network, release the transition wakelock in
             scheduleReleaseNetworkTransitionWakelock();
         }
@@ -5571,25 +5572,10 @@
         return ServiceManager.checkService(name) != null;
     }
 
-    private void logDefaultNetworkEvent(NetworkAgentInfo newNai, NetworkAgentInfo prevNai) {
-        int newNetid = NETID_UNSET;
-        int prevNetid = NETID_UNSET;
-        int[] transports = new int[0];
-        boolean hadIPv4 = false;
-        boolean hadIPv6 = false;
-
-        if (newNai != null) {
-            newNetid = newNai.network.netId;
-            transports = newNai.networkCapabilities.getTransportTypes();
-        }
-        if (prevNai != null) {
-            prevNetid = prevNai.network.netId;
-            final LinkProperties lp = prevNai.linkProperties;
-            hadIPv4 = lp.hasIPv4Address() && lp.hasIPv4DefaultRoute();
-            hadIPv6 = lp.hasGlobalIPv6Address() && lp.hasIPv6DefaultRoute();
-        }
-
-        mMetricsLog.log(new DefaultNetworkEvent(newNetid, transports, prevNetid, hadIPv4, hadIPv6));
+    @VisibleForTesting
+    protected IpConnectivityMetrics.Logger metricsLogger() {
+        return checkNotNull(LocalServices.getService(IpConnectivityMetrics.Logger.class),
+                "no IpConnectivityMetrics service");
     }
 
     private void logNetworkEvent(NetworkAgentInfo nai, int evtype) {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index c2cb66d..27a29b6 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -104,6 +104,8 @@
 import com.android.internal.util.WakeupMessage;
 import com.android.internal.util.test.BroadcastInterceptingContext;
 import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.server.connectivity.DefaultNetworkMetrics;
+import com.android.server.connectivity.IpConnectivityMetrics;
 import com.android.server.connectivity.MockableSystemProperties;
 import com.android.server.connectivity.NetworkAgentInfo;
 import com.android.server.connectivity.NetworkMonitor;
@@ -156,6 +158,9 @@
     private MockNetworkAgent mEthernetNetworkAgent;
     private Context mContext;
 
+    @Mock IpConnectivityMetrics.Logger mMetricsService;
+    @Mock DefaultNetworkMetrics mDefaultNetworkMetrics;
+
     // This class exists to test bindProcessToNetwork and getBoundNetworkForProcess. These methods
     // do not go through ConnectivityService but talk to netd directly, so they don't automatically
     // reflect the state of our test ConnectivityService.
@@ -805,6 +810,11 @@
             return Context.ETHERNET_SERVICE.equals(name);
         }
 
+        @Override
+        protected IpConnectivityMetrics.Logger metricsLogger() {
+            return mMetricsService;
+        }
+
         public WrappedNetworkMonitor getLastCreatedWrappedNetworkMonitor() {
             return mLastCreatedNetworkMonitor;
         }
@@ -833,6 +843,9 @@
     public void setUp() throws Exception {
         mContext = InstrumentationRegistry.getContext();
 
+        MockitoAnnotations.initMocks(this);
+        when(mMetricsService.defaultNetworkMetrics()).thenReturn(mDefaultNetworkMetrics);
+
         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
         // http://b/25897652 .
         if (Looper.myLooper() == null) {
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index b4b8094..9e97d84 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -206,7 +206,7 @@
                         eq(CRYPT_KEY),
                         anyInt(),
                         eq(""),
-                        isNull(),
+                        eq(new byte[] {}),
                         eq(0),
                         anyInt(),
                         anyInt(),
@@ -227,7 +227,7 @@
                         eq(CRYPT_KEY),
                         anyInt(),
                         eq(""),
-                        isNull(),
+                        eq(new byte[] {}),
                         eq(0),
                         anyInt(),
                         anyInt(),
@@ -256,10 +256,10 @@
                         anyLong(),
                         eq(TEST_SPI_OUT),
                         eq(""),
-                        isNull(),
+                        eq(new byte[] {}),
                         eq(0),
                         eq(""),
-                        isNull(),
+                        eq(new byte[] {}),
                         eq(0),
                         eq(IpSecAlgorithm.AUTH_CRYPT_AES_GCM),
                         eq(CRYPT_KEY),
@@ -277,10 +277,10 @@
                         anyLong(),
                         eq(TEST_SPI_IN),
                         eq(""),
-                        isNull(),
+                        eq(new byte[] {}),
                         eq(0),
                         eq(""),
-                        isNull(),
+                        eq(new byte[] {}),
                         eq(0),
                         eq(IpSecAlgorithm.AUTH_CRYPT_AES_GCM),
                         eq(CRYPT_KEY),
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
index 2624176..ad6ebf9 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityEventBuilderTest.java
@@ -198,21 +198,20 @@
 
     @Test
     public void testDefaultNetworkEventSerialization() {
-        ConnectivityMetricsEvent ev = describeIpEvent(
-                aType(DefaultNetworkEvent.class),
-                anInt(102),
-                anIntArray(1, 2, 3),
-                anInt(101),
-                aBool(true),
-                aBool(false));
+        DefaultNetworkEvent ev = new DefaultNetworkEvent();
+        ev.netId = 102;
+        ev.prevNetId = 101;
+        ev.transportTypes = new int[]{1, 2, 3};
+        ev.prevIPv4 = true;
+        ev.prevIPv6 = true;
 
         String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
                 "  if_name: \"\"",
                 "  link_layer: 0",
-                "  network_id: 0",
-                "  time_ms: 1",
+                "  network_id: 102",
+                "  time_ms: 0",
                 "  transports: 0",
                 "  default_network_event <",
                 "    default_network_duration_ms: 0",
@@ -226,7 +225,7 @@
                 "    previous_network_id <",
                 "      network_id: 101",
                 "    >",
-                "    previous_network_ip_support: 1",
+                "    previous_network_ip_support: 3",
                 "    transport_types: 1",
                 "    transport_types: 2",
                 "    transport_types: 3",
@@ -234,7 +233,7 @@
                 ">",
                 "version: 2\n");
 
-        verifySerialization(want, ev);
+        verifySerialization(want, IpConnectivityEventBuilder.toProto(ev));
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
index a395c48..6c1decc 100644
--- a/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
+++ b/tests/net/java/com/android/server/connectivity/IpConnectivityMetricsTest.java
@@ -18,6 +18,7 @@
 
 import static android.net.metrics.INetdEventListener.EVENT_GETADDRINFO;
 import static android.net.metrics.INetdEventListener.EVENT_GETHOSTBYNAME;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -30,6 +31,10 @@
 import android.net.ConnectivityManager;
 import android.net.ConnectivityMetricsEvent;
 import android.net.IIpConnectivityMetrics;
+import android.net.IpPrefix;
+import android.net.LinkAddress;
+import android.net.LinkProperties;
+import android.net.RouteInfo;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.metrics.ApfProgramEvent;
@@ -41,18 +46,22 @@
 import android.net.metrics.IpReachabilityEvent;
 import android.net.metrics.RaEvent;
 import android.net.metrics.ValidationProbeEvent;
-import android.system.OsConstants;
 import android.os.Parcelable;
 import android.support.test.runner.AndroidJUnit4;
+import android.system.OsConstants;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Base64;
+
+import com.android.internal.util.BitUtils;
 import com.android.server.connectivity.metrics.nano.IpConnectivityLogClass;
+
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
+
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
@@ -162,6 +171,144 @@
     }
 
     @Test
+    public void testDefaultNetworkEvents() throws Exception {
+        final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
+        final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
+
+        NetworkAgentInfo[][] defaultNetworks = {
+            // nothing -> cell
+            {null, makeNai(100, 10, false, true, cell)},
+            // cell -> wifi
+            {makeNai(100, 50, true, true, cell), makeNai(101, 20, true, false, wifi)},
+            // wifi -> nothing
+            {makeNai(101, 60, true, false, wifi), null},
+            // nothing -> cell
+            {null, makeNai(102, 10, true, true, cell)},
+            // cell -> wifi
+            {makeNai(102, 50, true, true, cell), makeNai(103, 20, true, false, wifi)},
+        };
+
+        for (NetworkAgentInfo[] pair : defaultNetworks) {
+            mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(pair[1], pair[0]);
+        }
+
+        String want = String.join("\n",
+                "dropped_events: 0",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 0",
+                "  network_id: 100",
+                "  time_ms: 0",
+                "  transports: 0",
+                "  default_network_event <",
+                "    default_network_duration_ms: 0",
+                "    final_score: 0",
+                "    initial_score: 0",
+                "    ip_support: 0",
+                "    network_id <",
+                "      network_id: 100",
+                "    >",
+                "    no_default_network_duration_ms: 0",
+                "    previous_network_id <",
+                "      network_id: 0",
+                "    >",
+                "    previous_network_ip_support: 0",
+                "    transport_types: 0",
+                "  >",
+                ">",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 0",
+                "  network_id: 101",
+                "  time_ms: 0",
+                "  transports: 0",
+                "  default_network_event <",
+                "    default_network_duration_ms: 0",
+                "    final_score: 0",
+                "    initial_score: 0",
+                "    ip_support: 0",
+                "    network_id <",
+                "      network_id: 101",
+                "    >",
+                "    no_default_network_duration_ms: 0",
+                "    previous_network_id <",
+                "      network_id: 100",
+                "    >",
+                "    previous_network_ip_support: 3",
+                "    transport_types: 1",
+                "  >",
+                ">",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 0",
+                "  network_id: 0",
+                "  time_ms: 0",
+                "  transports: 0",
+                "  default_network_event <",
+                "    default_network_duration_ms: 0",
+                "    final_score: 0",
+                "    initial_score: 0",
+                "    ip_support: 0",
+                "    network_id <",
+                "      network_id: 0",
+                "    >",
+                "    no_default_network_duration_ms: 0",
+                "    previous_network_id <",
+                "      network_id: 101",
+                "    >",
+                "    previous_network_ip_support: 1",
+                "  >",
+                ">",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 0",
+                "  network_id: 102",
+                "  time_ms: 0",
+                "  transports: 0",
+                "  default_network_event <",
+                "    default_network_duration_ms: 0",
+                "    final_score: 0",
+                "    initial_score: 0",
+                "    ip_support: 0",
+                "    network_id <",
+                "      network_id: 102",
+                "    >",
+                "    no_default_network_duration_ms: 0",
+                "    previous_network_id <",
+                "      network_id: 0",
+                "    >",
+                "    previous_network_ip_support: 0",
+                "    transport_types: 0",
+                "  >",
+                ">",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 0",
+                "  network_id: 103",
+                "  time_ms: 0",
+                "  transports: 0",
+                "  default_network_event <",
+                "    default_network_duration_ms: 0",
+                "    final_score: 0",
+                "    initial_score: 0",
+                "    ip_support: 0",
+                "    network_id <",
+                "      network_id: 103",
+                "    >",
+                "    no_default_network_duration_ms: 0",
+                "    previous_network_id <",
+                "      network_id: 102",
+                "    >",
+                "    previous_network_ip_support: 3",
+                "    transport_types: 1",
+                "  >",
+                ">",
+                "version: 2\n");
+
+        verifySerialization(want, getdump("flush"));
+    }
+
+    @Test
     public void testEndToEndLogging() throws Exception {
         // TODO: instead of comparing textpb to textpb, parse textpb and compare proto to proto.
         IpConnectivityLog logger = new IpConnectivityLog(mService.impl);
@@ -194,7 +341,6 @@
         Parcelable[] events = {
             new IpReachabilityEvent(IpReachabilityEvent.NUD_FAILED),
             new DhcpClientEvent("SomeState", 192),
-            new DefaultNetworkEvent(102, new int[]{1,2,3}, 101, true, false),
             new IpManagerEvent(IpManagerEvent.PROVISIONING_OK, 5678),
             validationEv,
             apfStats,
@@ -233,6 +379,13 @@
         wakeupEvent("wlan0", 10008);
         wakeupEvent("rmnet0", 1000);
 
+        final long cell = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
+        final long wifi = BitUtils.packBits(new int[]{NetworkCapabilities.TRANSPORT_WIFI});
+        NetworkAgentInfo cellNai = makeNai(100, 50, false, true, cell);
+        NetworkAgentInfo wifiNai = makeNai(101, 60, true, false, wifi);
+        mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(cellNai, null);
+        mService.mDefaultNetworkMetrics.logDefaultNetworkEvent(wifiNai, cellNai);
+
         String want = String.join("\n",
                 "dropped_events: 0",
                 "events <",
@@ -264,30 +417,6 @@
                 "  network_id: 0",
                 "  time_ms: 300",
                 "  transports: 0",
-                "  default_network_event <",
-                "    default_network_duration_ms: 0",
-                "    final_score: 0",
-                "    initial_score: 0",
-                "    ip_support: 0",
-                "    network_id <",
-                "      network_id: 102",
-                "    >",
-                "    no_default_network_duration_ms: 0",
-                "    previous_network_id <",
-                "      network_id: 101",
-                "    >",
-                "    previous_network_ip_support: 1",
-                "    transport_types: 1",
-                "    transport_types: 2",
-                "    transport_types: 3",
-                "  >",
-                ">",
-                "events <",
-                "  if_name: \"\"",
-                "  link_layer: 4",
-                "  network_id: 0",
-                "  time_ms: 400",
-                "  transports: 0",
                 "  ip_provisioning_event <",
                 "    event_type: 1",
                 "    if_name: \"\"",
@@ -298,7 +427,7 @@
                 "  if_name: \"\"",
                 "  link_layer: 4",
                 "  network_id: 0",
-                "  time_ms: 500",
+                "  time_ms: 400",
                 "  transports: 0",
                 "  validation_probe_event <",
                 "    latency_ms: 40730",
@@ -310,7 +439,7 @@
                 "  if_name: \"\"",
                 "  link_layer: 4",
                 "  network_id: 0",
-                "  time_ms: 600",
+                "  time_ms: 500",
                 "  transports: 0",
                 "  apf_statistics <",
                 "    dropped_ras: 2",
@@ -331,7 +460,7 @@
                 "  if_name: \"\"",
                 "  link_layer: 4",
                 "  network_id: 0",
-                "  time_ms: 700",
+                "  time_ms: 600",
                 "  transports: 0",
                 "  ra_event <",
                 "    dnssl_lifetime: -1",
@@ -344,6 +473,50 @@
                 ">",
                 "events <",
                 "  if_name: \"\"",
+                "  link_layer: 0",
+                "  network_id: 100",
+                "  time_ms: 0",
+                "  transports: 0",
+                "  default_network_event <",
+                "    default_network_duration_ms: 0",
+                "    final_score: 0",
+                "    initial_score: 0",
+                "    ip_support: 0",
+                "    network_id <",
+                "      network_id: 100",
+                "    >",
+                "    no_default_network_duration_ms: 0",
+                "    previous_network_id <",
+                "      network_id: 0",
+                "    >",
+                "    previous_network_ip_support: 0",
+                "    transport_types: 0",
+                "  >",
+                ">",
+                "events <",
+                "  if_name: \"\"",
+                "  link_layer: 0",
+                "  network_id: 101",
+                "  time_ms: 0",
+                "  transports: 0",
+                "  default_network_event <",
+                "    default_network_duration_ms: 0",
+                "    final_score: 0",
+                "    initial_score: 0",
+                "    ip_support: 0",
+                "    network_id <",
+                "      network_id: 101",
+                "    >",
+                "    no_default_network_duration_ms: 0",
+                "    previous_network_id <",
+                "      network_id: 100",
+                "    >",
+                "    previous_network_ip_support: 2",
+                "    transport_types: 1",
+                "  >",
+                ">",
+                "events <",
+                "  if_name: \"\"",
                 "  link_layer: 4",
                 "  network_id: 100",
                 "  time_ms: 0",
@@ -471,6 +644,26 @@
         mNetdListener.onWakeupEvent(prefix, uid, uid, 0);
     }
 
+    NetworkAgentInfo makeNai(int netId, int score, boolean ipv4, boolean ipv6, long transports) {
+        NetworkAgentInfo nai = mock(NetworkAgentInfo.class);
+        when(nai.network()).thenReturn(new Network(netId));
+        when(nai.getCurrentScore()).thenReturn(score);
+        nai.linkProperties = new LinkProperties();
+        nai.networkCapabilities = new NetworkCapabilities();
+        for (int t : BitUtils.unpackBits(transports)) {
+            nai.networkCapabilities.addTransportType(t);
+        }
+        if (ipv4) {
+            nai.linkProperties.addLinkAddress(new LinkAddress("192.0.2.12/24"));
+            nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("0.0.0.0/0")));
+        }
+        if (ipv6) {
+            nai.linkProperties.addLinkAddress(new LinkAddress("2001:db8:dead:beef:f00::a0/64"));
+            nai.linkProperties.addRoute(new RouteInfo(new IpPrefix("::/0")));
+        }
+        return nai;
+    }
+
     List<ConnectivityMetricsEvent> verifyEvents(int n, int timeoutMs) throws Exception {
         ArgumentCaptor<ConnectivityMetricsEvent> captor =
                 ArgumentCaptor.forClass(ConnectivityMetricsEvent.class);